ext/faad/gstfaad.c: Fix #334748: use fake_codec_data if the first bytes of the first buffer we process doesn't look l...

Original commit message from CVS:
* ext/faad/gstfaad.c: (gst_faad_setcaps),
(looks_like_valid_header), (gst_faad_chain):
Fix #334748: use fake_codec_data if the first bytes of the first
buffer we process doesn't look like plausible AAC data (e.g.
reserved values for rate, or channels). Fixes playback of Apple's
movie trailers.
This commit is contained in:
Michael Smith 2006-05-03 10:25:46 +00:00
parent f2ff9c1617
commit f910e0f4a5
2 changed files with 51 additions and 5 deletions

View file

@ -1,3 +1,12 @@
2006-05-03 Michael Smith <msmith@fluendo.com>
* ext/faad/gstfaad.c: (gst_faad_setcaps),
(looks_like_valid_header), (gst_faad_chain):
Fix #334748: use fake_codec_data if the first bytes of the first
buffer we process doesn't look like plausible AAC data (e.g.
reserved values for rate, or channels). Fixes playback of Apple's
movie trailers.
2006-05-02 Edgard Lima <edgard.lima@indt.org.br> 2006-05-02 Edgard Lima <edgard.lima@indt.org.br>
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_get_caps): * sys/v4l2/gstv4l2src.c: (gst_v4l2src_get_caps):

View file

@ -312,12 +312,14 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps)
gst_structure_get_int (str, "channels", &channels)) { gst_structure_get_int (str, "channels", &channels)) {
gint rate_idx, profile; gint rate_idx, profile;
profile = 3; /* 0=MAIN, 1=LC, 2=SSR, 3=? */ profile = 3; /* 0=MAIN, 1=LC, 2=SSR, 3=LTP */
rate_idx = aac_rate_idx (rate); rate_idx = aac_rate_idx (rate);
faad->fake_codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1); faad->fake_codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
faad->fake_codec_data[1] = ((rate_idx & 0x1) << 7) | (channels << 3); faad->fake_codec_data[1] = ((rate_idx & 0x1) << 7) | (channels << 3);
GST_LOG_OBJECT (faad, "created fake codec data (%u,%u)", rate, channels); GST_LOG_OBJECT (faad, "created fake codec data (%u,%u): 0x%x 0x%x", rate,
channels, (int) faad->fake_codec_data[0],
(int) faad->fake_codec_data[1]);
} }
} }
@ -1052,6 +1054,28 @@ gst_faad_sync (GstBuffer * buf, guint * off)
return FALSE; return FALSE;
} }
static gboolean
looks_like_valid_header (guint8 * input_data, guint input_size)
{
guint32 rate;
guint32 channels;
if (input_size < 2)
return FALSE;
rate = ((input_data[0] & 0x7) << 1) | ((input_data[1] & 0x80) >> 7);
channels = (input_data[1] & 0x78) >> 3;
if (rate == 0xd || rate == 0xe) /* Reserved values */
return FALSE;
if (channels == 0) /* Extended specifier: never seen one of these */
return FALSE;
return TRUE;
}
static GstFlowReturn static GstFlowReturn
gst_faad_chain (GstPad * pad, GstBuffer * buffer) gst_faad_chain (GstPad * pad, GstBuffer * buffer)
{ {
@ -1108,10 +1132,23 @@ gst_faad_chain (GstPad * pad, GstBuffer * buffer)
guint8 ch; guint8 ch;
GST_DEBUG_OBJECT (faad, "initialising ..."); GST_DEBUG_OBJECT (faad, "initialising ...");
if (faacDecInit (faad->handle, input_data, input_size, &rate, &ch) < 0) /* We check if the first data looks like it might plausibly contain
goto init_failed; * appropriate initialisation info... if not, we use our fake_codec_data
*/
if (looks_like_valid_header (input_data, input_size) || !faad->packetised) {
if (faacDecInit (faad->handle, input_data, input_size, &rate, &ch) < 0)
goto init_failed;
GST_DEBUG_OBJECT (faad, "faacDecInit() ok: rate=%u,channels=%u", rate, ch); GST_DEBUG_OBJECT (faad, "faacDecInit() ok: rate=%u,channels=%u", rate,
ch);
} else {
if ((gint8) faacDecInit2 (faad->handle, faad->fake_codec_data, 2,
&rate, &ch) < 0) {
goto init2_failed;
}
GST_DEBUG_OBJECT (faad, "faacDecInit2() ok: rate=%u,channels=%u", rate,
ch);
}
skip_bytes = 0; skip_bytes = 0;
faad->init = TRUE; faad->init = TRUE;