ext/faad/gstfaad.c: Fix #334748: use fake_codec_data if the first bytes of the first...
authorMichael Smith <msmith@xiph.org>
Wed, 3 May 2006 10:25:46 +0000 (10:25 +0000)
committerMichael Smith <msmith@xiph.org>
Wed, 3 May 2006 10:25:46 +0000 (10:25 +0000)
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.

ChangeLog
ext/faad/gstfaad.c

index 60e179badf78ea4a4eb4947edd2ca98eaa1e615f..50f546d2a704572448b02422a85b787ec2fca25c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * sys/v4l2/gstv4l2src.c: (gst_v4l2src_get_caps):
index 85009de8512cbe4c8219ac2fc4073ef0b10544e8..2c745d0eb7cc82c9c6e667b9f994b4f4e1597c33 100644 (file)
@@ -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;