Example #1
0
 def _setThumbnail(self, time, pixbuf):
     # Q: Is "time" guaranteed to be nanosecond precise?
     # A: Not always.
     # => __tim says: "that's how it should be"
     # => also see gst-plugins-good/tests/icles/gdkpixbufsink-test
     # => Daniel: It is *not* nanosecond precise when we remove the videorate
     #            element from the pipeline
     # => thiblahute: not the case with mpegts
     original_time = time
     if time in self.thumbs:
         thumb = self.thumbs[time]
     else:
         sorted_times = sorted(self.thumbs.keys())
         index = binary_search(sorted_times, time)
         time = sorted_times[index]
         thumb = self.thumbs[time]
         if thumb.has_pixel_data:
             # If this happens, it means the precision of the thumbnail
             # generator is not good enough for the current thumbnail
             # interval.
             # We could consider shifting the thumbnails, but seems like
             # too much trouble for something which does not happen in
             # practice. My last words..
             self.fixme("Thumbnail is already set for time: %s, %s",
                        format_ns(time), format_ns(original_time))
             return
     thumb.set_from_gdkpixbuf_animated(pixbuf)
     if time in self.queue:
         self.queue.remove(time)
     self.thumb_cache[time] = pixbuf
Example #2
0
 def _setThumbnail(self, time, pixbuf):
     # Q: Is "time" guaranteed to be nanosecond precise?
     # A: Not always.
     # => __tim says: "that's how it should be"
     # => also see gst-plugins-good/tests/icles/gdkpixbufsink-test
     # => Daniel: It is *not* nanosecond precise when we remove the videorate
     #            element from the pipeline
     # => thiblahute: not the case with mpegts
     original_time = time
     if time in self.thumbs:
         thumb = self.thumbs[time]
     else:
         sorted_times = sorted(self.thumbs.keys())
         index = binary_search(sorted_times, time)
         time = sorted_times[index]
         thumb = self.thumbs[time]
         if thumb.has_pixel_data:
             # If this happens, it means the precision of the thumbnail
             # generator is not good enough for the current thumbnail
             # interval.
             # We could consider shifting the thumbnails, but seems like
             # too much trouble for something which does not happen in
             # practice. My last words..
             self.fixme("Thumbnail is already set for time: %s, %s",
                        format_ns(time), format_ns(original_time))
             return
     thumb.set_from_gdkpixbuf_animated(pixbuf)
     if time in self.queue:
         self.queue.remove(time)
     self.thumb_cache[time] = pixbuf
Example #3
0
    def _seekTimeoutCb(self, relative=False):
        self.pending_seek_id = None

        if relative:
            try:
                self.emit('seek-relative', self._time)
            except PipelineError:
                self.error("Error while seeking %s relative", self._time)
                # if an exception happened while seeking, properly
                # reset ourselves
                return False

            self._time = None
        elif self.position is not None:
            position = max(0, self.position)
            self.position = None
            try:
                self.emit('seek', position)
            except PipelineError as e:
                self.error("Error while seeking to position: %s, reason: %s",
                           format_ns(position), e)
                # if an exception happened while seeking, properly
                # reset ourselves
                return False

        if self.pending_position:
            self.seek(self.pending_position, on_idle=True)
            self.pending_position = None

        return False
Example #4
0
    def _seekTimeoutCb(self, relative=False):
        self.pending_seek_id = None

        if relative:
            try:
                self.emit('seek-relative', self._time)
            except PipelineError:
                self.error("Error while seeking %s relative", self._time)
                # if an exception happened while seeking, properly
                # reset ourselves
                return False

            self._time = None
        elif self.position is not None:
            position = max(0, self.position)
            self.position = None
            try:
                self.emit('seek', position)
            except PipelineError as e:
                self.error("Error while seeking to position: %s, reason: %s",
                           format_ns(position), e)
                # if an exception happened while seeking, properly
                # reset ourselves
                return False

        if self.pending_position:
            self.seek(self.pending_position, on_idle=True)
            self.pending_position = None

        return False
Example #5
0
    def getPosition(self, blocks=False):
        """
        Get the current position of the L{Pipeline}.

        @return: The current position or Gst.CLOCK_TIME_NONE
        @rtype: L{long}
        @raise PipelineError: If the position couldn't be obtained.
        """
        maincontext = GLib.main_context_default()
        if blocks and self._recovery_state == self.RecoveryState.NOT_RECOVERING:
            while self._waiting_for_async_done and self._recovery_state == self.RecoveryState.NOT_RECOVERING:
                self.info("Iterating mainloop waiting for the pipeline to be ready to be queried")
                maincontext.iteration(True)

        try:
            res, cur = self._pipeline.query_position(Gst.Format.TIME)
        except Exception as e:
            self.handleException(e)
            raise PipelineError("Couldn't get position")

        if not res:
            raise PipelineError("Position not available")

        self.log("Got position %s", format_ns(cur))
        return cur
Example #6
0
    def simple_seek(self, position):
        """
        Seeks in the L{Pipeline} to the given position.

        @param position: Position to seek to
        @type position: L{long}
        @raise PipelineError: If seek failed
        """
        if self._waiting_for_async_done is True:
            self._next_seek = position
            self.info("Setting next seek to %s", self._next_seek)
            return

        self.debug("position: %s", format_ns(position))

        # clamp between [0, duration]
        position = max(0, min(position, self.getDuration()))

        res = self._pipeline.seek(1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
                                  Gst.SeekType.SET, position,
                                  Gst.SeekType.NONE, -1)
        self._addWaitingForAsyncDoneTimeout()

        if not res:
            raise PipelineError(self.get_name() + " seek failed: " + str(position))

        self._last_position = position

        self.debug("seeking successful")
        self.emit('position', position)
Example #7
0
    def simple_seek(self, position):
        """Seeks in the low-level pipeline to the specified position.

        Args:
            position (int): Position to seek to.

        Raises:
            PipelineError: When the seek fails.
        """
        if self._waiting_for_async_done is True:
            self._next_seek = position
            self.info("Setting next seek to %s", self._next_seek)
            return

        self.debug("position: %s", format_ns(position))

        # clamp between [0, duration]
        position = max(0, min(position, self.getDuration()))

        res = self._pipeline.seek(1.0,
                                  Gst.Format.TIME,
                                  Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
                                  Gst.SeekType.SET,
                                  position,
                                  Gst.SeekType.NONE,
                                  -1)

        if not res:
            raise PipelineError(self.get_name() + " seek failed: " + str(position))

        self._addWaitingForAsyncDoneTimeout()
        self._last_position = position

        self.debug("seeking successful")
        self.emit('position', position)
Example #8
0
    def getPosition(self, fails=True):
        """Gets the current position of the low-level pipeline.

        Returns:
            int: The current position or Gst.CLOCK_TIME_NONE.

        Raises:
            PipelineError: If the position couldn't be obtained.
        """
        try:
            res, cur = self._pipeline.query_position(Gst.Format.TIME)
        except Exception as e:
            self.handleException(e)
            raise PipelineError("Couldn't get position")

        if res:
            self._last_position = cur
        else:
            if fails:
                raise PipelineError("Position not available")

            cur = self._last_position

        self.log("Got position %s", format_ns(cur))
        return cur
Example #9
0
    def getPosition(self, fails=True):
        """Gets the current position of the low-level pipeline.

        Returns:
            int: The current position or Gst.CLOCK_TIME_NONE.

        Raises:
            PipelineError: If the position couldn't be obtained.
        """
        try:
            res, cur = self._pipeline.query_position(Gst.Format.TIME)
        except Exception as e:
            self.handleException(e)
            raise PipelineError("Couldn't get position")

        if res:
            self._last_position = cur
        else:
            if fails:
                raise PipelineError("Position not available")

            cur = self._last_position

        self.log("Got position %s", format_ns(cur))
        return cur
Example #10
0
    def simple_seek(self, position):
        """
        Seeks in the L{Pipeline} to the given position.

        @param position: Position to seek to
        @type position: L{long}
        @raise PipelineError: If seek failed
        """
        if self._waiting_for_async_done is True:
            self._next_seek = position
            self.info("Setting next seek to %s", self._next_seek)
            return

        self.debug("position: %s", format_ns(position))

        # clamp between [0, duration]
        position = max(0, min(position, self.getDuration()) - 1)

        res = self._pipeline.seek(1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH,
                                  Gst.SeekType.SET, position,
                                  Gst.SeekType.NONE, -1)
        self._addWaitingForAsyncDoneTimeout()

        if not res:
            raise PipelineError(self.get_name() + " seek failed: " +
                                str(position))

        self._last_position = position

        self.debug("seeking successful")
        self.emit('position', position)
Example #11
0
    def simple_seek(self, position):
        """Seeks in the low-level pipeline to the specified position.

        Args:
            position (int): Position to seek to.

        Raises:
            PipelineError: When the seek fails.
        """
        if self._busy_async or self.getState() < Gst.State.PAUSED:
            self._next_seek = position
            self.info("Setting next seek to %s", self._next_seek)
            return

        self._next_seek = None

        # clamp between [0, duration]
        position = max(0, min(position, self.getDuration()))
        self.debug("Seeking to position: %s", format_ns(position))
        res = self._pipeline.seek(1.0,
                                  Gst.Format.TIME,
                                  Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
                                  Gst.SeekType.SET,
                                  position,
                                  Gst.SeekType.NONE,
                                  -1)
        if not res:
            raise PipelineError(self.get_name() + " seek failed: " + str(position))

        self._addWaitingForAsyncDoneTimeout()

        self.emit('position', position)
Example #12
0
    def clipTrimPreview(self, tl_obj, position):
        """
        While a clip is being trimmed, show a live preview of it.
        """
        if isinstance(tl_obj,
                      GES.TitleClip) or tl_obj.props.is_image or not hasattr(
                          tl_obj, "get_uri"):
            self.log("%s is an image or has no URI, so not previewing trim" %
                     tl_obj)
            return False

        clip_uri = tl_obj.props.uri
        cur_time = time()
        if self.pipeline == self.app.project_manager.current_project.pipeline:
            self.debug("Creating temporary pipeline for clip %s, position %s",
                       clip_uri, format_ns(position))
            self._oldTimelinePos = self.pipeline.getPosition()
            self.setPipeline(AssetPipeline(tl_obj))
            self._lastClipTrimTime = cur_time

        if (cur_time - self._lastClipTrimTime
            ) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED:
            # Do not seek more than once every 200 ms (for performance)
            self.pipeline.simple_seek(position)
            self._lastClipTrimTime = cur_time
Example #13
0
 def getDuration(self):
     """Gets the duration of the low-level pipeline."""
     dur = self._getDuration()
     self.log("Got duration %s", format_ns(dur))
     if self._duration != dur:
         self.emit("duration-changed", dur)
     self._duration = dur
     return dur
Example #14
0
 def getDuration(self):
     """Gets the duration of the low-level pipeline."""
     dur = self._getDuration()
     self.log("Got duration %s", format_ns(dur))
     if self._duration != dur:
         self.emit("duration-changed", dur)
     self._duration = dur
     return dur
Example #15
0
    def getDuration(self, format=Gst.Format.TIME):
        """
        Get the duration of the C{Pipeline}.
        """
        self.log("format %r", format)

        dur = self._getDuration(format)
        self.log("Got duration %s", format_ns(dur))
        if self._duration != dur:
            self.emit("duration-changed", dur)

        self._duration = dur

        return dur
Example #16
0
    def getPosition(self):
        """
        Get the current position of the L{Pipeline}.

        @return: The current position or Gst.CLOCK_TIME_NONE
        @rtype: L{long}
        @raise PipelineError: If the position couldn't be obtained.
        """
        try:
            res, cur = self._pipeline.query_position(Gst.Format.TIME)
        except Exception as e:
            self.handleException(e)
            raise PipelineError("Couldn't get position")

        if not res:
            raise PipelineError("Position not available")

        self.log("Got position %s", format_ns(cur))
        return cur
Example #17
0
    def getPosition(self):
        """
        Get the current position of the L{Pipeline}.

        @return: The current position or Gst.CLOCK_TIME_NONE
        @rtype: L{long}
        @raise PipelineError: If the position couldn't be obtained.
        """
        try:
            res, cur = self._pipeline.query_position(Gst.Format.TIME)
        except Exception as e:
            self.handleException(e)
            raise PipelineError("Couldn't get position")

        if not res:
            raise PipelineError("Position not available")

        self.log("Got position %s", format_ns(cur))
        return cur
Example #18
0
    def simple_seek(self, position, format=Gst.Format.TIME):
        """
        Seeks in the L{Pipeline} to the given position.

        @param position: Position to seek to
        @type position: L{long}
        @param format: The C{Format} of the seek position
        @type format: C{Gst.Format}
        @raise PipelineError: If seek failed
        """
        if self._waiting_for_async_done is True:
            self._next_seek = (position, format)
            self.info("Setting next seek to %s", self._next_seek)
            return

        if format == Gst.Format.TIME:
            self.debug("position: %s", format_ns(position))
        else:
            self.debug("position: %d, format: %d", position, format)

        # clamp between [0, duration]
        if format == Gst.Format.TIME:
            position = max(0, min(position, self.getDuration()) - 1)

        res = self._pipeline.seek(1.0, format, Gst.SeekFlags.FLUSH,
                                  Gst.SeekType.SET, position,
                                  Gst.SeekType.NONE, -1)
        self._waiting_for_async_done = True

        if self._timeout_async_id:
            GLib.source_remove(self._timeout_async_id)
            self._timeout_async_id = 0

        self._timeout_async_id = GLib.timeout_add(1000, self._resetWaitingForAsyncDone)

        if not res:
            self.debug("seeking failed")
            raise PipelineError("seek failed")

        self.lastPosition = position

        self.debug("seeking successful")
        self.emit('position', position)
Example #19
0
    def simple_seek(self, position):
        if self.props.timeline.is_empty():
            # Nowhere to seek.
            return

        if self._rendering():
            raise PipelineError("Trying to seek while rendering")

        st = Gst.Structure.new_empty("seek")
        if self.getState() == Gst.State.PLAYING:
            st.set_value("playback_time", float(
                self.getPosition()) / Gst.SECOND)
        st.set_value("start", float(position / Gst.SECOND))
        st.set_value("flags", "accurate+flush")
        self.app.write_action(st)

        try:
            SimplePipeline.simple_seek(self, position)
        except PipelineError as e:
            self.error("Error while seeking to position: %s, reason: %s",
                       format_ns(position), e)
Example #20
0
    def clipTrimPreview(self, tl_obj, position):
        """
        While a clip is being trimmed, show a live preview of it.
        """
        if isinstance(tl_obj, GES.TitleClip) or tl_obj.props.is_image or not hasattr(tl_obj, "get_uri"):
            self.log("%s is an image or has no URI, so not previewing trim" % tl_obj)
            return False

        clip_uri = tl_obj.props.uri
        cur_time = time()
        if self.pipeline == self.app.current_project.pipeline:
            self.debug("Creating temporary pipeline for clip %s, position %s",
                clip_uri, format_ns(position))
            self._oldTimelinePos = self.pipeline.getPosition()
            self.setPipeline(AssetPipeline(tl_obj))
            self._lastClipTrimTime = cur_time

        if (cur_time - self._lastClipTrimTime) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED:
            # Do not seek more than once every 200 ms (for performance)
            self.pipeline.simple_seek(position)
            self._lastClipTrimTime = cur_time
Example #21
0
    def simple_seek(self, position):
        if self._timeline.is_empty():
            # Nowhere to seek.
            return

        if self._rendering():
            raise PipelineError("Trying to seek while rendering")

        st = Gst.Structure.new_empty("seek")
        if self.getState() == Gst.State.PLAYING:
            st.set_value("playback_time", float(
                self.getPosition()) / Gst.SECOND)
        st.set_value("start", float(position / Gst.SECOND))
        st.set_value("flags", "accurate+flush")
        self.app.write_action(st)

        try:
            SimplePipeline.simple_seek(self, position)
        except PipelineError as e:
            self.error("Error while seeking to position: %s, reason: %s",
                       format_ns(position), e)
Example #22
0
    def clipTrimPreview(self, clip, position):
        """Shows a live preview of a clip being trimmed."""
        if not hasattr(clip, "get_uri") or isinstance(clip, GES.TitleClip) or clip.props.is_image:
            self.log(
                "%s is an image or has no URI, so not previewing trim" % clip)
            return False

        clip_uri = clip.props.uri
        cur_time = time()
        if self.pipeline == self.app.project_manager.current_project.pipeline:
            self.debug("Creating temporary pipeline for clip %s, position %s",
                       clip_uri, format_ns(position))
            self._oldTimelinePos = self.pipeline.getPosition(False)
            self.pipeline.set_state(Gst.State.NULL)
            self.setPipeline(AssetPipeline(clip))
            self.__owning_pipeline = True
            self._lastClipTrimTime = cur_time

        if (cur_time - self._lastClipTrimTime) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED:
            # Do not seek more than once every 200 ms (for performance)
            self.pipeline.simple_seek(position)
            self._lastClipTrimTime = cur_time
Example #23
0
    def clipTrimPreview(self, clip, position):
        """Shows a live preview of a clip being trimmed."""
        if not hasattr(clip, "get_uri") or isinstance(clip, GES.TitleClip) or clip.props.is_image:
            self.log(
                "%s is an image or has no URI, so not previewing trim" % clip)
            return False

        clip_uri = clip.props.uri
        cur_time = time()
        if self.pipeline == self.app.project_manager.current_project.pipeline:
            self.debug("Creating temporary pipeline for clip %s, position %s",
                       clip_uri, format_ns(position))
            self._oldTimelinePos = self.pipeline.getPosition(False)
            self.pipeline.set_state(Gst.State.NULL)
            self.setPipeline(AssetPipeline(clip))
            self.__owning_pipeline = True
            self._lastClipTrimTime = cur_time

        if (cur_time - self._lastClipTrimTime) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED:
            # Do not seek more than once every 200 ms (for performance)
            self.pipeline.simple_seek(position)
            self._lastClipTrimTime = cur_time