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>
* 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;
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:

View file

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