wtay gst-plugins-base: gst-plugins-base/ gst-plugins-base/ext/theora/

[email protected]
Newsgroups gmane.comp.video.gstreamer.cvs
Message-ID <[email protected]>
CVS Root:       /cvs/gstreamer
Module:         gst-plugins-base
Changes by:     wtay
Date:           Tue Nov 25 2008  15:14:44 UTC

Log message:
* ext/theora/gsttheoraenc.h:
* ext/theora/theoraenc.c: (gst_theora_enc_init),
(theora_buffer_from_packet), (theora_push_packet),
(theora_enc_sink_event), (theora_enc_is_discontinuous),
(theora_enc_chain):
Parse segment events.
Pass incomming buffer timestamps to outgoing buffers.
Use the running_time to construct the granulepos.
Fixes #562163.

Modified files:
    .               : ChangeLog
    ext/theora      : gsttheoraenc.h theoraenc.c

Links:
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ChangeLog.diff?r1=1.4215&r2=1.4216
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ext/theora/gsttheoraenc.h.diff?r1=1.7&r2=1.8
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ext/theora/theoraenc.c.diff?r1=1.67&r2=1.68

====Begin Diffs====
Index: ChangeLog
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ChangeLog,v
retrieving revision 1.4215
retrieving revision 1.4216
diff -u -d -r1.4215 -r1.4216
--- ChangeLog	25 Nov 2008 11:00:54 -0000	1.4215
+++ ChangeLog	25 Nov 2008 15:14:25 -0000	1.4216
@@ -1,5 +1,17 @@
 2008-11-25  Wim Taymans  <[email protected]>
 
+	* ext/theora/gsttheoraenc.h:
+	* ext/theora/theoraenc.c: (gst_theora_enc_init),
+	(theora_buffer_from_packet), (theora_push_packet),
+	(theora_enc_sink_event), (theora_enc_is_discontinuous),
+	(theora_enc_chain):
+	Parse segment events.
+	Pass incomming buffer timestamps to outgoing buffers.
+	Use the running_time to construct the granulepos.
+	Fixes #562163.
+
+2008-11-25  Wim Taymans  <[email protected]>
 	* gst/playback/gstplaybin2.c: (activate_group):
 	Fix buffer-duration property.
Index: gsttheoraenc.h
RCS file: /cvs/gstreamer/gst-plugins-base/ext/theora/gsttheoraenc.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- gsttheoraenc.h	19 Apr 2007 16:58:53 -0000	1.7
+++ gsttheoraenc.h	25 Nov 2008 15:14:30 -0000	1.8
@@ -67,6 +67,8 @@
   GstPad *sinkpad;
   GstPad *srcpad;
+  GstSegment segment;
   ogg_stream_state to;
   theora_state state;
Index: theoraenc.c
RCS file: /cvs/gstreamer/gst-plugins-base/ext/theora/theoraenc.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- theoraenc.c	13 Aug 2008 00:59:07 -0000	1.67
+++ theoraenc.c	25 Nov 2008 15:14:30 -0000	1.68
@@ -286,6 +286,8 @@
       gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
+  gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
   enc->center = THEORA_DEF_CENTER;
   enc->border = THEORA_DEF_BORDER;
@@ -430,7 +432,8 @@
 /* prepare a buffer for transmission by passing data through libtheora */
 static GstFlowReturn
 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
-    GstClockTime timestamp, GstClockTime duration, GstBuffer ** buffer)
+    GstClockTime timestamp, GstClockTime running_time,
+    GstClockTime duration, GstBuffer ** buffer)
 {
   GstBuffer *buf;
   GstFlowReturn ret = GST_FLOW_OK;
@@ -452,7 +455,7 @@
   GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
       GST_BUFFER_OFFSET_END (buf));
-  GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset;
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
   GST_BUFFER_DURATION (buf) = duration;
   if (enc->next_discont) {
@@ -489,12 +492,14 @@
 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
-    GstClockTime timestamp, GstClockTime duration)
+    GstClockTime timestamp, GstClockTime running_time, GstClockTime duration)
   GstFlowReturn ret;
-  ret = theora_buffer_from_packet (enc, packet, timestamp, duration, &buf);
+  ret =
+      theora_buffer_from_packet (enc, packet, timestamp, running_time, duration,
+      &buf);
   if (ret == GST_FLOW_OK)
     ret = theora_push_buffer (enc, buf);
@@ -581,19 +586,40 @@
   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+    {
+      gboolean update;
+      gdouble rate, applied_rate;
+      GstFormat format;
+      gint64 start, stop, time;
+      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
+          &format, &start, &stop, &time);
+      gst_segment_set_newsegment_full (&enc->segment, update, rate,
+          applied_rate, format, start, stop, time);
+      res = gst_pad_push_event (enc->srcpad, event);
+      break;
+    }
     case GST_EVENT_EOS:
       if (enc->initialised) {
-        /* push last packet with eos flag */
+        /* push last packet with eos flag, should not be called */
         while (theora_encode_packetout (&enc->state, 1, &op)) {
           GstClockTime next_time =
               theora_enc_get_ogg_packet_end_time (enc, &op);
-          theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
+          theora_push_packet (enc, &op, GST_CLOCK_TIME_NONE, enc->next_ts,
+              next_time - enc->next_ts);
           enc->next_ts = next_time;
         }
       }
       res = gst_pad_push_event (enc->srcpad, event);
       break;
+    case GST_EVENT_FLUSH_STOP:
+      gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
     case GST_EVENT_CUSTOM_DOWNSTREAM:
     {
       const GstStructure *s;
@@ -624,9 +650,9 @@
 }
 static gboolean
-theora_enc_is_discontinuous (GstTheoraEnc * enc, GstBuffer * buffer)
+theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
+    GstClockTime duration)
-  GstClockTime ts = GST_BUFFER_TIMESTAMP (buffer);
   GstClockTimeDiff max_diff;
   gboolean ret = FALSE;
@@ -634,18 +660,19 @@
   max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
       (enc->info.fps_numerator * 4);
-  if (ts != GST_CLOCK_TIME_NONE && enc->expected_ts != GST_CLOCK_TIME_NONE) {
-    if ((GstClockTimeDiff) (ts - enc->expected_ts) > max_diff) {
+  if (timestamp != GST_CLOCK_TIME_NONE
+      && enc->expected_ts != GST_CLOCK_TIME_NONE) {
+    if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) {
       GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
           " exceeds expected value %" GST_TIME_FORMAT
           " by too much, marking discontinuity",
-          GST_TIME_ARGS (ts), GST_TIME_ARGS (enc->expected_ts));
+          GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts));
       ret = TRUE;
     }
   }
-  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
-    enc->expected_ts = ts + GST_BUFFER_DURATION (buffer);
+  if (GST_CLOCK_TIME_IS_VALID (duration))
+    enc->expected_ts = timestamp + duration;
   else
     enc->expected_ts = GST_CLOCK_TIME_NONE;
@@ -657,12 +684,28 @@
   GstTheoraEnc *enc;
   ogg_packet op;
-  GstClockTime in_time;
+  GstClockTime timestamp, duration, running_time;
-  in_time = GST_BUFFER_TIMESTAMP (buffer);
+  /* we keep track of two timelines.
+   * - The timestamps from the incomming buffers, which we copy to the outgoing
+   *   encoded buffers as-is. We need to do this as we simply forward the
+   *   newsegment events.
+   * - The running_time of the buffers, which we use to construct the granulepos
+   *   in the packets.
+   */
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  duration = GST_BUFFER_DURATION (buffer);
+  running_time =
+      gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp);
+  /* make sure we copy the discont flag to the next outgoing buffer when it's
+   * set on the incomming buffer */
+  if (GST_BUFFER_IS_DISCONT (buffer)) {
+    enc->next_discont = TRUE;
+  }
   if (enc->packetno == 0) {
     /* no packets written yet, setup headers */
@@ -684,8 +727,9 @@
     if (theora_encode_header (&enc->state, &op) != 0)
       goto encoder_disabled;
-    ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
-        GST_CLOCK_TIME_NONE, &buf1);
+    ret =
+        theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
+        GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf1);
     if (ret != GST_FLOW_OK) {
       goto header_buffer_alloc;
@@ -697,8 +741,9 @@
     if (theora_encode_comment (&enc->comment, &op) != 0)
-        GST_CLOCK_TIME_NONE, &buf2);
+        GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf2);
     /* Theora expects us to put this packet buffer into an ogg page,
      * in which case it becomes the ogg library's responsibility to
      * free it. Since we're copying and outputting a gst_buffer,
@@ -714,8 +759,9 @@
     if (theora_encode_tables (&enc->state, &op) != 0)
-        GST_CLOCK_TIME_NONE, &buf3);
+        GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf3);
       gst_buffer_unref (buf1);
       gst_buffer_unref (buf2);
@@ -749,8 +795,9 @@
     enc->granulepos_offset =
-        gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
-    enc->timestamp_offset = in_time;
+        gst_util_uint64_scale (running_time, enc->fps_n,
+        GST_SECOND * enc->fps_d);
+    enc->timestamp_offset = running_time;
     enc->next_ts = 0;
@@ -903,11 +950,12 @@
       buffer = newbuf;
-    if (theora_enc_is_discontinuous (enc, buffer)) {
+    if (theora_enc_is_discontinuous (enc, running_time, duration)) {
       theora_enc_reset (enc);
       enc->granulepos_offset =
-          gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
-      enc->timestamp_offset = in_time;
+          gst_util_uint64_scale (running_time, enc->fps_n,
+          GST_SECOND * enc->fps_d);
+      enc->timestamp_offset = running_time;
       enc->next_ts = 0;
       enc->next_discont = TRUE;
@@ -916,10 +964,14 @@
     ret = GST_FLOW_OK;
     while (theora_encode_packetout (&enc->state, 0, &op)) {
-      GstClockTime next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
+      GstClockTime next_time;
+      next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
       ret =
+          theora_push_packet (enc, &op, timestamp, enc->next_ts,
+          next_time - enc->next_ts);
       enc->next_ts = next_time;
       if (ret != GST_FLOW_OK)
         goto data_push;

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.