[pitivi] project: Unset the preset when the muxer changes
- From: Thibault Saunier <tsaunier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] project: Unset the preset when the muxer changes
- Date: Sun, 30 Aug 2020 21:58:03 +0000 (UTC)
commit e579f12b56e248877230a9774b946c44bd54e53d
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Tue Jun 2 00:57:25 2020 +0200
project: Unset the preset when the muxer changes
Fixes #2300
pitivi/project.py | 106 ++++++++++++++++++++++++++++++++++++++-------------
pitivi/render.py | 1 +
tests/test_render.py | 17 +++++++++
3 files changed, 98 insertions(+), 26 deletions(-)
---
diff --git a/pitivi/project.py b/pitivi/project.py
index d9819cd5..86d4f29c 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -1088,9 +1088,14 @@ class Project(Loggable, GES.Project):
caps = self._get_caps_from_feature(value)
if caps:
self.audio_profile.set_format(caps)
+
+ # Set the name of the factory for producing the audio encoder.
self.audio_profile.set_preset_name(value)
- # Gst.Preset can be set exclusively through EncodingTagets for now.
+
+ # Make sure the encoder does not use any encoding preset.
+ # Gst.Preset can be set exclusively through EncodingTargets for now.
self.audio_profile.set_preset(None)
+
self._emit_change("aencoder")
@property
@@ -1103,9 +1108,14 @@ class Project(Loggable, GES.Project):
caps = self._get_caps_from_feature(value)
if caps:
self.video_profile.set_format(caps)
+
+ # Set the name of the factory for producing the video encoder.
self.video_profile.set_preset_name(value)
- # Gst.Preset can be set exclusively through EncodingTagets for now.
+
+ # Make sure the encoder does not use any encoding preset.
+ # Gst.Preset can be set exclusively through EncodingTargets for now.
self.video_profile.set_preset(None)
+
self._emit_change("vencoder")
@property
@@ -1118,7 +1128,14 @@ class Project(Loggable, GES.Project):
caps = self._get_caps_from_feature(value)
if caps:
self.container_profile.set_format(caps)
+
+ # Set the name of the factory for producing the container.
self.container_profile.set_preset_name(value)
+
+ # Make sure the encoder does not use any encoding preset.
+ # Gst.Preset can be set exclusively through EncodingTargets for now.
+ self.container_profile.set_preset(None)
+
self._emit_change("muxer")
def _get_caps_from_feature(self, name):
@@ -1495,8 +1512,7 @@ class Project(Loggable, GES.Project):
if self.container_profile.is_equal(container_profile):
return True
- muxer = self._get_element_factory_name(
- Encoders().muxers, container_profile)
+ muxer = self._get_element_factory_name(container_profile)
if muxer is None:
muxer = Encoders().default_muxer
container_profile.set_preset_name(muxer)
@@ -1512,7 +1528,7 @@ class Project(Loggable, GES.Project):
profile.set_restriction(Gst.Caps("video/x-raw"))
self._ensure_video_restrictions(profile)
- vencoder = self._get_element_factory_name(Encoders().vencoders, profile)
+ vencoder = self._get_element_factory_name(profile)
if vencoder:
profile.set_preset_name(vencoder)
elif isinstance(profile, GstPbutils.EncodingAudioProfile):
@@ -1521,7 +1537,7 @@ class Project(Loggable, GES.Project):
profile.set_restriction(Gst.Caps("audio/x-raw"))
self._ensure_audio_restrictions(profile)
- aencoder = self._get_element_factory_name(Encoders().aencoders, profile)
+ aencoder = self._get_element_factory_name(profile)
if aencoder:
profile.set_preset_name(aencoder)
else:
@@ -2056,33 +2072,71 @@ class Project(Loggable, GES.Project):
self.emit("rendering-settings-changed", key)
self.set_modification_state(True)
- def _get_element_factory_name(self, elements, profile):
+ def _get_element_factory_name(self, profile):
+ """Finds a factory for an element compatible with the specified profile.
+
+ Args:
+ profile (GstPbutils.EncodingProfile): A muxer, video or audio
+ profile.
+
+ Returns:
+ str: The name of the factory which can produce the required
+ element, or None.
+ """
if profile.get_preset_name():
return profile.get_preset_name()
- factories = Gst.ElementFactory.list_filter(elements,
- Gst.Caps(
- profile.get_format()),
- Gst.PadDirection.SRC,
- False)
- if factories:
- factories.sort(key=lambda x: - x.get_rank())
- preset = profile.get_preset()
- # Make sure that if a #Gst.Preset is set we find an
- # element that can handle that preset.
- if preset:
- for factory in factories:
- elem = factory.create()
- if isinstance(elem, Gst.Preset):
- if elem.load_preset(preset):
- return factory.get_name()
- self.error("Could not find any element with preset %s",
- preset)
- return None
+ factories = self.__factories_compatible_with_profile(profile)
+ if not factories:
+ return None
+ preset = profile.get_preset()
+ if not preset:
+ # The element does not need to support a specific preset.
+ # Return the compatible factory with the highest rank.
return factories[0].get_name()
+
+ # Make sure that if a #Gst.Preset is set we find an
+ # element that can handle that preset.
+ for factory in factories:
+ elem = factory.create()
+ if isinstance(elem, Gst.Preset):
+ if elem.load_preset(preset):
+ return factory.get_name()
+
+ self.error("Could not find any element with preset %s", preset)
return None
+ def __factories_compatible_with_profile(self, profile):
+ """Finds factories of the same type as the specified profile.
+
+ Args:
+ profile (GstPbutils.EncodingProfile): A muxer, video or audio
+ profile.
+
+ Returns:
+ list[Gst.ElementFactory]: The element factories producing elements
+ of the same type as the specified profile.
+ """
+ element_factories = []
+ if isinstance(profile, GstPbutils.EncodingContainerProfile):
+ element_factories = Encoders().muxers
+ elif isinstance(profile, GstPbutils.EncodingVideoProfile):
+ element_factories = Encoders().vencoders
+ elif isinstance(profile, GstPbutils.EncodingAudioProfile):
+ element_factories = Encoders().aencoders
+ else:
+ raise ValueError("Profile type not handled: %s" % profile)
+
+ factories = Gst.ElementFactory.list_filter(element_factories,
+ Gst.Caps(profile.get_format()),
+ Gst.PadDirection.SRC,
+ False)
+
+ factories.sort(key=lambda x: - x.get_rank())
+
+ return factories
+
# ---------------------- UI classes ----------------------------------------- #
diff --git a/pitivi/render.py b/pitivi/render.py
index 6e24dbde..ff18fdbc 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -1575,6 +1575,7 @@ class RenderDialog(Loggable):
"""Handles the changing of the container format combobox."""
if self._setting_encoding_profile:
return
+
factory = get_combo_value(combo)
self.project.muxer = factory.get_name()
diff --git a/tests/test_render.py b/tests/test_render.py
index 7f864c6a..f3f212c7 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -429,6 +429,23 @@ class TestRender(BaseTestMediaLibrary):
"""Tests rendering a simple timeline with the youtube profile."""
self.check_simple_rendering_profile("youtube")
+ @skipUnless(*encoding_target_exists("youtube"))
+ def test_preset_reset_when_changing_muxer(self):
+ """Tests setting the container profile manually."""
+ _, dialog = self.setup_project_with_profile("youtube")
+
+ # The container and video encoder profiles in the "youtube"
+ # EncodingTarget are "qtmux" and "x264enc". They have a common
+ # "preset" called "Profile YouTube".
+ # When changing the container manually from qt4mux to mp4mux
+ # the container profile's "preset" needs to be reset, otherwise
+ # rendering will hang because mp4mux is missing the
+ # "Profile YouTube" preset.
+ self.assertTrue(set_combo_value(dialog.muxer_combo,
+ Gst.ElementFactory.find("mp4mux")))
+
+ self.render(dialog)
+
def test_preset_changes_file_extension(self):
"""Test file extension changes according to the chosen preset."""
_, dialog = self.setup_project_with_profile("youtube")
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]