ext/amrnb/amrnbparse.*: Fix the duration query. Fixes #536226.

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.
This commit is contained in:
Benoit Fouet 2008-09-26 09:57:02 +00:00 committed by Wim Taymans
parent 600ab94cc2
commit f0d2495012
4 changed files with 53 additions and 27 deletions

View file

@ -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> 2008-09-02 Tim-Philipp Müller <tim.muller at collabora co uk>
* po/LINGUAS: * po/LINGUAS:

2
common

@ -1 +1 @@
Subproject commit 8d494854a6018336a80ece82ceb3df0033e2da9c Subproject commit 1ff63d8f92c36bf207434436f4ce75f2a4ea11a4

View file

@ -216,22 +216,23 @@ gst_amrnbparse_query (GstPad * pad, GstQuery * query)
return FALSE; return FALSE;
tot = -1; tot = -1;
res = FALSE;
peer = gst_pad_get_peer (amrnbparse->sinkpad); peer = gst_pad_get_peer (amrnbparse->sinkpad);
if (peer) { if (peer) {
GstFormat pformat; GstFormat pformat;
gint64 pcur, ptot; gint64 ptot;
pformat = GST_FORMAT_BYTES; pformat = GST_FORMAT_BYTES;
res = gst_pad_query_position (peer, &pformat, &pcur); res = gst_pad_query_duration (peer, &pformat, &ptot);
res &= gst_pad_query_duration (peer, &pformat, &ptot); if (res && amrnbparse->block) {
gst_object_unref (GST_OBJECT (peer)); tot =
if (res) { gst_util_uint64_scale_int (ptot, 20 * GST_MSECOND,
tot = amrnbparse->ts * ((gdouble) ptot / pcur); amrnbparse->block);
} }
gst_object_unref (GST_OBJECT (peer));
} }
gst_query_set_duration (query, GST_FORMAT_TIME, tot); gst_query_set_duration (query, GST_FORMAT_TIME, tot);
res = TRUE;
break; break;
} }
default: default:
@ -290,7 +291,7 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
{ {
GstAmrnbParse *amrnbparse; GstAmrnbParse *amrnbparse;
GstFlowReturn res; GstFlowReturn res;
gint block, mode; gint mode;
const guint8 *data; const guint8 *data;
GstBuffer *out; GstBuffer *out;
GstClockTime timestamp; GstClockTime timestamp;
@ -311,6 +312,7 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
/* init */ /* init */
if (amrnbparse->need_header) { if (amrnbparse->need_header) {
GstEvent *segev; GstEvent *segev;
GstCaps *caps;
if (gst_adapter_available (amrnbparse->adapter) < 6) if (gst_adapter_available (amrnbparse->adapter) < 6)
goto done; goto done;
@ -323,6 +325,11 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
amrnbparse->need_header = FALSE; 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"); GST_DEBUG_OBJECT (amrnbparse, "Sending first segment");
segev = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, segev = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
GST_FORMAT_TIME, 0, -1, 0); GST_FORMAT_TIME, 0, -1, 0);
@ -337,15 +344,15 @@ gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer)
/* get size */ /* get size */
mode = (data[0] >> 3) & 0x0F; 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; break;
out = gst_buffer_new_and_alloc (block); out = gst_buffer_new_and_alloc (amrnbparse->block);
data = gst_adapter_peek (amrnbparse->adapter, block); data = gst_adapter_peek (amrnbparse->adapter, amrnbparse->block);
memcpy (GST_BUFFER_DATA (out), data, block); memcpy (GST_BUFFER_DATA (out), data, amrnbparse->block);
/* timestamp, all constants that won't overflow */ /* timestamp, all constants that won't overflow */
GST_BUFFER_DURATION (out) = GST_SECOND * 160 / 8000; 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)) if (GST_CLOCK_TIME_IS_VALID (amrnbparse->ts))
amrnbparse->ts += GST_BUFFER_DURATION (out); amrnbparse->ts += GST_BUFFER_DURATION (out);
gst_buffer_set_caps (out, gst_buffer_set_caps (out, GST_PAD_CAPS (amrnbparse->srcpad));
(GstCaps *) gst_pad_get_pad_template_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); res = gst_pad_push (amrnbparse->srcpad, out);
gst_adapter_flush (amrnbparse->adapter, block); gst_adapter_flush (amrnbparse->adapter, amrnbparse->block);
} }
done: done:
@ -412,19 +419,26 @@ gst_amrnbparse_loop (GstPad * pad)
GstBuffer *buffer; GstBuffer *buffer;
guint8 *data; guint8 *data;
gint size; gint size;
gint block, mode; gint mode;
GstFlowReturn ret; GstFlowReturn ret;
amrnbparse = GST_AMRNBPARSE (GST_PAD_PARENT (pad)); amrnbparse = GST_AMRNBPARSE (GST_PAD_PARENT (pad));
/* init */ /* init */
if (G_UNLIKELY (amrnbparse->need_header)) { if (G_UNLIKELY (amrnbparse->need_header)) {
GstCaps *caps;
if (!gst_amrnbparse_pull_header (amrnbparse)) { if (!gst_amrnbparse_pull_header (amrnbparse)) {
GST_ELEMENT_ERROR (amrnbparse, STREAM, WRONG_TYPE, (NULL), (NULL)); GST_ELEMENT_ERROR (amrnbparse, STREAM, WRONG_TYPE, (NULL), (NULL));
GST_LOG_OBJECT (amrnbparse, "could not read header"); GST_LOG_OBJECT (amrnbparse, "could not read header");
goto need_pause; 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_DEBUG_OBJECT (amrnbparse, "Sending newsegment event");
gst_pad_push_event (amrnbparse->srcpad, gst_pad_push_event (amrnbparse->srcpad,
gst_event_new_new_segment_full (FALSE, 1.0, 1.0, gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
@ -452,36 +466,35 @@ gst_amrnbparse_loop (GstPad * pad)
/* get size */ /* get size */
mode = (data[0] >> 3) & 0x0F; 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); gst_buffer_unref (buffer);
ret = ret =
gst_pad_pull_range (amrnbparse->sinkpad, amrnbparse->offset, block, gst_pad_pull_range (amrnbparse->sinkpad, amrnbparse->offset,
&buffer); amrnbparse->block, &buffer);
if (ret == GST_FLOW_UNEXPECTED) if (ret == GST_FLOW_UNEXPECTED)
goto eos; goto eos;
else if (ret != GST_FLOW_OK) else if (ret != GST_FLOW_OK)
goto need_pause; goto need_pause;
if (GST_BUFFER_SIZE (buffer) < block) { if (GST_BUFFER_SIZE (buffer) < amrnbparse->block) {
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
goto eos; goto eos;
} }
amrnbparse->offset += block; amrnbparse->offset += amrnbparse->block;
/* output */ /* output */
buffer = gst_buffer_make_metadata_writable (buffer); buffer = gst_buffer_make_metadata_writable (buffer);
GST_BUFFER_DURATION (buffer) = GST_SECOND * 160 / 8000; GST_BUFFER_DURATION (buffer) = GST_SECOND * 160 / 8000;
GST_BUFFER_TIMESTAMP (buffer) = amrnbparse->ts; GST_BUFFER_TIMESTAMP (buffer) = amrnbparse->ts;
gst_buffer_set_caps (buffer, gst_buffer_set_caps (buffer, GST_PAD_CAPS (amrnbparse->srcpad));
(GstCaps *) gst_pad_get_pad_template_caps (amrnbparse->srcpad));
GST_DEBUG_OBJECT (amrnbparse, "Pushing %2d bytes, ts=%" GST_TIME_FORMAT, 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); 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: case GST_STATE_CHANGE_READY_TO_PAUSED:
amrnbparse->need_header = TRUE; amrnbparse->need_header = TRUE;
amrnbparse->ts = -1; amrnbparse->ts = -1;
amrnbparse->block = 0;
gst_segment_init (&amrnbparse->segment, GST_FORMAT_TIME); gst_segment_init (&amrnbparse->segment, GST_FORMAT_TIME);
break; break;
default: default:

View file

@ -50,6 +50,7 @@ struct _GstAmrnbParse {
gboolean seekable; gboolean seekable;
gboolean need_header; gboolean need_header;
gint64 offset; gint64 offset;
gint block;
guint64 ts; guint64 ts;