ext/amrnb/amrnbparse.*: Fix the duration query. Fixes #536226.
authorBenoit Fouet <benoit.fouet@purplelabs.com>
Fri, 26 Sep 2008 09:57:02 +0000 (09:57 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 26 Sep 2008 09:57:02 +0000 (09:57 +0000)
Original commit message from CVS:
Patch by: Benoit Fouet <benoit dot fouet at purplelabs dot com>
* ext/amrnb/amrnbparse.c: (gst_amrnbparse_query),
(gst_amrnbparse_chain), (gst_amrnbparse_loop),
(gst_amrnbparse_state_change):
* ext/amrnb/amrnbparse.h:
Fix the duration query. Fixes #536226.
Also set caps on the pads and buffers more correctly.

ChangeLog
common
ext/amrnb/amrnbparse.c
ext/amrnb/amrnbparse.h

index 971ff00..4271f79 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-09-26  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       Patch by: Benoit Fouet <benoit dot fouet at purplelabs dot com>
+
+       * ext/amrnb/amrnbparse.c: (gst_amrnbparse_query),
+       (gst_amrnbparse_chain), (gst_amrnbparse_loop),
+       (gst_amrnbparse_state_change):
+       * ext/amrnb/amrnbparse.h:
+       Fix the duration query. Fixes #536226.
+       Also set caps on the pads and buffers more correctly.
+
 2008-09-02  Tim-Philipp Müller  <tim.muller at collabora co uk>
 
        * po/LINGUAS:
diff --git a/common b/common
index 8d49485..1ff63d8 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 8d494854a6018336a80ece82ceb3df0033e2da9c
+Subproject commit 1ff63d8f92c36bf207434436f4ce75f2a4ea11a4
index 8de80f5..8833ab2 100644 (file)
@@ -216,22 +216,23 @@ gst_amrnbparse_query (GstPad * pad, GstQuery * query)
         return FALSE;
 
       tot = -1;
+      res = FALSE;
 
       peer = gst_pad_get_peer (amrnbparse->sinkpad);
       if (peer) {
         GstFormat pformat;
-        gint64 pcur, ptot;
+        gint64 ptot;
 
         pformat = GST_FORMAT_BYTES;
-        res = gst_pad_query_position (peer, &pformat, &pcur);
-        res &= gst_pad_query_duration (peer, &pformat, &ptot);
-        gst_object_unref (GST_OBJECT (peer));
-        if (res) {
-          tot = amrnbparse->ts * ((gdouble) ptot / pcur);
+        res = gst_pad_query_duration (peer, &pformat, &ptot);
+        if (res && amrnbparse->block) {
+          tot =
+              gst_util_uint64_scale_int (ptot, 20 * GST_MSECOND,
+              amrnbparse->block);
         }
+        gst_object_unref (GST_OBJECT (peer));
       }
       gst_query_set_duration (query, GST_FORMAT_TIME, tot);
-      res = TRUE;
       break;
     }
     default:
@@ -290,7 +291,7 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
 {
   GstAmrnbParse *amrnbparse;
   GstFlowReturn res;
-  gint block, mode;
+  gint mode;
   const guint8 *data;
   GstBuffer *out;
   GstClockTime timestamp;
@@ -311,6 +312,7 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
   /* init */
   if (amrnbparse->need_header) {
     GstEvent *segev;
+    GstCaps *caps;
 
     if (gst_adapter_available (amrnbparse->adapter) < 6)
       goto done;
@@ -323,6 +325,11 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
 
     amrnbparse->need_header = FALSE;
 
+    caps = gst_caps_new_simple ("audio/AMR",
+        "rate", G_TYPE_INT, 8000, "channels", G_TYPE_INT, 1, NULL);
+    gst_pad_set_caps (amrnbparse->srcpad, caps);
+    gst_caps_unref (caps);
+
     GST_DEBUG_OBJECT (amrnbparse, "Sending first segment");
     segev = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
         GST_FORMAT_TIME, 0, -1, 0);
@@ -337,15 +344,15 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
 
     /* get size */
     mode = (data[0] >> 3) & 0x0F;
-    block = block_size[mode] + 1;       /* add one for the mode */
+    amrnbparse->block = block_size[mode] + 1;   /* add one for the mode */
 
-    if (gst_adapter_available (amrnbparse->adapter) < block)
+    if (gst_adapter_available (amrnbparse->adapter) < amrnbparse->block)
       break;
 
-    out = gst_buffer_new_and_alloc (block);
+    out = gst_buffer_new_and_alloc (amrnbparse->block);
 
-    data = gst_adapter_peek (amrnbparse->adapter, block);
-    memcpy (GST_BUFFER_DATA (out), data, block);
+    data = gst_adapter_peek (amrnbparse->adapter, amrnbparse->block);
+    memcpy (GST_BUFFER_DATA (out), data, amrnbparse->block);
 
     /* timestamp, all constants that won't overflow */
     GST_BUFFER_DURATION (out) = GST_SECOND * 160 / 8000;
@@ -353,13 +360,13 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
     if (GST_CLOCK_TIME_IS_VALID (amrnbparse->ts))
       amrnbparse->ts += GST_BUFFER_DURATION (out);
 
-    gst_buffer_set_caps (out,
-        (GstCaps *) gst_pad_get_pad_template_caps (amrnbparse->srcpad));
+    gst_buffer_set_caps (out, GST_PAD_CAPS (amrnbparse->srcpad));
 
-    GST_DEBUG_OBJECT (amrnbparse, "Pushing %d bytes of data", block);
+    GST_DEBUG_OBJECT (amrnbparse, "Pushing %d bytes of data",
+        amrnbparse->block);
     res = gst_pad_push (amrnbparse->srcpad, out);
 
-    gst_adapter_flush (amrnbparse->adapter, block);
+    gst_adapter_flush (amrnbparse->adapter, amrnbparse->block);
   }
 done:
 
@@ -412,19 +419,26 @@ gst_amrnbparse_loop (GstPad * pad)
   GstBuffer *buffer;
   guint8 *data;
   gint size;
-  gint block, mode;
+  gint mode;
   GstFlowReturn ret;
 
   amrnbparse = GST_AMRNBPARSE (GST_PAD_PARENT (pad));
 
   /* init */
   if (G_UNLIKELY (amrnbparse->need_header)) {
+    GstCaps *caps;
+
     if (!gst_amrnbparse_pull_header (amrnbparse)) {
       GST_ELEMENT_ERROR (amrnbparse, STREAM, WRONG_TYPE, (NULL), (NULL));
       GST_LOG_OBJECT (amrnbparse, "could not read header");
       goto need_pause;
     }
 
+    caps = gst_caps_new_simple ("audio/AMR",
+        "rate", G_TYPE_INT, 8000, "channels", G_TYPE_INT, 1, NULL);
+    gst_pad_set_caps (amrnbparse->srcpad, caps);
+    gst_caps_unref (caps);
+
     GST_DEBUG_OBJECT (amrnbparse, "Sending newsegment event");
     gst_pad_push_event (amrnbparse->srcpad,
         gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
@@ -452,36 +466,35 @@ gst_amrnbparse_loop (GstPad * pad)
 
   /* get size */
   mode = (data[0] >> 3) & 0x0F;
-  block = block_size[mode] + 1; /* add one for the mode */
+  amrnbparse->block = block_size[mode] + 1;     /* add one for the mode */
 
   gst_buffer_unref (buffer);
 
   ret =
-      gst_pad_pull_range (amrnbparse->sinkpad, amrnbparse->offset, block,
-      &buffer);
+      gst_pad_pull_range (amrnbparse->sinkpad, amrnbparse->offset,
+      amrnbparse->block, &buffer);
 
   if (ret == GST_FLOW_UNEXPECTED)
     goto eos;
   else if (ret != GST_FLOW_OK)
     goto need_pause;
 
-  if (GST_BUFFER_SIZE (buffer) < block) {
+  if (GST_BUFFER_SIZE (buffer) < amrnbparse->block) {
     gst_buffer_unref (buffer);
     goto eos;
   }
 
-  amrnbparse->offset += block;
+  amrnbparse->offset += amrnbparse->block;
 
   /* output */
   buffer = gst_buffer_make_metadata_writable (buffer);
   GST_BUFFER_DURATION (buffer) = GST_SECOND * 160 / 8000;
   GST_BUFFER_TIMESTAMP (buffer) = amrnbparse->ts;
 
-  gst_buffer_set_caps (buffer,
-      (GstCaps *) gst_pad_get_pad_template_caps (amrnbparse->srcpad));
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (amrnbparse->srcpad));
 
   GST_DEBUG_OBJECT (amrnbparse, "Pushing %2d bytes, ts=%" GST_TIME_FORMAT,
-      block, GST_TIME_ARGS (amrnbparse->ts));
+      amrnbparse->block, GST_TIME_ARGS (amrnbparse->ts));
 
   ret = gst_pad_push (amrnbparse->srcpad, buffer);
 
@@ -576,6 +589,7 @@ gst_amrnbparse_state_change (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       amrnbparse->need_header = TRUE;
       amrnbparse->ts = -1;
+      amrnbparse->block = 0;
       gst_segment_init (&amrnbparse->segment, GST_FORMAT_TIME);
       break;
     default:
index 9b609a4..5c5e754 100644 (file)
@@ -50,6 +50,7 @@ struct _GstAmrnbParse {
   gboolean seekable;
   gboolean need_header;
   gint64 offset;
+  gint block;
 
   guint64 ts;