[pitivi/1.0] previewers: Make the min thumb interval length a constant
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi/1.0] previewers: Make the min thumb interval length a constant
- Date: Tue, 19 Dec 2017 23:41:19 +0000 (UTC)
commit 2c08b1a36feb20a2ae288ebda97d871c78fe3e40
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Sun Dec 10 22:07:19 2017 +0100
previewers: Make the min thumb interval length a constant
Reviewed-by: Thibault Saunier <tsaunier gnome org>
Differential Revision: https://phabricator.freedesktop.org/D1912
pitivi/timeline/elements.py | 2 +-
pitivi/timeline/previewers.py | 70 ++++++++++++++++++++++------------------
tests/test_previewers.py | 28 ++++++++++++++++
3 files changed, 67 insertions(+), 33 deletions(-)
---
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index d5e836a..97bebd3 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -580,7 +580,7 @@ class TimelineElement(Gtk.Layout, Zoomable, Loggable):
self.__update_keyframe_curve_visibility()
if self.__previewer:
- self.__previewer.setSelected(selected)
+ self.__previewer.set_selected(selected)
def __update_keyframe_curve_visibility(self):
"""Updates the keyframes widget visibility by adding or removing it."""
diff --git a/pitivi/timeline/previewers.py b/pitivi/timeline/previewers.py
index 6a5fb03..514e139 100644
--- a/pitivi/timeline/previewers.py
+++ b/pitivi/timeline/previewers.py
@@ -58,6 +58,9 @@ except ImportError:
SAMPLE_DURATION = Gst.SECOND / 100
THUMB_MARGIN_PX = 3
+THUMB_HEIGHT = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX
+THUMB_PERIOD = int(Gst.SECOND / 2)
+assert Gst.SECOND % THUMB_PERIOD == 0
# For the waveforms, ensures we always have a little extra surface when
# scrolling while playing.
MARGIN = 500
@@ -67,8 +70,6 @@ PREVIEW_GENERATOR_SIGNALS = {
"error": (GObject.SIGNAL_RUN_LAST, None, ()),
}
-THUMB_HEIGHT = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX
-
GlobalSettings.addConfigSection("previewers")
GlobalSettings.addConfigOption("previewers_max_cpu",
@@ -433,9 +434,6 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.queue = []
self._thumb_cb_id = None
- # We should have one thumbnail per thumb_period.
- # TODO: get this from the user settings
- self.thumb_period = int(0.5 * Gst.SECOND)
self.thumb_height = THUMB_HEIGHT
self.__image_pixbuf = None
@@ -460,34 +458,36 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.connect("notify::height-request", self._height_changed_cb)
- # Internal API
- def _setupPipeline(self):
+ def _setup_pipeline(self):
"""Creates the pipeline.
It has the form "playbin ! thumbnailsink" where thumbnailsink
is a Bin made out of "videorate ! capsfilter ! gdkpixbufsink"
"""
- # TODO: don't hardcode framerate
- self.pipeline = Gst.parse_launch(
+ pipeline = Gst.parse_launch(
"uridecodebin uri={uri} name=decode ! "
"videoconvert ! "
"videorate ! "
"videoscale method=lanczos ! "
"capsfilter caps=video/x-raw,format=(string)RGBA,height=(int){height},"
- "pixel-aspect-ratio=(fraction)1/1,framerate=2/1 ! "
- "gdkpixbufsink name=gdkpixbufsink".format(uri=self.uri, height=self.thumb_height))
+ "pixel-aspect-ratio=(fraction)1/1,framerate={thumbs_per_second}/1 ! "
+ "gdkpixbufsink name=gdkpixbufsink".format(
+ uri=self.uri,
+ height=self.thumb_height,
+ thumbs_per_second=int(Gst.SECOND / THUMB_PERIOD)))
- # get the gdkpixbufsink and the sinkpad
- self.gdkpixbufsink = self.pipeline.get_by_name("gdkpixbufsink")
+ # Get the gdkpixbufsink which contains the the sinkpad.
+ self.gdkpixbufsink = pipeline.get_by_name("gdkpixbufsink")
- decode = self.pipeline.get_by_name("decode")
+ decode = pipeline.get_by_name("decode")
decode.connect("autoplug-select", self._autoplug_select_cb)
self.__preroll_timeout_id = GLib.timeout_add_seconds(MAX_BRINGING_TO_PAUSED_DURATION,
self.__preroll_timed_out_cb)
- self.pipeline.get_bus().add_signal_watch()
- self.pipeline.get_bus().connect("message", self.__bus_message_cb)
- self.pipeline.set_state(Gst.State.PAUSED)
+ pipeline.get_bus().add_signal_watch()
+ pipeline.get_bus().connect("message", self.__bus_message_cb)
+ pipeline.set_state(Gst.State.PAUSED)
+ return pipeline
def _checkCPU(self):
"""Adjusts when the next thumbnail is generated.
@@ -531,7 +531,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.debug("Could not determine duration of: %s", self.uri)
duration = self.ges_elem.props.duration
- self.queue = list(range(0, duration, self.thumb_period))
+ self.queue = list(range(0, duration, THUMB_PERIOD))
self._checkCPU()
@@ -563,16 +563,22 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self._thumb_cb_id = None
return False
- def _get_thumb_duration(self):
- thumb_duration_tmp = Zoomable.pixelToNs(self.thumb_width + THUMB_MARGIN_PX)
- # quantize thumb length to thumb_period
- thumb_duration = quantize(thumb_duration_tmp, self.thumb_period)
- # make sure that the thumb duration after the quantization isn't
- # smaller than before
- if thumb_duration < thumb_duration_tmp:
- thumb_duration += self.thumb_period
- # make sure that we don't show thumbnails more often than thumb_period
- return max(thumb_duration, self.thumb_period)
+ @property
+ def thumb_interval(self):
+ """Gets the interval for which a thumbnail is displayed.
+
+ Returns:
+ int: a duration in nanos, multiple of THUMB_PERIOD.
+ """
+ interval = Zoomable.pixelToNs(self.thumb_width + THUMB_MARGIN_PX)
+ # Make sure the thumb interval is a multiple of THUMB_PERIOD.
+ quantized = quantize(interval, THUMB_PERIOD)
+ # Make sure the quantized thumb interval fits
+ # the thumb and the margin.
+ if quantized < interval:
+ quantized += THUMB_PERIOD
+ # Make sure we don't show thumbs more often than THUMB_PERIOD.
+ return max(THUMB_PERIOD, quantized)
def _update_thumbnails(self):
"""Updates the thumbnails for the currently visible clip portion."""
@@ -581,10 +587,10 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
thumbs = {}
self.wishlist = []
- thumb_duration = self._get_thumb_duration()
- element_left = quantize(self.ges_elem.props.in_point, thumb_duration)
+ interval = self.thumb_interval
+ element_left = quantize(self.ges_elem.props.in_point, interval)
element_right = self.ges_elem.props.in_point + self.ges_elem.props.duration
- for position in range(element_left, element_right, thumb_duration):
+ for position in range(element_left, element_right, interval):
x = Zoomable.nsToPixel(position) - self.nsToPixel(self.ges_elem.props.in_point)
y = (self.props.height_request - self.thumb_height) / 2
try:
@@ -696,7 +702,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
thumb.props.opacity = opacity
def startGeneration(self):
- self._setupPipeline()
+ self.pipeline = self._setup_pipeline()
self._startThumbnailingWhenIdle()
def _ensure_proxy_thumbnails_cache(self):
diff --git a/tests/test_previewers.py b/tests/test_previewers.py
index 9e855f1..22a5257 100644
--- a/tests/test_previewers.py
+++ b/tests/test_previewers.py
@@ -29,7 +29,9 @@ from gi.repository import Gst
from pitivi.timeline.previewers import get_wavefile_location_for_uri
from pitivi.timeline.previewers import THUMB_HEIGHT
+from pitivi.timeline.previewers import THUMB_PERIOD
from pitivi.timeline.previewers import ThumbnailCache
+from pitivi.timeline.previewers import VideoPreviewer
from tests import common
from tests.test_media_library import BaseTestMediaLibrary
@@ -94,6 +96,32 @@ class TestAudioPreviewer(BaseTestMediaLibrary):
self.assertEqual(samples, SIMPSON_WAVFORM_VALUES)
+class TestVideoPreviewer(common.TestCase):
+ """Tests for the `VideoPreviewer` class."""
+
+ def test_thumb_interval(self):
+ """Checks the `thumb_interval` property."""
+ ges_elem = mock.Mock()
+ ges_elem.props.uri = common.get_sample_uri("1sec_simpsons_trailer.mp4")
+ ges_elem.props.id = common.get_sample_uri("1sec_simpsons_trailer.mp4")
+ previewer = VideoPreviewer(ges_elem, 94)
+ previewer.thumb_width = 1 # Just so it's not None.
+
+ def run_thumb_interval(interval):
+ """Runs thumb_interval."""
+ with mock.patch("pitivi.utils.timeline.Zoomable.pixelToNs") as pixel_to_ns:
+ pixel_to_ns.return_value = interval
+ return previewer.thumb_interval
+
+ self.assertEqual(run_thumb_interval(1), THUMB_PERIOD)
+ self.assertEqual(run_thumb_interval(THUMB_PERIOD - 1), THUMB_PERIOD)
+ self.assertEqual(run_thumb_interval(THUMB_PERIOD), THUMB_PERIOD)
+
+ self.assertEqual(run_thumb_interval(THUMB_PERIOD + 1), 2 * THUMB_PERIOD)
+ self.assertEqual(run_thumb_interval(2 * THUMB_PERIOD - 1), 2 * THUMB_PERIOD)
+ self.assertEqual(run_thumb_interval(2 * THUMB_PERIOD), 2 * THUMB_PERIOD)
+
+
class TestThumbnailCache(BaseTestMediaLibrary):
"""Tests for the ThumbnailCache class."""
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]