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,
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,
* 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;
goto end;
}
- stsd_data += 32;
- length -= 32;
+ stsd_data += 16;
+ length -= 16;
version = QT_UINT16 (stsd_data);
if (version == 3) {
if (length >= 70) {
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;
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;
}
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);
&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;
}
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);
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);
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;
}
GST_LOG_OBJECT (qtdemux, "frame count: %u",
- QT_UINT16 (stsd_data + offset + 48));
+ QT_UINT16 (stsd_entry_data + offset + 32));
esds = NULL;
pasp = NULL;
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) {
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) {
{
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);
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:
}
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) {
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)
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:
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);
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);
}
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:
}
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 */
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;
#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);
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. */
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 */
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);
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;
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;
{
guint16 bps;
- bps = QT_UINT16 (stsd_data + 98);
+ bps = QT_UINT16 (stsd_entry_data + 82);
switch (bps) {
case 15:
format = GST_VIDEO_FORMAT_RGB15;
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;
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;