[pitivi] render: Avoid incompatibilities between restriction caps and format ones



commit 7ada44e7852779dff5911ac90e258e3c7d3e28a9
Author: Thibault Saunier <tsaunier gnome org>
Date:   Sat Jul 15 00:48:37 2017 -0400

    render: Avoid incompatibilities between restriction caps and format ones
    
    This would lead to rendering being impossible.
    
    Fixes T7754
    
    Reviewed-by: Alex Băluț <<alexandru balut gmail com>>
    Differential Revision: https://phabricator.freedesktop.org/D1780

 pitivi/project.py    |   15 +++++++++-
 pitivi/render.py     |    2 +-
 tests/test_render.py |   67 ++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 79 insertions(+), 5 deletions(-)
---
diff --git a/pitivi/project.py b/pitivi/project.py
index 4af319d..ce5cccc 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -1529,8 +1529,19 @@ class Project(Loggable, GES.Project):
     def _ensureAudioRestrictions(self, profile=None, ref_restrictions=None):
         if not profile:
             profile = self.audio_profile
-        return self._ensureRestrictions(profile,
-            [("channels", 2), ("rate", 44100)], ref_restrictions)
+        defaults = [["channels", 2], ["rate", 44100]]
+        for fv in defaults:
+            field, value = fv
+            fvalue = profile.get_format()[0][field]
+            if isinstance(fvalue, Gst.ValueList) and value not in fvalue.array:
+                fv[1] = fvalue.array[0]
+            elif isinstance(fvalue, range) and value not in fvalue:
+                fv[1] = fvalue[0]
+            else:
+                self.warning("How should we handle ensuring restriction caps"
+                             " compatibility for field %s with format value: %s",
+                             field, fvalue)
+        return self._ensureRestrictions(profile, defaults, ref_restrictions)
 
     def _maybeInitSettingsFromAsset(self, asset):
         """Updates the project settings to match the specified asset.
diff --git a/pitivi/render.py b/pitivi/render.py
index ad62870..67d3da5 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -476,7 +476,7 @@ class RenderDialog(Loggable):
         def factory(x):
             return Encoders().factories_by_name.get(getattr(self.project, x))
 
-        self.project.set_container_profile(encoding_profile)
+        self.project.set_container_profile(encoding_profile, reset_all=True)
         self._setting_encoding_profile = True
 
         if not set_combo_value(self.muxer_combo, factory('muxer')):
diff --git a/tests/test_render.py b/tests/test_render.py
index 1575636..c3bcf48 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -19,6 +19,8 @@
 """Tests for the render module."""
 # pylint: disable=protected-access,no-self-use
 # pylint: disable=too-many-locals
+import os
+import tempfile
 from unittest import mock
 from unittest import skipUnless
 
@@ -44,6 +46,14 @@ def factory_exists(*factories):
     return True, ""
 
 
+def encoding_target_exists(tname):
+    """Checks if a GstEncodingTarget called @name exists."""
+    for target in GstPbutils.encoding_list_all_targets():
+        if tname in target.get_name().split(";"):
+            return True, ""
+    return False, "EncodingTarget %s not present on the system" % tname
+
+
 def find_preset_row_index(combo, name):
     """Finds @name in @combo."""
     for i, row in enumerate(combo.get_model()):
@@ -147,7 +157,7 @@ class TestRender(common.TestCase):
             profile = project.container_profile.copy()
             vprofile, = [p for p in profile.get_profiles()
                          if isinstance(p, GstPbutils.EncodingVideoProfile)]
-            vprofile.set_restriction(Gst.Caps('video/x-raw'))
+            vprofile.set_restriction(Gst.Caps("video/x-raw"))
             project.set_container_profile(profile)
             self.assertEqual(project.video_profile.get_restriction()[0]["format"],
                              "Y444")
@@ -157,7 +167,7 @@ class TestRender(common.TestCase):
     def test_loading_preset(self):
         """Checks preset values are properly exposed in the UI."""
         def preset_changed_cb(combo, changed):
-            """Callback for the 'combo::changed' signal."""
+            """Callback for the "combo::changed" signal."""
             changed.append(1)
 
         project = self.create_simple_project()
@@ -249,3 +259,56 @@ class TestRender(common.TestCase):
                          profile_names + ['test'])
         active_iter = preset_combo.get_active_iter()
         self.assertEqual(preset_combo.props.model.get_value(active_iter, 0), 'test')
+
+    def check_simple_rendering_profile(self, profile_name):
+        """Checks that rendering with the specified profile works."""
+
+        project = self.create_simple_project()
+        dialog = self.create_rendering_dialog(project)
+
+        # Select wanted profile
+        preset_combo = dialog.render_presets.combo
+        if profile_name:
+            i = find_preset_row_index(preset_combo, profile_name)
+            self.assertIsNotNone(i)
+            preset_combo.set_active(i)
+        from pitivi.render import RenderingProgressDialog
+
+        with tempfile.TemporaryDirectory() as temp_dir:
+            # Start rendering
+            with mock.patch.object(dialog.filebutton, "get_uri",
+                                   return_value=Gst.filename_to_uri(temp_dir)):
+                with mock.patch.object(dialog.fileentry, "get_text", return_value="outfile"):
+                    with mock.patch.object(RenderingProgressDialog, "__new__"):
+                        dialog._renderButtonClickedCb(None)
+
+            message = dialog._pipeline.get_bus().timed_pop_filtered(
+                10 * Gst.SECOND,
+                Gst.MessageType.EOS | Gst.MessageType.ERROR)
+            Gst.debug_bin_to_dot_file_with_ts(
+                dialog._pipeline, Gst.DebugGraphDetails.ALL,
+                "test_rendering_with_profile.dot")
+
+            result_file = Gst.filename_to_uri(os.path.join(temp_dir, "outfile"))
+            struct = message.get_structure() if message else None
+            self.assertEqual(message.type, Gst.MessageType.EOS,
+                             struct.to_string() if struct else message)
+            asset = GES.UriClipAsset.request_sync(result_file)
+            # FIXME Check more things?
+            self.assertIsNotNone(asset)
+
+    @skipUnless(*encoding_target_exists("youtube"))
+    # pylint: disable=invalid-name
+    def test_rendering_with_youtube_profile(self):
+        """Tests rendering a simple timeline with the youtube profile."""
+        self.check_simple_rendering_profile("youtube")
+
+    @skipUnless(*encoding_target_exists("dvd"))
+    def test_rendering_with_dvd_profile(self):
+        """Tests rendering a simple timeline with the DVD profile."""
+        self.check_simple_rendering_profile("dvd")
+
+    # pylint: disable=invalid-name
+    def test_rendering_with_default_profile(self):
+        """Tests rendering a simple timeline with the default profile."""
+        self.check_simple_rendering_profile(None)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]