pitivi r1240 - in branches/SOC_2008_BLEWIS: . pitivi/elements



Author: edwardrv
Date: Mon Aug 25 16:41:03 2008
New Revision: 1240
URL: http://svn.gnome.org/viewvc/pitivi?rev=1240&view=rev

Log:
* pitivi/elements/imagefreeze.py:
Rewrite imagefreeze seeking/output.
Now uses a gst.Task for outputting and proper seeking handling.


Modified:
   branches/SOC_2008_BLEWIS/ChangeLog
   branches/SOC_2008_BLEWIS/pitivi/elements/imagefreeze.py

Modified: branches/SOC_2008_BLEWIS/pitivi/elements/imagefreeze.py
==============================================================================
--- branches/SOC_2008_BLEWIS/pitivi/elements/imagefreeze.py	(original)
+++ branches/SOC_2008_BLEWIS/pitivi/elements/imagefreeze.py	Mon Aug 25 16:41:03 2008
@@ -85,6 +85,10 @@
         self._segment.init(gst.FORMAT_TIME)
         self._needsegment = True
         self._bufferduration = 0
+        # this is the buffer we store and repeatedly output
+        self._buffer = None
+        # this will be set by our task
+        self.last_return = gst.FLOW_OK
 
     def _sink_setcaps(self, pad, caps):
         gst.debug("caps %s" % caps.to_string())
@@ -130,15 +134,26 @@
         if event.type == gst.EVENT_SEEK:
             rate,fmt,flags,startt,start,stopt,stop = event.parse_seek()
             gst.debug("Handling seek event %r" % flags)
+            if flags & gst.SEEK_FLAG_FLUSH:
+                gst.debug("sending flush_start event")
+                self.srcpad.push_event(gst.event_new_flush_start())
             self._segment.set_seek(*event.parse_seek())
             gst.debug("_segment start:%s stop:%s" % (gst.TIME_ARGS(self._segment.start),
                                                      gst.TIME_ARGS(self._segment.stop)))
             # create a new initial seek
-            self._needsegment = True
+            gst.debug("pausing task")
+            self.srcpad.pause_task()
+            gst.debug("task paused")
             seek = gst.event_new_seek(1.0, gst.FORMAT_TIME, flags,
                                       gst.SEEK_TYPE_NONE, 0,
                                       gst.SEEK_TYPE_NONE, 0)
-            return self.sinkpad.push_event(seek)
+            #return self.sinkpad.push_event(seek)
+            self._needsegment = True
+            if flags & gst.SEEK_FLAG_FLUSH:
+                self.srcpad.push_event(gst.event_new_flush_stop())
+            self.srcpad.start_task(self.our_task)
+            return True
+
         return self.sinkpad.push_event(event)
 
     def _sink_event(self, pad, event):
@@ -153,53 +168,63 @@
     def _sink_chain(self, pad, buffer):
         gst.debug("buffer %s %s" % (gst.TIME_ARGS(buffer.timestamp),
                                     gst.TIME_ARGS(buffer.duration)))
-        res = gst.FLOW_OK
-
-        # and now we go in a glorious loop :)
-        while res == gst.FLOW_OK:
-            gst.debug("needsegment: %r" % self._needsegment)
-
-            if self._needsegment:
-                gst.debug("Need to output a new segment")
-                segment = gst.event_new_new_segment(False,
-                                                    self._segment.rate,
-                                                    self._segment.format,
-                                                    self._segment.start,
-                                                    self._segment.stop,
-                                                    self._segment.start)
-                self.srcpad.push_event(segment)
-                # calculate offset
-                # offset is int(segment.start / outputrate)
-                self._offset = int(self._segment.start * self._outputrate.num / self._outputrate.denom / gst.SECOND)
-                self._needsegment = False
-
-            # new position
-            position = self._offset * gst.SECOND * self._outputrate.denom / self._outputrate.num
-            if self._segment.stop != -1 and position > self._segment.stop:
-                gst.debug("end of configured segment (position:%s / segment_stop:%s)" % (gst.TIME_ARGS(position),
-                                                                                         gst.TIME_ARGS(self._segment.stop)))
-                # end of stream/segment handling
-                if self._segment.flags & gst.SEEK_FLAG_SEGMENT:
-                    # emit a gst.MESSAGE_SEGMENT_DONE
-                    self.post_message(gst.message_new_segment_done(self, gst.FORMAT_TIME, self._segment.stop))
-                else:
-                    self.srcpad.push_event(gst.event_new_eos())
-                res = gst.FLOW_WRONG_STATE
-                break
-
-            # we need to update the caps here !
-            obuf = buffer.make_metadata_writable()
-            ok, nstart, nstop = self._segment.clip(gst.FORMAT_TIME,
-                                                   position, position + self._bufferduration)
-            if ok:
-                obuf.timestamp = nstart
-                obuf.duration = nstop - nstart
-                obuf.caps = self._srccaps
-                gst.debug("Pushing out buffer %s" % gst.TIME_ARGS(obuf.timestamp))
-                res = self.srcpad.push(obuf)
-            self._offset += 1
-
-        return res
+        if self._buffer != None:
+            gst.debug("already have a buffer ! Returning GST_FLOW_WRONG_STATE")
+            return gst.FLOW_WRONG_STATE
+
+        self._buffer = buffer
+        self.srcpad.start_task(self.our_task)
+        return gst.FLOW_WRONG_STATE
+
+    def our_task(self, something):
+        #this is where we repeatedly output our buffer
+        gst.debug("self:%r, something:%r" % (self, something))
+
+        gst.debug("needsegment: %r" % self._needsegment)
+        if self._needsegment:
+            gst.debug("Need to output a new segment")
+            segment = gst.event_new_new_segment(False,
+                                                self._segment.rate,
+                                                self._segment.format,
+                                                self._segment.start,
+                                                self._segment.stop,
+                                                self._segment.start)
+            self.srcpad.push_event(segment)
+            # calculate offset
+            # offset is int(segment.start / outputrate)
+            self._offset = int(self._segment.start * self._outputrate.num / self._outputrate.denom / gst.SECOND)
+            self._needsegment = False
+            gst.debug("Newsegment event pushed")
+
+        # new position
+        position = self._offset * gst.SECOND * self._outputrate.denom / self._outputrate.num
+        if self._segment.stop != -1 and position > self._segment.stop:
+            gst.debug("end of configured segment (position:%s / segment_stop:%s)" % (gst.TIME_ARGS(position),
+                                                                                     gst.TIME_ARGS(self._segment.stop)))
+            # end of stream/segment handling
+            if self._segment.flags & gst.SEEK_FLAG_SEGMENT:
+                # emit a gst.MESSAGE_SEGMENT_DONE
+                self.post_message(gst.message_new_segment_done(self, gst.FORMAT_TIME, self._segment.stop))
+            else:
+                self.srcpad.push_event(gst.event_new_eos())
+            self.last_return = gst.FLOW_WRONG_STATE
+            self.srcpad.pause_task()
+
+        # we need to update the caps here !
+        obuf = self._buffer.make_metadata_writable()
+        ok, nstart, nstop = self._segment.clip(gst.FORMAT_TIME,
+                                               position, position + self._bufferduration)
+        if ok:
+            obuf.timestamp = nstart
+            obuf.duration = nstop - nstart
+            obuf.caps = self._srccaps
+            gst.debug("Pushing out buffer %s" % gst.TIME_ARGS(obuf.timestamp))
+            self.last_return = self.srcpad.push(obuf)
+        self._offset += 1
+
+        if self.last_return != gst.FLOW_OK:
+            gst.debug("Pausing ourself, last_return : %s" % gst.flow_get_name(self.last_return))
+            self.srcpad.pause_task()
 
     def do_change_state(self, transition):
         if transition in [gst.STATE_CHANGE_READY_TO_PAUSED, gst.STATE_CHANGE_PAUSED_TO_READY]:
@@ -207,3 +232,67 @@
         return gst.Element.do_change_state(self, transition)
 
 gobject.type_register(ImageFreeze)
+
+def dataprobe(pad, data):
+    if isinstance(data, gst.Buffer):
+        print "Buffer", gst.TIME_ARGS(data.timestamp), gst.TIME_ARGS(data.duration), data.caps.to_string()
+    else:
+        print "Event", data.type
+        if data.type == gst.EVENT_NEWSEGMENT:
+            print data.parse_new_segment()
+    return True
+
+def make_image_video_bin(location):
+    b = gst.Bin("image-video-bin-"+location)
+    src = gst.element_factory_make("filesrc")
+    src.props.location = location
+    src.props.blocksize = 1024 * 1024
+    dec = gst.element_factory_make("jpegdec")
+    vscale = gst.element_factory_make("videoscale")
+    freeze = ImageFreeze()
+    cfil = gst.element_factory_make("capsfilter")
+    cfil.props.caps = gst.Caps("video/x-raw-yuv,framerate=25/1")
+    p.add(src, dec, vscale, freeze, cfil)
+    gst.element_link_many(src, dec, vscale)
+    vscale.link(freeze, gst.Caps("video/x-raw-yuv,width=640,height=480"))
+    gst.element_link_many(freeze, cfil)
+
+    b.add_pad(gst.GhostPad("src", cfil.get_pad("src")))
+
+    return b
+
+def post_link(gnls, pad, q):
+    gnls.link(q)
+
+# filesrc ! jpegdec ! imagefreeze ! xvimagesink
+if __name__ == "__main__":
+    import sys
+    p = gst.Pipeline()
+
+    b = make_image_video_bin(sys.argv[1])
+    gnls = gst.element_factory_make("gnlsource")
+    gnls.add(b)
+
+    gnls.props.media_start = 5 * gst.SECOND
+    gnls.props.media_duration = 5 * gst.SECOND
+    gnls.props.duration = 5 * gst.SECOND
+
+    toverl = gst.element_factory_make("timeoverlay")
+    sink = gst.element_factory_make("xvimagesink")
+    sink.get_pad("sink").add_data_probe(dataprobe)
+
+    q = gst.element_factory_make("queue")
+
+    p.add(gnls, toverl, q, sink)
+
+    gst.element_link_many(q, toverl, sink)
+    #q.link(sink)
+
+    gnls.connect("pad-added", post_link, q)
+
+    ml = gobject.MainLoop()
+
+    p.set_state(gst.STATE_PLAYING)
+
+    ml.run()
+



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