ext/faad/gstfaad.*: Allow playback of raw (unframed) MPEG AAC files (#148993).

Original commit message from CVS:
Reviewed by: Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
* ext/faad/gstfaad.c: (gst_faad_init), (gst_faad_sinkconnect),
(gst_faad_chain), (gst_faad_change_state):
* ext/faad/gstfaad.h:
Allow playback of raw (unframed) MPEG AAC files (#148993).
This commit is contained in:
Ronald S. Bultje 2004-10-01 13:00:41 +00:00
parent 060ae9b59b
commit cebbba83a9
3 changed files with 93 additions and 34 deletions

View file

@ -1,3 +1,12 @@
2004-10-01 Sebastien Cote <sc5@hermes.usherb.ca>
Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/faad/gstfaad.c: (gst_faad_init), (gst_faad_sinkconnect),
(gst_faad_chain), (gst_faad_change_state):
* ext/faad/gstfaad.h:
Allow playback of raw (unframed) MPEG AAC files (#148993).
2004-10-01 Sebastien Cote <sc5@hermes.usherb.ca> 2004-10-01 Sebastien Cote <sc5@hermes.usherb.ca>
Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net> Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net>

View file

@ -124,6 +124,7 @@ gst_faad_init (GstFaad * faad)
faad->handle = NULL; faad->handle = NULL;
faad->samplerate = -1; faad->samplerate = -1;
faad->channels = -1; faad->channels = -1;
faad->tempbuf = NULL;
GST_FLAG_SET (faad, GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (faad, GST_ELEMENT_EVENT_AWARE);
@ -152,7 +153,6 @@ gst_faad_sinkconnect (GstPad * pad, const GstCaps * caps)
GstBuffer *buf; GstBuffer *buf;
if ((value = gst_structure_get_value (str, "codec_data"))) { if ((value = gst_structure_get_value (str, "codec_data"))) {
GstPadLinkReturn ret;
gulong samplerate; gulong samplerate;
guchar channels; guchar channels;
@ -165,11 +165,12 @@ gst_faad_sinkconnect (GstPad * pad, const GstCaps * caps)
faad->samplerate = samplerate; faad->samplerate = samplerate;
faad->channels = channels; faad->channels = channels;
ret = gst_pad_renegotiate (faad->srcpad); if (faad->tempbuf) {
if (ret == GST_PAD_LINK_DELAYED) gst_buffer_unref (faad->tempbuf);
ret = GST_PAD_LINK_OK; faad->tempbuf = NULL;
}
return ret; return GST_PAD_LINK_OK;
} }
/* if there's no decoderspecificdata, it's all fine. We cannot know /* if there's no decoderspecificdata, it's all fine. We cannot know
@ -326,6 +327,8 @@ gst_faad_srcconnect (GstPad * pad, const GstCaps * caps)
static void static void
gst_faad_chain (GstPad * pad, GstData * data) gst_faad_chain (GstPad * pad, GstData * data)
{ {
guint input_size;
guchar *input_data;
GstFaad *faad = GST_FAAD (gst_pad_get_parent (pad)); GstFaad *faad = GST_FAAD (gst_pad_get_parent (pad));
GstBuffer *buf, *outbuf; GstBuffer *buf, *outbuf;
faacDecFrameInfo info; faacDecFrameInfo info;
@ -336,6 +339,20 @@ gst_faad_chain (GstPad * pad, GstData * data)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS: case GST_EVENT_EOS:
if (faad->tempbuf != NULL) {
/* Try to decode the remaining data */
out = faacDecDecode (faad->handle, &info,
GST_BUFFER_DATA (faad->tempbuf), GST_BUFFER_SIZE (faad->tempbuf));
gst_buffer_unref (faad->tempbuf);
faad->tempbuf = NULL;
if (out && !info.error && info.samples > 0) {
outbuf = gst_buffer_new_and_alloc (info.samples * faad->bps);
/* ugh */
memcpy (GST_BUFFER_DATA (outbuf), out, GST_BUFFER_SIZE (outbuf));
gst_pad_push (faad->srcpad, GST_DATA (outbuf));
}
}
gst_element_set_eos (GST_ELEMENT (faad)); gst_element_set_eos (GST_ELEMENT (faad));
gst_pad_push (faad->srcpad, data); gst_pad_push (faad->srcpad, data);
return; return;
@ -356,6 +373,7 @@ gst_faad_chain (GstPad * pad, GstData * data)
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), &samplerate, &channels); GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), &samplerate, &channels);
faad->samplerate = samplerate; faad->samplerate = samplerate;
faad->channels = channels; faad->channels = channels;
ret = gst_pad_renegotiate (faad->srcpad); ret = gst_pad_renegotiate (faad->srcpad);
if (GST_PAD_LINK_FAILED (ret)) { if (GST_PAD_LINK_FAILED (ret)) {
GST_ELEMENT_ERROR (faad, CORE, NEGOTIATION, (NULL), (NULL)); GST_ELEMENT_ERROR (faad, CORE, NEGOTIATION, (NULL), (NULL));
@ -364,42 +382,66 @@ gst_faad_chain (GstPad * pad, GstData * data)
} }
} }
out = faacDecDecode (faad->handle, &info, /* Use the leftovers */
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); if (faad->tempbuf) {
if (info.error) { buf = gst_buffer_join (faad->tempbuf, buf);
GST_ELEMENT_ERROR (faad, STREAM, DECODE, (NULL), faad->tempbuf = NULL;
("Failed to decode buffer: %s", faacDecGetErrorMessage (info.error)));
gst_buffer_unref (buf);
return;
} }
if (info.samplerate != faad->samplerate || info.channels != faad->channels) { input_data = GST_BUFFER_DATA (buf);
GstPadLinkReturn ret; input_size = GST_BUFFER_SIZE (buf);
info.bytesconsumed = input_size;
while (input_size > (faad->channels * FAAD_MIN_STREAMSIZE)
&& info.bytesconsumed > 0) {
out = faacDecDecode (faad->handle, &info, input_data, input_size);
if (info.error) {
GST_ELEMENT_ERROR (faad, STREAM, DECODE, (NULL),
("Failed to decode buffer: %s", faacDecGetErrorMessage (info.error)));
break;
}
faad->samplerate = info.samplerate; input_size -= info.bytesconsumed;
faad->channels = info.channels; input_data += info.bytesconsumed;
ret = gst_pad_renegotiate (faad->srcpad);
if (GST_PAD_LINK_FAILED (ret)) { if (out) {
GST_ELEMENT_ERROR (faad, CORE, NEGOTIATION, (NULL), (NULL));
gst_buffer_unref (buf); if (info.samplerate != faad->samplerate
return; || info.channels != faad->channels) {
GstPadLinkReturn ret;
faad->samplerate = info.samplerate;
faad->channels = info.channels;
ret = gst_pad_renegotiate (faad->srcpad);
if (GST_PAD_LINK_FAILED (ret)) {
GST_ELEMENT_ERROR (faad, CORE, NEGOTIATION, (NULL), (NULL));
break;
}
}
if (info.samples > 0) {
outbuf = gst_buffer_new_and_alloc (info.samples * faad->bps);
/* ugh */
memcpy (GST_BUFFER_DATA (outbuf), out, GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
gst_pad_push (faad->srcpad, GST_DATA (outbuf));
}
}
};
/* Keep the leftovers */
if (input_size > 0) {
if (input_size < GST_BUFFER_SIZE (buf))
faad->tempbuf = gst_buffer_create_sub (buf,
GST_BUFFER_SIZE (buf) - input_size, input_size);
else {
faad->tempbuf = buf;
gst_buffer_ref (buf);
} }
} }
if (info.samples == 0) {
gst_buffer_unref (buf);
return;
}
/* FIXME: did it handle the whole buffer? */
outbuf = gst_buffer_new_and_alloc (info.samples * faad->bps);
/* ugh */
memcpy (GST_BUFFER_DATA (outbuf), out, GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
gst_pad_push (faad->srcpad, GST_DATA (outbuf));
} }
static GstElementStateReturn static GstElementStateReturn
@ -416,6 +458,7 @@ gst_faad_change_state (GstElement * element)
conf = faacDecGetCurrentConfiguration (faad->handle); conf = faacDecGetCurrentConfiguration (faad->handle);
conf->defObjectType = LC; conf->defObjectType = LC;
conf->dontUpSampleImplicitSBR = 1;
faacDecSetConfiguration (faad->handle, conf); faacDecSetConfiguration (faad->handle, conf);
} }
break; break;
@ -426,6 +469,10 @@ gst_faad_change_state (GstElement * element)
case GST_STATE_READY_TO_NULL: case GST_STATE_READY_TO_NULL:
faacDecClose (faad->handle); faacDecClose (faad->handle);
faad->handle = NULL; faad->handle = NULL;
if (faad->tempbuf) {
gst_buffer_unref (faad->tempbuf);
faad->tempbuf = NULL;
}
break; break;
default: default:
break; break;

View file

@ -47,6 +47,9 @@ typedef struct _GstFaad {
channels, channels,
bps; bps;
/* used to keep input leftovers */
GstBuffer *tempbuf;
/* FAAD object */ /* FAAD object */
faacDecHandle handle; faacDecHandle handle;
} GstFaad; } GstFaad;