From f910e0f4a58505251af8308fa33f646de8d7e5fe Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Wed, 3 May 2006 10:25:46 +0000 Subject: 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. --- ext/faad/gstfaad.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'ext/faad') diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c index 85009de8..2c745d0e 100644 --- a/ext/faad/gstfaad.c +++ b/ext/faad/gstfaad.c @@ -312,12 +312,14 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps) gst_structure_get_int (str, "channels", &channels)) { 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); faad->fake_codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1); 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; } +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 gst_faad_chain (GstPad * pad, GstBuffer * buffer) { @@ -1108,10 +1132,23 @@ gst_faad_chain (GstPad * pad, GstBuffer * buffer) guint8 ch; GST_DEBUG_OBJECT (faad, "initialising ..."); - 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); + /* We check if the first data looks like it might plausibly contain + * 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); + } 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; faad->init = TRUE; -- cgit v1.2.1