qtdemux: Invent AAC codec_data if none is present
authorSebastian Dröge <sebastian@centricular.com>
Mon, 4 Jul 2016 14:55:32 +0000 (16:55 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 4 Jul 2016 14:55:32 +0000 (16:55 +0200)
Without, raw AAC can't be handled and we have some information available in
the decoder that most likely allows us to decode the stream in one way or
another. This is the same code already used by matroskademux for the same
reasons, and ffmpeg/vlc play such files just fine too by guesswork.

gst/isomp4/qtdemux.c

index 3e7fe80..be9b4e7 100644 (file)
@@ -12669,6 +12669,55 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
       if (data_ptr != NULL && data_len >= 2) {
         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
             data_ptr, data_len);
+      } else {
+        const gchar *profile_str = NULL;
+        GstBuffer *buffer;
+        GstMapInfo map;
+        guint8 *codec_data;
+        gint rate_idx, profile;
+
+        /* No codec_data, let's invent something.
+         * FIXME: This is wrong for SBR! */
+
+        GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
+
+        buffer = gst_buffer_new_and_alloc (2);
+        gst_buffer_map (buffer, &map, GST_MAP_WRITE);
+        codec_data = map.data;
+
+        rate_idx =
+            gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
+
+        switch (object_type_id) {
+          case 0x66:
+            profile_str = "main";
+            profile = 0;
+            break;
+          case 67:
+            profile_str = "lc";
+            profile = 1;
+            break;
+          case 68:
+            profile_str = "ssr";
+            profile = 2;
+            break;
+          default:
+            profile = 3;
+            break;
+        }
+
+        codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
+        codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
+
+        gst_buffer_unmap (buffer, &map);
+        gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
+            buffer, NULL);
+        gst_buffer_unref (buffer);
+
+        if (profile_str) {
+          gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
+              profile_str, NULL);
+        }
       }
       break;
     case 0x60:                 /* MPEG-2, various profiles */