summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiagoss@osg.samsung.com>2016-04-05 14:34:00 -0300
committerThiago Santos <thiago@waltznetworks.com>2017-04-11 14:13:56 -0700
commit54e252e0955287bf6971fba89666e9fa4901e118 (patch)
tree451b0165ec99a07ac38e8fac3e5ba738c40fd1cb
parentbd32bcc36cc7b08a0aecbad3bcc5dbd7308b9e19 (diff)
qtdemux: rework stsd sample entries access
Instead of using the stsd as a base pointer, use the actual stsd entry as the stsd can have multiple entries. This is rarely used for file playback but is a possible profile with in DVB DASH specs. This still doesn't support stsd with multiple entries but makes it easier to do so.
-rw-r--r--gst/isomp4/qtdemux.c167
1 files changed, 87 insertions, 80 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index 105a267dc..f82556e99 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -524,7 +524,7 @@ static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
QtDemuxStream * stream, GNode * esds, GstTagList * list);
static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
- QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
+ QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_entry_data,
gchar ** codec_name);
static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
@@ -533,7 +533,7 @@ static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
gchar ** codec_name);
static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
- QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
+ QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_entry_data,
gchar ** codec_name);
static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
@@ -9003,12 +9003,12 @@ done:
* the SMI and gama atoms.
*/
static void
-qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
- guint8 ** gamma, GstBuffer ** seqh)
+qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
+ const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
{
- guint8 *_gamma = NULL;
+ const guint8 *_gamma = NULL;
GstBuffer *_seqh = NULL;
- guint8 *stsd_data = stsd->data;
+ const guint8 *stsd_data = stsd_entry_data;
guint32 length = QT_UINT32 (stsd_data);
guint16 version;
@@ -9017,8 +9017,8 @@ qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
goto end;
}
- stsd_data += 32;
- length -= 32;
+ stsd_data += 16;
+ length -= 16;
version = QT_UINT16 (stsd_data);
if (version == 3) {
if (length >= 70) {
@@ -9026,7 +9026,7 @@ qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
stsd_data += 70;
while (length > 8) {
guint32 fourcc, size;
- guint8 *data;
+ const guint8 *data;
size = QT_UINT32 (stsd_data);
fourcc = QT_FOURCC (stsd_data + 4);
data = stsd_data + 8;
@@ -9463,6 +9463,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
gboolean new_stream = FALSE;
gchar *codec = NULL;
const guint8 *stsd_data;
+ const guint8 *stsd_entry_data;
+ guint remaining_stsd_len;
guint16 lang_code; /* quicktime lang code or packed iso code */
guint32 version;
guint32 tkhd_flags = 0;
@@ -9684,13 +9686,15 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
GST_LOG_OBJECT (qtdemux, "stsd len: %d", stsd_len);
+ stsd_entry_data = stsd_data + 16;
+ remaining_stsd_len = stsd_len - 16;
/* and that entry should fit within stsd */
- len = QT_UINT32 (stsd_data + 16);
- if (len > stsd_len + 16)
+ len = QT_UINT32 (stsd_entry_data);
+ if (len > remaining_stsd_len)
goto corrupt_file;
- stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
+ stream->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
GST_LOG_OBJECT (qtdemux, "stsd type: %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (stream->fourcc));
GST_LOG_OBJECT (qtdemux, "stsd type len: %d", len);
@@ -9732,21 +9736,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
&stream->stream_tags);
offset = 16;
- if (len < 86)
+ if (len < 86) /* TODO verify */
goto corrupt_file;
- stream->width = QT_UINT16 (stsd_data + offset + 32);
- stream->height = QT_UINT16 (stsd_data + offset + 34);
+ stream->width = QT_UINT16 (stsd_entry_data + offset + 16);
+ stream->height = QT_UINT16 (stsd_entry_data + offset + 18);
stream->fps_n = 0; /* this is filled in later */
stream->fps_d = 0; /* this is filled in later */
- stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
- stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
+ stream->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
+ stream->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
/* if color_table_id is 0, ctab atom must follow; however some files
* produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
* if color table is not present we'll correct the value */
if (stream->color_table_id == 0 &&
- (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
+ (len < 90
+ || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
stream->color_table_id = -1;
}
@@ -9802,9 +9807,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
goto corrupt_file;
/* read table */
- start = QT_UINT32 (stsd_data + offset + 86);
- palette_count = QT_UINT16 (stsd_data + offset + 90);
- end = QT_UINT16 (stsd_data + offset + 92);
+ start = QT_UINT32 (stsd_entry_data + offset + 70);
+ palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
+ end = QT_UINT16 (stsd_entry_data + offset + 76);
GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
start, end, palette_count);
@@ -9824,10 +9829,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
for (j = 0, i = start; i <= end; j++, i++) {
guint32 a, r, g, b;
- a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
- r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
- g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
- b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
+ a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
+ r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
+ g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
+ b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
(g & 0xff00) | (b >> 8);
@@ -9838,7 +9843,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
gst_caps_unref (stream->caps);
stream->caps =
- qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+ qtdemux_video_caps (qtdemux, stream, fourcc, stsd_entry_data, &codec);
if (G_UNLIKELY (!stream->caps)) {
g_free (palette_data);
goto unknown_stream;
@@ -9882,7 +9887,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
GST_LOG_OBJECT (qtdemux, "frame count: %u",
- QT_UINT16 (stsd_data + offset + 48));
+ QT_UINT16 (stsd_entry_data + offset + 32));
esds = NULL;
pasp = NULL;
@@ -10011,8 +10016,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
case FOURCC_avc1:
case FOURCC_avc3:
{
- gint len = QT_UINT32 (stsd_data) - 0x66;
- const guint8 *avc_data = stsd_data + 0x66;
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *avc_data = stsd_entry_data + 0x56;
/* find avcC */
while (len >= 0x8) {
@@ -10121,8 +10126,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
case FOURCC_hvc1:
case FOURCC_hev1:
{
- gint len = QT_UINT32 (stsd_data) - 0x66;
- const guint8 *hevc_data = stsd_data + 0x66;
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *hevc_data = stsd_entry_data + 0x56;
/* find hevc */
while (len >= 0x8) {
@@ -10462,10 +10467,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
{
GstBuffer *buf;
GstBuffer *seqh = NULL;
- guint8 *gamma_data = NULL;
- gint len = QT_UINT32 (stsd_data);
+ const guint8 *gamma_data = NULL;
+ gint len = QT_UINT32 (stsd_data); /* FIXME review - why put the whole stsd in codec data? */
- qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
+ qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
+ &seqh);
if (gamma_data) {
gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
QT_FP32 (gamma_data), NULL);
@@ -10490,7 +10496,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
case FOURCC_WRLE:
{
gst_caps_set_simple (stream->caps,
- "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
+ "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
+ NULL);
break;
}
case FOURCC_XiTh:
@@ -10538,8 +10545,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
case FOURCC_vc_1:
{
- gint len = QT_UINT32 (stsd_data) - 0x66;
- const guint8 *vc1_data = stsd_data + 0x66;
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *vc1_data = stsd_entry_data + 0x56;
/* find dvc1 */
while (len >= 8) {
@@ -10589,25 +10596,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
guint16 compression_id;
gboolean amrwb = FALSE;
- offset = 32;
+ offset = 16;
/* sample description entry (16) + sound sample description v0 (20) */
if (len < 36)
goto corrupt_file;
- version = QT_UINT32 (stsd_data + offset);
- stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
- samplesize = QT_UINT16 (stsd_data + offset + 10);
- compression_id = QT_UINT16 (stsd_data + offset + 12);
- stream->rate = QT_FP32 (stsd_data + offset + 16);
+ version = QT_UINT32 (stsd_entry_data + offset);
+ stream->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
+ samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
+ compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
+ stream->rate = QT_FP32 (stsd_entry_data + offset + 16);
GST_LOG_OBJECT (qtdemux, "version/rev: %08x", version);
GST_LOG_OBJECT (qtdemux, "vendor: %08x",
- QT_UINT32 (stsd_data + offset + 4));
+ QT_UINT32 (stsd_entry_data + offset + 4));
GST_LOG_OBJECT (qtdemux, "n_channels: %d", stream->n_channels);
GST_LOG_OBJECT (qtdemux, "sample_size: %d", samplesize);
GST_LOG_OBJECT (qtdemux, "compression_id: %d", compression_id);
GST_LOG_OBJECT (qtdemux, "packet size: %d",
- QT_UINT16 (stsd_data + offset + 14));
+ QT_UINT16 (stsd_entry_data + offset + 14));
GST_LOG_OBJECT (qtdemux, "sample rate: %g", stream->rate);
if (compression_id == 0xfffe)
@@ -10620,7 +10627,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->samples_per_packet = stream->samples_per_frame;
stream->bytes_per_packet = stream->bytes_per_sample;
- offset = 52;
+ offset = 36;
switch (fourcc) {
/* Yes, these have to be hard-coded */
case FOURCC_MAC6:
@@ -10686,10 +10693,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
default:
{
/* only parse extra decoding config for non-pcm audio */
- stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
- stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
- stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
- stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
+ stream->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
+ stream->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
+ stream->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
+ stream->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
GST_LOG_OBJECT (qtdemux, "samples/packet: %d",
stream->samples_per_packet);
@@ -10720,21 +10727,21 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
if (len < 72)
goto corrupt_file;
- qtfp.val = QT_UINT64 (stsd_data + offset + 4);
+ qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
stream->rate = qtfp.fp;
- stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
+ stream->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
GST_LOG_OBJECT (qtdemux, "sample rate: %g", stream->rate);
GST_LOG_OBJECT (qtdemux, "n_channels: %d", stream->n_channels);
GST_LOG_OBJECT (qtdemux, "bits/channel: %d",
- QT_UINT32 (stsd_data + offset + 20));
+ QT_UINT32 (stsd_entry_data + offset + 20));
GST_LOG_OBJECT (qtdemux, "format flags: %X",
- QT_UINT32 (stsd_data + offset + 24));
+ QT_UINT32 (stsd_entry_data + offset + 24));
GST_LOG_OBJECT (qtdemux, "bytes/packet: %d",
- QT_UINT32 (stsd_data + offset + 28));
+ QT_UINT32 (stsd_entry_data + offset + 28));
GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
- QT_UINT32 (stsd_data + offset + 32));
+ QT_UINT32 (stsd_entry_data + offset + 32));
} else if (version != 0x00000) {
GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
}
@@ -10743,7 +10750,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
gst_caps_unref (stream->caps);
stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
- stsd_data + 32, len - 16, &codec);
+ stsd_entry_data + 32, len - 16, &codec);
switch (fourcc) {
case FOURCC_in24:
@@ -10829,8 +10836,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
case FOURCC_wma_:
{
- gint len = QT_UINT32 (stsd_data) - offset;
- const guint8 *wfex_data = stsd_data + offset;
+ gint len = QT_UINT32 (stsd_entry_data) - offset;
+ const guint8 *wfex_data = stsd_entry_data + offset;
const gchar *codec_name = NULL;
gint version = 1;
/* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
@@ -11024,8 +11031,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
if (len < offset + 20) {
GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
} else {
- guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
- const guint8 *data = stsd_data + offset + 16;
+ guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
+ const guint8 *data = stsd_entry_data + offset + 16;
GNode *wavenode;
GNode *waveheadernode;
@@ -11083,12 +11090,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
#endif
case FOURCC_QDM2:
{
- gint len = QT_UINT32 (stsd_data);
+ gint len = QT_UINT32 (stsd_entry_data);
- if (len > 0x4C) {
- GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
+ if (len > 0x3C) {
+ GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
- gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
+ gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
gst_caps_set_simple (stream->caps,
"codec_data", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf);
@@ -11245,13 +11252,13 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
amrwb = TRUE;
case FOURCC_samr:
{
- gint len = QT_UINT32 (stsd_data);
+ gint len = QT_UINT32 (stsd_entry_data);
- if (len > 0x34) {
- GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
+ if (len > 0x24) {
+ GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
guint bitrate;
- gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
+ gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
/* If we have enough data, let's try to get the 'damr' atom. See
* the 3GPP container spec (26.244) for more details. */
@@ -11270,14 +11277,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
case FOURCC_mp4a:
{
/* mp4a atom withtout ESDS; Attempt to build codec data from atom */
- gint len = QT_UINT32 (stsd_data);
+ gint len = QT_UINT32 (stsd_entry_data);
- if (len >= 50) {
- guint16 sound_version = QT_UINT16 (stsd_data + 32);
+ if (len >= 34) {
+ guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
if (sound_version == 1) {
- guint16 channels = QT_UINT16 (stsd_data + 40);
- guint32 time_scale = QT_UINT32 (stsd_data + 46);
+ guint16 channels = QT_UINT16 (stsd_entry_data + 24);
+ guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
guint8 codec_data[2];
GstBuffer *buf;
gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
@@ -11326,7 +11333,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->sparse = TRUE;
stream->caps =
- qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+ qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_entry_data, &codec);
if (codec) {
gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_SUBTITLE_CODEC, codec, NULL);
@@ -11367,7 +11374,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->sampled = TRUE;
stream->caps =
- qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+ qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_entry_data, &codec);
if (stream->caps == NULL)
goto unknown_stream;
@@ -13398,7 +13405,7 @@ _get_unknown_codec_name (const gchar * type, guint32 fourcc)
static GstCaps *
qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
+ guint32 fourcc, const guint8 * stsd_entry_data, gchar ** codec_name)
{
GstCaps *caps = NULL;
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
@@ -13454,7 +13461,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
{
guint16 bps;
- bps = QT_UINT16 (stsd_data + 98);
+ bps = QT_UINT16 (stsd_entry_data + 82);
switch (bps) {
case 15:
format = GST_VIDEO_FORMAT_RGB15;
@@ -14153,7 +14160,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
static GstCaps *
qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
+ guint32 fourcc, const guint8 * stsd_entry_data, gchar ** codec_name)
{
GstCaps *caps;
@@ -14191,7 +14198,7 @@ qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
static GstCaps *
qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
+ guint32 fourcc, const guint8 * stsd_entry_data, gchar ** codec_name)
{
GstCaps *caps;