summaryrefslogtreecommitdiffstats
path: root/gst/qtdemux
diff options
context:
space:
mode:
authorMichael Smith <msmith@songbirdnest.com>2009-04-21 14:02:01 -0700
committerMichael Smith <msmith@songbirdnest.com>2009-04-21 14:04:07 -0700
commit922c9f529a88f3be6d2459b0d0519c12dcc1a431 (patch)
treea431b0bb6551f0e19f35bba79bfcf91aaa0d2320 /gst/qtdemux
parent8d8e9af0a89cff894f7ee8e6fc8b83fe3f39562f (diff)
qtdemux: override caps based on data from ESDS atoms in mpeg4.
If the codec is actually something else (e.g. mjpeg) change the caps to match when parsing the ESDS atom. Also, for AAC, override rate and channels with correct values read from ESDS, since the rate/channels values elsewhere are often wrong.
Diffstat (limited to 'gst/qtdemux')
-rw-r--r--gst/qtdemux/qtdemux.c132
1 files changed, 104 insertions, 28 deletions
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index 6ff2157f..b2db4527 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -5052,6 +5052,8 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
guint8 *data_ptr = NULL;
int data_len = 0;
guint8 object_type_id = 0;
+ char *codec_name = NULL;
+ GstCaps *caps = NULL;
qtdemux_dump_mem (ptr, len);
ptr += 8;
@@ -5095,6 +5097,108 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
}
}
+ /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
+ * in use, and should also be used to override some other parameters for some
+ * codecs. */
+ switch (object_type_id) {
+ case 0x20: /* MPEG-4 */
+ break; /* Nothing special needed here */
+ case 0x21: /* H.264 */
+ codec_name = "H.264 / AVC";
+ caps = gst_caps_new_simple ("video/x-h264", NULL);
+ break;
+ case 0x40: /* AAC (any) */
+ case 0x66: /* AAC Main */
+ case 0x67: /* AAC LC */
+ case 0x68: /* AAC SSR */
+ /* Override channels and rate based on the codec_data, as it's often
+ * wrong. */
+ if (data_ptr && data_len >= 2) {
+ guint channels, rateindex;
+ int rates[] = { 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+ };
+
+ channels = (data_ptr[1] & 0x7f) >> 3;
+ if (channels <= 7) {
+ stream->n_channels = channels;
+ }
+
+ rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
+ if (rateindex < sizeof (rates) / sizeof (*rates)) {
+ stream->rate = rates[rateindex];
+ }
+ }
+ break;
+ case 0x60: /* MPEG-2, various profiles */
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ codec_name = "MPEG-2 video";
+
+ gst_caps_unref (stream->caps);
+ stream->caps = gst_caps_new_simple ("video/mpeg",
+ "mpegversion", G_TYPE_INT, 2,
+ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+ break;
+ case 0x69: /* MP3 has two different values, accept either */
+ case 0x6B:
+ /* change to mpeg1 layer 3 audio */
+ gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
+ "mpegversion", G_TYPE_INT, 1, NULL);
+ codec_name = "MPEG-1 layer 3";
+ break;
+ case 0x6A: /* MPEG-1 */
+ codec_name = "MPEG-1 video";
+
+ gst_caps_unref (stream->caps);
+ stream->caps = gst_caps_new_simple ("video/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+ break;
+ case 0x6C: /* MJPEG */
+ caps = gst_caps_new_simple ("image/jpeg", NULL);
+ codec_name = "Motion-JPEG";
+ break;
+ case 0x6D: /* PNG */
+ caps = gst_caps_new_simple ("image/png", NULL);
+ codec_name = "PNG still images";
+ break;
+ case 0x6E: /* JPEG2000 */
+ codec_name = "JPEG-2000";
+ caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
+ break;
+ case 0xA4: /* Dirac */
+ codec_name = "Dirac";
+ caps = gst_caps_new_simple ("video/x-dirac", NULL);
+ break;
+ case 0xA5: /* AC3 */
+ codec_name = "AC-3 audio";
+ caps = gst_caps_new_simple ("audio/x-ac3", NULL);
+ break;
+ case 0xE1: /* QCELP */
+ /* QCELP, the codec_data is a riff tag (little endian) with
+ * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
+ caps = gst_caps_new_simple ("audio/qcelp", NULL);
+ codec_name = "QCELP";
+ break;
+ default:
+ break;
+ }
+
+ /* If we have a replacement caps, then change our caps for this stream */
+ if (caps) {
+ gst_caps_unref (stream->caps);
+ stream->caps = caps;
+ }
+
+ if (codec_name && list)
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+ GST_TAG_AUDIO_CODEC, codec_name, NULL);
+
+ /* Add the codec_data attribute to caps, if we have it */
if (data_ptr) {
GstBuffer *buffer;
@@ -5108,35 +5212,7 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
buffer, NULL);
gst_buffer_unref (buffer);
}
- /* object_type_id in the stsd atom in mp4a tells us about AAC or plain
- * MPEG audio and other formats */
- switch (object_type_id) {
- case 107:
- /* change to mpeg1 layer 3 audio */
- gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
- "mpegversion", G_TYPE_INT, 1, NULL);
- if (list)
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- GST_TAG_AUDIO_CODEC, "MPEG-1 layer 3", NULL);
- break;
- case 0xE1:
- {
- GstStructure *structure;
-
- /* QCELP, the codec_data is a riff tag (little endian) with
- * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
- structure = gst_caps_get_structure (stream->caps, 0);
- gst_structure_set_name (structure, "audio/qcelp");
- gst_structure_remove_fields (structure, "mpegversion", "framed", NULL);
- if (list)
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- GST_TAG_AUDIO_CODEC, "QCELP", NULL);
- break;
- }
- default:
- break;
- }
}
#define _codec(name) \