commit 24d4deacf3b1587df6782696f51c9e12496041e5
Author: Jan Schmidt <thaytan@noraisin.net>
Date:   Wed Aug 11 06:06:16 2010 +1000

    mpegaudioparse: Implement half-baked reverse play support

diff --git a/gst/mpegaudioparse/gstmpegaudioparse.c b/gst/mpegaudioparse/gstmpegaudioparse.c
index aed15d6..0ba205a 100644
--- a/gst/mpegaudioparse/gstmpegaudioparse.c
+++ b/gst/mpegaudioparse/gstmpegaudioparse.c
@@ -482,6 +482,13 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event)
       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
           &format, &start, &stop, &pos);
 
+      GST_DEBUG_OBJECT (mp3parse,
+          "received NEWSEGMENT update %d, rate %lf, applied rate %lf, "
+          "format %d, "
+          "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+          G_GINT64_FORMAT, update, rate, applied_rate,
+          format, start, stop, pos);
+
       g_mutex_lock (mp3parse->pending_seeks_lock);
       if (format == GST_FORMAT_BYTES && mp3parse->pending_accurate_seeks) {
 
@@ -498,7 +505,7 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event)
 
           event =
               gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
-              GST_FORMAT_TIME, s->start, s->stop, s->last_stop);
+              GST_FORMAT_TIME, s->start, s->stop, s->start);
 
           mp3parse->segment = seek->segment;
 
@@ -862,7 +869,7 @@ gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size,
      * That is the reason of the calculated offset */
     GST_DEBUG_OBJECT (mp3parse,
         "Buffer after configured segment range %" GST_TIME_FORMAT " to %"
-        GST_TIME_FORMAT ", returning GST_FLOW_UNEXPECTED, timestamp %"
+        GST_TIME_FORMAT ", dropping, timestamp %"
         GST_TIME_FORMAT " duration %" GST_TIME_FORMAT ", offset 0x%08"
         G_GINT64_MODIFIER "x", GST_TIME_ARGS (push_start),
         GST_TIME_ARGS (mp3parse->segment.stop),
@@ -871,7 +878,7 @@ gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size,
         GST_BUFFER_OFFSET (outbuf));
 
     gst_buffer_unref (outbuf);
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_OK;
   } else {
     GST_DEBUG_OBJECT (mp3parse,
         "pushing buffer of %d bytes, timestamp %" GST_TIME_FORMAT
@@ -1412,7 +1419,7 @@ gst_mp3parse_handle_data (GstMPEGAudioParse * mp3parse, gboolean at_eos)
         mp3parse->sync_offset = mp3parse->tracked_offset;
       mp3parse->resyncing = TRUE;
       gst_mp3parse_flush_bytes (mp3parse, 1);
-      GST_DEBUG_OBJECT (mp3parse, "wrong header, skipping byte");
+      GST_LOG_OBJECT (mp3parse, "wrong header, skipping byte");
       continue;
     }
 
@@ -1555,11 +1562,30 @@ gst_mp3parse_chain (GstPad * pad, GstBuffer * buf)
 
   mp3parse = GST_MP3PARSE (GST_PAD_PARENT (pad));
 
-  GST_LOG_OBJECT (mp3parse, "buffer of %d bytes", GST_BUFFER_SIZE (buf));
+  GST_LOG_OBJECT (mp3parse,
+      "input buffer of %d bytes, timestamp %" GST_TIME_FORMAT
+      ", offset %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_OFFSET (buf));
 
   timestamp = GST_BUFFER_TIMESTAMP (buf);
 
-  mp3parse->discont |= GST_BUFFER_IS_DISCONT (buf);
+  if (GST_BUFFER_IS_DISCONT (buf)) {
+    GST_DEBUG_OBJECT (mp3parse, "Input buffer is discont");
+    mp3parse->discont = TRUE;
+
+    /* Clear leftover data */
+    mp3parse->skip = 0;
+    mp3parse->resyncing = TRUE;
+    mp3parse->next_ts = GST_CLOCK_TIME_NONE;
+    mp3parse->cur_offset = -1;
+
+    mp3parse->sync_offset = 0;
+    mp3parse->tracked_offset = 0;
+    mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
+    mp3parse->pending_offset = -1;
+
+    gst_adapter_clear (mp3parse->adapter);
+  }
 
   /* If we don't yet have a next timestamp, save it and the incoming offset
    * so we can apply it to the right outgoing buffer */
@@ -1595,10 +1621,10 @@ gst_mp3parse_chain (GstPad * pad, GstBuffer * buf)
 static gboolean
 head_check (GstMPEGAudioParse * mp3parse, unsigned long head)
 {
-  GST_DEBUG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
+  GST_LOG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
   /* if it's not a valid sync */
   if ((head & 0xffe00000) != 0xffe00000) {
-    GST_WARNING_OBJECT (mp3parse, "invalid sync");
+    GST_LOG_OBJECT (mp3parse, "invalid sync");
     return FALSE;
   }
   /* if it's an invalid MPEG version */
@@ -1916,23 +1942,25 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event)
   gint64 byte_cur, byte_stop;
   MPEGAudioPendingAccurateSeek *seek;
   GstClockTime start;
+  gboolean ret;
 
   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
       &stop_type, &stop);
 
-  GST_DEBUG_OBJECT (mp3parse, "Performing seek to %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (cur));
+  GST_DEBUG_OBJECT (mp3parse, "Received seek request rate %lf "
+      "format %d, flags 0x%x type %d val %" G_GINT64_FORMAT " -- type %d val %"
+      G_GINT64_FORMAT, rate, format, flags, cur_type, cur, stop_type, stop);
 
   /* For any format other than TIME, see if upstream handles
    * it directly or fail. For TIME, try upstream, but do it ourselves if
    * it fails upstream */
+  gst_event_ref (event);
+  ret = gst_pad_push_event (mp3parse->sinkpad, event);
+  if (ret)
+    return TRUE;                /* Caller unrefs the event */
   if (format != GST_FORMAT_TIME) {
-    gst_event_ref (event);
-    return gst_pad_push_event (mp3parse->sinkpad, event);
-  } else {
-    gst_event_ref (event);
-    if (gst_pad_push_event (mp3parse->sinkpad, event))
-      return TRUE;
+    /* Can only handle TIME seeks below here */
+    return FALSE;
   }
 
   seek = g_new0 (MPEGAudioPendingAccurateSeek, 1);
@@ -1942,6 +1970,10 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event)
   gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME,
       flags, cur_type, cur, stop_type, stop, NULL);
 
+  GST_DEBUG_OBJECT (mp3parse, "Performing seek to time %" GST_TIME_FORMAT
+      " -- %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (seek->segment.start), GST_TIME_ARGS (seek->segment.stop));
+
   /* Handle TIME based seeks by converting to a BYTE position */
 
   /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames
@@ -2008,18 +2040,18 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event)
     mp3parse->pending_accurate_seeks =
         g_slist_prepend (mp3parse->pending_accurate_seeks, seek);
     g_mutex_unlock (mp3parse->pending_seeks_lock);
-    if (gst_pad_push_event (mp3parse->sinkpad, event)) {
-      mp3parse->exact_position = TRUE;
-      return TRUE;
-    } else {
-      mp3parse->exact_position = TRUE;
+
+    ret = gst_pad_push_event (mp3parse->sinkpad, event);
+    mp3parse->exact_position = TRUE;
+    if (!ret) {
+      /* Upstream seek failed. Remove it from the list */
       g_mutex_lock (mp3parse->pending_seeks_lock);
       mp3parse->pending_accurate_seeks =
           g_slist_remove (mp3parse->pending_accurate_seeks, seek);
       g_mutex_unlock (mp3parse->pending_seeks_lock);
       g_free (seek);
-      return FALSE;
     }
+    return ret;
   }
 
   mp3parse->exact_position = FALSE;
@@ -2110,6 +2142,8 @@ mp3parse_src_query (GstPad * pad, GstQuery * query)
       } else if (format == GST_FORMAT_TIME) {
         if (mp3parse->next_ts == GST_CLOCK_TIME_NONE)
           goto out;
+        GST_LOG_OBJECT (mp3parse, "Query: position %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (mp3parse->next_ts));
         gst_query_set_position (query, GST_FORMAT_TIME, mp3parse->next_ts);
         res = TRUE;
       }
