Commit 86b427dc authored by Thiago Santos's avatar Thiago Santos Committed by Thiago Sousa Santos

qtdemux: parse all stsd entries

stsd can have multiple format entries, parse them all.

This is required to play DVB DASH profile that uses multiple entries
to identify the different available bitrates/options on dash streams

The stream format-specific data is not stored into QtDemuxStreamStsdEntry
parent 54e252e0
......@@ -216,15 +216,55 @@ typedef struct
guint64 moof_offset;
} QtDemuxRandomAccessEntry;
typedef struct _QtDemuxStreamStsdEntry
{
GstCaps *caps;
guint32 fourcc;
gboolean sparse;
/* video info */
gint width;
gint height;
gint par_w;
gint par_h;
/* Numerator/denominator framerate */
gint fps_n;
gint fps_d;
GstVideoColorimetry colorimetry;
guint16 bits_per_sample;
guint16 color_table_id;
GstMemory *rgb8_palette;
guint interlace_mode;
guint field_order;
/* audio info */
gdouble rate;
gint n_channels;
guint samples_per_packet;
guint samples_per_frame;
guint bytes_per_packet;
guint bytes_per_sample;
guint bytes_per_frame;
guint compression;
/* if we use chunks or samples */
gboolean sampled;
guint padding;
} QtDemuxStreamStsdEntry;
#define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
struct _QtDemuxStream
{
GstPad *pad;
QtDemuxStreamStsdEntry *stsd_entries;
guint stsd_entries_length;
guint cur_stsd_entry_index;
/* stream type */
guint32 subtype;
GstCaps *caps;
guint32 fourcc;
gboolean sparse;
gboolean new_caps; /* If TRUE, caps need to be generated (by
* calling _configure_stream()) This happens
......@@ -267,37 +307,10 @@ struct _QtDemuxStream
guint32 max_buffer_size; /* Maximum allowed size for output buffers.
* Currently only set for raw audio streams*/
/* if we use chunks or samples */
gboolean sampled;
guint padding;
/* video info */
gint width;
gint height;
/* aspect ratio */
gint display_width;
gint display_height;
gint par_w;
gint par_h;
/* Numerator/denominator framerate */
gint fps_n;
gint fps_d;
GstVideoColorimetry colorimetry;
guint16 bits_per_sample;
guint16 color_table_id;
GstMemory *rgb8_palette;
guint interlace_mode;
guint field_order;
/* audio info */
gdouble rate;
gint n_channels;
guint samples_per_packet;
guint samples_per_frame;
guint bytes_per_packet;
guint bytes_per_sample;
guint bytes_per_frame;
guint compression;
/* allocation */
gboolean use_allocator;
......@@ -522,19 +535,20 @@ static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
GNode * udta);
static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
QtDemuxStream * stream, GNode * esds, GstTagList * list);
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
GstTagList * list);
static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_entry_data,
gchar ** codec_name);
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, 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,
gchar ** codec_name);
static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
const guint8 * data, int len, gchar ** codec_name);
static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
gchar ** codec_name);
static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_entry_data,
gchar ** codec_name);
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
const guint8 * stsd_entry_data, gchar ** codec_name);
static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 n);
......@@ -1308,7 +1322,7 @@ gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
str = qtdemux->streams[n];
if (str->sparse && !use_sparse)
if (CUR_STREAM (str)->sparse && !use_sparse)
continue;
seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
......@@ -1847,7 +1861,7 @@ gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
}
/* avoid index from sparse streams since they might be far away */
if (!str->sparse) {
if (!CUR_STREAM (str)->sparse) {
/* determine min/max time */
time = QTSAMPLE_PTS (str, &str->samples[i]);
if (min_time == -1 || (!fw && time > min_time) ||
......@@ -1960,26 +1974,29 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
demux->timescale = stream->timescale;
mediacaps = gst_value_get_caps (value);
if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
if (!CUR_STREAM (stream)->caps
|| !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
mediacaps);
stream->new_caps = TRUE;
}
gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
structure = gst_caps_get_structure (mediacaps, 0);
if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
stream->subtype = FOURCC_vide;
gst_structure_get_int (structure, "width", &stream->width);
gst_structure_get_int (structure, "height", &stream->height);
gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
&stream->fps_d);
gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
gst_structure_get_int (structure, "height",
&CUR_STREAM (stream)->height);
gst_structure_get_fraction (structure, "framerate",
&CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
} else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
gint rate = 0;
stream->subtype = FOURCC_soun;
gst_structure_get_int (structure, "channels", &stream->n_channels);
gst_structure_get_int (structure, "channels",
&CUR_STREAM (stream)->n_channels);
gst_structure_get_int (structure, "rate", &rate);
stream->rate = rate;
CUR_STREAM (stream)->rate = rate;
}
}
gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
......@@ -2455,15 +2472,20 @@ gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
static void
gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
{
gint i;
if (stream->allocator)
gst_object_unref (stream->allocator);
while (stream->buffers) {
gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
}
if (stream->rgb8_palette) {
gst_memory_unref (stream->rgb8_palette);
stream->rgb8_palette = NULL;
for (i = 0; i < stream->stsd_entries_length; i++) {
QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
if (entry->rgb8_palette) {
gst_memory_unref (entry->rgb8_palette);
entry->rgb8_palette = NULL;
}
entry->sparse = FALSE;
}
gst_tag_list_unref (stream->stream_tags);
......@@ -2472,7 +2494,6 @@ gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
g_free (stream->redirect_uri);
stream->redirect_uri = NULL;
stream->sent_eos = FALSE;
stream->sparse = FALSE;
stream->protected = FALSE;
if (stream->protection_scheme_info) {
if (stream->protection_scheme_type == FOURCC_cenc) {
......@@ -2498,10 +2519,15 @@ gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
static void
gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
{
gint i;
gst_qtdemux_stream_clear (qtdemux, stream);
if (stream->caps)
gst_caps_unref (stream->caps);
stream->caps = NULL;
for (i = 0; i < stream->stsd_entries_length; i++) {
QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
if (entry->caps) {
gst_caps_unref (entry->caps);
entry->caps = NULL;
}
}
gst_tag_list_unref (stream->stream_tags);
if (stream->pad) {
gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
......@@ -2609,7 +2635,7 @@ qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
stream = qtdemux->streams[0];
structure = gst_caps_get_structure (stream->caps, 0);
structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
if (!gst_structure_has_name (structure, "application/x-cenc")) {
GST_WARNING_OBJECT (qtdemux,
"Attempting PIFF box parsing on an unencrypted stream.");
......@@ -3563,7 +3589,7 @@ qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
} else if (stream->protected) {
aux_info_type = stream->protection_scheme_type;
} else {
aux_info_type = stream->fourcc;
aux_info_type = CUR_STREAM (stream)->fourcc;
}
if (info_type)
......@@ -5130,14 +5156,14 @@ gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
/* depending on the type, setup the clip parameters */
if (stream->subtype == FOURCC_soun) {
frame_size = stream->bytes_per_frame;
frame_size = CUR_STREAM (stream)->bytes_per_frame;
num_rate = GST_SECOND;
denom_rate = (gint) stream->rate;
denom_rate = (gint) CUR_STREAM (stream)->rate;
clip_data = TRUE;
} else if (stream->subtype == FOURCC_vide) {
frame_size = size;
num_rate = stream->fps_n;
denom_rate = stream->fps_d;
num_rate = CUR_STREAM (stream)->fps_n;
denom_rate = CUR_STREAM (stream)->fps_d;
clip_data = FALSE;
} else
goto wrong_type;
......@@ -5280,7 +5306,7 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
gchar *str;
/* not many cases for now */
if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
/* send a one time dvd clut event */
if (stream->pending_event && stream->pad)
gst_pad_push_event (stream->pad, stream->pending_event);
......@@ -5345,7 +5371,7 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
/* offset the timestamps according to the edit list */
if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
gchar *url;
GstMapInfo map;
......@@ -5413,11 +5439,12 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
GST_BUFFER_OFFSET (buf) = -1;
GST_BUFFER_OFFSET_END (buf) = -1;
if (G_UNLIKELY (stream->rgb8_palette))
gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
gst_buffer_append_memory (buf,
gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
if (G_UNLIKELY (stream->padding)) {
gst_buffer_resize (buf, stream->padding, -1);
if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
}
#if 0
if (G_UNLIKELY (qtdemux->element_index)) {
......@@ -5789,11 +5816,15 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
if (size != sample_size) {
pts += gst_util_uint64_scale_int (GST_SECOND,
stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
dts += gst_util_uint64_scale_int (GST_SECOND,
stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
duration = gst_util_uint64_scale_int (GST_SECOND,
size / stream->bytes_per_frame, stream->timescale);
stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
stream->timescale);
dts +=
gst_util_uint64_scale_int (GST_SECOND,
stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
stream->timescale);
duration =
gst_util_uint64_scale_int (GST_SECOND,
size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
}
ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
......@@ -5804,7 +5835,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
QtDemuxSegment *segment = &stream->segments[stream->segment_index];
GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
sample->timestamp +
stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
if (time_position >= segment->media_start) {
/* inside the segment, update time_position, looks very familiar to
* GStreamer segments, doesn't it? */
......@@ -6171,7 +6203,7 @@ gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
QtDemuxStream *stream;
stream = demux->streams[i];
gst_qtdemux_push_tags (demux, stream);
if (stream->sparse) {
if (CUR_STREAM (stream)->sparse) {
GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
gst_pad_push_event (stream->pad,
gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
......@@ -6829,7 +6861,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (stream->fourcc));
GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
dts = QTSAMPLE_DTS (stream, sample);
pts = QTSAMPLE_PTS (stream, sample);
......@@ -7628,7 +7660,8 @@ gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
g_return_val_if_fail (qtdemux != NULL, FALSE);
g_return_val_if_fail (stream != NULL, FALSE);
g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
FALSE);
if (stream->protection_scheme_type != FOURCC_cenc) {
GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
......@@ -7650,7 +7683,7 @@ gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
return FALSE;
}
s = gst_caps_get_structure (stream->caps, 0);
s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
if (!gst_structure_has_name (s, "application/x-cenc")) {
gst_structure_set (s,
"original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
......@@ -7671,12 +7704,12 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
/* still frame */
stream->fps_n = 0;
stream->fps_d = 1;
CUR_STREAM (stream)->fps_n = 0;
CUR_STREAM (stream)->fps_d = 1;
} else {
if (stream->duration == 0 || stream->n_samples < 2) {
stream->fps_n = stream->timescale;
stream->fps_d = 1;
CUR_STREAM (stream)->fps_n = stream->timescale;
CUR_STREAM (stream)->fps_d = 1;
fps_available = FALSE;
} else {
GstClockTime avg_duration;
......@@ -7708,95 +7741,103 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
GST_TIME_FORMAT, duration, stream->first_duration,
n_samples - 1, GST_TIME_ARGS (avg_duration));
gst_video_guess_framerate (avg_duration, &stream->fps_n,
&stream->fps_d);
gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
&CUR_STREAM (stream)->fps_d);
GST_DEBUG_OBJECT (qtdemux,
"Calculating framerate, timescale %u gave fps_n %d fps_d %d",
stream->timescale, stream->fps_n, stream->fps_d);
stream->timescale, CUR_STREAM (stream)->fps_n, CUR_STREAM (stream)->fps_d);
}
}
if (stream->caps) {
stream->caps = gst_caps_make_writable (stream->caps);
if (CUR_STREAM (stream)->caps) {
CUR_STREAM (stream)->caps =
gst_caps_make_writable (CUR_STREAM (stream)->caps);
gst_caps_set_simple (stream->caps,
"width", G_TYPE_INT, stream->width,
"height", G_TYPE_INT, stream->height, NULL);
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"width", G_TYPE_INT, CUR_STREAM (stream)->width,
"height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
/* set framerate if calculated framerate is reliable */
if (fps_available) {
gst_caps_set_simple (stream->caps,
"framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n, CUR_STREAM (stream)->fps_d, NULL);
}
/* calculate pixel-aspect-ratio using display width and height */
GST_DEBUG_OBJECT (qtdemux,
"video size %dx%d, target display size %dx%d", stream->width,
stream->height, stream->display_width, stream->display_height);
"video size %dx%d, target display size %dx%d",
CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
stream->display_width, stream->display_height);
/* qt file might have pasp atom */
if (stream->par_w > 0 && stream->par_h > 0) {
GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
} else if (stream->display_width > 0 && stream->display_height > 0 &&
stream->width > 0 && stream->height > 0) {
if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
CUR_STREAM (stream)->par_h);
gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
CUR_STREAM (stream)->par_h, NULL);
} else if (stream->display_width > 0 && stream->display_height > 0
&& CUR_STREAM (stream)->width > 0
&& CUR_STREAM (stream)->height > 0) {
gint n, d;
/* calculate the pixel aspect ratio using the display and pixel w/h */
n = stream->display_width * stream->height;
d = stream->display_height * stream->width;
n = stream->display_width * CUR_STREAM (stream)->height;
d = stream->display_height * CUR_STREAM (stream)->width;
if (n == d)
n = d = 1;
GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
stream->par_w = n;
stream->par_h = d;
gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
}
if (stream->interlace_mode > 0) {
if (stream->interlace_mode == 1) {
gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
"progressive", NULL);
} else if (stream->interlace_mode == 2) {
gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
"interleaved", NULL);
if (stream->field_order == 9) {
gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
"top-field-first", NULL);
} else if (stream->field_order == 14) {
gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
"bottom-field-first", NULL);
CUR_STREAM (stream)->par_w = n;
CUR_STREAM (stream)->par_h = d;
gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
CUR_STREAM (stream)->par_h, NULL);
}
if (CUR_STREAM (stream)->interlace_mode > 0) {
if (CUR_STREAM (stream)->interlace_mode == 1) {
gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
G_TYPE_STRING, "progressive", NULL);
} else if (CUR_STREAM (stream)->interlace_mode == 2) {
gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
G_TYPE_STRING, "interleaved", NULL);
if (CUR_STREAM (stream)->field_order == 9) {
gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
G_TYPE_STRING, "top-field-first", NULL);
} else if (CUR_STREAM (stream)->field_order == 14) {
gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
G_TYPE_STRING, "bottom-field-first", NULL);
}
}
}
/* Create incomplete colorimetry here if needed */
if (stream->colorimetry.range ||
stream->colorimetry.matrix ||
stream->colorimetry.transfer || stream->colorimetry.primaries) {
if (CUR_STREAM (stream)->colorimetry.range ||
CUR_STREAM (stream)->colorimetry.matrix ||
CUR_STREAM (stream)->colorimetry.transfer
|| CUR_STREAM (stream)->colorimetry.primaries) {
gchar *colorimetry =
gst_video_colorimetry_to_string (&stream->colorimetry);
gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
colorimetry, NULL);
gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
G_TYPE_STRING, colorimetry, NULL);
g_free (colorimetry);
}
if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
guint par_w = 1, par_h = 1;
if (stream->par_w > 0 && stream->par_h > 0) {
par_w = stream->par_w;
par_h = stream->par_h;
if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
par_w = CUR_STREAM (stream)->par_w;
par_h = CUR_STREAM (stream)->par_h;
}
if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
stream->width, stream->height, par_w, par_h)) {
CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
par_h)) {
stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
}
gst_caps_set_simple (stream->caps,
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"multiview-mode", G_TYPE_STRING,
gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
"multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
......@@ -7806,19 +7847,20 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
}
else if (stream->subtype == FOURCC_soun) {
if (stream->caps) {
stream->caps = gst_caps_make_writable (stream->caps);
if (stream->rate > 0)
gst_caps_set_simple (stream->caps,
"rate", G_TYPE_INT, (int) stream->rate, NULL);
if (stream->n_channels > 0)
gst_caps_set_simple (stream->caps,
"channels", G_TYPE_INT, stream->n_channels, NULL);
if (stream->n_channels > 2) {
if (CUR_STREAM (stream)->caps) {
CUR_STREAM (stream)->caps =
gst_caps_make_writable (CUR_STREAM (stream)->caps);
if (CUR_STREAM (stream)->rate > 0)
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
if (CUR_STREAM (stream)->n_channels > 0)
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
if (CUR_STREAM (stream)->n_channels > 2) {
/* FIXME: Need to parse the 'chan' atom to get channel layouts
* correctly; this is just the minimum we can do - assume
* we don't actually have any channel positions. */
gst_caps_set_simple (stream->caps,
gst_caps_set_simple (CUR_STREAM (stream)->caps,
"channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
}
}
......@@ -7842,6 +7884,8 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
}
}
GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
CUR_STREAM (stream)->caps);
if (stream->new_stream) {
gchar *stream_id;
GstEvent *event;
......@@ -7871,7 +7915,7 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
gst_event_set_group_id (event, qtdemux->group_id);
if (stream->disabled)
stream_flags |= GST_STREAM_FLAG_UNSELECT;
if (stream->sparse) {
if (CUR_STREAM (stream)->sparse) {
stream_flags |= GST_STREAM_FLAG_SPARSE;
} else {
stream_flags &= ~GST_STREAM_FLAG_SPARSE;
......@@ -7883,11 +7927,12 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
prev_caps = gst_pad_get_current_caps (stream->pad);
if (stream->caps) {
if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
if (CUR_STREAM (stream)->caps) {
if (!prev_caps
|| !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
stream->caps);
gst_pad_set_caps (stream->pad, stream->caps);
CUR_STREAM (stream)->caps);
gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
} else {
GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
}
......@@ -7954,7 +7999,7 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
goto done;
}
qtdemux->n_sub_streams++;
} else if (stream->caps) {
} else if (CUR_STREAM (stream)->caps) {
gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
stream->pad =
......@@ -8260,7 +8305,8 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
goto corrupt_file;
/* chunks_are_samples == TRUE means treat chunks as samples */
stream->chunks_are_samples = stream->sample_size && !stream->sampled;
stream->chunks_are_samples = stream->sample_size
&& !CUR_STREAM (stream)->sampled;
if (stream->chunks_are_samples) {
/* treat chunks as samples */
if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
......@@ -8396,7 +8442,8 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
guint32 n_samples;
GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
GST_FOURCC_FORMAT ", pad %s",
GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
n_samples = stream->n_samples;
......@@ -8521,10 +8568,12 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
"%" G_GUINT64_FORMAT, j, cur->offset);
if (stream->samples_per_frame > 0 && stream->bytes_per_frame > 0) {
if (CUR_STREAM (stream)->samples_per_frame > 0 &&
CUR_STREAM (stream)->bytes_per_frame > 0) {
cur->size =
(stream->samples_per_chunk * stream->n_channels) /
stream->samples_per_frame * stream->bytes_per_frame;
(stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
CUR_STREAM (stream)->samples_per_frame *
CUR_STREAM (stream)->bytes_per_frame;
} else {
cur->size = stream->samples_per_chunk;
}
......@@ -9465,6 +9514,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
const guint8 *stsd_data;
const guint8 *stsd_entry_data;
guint remaining_stsd_len;
guint stsd_entry_count;
guint stsd_index;
guint16 lang_code; /* quicktime lang code or packed iso code */
guint32 version;
guint32 tkhd_flags = 0;
......@@ -9685,1626 +9736,1710 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
}
stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
GST_LOG_OBJECT (qtdemux, "stsd len: %d", stsd_len);
GST_LOG_OBJECT (qtdemux, "stsd entry count: %u", stsd_entry_count);
stsd_entry_data = stsd_data + 16;
remaining_stsd_len = stsd_len - 16;
for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
/* and that entry should fit within stsd */
len = QT_UINT32 (stsd_entry_data);
if (len > remaining_stsd_len)