* <refsect2>
* <title>Example launch line</title>
* |[
- * gst-launch filesrc location=test.mov ! qtdemux name=demux demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
+ * gst-launch filesrc location=test.mov ! qtdemux name=demux demux.audio_0 ! decodebin ! audioconvert ! audioresample ! autoaudiosink demux.video_0 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
* ]| Play (parse and decode) a .mov file and try to output it to
* an automatically detected soundcard and videosink. If the MOV file contains
* compressed audio or video data, this will only work if you have the
);
static GstStaticPadTemplate gst_qtdemux_videosrc_template =
-GST_STATIC_PAD_TEMPLATE ("video_%02d",
+GST_STATIC_PAD_TEMPLATE ("video_%u",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
-GST_STATIC_PAD_TEMPLATE ("audio_%02d",
+GST_STATIC_PAD_TEMPLATE ("audio_%u",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate gst_qtdemux_subsrc_template =
-GST_STATIC_PAD_TEMPLATE ("subtitle_%02d",
+GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
}
#endif
-static const GstQueryType *
-gst_qtdemux_get_src_query_types (GstPad * pad)
-{
- static const GstQueryType src_types[] = {
- GST_QUERY_POSITION,
- GST_QUERY_DURATION,
- GST_QUERY_CONVERT,
- GST_QUERY_FORMATS,
- GST_QUERY_SEEKING,
- 0
- };
-
- return src_types;
-}
-
static gboolean
gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
{
gst_segment_init (&stream->segment, GST_FORMAT_TIME);
if (stream->subtype == FOURCC_vide) {
- gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
+ gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
stream->pad =
gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
}
qtdemux->n_video_streams++;
} else if (stream->subtype == FOURCC_soun) {
- gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
+ gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
stream->pad =
gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
} else if (stream->subtype == FOURCC_strm) {
GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
} else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
- gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
+ gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
stream->pad =
gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
gst_pad_use_fixed_caps (stream->pad);
gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
- gst_pad_set_query_type_function (stream->pad,
- gst_qtdemux_get_src_query_types);
gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
/* sync sample atom */
stream->stps_present = FALSE;
if ((stream->stss_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
&stream->stss) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
/* partial sync sample atom */
if ((stream->stps_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
&stream->stps) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
/* composition time-to-sample */
if ((stream->ctts_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
&stream->ctts) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
stream->caps =
qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
if (codec) {
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_VIDEO_CODEC, codec, NULL);
g_free (codec);
}
if (!list)
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GstStructure *s;
gint bitrate = 0;
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_AUDIO_CODEC, codec, NULL);
g_free (codec);
if ((len - 0x34) > 8 &&
(bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
if (!list)
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
}
stream->caps =
qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
if (codec) {
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_SUBTITLE_CODEC, codec, NULL);
g_free (codec);
const gchar *lang_code;
if (!list)
- list = gst_tag_list_new ();
+ list = gst_tag_list_new_empty ();
/* convert ISO 639-2 code to ISO 639-1 */
lang_code = gst_tag_get_language_code (stream->lang_id);
", Stream bitrate = %u", sys_bitrate, bitrate);
if (!stream->pending_tags)
- stream->pending_tags = gst_tag_list_new ();
+ stream->pending_tags = gst_tag_list_new_empty ();
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_BITRATE, bitrate, NULL);
GST_DEBUG_OBJECT (qtdemux, "new tag list");
if (!qtdemux->tag_list)
- qtdemux->tag_list = gst_tag_list_new ();
+ qtdemux->tag_list = gst_tag_list_new_empty ();
i = 0;
while (i < G_N_ELEMENTS (add_funcs)) {
const gchar *fmt;
if (tags == NULL)
- tags = gst_tag_list_new ();
+ tags = gst_tag_list_new_empty ();
if (qtdemux->major_brand == FOURCC_mjp2)
fmt = "Motion JPEG 2000";
/* Moving qt creation time (secs since 1904) to unix time */
if (creation_time != 0) {
if (creation_time > QTDEMUX_SECONDS_FROM_1904_TO_1970) {
+ GTimeVal now;
+
creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
- datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
+ /* some data cleansing sanity */
+ g_get_current_time (&now);
+ if (now.tv_sec + 24 * 3600 < creation_time) {
+ GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
+ } else {
+ datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
+ }
} else {
GST_WARNING_OBJECT (qtdemux, "Can't handle datetimes before 1970 yet, "
"please file a bug at http://bugzilla.gnome.org");
}
if (datetime) {
if (!qtdemux->tag_list)
- qtdemux->tag_list = gst_tag_list_new ();
+ qtdemux->tag_list = gst_tag_list_new_empty ();
/* Use KEEP as explicit tags should have a higher priority than mvhd tag */
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
/* set duration in the segment info */
gst_qtdemux_get_duration (qtdemux, &duration);
- if (duration)
+ if (duration) {
qtdemux->segment.duration = duration;
+ /* also do not exceed duration; stop is set that way post seek anyway,
+ * and segment activation falls back to duration,
+ * whereas loop only checks stop, so let's align this here as well */
+ qtdemux->segment.stop = duration;
+ }
/* parse all traks */
trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);