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
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;
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);
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);
}
/* 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) ||
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);
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);
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) {
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);
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.");
} 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)
/* 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;
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);
/* 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;
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)) {
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,
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? */
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));
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);
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");
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),
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;
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,
}
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);
}
}
}
}
+ GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
+ CUR_STREAM (stream)->caps);
if (stream->new_stream) {
gchar *stream_id;
GstEvent *event;
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;
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");
}
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 =
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))
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;
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;
}
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;
}
}
+ 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)
- goto corrupt_file;
+ /* and that entry should fit within stsd */
+ len = QT_UINT32 (stsd_entry_data);
+ if (len > remaining_stsd_len)
+ goto corrupt_file;
- 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);
+ entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
+ GST_LOG_OBJECT (qtdemux, "stsd type: %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (entry->fourcc));
+ GST_LOG_OBJECT (qtdemux, "stsd type len: %d", len);
- if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
- goto error_encrypted;
+ if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
+ goto error_encrypted;
- if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
- GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
- stream->protected = TRUE;
- if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
- GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
- }
+ if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
+ /* FIXME this looks wrong, there might be multiple children
+ * with the same type */
+ GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
+ stream->protected = TRUE;
+ if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
+ GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
+ }
- if (stream->subtype == FOURCC_vide) {
- guint32 w = 0, h = 0;
- gboolean gray;
- gint depth, palette_size, palette_count;
- guint32 matrix[9];
- guint32 *palette_data = NULL;
+ if (stream->subtype == FOURCC_vide) {
+ guint32 w = 0, h = 0;
+ gboolean gray;
+ gint depth, palette_size, palette_count;
+ guint32 matrix[9];
+ guint32 *palette_data = NULL;
- stream->sampled = TRUE;
+ entry->sampled = TRUE;
- /* version 1 uses some 64-bit ints */
- if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
- goto corrupt_file;
+ /* version 1 uses some 64-bit ints */
+ if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
+ goto corrupt_file;
- if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
- goto corrupt_file;
+ if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
+ goto corrupt_file;
- if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
- || !gst_byte_reader_get_uint32_be (&tkhd, &h))
- goto corrupt_file;
+ if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
+ || !gst_byte_reader_get_uint32_be (&tkhd, &h))
+ goto corrupt_file;
- stream->display_width = w >> 16;
- stream->display_height = h >> 16;
+ stream->display_width = w >> 16;
+ stream->display_height = h >> 16;
- qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
- &stream->stream_tags);
+ qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
+ &stream->stream_tags);
- offset = 16;
- if (len < 86) /* TODO verify */
- goto corrupt_file;
+ offset = 16;
+ if (len < 86) /* TODO verify */
+ goto corrupt_file;
- 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_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_entry_data + offset + 70) != FOURCC_ctab)) {
- stream->color_table_id = -1;
- }
-
- GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
- stream->width, stream->height, stream->bits_per_sample,
- stream->color_table_id);
-
- depth = stream->bits_per_sample;
-
- /* more than 32 bits means grayscale */
- gray = (depth > 32);
- /* low 32 bits specify the depth */
- depth &= 0x1F;
-
- /* different number of palette entries is determined by depth. */
- palette_count = 0;
- if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
- palette_count = (1 << depth);
- palette_size = palette_count * 4;
-
- if (stream->color_table_id) {
- switch (palette_count) {
- case 0:
- break;
- case 2:
- palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
- break;
- case 4:
- palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
- break;
- case 16:
- if (gray)
- palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
- else
- palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
- break;
- case 256:
- if (gray)
- palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
- else
- palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
- break;
- default:
- GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
- (_("The video in this file might not play correctly.")),
- ("unsupported palette depth %d", depth));
- break;
- }
- } else {
- gint i, j, start, end;
+ entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
+ entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
+ entry->fps_n = 0; /* this is filled in later */
+ entry->fps_d = 0; /* this is filled in later */
+ entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
+ entry->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 (entry->color_table_id == 0 &&
+ (len < 90
+ || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
+ entry->color_table_id = -1;
+ }
+
+ GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
+ entry->width, entry->height, entry->bits_per_sample,
+ entry->color_table_id);
+
+ depth = entry->bits_per_sample;
+
+ /* more than 32 bits means grayscale */
+ gray = (depth > 32);
+ /* low 32 bits specify the depth */
+ depth &= 0x1F;
+
+ /* different number of palette entries is determined by depth. */
+ palette_count = 0;
+ if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
+ palette_count = (1 << depth);
+ palette_size = palette_count * 4;
+
+ if (entry->color_table_id) {
+ switch (palette_count) {
+ case 0:
+ break;
+ case 2:
+ palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
+ break;
+ case 4:
+ palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
+ break;
+ case 16:
+ if (gray)
+ palette_data =
+ g_memdup (ff_qt_grayscale_palette_16, palette_size);
+ else
+ palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
+ break;
+ case 256:
+ if (gray)
+ palette_data =
+ g_memdup (ff_qt_grayscale_palette_256, palette_size);
+ else
+ palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
+ break;
+ default:
+ GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
+ (_("The video in this file might not play correctly.")),
+ ("unsupported palette depth %d", depth));
+ break;
+ }
+ } else {
+ gint i, j, start, end;
- if (len < 94)
- goto corrupt_file;
+ if (len < 94)
+ goto corrupt_file;
- /* read table */
- 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);
+ /* read table */
+ 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);
+ GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
+ start, end, palette_count);
- if (end > 255)
- end = 255;
- if (start > end)
- start = end;
+ if (end > 255)
+ end = 255;
+ if (start > end)
+ start = end;
- if (len < 94 + (end - start) * 8)
- goto corrupt_file;
+ if (len < 94 + (end - start) * 8)
+ goto corrupt_file;
- /* palette is always the same size */
- palette_data = g_malloc0 (256 * 4);
- palette_size = 256 * 4;
+ /* palette is always the same size */
+ palette_data = g_malloc0 (256 * 4);
+ palette_size = 256 * 4;
- for (j = 0, i = start; i <= end; j++, i++) {
- guint32 a, r, g, b;
+ for (j = 0, i = start; i <= end; j++, i++) {
+ guint32 a, r, g, b;
- 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));
+ 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);
+ palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
+ (g & 0xff00) | (b >> 8);
+ }
}
- }
-
- if (stream->caps)
- gst_caps_unref (stream->caps);
- stream->caps =
- qtdemux_video_caps (qtdemux, stream, fourcc, stsd_entry_data, &codec);
- if (G_UNLIKELY (!stream->caps)) {
- g_free (palette_data);
- goto unknown_stream;
- }
+ if (entry->caps)
+ gst_caps_unref (entry->caps);
- if (codec) {
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_VIDEO_CODEC, codec, NULL);
- g_free (codec);
- codec = NULL;
- }
+ entry->caps =
+ qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
+ &codec);
+ if (G_UNLIKELY (!entry->caps)) {
+ g_free (palette_data);
+ goto unknown_stream;
+ }
+ if (codec) {
+ gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_VIDEO_CODEC, codec, NULL);
+ g_free (codec);
+ codec = NULL;
+ }
- if (palette_data) {
- GstStructure *s;
+ if (palette_data) {
+ GstStructure *s;
- if (stream->rgb8_palette)
- gst_memory_unref (stream->rgb8_palette);
- stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
- palette_data, palette_size, 0, palette_size, palette_data, g_free);
+ if (entry->rgb8_palette)
+ gst_memory_unref (entry->rgb8_palette);
+ entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+ palette_data, palette_size, 0, palette_size, palette_data, g_free);
- s = gst_caps_get_structure (stream->caps, 0);
+ s = gst_caps_get_structure (entry->caps, 0);
- /* non-raw video has a palette_data property. raw video has the palette as
- * an extra plane that we append to the output buffers before we push
- * them*/
- if (!gst_structure_has_name (s, "video/x-raw")) {
- GstBuffer *palette;
+ /* non-raw video has a palette_data property. raw video has the palette as
+ * an extra plane that we append to the output buffers before we push
+ * them*/
+ if (!gst_structure_has_name (s, "video/x-raw")) {
+ GstBuffer *palette;
- palette = gst_buffer_new ();
- gst_buffer_append_memory (palette, stream->rgb8_palette);
- stream->rgb8_palette = NULL;
+ palette = gst_buffer_new ();
+ gst_buffer_append_memory (palette, entry->rgb8_palette);
+ entry->rgb8_palette = NULL;
- gst_caps_set_simple (stream->caps, "palette_data",
- GST_TYPE_BUFFER, palette, NULL);
- gst_buffer_unref (palette);
+ gst_caps_set_simple (entry->caps, "palette_data",
+ GST_TYPE_BUFFER, palette, NULL);
+ gst_buffer_unref (palette);
+ }
+ } else if (palette_count != 0) {
+ GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
+ (NULL), ("Unsupported palette depth %d", depth));
+ }
+
+ GST_LOG_OBJECT (qtdemux, "frame count: %u",
+ QT_UINT16 (stsd_entry_data + offset + 32));
+
+ esds = NULL;
+ pasp = NULL;
+ colr = NULL;
+ fiel = NULL;
+ /* pick 'the' stsd child */
+ mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
+ if (!stream->protected) {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
+ mp4v = NULL;
+ }
+ } else {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
+ mp4v = NULL;
+ }
}
- } else if (palette_count != 0) {
- GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
- (NULL), ("Unsupported palette depth %d", depth));
- }
- GST_LOG_OBJECT (qtdemux, "frame count: %u",
- QT_UINT16 (stsd_entry_data + offset + 32));
-
- esds = NULL;
- pasp = NULL;
- colr = NULL;
- fiel = NULL;
- /* pick 'the' stsd child */
- mp4v = qtdemux_tree_get_child_by_index (stsd, 0);
- if (!stream->protected) {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
- mp4v = NULL;
- }
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
- mp4v = NULL;
+ if (mp4v) {
+ esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
+ pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
+ colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
+ fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
}
- }
-
- if (mp4v) {
- esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
- pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
- colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
- fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
- }
- if (pasp) {
- const guint8 *pasp_data = (const guint8 *) pasp->data;
- gint len = QT_UINT32 (pasp_data);
+ if (pasp) {
+ const guint8 *pasp_data = (const guint8 *) pasp->data;
+ gint len = QT_UINT32 (pasp_data);
- if (len == 16) {
- stream->par_w = QT_UINT32 (pasp_data + 8);
- stream->par_h = QT_UINT32 (pasp_data + 12);
+ if (len == 16) {
+ CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
+ CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
+ } else {
+ CUR_STREAM (stream)->par_w = 0;
+ CUR_STREAM (stream)->par_h = 0;
+ }
} else {
- stream->par_w = 0;
- stream->par_h = 0;
+ CUR_STREAM (stream)->par_w = 0;
+ CUR_STREAM (stream)->par_h = 0;
}
- } else {
- stream->par_w = 0;
- stream->par_h = 0;
- }
- if (fiel) {
- const guint8 *fiel_data = (const guint8 *) fiel->data;
- gint len = QT_UINT32 (fiel_data);
+ if (fiel) {
+ const guint8 *fiel_data = (const guint8 *) fiel->data;
+ gint len = QT_UINT32 (fiel_data);
- if (len == 10) {
- stream->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
- stream->field_order = GST_READ_UINT8 (fiel_data + 9);
+ if (len == 10) {
+ CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
+ CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
+ }
}
- }
- if (colr) {
- const guint8 *colr_data = (const guint8 *) colr->data;
- gint len = QT_UINT32 (colr_data);
+ if (colr) {
+ const guint8 *colr_data = (const guint8 *) colr->data;
+ gint len = QT_UINT32 (colr_data);
- if (len == 19 || len == 18) {
- guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
+ if (len == 19 || len == 18) {
+ guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
- if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
- guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
- guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
- guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
- gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
+ if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
+ guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
+ guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
+ guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
+ gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
- switch (primaries) {
- case 1:
- stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
- break;
- case 5:
- stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
- break;
- case 6:
- stream->colorimetry.primaries =
- GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
- break;
- case 9:
- stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
- break;
- default:
- break;
- }
+ switch (primaries) {
+ case 1:
+ CUR_STREAM (stream)->colorimetry.primaries =
+ GST_VIDEO_COLOR_PRIMARIES_BT709;
+ break;
+ case 5:
+ CUR_STREAM (stream)->colorimetry.primaries =
+ GST_VIDEO_COLOR_PRIMARIES_BT470BG;
+ break;
+ case 6:
+ CUR_STREAM (stream)->colorimetry.primaries =
+ GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
+ break;
+ case 9:
+ CUR_STREAM (stream)->colorimetry.primaries =
+ GST_VIDEO_COLOR_PRIMARIES_BT2020;
+ break;
+ default:
+ break;
+ }
- switch (transfer_function) {
- case 1:
- stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
- break;
- case 7:
- stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
- break;
- default:
- break;
- }
+ switch (transfer_function) {
+ case 1:
+ CUR_STREAM (stream)->colorimetry.transfer =
+ GST_VIDEO_TRANSFER_BT709;
+ break;
+ case 7:
+ CUR_STREAM (stream)->colorimetry.transfer =
+ GST_VIDEO_TRANSFER_SMPTE240M;
+ break;
+ default:
+ break;
+ }
- switch (matrix) {
- case 1:
- stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
- break;
- case 6:
- stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
- break;
- case 7:
- stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
- break;
- case 9:
- stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
- break;
- default:
- break;
- }
+ switch (matrix) {
+ case 1:
+ CUR_STREAM (stream)->colorimetry.matrix =
+ GST_VIDEO_COLOR_MATRIX_BT709;
+ break;
+ case 6:
+ CUR_STREAM (stream)->colorimetry.matrix =
+ GST_VIDEO_COLOR_MATRIX_BT601;
+ break;
+ case 7:
+ CUR_STREAM (stream)->colorimetry.matrix =
+ GST_VIDEO_COLOR_MATRIX_SMPTE240M;
+ break;
+ case 9:
+ CUR_STREAM (stream)->colorimetry.matrix =
+ GST_VIDEO_COLOR_MATRIX_BT2020;
+ break;
+ default:
+ break;
+ }
- stream->colorimetry.range =
- full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
- GST_VIDEO_COLOR_RANGE_16_235;
+ CUR_STREAM (stream)->colorimetry.range =
+ full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
+ GST_VIDEO_COLOR_RANGE_16_235;
+ } else {
+ GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
+ }
} else {
- GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
+ GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
}
- } else {
- GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
}
- }
-
- if (esds) {
- gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
- } else {
- switch (fourcc) {
- case FOURCC_H264:
- case FOURCC_avc1:
- case FOURCC_avc3:
- {
- gint len = QT_UINT32 (stsd_entry_data) - 0x56;
- const guint8 *avc_data = stsd_entry_data + 0x56;
- /* find avcC */
- while (len >= 0x8) {
- gint size;
-
- if (QT_UINT32 (avc_data) <= len)
- size = QT_UINT32 (avc_data) - 0x8;
- else
- size = len - 0x8;
-
- if (size < 1)
- /* No real data, so break out */
- break;
-
- switch (QT_FOURCC (avc_data + 0x4)) {
- case FOURCC_avcC:
- {
- /* parse, if found */
- GstBuffer *buf;
-
- GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
-
- /* First 4 bytes are the length of the atom, the next 4 bytes
- * are the fourcc, the next 1 byte is the version, and the
- * subsequent bytes are profile_tier_level structure like data. */
- gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
- avc_data + 8 + 1, size - 1);
- buf = gst_buffer_new_and_alloc (size);
- gst_buffer_fill (buf, 0, avc_data + 0x8, size);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
+ if (esds) {
+ gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
+ stream->stream_tags);
+ } else {
+ switch (fourcc) {
+ case FOURCC_H264:
+ case FOURCC_avc1:
+ case FOURCC_avc3:
+ {
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *avc_data = stsd_entry_data + 0x56;
+
+ /* find avcC */
+ while (len >= 0x8) {
+ gint size;
+
+ if (QT_UINT32 (avc_data) <= len)
+ size = QT_UINT32 (avc_data) - 0x8;
+ else
+ size = len - 0x8;
+ if (size < 1)
+ /* No real data, so break out */
break;
- }
- case FOURCC_strf:
- {
- GstBuffer *buf;
- GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
+ switch (QT_FOURCC (avc_data + 0x4)) {
+ case FOURCC_avcC:
+ {
+ /* parse, if found */
+ GstBuffer *buf;
- /* First 4 bytes are the length of the atom, the next 4 bytes
- * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
- * next 1 byte is the version, and the
- * subsequent bytes are sequence parameter set like data. */
-
- size -= 40; /* we'll be skipping BITMAPINFOHEADER */
- if (size > 1) {
- gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
- avc_data + 8 + 40 + 1, size - 1);
+ GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
+ /* First 4 bytes are the length of the atom, the next 4 bytes
+ * are the fourcc, the next 1 byte is the version, and the
+ * subsequent bytes are profile_tier_level structure like data. */
+ gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
+ avc_data + 8 + 1, size - 1);
buf = gst_buffer_new_and_alloc (size);
- gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
- gst_caps_set_simple (stream->caps,
+ gst_buffer_fill (buf, 0, avc_data + 0x8, size);
+ gst_caps_set_simple (entry->caps,
"codec_data", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf);
- }
- break;
- }
- case FOURCC_btrt:
- {
- guint avg_bitrate, max_bitrate;
- /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
- if (size < 12)
break;
+ }
+ case FOURCC_strf:
+ {
+ GstBuffer *buf;
+
+ GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
+
+ /* First 4 bytes are the length of the atom, the next 4 bytes
+ * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
+ * next 1 byte is the version, and the
+ * subsequent bytes are sequence parameter set like data. */
+
+ size -= 40; /* we'll be skipping BITMAPINFOHEADER */
+ if (size > 1) {
+ gst_codec_utils_h264_caps_set_level_and_profile
+ (entry->caps, avc_data + 8 + 40 + 1, size - 1);
+
+ buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ }
+ break;
+ }
+ case FOURCC_btrt:
+ {
+ guint avg_bitrate, max_bitrate;
+
+ /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
+ if (size < 12)
+ break;
- max_bitrate = QT_UINT32 (avc_data + 0xc);
- avg_bitrate = QT_UINT32 (avc_data + 0x10);
+ max_bitrate = QT_UINT32 (avc_data + 0xc);
+ avg_bitrate = QT_UINT32 (avc_data + 0x10);
- if (!max_bitrate && !avg_bitrate)
- break;
+ if (!max_bitrate && !avg_bitrate)
+ break;
- /* Some muxers seem to swap the average and maximum bitrates
- * (I'm looking at you, YouTube), so we swap for sanity. */
- if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
- guint temp = avg_bitrate;
+ /* Some muxers seem to swap the average and maximum bitrates
+ * (I'm looking at you, YouTube), so we swap for sanity. */
+ if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
+ guint temp = avg_bitrate;
- avg_bitrate = max_bitrate;
- max_bitrate = temp;
- }
+ avg_bitrate = max_bitrate;
+ max_bitrate = temp;
+ }
- if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
- }
- if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_BITRATE, avg_bitrate, NULL);
+ if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
+ gst_tag_list_add (stream->stream_tags,
+ GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
+ max_bitrate, NULL);
+ }
+ if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
+ gst_tag_list_add (stream->stream_tags,
+ GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
+ NULL);
+ }
+
+ break;
}
- break;
+ default:
+ break;
}
- default:
- break;
+ len -= size + 8;
+ avc_data += size + 8;
}
- len -= size + 8;
- avc_data += size + 8;
+ break;
}
+ case FOURCC_H265:
+ case FOURCC_hvc1:
+ case FOURCC_hev1:
+ {
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *hevc_data = stsd_entry_data + 0x56;
+
+ /* find hevc */
+ while (len >= 0x8) {
+ gint size;
+
+ if (QT_UINT32 (hevc_data) <= len)
+ size = QT_UINT32 (hevc_data) - 0x8;
+ else
+ size = len - 0x8;
- break;
- }
- case FOURCC_H265:
- case FOURCC_hvc1:
- case FOURCC_hev1:
- {
- gint len = QT_UINT32 (stsd_entry_data) - 0x56;
- const guint8 *hevc_data = stsd_entry_data + 0x56;
-
- /* find hevc */
- while (len >= 0x8) {
- gint size;
-
- if (QT_UINT32 (hevc_data) <= len)
- size = QT_UINT32 (hevc_data) - 0x8;
- else
- size = len - 0x8;
-
- if (size < 1)
- /* No real data, so break out */
- break;
+ if (size < 1)
+ /* No real data, so break out */
+ break;
- switch (QT_FOURCC (hevc_data + 0x4)) {
- case FOURCC_hvcC:
- {
- /* parse, if found */
- GstBuffer *buf;
+ switch (QT_FOURCC (hevc_data + 0x4)) {
+ case FOURCC_hvcC:
+ {
+ /* parse, if found */
+ GstBuffer *buf;
- GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
+ GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
- /* First 4 bytes are the length of the atom, the next 4 bytes
- * are the fourcc, the next 1 byte is the version, and the
- * subsequent bytes are sequence parameter set like data. */
- gst_codec_utils_h265_caps_set_level_tier_and_profile
- (stream->caps, hevc_data + 8 + 1, size - 1);
+ /* First 4 bytes are the length of the atom, the next 4 bytes
+ * are the fourcc, the next 1 byte is the version, and the
+ * subsequent bytes are sequence parameter set like data. */
+ gst_codec_utils_h265_caps_set_level_tier_and_profile
+ (entry->caps, hevc_data + 8 + 1, size - 1);
- buf = gst_buffer_new_and_alloc (size);
- gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- break;
+ buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
+ len -= size + 8;
+ hevc_data += size + 8;
}
- len -= size + 8;
- hevc_data += size + 8;
+ break;
}
- break;
- }
- case FOURCC_mp4v:
- case FOURCC_MP4V:
- case FOURCC_fmp4:
- case FOURCC_FMP4:
- case FOURCC_xvid:
- case FOURCC_XVID:
- {
- GNode *glbl;
-
- GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
+ case FOURCC_mp4v:
+ case FOURCC_MP4V:
+ case FOURCC_fmp4:
+ case FOURCC_FMP4:
+ case FOURCC_xvid:
+ case FOURCC_XVID:
+ {
+ GNode *glbl;
+
+ GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (fourcc));
- /* codec data might be in glbl extension atom */
- glbl = mp4v ?
- qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
- if (glbl) {
- guint8 *data;
- GstBuffer *buf;
- gint len;
-
- GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
- data = glbl->data;
- len = QT_UINT32 (data);
- if (len > 0x8) {
- len -= 0x8;
- buf = gst_buffer_new_and_alloc (len);
- gst_buffer_fill (buf, 0, data + 8, len);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
+ /* codec data might be in glbl extension atom */
+ glbl = mp4v ?
+ qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
+ if (glbl) {
+ guint8 *data;
+ GstBuffer *buf;
+ gint len;
+
+ GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
+ data = glbl->data;
+ len = QT_UINT32 (data);
+ if (len > 0x8) {
+ len -= 0x8;
+ buf = gst_buffer_new_and_alloc (len);
+ gst_buffer_fill (buf, 0, data + 8, len);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ }
}
- }
- break;
- }
- case FOURCC_mjp2:
- {
- /* see annex I of the jpeg2000 spec */
- GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
- const guint8 *data;
- const gchar *colorspace = NULL;
- gint ncomp = 0;
- guint32 ncomp_map = 0;
- gint32 *comp_map = NULL;
- guint32 nchan_def = 0;
- gint32 *chan_def = NULL;
-
- GST_DEBUG_OBJECT (qtdemux, "found mjp2");
- /* some required atoms */
- mjp2 = qtdemux_tree_get_child_by_index (stsd, 0);
- if (!mjp2)
- break;
- jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
- if (!jp2h)
break;
+ }
+ case FOURCC_mjp2:
+ {
+ /* see annex I of the jpeg2000 spec */
+ GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
+ const guint8 *data;
+ const gchar *colorspace = NULL;
+ gint ncomp = 0;
+ guint32 ncomp_map = 0;
+ gint32 *comp_map = NULL;
+ guint32 nchan_def = 0;
+ gint32 *chan_def = NULL;
+
+ GST_DEBUG_OBJECT (qtdemux, "found mjp2");
+ /* some required atoms */
+ mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
+ if (!mjp2)
+ break;
+ jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
+ if (!jp2h)
+ break;
- /* number of components; redundant with info in codestream, but useful
- to a muxer */
- ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
- if (!ihdr || QT_UINT32 (ihdr->data) != 22)
- break;
- ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
+ /* number of components; redundant with info in codestream, but useful
+ to a muxer */
+ ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
+ if (!ihdr || QT_UINT32 (ihdr->data) != 22)
+ break;
+ ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
- colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
- if (!colr)
- break;
- GST_DEBUG_OBJECT (qtdemux, "found colr");
- /* extract colour space info */
- if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
- switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
- case 16:
- colorspace = "sRGB";
- break;
- case 17:
- colorspace = "GRAY";
- break;
- case 18:
- colorspace = "sYUV";
- break;
- default:
- colorspace = NULL;
- break;
+ colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
+ if (!colr)
+ break;
+ GST_DEBUG_OBJECT (qtdemux, "found colr");
+ /* extract colour space info */
+ if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
+ switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
+ case 16:
+ colorspace = "sRGB";
+ break;
+ case 17:
+ colorspace = "GRAY";
+ break;
+ case 18:
+ colorspace = "sYUV";
+ break;
+ default:
+ colorspace = NULL;
+ break;
+ }
}
- }
- if (!colorspace)
- /* colr is required, and only values 16, 17, and 18 are specified,
- so error if we have no colorspace */
- break;
+ if (!colorspace)
+ /* colr is required, and only values 16, 17, and 18 are specified,
+ so error if we have no colorspace */
+ break;
- /* extract component mapping */
- cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
- if (cmap) {
- guint32 cmap_len = 0;
- int i;
- cmap_len = QT_UINT32 (cmap->data);
- if (cmap_len >= 8) {
- /* normal box, subtract off header */
- cmap_len -= 8;
- /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
- if (cmap_len % 4 == 0) {
- ncomp_map = (cmap_len / 4);
- comp_map = g_new0 (gint32, ncomp_map);
- for (i = 0; i < ncomp_map; i++) {
- guint16 cmp;
- guint8 mtyp, pcol;
- cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
- mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
- pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
- comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
+ /* extract component mapping */
+ cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
+ if (cmap) {
+ guint32 cmap_len = 0;
+ int i;
+ cmap_len = QT_UINT32 (cmap->data);
+ if (cmap_len >= 8) {
+ /* normal box, subtract off header */
+ cmap_len -= 8;
+ /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
+ if (cmap_len % 4 == 0) {
+ ncomp_map = (cmap_len / 4);
+ comp_map = g_new0 (gint32, ncomp_map);
+ for (i = 0; i < ncomp_map; i++) {
+ guint16 cmp;
+ guint8 mtyp, pcol;
+ cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
+ mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
+ pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
+ comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
+ }
}
}
}
- }
- /* extract channel definitions */
- cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
- if (cdef) {
- guint32 cdef_len = 0;
- int i;
- cdef_len = QT_UINT32 (cdef->data);
- if (cdef_len >= 10) {
- /* normal box, subtract off header and len */
- cdef_len -= 10;
- /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
- if (cdef_len % 6 == 0) {
- nchan_def = (cdef_len / 6);
- chan_def = g_new0 (gint32, nchan_def);
- for (i = 0; i < nchan_def; i++)
- chan_def[i] = -1;
- for (i = 0; i < nchan_def; i++) {
- guint16 cn, typ, asoc;
- cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
- typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
- asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
- if (cn < nchan_def) {
- switch (typ) {
- case 0:
- chan_def[cn] = asoc;
- break;
- case 1:
- chan_def[cn] = 0; /* alpha */
- break;
- default:
- chan_def[cn] = -typ;
+ /* extract channel definitions */
+ cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
+ if (cdef) {
+ guint32 cdef_len = 0;
+ int i;
+ cdef_len = QT_UINT32 (cdef->data);
+ if (cdef_len >= 10) {
+ /* normal box, subtract off header and len */
+ cdef_len -= 10;
+ /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
+ if (cdef_len % 6 == 0) {
+ nchan_def = (cdef_len / 6);
+ chan_def = g_new0 (gint32, nchan_def);
+ for (i = 0; i < nchan_def; i++)
+ chan_def[i] = -1;
+ for (i = 0; i < nchan_def; i++) {
+ guint16 cn, typ, asoc;
+ cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
+ typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
+ asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
+ if (cn < nchan_def) {
+ switch (typ) {
+ case 0:
+ chan_def[cn] = asoc;
+ break;
+ case 1:
+ chan_def[cn] = 0; /* alpha */
+ break;
+ default:
+ chan_def[cn] = -typ;
+ }
}
}
}
}
}
- }
- gst_caps_set_simple (stream->caps,
- "num-components", G_TYPE_INT, ncomp, NULL);
- gst_caps_set_simple (stream->caps,
- "colorspace", G_TYPE_STRING, colorspace, NULL);
-
- if (comp_map) {
- GValue arr = { 0, };
- GValue elt = { 0, };
- int i;
- g_value_init (&arr, GST_TYPE_ARRAY);
- g_value_init (&elt, G_TYPE_INT);
- for (i = 0; i < ncomp_map; i++) {
- g_value_set_int (&elt, comp_map[i]);
- gst_value_array_append_value (&arr, &elt);
+ gst_caps_set_simple (entry->caps,
+ "num-components", G_TYPE_INT, ncomp, NULL);
+ gst_caps_set_simple (entry->caps,
+ "colorspace", G_TYPE_STRING, colorspace, NULL);
+
+ if (comp_map) {
+ GValue arr = { 0, };
+ GValue elt = { 0, };
+ int i;
+ g_value_init (&arr, GST_TYPE_ARRAY);
+ g_value_init (&elt, G_TYPE_INT);
+ for (i = 0; i < ncomp_map; i++) {
+ g_value_set_int (&elt, comp_map[i]);
+ gst_value_array_append_value (&arr, &elt);
+ }
+ gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
+ "component-map", &arr);
+ g_value_unset (&elt);
+ g_value_unset (&arr);
+ g_free (comp_map);
}
- gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
- "component-map", &arr);
- g_value_unset (&elt);
- g_value_unset (&arr);
- g_free (comp_map);
- }
- if (chan_def) {
- GValue arr = { 0, };
- GValue elt = { 0, };
- int i;
- g_value_init (&arr, GST_TYPE_ARRAY);
- g_value_init (&elt, G_TYPE_INT);
- for (i = 0; i < nchan_def; i++) {
- g_value_set_int (&elt, chan_def[i]);
- gst_value_array_append_value (&arr, &elt);
+ if (chan_def) {
+ GValue arr = { 0, };
+ GValue elt = { 0, };
+ int i;
+ g_value_init (&arr, GST_TYPE_ARRAY);
+ g_value_init (&elt, G_TYPE_INT);
+ for (i = 0; i < nchan_def; i++) {
+ g_value_set_int (&elt, chan_def[i]);
+ gst_value_array_append_value (&arr, &elt);
+ }
+ gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
+ "channel-definitions", &arr);
+ g_value_unset (&elt);
+ g_value_unset (&arr);
+ g_free (chan_def);
}
- gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
- "channel-definitions", &arr);
- g_value_unset (&elt);
- g_value_unset (&arr);
- g_free (chan_def);
- }
- /* some optional atoms */
- field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
- prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
+ /* some optional atoms */
+ field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
+ prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
- /* indicate possible fields in caps */
- if (field) {
- data = (guint8 *) field->data + 8;
- if (*data != 1)
- gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
- (gint) * data, NULL);
+ /* indicate possible fields in caps */
+ if (field) {
+ data = (guint8 *) field->data + 8;
+ if (*data != 1)
+ gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
+ (gint) * data, NULL);
+ }
+ /* add codec_data if provided */
+ if (prefix) {
+ GstBuffer *buf;
+ gint len;
+
+ GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
+ data = prefix->data;
+ len = QT_UINT32 (data);
+ if (len > 0x8) {
+ len -= 0x8;
+ buf = gst_buffer_new_and_alloc (len);
+ gst_buffer_fill (buf, 0, data + 8, len);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ }
+ }
+ break;
}
- /* add codec_data if provided */
- if (prefix) {
+ case FOURCC_SVQ3:
+ case FOURCC_VP31:
+ {
GstBuffer *buf;
- gint len;
-
- GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
- data = prefix->data;
- len = QT_UINT32 (data);
- if (len > 0x8) {
- len -= 0x8;
- buf = gst_buffer_new_and_alloc (len);
- gst_buffer_fill (buf, 0, data + 8, len);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
+ GstBuffer *seqh = NULL;
+ 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_entry_data, &gamma_data,
+ &seqh);
+ if (gamma_data) {
+ gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
+ QT_FP32 (gamma_data), NULL);
}
- }
- break;
- }
- case FOURCC_jpeg:
- {
- /* https://developer.apple.com/standards/qtff-2001.pdf,
- * page 92, "Video Sample Description", under table 3.1 */
- GstByteReader br;
-
- const gint compressor_offset = 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
- const gint min_size = compressor_offset + 32 + 2 + 2;
- GNode *jpeg;
- guint32 len;
- guint16 color_table_id = 0;
- gboolean ok;
-
- GST_DEBUG_OBJECT (qtdemux, "found jpeg");
-
- /* recover information on interlaced/progressive */
- jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
- if (!jpeg)
+ if (seqh) {
+ /* sorry for the bad name, but we don't know what this is, other
+ * than its own fourcc */
+ gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
+ NULL);
+ gst_buffer_unref (seqh);
+ }
+
+ GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
+ buf = gst_buffer_new_and_alloc (len);
+ gst_buffer_fill (buf, 0, stsd_data, len);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
break;
+ }
+ case FOURCC_jpeg:
+ {
+ /* https://developer.apple.com/standards/qtff-2001.pdf,
+ * page 92, "Video Sample Description", under table 3.1 */
+ GstByteReader br;
- len = QT_UINT32 (jpeg->data);
- GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
- min_size);
- if (len >= min_size) {
- gst_byte_reader_init (&br, jpeg->data, len);
-
- gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
- gst_byte_reader_get_uint16_le (&br, &color_table_id);
- if (color_table_id != 0) {
- /* the spec says there can be concatenated chunks in the data, and we want
- * to find one called field. Walk through them. */
- gint offset = min_size;
- while (offset + 8 < len) {
- guint32 size = 0, tag;
- ok = gst_byte_reader_get_uint32_le (&br, &size);
- ok &= gst_byte_reader_get_uint32_le (&br, &tag);
- if (!ok || size < 8) {
- GST_WARNING_OBJECT (qtdemux,
- "Failed to walk optional chunk list");
- break;
- }
- GST_DEBUG_OBJECT (qtdemux,
- "Found optional %4.4s chunk, size %u", (const char *) &tag,
- size);
- if (tag == FOURCC_fiel) {
- guint8 n_fields, ordering;
- gst_byte_reader_get_uint8 (&br, &n_fields);
- gst_byte_reader_get_uint8 (&br, &ordering);
- if (n_fields == 1 || n_fields == 2) {
- GST_DEBUG_OBJECT (qtdemux,
- "Found fiel tag with %u fields, ordering %u", n_fields,
- ordering);
- if (n_fields == 2)
- gst_caps_set_simple (stream->caps, "interlace-mode",
- G_TYPE_STRING, "interleaved", NULL);
- } else {
+ const gint compressor_offset =
+ 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
+ const gint min_size = compressor_offset + 32 + 2 + 2;
+ GNode *jpeg;
+ guint32 len;
+ guint16 color_table_id = 0;
+ gboolean ok;
+
+ GST_DEBUG_OBJECT (qtdemux, "found jpeg");
+
+ /* recover information on interlaced/progressive */
+ jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
+ if (!jpeg)
+ break;
+
+ len = QT_UINT32 (jpeg->data);
+ GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
+ min_size);
+ if (len >= min_size) {
+ gst_byte_reader_init (&br, jpeg->data, len);
+
+ gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
+ gst_byte_reader_get_uint16_le (&br, &color_table_id);
+ if (color_table_id != 0) {
+ /* the spec says there can be concatenated chunks in the data, and we want
+ * to find one called field. Walk through them. */
+ gint offset = min_size;
+ while (offset + 8 < len) {
+ guint32 size = 0, tag;
+ ok = gst_byte_reader_get_uint32_le (&br, &size);
+ ok &= gst_byte_reader_get_uint32_le (&br, &tag);
+ if (!ok || size < 8) {
GST_WARNING_OBJECT (qtdemux,
- "Found fiel tag with invalid fields (%u)", n_fields);
+ "Failed to walk optional chunk list");
+ break;
}
+ GST_DEBUG_OBJECT (qtdemux,
+ "Found optional %4.4s chunk, size %u",
+ (const char *) &tag, size);
+ if (tag == FOURCC_fiel) {
+ guint8 n_fields = 0, ordering = 0;
+ gst_byte_reader_get_uint8 (&br, &n_fields);
+ gst_byte_reader_get_uint8 (&br, &ordering);
+ if (n_fields == 1 || n_fields == 2) {
+ GST_DEBUG_OBJECT (qtdemux,
+ "Found fiel tag with %u fields, ordering %u",
+ n_fields, ordering);
+ if (n_fields == 2)
+ gst_caps_set_simple (CUR_STREAM (stream)->caps,
+ "interlace-mode", G_TYPE_STRING, "interleaved",
+ NULL);
+ } else {
+ GST_WARNING_OBJECT (qtdemux,
+ "Found fiel tag with invalid fields (%u)", n_fields);
+ }
+ }
+ offset += size;
}
- offset += size;
+ } else {
+ GST_DEBUG_OBJECT (qtdemux,
+ "Color table ID is 0, not trying to get interlacedness");
}
} else {
- GST_DEBUG_OBJECT (qtdemux,
- "Color table ID is 0, not trying to get interlacedness");
+ GST_WARNING_OBJECT (qtdemux,
+ "Length of jpeg chunk is too small, not trying to get interlacedness");
}
- } else {
- GST_WARNING_OBJECT (qtdemux,
- "Length of jpeg chunk is too small, not trying to get interlacedness");
- }
- break;
- }
- case FOURCC_SVQ3:
- case FOURCC_VP31:
- {
- GstBuffer *buf;
- GstBuffer *seqh = NULL;
- 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_entry_data, &gamma_data,
- &seqh);
- if (gamma_data) {
- gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
- QT_FP32 (gamma_data), NULL);
+ break;
}
- if (seqh) {
- /* sorry for the bad name, but we don't know what this is, other
- * than its own fourcc */
- gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
+ case FOURCC_rle_:
+ case FOURCC_WRLE:
+ {
+ gst_caps_set_simple (entry->caps,
+ "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 82),
NULL);
- gst_buffer_unref (seqh);
+ break;
}
+ case FOURCC_XiTh:
+ {
+ GNode *xith, *xdxt;
- GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
- buf = gst_buffer_new_and_alloc (len);
- gst_buffer_fill (buf, 0, stsd_data, len);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- break;
- }
- case FOURCC_rle_:
- case FOURCC_WRLE:
- {
- gst_caps_set_simple (stream->caps,
- "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
- NULL);
- break;
- }
- case FOURCC_XiTh:
- {
- GNode *xith, *xdxt;
+ GST_DEBUG_OBJECT (qtdemux, "found XiTh");
+ xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
+ if (!xith)
+ break;
- GST_DEBUG_OBJECT (qtdemux, "found XiTh");
- xith = qtdemux_tree_get_child_by_index (stsd, 0);
- if (!xith)
- break;
+ xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
+ if (!xdxt)
+ break;
- xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
- if (!xdxt)
+ GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
+ /* collect the headers and store them in a stream list so that we can
+ * send them out first */
+ qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
break;
+ }
+ case FOURCC_ovc1:
+ {
+ GNode *ovc1;
+ guint8 *ovc1_data;
+ guint ovc1_len;
+ GstBuffer *buf;
- GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
- /* collect the headers and store them in a stream list so that we can
- * send them out first */
- qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
- break;
- }
- case FOURCC_ovc1:
- {
- GNode *ovc1;
- guint8 *ovc1_data;
- guint ovc1_len;
- GstBuffer *buf;
-
- GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
- ovc1 = qtdemux_tree_get_child_by_index (stsd, 0);
- if (!ovc1)
- break;
- ovc1_data = ovc1->data;
- ovc1_len = QT_UINT32 (ovc1_data);
- if (ovc1_len <= 198) {
- GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
+ GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
+ ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
+ if (!ovc1)
+ break;
+ ovc1_data = ovc1->data;
+ ovc1_len = QT_UINT32 (ovc1_data);
+ if (ovc1_len <= 198) {
+ GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
+ break;
+ }
+ buf = gst_buffer_new_and_alloc (ovc1_len - 198);
+ gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
break;
}
- buf = gst_buffer_new_and_alloc (ovc1_len - 198);
- gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- break;
- }
- case FOURCC_vc_1:
- {
- gint len = QT_UINT32 (stsd_entry_data) - 0x56;
- const guint8 *vc1_data = stsd_entry_data + 0x56;
+ case FOURCC_vc_1:
+ {
+ gint len = QT_UINT32 (stsd_entry_data) - 0x56;
+ const guint8 *vc1_data = stsd_entry_data + 0x56;
- /* find dvc1 */
- while (len >= 8) {
- gint size;
+ /* find dvc1 */
+ while (len >= 8) {
+ gint size;
- if (QT_UINT32 (vc1_data) <= len)
- size = QT_UINT32 (vc1_data) - 8;
- else
- size = len - 8;
+ if (QT_UINT32 (vc1_data) <= len)
+ size = QT_UINT32 (vc1_data) - 8;
+ else
+ size = len - 8;
- if (size < 1)
- /* No real data, so break out */
- break;
+ if (size < 1)
+ /* No real data, so break out */
+ break;
- switch (QT_FOURCC (vc1_data + 0x4)) {
- case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
- {
- GstBuffer *buf;
+ switch (QT_FOURCC (vc1_data + 0x4)) {
+ case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
+ {
+ GstBuffer *buf;
- GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
- buf = gst_buffer_new_and_alloc (size);
- gst_buffer_fill (buf, 0, vc1_data + 8, size);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- break;
+ GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
+ buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (buf, 0, vc1_data + 8, size);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
+ len -= size + 8;
+ vc1_data += size + 8;
}
- len -= size + 8;
- vc1_data += size + 8;
+ break;
}
- break;
+ default:
+ break;
}
- default:
- break;
}
- }
- GST_INFO_OBJECT (qtdemux,
- "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
- GST_FOURCC_ARGS (fourcc), stream->caps);
-
- } else if (stream->subtype == FOURCC_soun) {
- int version, samplesize;
- guint16 compression_id;
- gboolean amrwb = FALSE;
+ GST_INFO_OBJECT (qtdemux,
+ "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
+ GST_FOURCC_ARGS (fourcc), entry->caps);
- offset = 16;
- /* sample description entry (16) + sound sample description v0 (20) */
- if (len < 36)
- goto corrupt_file;
+ } else if (stream->subtype == FOURCC_soun) {
+ int version, samplesize;
+ guint16 compression_id;
+ gboolean amrwb = FALSE;
- 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_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_entry_data + offset + 14));
- GST_LOG_OBJECT (qtdemux, "sample rate: %g", stream->rate);
-
- if (compression_id == 0xfffe)
- stream->sampled = TRUE;
-
- /* first assume uncompressed audio */
- stream->bytes_per_sample = samplesize / 8;
- stream->samples_per_frame = stream->n_channels;
- stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
- stream->samples_per_packet = stream->samples_per_frame;
- stream->bytes_per_packet = stream->bytes_per_sample;
-
- offset = 36;
- switch (fourcc) {
- /* Yes, these have to be hard-coded */
- case FOURCC_MAC6:
- {
- stream->samples_per_packet = 6;
- stream->bytes_per_packet = 1;
- stream->bytes_per_frame = 1 * stream->n_channels;
- stream->bytes_per_sample = 1;
- stream->samples_per_frame = 6 * stream->n_channels;
- break;
- }
- case FOURCC_MAC3:
- {
- stream->samples_per_packet = 3;
- stream->bytes_per_packet = 1;
- stream->bytes_per_frame = 1 * stream->n_channels;
- stream->bytes_per_sample = 1;
- stream->samples_per_frame = 3 * stream->n_channels;
- break;
- }
- case FOURCC_ima4:
- {
- stream->samples_per_packet = 64;
- stream->bytes_per_packet = 34;
- stream->bytes_per_frame = 34 * stream->n_channels;
- stream->bytes_per_sample = 2;
- stream->samples_per_frame = 64 * stream->n_channels;
- break;
- }
- case FOURCC_ulaw:
- case FOURCC_alaw:
- {
- stream->samples_per_packet = 1;
- stream->bytes_per_packet = 1;
- stream->bytes_per_frame = 1 * stream->n_channels;
- stream->bytes_per_sample = 1;
- stream->samples_per_frame = 1 * stream->n_channels;
- break;
- }
- case FOURCC_agsm:
- {
- stream->samples_per_packet = 160;
- stream->bytes_per_packet = 33;
- stream->bytes_per_frame = 33 * stream->n_channels;
- stream->bytes_per_sample = 2;
- stream->samples_per_frame = 160 * stream->n_channels;
- break;
- }
- default:
- break;
- }
-
- if (version == 0x00010000) {
- /* sample description entry (16) + sound sample description v1 (20+16) */
- if (len < 52)
+ offset = 16;
+ /* sample description entry (16) + sound sample description v0 (20) */
+ if (len < 36)
goto corrupt_file;
+ version = QT_UINT32 (stsd_entry_data + offset);
+ entry->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);
+ entry->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_entry_data + offset + 4));
+ GST_LOG_OBJECT (qtdemux, "n_channels: %d", entry->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_entry_data + offset + 14));
+ GST_LOG_OBJECT (qtdemux, "sample rate: %g", entry->rate);
+
+ if (compression_id == 0xfffe)
+ entry->sampled = TRUE;
+
+ /* first assume uncompressed audio */
+ entry->bytes_per_sample = samplesize / 8;
+ entry->samples_per_frame = entry->n_channels;
+ entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
+ entry->samples_per_packet = entry->samples_per_frame;
+ entry->bytes_per_packet = entry->bytes_per_sample;
+
+ offset = 36;
switch (fourcc) {
- case FOURCC_twos:
- case FOURCC_sowt:
- case FOURCC_raw_:
+ /* Yes, these have to be hard-coded */
+ case FOURCC_MAC6:
+ {
+ entry->samples_per_packet = 6;
+ entry->bytes_per_packet = 1;
+ entry->bytes_per_frame = 1 * entry->n_channels;
+ entry->bytes_per_sample = 1;
+ entry->samples_per_frame = 6 * entry->n_channels;
break;
- default:
+ }
+ case FOURCC_MAC3:
{
- /* only parse extra decoding config for non-pcm audio */
- 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);
- GST_LOG_OBJECT (qtdemux, "bytes/packet: %d",
- stream->bytes_per_packet);
- GST_LOG_OBJECT (qtdemux, "bytes/frame: %d",
- stream->bytes_per_frame);
- GST_LOG_OBJECT (qtdemux, "bytes/sample: %d",
- stream->bytes_per_sample);
-
- if (!stream->sampled && stream->bytes_per_packet) {
- stream->samples_per_frame = (stream->bytes_per_frame /
- stream->bytes_per_packet) * stream->samples_per_packet;
- GST_LOG_OBJECT (qtdemux, "samples/frame: %d",
- stream->samples_per_frame);
- }
+ entry->samples_per_packet = 3;
+ entry->bytes_per_packet = 1;
+ entry->bytes_per_frame = 1 * entry->n_channels;
+ entry->bytes_per_sample = 1;
+ entry->samples_per_frame = 3 * entry->n_channels;
+ break;
+ }
+ case FOURCC_ima4:
+ {
+ entry->samples_per_packet = 64;
+ entry->bytes_per_packet = 34;
+ entry->bytes_per_frame = 34 * entry->n_channels;
+ entry->bytes_per_sample = 2;
+ entry->samples_per_frame = 64 * entry->n_channels;
break;
}
+ case FOURCC_ulaw:
+ case FOURCC_alaw:
+ {
+ entry->samples_per_packet = 1;
+ entry->bytes_per_packet = 1;
+ entry->bytes_per_frame = 1 * entry->n_channels;
+ entry->bytes_per_sample = 1;
+ entry->samples_per_frame = 1 * entry->n_channels;
+ break;
+ }
+ case FOURCC_agsm:
+ {
+ entry->samples_per_packet = 160;
+ entry->bytes_per_packet = 33;
+ entry->bytes_per_frame = 33 * entry->n_channels;
+ entry->bytes_per_sample = 2;
+ entry->samples_per_frame = 160 * entry->n_channels;
+ break;
+ }
+ default:
+ break;
}
- } else if (version == 0x00020000) {
- union
- {
- gdouble fp;
- guint64 val;
- } qtfp;
- /* sample description entry (16) + sound sample description v2 (56) */
- if (len < 72)
- goto corrupt_file;
+ if (version == 0x00010000) {
+ /* sample description entry (16) + sound sample description v1 (20+16) */
+ if (len < 52)
+ goto corrupt_file;
- qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
- stream->rate = qtfp.fp;
- stream->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
+ switch (fourcc) {
+ case FOURCC_twos:
+ case FOURCC_sowt:
+ case FOURCC_raw_:
+ break;
+ default:
+ {
+ /* only parse extra decoding config for non-pcm audio */
+ entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
+ entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
+ entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
+ entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
+
+ GST_LOG_OBJECT (qtdemux, "samples/packet: %d",
+ entry->samples_per_packet);
+ GST_LOG_OBJECT (qtdemux, "bytes/packet: %d",
+ entry->bytes_per_packet);
+ GST_LOG_OBJECT (qtdemux, "bytes/frame: %d",
+ entry->bytes_per_frame);
+ GST_LOG_OBJECT (qtdemux, "bytes/sample: %d",
+ entry->bytes_per_sample);
+
+ if (!entry->sampled && entry->bytes_per_packet) {
+ entry->samples_per_frame = (entry->bytes_per_frame /
+ entry->bytes_per_packet) * entry->samples_per_packet;
+ GST_LOG_OBJECT (qtdemux, "samples/frame: %d",
+ entry->samples_per_frame);
+ }
+ break;
+ }
+ }
+ } else if (version == 0x00020000) {
+ union
+ {
+ gdouble fp;
+ guint64 val;
+ } qtfp;
- 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_entry_data + offset + 20));
- GST_LOG_OBJECT (qtdemux, "format flags: %X",
- QT_UINT32 (stsd_entry_data + offset + 24));
- GST_LOG_OBJECT (qtdemux, "bytes/packet: %d",
- QT_UINT32 (stsd_entry_data + offset + 28));
- GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
- QT_UINT32 (stsd_entry_data + offset + 32));
- } else if (version != 0x00000) {
- GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
- }
+ /* sample description entry (16) + sound sample description v2 (56) */
+ if (len < 72)
+ goto corrupt_file;
- if (stream->caps)
- gst_caps_unref (stream->caps);
+ qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
+ entry->rate = qtfp.fp;
+ entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
- stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
- stsd_entry_data + 32, len - 16, &codec);
+ GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
+ GST_LOG_OBJECT (qtdemux, "sample rate: %g", entry->rate);
+ GST_LOG_OBJECT (qtdemux, "n_channels: %d", entry->n_channels);
+ GST_LOG_OBJECT (qtdemux, "bits/channel: %d",
+ QT_UINT32 (stsd_entry_data + offset + 20));
+ GST_LOG_OBJECT (qtdemux, "format flags: %X",
+ QT_UINT32 (stsd_entry_data + offset + 24));
+ GST_LOG_OBJECT (qtdemux, "bytes/packet: %d",
+ QT_UINT32 (stsd_entry_data + offset + 28));
+ GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
+ QT_UINT32 (stsd_entry_data + offset + 32));
+ } else if (version != 0x00000) {
+ GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
+ version);
+ }
- switch (fourcc) {
- case FOURCC_in24:
- {
- GNode *enda;
- GNode *in24;
+ if (entry->caps)
+ gst_caps_unref (entry->caps);
- in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
+ entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
+ stsd_entry_data + 32, len - 16, &codec);
- enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
- if (!enda) {
- wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
- if (wave)
- enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
- }
- if (enda) {
- int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
- gst_caps_set_simple (stream->caps,
- "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
- }
- break;
- }
- case FOURCC_owma:
- {
- const guint8 *owma_data;
- const gchar *codec_name = NULL;
- guint owma_len;
- GstBuffer *buf;
- gint version = 1;
- /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
- /* FIXME this should also be gst_riff_strf_auds,
- * but the latter one is actually missing bits-per-sample :( */
- typedef struct
+ switch (fourcc) {
+ case FOURCC_in24:
{
- gint16 wFormatTag;
- gint16 nChannels;
- gint32 nSamplesPerSec;
- gint32 nAvgBytesPerSec;
- gint16 nBlockAlign;
- gint16 wBitsPerSample;
- gint16 cbSize;
- } WAVEFORMATEX;
- WAVEFORMATEX *wfex;
-
- GST_DEBUG_OBJECT (qtdemux, "parse owma");
- owma_data = stsd_entry_data;
- owma_len = QT_UINT32 (owma_data);
- if (owma_len <= 54) {
- GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
+ GNode *enda;
+ GNode *in24;
+
+ in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
+
+ enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
+ if (!enda) {
+ wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
+ if (wave)
+ enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
+ }
+ if (enda) {
+ int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
+ gst_caps_set_simple (entry->caps,
+ "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
+ NULL);
+ }
break;
}
- wfex = (WAVEFORMATEX *) (owma_data + 36);
- buf = gst_buffer_new_and_alloc (owma_len - 54);
- gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
- if (wfex->wFormatTag == 0x0161) {
- codec_name = "Windows Media Audio";
- version = 2;
- } else if (wfex->wFormatTag == 0x0162) {
- codec_name = "Windows Media Audio 9 Pro";
- version = 3;
- } else if (wfex->wFormatTag == 0x0163) {
- codec_name = "Windows Media Audio 9 Lossless";
- /* is that correct? gstffmpegcodecmap.c is missing it, but
- * fluendo codec seems to support it */
- version = 4;
- }
+ case FOURCC_owma:
+ {
+ const guint8 *owma_data;
+ const gchar *codec_name = NULL;
+ guint owma_len;
+ GstBuffer *buf;
+ gint version = 1;
+ /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
+ /* FIXME this should also be gst_riff_strf_auds,
+ * but the latter one is actually missing bits-per-sample :( */
+ typedef struct
+ {
+ gint16 wFormatTag;
+ gint16 nChannels;
+ gint32 nSamplesPerSec;
+ gint32 nAvgBytesPerSec;
+ gint16 nBlockAlign;
+ gint16 wBitsPerSample;
+ gint16 cbSize;
+ } WAVEFORMATEX;
+ WAVEFORMATEX *wfex;
+
+ GST_DEBUG_OBJECT (qtdemux, "parse owma");
+ owma_data = stsd_entry_data;
+ owma_len = QT_UINT32 (owma_data);
+ if (owma_len <= 54) {
+ GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
+ break;
+ }
+ wfex = (WAVEFORMATEX *) (owma_data + 36);
+ buf = gst_buffer_new_and_alloc (owma_len - 54);
+ gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
+ if (wfex->wFormatTag == 0x0161) {
+ codec_name = "Windows Media Audio";
+ version = 2;
+ } else if (wfex->wFormatTag == 0x0162) {
+ codec_name = "Windows Media Audio 9 Pro";
+ version = 3;
+ } else if (wfex->wFormatTag == 0x0163) {
+ codec_name = "Windows Media Audio 9 Lossless";
+ /* is that correct? gstffmpegcodecmap.c is missing it, but
+ * fluendo codec seems to support it */
+ version = 4;
+ }
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf,
- "wmaversion", G_TYPE_INT, version,
- "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
- "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
- "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
- "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
- NULL);
- gst_buffer_unref (buf);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf,
+ "wmaversion", G_TYPE_INT, version,
+ "block_align", G_TYPE_INT,
+ GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
+ GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
+ GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
+ GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
+ gst_buffer_unref (buf);
- if (codec_name) {
- g_free (codec);
- codec = g_strdup (codec_name);
+ if (codec_name) {
+ g_free (codec);
+ codec = g_strdup (codec_name);
+ }
+ break;
}
- break;
- }
- case FOURCC_wma_:
- {
- 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 */
- /* FIXME this should also be gst_riff_strf_auds,
- * but the latter one is actually missing bits-per-sample :( */
- typedef struct
+ case FOURCC_wma_:
{
- gint16 wFormatTag;
- gint16 nChannels;
- gint32 nSamplesPerSec;
- gint32 nAvgBytesPerSec;
- gint16 nBlockAlign;
- gint16 wBitsPerSample;
- gint16 cbSize;
- } WAVEFORMATEX;
- WAVEFORMATEX wfex;
-
- /* FIXME: unify with similar wavformatex parsing code above */
- GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
-
- /* find wfex */
- while (len >= 8) {
- gint size;
-
- if (QT_UINT32 (wfex_data) <= len)
- size = QT_UINT32 (wfex_data) - 8;
- else
- size = len - 8;
+ 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 */
+ /* FIXME this should also be gst_riff_strf_auds,
+ * but the latter one is actually missing bits-per-sample :( */
+ typedef struct
+ {
+ gint16 wFormatTag;
+ gint16 nChannels;
+ gint32 nSamplesPerSec;
+ gint32 nAvgBytesPerSec;
+ gint16 nBlockAlign;
+ gint16 wBitsPerSample;
+ gint16 cbSize;
+ } WAVEFORMATEX;
+ WAVEFORMATEX wfex;
+
+ /* FIXME: unify with similar wavformatex parsing code above */
+ GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
+
+ /* find wfex */
+ while (len >= 8) {
+ gint size;
- if (size < 1)
- /* No real data, so break out */
- break;
+ if (QT_UINT32 (wfex_data) <= len)
+ size = QT_UINT32 (wfex_data) - 8;
+ else
+ size = len - 8;
- switch (QT_FOURCC (wfex_data + 4)) {
- case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
- {
- GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
+ if (size < 1)
+ /* No real data, so break out */
+ break;
- if (size < 8 + 18)
- break;
+ switch (QT_FOURCC (wfex_data + 4)) {
+ case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
+ {
+ GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
- wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
- wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
- wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
- wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
- wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
- wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
- wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
-
- GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
- GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
- "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
- "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
- wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
- wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
-
- if (wfex.wFormatTag == 0x0161) {
- codec_name = "Windows Media Audio";
- version = 2;
- } else if (wfex.wFormatTag == 0x0162) {
- codec_name = "Windows Media Audio 9 Pro";
- version = 3;
- } else if (wfex.wFormatTag == 0x0163) {
- codec_name = "Windows Media Audio 9 Lossless";
- /* is that correct? gstffmpegcodecmap.c is missing it, but
- * fluendo codec seems to support it */
- version = 4;
- }
+ if (size < 8 + 18)
+ break;
- gst_caps_set_simple (stream->caps,
- "wmaversion", G_TYPE_INT, version,
- "block_align", G_TYPE_INT, wfex.nBlockAlign,
- "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
- "width", G_TYPE_INT, wfex.wBitsPerSample,
- "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
+ wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
+ wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
+ wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
+ wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
+ wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
+ wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
+ wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
+
+ GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
+ GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
+ "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
+ "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
+ wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
+ wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
+
+ if (wfex.wFormatTag == 0x0161) {
+ codec_name = "Windows Media Audio";
+ version = 2;
+ } else if (wfex.wFormatTag == 0x0162) {
+ codec_name = "Windows Media Audio 9 Pro";
+ version = 3;
+ } else if (wfex.wFormatTag == 0x0163) {
+ codec_name = "Windows Media Audio 9 Lossless";
+ /* is that correct? gstffmpegcodecmap.c is missing it, but
+ * fluendo codec seems to support it */
+ version = 4;
+ }
- if (size > wfex.cbSize) {
- GstBuffer *buf;
+ gst_caps_set_simple (entry->caps,
+ "wmaversion", G_TYPE_INT, version,
+ "block_align", G_TYPE_INT, wfex.nBlockAlign,
+ "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
+ "width", G_TYPE_INT, wfex.wBitsPerSample,
+ "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
- buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
- gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
- size - wfex.cbSize);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- } else {
- GST_WARNING_OBJECT (qtdemux, "no codec data");
- }
+ if (size > wfex.cbSize) {
+ GstBuffer *buf;
- if (codec_name) {
- g_free (codec);
- codec = g_strdup (codec_name);
+ buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
+ gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
+ size - wfex.cbSize);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ } else {
+ GST_WARNING_OBJECT (qtdemux, "no codec data");
+ }
+
+ if (codec_name) {
+ g_free (codec);
+ codec = g_strdup (codec_name);
+ }
+ break;
}
- break;
+ default:
+ break;
}
- default:
- break;
+ len -= size + 8;
+ wfex_data += size + 8;
}
- len -= size + 8;
- wfex_data += size + 8;
- }
- break;
- }
- case FOURCC_opus:
- {
- const guint8 *opus_data;
- guint8 *channel_mapping = NULL;
- guint32 rate;
- guint8 channels;
- guint8 channel_mapping_family;
- guint8 stream_count;
- guint8 coupled_count;
- guint8 i;
-
- opus_data = stsd_entry_data;
-
- channels = GST_READ_UINT8 (opus_data + 45);
- rate = GST_READ_UINT32_LE (opus_data + 48);
- channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
- stream_count = GST_READ_UINT8 (opus_data + 55);
- coupled_count = GST_READ_UINT8 (opus_data + 56);
-
- if (channels > 0) {
- channel_mapping = g_malloc (channels * sizeof (guint8));
- for (i = 0; i < channels; i++)
- channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
+ break;
}
+ case FOURCC_opus:
+ {
+ const guint8 *opus_data;
+ guint8 *channel_mapping = NULL;
+ guint32 rate;
+ guint8 channels;
+ guint8 channel_mapping_family;
+ guint8 stream_count;
+ guint8 coupled_count;
+ guint8 i;
+
+ opus_data = stsd_entry_data;
+
+ channels = GST_READ_UINT8 (opus_data + 45);
+ rate = GST_READ_UINT32_LE (opus_data + 48);
+ channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
+ stream_count = GST_READ_UINT8 (opus_data + 55);
+ coupled_count = GST_READ_UINT8 (opus_data + 56);
+
+ if (channels > 0) {
+ channel_mapping = g_malloc (channels * sizeof (guint8));
+ for (i = 0; i < channels; i++)
+ channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
+ }
- stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
- channel_mapping_family, stream_count, coupled_count,
- channel_mapping);
- break;
+ entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
+ channel_mapping_family, stream_count, coupled_count,
+ channel_mapping);
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
- }
- if (codec) {
- GstStructure *s;
- gint bitrate = 0;
+ if (codec) {
+ GstStructure *s;
+ gint bitrate = 0;
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_AUDIO_CODEC, codec, NULL);
- g_free (codec);
- codec = NULL;
-
- /* some bitrate info may have ended up in caps */
- s = gst_caps_get_structure (stream->caps, 0);
- gst_structure_get_int (s, "bitrate", &bitrate);
- if (bitrate > 0)
gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_BITRATE, bitrate, NULL);
- }
+ GST_TAG_AUDIO_CODEC, codec, NULL);
+ g_free (codec);
+ codec = NULL;
- mp4a = qtdemux_tree_get_child_by_index (stsd, 0);
- if (!stream->protected) {
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
- mp4v = NULL;
+ /* some bitrate info may have ended up in caps */
+ s = gst_caps_get_structure (entry->caps, 0);
+ gst_structure_get_int (s, "bitrate", &bitrate);
+ if (bitrate > 0)
+ gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_BITRATE, bitrate, NULL);
}
- }
- if (stream->protected && fourcc == FOURCC_mp4a) {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
- mp4a = NULL;
+
+ mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
+ if (!stream->protected) {
+ } else {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
+ mp4v = NULL;
+ }
}
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
- mp4a = NULL;
+ if (stream->protected && fourcc == FOURCC_mp4a) {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
+ mp4a = NULL;
+ }
+ } else {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
+ mp4a = NULL;
+ }
}
- }
- wave = NULL;
- esds = NULL;
- if (mp4a) {
- wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
- if (wave)
- esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
- if (!esds)
- esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
- }
+ wave = NULL;
+ esds = NULL;
+ if (mp4a) {
+ wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
+ if (wave)
+ esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
+ if (!esds)
+ esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
+ }
- /* If the fourcc's bottom 16 bits gives 'sm', then the top
- 16 bits is a byte-swapped wave-style codec identifier,
- and we can find a WAVE header internally to a 'wave' atom here.
- This can more clearly be thought of as 'ms' as the top 16 bits, and a
- codec id as the bottom 16 bits - but byte-swapped to store in QT (which
- is big-endian).
- */
- if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
- if (len < offset + 20) {
- GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
- } else {
- guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
- const guint8 *data = stsd_entry_data + offset + 16;
- GNode *wavenode;
- GNode *waveheadernode;
-
- wavenode = g_node_new ((guint8 *) data);
- if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
- const guint8 *waveheader;
- guint32 headerlen;
-
- waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
- if (waveheadernode) {
- waveheader = (const guint8 *) waveheadernode->data;
- headerlen = QT_UINT32 (waveheader);
-
- if (headerlen > 8) {
- gst_riff_strf_auds *header = NULL;
- GstBuffer *headerbuf;
- GstBuffer *extra;
-
- waveheader += 8;
- headerlen -= 8;
-
- headerbuf = gst_buffer_new_and_alloc (headerlen);
- gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
-
- if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
- headerbuf, &header, &extra)) {
- gst_caps_unref (stream->caps);
- /* FIXME: Need to do something with the channel reorder map */
- stream->caps = gst_riff_create_audio_caps (header->format, NULL,
- header, extra, NULL, NULL, NULL);
-
- if (extra)
- gst_buffer_unref (extra);
- g_free (header);
+ /* If the fourcc's bottom 16 bits gives 'sm', then the top
+ 16 bits is a byte-swapped wave-style codec identifier,
+ and we can find a WAVE header internally to a 'wave' atom here.
+ This can more clearly be thought of as 'ms' as the top 16 bits, and a
+ codec id as the bottom 16 bits - but byte-swapped to store in QT (which
+ is big-endian).
+ */
+ if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
+ if (len < offset + 20) {
+ GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
+ } else {
+ guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
+ const guint8 *data = stsd_entry_data + offset + 16;
+ GNode *wavenode;
+ GNode *waveheadernode;
+
+ wavenode = g_node_new ((guint8 *) data);
+ if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
+ const guint8 *waveheader;
+ guint32 headerlen;
+
+ waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
+ if (waveheadernode) {
+ waveheader = (const guint8 *) waveheadernode->data;
+ headerlen = QT_UINT32 (waveheader);
+
+ if (headerlen > 8) {
+ gst_riff_strf_auds *header = NULL;
+ GstBuffer *headerbuf;
+ GstBuffer *extra;
+
+ waveheader += 8;
+ headerlen -= 8;
+
+ headerbuf = gst_buffer_new_and_alloc (headerlen);
+ gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
+
+ if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
+ headerbuf, &header, &extra)) {
+ gst_caps_unref (entry->caps);
+ /* FIXME: Need to do something with the channel reorder map */
+ entry->caps =
+ gst_riff_create_audio_caps (header->format, NULL, header,
+ extra, NULL, NULL, NULL);
+
+ if (extra)
+ gst_buffer_unref (extra);
+ g_free (header);
+ }
}
- }
- } else
- GST_DEBUG ("Didn't find waveheadernode for this codec");
+ } else
+ GST_DEBUG ("Didn't find waveheadernode for this codec");
+ }
+ g_node_destroy (wavenode);
}
- g_node_destroy (wavenode);
- }
- } else if (esds) {
- gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
- } else {
- switch (fourcc) {
+ } else if (esds) {
+ gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
+ stream->stream_tags);
+ } else {
+ switch (fourcc) {
#if 0
- /* FIXME: what is in the chunk? */
- case FOURCC_QDMC:
- {
- gint len = QT_UINT32 (stsd_data);
+ /* FIXME: what is in the chunk? */
+ case FOURCC_QDMC:
+ {
+ gint len = QT_UINT32 (stsd_data);
- /* seems to be always = 116 = 0x74 */
- break;
- }
+ /* seems to be always = 116 = 0x74 */
+ break;
+ }
#endif
- case FOURCC_QDM2:
- {
- gint len = QT_UINT32 (stsd_entry_data);
-
- if (len > 0x3C) {
- GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
+ case FOURCC_QDM2:
+ {
+ gint len = QT_UINT32 (stsd_entry_data);
- 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);
- }
- gst_caps_set_simple (stream->caps,
- "samplesize", G_TYPE_INT, samplesize, NULL);
- break;
- }
- case FOURCC_alac:
- {
- GNode *alac, *wave = NULL;
-
- /* apparently, m4a has this atom appended directly in the stsd entry,
- * while mov has it in a wave atom */
- alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
- if (alac) {
- /* alac now refers to stsd entry atom */
- wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
- if (wave)
- alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
- else
- alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
- }
- if (alac) {
- const guint8 *alac_data = alac->data;
- gint len = QT_UINT32 (alac->data);
- GstBuffer *buf;
+ if (len > 0x3C) {
+ GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
- if (len < 36) {
- GST_DEBUG_OBJECT (qtdemux,
- "discarding alac atom with unexpected len %d", len);
- } else {
- /* codec-data contains alac atom size and prefix,
- * ffmpeg likes it that way, not quite gst-ish though ...*/
- buf = gst_buffer_new_and_alloc (len);
- gst_buffer_fill (buf, 0, alac->data, len);
- gst_caps_set_simple (stream->caps,
+ gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
+ gst_caps_set_simple (entry->caps,
"codec_data", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf);
-
- stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
- stream->n_channels = QT_UINT8 (alac_data + 21);
- stream->rate = QT_UINT32 (alac_data + 32);
}
+ gst_caps_set_simple (entry->caps,
+ "samplesize", G_TYPE_INT, samplesize, NULL);
+ break;
}
- gst_caps_set_simple (stream->caps,
- "samplesize", G_TYPE_INT, samplesize, NULL);
- break;
- }
- case FOURCC_fLaC:
- {
- /* The codingname of the sample entry is 'fLaC' */
- GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
-
- if (flac) {
- /* The 'dfLa' box is added to the sample entry to convey
- initializing information for the decoder. */
- const GNode *dfla =
- qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
-
- if (dfla) {
- const guint32 len = QT_UINT32 (dfla->data);
+ case FOURCC_alac:
+ {
+ GNode *alac, *wave = NULL;
+
+ /* apparently, m4a has this atom appended directly in the stsd entry,
+ * while mov has it in a wave atom */
+ alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
+ if (alac) {
+ /* alac now refers to stsd entry atom */
+ wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
+ if (wave)
+ alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
+ else
+ alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
+ }
+ if (alac) {
+ const guint8 *alac_data = alac->data;
+ gint len = QT_UINT32 (alac->data);
+ GstBuffer *buf;
- /* Must contain at least dfLa box header (12),
- * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
- if (len < 50) {
+ if (len < 36) {
GST_DEBUG_OBJECT (qtdemux,
- "discarding dfla atom with unexpected len %d", len);
+ "discarding alac atom with unexpected len %d", len);
} else {
- /* skip dfLa header to get the METADATA_BLOCKs */
- const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
- const guint32 metadata_blocks_len = len - 12;
+ /* codec-data contains alac atom size and prefix,
+ * ffmpeg likes it that way, not quite gst-ish though ...*/
+ buf = gst_buffer_new_and_alloc (len);
+ gst_buffer_fill (buf, 0, alac->data, len);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
- gchar *stream_marker = g_strdup ("fLaC");
- GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
- strlen (stream_marker));
+ entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
+ entry->n_channels = QT_UINT8 (alac_data + 21);
+ entry->rate = QT_UINT32 (alac_data + 32);
+ }
+ }
+ gst_caps_set_simple (entry->caps,
+ "samplesize", G_TYPE_INT, samplesize, NULL);
+ break;
+ }
+ case FOURCC_fLaC:
+ {
+ /* The codingname of the sample entry is 'fLaC' */
+ GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
+
+ if (flac) {
+ /* The 'dfLa' box is added to the sample entry to convey
+ initializing information for the decoder. */
+ const GNode *dfla =
+ qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
+
+ if (dfla) {
+ const guint32 len = QT_UINT32 (dfla->data);
+
+ /* Must contain at least dfLa box header (12),
+ * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
+ if (len < 50) {
+ GST_DEBUG_OBJECT (qtdemux,
+ "discarding dfla atom with unexpected len %d", len);
+ } else {
+ /* skip dfLa header to get the METADATA_BLOCKs */
+ const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
+ const guint32 metadata_blocks_len = len - 12;
+
+ gchar *stream_marker = g_strdup ("fLaC");
+ GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
+ strlen (stream_marker));
- guint32 index = 0;
- guint32 remainder = 0;
- guint32 block_size = 0;
- gboolean is_last = FALSE;
+ guint32 index = 0;
+ guint32 remainder = 0;
+ guint32 block_size = 0;
+ gboolean is_last = FALSE;
- GValue array = G_VALUE_INIT;
- GValue value = G_VALUE_INIT;
+ GValue array = G_VALUE_INIT;
+ GValue value = G_VALUE_INIT;
- g_value_init (&array, GST_TYPE_ARRAY);
- g_value_init (&value, GST_TYPE_BUFFER);
+ g_value_init (&array, GST_TYPE_ARRAY);
+ g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, block);
- gst_value_array_append_value (&array, &value);
- g_value_reset (&value);
+ gst_value_set_buffer (&value, block);
+ gst_value_array_append_value (&array, &value);
+ g_value_reset (&value);
- gst_buffer_unref (block);
+ gst_buffer_unref (block);
- /* check there's at least one METADATA_BLOCK_HEADER's worth
- * of data, and we haven't already finished parsing */
- while (!is_last && ((index + 3) < metadata_blocks_len)) {
- remainder = metadata_blocks_len - index;
+ /* check there's at least one METADATA_BLOCK_HEADER's worth
+ * of data, and we haven't already finished parsing */
+ while (!is_last && ((index + 3) < metadata_blocks_len)) {
+ remainder = metadata_blocks_len - index;
- /* add the METADATA_BLOCK_HEADER size to the signalled size */
- block_size = 4 +
- (metadata_blocks[index + 1] << 16) +
- (metadata_blocks[index + 2] << 8) +
- metadata_blocks[index + 3];
+ /* add the METADATA_BLOCK_HEADER size to the signalled size */
+ block_size = 4 +
+ (metadata_blocks[index + 1] << 16) +
+ (metadata_blocks[index + 2] << 8) +
+ metadata_blocks[index + 3];
- /* be careful not to read off end of box */
- if (block_size > remainder) {
- break;
- }
+ /* be careful not to read off end of box */
+ if (block_size > remainder) {
+ break;
+ }
- is_last = metadata_blocks[index] >> 7;
+ is_last = metadata_blocks[index] >> 7;
- block = gst_buffer_new_and_alloc (block_size);
+ block = gst_buffer_new_and_alloc (block_size);
- gst_buffer_fill (block, 0, &metadata_blocks[index],
- block_size);
+ gst_buffer_fill (block, 0, &metadata_blocks[index],
+ block_size);
- gst_value_set_buffer (&value, block);
- gst_value_array_append_value (&array, &value);
- g_value_reset (&value);
+ gst_value_set_buffer (&value, block);
+ gst_value_array_append_value (&array, &value);
+ g_value_reset (&value);
- gst_buffer_unref (block);
+ gst_buffer_unref (block);
- index += block_size;
- }
+ index += block_size;
+ }
- /* only append the metadata if we successfully read all of it */
- if (is_last) {
- gst_structure_set_value (gst_caps_get_structure (stream->caps,
- 0), "streamheader", &array);
- } else {
- GST_WARNING_OBJECT (qtdemux,
- "discarding all METADATA_BLOCKs due to invalid "
- "block_size %d at idx %d, rem %d", block_size, index,
- remainder);
- }
+ /* only append the metadata if we successfully read all of it */
+ if (is_last) {
+ gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
+ (stream)->caps, 0), "streamheader", &array);
+ } else {
+ GST_WARNING_OBJECT (qtdemux,
+ "discarding all METADATA_BLOCKs due to invalid "
+ "block_size %d at idx %d, rem %d", block_size, index,
+ remainder);
+ }
- g_value_unset (&value);
- g_value_unset (&array);
+ g_value_unset (&value);
+ g_value_unset (&array);
- /* The sample rate obtained from the stsd may not be accurate
- * since it cannot represent rates greater than 65535Hz, so
- * override that value with the sample rate from the
- * METADATA_BLOCK_STREAMINFO block */
- stream->rate =
- (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
+ /* The sample rate obtained from the stsd may not be accurate
+ * since it cannot represent rates greater than 65535Hz, so
+ * override that value with the sample rate from the
+ * METADATA_BLOCK_STREAMINFO block */
+ CUR_STREAM (stream)->rate =
+ (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
+ }
}
}
+ break;
}
- break;
- }
- case FOURCC_sawb:
- /* Fallthrough! */
- amrwb = TRUE;
- case FOURCC_samr:
- {
- gint len = QT_UINT32 (stsd_entry_data);
+ case FOURCC_sawb:
+ /* Fallthrough! */
+ amrwb = TRUE;
+ case FOURCC_samr:
+ {
+ gint len = QT_UINT32 (stsd_entry_data);
+
+ if (len > 0x24) {
+ GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
+ guint bitrate;
+
+ 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. */
+ if ((len - 0x34) > 8 &&
+ (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
+ gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
+ }
- if (len > 0x24) {
- GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
- guint bitrate;
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ }
+ break;
+ }
+ case FOURCC_mp4a:
+ {
+ /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
+ gint len = QT_UINT32 (stsd_entry_data);
+
+ if (len >= 34) {
+ guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
+
+ if (sound_version == 1) {
+ 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 */
- gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
+ gint sample_rate_index =
+ gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
- /* If we have enough data, let's try to get the 'damr' atom. See
- * the 3GPP container spec (26.244) for more details. */
- if ((len - 0x34) > 8 &&
- (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
- }
+ /* build AAC codec data */
+ codec_data[0] = profile << 3;
+ codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
+ codec_data[1] = (sample_rate_index & 0x01) << 7;
+ codec_data[1] |= (channels & 0xF) << 3;
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
+ buf = gst_buffer_new_and_alloc (2);
+ gst_buffer_fill (buf, 0, codec_data, 2);
+ gst_caps_set_simple (entry->caps,
+ "codec_data", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ }
+ }
+ break;
}
- break;
+ default:
+ GST_INFO_OBJECT (qtdemux,
+ "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
+ break;
}
- case FOURCC_mp4a:
- {
- /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
- gint len = QT_UINT32 (stsd_entry_data);
-
- if (len >= 34) {
- guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
+ }
+ GST_INFO_OBJECT (qtdemux,
+ "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
+ GST_FOURCC_ARGS (fourcc), entry->caps);
- if (sound_version == 1) {
- 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 */
+ } else if (stream->subtype == FOURCC_strm) {
+ if (fourcc == FOURCC_rtsp) {
+ stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
+ } else {
+ GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (fourcc));
+ goto unknown_stream;
+ }
+ entry->sampled = TRUE;
+ } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
+ || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
- gint sample_rate_index =
- gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
+ entry->sampled = TRUE;
+ entry->sparse = TRUE;
- /* build AAC codec data */
- codec_data[0] = profile << 3;
- codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
- codec_data[1] = (sample_rate_index & 0x01) << 7;
- codec_data[1] |= (channels & 0xF) << 3;
+ entry->caps =
+ qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
+ &codec);
+ if (codec) {
+ gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_SUBTITLE_CODEC, codec, NULL);
+ g_free (codec);
+ codec = NULL;
+ }
- buf = gst_buffer_new_and_alloc (2);
- gst_buffer_fill (buf, 0, codec_data, 2);
- gst_caps_set_simple (stream->caps,
- "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- }
+ /* hunt for sort-of codec data */
+ switch (fourcc) {
+ case FOURCC_mp4s:
+ {
+ GNode *mp4s = NULL;
+ GNode *esds = NULL;
+
+ /* look for palette in a stsd->mp4s->esds sub-atom */
+ mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
+ if (mp4s)
+ esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
+ if (esds == NULL) {
+ /* Invalid STSD */
+ GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
+ break;
}
+
+ gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
+ stream->stream_tags);
break;
}
default:
"unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
break;
}
- }
- GST_INFO_OBJECT (qtdemux,
- "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
- GST_FOURCC_ARGS (fourcc), stream->caps);
-
- } else if (stream->subtype == FOURCC_strm) {
- if (fourcc == FOURCC_rtsp) {
- stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
+ GST_INFO_OBJECT (qtdemux,
+ "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
+ GST_FOURCC_ARGS (fourcc), entry->caps);
} else {
- GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
- goto unknown_stream;
- }
- stream->sampled = TRUE;
- } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
- || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
+ /* everything in 1 sample */
+ entry->sampled = TRUE;
- stream->sampled = TRUE;
- stream->sparse = TRUE;
+ entry->caps =
+ qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
+ &codec);
- stream->caps =
- 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);
- g_free (codec);
- codec = NULL;
- }
-
- /* hunt for sort-of codec data */
- switch (fourcc) {
- case FOURCC_mp4s:
- {
- GNode *mp4s = NULL;
- GNode *esds = NULL;
-
- /* look for palette in a stsd->mp4s->esds sub-atom */
- mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
- if (mp4s)
- esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
- if (esds == NULL) {
- /* Invalid STSD */
- GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
- break;
- }
+ if (entry->caps == NULL)
+ goto unknown_stream;
- gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
- break;
+ if (codec) {
+ gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_SUBTITLE_CODEC, codec, NULL);
+ g_free (codec);
+ codec = NULL;
}
- default:
- GST_INFO_OBJECT (qtdemux,
- "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
- break;
}
- GST_INFO_OBJECT (qtdemux,
- "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
- GST_FOURCC_ARGS (fourcc), stream->caps);
- } else {
- /* everything in 1 sample */
- stream->sampled = TRUE;
- stream->caps =
- qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_entry_data, &codec);
+ /* promote to sampled format */
+ if (entry->fourcc == FOURCC_samr) {
+ /* force mono 8000 Hz for AMR */
+ entry->sampled = TRUE;
+ entry->n_channels = 1;
+ entry->rate = 8000;
+ } else if (entry->fourcc == FOURCC_sawb) {
+ /* force mono 16000 Hz for AMR-WB */
+ entry->sampled = TRUE;
+ entry->n_channels = 1;
+ entry->rate = 16000;
+ } else if (entry->fourcc == FOURCC_mp4a) {
+ entry->sampled = TRUE;
+ }
- if (stream->caps == NULL)
- goto unknown_stream;
- if (codec) {
- gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_SUBTITLE_CODEC, codec, NULL);
- g_free (codec);
- codec = NULL;
- }
- }
+ stsd_entry_data += len;
+ remaining_stsd_len -= len;
- /* promote to sampled format */
- if (stream->fourcc == FOURCC_samr) {
- /* force mono 8000 Hz for AMR */
- stream->sampled = TRUE;
- stream->n_channels = 1;
- stream->rate = 8000;
- } else if (stream->fourcc == FOURCC_sawb) {
- /* force mono 16000 Hz for AMR-WB */
- stream->sampled = TRUE;
- stream->n_channels = 1;
- stream->rate = 16000;
- } else if (stream->fourcc == FOURCC_mp4a) {
- stream->sampled = TRUE;
}
/* collect sample information */
case FOURCC_soun:
case FOURCC_vide:
GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
- qtdemux->streams[i]->caps);
+ CUR_STREAM (qtdemux->streams[i])->caps);
/* retrieve bitrate, prefer avg then max */
bitrate = 0;
if (qtdemux->streams[i]->stream_tags) {
guint32 sample_num = 0;
GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
- i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
+ i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
if (qtdemux->fragmented) {
/* need all moov samples first */
GstTagList *list;
GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
- i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
+ i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
stream->track_id == qtdemux->chapters_track_id) {
/* this can change the codec originally present in @list */
static void
gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
- GNode * esds, GstTagList * list)
+ QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
{
int len = QT_UINT32 (esds->data);
guint8 *ptr = esds->data;
* profile_and_level_indication */
if (data_ptr != NULL && data_len >= 5 &&
GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
- gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
+ gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
data_ptr + 4, data_len - 4);
}
break; /* Nothing special needed here */
channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
if (channels > 0)
- stream->n_channels = channels;
+ entry->n_channels = channels;
rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
if (rate > 0)
- stream->rate = rate;
+ entry->rate = rate;
}
/* Set level and profile if possible */
if (data_ptr != NULL && data_len >= 2) {
- gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
+ gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
data_ptr, data_len);
} else {
const gchar *profile_str = NULL;
codec_data = map.data;
rate_idx =
- gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
+ gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
+ (stream)->rate);
switch (object_type_id) {
case 0x66:
}
codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
- codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
+ codec_data[1] =
+ ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
gst_buffer_unmap (buffer, &map);
- gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
- buffer, NULL);
+ gst_caps_set_simple (CUR_STREAM (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);
+ gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
+ G_TYPE_STRING, profile_str, NULL);
}
}
break;
/* If we have a replacement caps, then change our caps for this stream */
if (caps) {
- gst_caps_unref (stream->caps);
- stream->caps = caps;
+ gst_caps_unref (entry->caps);
+ entry->caps = caps;
}
if (codec_name && list)
GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
- gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
+ gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
buffer, NULL);
gst_buffer_unref (buffer);
}
static GstCaps *
qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * stsd_entry_data, gchar ** codec_name)
+ QtDemuxStreamStsdEntry * entry, guint32 fourcc,
+ const guint8 * stsd_entry_data, gchar ** codec_name)
{
GstCaps *caps = NULL;
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
case FOURCC_mjp2:
_codec ("JPEG-2000");
/* override to what it should be according to spec, avoid palette_data */
- stream->bits_per_sample = 24;
+ entry->bits_per_sample = 24;
caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
break;
case FOURCC_SVQ3:
caps = gst_caps_new_empty_simple ("video/x-theora");
/* theora uses one byte of padding in the data stream because it does not
* allow 0 sized packets while theora does */
- stream->padding = 1;
+ entry->padding = 1;
break;
case FOURCC_drac:
_codec ("Dirac");
GstVideoInfo info;
gst_video_info_init (&info);
- gst_video_info_set_format (&info, format, stream->width, stream->height);
+ gst_video_info_set_format (&info, format, entry->width, entry->height);
caps = gst_video_info_to_caps (&info);
*codec_name = gst_pb_utils_get_codec_description (caps);
static GstCaps *
qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
+ QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
+ int len, gchar ** codec_name)
{
GstCaps *caps;
const GstStructure *s;
GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
- depth = stream->bytes_per_packet * 8;
+ depth = entry->bytes_per_packet * 8;
switch (fourcc) {
case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
_codec ("EAC-3 audio");
caps = gst_caps_new_simple ("audio/x-eac3",
"framed", G_TYPE_BOOLEAN, TRUE, NULL);
- stream->sampled = TRUE;
+ entry->sampled = TRUE;
break;
case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
case FOURCC_ac_3:
_codec ("AC-3 audio");
caps = gst_caps_new_simple ("audio/x-ac3",
"framed", G_TYPE_BOOLEAN, TRUE, NULL);
- stream->sampled = TRUE;
+ entry->sampled = TRUE;
break;
case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
_codec ("DTS audio");
caps = gst_caps_new_simple ("audio/x-dts",
"framed", G_TYPE_BOOLEAN, TRUE, NULL);
- stream->sampled = TRUE;
+ entry->sampled = TRUE;
break;
case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
_codec ("DTS-HD audio");
caps = gst_caps_new_simple ("audio/x-dts",
"framed", G_TYPE_BOOLEAN, TRUE, NULL);
- stream->sampled = TRUE;
+ entry->sampled = TRUE;
break;
case FOURCC_MAC3:
_codec ("MACE-3");
if (data && len >= 56) {
depth = QT_UINT32 (data + 40);
flags = QT_UINT32 (data + 44);
- width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
+ width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
}
if ((flags & FLAG_IS_FLOAT) == 0) {
if (depth == 0)
name = gst_structure_get_name (s);
if (g_str_has_prefix (name, "audio/x-raw")) {
stream->need_clip = TRUE;
- stream->max_buffer_size = 4096 * stream->bytes_per_frame;
+ stream->max_buffer_size = 4096 * entry->bytes_per_frame;
GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
}
return caps;
static GstCaps *
qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
- guint32 fourcc, const guint8 * stsd_entry_data, gchar ** codec_name)
+ QtDemuxStreamStsdEntry * entry, 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_entry_data, gchar ** codec_name)
+ QtDemuxStreamStsdEntry * entry, guint32 fourcc,
+ const guint8 * stsd_entry_data, gchar ** codec_name)
{
GstCaps *caps;