[pitivi] render: Fix clips size restoring after scaled rendering



commit c9293d180006243539bd0d4ee8d191f1d706a96f
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Sun Jan 7 12:52:55 2018 +0100

    render: Fix clips size restoring after scaled rendering
    
    Fixes https://phabricator.freedesktop.org/T7809
    
    Differential Revision: https://phabricator.freedesktop.org/D1928

 pitivi/render.py            |   33 ++++++++++++++++-----------
 pitivi/timeline/timeline.py |    2 +-
 tests/common.py             |   48 ++++++++++++++++++++++++----------------
 tests/test_render.py        |   51 ++++++++++++++++++++++++++++++++++++++----
 4 files changed, 95 insertions(+), 39 deletions(-)
---
diff --git a/pitivi/render.py b/pitivi/render.py
index d74f00f..74b87aa 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -872,11 +872,11 @@ class RenderDialog(Loggable):
         self._rendering_is_paused = False
         self._time_spent_paused = 0
         self._pipeline.set_state(Gst.State.NULL)
+        self.project.set_rendering(False)
         self.__useProxyAssets()
         self._disconnectFromGst()
         self._pipeline.set_mode(GES.PipelineFlags.FULL_PREVIEW)
         self._pipeline.set_state(Gst.State.PAUSED)
-        self.project.set_rendering(False)
 
     def _pauseRender(self, unused_progress):
         self._rendering_is_paused = self.progress.play_pause_button.get_active(
@@ -926,7 +926,7 @@ class RenderDialog(Loggable):
             self.debug("Rendering from proxies, not replacing assets")
             return
 
-        for layer in self.app.gui.timeline_ui.ges_timeline.get_layers():
+        for layer in self.app.project_manager.current_project.ges_timeline.get_layers():
             for clip in layer.get_clips():
                 if not isinstance(clip, GES.UriClip):
                     continue
@@ -934,29 +934,34 @@ class RenderDialog(Loggable):
                 asset = clip.get_asset()
                 asset_target = asset.get_proxy_target()
                 if not asset_target:
+                    # The asset is not a proxy.
                     continue
 
                 if self.__automatically_use_proxies.get_active():
-                    if self.app.proxy_manager.isAssetFormatWellSupported(
+                    if not self.app.proxy_manager.isAssetFormatWellSupported(
                             asset_target):
-                        self.info("Asset %s format well supported, "
-                                  "rendering from real asset.",
-                                  asset_target.props.id)
-                    else:
-                        self.info("Asset %s format not well supported, "
+                        self.info("Original asset %s format not well supported, "
                                   "rendering from proxy.",
                                   asset_target.props.id)
                         continue
 
-                if not asset_target.get_error():
-                    clip.set_asset(asset_target)
-                    self.error("Using %s as an asset (instead of %s)",
-                               asset_target.get_id(),
-                               asset.get_id())
-                    self.__unproxiedClips[clip] = asset
+                    self.info("Original asset %s format well supported, "
+                              "rendering from real asset.",
+                              asset_target.props.id)
+
+                if asset_target.get_error():
+                    # The original asset cannot be used.
+                    continue
+
+                clip.set_asset(asset_target)
+                self.info("Using original asset %s (instead of proxy %s)",
+                          asset_target.get_id(),
+                          asset.get_id())
+                self.__unproxiedClips[clip] = asset
 
     def __useProxyAssets(self):
         for clip, asset in self.__unproxiedClips.items():
+            self.info("Reverting to using proxy asset %s", asset)
             clip.set_asset(asset)
 
         self.__unproxiedClips = {}
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index a916413..994ba98 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -439,7 +439,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
     def setProject(self, project):
         """Connects to the GES.Timeline holding the project."""
         # Avoid starting/closing preview generation like crazy while tearing down project
-        with Previewer.manager.paused(True):
+        with Previewer.manager.paused(interrupt=True):
             if self.ges_timeline is not None:
                 self.disconnect_by_func(self._button_press_event_cb)
                 self.disconnect_by_func(self._button_release_event_cb)
diff --git a/tests/common.py b/tests/common.py
index 5550376..d488a18 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -27,7 +27,6 @@ import tempfile
 import unittest
 from unittest import mock
 
-from gi.repository import GES
 from gi.repository import GLib
 from gi.repository import Gst
 from gi.repository import Gtk
@@ -72,6 +71,10 @@ def create_pitivi_mock(**settings):
     app.settings = __create_settings(**settings)
     app.proxy_manager = ProxyManager(app)
 
+    # TODO: Get rid of Zoomable.app.
+    from pitivi.utils.timeline import Zoomable
+    Zoomable.app = app
+
     return app
 
 
@@ -91,6 +94,12 @@ def create_pitivi(**settings):
 
 
 def create_timeline_container():
+    # TODO: Get rid of Previewer.manager.
+    from pitivi.timeline.previewers import Previewer
+    from pitivi.timeline.previewers import PreviewGeneratorManager
+    assert hasattr(Previewer, "manager")
+    Previewer.manager = PreviewGeneratorManager()
+
     app = create_pitivi_mock()
     project_manager = ProjectManager(app)
     project_manager.newBlankProject()
@@ -118,10 +127,12 @@ def create_main_loop():
         timed_out = True
         mainloop.quit()
 
-    def run(timeout_seconds=5):
+    def run(timeout_seconds=5, until_empty=False):
         source = GLib.timeout_source_new_seconds(timeout_seconds)
         source.set_callback(timeout_cb)
         source.attach()
+        if until_empty:
+            GLib.idle_add(mainloop.quit)
         GLib.MainLoop.run(mainloop)
         source.destroy()
         if timed_out:
@@ -249,29 +260,28 @@ def created_project_file(asset_uri):
     os.remove(xges_path)
 
 
-def get_sample_uri(sample, tests_dir=None):
-    if not tests_dir:
+def get_sample_uri(sample, samples_dir=None):
+    if not samples_dir:
         tests_dir = os.path.dirname(os.path.abspath(__file__))
-        tests_dir = os.path.join(tests_dir, "samples")
-    return Gst.filename_to_uri(os.path.join(tests_dir, sample))
+        samples_dir = os.path.join(tests_dir, "samples")
+    return Gst.filename_to_uri(os.path.join(samples_dir, sample))
 
 
 @contextlib.contextmanager
 def cloned_sample(*samples):
     """Gets a context manager which commits the transaction at the end."""
-    tmpdir = tempfile.mkdtemp(suffix="pitivi_cloned_samples")
-    module = globals()
-    original_get_sample_uri = module["get_sample_uri"]
-    module["get_sample_uri"] = lambda sample: original_get_sample_uri(sample, tests_dir=tmpdir)
-    for sample in samples:
-        sample_path = path_from_uri(original_get_sample_uri(sample))
-        clone_path = path_from_uri(get_sample_uri(sample))
-        shutil.copyfile(sample_path, clone_path)
-    try:
-        yield tmpdir
-    finally:
-        module["get_sample_uri"] = original_get_sample_uri
-        shutil.rmtree(tmpdir)
+    with tempfile.TemporaryDirectory() as tmpdir:
+        module = globals()
+        original_get_sample_uri = module["get_sample_uri"]
+        module["get_sample_uri"] = lambda sample: original_get_sample_uri(sample, samples_dir=tmpdir)
+        try:
+            for sample in samples:
+                sample_path = path_from_uri(original_get_sample_uri(sample))
+                clone_path = path_from_uri(get_sample_uri(sample))
+                shutil.copyfile(sample_path, clone_path)
+            yield tmpdir
+        finally:
+            module["get_sample_uri"] = original_get_sample_uri
 
 
 def get_clip_children(ges_clip, *track_types, recursive=False):
diff --git a/tests/test_render.py b/tests/test_render.py
index 2c9fac2..e4118f9 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -32,9 +32,11 @@ from gi.repository import Gtk
 from pitivi.preset import EncodingTargetManager
 from pitivi.render import Encoders
 from pitivi.render import extension_for_muxer
+from pitivi.timeline.timeline import TimelineContainer
 from pitivi.utils.ui import get_combo_value
 from pitivi.utils.ui import set_combo_value
 from tests import common
+from tests.test_media_library import BaseTestMediaLibrary
 
 
 def factory_exists(*factories):
@@ -63,7 +65,7 @@ def find_preset_row_index(combo, name):
     return None
 
 
-class TestRender(common.TestCase):
+class TestRender(BaseTestMediaLibrary):
     """Tests for functions."""
 
     def test_extensions_supported(self):
@@ -104,8 +106,8 @@ class TestRender(common.TestCase):
         mainloop.run()
 
         layer, = project.ges_timeline.get_layers()
-        layer.add_asset(project.list_assets(GES.UriClip)[0],
-                        0, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.UNKNOWN)
+        asset, = project.list_assets(GES.UriClip)
+        layer.add_asset(asset, 0, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.UNKNOWN)
 
         return project
 
@@ -263,7 +265,9 @@ class TestRender(common.TestCase):
 
     def check_simple_rendering_profile(self, profile_name):
         """Checks that rendering with the specified profile works."""
-
+        # TODO: Get rid of Zoomable._instances.
+        from pitivi.utils.timeline import Zoomable
+        del Zoomable._instances[:]
         project = self.create_simple_project()
         dialog = self.create_rendering_dialog(project)
 
@@ -290,18 +294,55 @@ class TestRender(common.TestCase):
             message = dialog._pipeline.get_bus().timed_pop_filtered(
                 10 * Gst.SECOND,
                 Gst.MessageType.EOS | Gst.MessageType.ERROR)
+            self.assertIsNotNone(message)
             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
+            struct = message.get_structure()
             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)
 
+            if message:
+                dialog._pipeline.get_bus().post(message)
+
+    def test_rendering_with_scale(self):
+        """Tests rendering with a smaller scale."""
+        sample_name = "30fps_numeroted_frames_red.mkv"
+        with common.cloned_sample(sample_name):
+            self.check_import([sample_name])
+
+            project = self.app.project_manager.current_project
+            timeline_container = TimelineContainer(self.app)
+            timeline_container.setProject(project)
+
+            assets = project.list_assets(GES.UriClip)
+            asset, = [a for a in assets if "proxy" in a.props.id]
+            layer, = project.ges_timeline.get_layers()
+            clip = asset.extract()
+            layer.add_clip(clip)
+            video_source = clip.find_track_element(None, GES.VideoUriSource)
+            self.assertEqual(video_source.get_child_property("width")[1], 320)
+            self.assertEqual(video_source.get_child_property("height")[1], 240)
+
+            dialog = self.create_rendering_dialog(project)
+
+            # Simulate setting the scale to 10%.
+            with mock.patch.object(dialog.scale_spinbutton, "get_value",
+                                   return_value=10):
+                dialog._scaleSpinbuttonChangedCb(None)
+                self.render(dialog)
+
+            self.mainloop.run(until_empty=True)
+
+            video_source = clip.find_track_element(None, GES.VideoUriSource)
+            self.assertEqual(video_source.get_child_property("width")[1], 320)
+            self.assertEqual(video_source.get_child_property("height")[1], 240)
+
     @skipUnless(*encoding_target_exists("youtube"))
     # pylint: disable=invalid-name
     def test_rendering_with_youtube_profile(self):


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