1 /* GStreamer Matroska muxer/demuxer
2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * (c) 2006 Tim-Philipp Müller <tim centricular net>
4 * (c) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5 * (c) 2011 Debarshi Ray <rishi@gnu.org>
7 * matroska-demux.c: matroska file/stream demuxer
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 /* TODO: check CRC32 if present
26 * TODO: there can be a segment after the first segment. Handle like
27 * chained oggs. Fixes #334082
28 * TODO: Test samples: http://www.matroska.org/samples/matrix/index.html
29 * http://samples.mplayerhq.hu/Matroska/
30 * TODO: check if demuxing is done correct for all codecs according to spec
31 * TODO: seeking with incomplete or without CUE
35 * SECTION:element-matroskademux
37 * matroskademux demuxes a Matroska file into the different contained streams.
40 * <title>Example launch line</title>
42 * gst-launch -v filesrc location=/path/to/mkv ! matroskademux ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
43 * ]| This pipeline demuxes a Matroska file and outputs the contained Vorbis audio.
54 #include <glib/gprintf.h>
56 /* For AVI compatibility mode
57 and for fourcc stuff */
58 #include <gst/riff/riff-read.h>
59 #include <gst/riff/riff-ids.h>
60 #include <gst/riff/riff-media.h>
62 #include <gst/audio/audio.h>
63 #include <gst/tag/tag.h>
64 #include <gst/pbutils/pbutils.h>
66 #include "matroska-demux.h"
67 #include "matroska-ids.h"
69 GST_DEBUG_CATEGORY_STATIC (matroskademux_debug);
70 #define GST_CAT_DEFAULT matroskademux_debug
72 #define DEBUG_ELEMENT_START(demux, ebml, element) \
73 GST_DEBUG_OBJECT (demux, "Parsing " element " element at offset %" \
74 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
76 #define DEBUG_ELEMENT_STOP(demux, ebml, element, ret) \
77 GST_DEBUG_OBJECT (demux, "Parsing " element " element " \
78 " finished with '%s'", gst_flow_get_name (ret))
88 #define DEFAULT_MAX_GAP_TIME (2 * GST_SECOND)
90 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
93 GST_STATIC_CAPS ("video/x-matroska; video/webm")
96 /* TODO: fill in caps! */
98 static GstStaticPadTemplate audio_src_templ =
99 GST_STATIC_PAD_TEMPLATE ("audio_%u",
102 GST_STATIC_CAPS ("ANY")
105 static GstStaticPadTemplate video_src_templ =
106 GST_STATIC_PAD_TEMPLATE ("video_%u",
109 GST_STATIC_CAPS ("ANY")
112 static GstStaticPadTemplate subtitle_src_templ =
113 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
116 GST_STATIC_CAPS ("text/x-pango-markup; application/x-ssa; "
117 "application/x-ass;application/x-usf; video/x-dvd-subpicture; "
118 "subpicture/x-pgs; subtitle/x-kate; " "application/x-subtitle-unknown")
121 static GstFlowReturn gst_matroska_demux_parse_id (GstMatroskaDemux * demux,
122 guint32 id, guint64 length, guint needed);
124 /* element functions */
125 static void gst_matroska_demux_loop (GstPad * pad);
127 static gboolean gst_matroska_demux_element_send_event (GstElement * element,
129 static gboolean gst_matroska_demux_element_query (GstElement * element,
133 static gboolean gst_matroska_demux_sink_activate (GstPad * sinkpad,
135 static gboolean gst_matroska_demux_sink_activate_mode (GstPad * sinkpad,
136 GstObject * parent, GstPadMode mode, gboolean active);
138 static gboolean gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
139 GstPad * pad, GstEvent * event);
140 static gboolean gst_matroska_demux_handle_src_event (GstPad * pad,
141 GstObject * parent, GstEvent * event);
142 static gboolean gst_matroska_demux_handle_src_query (GstPad * pad,
143 GstObject * parent, GstQuery * query);
145 static gboolean gst_matroska_demux_handle_sink_event (GstPad * pad,
146 GstObject * parent, GstEvent * event);
147 static GstFlowReturn gst_matroska_demux_chain (GstPad * pad,
148 GstObject * object, GstBuffer * buffer);
150 static GstStateChangeReturn
151 gst_matroska_demux_change_state (GstElement * element,
152 GstStateChange transition);
154 gst_matroska_demux_set_index (GstElement * element, GstIndex * index);
155 static GstIndex *gst_matroska_demux_get_index (GstElement * element);
158 static GstCaps *gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext
159 * videocontext, const gchar * codec_id, guint8 * data, guint size,
160 gchar ** codec_name, guint32 * riff_fourcc);
161 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
162 * audiocontext, const gchar * codec_id, guint8 * data, guint size,
163 gchar ** codec_name, guint16 * riff_audio_fmt);
165 * gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
166 subtitlecontext, const gchar * codec_id, gpointer data, guint size);
169 static void gst_matroska_demux_reset (GstElement * element);
170 static gboolean perform_seek_to_offset (GstMatroskaDemux * demux,
173 /* gobject functions */
174 static void gst_matroska_demux_set_property (GObject * object,
175 guint prop_id, const GValue * value, GParamSpec * pspec);
176 static void gst_matroska_demux_get_property (GObject * object,
177 guint prop_id, GValue * value, GParamSpec * pspec);
179 GType gst_matroska_demux_get_type (void);
180 #define parent_class gst_matroska_demux_parent_class
181 G_DEFINE_TYPE (GstMatroskaDemux, gst_matroska_demux, GST_TYPE_ELEMENT);
184 gst_matroska_demux_finalize (GObject * object)
186 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (object);
188 if (demux->common.src) {
189 g_ptr_array_free (demux->common.src, TRUE);
190 demux->common.src = NULL;
193 if (demux->common.global_tags) {
194 gst_tag_list_free (demux->common.global_tags);
195 demux->common.global_tags = NULL;
198 g_object_unref (demux->common.adapter);
200 G_OBJECT_CLASS (parent_class)->finalize (object);
204 gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
206 GObjectClass *gobject_class = (GObjectClass *) klass;
207 GstElementClass *gstelement_class = (GstElementClass *) klass;
209 GST_DEBUG_CATEGORY_INIT (matroskademux_debug, "matroskademux", 0,
212 gobject_class->finalize = gst_matroska_demux_finalize;
214 gobject_class->get_property = gst_matroska_demux_get_property;
215 gobject_class->set_property = gst_matroska_demux_set_property;
217 g_object_class_install_property (gobject_class, ARG_MAX_GAP_TIME,
218 g_param_spec_uint64 ("max-gap-time", "Maximum gap time",
219 "The demuxer sends out segment events for skipping "
220 "gaps longer than this (0 = disabled).", 0, G_MAXUINT64,
221 DEFAULT_MAX_GAP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
223 gstelement_class->change_state =
224 GST_DEBUG_FUNCPTR (gst_matroska_demux_change_state);
225 gstelement_class->send_event =
226 GST_DEBUG_FUNCPTR (gst_matroska_demux_element_send_event);
227 gstelement_class->query =
228 GST_DEBUG_FUNCPTR (gst_matroska_demux_element_query);
229 gstelement_class->set_index =
230 GST_DEBUG_FUNCPTR (gst_matroska_demux_set_index);
231 gstelement_class->get_index =
232 GST_DEBUG_FUNCPTR (gst_matroska_demux_get_index);
234 gst_element_class_add_pad_template (gstelement_class,
235 gst_static_pad_template_get (&video_src_templ));
236 gst_element_class_add_pad_template (gstelement_class,
237 gst_static_pad_template_get (&audio_src_templ));
238 gst_element_class_add_pad_template (gstelement_class,
239 gst_static_pad_template_get (&subtitle_src_templ));
240 gst_element_class_add_pad_template (gstelement_class,
241 gst_static_pad_template_get (&sink_templ));
243 gst_element_class_set_details_simple (gstelement_class, "Matroska demuxer",
245 "Demuxes Matroska/WebM streams into video/audio/subtitles",
246 "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
250 gst_matroska_demux_init (GstMatroskaDemux * demux)
252 demux->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
254 gst_pad_set_activate_function (demux->common.sinkpad,
255 GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate));
256 gst_pad_set_activatemode_function (demux->common.sinkpad,
257 GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate_mode));
258 gst_pad_set_chain_function (demux->common.sinkpad,
259 GST_DEBUG_FUNCPTR (gst_matroska_demux_chain));
260 gst_pad_set_event_function (demux->common.sinkpad,
261 GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_sink_event));
262 gst_element_add_pad (GST_ELEMENT (demux), demux->common.sinkpad);
264 /* initial stream no. */
265 demux->common.src = NULL;
267 demux->common.writing_app = NULL;
268 demux->common.muxing_app = NULL;
269 demux->common.index = NULL;
270 demux->common.global_tags = NULL;
272 demux->common.adapter = gst_adapter_new ();
274 /* property defaults */
275 demux->max_gap_time = DEFAULT_MAX_GAP_TIME;
277 GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
280 gst_matroska_demux_reset (GST_ELEMENT (demux));
284 gst_matroska_track_free (GstMatroskaTrackContext * track)
286 g_free (track->codec_id);
287 g_free (track->codec_name);
288 g_free (track->name);
289 g_free (track->language);
290 g_free (track->codec_priv);
291 g_free (track->codec_state);
293 if (track->encodings != NULL) {
296 for (i = 0; i < track->encodings->len; ++i) {
297 GstMatroskaTrackEncoding *enc = &g_array_index (track->encodings,
298 GstMatroskaTrackEncoding,
301 g_free (enc->comp_settings);
303 g_array_free (track->encodings, TRUE);
306 if (track->pending_tags)
307 gst_tag_list_free (track->pending_tags);
309 if (track->index_table)
310 g_array_free (track->index_table, TRUE);
316 * Returns the aggregated GstFlowReturn.
319 gst_matroska_demux_combine_flows (GstMatroskaDemux * demux,
320 GstMatroskaTrackContext * track, GstFlowReturn ret)
324 /* store the value */
325 track->last_flow = ret;
327 /* any other error that is not-linked can be returned right away */
328 if (ret != GST_FLOW_NOT_LINKED)
331 /* only return NOT_LINKED if all other pads returned NOT_LINKED */
332 g_assert (demux->common.src->len == demux->common.num_streams);
333 for (i = 0; i < demux->common.src->len; i++) {
334 GstMatroskaTrackContext *ostream = g_ptr_array_index (demux->common.src,
340 ret = ostream->last_flow;
341 /* some other return value (must be SUCCESS but we can return
342 * other values as well) */
343 if (ret != GST_FLOW_NOT_LINKED)
346 /* if we get here, all other pads were unlinked and we return
349 GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
354 gst_matroska_demux_free_parsed_el (gpointer mem, gpointer user_data)
356 g_slice_free (guint64, mem);
360 gst_matroska_demux_reset (GstElement * element)
362 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
365 GST_DEBUG_OBJECT (demux, "Resetting state");
368 demux->common.state = GST_MATROSKA_READ_STATE_START;
370 /* clean up existing streams */
371 if (demux->common.src) {
372 g_assert (demux->common.src->len == demux->common.num_streams);
373 for (i = 0; i < demux->common.src->len; i++) {
374 GstMatroskaTrackContext *context = g_ptr_array_index (demux->common.src,
377 if (context->pad != NULL)
378 gst_element_remove_pad (GST_ELEMENT (demux), context->pad);
380 gst_caps_replace (&context->caps, NULL);
381 gst_matroska_track_free (context);
383 g_ptr_array_free (demux->common.src, TRUE);
385 demux->common.src = g_ptr_array_new ();
387 demux->common.num_streams = 0;
388 demux->num_a_streams = 0;
389 demux->num_t_streams = 0;
390 demux->num_v_streams = 0;
392 /* reset media info */
393 g_free (demux->common.writing_app);
394 demux->common.writing_app = NULL;
395 g_free (demux->common.muxing_app);
396 demux->common.muxing_app = NULL;
399 if (demux->common.index) {
400 g_array_free (demux->common.index, TRUE);
401 demux->common.index = NULL;
404 if (demux->clusters) {
405 g_array_free (demux->clusters, TRUE);
406 demux->clusters = NULL;
411 demux->common.time_scale = 1000000;
412 demux->common.created = G_MININT64;
414 demux->common.index_parsed = FALSE;
415 demux->tracks_parsed = FALSE;
416 demux->common.segmentinfo_parsed = FALSE;
417 demux->common.attachments_parsed = FALSE;
419 g_list_foreach (demux->common.tags_parsed,
420 (GFunc) gst_matroska_demux_free_parsed_el, NULL);
421 g_list_free (demux->common.tags_parsed);
422 demux->common.tags_parsed = NULL;
424 g_list_foreach (demux->seek_parsed,
425 (GFunc) gst_matroska_demux_free_parsed_el, NULL);
426 g_list_free (demux->seek_parsed);
427 demux->seek_parsed = NULL;
429 gst_segment_init (&demux->common.segment, GST_FORMAT_TIME);
430 demux->last_stop_end = GST_CLOCK_TIME_NONE;
431 demux->seek_block = 0;
432 demux->stream_start_time = GST_CLOCK_TIME_NONE;
434 demux->common.offset = 0;
435 demux->cluster_time = GST_CLOCK_TIME_NONE;
436 demux->cluster_offset = 0;
437 demux->next_cluster_offset = 0;
438 demux->index_offset = 0;
439 demux->seekable = FALSE;
440 demux->need_segment = FALSE;
441 demux->building_index = FALSE;
442 if (demux->seek_event) {
443 gst_event_unref (demux->seek_event);
444 demux->seek_event = NULL;
447 demux->seek_index = NULL;
448 demux->seek_entry = 0;
450 if (demux->close_segment) {
451 gst_event_unref (demux->close_segment);
452 demux->close_segment = NULL;
455 if (demux->new_segment) {
456 gst_event_unref (demux->new_segment);
457 demux->new_segment = NULL;
460 if (demux->common.element_index) {
461 gst_object_unref (demux->common.element_index);
462 demux->common.element_index = NULL;
464 demux->common.element_index_writer_id = -1;
466 if (demux->common.global_tags) {
467 gst_tag_list_free (demux->common.global_tags);
469 demux->common.global_tags = gst_tag_list_new_empty ();
471 if (demux->common.cached_buffer) {
472 if (demux->common.cached_data) {
473 gst_buffer_unmap (demux->common.cached_buffer,
474 demux->common.cached_data, -1);
475 demux->common.cached_data = NULL;
477 gst_buffer_unref (demux->common.cached_buffer);
478 demux->common.cached_buffer = NULL;
483 gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
485 gpointer data, buf_data;
486 gsize size, buf_size;
488 g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
490 GST_DEBUG ("decoding buffer %p", buf);
492 buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
494 g_return_val_if_fail (buf_size > 0, buf);
499 if (gst_matroska_decode_data (context->encodings, &data, &size,
500 GST_MATROSKA_TRACK_ENCODING_SCOPE_FRAME, FALSE)) {
501 gst_buffer_unmap (buf, buf_data, buf_size);
502 gst_buffer_unref (buf);
503 return gst_buffer_new_wrapped (data, size);
505 GST_DEBUG ("decode data failed");
506 gst_buffer_unmap (buf, buf_data, buf_size);
507 gst_buffer_unref (buf);
513 gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml)
515 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
516 GstMatroskaTrackContext *context;
517 GstPadTemplate *templ = NULL;
518 GstCaps *caps = NULL;
519 gchar *padname = NULL;
521 guint32 id, riff_fourcc = 0;
522 guint16 riff_audio_fmt = 0;
523 GstTagList *list = NULL;
526 DEBUG_ELEMENT_START (demux, ebml, "TrackEntry");
528 /* start with the master */
529 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
530 DEBUG_ELEMENT_STOP (demux, ebml, "TrackEntry", ret);
534 /* allocate generic... if we know the type, we'll g_renew()
535 * with the precise type */
536 context = g_new0 (GstMatroskaTrackContext, 1);
537 g_ptr_array_add (demux->common.src, context);
538 context->index = demux->common.num_streams;
539 context->index_writer_id = -1;
540 context->type = 0; /* no type yet */
541 context->default_duration = 0;
543 context->set_discont = TRUE;
544 context->timecodescale = 1.0;
546 GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
547 GST_MATROSKA_TRACK_LACING;
548 context->last_flow = GST_FLOW_OK;
549 context->to_offset = G_MAXINT64;
550 context->alignment = 1;
551 demux->common.num_streams++;
552 g_assert (demux->common.src->len == demux->common.num_streams);
554 GST_DEBUG_OBJECT (demux, "Stream number %d", context->index);
556 /* try reading the trackentry headers */
557 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
558 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
562 /* track number (unique stream ID) */
563 case GST_MATROSKA_ID_TRACKNUMBER:{
566 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
570 GST_ERROR_OBJECT (demux, "Invalid TrackNumber 0");
571 ret = GST_FLOW_ERROR;
573 } else if (!gst_matroska_read_common_tracknumber_unique (&demux->common,
575 GST_ERROR_OBJECT (demux, "TrackNumber %" G_GUINT64_FORMAT
576 " is not unique", num);
577 ret = GST_FLOW_ERROR;
581 GST_DEBUG_OBJECT (demux, "TrackNumber: %" G_GUINT64_FORMAT, num);
585 /* track UID (unique identifier) */
586 case GST_MATROSKA_ID_TRACKUID:{
589 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
593 GST_ERROR_OBJECT (demux, "Invalid TrackUID 0");
594 ret = GST_FLOW_ERROR;
598 GST_DEBUG_OBJECT (demux, "TrackUID: %" G_GUINT64_FORMAT, num);
603 /* track type (video, audio, combined, subtitle, etc.) */
604 case GST_MATROSKA_ID_TRACKTYPE:{
607 if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
611 if (context->type != 0 && context->type != track_type) {
612 GST_WARNING_OBJECT (demux,
613 "More than one tracktype defined in a TrackEntry - skipping");
615 } else if (track_type < 1 || track_type > 254) {
616 GST_WARNING_OBJECT (demux, "Invalid TrackType %" G_GUINT64_FORMAT,
621 GST_DEBUG_OBJECT (demux, "TrackType: %" G_GUINT64_FORMAT, track_type);
623 /* ok, so we're actually going to reallocate this thing */
624 switch (track_type) {
625 case GST_MATROSKA_TRACK_TYPE_VIDEO:
626 gst_matroska_track_init_video_context (&context);
628 case GST_MATROSKA_TRACK_TYPE_AUDIO:
629 gst_matroska_track_init_audio_context (&context);
631 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
632 gst_matroska_track_init_subtitle_context (&context);
634 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
635 case GST_MATROSKA_TRACK_TYPE_LOGO:
636 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
637 case GST_MATROSKA_TRACK_TYPE_CONTROL:
639 GST_WARNING_OBJECT (demux,
640 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
645 g_ptr_array_index (demux->common.src, demux->common.num_streams - 1)
650 /* tracktype specific stuff for video */
651 case GST_MATROSKA_ID_TRACKVIDEO:{
652 GstMatroskaTrackVideoContext *videocontext;
654 DEBUG_ELEMENT_START (demux, ebml, "TrackVideo");
656 if (!gst_matroska_track_init_video_context (&context)) {
657 GST_WARNING_OBJECT (demux,
658 "TrackVideo element in non-video track - ignoring track");
659 ret = GST_FLOW_ERROR;
661 } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
664 videocontext = (GstMatroskaTrackVideoContext *) context;
665 g_ptr_array_index (demux->common.src, demux->common.num_streams - 1)
668 while (ret == GST_FLOW_OK &&
669 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
670 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
674 /* Should be one level up but some broken muxers write it here. */
675 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
678 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
682 GST_WARNING_OBJECT (demux, "Invalid TrackDefaultDuration 0");
686 GST_DEBUG_OBJECT (demux,
687 "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
688 context->default_duration = num;
692 /* video framerate */
693 /* NOTE: This one is here only for backward compatibility.
694 * Use _TRACKDEFAULDURATION one level up. */
695 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
698 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
702 GST_WARNING_OBJECT (demux, "Invalid TrackVideoFPS %lf", num);
706 GST_DEBUG_OBJECT (demux, "TrackVideoFrameRate: %lf", num);
707 if (context->default_duration == 0)
708 context->default_duration =
709 gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
710 videocontext->default_fps = num;
714 /* width of the size to display the video at */
715 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
718 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
722 GST_WARNING_OBJECT (demux, "Invalid TrackVideoDisplayWidth 0");
726 GST_DEBUG_OBJECT (demux,
727 "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
728 videocontext->display_width = num;
732 /* height of the size to display the video at */
733 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
736 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
740 GST_WARNING_OBJECT (demux, "Invalid TrackVideoDisplayHeight 0");
744 GST_DEBUG_OBJECT (demux,
745 "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
746 videocontext->display_height = num;
750 /* width of the video in the file */
751 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
754 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
758 GST_WARNING_OBJECT (demux, "Invalid TrackVideoPixelWidth 0");
762 GST_DEBUG_OBJECT (demux,
763 "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
764 videocontext->pixel_width = num;
768 /* height of the video in the file */
769 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
772 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
776 GST_WARNING_OBJECT (demux, "Invalid TrackVideoPixelHeight 0");
780 GST_DEBUG_OBJECT (demux,
781 "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
782 videocontext->pixel_height = num;
786 /* whether the video is interlaced */
787 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
790 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
794 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
796 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
797 GST_DEBUG_OBJECT (demux, "TrackVideoInterlaced: %d",
798 (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 :
803 /* aspect ratio behaviour */
804 case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
807 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
810 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
811 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
812 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
813 GST_WARNING_OBJECT (demux,
814 "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
817 GST_DEBUG_OBJECT (demux,
818 "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
819 videocontext->asr_mode = num;
823 /* colourspace (only matters for raw video) fourcc */
824 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
829 gst_ebml_read_binary (ebml, &id, &data,
830 &datalen)) != GST_FLOW_OK)
835 GST_WARNING_OBJECT (demux,
836 "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
841 memcpy (&videocontext->fourcc, data, 4);
842 GST_DEBUG_OBJECT (demux,
843 "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
844 GST_FOURCC_ARGS (videocontext->fourcc));
850 GST_WARNING_OBJECT (demux,
851 "Unknown TrackVideo subelement 0x%x - ignoring", id);
853 case GST_MATROSKA_ID_VIDEOSTEREOMODE:
854 case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
855 case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
856 case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
857 case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
858 case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
859 case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
860 ret = gst_ebml_read_skip (ebml);
865 DEBUG_ELEMENT_STOP (demux, ebml, "TrackVideo", ret);
869 /* tracktype specific stuff for audio */
870 case GST_MATROSKA_ID_TRACKAUDIO:{
871 GstMatroskaTrackAudioContext *audiocontext;
873 DEBUG_ELEMENT_START (demux, ebml, "TrackAudio");
875 if (!gst_matroska_track_init_audio_context (&context)) {
876 GST_WARNING_OBJECT (demux,
877 "TrackAudio element in non-audio track - ignoring track");
878 ret = GST_FLOW_ERROR;
882 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
885 audiocontext = (GstMatroskaTrackAudioContext *) context;
886 g_ptr_array_index (demux->common.src, demux->common.num_streams - 1)
889 while (ret == GST_FLOW_OK &&
890 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
891 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
896 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
899 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
904 GST_WARNING_OBJECT (demux,
905 "Invalid TrackAudioSamplingFrequency %lf", num);
909 GST_DEBUG_OBJECT (demux, "TrackAudioSamplingFrequency: %lf", num);
910 audiocontext->samplerate = num;
915 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
918 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
922 GST_WARNING_OBJECT (demux, "Invalid TrackAudioBitDepth 0");
926 GST_DEBUG_OBJECT (demux, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
928 audiocontext->bitdepth = num;
933 case GST_MATROSKA_ID_AUDIOCHANNELS:{
936 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
940 GST_WARNING_OBJECT (demux, "Invalid TrackAudioChannels 0");
944 GST_DEBUG_OBJECT (demux, "TrackAudioChannels: %" G_GUINT64_FORMAT,
946 audiocontext->channels = num;
951 GST_WARNING_OBJECT (demux,
952 "Unknown TrackAudio subelement 0x%x - ignoring", id);
954 case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
955 case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
956 ret = gst_ebml_read_skip (ebml);
961 DEBUG_ELEMENT_STOP (demux, ebml, "TrackAudio", ret);
966 /* codec identifier */
967 case GST_MATROSKA_ID_CODECID:{
970 if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
973 GST_DEBUG_OBJECT (demux, "CodecID: %s", GST_STR_NULL (text));
974 context->codec_id = text;
978 /* codec private data */
979 case GST_MATROSKA_ID_CODECPRIVATE:{
984 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
987 context->codec_priv = data;
988 context->codec_priv_size = size;
990 GST_DEBUG_OBJECT (demux, "CodecPrivate of size %" G_GUINT64_FORMAT,
995 /* name of the codec */
996 case GST_MATROSKA_ID_CODECNAME:{
999 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1002 GST_DEBUG_OBJECT (demux, "CodecName: %s", GST_STR_NULL (text));
1003 context->codec_name = text;
1007 /* name of this track */
1008 case GST_MATROSKA_ID_TRACKNAME:{
1011 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1014 context->name = text;
1015 GST_DEBUG_OBJECT (demux, "TrackName: %s", GST_STR_NULL (text));
1019 /* language (matters for audio/subtitles, mostly) */
1020 case GST_MATROSKA_ID_TRACKLANGUAGE:{
1023 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1027 context->language = text;
1030 if (strlen (context->language) >= 4 && context->language[3] == '-')
1031 context->language[3] = '\0';
1033 GST_DEBUG_OBJECT (demux, "TrackLanguage: %s",
1034 GST_STR_NULL (context->language));
1038 /* whether this is actually used */
1039 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
1042 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1046 context->flags |= GST_MATROSKA_TRACK_ENABLED;
1048 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
1050 GST_DEBUG_OBJECT (demux, "TrackEnabled: %d",
1051 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1055 /* whether it's the default for this track type */
1056 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
1059 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1063 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
1065 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
1067 GST_DEBUG_OBJECT (demux, "TrackDefault: %d",
1068 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1072 /* whether the track must be used during playback */
1073 case GST_MATROSKA_ID_TRACKFLAGFORCED:{
1076 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1080 context->flags |= GST_MATROSKA_TRACK_FORCED;
1082 context->flags &= ~GST_MATROSKA_TRACK_FORCED;
1084 GST_DEBUG_OBJECT (demux, "TrackForced: %d",
1085 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1089 /* lacing (like MPEG, where blocks don't end/start on frame
1091 case GST_MATROSKA_ID_TRACKFLAGLACING:{
1094 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1098 context->flags |= GST_MATROSKA_TRACK_LACING;
1100 context->flags &= ~GST_MATROSKA_TRACK_LACING;
1102 GST_DEBUG_OBJECT (demux, "TrackLacing: %d",
1103 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1107 /* default length (in time) of one data block in this track */
1108 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1111 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1116 GST_WARNING_OBJECT (demux, "Invalid TrackDefaultDuration 0");
1120 GST_DEBUG_OBJECT (demux, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
1122 context->default_duration = num;
1126 case GST_MATROSKA_ID_CONTENTENCODINGS:{
1127 ret = gst_matroska_read_common_read_track_encodings (&demux->common,
1132 case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
1135 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1139 GST_WARNING_OBJECT (demux, "Invalid TrackTimeCodeScale %lf", num);
1143 GST_DEBUG_OBJECT (demux, "TrackTimeCodeScale: %lf", num);
1144 context->timecodescale = num;
1149 GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
1152 /* we ignore these because they're nothing useful (i.e. crap)
1153 * or simply not implemented yet. */
1154 case GST_MATROSKA_ID_TRACKMINCACHE:
1155 case GST_MATROSKA_ID_TRACKMAXCACHE:
1156 case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
1157 case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
1158 case GST_MATROSKA_ID_TRACKOVERLAY:
1159 case GST_MATROSKA_ID_TRACKTRANSLATE:
1160 case GST_MATROSKA_ID_TRACKOFFSET:
1161 case GST_MATROSKA_ID_CODECSETTINGS:
1162 case GST_MATROSKA_ID_CODECINFOURL:
1163 case GST_MATROSKA_ID_CODECDOWNLOADURL:
1164 case GST_MATROSKA_ID_CODECDECODEALL:
1165 ret = gst_ebml_read_skip (ebml);
1170 DEBUG_ELEMENT_STOP (demux, ebml, "TrackEntry", ret);
1172 /* Decode codec private data if necessary */
1173 if (context->encodings && context->encodings->len > 0 && context->codec_priv
1174 && context->codec_priv_size > 0) {
1175 if (!gst_matroska_decode_data (context->encodings,
1176 &context->codec_priv, &context->codec_priv_size,
1177 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
1178 GST_WARNING_OBJECT (demux, "Decoding codec private data failed");
1179 ret = GST_FLOW_ERROR;
1183 if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
1184 && ret != GST_FLOW_UNEXPECTED)) {
1185 if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
1186 GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
1188 demux->common.num_streams--;
1189 g_ptr_array_remove_index (demux->common.src, demux->common.num_streams);
1190 g_assert (demux->common.src->len == demux->common.num_streams);
1192 gst_matroska_track_free (context);
1198 /* now create the GStreamer connectivity */
1199 switch (context->type) {
1200 case GST_MATROSKA_TRACK_TYPE_VIDEO:{
1201 GstMatroskaTrackVideoContext *videocontext =
1202 (GstMatroskaTrackVideoContext *) context;
1204 padname = g_strdup_printf ("video_%u", demux->num_v_streams++);
1205 templ = gst_element_class_get_pad_template (klass, "video_%u");
1206 caps = gst_matroska_demux_video_caps (videocontext,
1207 context->codec_id, context->codec_priv,
1208 context->codec_priv_size, &codec, &riff_fourcc);
1211 list = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec, NULL);
1217 case GST_MATROSKA_TRACK_TYPE_AUDIO:{
1218 GstMatroskaTrackAudioContext *audiocontext =
1219 (GstMatroskaTrackAudioContext *) context;
1221 padname = g_strdup_printf ("audio_%u", demux->num_a_streams++);
1222 templ = gst_element_class_get_pad_template (klass, "audio_%u");
1223 caps = gst_matroska_demux_audio_caps (audiocontext,
1224 context->codec_id, context->codec_priv, context->codec_priv_size,
1225 &codec, &riff_audio_fmt);
1228 list = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec, NULL);
1234 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
1235 GstMatroskaTrackSubtitleContext *subtitlecontext =
1236 (GstMatroskaTrackSubtitleContext *) context;
1238 padname = g_strdup_printf ("subtitle_%u", demux->num_t_streams++);
1239 templ = gst_element_class_get_pad_template (klass, "subtitle_%u");
1240 caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
1241 context->codec_id, context->codec_priv, context->codec_priv_size);
1245 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
1246 case GST_MATROSKA_TRACK_TYPE_LOGO:
1247 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
1248 case GST_MATROSKA_TRACK_TYPE_CONTROL:
1250 /* we should already have quit by now */
1251 g_assert_not_reached ();
1254 if ((context->language == NULL || *context->language == '\0') &&
1255 (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
1256 context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
1257 GST_LOG ("stream %d: language=eng (assuming default)", context->index);
1258 context->language = g_strdup ("eng");
1261 if (context->language) {
1265 list = gst_tag_list_new_empty ();
1267 /* Matroska contains ISO 639-2B codes, we want ISO 639-1 */
1268 lang = gst_tag_get_language_code (context->language);
1269 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
1270 GST_TAG_LANGUAGE_CODE, (lang) ? lang : context->language, NULL);
1274 GST_WARNING_OBJECT (demux, "could not determine caps for stream with "
1275 "codec_id='%s'", context->codec_id);
1276 switch (context->type) {
1277 case GST_MATROSKA_TRACK_TYPE_VIDEO:
1278 caps = gst_caps_new_empty_simple ("video/x-unknown");
1280 case GST_MATROSKA_TRACK_TYPE_AUDIO:
1281 caps = gst_caps_new_empty_simple ("audio/x-unknown");
1283 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
1284 caps = gst_caps_new_empty_simple ("application/x-subtitle-unknown");
1286 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
1288 caps = gst_caps_new_empty_simple ("application/x-matroska-unknown");
1291 gst_caps_set_simple (caps, "codec-id", G_TYPE_STRING, context->codec_id,
1294 /* add any unrecognised riff fourcc / audio format, but after codec-id */
1295 if (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO && riff_audio_fmt != 0)
1296 gst_caps_set_simple (caps, "format", G_TYPE_INT, riff_audio_fmt, NULL);
1297 else if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO && riff_fourcc != 0) {
1298 gchar *fstr = g_strdup_printf ("%" GST_FOURCC_FORMAT,
1299 GST_FOURCC_ARGS (riff_fourcc));
1300 gst_caps_set_simple (caps, "fourcc", G_TYPE_STRING, fstr, NULL);
1305 /* the pad in here */
1306 context->pad = gst_pad_new_from_template (templ, padname);
1307 context->caps = caps;
1309 gst_pad_set_event_function (context->pad,
1310 GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_event));
1311 gst_pad_set_query_function (context->pad,
1312 GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_query));
1314 GST_INFO_OBJECT (demux, "Adding pad '%s' with caps %" GST_PTR_FORMAT,
1317 context->pending_tags = list;
1319 gst_pad_set_element_private (context->pad, context);
1321 gst_pad_use_fixed_caps (context->pad);
1322 gst_pad_set_active (context->pad, TRUE);
1323 gst_pad_set_caps (context->pad, context->caps);
1324 gst_element_add_pad (GST_ELEMENT (demux), context->pad);
1333 gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad,
1336 gboolean res = FALSE;
1337 GstMatroskaTrackContext *context = NULL;
1340 context = gst_pad_get_element_private (pad);
1343 switch (GST_QUERY_TYPE (query)) {
1344 case GST_QUERY_POSITION:
1348 gst_query_parse_position (query, &format, NULL);
1350 if (format == GST_FORMAT_TIME) {
1351 GST_OBJECT_LOCK (demux);
1353 gst_query_set_position (query, GST_FORMAT_TIME,
1354 context->pos - demux->stream_start_time);
1356 gst_query_set_position (query, GST_FORMAT_TIME,
1357 demux->common.segment.position - demux->stream_start_time);
1358 GST_OBJECT_UNLOCK (demux);
1359 } else if (format == GST_FORMAT_DEFAULT && context
1360 && context->default_duration) {
1361 GST_OBJECT_LOCK (demux);
1362 gst_query_set_position (query, GST_FORMAT_DEFAULT,
1363 context->pos / context->default_duration);
1364 GST_OBJECT_UNLOCK (demux);
1366 GST_DEBUG_OBJECT (demux,
1367 "only position query in TIME and DEFAULT format is supported");
1373 case GST_QUERY_DURATION:
1377 gst_query_parse_duration (query, &format, NULL);
1379 if (format == GST_FORMAT_TIME) {
1380 GST_OBJECT_LOCK (demux);
1381 gst_query_set_duration (query, GST_FORMAT_TIME,
1382 demux->common.segment.duration);
1383 GST_OBJECT_UNLOCK (demux);
1384 } else if (format == GST_FORMAT_DEFAULT && context
1385 && context->default_duration) {
1386 GST_OBJECT_LOCK (demux);
1387 gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1388 demux->common.segment.duration / context->default_duration);
1389 GST_OBJECT_UNLOCK (demux);
1391 GST_DEBUG_OBJECT (demux,
1392 "only duration query in TIME and DEFAULT format is supported");
1399 case GST_QUERY_SEEKING:
1403 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1404 GST_OBJECT_LOCK (demux);
1405 if (fmt == GST_FORMAT_TIME) {
1408 if (demux->streaming) {
1409 /* assuming we'll be able to get an index ... */
1410 seekable = demux->seekable;
1415 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1416 0, demux->common.segment.duration);
1419 GST_OBJECT_UNLOCK (demux);
1423 res = gst_pad_query_default (pad, (GstObject *) demux, query);
1431 gst_matroska_demux_element_query (GstElement * element, GstQuery * query)
1433 return gst_matroska_demux_query (GST_MATROSKA_DEMUX (element), NULL, query);
1437 gst_matroska_demux_handle_src_query (GstPad * pad, GstObject * parent,
1440 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
1442 return gst_matroska_demux_query (demux, pad, query);
1445 /* returns FALSE if there are no pads to deliver event to,
1446 * otherwise TRUE (whatever the outcome of event sending),
1447 * takes ownership of the passed event! */
1449 gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
1451 gboolean is_segment;
1452 gboolean ret = FALSE;
1455 g_return_val_if_fail (event != NULL, FALSE);
1457 GST_DEBUG_OBJECT (demux, "Sending event of type %s to all source pads",
1458 GST_EVENT_TYPE_NAME (event));
1460 is_segment = (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
1462 g_assert (demux->common.src->len == demux->common.num_streams);
1463 for (i = 0; i < demux->common.src->len; i++) {
1464 GstMatroskaTrackContext *stream;
1466 stream = g_ptr_array_index (demux->common.src, i);
1467 gst_event_ref (event);
1468 gst_pad_push_event (stream->pad, event);
1471 /* FIXME: send global tags before stream tags */
1472 if (G_UNLIKELY (is_segment && stream->pending_tags != NULL)) {
1473 GST_DEBUG_OBJECT (demux, "Sending pending_tags %p for pad %s:%s : %"
1474 GST_PTR_FORMAT, stream->pending_tags,
1475 GST_DEBUG_PAD_NAME (stream->pad), stream->pending_tags);
1476 gst_pad_push_event (stream->pad,
1477 gst_event_new_tag (stream->pending_tags));
1478 stream->pending_tags = NULL;
1482 if (G_UNLIKELY (is_segment && demux->common.global_tags != NULL)) {
1483 GstEvent *tag_event;
1484 gst_tag_list_add (demux->common.global_tags, GST_TAG_MERGE_REPLACE,
1485 GST_TAG_CONTAINER_FORMAT, "Matroska", NULL);
1486 GST_DEBUG_OBJECT (demux, "Sending global_tags %p : %" GST_PTR_FORMAT,
1487 demux->common.global_tags, demux->common.global_tags);
1489 tag_event = gst_event_new_tag (demux->common.global_tags);
1491 for (i = 0; i < demux->common.src->len; i++) {
1492 GstMatroskaTrackContext *stream;
1494 stream = g_ptr_array_index (demux->common.src, i);
1495 gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
1498 gst_event_unref (tag_event);
1499 demux->common.global_tags = NULL;
1502 gst_event_unref (event);
1507 gst_matroska_demux_element_send_event (GstElement * element, GstEvent * event)
1509 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1512 g_return_val_if_fail (event != NULL, FALSE);
1514 if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1515 res = gst_matroska_demux_handle_seek_event (demux, NULL, event);
1517 GST_WARNING_OBJECT (demux, "Unhandled event of type %s",
1518 GST_EVENT_TYPE_NAME (event));
1521 gst_event_unref (event);
1526 gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux,
1527 GstMatroskaIndex * entry, gboolean reset)
1531 GST_OBJECT_LOCK (demux);
1533 /* seek (relative to matroska segment) */
1534 /* position might be invalid; will error when streaming resumes ... */
1535 demux->common.offset = entry->pos + demux->common.ebml_segment_start;
1537 GST_DEBUG_OBJECT (demux, "Seeked to offset %" G_GUINT64_FORMAT ", block %d, "
1538 "time %" GST_TIME_FORMAT, entry->pos + demux->common.ebml_segment_start,
1539 entry->block, GST_TIME_ARGS (entry->time));
1541 /* update the time */
1542 gst_matroska_read_common_reset_streams (&demux->common, entry->time, TRUE);
1543 demux->common.segment.position = entry->time;
1544 demux->seek_block = entry->block;
1545 demux->seek_first = TRUE;
1546 demux->last_stop_end = GST_CLOCK_TIME_NONE;
1548 for (i = 0; i < demux->common.src->len; i++) {
1549 GstMatroskaTrackContext *stream = g_ptr_array_index (demux->common.src, i);
1552 stream->to_offset = G_MAXINT64;
1554 if (stream->from_offset != -1)
1555 stream->to_offset = stream->from_offset;
1557 stream->from_offset = -1;
1560 GST_OBJECT_UNLOCK (demux);
1566 gst_matroska_cluster_compare (gint64 * i1, gint64 * i2)
1576 /* searches for a cluster start from @pos,
1577 * return GST_FLOW_OK and cluster position in @pos if found */
1578 static GstFlowReturn
1579 gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
1581 gint64 newpos = *pos;
1583 GstFlowReturn ret = GST_FLOW_OK;
1584 const guint chunk = 64 * 1024;
1585 GstBuffer *buf = NULL;
1586 gpointer data = NULL;
1592 orig_offset = demux->common.offset;
1594 GST_LOG_OBJECT (demux, "searching cluster following offset %" G_GINT64_FORMAT,
1597 if (demux->clusters) {
1600 cpos = gst_util_array_binary_search (demux->clusters->data,
1601 demux->clusters->len, sizeof (gint64),
1602 (GCompareDataFunc) gst_matroska_cluster_compare,
1603 GST_SEARCH_MODE_AFTER, pos, NULL);
1606 GST_DEBUG_OBJECT (demux,
1607 "cluster reported at offset %" G_GINT64_FORMAT, *cpos);
1608 demux->common.offset = *cpos;
1609 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
1610 GST_ELEMENT_CAST (demux), &id, &length, &needed);
1611 if (ret == GST_FLOW_OK && id == GST_MATROSKA_ID_CLUSTER) {
1618 /* read in at newpos and scan for ebml cluster id */
1620 GstByteReader reader;
1624 gst_buffer_unmap (buf, data, size);
1625 gst_buffer_unref (buf);
1628 ret = gst_pad_pull_range (demux->common.sinkpad, newpos, chunk, &buf);
1629 if (ret != GST_FLOW_OK)
1631 GST_DEBUG_OBJECT (demux, "read buffer size %d at offset %" G_GINT64_FORMAT,
1632 gst_buffer_get_size (buf), newpos);
1633 data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
1634 gst_byte_reader_init (&reader, data, size);
1636 cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
1637 GST_MATROSKA_ID_CLUSTER, 0, gst_byte_reader_get_remaining (&reader));
1638 if (cluster_pos >= 0) {
1639 newpos += cluster_pos;
1640 /* prepare resuming at next byte */
1641 gst_byte_reader_skip (&reader, cluster_pos + 1);
1642 GST_DEBUG_OBJECT (demux,
1643 "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
1644 /* extra checks whether we really sync'ed to a cluster:
1645 * - either it is the first and only cluster
1646 * - either there is a cluster after this one
1647 * - either cluster length is undefined
1649 /* ok if first cluster (there may not a subsequent one) */
1650 if (newpos == demux->first_cluster_offset) {
1651 GST_DEBUG_OBJECT (demux, "cluster is first cluster -> OK");
1654 demux->common.offset = newpos;
1655 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
1656 GST_ELEMENT_CAST (demux), &id, &length, &needed);
1657 if (ret != GST_FLOW_OK) {
1658 GST_DEBUG_OBJECT (demux, "need more data -> continue");
1661 g_assert (id == GST_MATROSKA_ID_CLUSTER);
1662 GST_DEBUG_OBJECT (demux, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
1664 /* ok if undefined length or first cluster */
1665 if (length == GST_EBML_SIZE_UNKNOWN || length == G_MAXUINT64) {
1666 GST_DEBUG_OBJECT (demux, "cluster has undefined length -> OK");
1670 demux->common.offset += length + needed;
1671 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
1672 GST_ELEMENT_CAST (demux), &id, &length, &needed);
1673 if (ret != GST_FLOW_OK)
1675 GST_DEBUG_OBJECT (demux, "next element is %scluster",
1676 id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
1677 if (id == GST_MATROSKA_ID_CLUSTER)
1679 /* not ok, resume */
1682 /* partial cluster id may have been in tail of buffer */
1683 newpos += MAX (gst_byte_reader_get_remaining (&reader), 4) - 3;
1688 gst_buffer_unmap (buf, data, size);
1689 gst_buffer_unref (buf);
1694 demux->common.offset = orig_offset;
1699 /* bisect and scan through file for cluster starting before @time,
1700 * returns fake index entry with corresponding info on cluster */
1701 static GstMatroskaIndex *
1702 gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time)
1704 GstMatroskaIndex *entry = NULL;
1705 GstMatroskaReadState current_state;
1706 GstClockTime otime, prev_cluster_time, current_cluster_time, cluster_time;
1707 gint64 opos, newpos, startpos = 0, current_offset;
1708 gint64 prev_cluster_offset = -1, current_cluster_offset, cluster_offset;
1709 const guint chunk = 64 * 1024;
1710 GstBuffer *buf = NULL;
1716 /* (under)estimate new position, resync using cluster ebml id,
1717 * and scan forward to appropriate cluster
1718 * (and re-estimate if need to go backward) */
1720 prev_cluster_time = GST_CLOCK_TIME_NONE;
1722 /* store some current state */
1723 current_state = demux->common.state;
1724 g_return_val_if_fail (current_state == GST_MATROSKA_READ_STATE_DATA, NULL);
1726 current_cluster_offset = demux->cluster_offset;
1727 current_cluster_time = demux->cluster_time;
1728 current_offset = demux->common.offset;
1730 demux->common.state = GST_MATROSKA_READ_STATE_SCANNING;
1732 /* estimate using start and current position */
1733 GST_OBJECT_LOCK (demux);
1734 opos = demux->common.offset - demux->common.ebml_segment_start;
1735 otime = demux->common.segment.position;
1736 GST_OBJECT_UNLOCK (demux);
1738 /* avoid division by zero in first estimation below */
1743 GST_LOG_OBJECT (demux,
1744 "opos: %" G_GUINT64_FORMAT ", otime: %" GST_TIME_FORMAT ", %"
1745 GST_TIME_FORMAT " in stream time (start %" GST_TIME_FORMAT "), time %"
1746 GST_TIME_FORMAT, opos, GST_TIME_ARGS (otime),
1747 GST_TIME_ARGS (otime - demux->stream_start_time),
1748 GST_TIME_ARGS (demux->stream_start_time), GST_TIME_ARGS (time));
1750 gst_util_uint64_scale (opos - demux->common.ebml_segment_start,
1751 time - demux->stream_start_time,
1752 otime - demux->stream_start_time) - chunk;
1755 /* favour undershoot */
1756 newpos = newpos * 90 / 100;
1757 newpos += demux->common.ebml_segment_start;
1759 GST_DEBUG_OBJECT (demux,
1760 "estimated offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT,
1761 GST_TIME_ARGS (time), newpos);
1763 /* and at least start scanning before previous scan start to avoid looping */
1764 startpos = startpos * 90 / 100;
1765 if (startpos && startpos < newpos)
1768 /* read in at newpos and scan for ebml cluster id */
1772 ret = gst_matroska_demux_search_cluster (demux, &newpos);
1773 if (ret == GST_FLOW_UNEXPECTED) {
1774 /* heuristic HACK */
1775 newpos = startpos * 80 / 100;
1776 GST_DEBUG_OBJECT (demux, "EOS; "
1777 "new estimated offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT,
1778 GST_TIME_ARGS (time), newpos);
1781 } else if (ret != GST_FLOW_OK) {
1788 /* then start scanning and parsing for cluster time,
1789 * re-estimate if overshoot, otherwise next cluster and so on */
1790 demux->common.offset = newpos;
1791 demux->cluster_time = cluster_time = GST_CLOCK_TIME_NONE;
1793 guint64 cluster_size = 0;
1795 /* peek and parse some elements */
1796 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
1797 GST_ELEMENT_CAST (demux), &id, &length, &needed);
1798 if (ret != GST_FLOW_OK)
1800 GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
1801 "size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id,
1803 ret = gst_matroska_demux_parse_id (demux, id, length, needed);
1804 if (ret != GST_FLOW_OK)
1807 if (id == GST_MATROSKA_ID_CLUSTER) {
1808 cluster_time = GST_CLOCK_TIME_NONE;
1809 if (length == G_MAXUINT64)
1812 cluster_size = length + needed;
1814 if (demux->cluster_time != GST_CLOCK_TIME_NONE &&
1815 cluster_time == GST_CLOCK_TIME_NONE) {
1816 cluster_time = demux->cluster_time * demux->common.time_scale;
1817 cluster_offset = demux->cluster_offset;
1818 GST_DEBUG_OBJECT (demux, "found cluster at offset %" G_GINT64_FORMAT
1819 " with time %" GST_TIME_FORMAT, cluster_offset,
1820 GST_TIME_ARGS (cluster_time));
1821 if (cluster_time > time) {
1822 GST_DEBUG_OBJECT (demux, "overshot target");
1823 /* cluster overshoots */
1824 if (cluster_offset == demux->first_cluster_offset) {
1825 /* but no prev one */
1826 GST_DEBUG_OBJECT (demux, "but using first cluster anyway");
1827 prev_cluster_time = cluster_time;
1828 prev_cluster_offset = cluster_offset;
1831 if (prev_cluster_time != GST_CLOCK_TIME_NONE) {
1832 /* prev cluster did not overshoot, so prev cluster is target */
1835 /* re-estimate using this new position info */
1836 opos = cluster_offset;
1837 otime = cluster_time;
1841 /* cluster undershoots, goto next one */
1842 prev_cluster_time = cluster_time;
1843 prev_cluster_offset = cluster_offset;
1844 /* skip cluster if length is defined,
1845 * otherwise will be skippingly parsed into */
1847 GST_DEBUG_OBJECT (demux, "skipping to next cluster");
1848 demux->common.offset = cluster_offset + cluster_size;
1849 demux->cluster_time = GST_CLOCK_TIME_NONE;
1851 GST_DEBUG_OBJECT (demux, "parsing/skipping cluster elements");
1858 if (ret == GST_FLOW_UNEXPECTED) {
1859 if (prev_cluster_time != GST_CLOCK_TIME_NONE)
1865 entry = g_new0 (GstMatroskaIndex, 1);
1866 entry->time = prev_cluster_time;
1867 entry->pos = prev_cluster_offset - demux->common.ebml_segment_start;
1868 GST_DEBUG_OBJECT (demux, "simulated index entry; time %" GST_TIME_FORMAT
1869 ", pos %" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->time), entry->pos);
1873 gst_buffer_unref (buf);
1875 /* restore some state */
1876 demux->cluster_offset = current_cluster_offset;
1877 demux->cluster_time = current_cluster_time;
1878 demux->common.offset = current_offset;
1879 demux->common.state = current_state;
1885 gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
1886 GstPad * pad, GstEvent * event)
1888 GstMatroskaIndex *entry = NULL;
1889 GstMatroskaIndex scan_entry;
1891 GstSeekType cur_type, stop_type;
1893 gboolean flush, keyunit;
1896 GstMatroskaTrackContext *track = NULL;
1897 GstSegment seeksegment = { 0, };
1898 gboolean update = TRUE;
1901 track = gst_pad_get_element_private (pad);
1903 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1906 /* we can only seek on time */
1907 if (format != GST_FORMAT_TIME) {
1908 GST_DEBUG_OBJECT (demux, "Can only seek on TIME");
1912 /* copy segment, we need this because we still need the old
1913 * segment when we close the current segment. */
1914 memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment));
1917 GST_DEBUG_OBJECT (demux, "configuring seek");
1918 gst_segment_do_seek (&seeksegment, rate, format, flags,
1919 cur_type, cur, stop_type, stop, &update);
1920 /* compensate for clip start time */
1921 if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
1922 seeksegment.position += demux->stream_start_time;
1923 seeksegment.start += demux->stream_start_time;
1924 if (GST_CLOCK_TIME_IS_VALID (seeksegment.stop))
1925 seeksegment.stop += demux->stream_start_time;
1926 /* note that time should stay at indicated position */
1930 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1931 keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
1933 GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
1936 /* only have to update some segment,
1937 * but also still have to honour flush and so on */
1938 GST_DEBUG_OBJECT (demux, "... no update");
1939 /* bad goto, bad ... */
1943 /* check sanity before we start flushing and all that */
1944 GST_OBJECT_LOCK (demux);
1945 track = gst_matroska_read_common_get_seek_track (&demux->common, track);
1946 if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, track,
1947 seeksegment.position, &demux->seek_index, &demux->seek_entry)) ==
1949 /* pull mode without index can scan later on */
1950 if (demux->common.index || demux->streaming) {
1951 GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
1952 GST_OBJECT_UNLOCK (demux);
1956 GST_DEBUG_OBJECT (demux, "Seek position looks sane");
1957 GST_OBJECT_UNLOCK (demux);
1959 if (demux->streaming) {
1960 /* need to seek to cluster start to pick up cluster time */
1961 /* upstream takes care of flushing and all that
1962 * ... and segment event handling takes care of the rest */
1963 return perform_seek_to_offset (demux,
1964 entry->pos + demux->common.ebml_segment_start);
1969 GST_DEBUG_OBJECT (demux, "Starting flush");
1970 gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_start ());
1971 gst_matroska_demux_send_event (demux, gst_event_new_flush_start ());
1973 GST_DEBUG_OBJECT (demux, "Non-flushing seek, pausing task");
1974 gst_pad_pause_task (demux->common.sinkpad);
1980 /* now grab the stream lock so that streaming cannot continue, for
1981 * non flushing seeks when the element is in PAUSED this could block
1983 GST_DEBUG_OBJECT (demux, "Waiting for streaming to stop");
1984 GST_PAD_STREAM_LOCK (demux->common.sinkpad);
1986 /* pull mode without index can do some scanning */
1987 if (!demux->streaming && !demux->common.index) {
1988 /* need to stop flushing upstream as we need it next */
1990 gst_pad_push_event (demux->common.sinkpad,
1991 gst_event_new_flush_stop (TRUE));
1992 entry = gst_matroska_demux_search_pos (demux, seeksegment.position);
1993 /* keep local copy */
1995 scan_entry = *entry;
1997 entry = &scan_entry;
1999 GST_DEBUG_OBJECT (demux, "Scan failed to find matching position");
2001 gst_matroska_demux_send_event (demux, gst_event_new_flush_stop (TRUE));
2007 GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %"
2008 GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
2009 seeksegment.start = entry->time;
2010 seeksegment.position = entry->time;
2011 seeksegment.time = entry->time - demux->stream_start_time;
2016 GST_DEBUG_OBJECT (demux, "Stopping flush");
2017 gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop (TRUE));
2018 gst_matroska_demux_send_event (demux, gst_event_new_flush_stop (TRUE));
2019 } else if (demux->segment_running && update) {
2021 GST_DEBUG_OBJECT (demux, "Closing currently running segment");
2023 GST_OBJECT_LOCK (demux);
2024 if (demux->close_segment)
2025 gst_event_unref (demux->close_segment);
2027 segment = demux->common.segment;
2028 segment.stop = segment.position;
2029 demux->close_segment = gst_event_new_segment (&segment);
2030 GST_OBJECT_UNLOCK (demux);
2033 GST_OBJECT_LOCK (demux);
2034 /* now update the real segment info */
2035 GST_DEBUG_OBJECT (demux, "Committing new seek segment");
2036 memcpy (&demux->common.segment, &seeksegment, sizeof (GstSegment));
2037 GST_OBJECT_UNLOCK (demux);
2039 /* update some (segment) state */
2040 if (update && !gst_matroska_demux_move_to_entry (demux, entry, TRUE))
2043 /* notify start of new segment */
2044 if (demux->common.segment.flags & GST_SEEK_FLAG_SEGMENT) {
2047 msg = gst_message_new_segment_start (GST_OBJECT (demux),
2048 GST_FORMAT_TIME, demux->common.segment.start);
2049 gst_element_post_message (GST_ELEMENT (demux), msg);
2052 GST_OBJECT_LOCK (demux);
2053 if (demux->new_segment)
2054 gst_event_unref (demux->new_segment);
2055 /* On port from 0.10, discarded !update (for segment.update) here, FIXME? */
2056 demux->new_segment = gst_event_new_segment (&demux->common.segment);
2057 GST_OBJECT_UNLOCK (demux);
2059 /* restart our task since it might have been stopped when we did the
2061 demux->segment_running = TRUE;
2062 gst_pad_start_task (demux->common.sinkpad,
2063 (GstTaskFunction) gst_matroska_demux_loop, demux->common.sinkpad);
2065 /* streaming can continue now */
2066 GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
2072 GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
2073 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Got a seek error"));
2079 * Handle whether we can perform the seek event or if we have to let the chain
2080 * function handle seeks to build the seek indexes first.
2083 gst_matroska_demux_handle_seek_push (GstMatroskaDemux * demux, GstPad * pad,
2087 GstSeekType cur_type, stop_type;
2092 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2097 /* we can only seek on time */
2098 if (format != GST_FORMAT_TIME) {
2099 GST_DEBUG_OBJECT (demux, "Can only seek on TIME");
2103 if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
2104 GST_DEBUG_OBJECT (demux, "Seek end-time not supported in streaming mode");
2108 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
2109 GST_DEBUG_OBJECT (demux,
2110 "Non-flushing seek not supported in streaming mode");
2114 if (flags & GST_SEEK_FLAG_SEGMENT) {
2115 GST_DEBUG_OBJECT (demux, "Segment seek not supported in streaming mode");
2119 /* check for having parsed index already */
2120 if (!demux->common.index_parsed) {
2121 gboolean building_index;
2124 if (!demux->index_offset) {
2125 GST_DEBUG_OBJECT (demux, "no index (location); no seek in push mode");
2129 GST_OBJECT_LOCK (demux);
2130 /* handle the seek event in the chain function */
2131 demux->common.state = GST_MATROSKA_READ_STATE_SEEK;
2132 /* no more seek can be issued until state reset to _DATA */
2134 /* copy the event */
2135 if (demux->seek_event)
2136 gst_event_unref (demux->seek_event);
2137 demux->seek_event = gst_event_ref (event);
2139 /* set the building_index flag so that only one thread can setup the
2140 * structures for index seeking. */
2141 building_index = demux->building_index;
2142 if (!building_index) {
2143 demux->building_index = TRUE;
2144 offset = demux->index_offset;
2146 GST_OBJECT_UNLOCK (demux);
2148 if (!building_index) {
2149 /* seek to the first subindex or legacy index */
2150 GST_INFO_OBJECT (demux, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
2151 return perform_seek_to_offset (demux, offset);
2154 /* well, we are handling it already */
2158 /* delegate to tweaked regular seek */
2159 return gst_matroska_demux_handle_seek_event (demux, pad, event);
2163 gst_matroska_demux_handle_src_event (GstPad * pad, GstObject * parent,
2166 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
2167 gboolean res = TRUE;
2169 switch (GST_EVENT_TYPE (event)) {
2170 case GST_EVENT_SEEK:
2171 /* no seeking until we are (safely) ready */
2172 if (demux->common.state != GST_MATROSKA_READ_STATE_DATA) {
2173 GST_DEBUG_OBJECT (demux, "not ready for seeking yet");
2176 if (!demux->streaming)
2177 res = gst_matroska_demux_handle_seek_event (demux, pad, event);
2179 res = gst_matroska_demux_handle_seek_push (demux, pad, event);
2180 gst_event_unref (event);
2185 GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
2186 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2187 GstMatroskaTrackVideoContext *videocontext =
2188 (GstMatroskaTrackVideoContext *) context;
2190 GstClockTimeDiff diff;
2191 GstClockTime timestamp;
2193 gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
2195 GST_OBJECT_LOCK (demux);
2196 videocontext->earliest_time = timestamp + diff;
2197 GST_OBJECT_UNLOCK (demux);
2200 gst_event_unref (event);
2204 /* events we don't need to handle */
2205 case GST_EVENT_NAVIGATION:
2206 gst_event_unref (event);
2210 case GST_EVENT_LATENCY:
2212 res = gst_pad_push_event (demux->common.sinkpad, event);
2219 static GstFlowReturn
2220 gst_matroska_demux_seek_to_previous_keyframe (GstMatroskaDemux * demux)
2222 GstFlowReturn ret = GST_FLOW_UNEXPECTED;
2223 gboolean done = TRUE;
2226 g_return_val_if_fail (demux->seek_index, GST_FLOW_UNEXPECTED);
2227 g_return_val_if_fail (demux->seek_entry < demux->seek_index->len,
2228 GST_FLOW_UNEXPECTED);
2230 GST_DEBUG_OBJECT (demux, "locating previous keyframe");
2232 if (!demux->seek_entry) {
2233 GST_DEBUG_OBJECT (demux, "no earlier index entry");
2237 for (i = 0; i < demux->common.src->len; i++) {
2238 GstMatroskaTrackContext *stream = g_ptr_array_index (demux->common.src, i);
2240 GST_DEBUG_OBJECT (demux, "segment start %" GST_TIME_FORMAT
2241 ", stream %d at %" GST_TIME_FORMAT,
2242 GST_TIME_ARGS (demux->common.segment.start), stream->index,
2243 GST_TIME_ARGS (stream->from_time));
2244 if (GST_CLOCK_TIME_IS_VALID (stream->from_time)) {
2245 if (stream->from_time > demux->common.segment.start) {
2246 GST_DEBUG_OBJECT (demux, "stream %d not finished yet", stream->index);
2250 /* nothing pushed for this stream;
2251 * likely seek entry did not start at keyframe, so all was skipped.
2252 * So we need an earlier entry */
2258 GstMatroskaIndex *entry;
2260 entry = &g_array_index (demux->seek_index, GstMatroskaIndex,
2261 --demux->seek_entry);
2262 if (!gst_matroska_demux_move_to_entry (demux, entry, FALSE))
2272 static GstFlowReturn
2273 gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml)
2275 GstFlowReturn ret = GST_FLOW_OK;
2278 DEBUG_ELEMENT_START (demux, ebml, "Tracks");
2280 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2281 DEBUG_ELEMENT_STOP (demux, ebml, "Tracks", ret);
2285 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2286 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2290 /* one track within the "all-tracks" header */
2291 case GST_MATROSKA_ID_TRACKENTRY:
2292 ret = gst_matroska_demux_add_stream (demux, ebml);
2296 ret = gst_matroska_read_common_parse_skip (&demux->common, ebml,
2301 DEBUG_ELEMENT_STOP (demux, ebml, "Tracks", ret);
2303 demux->tracks_parsed = TRUE;
2309 * Read signed/unsigned "EBML" numbers.
2310 * Return: number of bytes processed.
2314 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
2316 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
2324 while (read <= 8 && !(total & len_mask)) {
2331 if ((total &= (len_mask - 1)) == len_mask - 1)
2336 if (data[n] == 0xff)
2338 total = (total << 8) | data[n];
2342 if (read == num_ffs && total != 0)
2351 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
2356 /* read as unsigned number first */
2357 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
2361 if (unum == G_MAXUINT64)
2364 *num = unum - ((1 << ((7 * res) - 1)) - 1);
2370 * Mostly used for subtitles. We add void filler data for each
2371 * lagging stream to make sure we don't deadlock.
2375 gst_matroska_demux_sync_streams (GstMatroskaDemux * demux)
2379 GST_OBJECT_LOCK (demux);
2381 GST_LOG_OBJECT (demux, "Sync to %" GST_TIME_FORMAT,
2382 GST_TIME_ARGS (demux->common.segment.position));
2384 g_assert (demux->common.num_streams == demux->common.src->len);
2385 for (stream_nr = 0; stream_nr < demux->common.src->len; stream_nr++) {
2386 GstMatroskaTrackContext *context;
2388 context = g_ptr_array_index (demux->common.src, stream_nr);
2390 GST_LOG_OBJECT (demux,
2391 "Checking for resync on stream %d (%" GST_TIME_FORMAT ")", stream_nr,
2392 GST_TIME_ARGS (context->pos));
2394 if (G_LIKELY (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
2395 GST_LOG_OBJECT (demux, "Skipping sync on non-subtitle stream");
2399 /* does it lag? 0.5 seconds is a random threshold...
2400 * lag need only be considered if we have advanced into requested segment */
2401 if (GST_CLOCK_TIME_IS_VALID (context->pos) &&
2402 GST_CLOCK_TIME_IS_VALID (demux->common.segment.position) &&
2403 demux->common.segment.position > demux->common.segment.start &&
2404 context->pos + (GST_SECOND / 2) < demux->common.segment.position) {
2409 new_start = demux->common.segment.position - (GST_SECOND / 2);
2410 if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop))
2411 new_start = MIN (new_start, demux->common.segment.stop);
2412 GST_DEBUG_OBJECT (demux,
2413 "Synchronizing stream %d with others by advancing time " "from %"
2414 GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr,
2415 GST_TIME_ARGS (context->pos), GST_TIME_ARGS (new_start));
2417 context->pos = new_start;
2419 /* advance stream time */
2420 segment = demux->common.segment;
2421 segment.start = new_start;
2422 segment.position = new_start;
2423 event = gst_event_new_segment (&segment);
2424 GST_OBJECT_UNLOCK (demux);
2425 gst_pad_push_event (context->pad, event);
2426 GST_OBJECT_LOCK (demux);
2430 GST_OBJECT_UNLOCK (demux);
2433 static GstFlowReturn
2434 gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux,
2435 GstMatroskaTrackContext * stream, guint8 * data, guint len)
2437 GstFlowReturn ret, cret;
2438 GstBuffer *header_buf;
2440 header_buf = gst_buffer_new_wrapped (g_memdup (data, len), len);
2442 if (stream->set_discont) {
2443 GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT);
2444 stream->set_discont = FALSE;
2447 ret = gst_pad_push (stream->pad, header_buf);
2450 cret = gst_matroska_demux_combine_flows (demux, stream, ret);
2455 static GstFlowReturn
2456 gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
2457 GstMatroskaTrackContext * stream)
2463 GST_LOG_OBJECT (demux, "priv data size = %u", stream->codec_priv_size);
2465 pdata = (guint8 *) stream->codec_priv;
2467 /* need at least 'fLaC' marker + STREAMINFO metadata block */
2468 if (stream->codec_priv_size < ((4) + (4 + 34))) {
2469 GST_WARNING_OBJECT (demux, "not enough codec priv data for flac headers");
2470 return GST_FLOW_ERROR;
2473 if (memcmp (pdata, "fLaC", 4) != 0) {
2474 GST_WARNING_OBJECT (demux, "no flac marker at start of stream headers");
2475 return GST_FLOW_ERROR;
2478 ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4);
2479 if (ret != GST_FLOW_OK)
2482 off = 4; /* skip fLaC marker */
2483 while (off < stream->codec_priv_size) {
2484 len = GST_READ_UINT8 (pdata + off + 1) << 16;
2485 len |= GST_READ_UINT8 (pdata + off + 2) << 8;
2486 len |= GST_READ_UINT8 (pdata + off + 3);
2488 GST_DEBUG_OBJECT (demux, "header packet: len=%u bytes, flags=0x%02x",
2489 len, (guint) pdata[off]);
2491 ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len + 4);
2492 if (ret != GST_FLOW_OK)
2500 static GstFlowReturn
2501 gst_matroska_demux_push_speex_codec_priv_data (GstMatroskaDemux * demux,
2502 GstMatroskaTrackContext * stream)
2505 guint8 *pdata = stream->codec_priv;
2507 GST_LOG_OBJECT (demux, "priv data size = %u", stream->codec_priv_size);
2509 /* need at least 'fLaC' marker + STREAMINFO metadata block */
2510 if (stream->codec_priv_size < 80) {
2511 GST_WARNING_OBJECT (demux, "not enough codec priv data for speex headers");
2512 return GST_FLOW_ERROR;
2515 if (memcmp (pdata, "Speex ", 8) != 0) {
2516 GST_WARNING_OBJECT (demux, "no Speex marker at start of stream headers");
2517 return GST_FLOW_ERROR;
2520 ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 80);
2521 if (ret != GST_FLOW_OK)
2524 if (stream->codec_priv_size == 80)
2527 return gst_matroska_demux_push_hdr_buf (demux, stream, pdata + 80,
2528 stream->codec_priv_size - 80);
2531 static GstFlowReturn
2532 gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
2533 GstMatroskaTrackContext * stream)
2536 guint8 *p = stream->codec_priv;
2537 gint i, offset, num_packets;
2538 guint *length, last;
2540 if (stream->codec_priv == NULL || stream->codec_priv_size == 0) {
2541 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2542 ("Missing codec private data for xiph headers, broken file"));
2543 return GST_FLOW_ERROR;
2546 /* start of the stream and vorbis audio or theora video, need to
2547 * send the codec_priv data as first three packets */
2548 num_packets = p[0] + 1;
2549 GST_DEBUG_OBJECT (demux, "%u stream headers, total length=%u bytes",
2550 (guint) num_packets, stream->codec_priv_size);
2552 length = g_alloca (num_packets * sizeof (guint));
2556 /* first packets, read length values */
2557 for (i = 0; i < num_packets - 1; i++) {
2559 while (offset < stream->codec_priv_size) {
2560 length[i] += p[offset];
2561 if (p[offset++] != 0xff)
2566 if (offset + last > stream->codec_priv_size)
2567 return GST_FLOW_ERROR;
2569 /* last packet is the remaining size */
2570 length[i] = stream->codec_priv_size - offset - last;
2572 for (i = 0; i < num_packets; i++) {
2573 GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i,
2575 if (offset + length[i] > stream->codec_priv_size)
2576 return GST_FLOW_ERROR;
2579 gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length[i]);
2580 if (ret != GST_FLOW_OK)
2583 offset += length[i];
2589 gst_matroska_demux_push_dvd_clut_change_event (GstMatroskaDemux * demux,
2590 GstMatroskaTrackContext * stream)
2594 g_assert (!strcmp (stream->codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB));
2596 if (!stream->codec_priv)
2599 /* ideally, VobSub private data should be parsed and stored more convenient
2600 * elsewhere, but for now, only interested in a small part */
2602 /* make sure we have terminating 0 */
2603 buf = g_strndup (stream->codec_priv, stream->codec_priv_size);
2605 /* just locate and parse palette part */
2606 start = strstr (buf, "palette:");
2611 guint8 r, g, b, y, u, v;
2614 while (g_ascii_isspace (*start))
2616 for (i = 0; i < 16; i++) {
2617 if (sscanf (start, "%06x", &col) != 1)
2620 while ((*start == ',') || g_ascii_isspace (*start))
2622 /* sigh, need to convert this from vobsub pseudo-RGB to YUV */
2623 r = (col >> 16) & 0xff;
2624 g = (col >> 8) & 0xff;
2626 y = CLAMP ((0.1494 * r + 0.6061 * g + 0.2445 * b) * 219 / 255 + 16, 0,
2628 u = CLAMP (0.6066 * r - 0.4322 * g - 0.1744 * b + 128, 0, 255);
2629 v = CLAMP (-0.08435 * r - 0.3422 * g + 0.4266 * b + 128, 0, 255);
2630 clut[i] = (y << 16) | (u << 8) | v;
2633 /* got them all without problems; build and send event */
2637 s = gst_structure_new ("application/x-gst-dvd", "event", G_TYPE_STRING,
2638 "dvd-spu-clut-change", "clut00", G_TYPE_INT, clut[0], "clut01",
2639 G_TYPE_INT, clut[1], "clut02", G_TYPE_INT, clut[2], "clut03",
2640 G_TYPE_INT, clut[3], "clut04", G_TYPE_INT, clut[4], "clut05",
2641 G_TYPE_INT, clut[5], "clut06", G_TYPE_INT, clut[6], "clut07",
2642 G_TYPE_INT, clut[7], "clut08", G_TYPE_INT, clut[8], "clut09",
2643 G_TYPE_INT, clut[9], "clut10", G_TYPE_INT, clut[10], "clut11",
2644 G_TYPE_INT, clut[11], "clut12", G_TYPE_INT, clut[12], "clut13",
2645 G_TYPE_INT, clut[13], "clut14", G_TYPE_INT, clut[14], "clut15",
2646 G_TYPE_INT, clut[15], NULL);
2648 gst_pad_push_event (stream->pad,
2649 gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s));
2655 static GstFlowReturn
2656 gst_matroska_demux_add_mpeg_seq_header (GstElement * element,
2657 GstMatroskaTrackContext * stream, GstBuffer ** buf)
2660 guint seq_header_len;
2661 guint32 header, tmp;
2663 if (stream->codec_state) {
2664 seq_header = stream->codec_state;
2665 seq_header_len = stream->codec_state_size;
2666 } else if (stream->codec_priv) {
2667 seq_header = stream->codec_priv;
2668 seq_header_len = stream->codec_priv_size;
2673 /* Sequence header only needed for keyframes */
2674 if (GST_BUFFER_FLAG_IS_SET (*buf, GST_BUFFER_FLAG_DELTA_UNIT))
2677 if (gst_buffer_get_size (*buf) < 4)
2680 gst_buffer_extract (*buf, 0, &tmp, sizeof (guint32));
2681 header = GUINT32_FROM_BE (tmp);
2683 /* Sequence start code, if not found prepend */
2684 if (header != 0x000001b3) {
2687 GST_DEBUG_OBJECT (element, "Prepending MPEG sequence header");
2689 newbuf = gst_buffer_new_wrapped (g_memdup (seq_header, seq_header_len),
2692 gst_buffer_copy_into (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS |
2693 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_MEMORY, 0,
2694 gst_buffer_get_size (*buf));
2696 gst_buffer_unref (*buf);
2703 static GstFlowReturn
2704 gst_matroska_demux_add_wvpk_header (GstElement * element,
2705 GstMatroskaTrackContext * stream, GstBuffer ** buf)
2707 GstMatroskaTrackAudioContext *audiocontext =
2708 (GstMatroskaTrackAudioContext *) stream;
2709 GstBuffer *newbuf = NULL;
2710 guint8 *buf_data, *data;
2718 wvh.version = GST_READ_UINT16_LE (stream->codec_priv);
2721 wvh.total_samples = -1;
2722 wvh.block_index = audiocontext->wvpk_block_index;
2724 if (audiocontext->channels <= 2) {
2725 guint32 block_samples, tmp;
2726 gsize size = gst_buffer_get_size (*buf);
2728 gst_buffer_extract (*buf, 0, &tmp, sizeof (guint32));
2729 block_samples = GUINT32_FROM_LE (tmp);
2730 /* we need to reconstruct the header of the wavpack block */
2732 /* -20 because ck_size is the size of the wavpack block -8
2733 * and lace_size is the size of the wavpack block + 12
2734 * (the three guint32 of the header that already are in the buffer) */
2735 wvh.ck_size = size + sizeof (Wavpack4Header) - 20;
2737 /* block_samples, flags and crc are already in the buffer */
2738 newbuf = gst_buffer_new_allocate (NULL, sizeof (Wavpack4Header) - 12, 0);
2740 data = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE);
2745 GST_WRITE_UINT32_LE (data + 4, wvh.ck_size);
2746 GST_WRITE_UINT16_LE (data + 8, wvh.version);
2747 GST_WRITE_UINT8 (data + 10, wvh.track_no);
2748 GST_WRITE_UINT8 (data + 11, wvh.index_no);
2749 GST_WRITE_UINT32_LE (data + 12, wvh.total_samples);
2750 GST_WRITE_UINT32_LE (data + 16, wvh.block_index);
2752 /* Append data from buf: */
2753 gst_buffer_copy_into (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS |
2754 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_MEMORY, 0, size);
2756 gst_buffer_unref (*buf);
2758 audiocontext->wvpk_block_index += block_samples;
2760 guint8 *outdata = NULL;
2762 gsize buf_size, size, out_size = 0;
2763 guint32 block_samples, flags, crc, blocksize;
2765 buf_data = gst_buffer_map (*buf, &buf_size, NULL, GST_MAP_READ);
2768 GST_ERROR_OBJECT (element, "Too small wavpack buffer");
2769 gst_buffer_unmap (*buf, buf_data, buf_size);
2770 return GST_FLOW_ERROR;
2776 block_samples = GST_READ_UINT32_LE (data);
2781 flags = GST_READ_UINT32_LE (data);
2784 crc = GST_READ_UINT32_LE (data);
2787 blocksize = GST_READ_UINT32_LE (data);
2791 if (blocksize == 0 || size < blocksize)
2794 g_assert ((newbuf == NULL) == (outdata == NULL));
2796 if (newbuf == NULL) {
2797 out_size = sizeof (Wavpack4Header) + blocksize;
2798 newbuf = gst_buffer_new_allocate (NULL, out_size, 0);
2800 gst_buffer_copy_into (newbuf, *buf,
2801 GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1);
2804 outdata = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE);
2806 gst_buffer_unmap (newbuf, outdata, out_size);
2807 out_size += sizeof (Wavpack4Header) + blocksize;
2808 gst_buffer_set_size (newbuf, out_size);
2809 outdata = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE);
2812 outdata[outpos] = 'w';
2813 outdata[outpos + 1] = 'v';
2814 outdata[outpos + 2] = 'p';
2815 outdata[outpos + 3] = 'k';
2818 GST_WRITE_UINT32_LE (outdata + outpos,
2819 blocksize + sizeof (Wavpack4Header) - 8);
2820 GST_WRITE_UINT16_LE (outdata + outpos + 4, wvh.version);
2821 GST_WRITE_UINT8 (outdata + outpos + 6, wvh.track_no);
2822 GST_WRITE_UINT8 (outdata + outpos + 7, wvh.index_no);
2823 GST_WRITE_UINT32_LE (outdata + outpos + 8, wvh.total_samples);
2824 GST_WRITE_UINT32_LE (outdata + outpos + 12, wvh.block_index);
2825 GST_WRITE_UINT32_LE (outdata + outpos + 16, block_samples);
2826 GST_WRITE_UINT32_LE (outdata + outpos + 20, flags);
2827 GST_WRITE_UINT32_LE (outdata + outpos + 24, crc);
2830 g_memmove (outdata + outpos, data, blocksize);
2831 outpos += blocksize;
2835 gst_buffer_unmap (*buf, buf_data, buf_size);
2836 gst_buffer_unref (*buf);
2839 gst_buffer_unmap (newbuf, outdata, out_size);
2842 audiocontext->wvpk_block_index += block_samples;
2848 /* @text must be null-terminated */
2850 gst_matroska_demux_subtitle_chunk_has_tag (GstElement * element,
2855 /* yes, this might all lead to false positives ... */
2856 tag = (gchar *) text;
2857 while ((tag = strchr (tag, '<'))) {
2859 if (*tag != '\0' && *(tag + 1) == '>') {
2860 /* some common convenience ones */
2861 /* maybe any character will do here ? */
2874 if (strstr (text, "<span"))
2880 static GstFlowReturn
2881 gst_matroska_demux_check_subtitle_buffer (GstElement * element,
2882 GstMatroskaTrackContext * stream, GstBuffer ** buf)
2884 GstMatroskaTrackSubtitleContext *sub_stream;
2885 const gchar *encoding;
2892 sub_stream = (GstMatroskaTrackSubtitleContext *) stream;
2894 data = gst_buffer_map (*buf, &size, NULL, GST_MAP_READ);
2896 if (!sub_stream->invalid_utf8) {
2897 if (g_utf8_validate (data, size, NULL)) {
2900 GST_WARNING_OBJECT (element, "subtitle stream %d is not valid UTF-8, this "
2901 "is broken according to the matroska specification", stream->num);
2902 sub_stream->invalid_utf8 = TRUE;
2905 /* file with broken non-UTF8 subtitle, do the best we can do to fix it */
2906 encoding = g_getenv ("GST_SUBTITLE_ENCODING");
2907 if (encoding == NULL || *encoding == '\0') {
2908 /* if local encoding is UTF-8 and no encoding specified
2909 * via the environment variable, assume ISO-8859-15 */
2910 if (g_get_charset (&encoding)) {
2911 encoding = "ISO-8859-15";
2915 utf8 = g_convert_with_fallback (data, size, "UTF-8", encoding, (char *) "*",
2919 GST_LOG_OBJECT (element, "could not convert string from '%s' to UTF-8: %s",
2920 encoding, err->message);
2924 /* invalid input encoding, fall back to ISO-8859-15 (always succeeds) */
2925 encoding = "ISO-8859-15";
2926 utf8 = g_convert_with_fallback (data, size, "UTF-8", encoding, (char *) "*",
2930 GST_LOG_OBJECT (element, "converted subtitle text from %s to UTF-8 %s",
2931 encoding, (err) ? "(using ISO-8859-15 as fallback)" : "");
2934 utf8 = g_strdup ("invalid subtitle");
2936 newbuf = gst_buffer_new_wrapped (utf8, strlen (utf8));
2937 gst_buffer_copy_into (newbuf, *buf,
2938 GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_META,
2940 gst_buffer_unmap (*buf, data, size);
2942 gst_buffer_unref (*buf);
2945 data = gst_buffer_map (*buf, &size, NULL, GST_MAP_READ);
2948 if (sub_stream->check_markup) {
2949 /* caps claim markup text, so we need to escape text,
2950 * except if text is already markup and then needs no further escaping */
2951 sub_stream->seen_markup_tag = sub_stream->seen_markup_tag ||
2952 gst_matroska_demux_subtitle_chunk_has_tag (element, data);
2954 if (!sub_stream->seen_markup_tag) {
2955 utf8 = g_markup_escape_text (data, size);
2957 newbuf = gst_buffer_new_wrapped (utf8, strlen (utf8));
2958 gst_buffer_copy_into (newbuf, *buf,
2959 GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS |
2960 GST_BUFFER_COPY_META, 0, -1);
2961 gst_buffer_unmap (*buf, data, size);
2962 gst_buffer_unref (*buf);
2971 static GstFlowReturn
2972 gst_matroska_demux_check_aac (GstElement * element,
2973 GstMatroskaTrackContext * stream, GstBuffer ** buf)
2978 gst_buffer_extract (*buf, 0, data, 2);
2979 size = gst_buffer_get_size (*buf);
2981 if (size > 2 && data[0] == 0xff && (data[1] >> 4 == 0x0f)) {
2985 /* tss, ADTS data, remove codec_data
2986 * still assume it is at least parsed */
2987 new_caps = gst_caps_copy (stream->caps);
2988 s = gst_caps_get_structure (new_caps, 0);
2990 gst_structure_remove_field (s, "codec_data");
2991 gst_caps_replace (&stream->caps, new_caps);
2992 gst_pad_set_caps (stream->pad, new_caps);
2993 GST_DEBUG_OBJECT (element, "ADTS AAC audio data; removing codec-data, "
2994 "new caps: %" GST_PTR_FORMAT, new_caps);
2995 gst_caps_unref (new_caps);
2998 /* disable subsequent checking */
2999 stream->postprocess_frame = NULL;
3005 gst_matroska_demux_align_buffer (GstMatroskaDemux * demux,
3006 GstBuffer * buffer, gsize alignment)
3011 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
3013 if (size < sizeof (guintptr)) {
3014 gst_buffer_unmap (buffer, data, size);
3018 if (((guintptr) data) & (alignment - 1)) {
3019 GstBuffer *new_buffer;
3022 new_buffer = gst_buffer_new_allocate (NULL,
3023 gst_buffer_get_size (buffer), alignment);
3024 /* Copy data "by hand", so ensure alignment is kept: */
3025 new_data = gst_buffer_map (new_buffer, NULL, NULL, GST_MAP_WRITE);
3026 memcpy (new_data, data, size);
3027 gst_buffer_unmap (new_buffer, new_data, -1);
3028 gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
3029 GST_DEBUG_OBJECT (demux, "We want output aligned on %d, reallocated",
3032 gst_buffer_unmap (buffer, data, size);
3033 gst_buffer_unref (buffer);
3038 gst_buffer_unmap (buffer, data, size);
3042 static GstFlowReturn
3043 gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
3044 GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
3045 gboolean is_simpleblock)
3047 GstMatroskaTrackContext *stream = NULL;
3048 GstFlowReturn ret = GST_FLOW_OK;
3049 gboolean readblock = FALSE;
3051 guint64 block_duration = -1;
3052 GstBuffer *buf = NULL;
3053 gpointer buf_data = NULL;
3055 gint stream_num = -1, n, laces = 0;
3057 gint *lace_size = NULL;
3060 gint64 referenceblock = 0;
3063 offset = gst_ebml_read_get_offset (ebml);
3065 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3066 if (!is_simpleblock) {
3067 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
3071 id = GST_MATROSKA_ID_SIMPLEBLOCK;
3075 /* one block inside the group. Note, block parsing is one
3076 * of the harder things, so this code is a bit complicated.
3077 * See http://www.matroska.org/ for documentation. */
3078 case GST_MATROSKA_ID_SIMPLEBLOCK:
3079 case GST_MATROSKA_ID_BLOCK:
3085 gst_buffer_unmap (buf, buf_data, buf_size);
3086 gst_buffer_unref (buf);
3089 if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
3092 buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
3096 /* first byte(s): blocknum */
3097 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3102 /* fetch stream from num */
3103 stream_num = gst_matroska_read_common_stream_from_num (&demux->common,
3105 if (G_UNLIKELY (size < 3)) {
3106 GST_WARNING_OBJECT (demux, "Invalid size %u", size);
3107 /* non-fatal, try next block(group) */
3110 } else if (G_UNLIKELY (stream_num < 0 ||
3111 stream_num >= demux->common.num_streams)) {
3112 /* let's not give up on a stray invalid track number */
3113 GST_WARNING_OBJECT (demux,
3114 "Invalid stream %d for track number %" G_GUINT64_FORMAT
3115 "; ignoring block", stream_num, num);
3119 stream = g_ptr_array_index (demux->common.src, stream_num);
3121 /* time (relative to cluster time) */
3122 time = ((gint16) GST_READ_UINT16_BE (data));
3125 flags = GST_READ_UINT8 (data);
3129 GST_LOG_OBJECT (demux, "time %" G_GUINT64_FORMAT ", flags %d", time,
3132 switch ((flags & 0x06) >> 1) {
3133 case 0x0: /* no lacing */
3135 lace_size = g_new (gint, 1);
3136 lace_size[0] = size;
3139 case 0x1: /* xiph lacing */
3140 case 0x2: /* fixed-size lacing */
3141 case 0x3: /* EBML lacing */
3143 goto invalid_lacing;
3144 laces = GST_READ_UINT8 (data) + 1;
3147 lace_size = g_new0 (gint, laces);
3149 switch ((flags & 0x06) >> 1) {
3150 case 0x1: /* xiph lacing */ {
3151 guint temp, total = 0;
3153 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
3156 goto invalid_lacing;
3157 temp = GST_READ_UINT8 (data);
3158 lace_size[n] += temp;
3164 total += lace_size[n];
3166 lace_size[n] = size - total;
3170 case 0x2: /* fixed-size lacing */
3171 for (n = 0; n < laces; n++)
3172 lace_size[n] = size / laces;
3175 case 0x3: /* EBML lacing */ {
3178 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3182 total = lace_size[0] = num;
3183 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
3187 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
3191 lace_size[n] = lace_size[n - 1] + snum;
3192 total += lace_size[n];
3195 lace_size[n] = size - total;
3202 if (stream->send_xiph_headers) {
3203 ret = gst_matroska_demux_push_xiph_codec_priv_data (demux, stream);
3204 stream->send_xiph_headers = FALSE;
3207 if (stream->send_flac_headers) {
3208 ret = gst_matroska_demux_push_flac_codec_priv_data (demux, stream);
3209 stream->send_flac_headers = FALSE;
3212 if (stream->send_speex_headers) {
3213 ret = gst_matroska_demux_push_speex_codec_priv_data (demux, stream);
3214 stream->send_speex_headers = FALSE;
3217 if (stream->send_dvd_event) {
3218 gst_matroska_demux_push_dvd_clut_change_event (demux, stream);
3219 /* FIXME: should we send this event again after (flushing) seek ? */
3220 stream->send_dvd_event = FALSE;
3223 if (ret != GST_FLOW_OK)
3230 case GST_MATROSKA_ID_BLOCKDURATION:{
3231 ret = gst_ebml_read_uint (ebml, &id, &block_duration);
3232 GST_DEBUG_OBJECT (demux, "BlockDuration: %" G_GUINT64_FORMAT,
3237 case GST_MATROSKA_ID_REFERENCEBLOCK:{
3238 ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
3239 GST_DEBUG_OBJECT (demux, "ReferenceBlock: %" G_GINT64_FORMAT,
3244 case GST_MATROSKA_ID_CODECSTATE:{
3246 guint64 data_len = 0;
3249 gst_ebml_read_binary (ebml, &id, &data,
3250 &data_len)) != GST_FLOW_OK)
3253 if (G_UNLIKELY (stream == NULL)) {
3254 GST_WARNING_OBJECT (demux,
3255 "Unexpected CodecState subelement - ignoring");
3259 g_free (stream->codec_state);
3260 stream->codec_state = data;
3261 stream->codec_state_size = data_len;
3263 /* Decode if necessary */
3264 if (stream->encodings && stream->encodings->len > 0
3265 && stream->codec_state && stream->codec_state_size > 0) {
3266 if (!gst_matroska_decode_data (stream->encodings,
3267 &stream->codec_state, &stream->codec_state_size,
3268 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
3269 GST_WARNING_OBJECT (demux, "Decoding codec state failed");
3273 GST_DEBUG_OBJECT (demux, "CodecState of %u bytes",
3274 stream->codec_state_size);
3279 ret = gst_matroska_read_common_parse_skip (&demux->common, ebml,
3283 case GST_MATROSKA_ID_BLOCKVIRTUAL:
3284 case GST_MATROSKA_ID_BLOCKADDITIONS:
3285 case GST_MATROSKA_ID_REFERENCEPRIORITY:
3286 case GST_MATROSKA_ID_REFERENCEVIRTUAL:
3287 case GST_MATROSKA_ID_SLICES:
3288 GST_DEBUG_OBJECT (demux,
3289 "Skipping BlockGroup subelement 0x%x - ignoring", id);
3290 ret = gst_ebml_read_skip (ebml);
3298 /* reading a number or so could have failed */
3299 if (ret != GST_FLOW_OK)
3302 if (ret == GST_FLOW_OK && readblock) {
3303 guint64 duration = 0;
3304 gint64 lace_time = 0;
3305 gboolean delta_unit;
3307 stream = g_ptr_array_index (demux->common.src, stream_num);
3309 if (cluster_time != GST_CLOCK_TIME_NONE) {
3310 /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
3311 * Drop unless the lace contains timestamp 0? */
3312 if (time < 0 && (-time) > cluster_time) {
3315 if (stream->timecodescale == 1.0)
3316 lace_time = (cluster_time + time) * demux->common.time_scale;
3319 gst_util_guint64_to_gdouble ((cluster_time + time) *
3320 demux->common.time_scale) * stream->timecodescale;
3323 lace_time = GST_CLOCK_TIME_NONE;
3326 /* need to refresh segment info ASAP */
3327 if (GST_CLOCK_TIME_IS_VALID (lace_time) && demux->need_segment) {
3328 GstSegment *segment = &demux->common.segment;
3329 guint64 segment_duration = 0;
3331 GST_DEBUG_OBJECT (demux,
3332 "generating segment starting at %" GST_TIME_FORMAT,
3333 GST_TIME_ARGS (lace_time));
3334 if (!GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
3335 demux->stream_start_time = lace_time;
3336 GST_DEBUG_OBJECT (demux,
3337 "Setting stream start time to %" GST_TIME_FORMAT,
3338 GST_TIME_ARGS (lace_time));
3340 if (GST_CLOCK_TIME_IS_VALID (segment->stop))
3341 segment_duration = segment->stop - segment->start;
3342 else if (GST_CLOCK_TIME_IS_VALID (segment->position))
3343 segment_duration = segment->position - segment->start;
3344 segment->base += segment_duration / fabs (segment->rate);
3345 segment->start = lace_time;
3346 segment->stop = GST_CLOCK_TIME_NONE;
3347 segment->position = lace_time - demux->stream_start_time;
3348 /* now convey our segment notion downstream */
3349 gst_matroska_demux_send_event (demux, gst_event_new_segment (segment));
3350 demux->need_segment = FALSE;
3353 if (block_duration != -1) {
3354 if (stream->timecodescale == 1.0)
3355 duration = gst_util_uint64_scale (block_duration,
3356 demux->common.time_scale, 1);
3359 gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
3360 (gst_util_uint64_scale (block_duration, demux->common.time_scale,
3361 1)) * stream->timecodescale);
3362 } else if (stream->default_duration) {
3363 duration = stream->default_duration * laces;
3365 /* else duration is diff between timecode of this and next block */
3367 /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
3368 a ReferenceBlock implies that this is not a keyframe. In either
3369 case, it only makes sense for video streams. */
3370 delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3371 ((is_simpleblock && !(flags & 0x80)) || referenceblock);
3373 if (delta_unit && stream->set_discont) {
3374 /* When doing seeks or such, we need to restart on key frames or
3375 * decoders might choke. */
3376 GST_DEBUG_OBJECT (demux, "skipping delta unit");
3380 for (n = 0; n < laces; n++) {
3383 if (G_UNLIKELY (lace_size[n] > size)) {
3384 GST_WARNING_OBJECT (demux, "Invalid lace size");
3388 /* QoS for video track with an index. the assumption is that
3389 index entries point to keyframes, but if that is not true we
3390 will instad skip until the next keyframe. */
3391 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3392 stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3393 stream->index_table && demux->common.segment.rate > 0.0) {
3394 GstMatroskaTrackVideoContext *videocontext =
3395 (GstMatroskaTrackVideoContext *) stream;
3396 GstClockTime earliest_time;
3397 GstClockTime earliest_stream_time;
3399 GST_OBJECT_LOCK (demux);
3400 earliest_time = videocontext->earliest_time;
3401 GST_OBJECT_UNLOCK (demux);
3402 earliest_stream_time = gst_segment_to_position (&demux->common.segment,
3403 GST_FORMAT_TIME, earliest_time);
3405 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3406 GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
3407 lace_time <= earliest_stream_time) {
3408 /* find index entry (keyframe) <= earliest_stream_time */
3409 GstMatroskaIndex *entry =
3410 gst_util_array_binary_search (stream->index_table->data,
3411 stream->index_table->len, sizeof (GstMatroskaIndex),
3412 (GCompareDataFunc) gst_matroska_index_seek_find,
3413 GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
3415 /* if that entry (keyframe) is after the current the current
3416 buffer, we can skip pushing (and thus decoding) all
3417 buffers until that keyframe. */
3418 if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
3419 entry->time > lace_time) {
3420 GST_LOG_OBJECT (demux, "Skipping lace before late keyframe");
3421 stream->set_discont = TRUE;
3427 sub = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
3428 gst_buffer_get_size (buf) - size, lace_size[n]);
3429 GST_DEBUG_OBJECT (demux, "created subbuffer %p", sub);
3432 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3434 GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3436 if (stream->encodings != NULL && stream->encodings->len > 0)
3437 sub = gst_matroska_decode_buffer (stream, sub);
3440 GST_WARNING_OBJECT (demux, "Decoding buffer failed");
3444 GST_BUFFER_TIMESTAMP (sub) = lace_time;
3446 if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
3447 GstClockTime last_stop_end;
3449 /* Check if this stream is after segment stop */
3450 if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) &&
3451 lace_time >= demux->common.segment.stop) {
3452 GST_DEBUG_OBJECT (demux,
3453 "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
3454 GST_TIME_ARGS (demux->common.segment.stop));
3455 gst_buffer_unref (sub);
3458 if (offset >= stream->to_offset) {
3459 GST_DEBUG_OBJECT (demux, "Stream %d after playback section",
3461 gst_buffer_unref (sub);
3465 /* handle gaps, e.g. non-zero start-time, or an cue index entry
3466 * that landed us with timestamps not quite intended */
3467 GST_OBJECT_LOCK (demux);
3468 if (demux->max_gap_time &&
3469 GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
3470 demux->common.segment.rate > 0.0) {
3471 GstClockTimeDiff diff;
3473 /* only send segments with increasing start times,
3474 * otherwise if these go back and forth downstream (sinks) increase
3475 * accumulated time and running_time */
3476 diff = GST_CLOCK_DIFF (demux->last_stop_end, lace_time);
3477 if (diff > 0 && diff > demux->max_gap_time
3478 && lace_time > demux->common.segment.start
3479 && (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)
3480 || lace_time < demux->common.segment.stop)) {
3482 GstEvent *event1, *event2;
3483 GST_DEBUG_OBJECT (demux,
3484 "Gap of %" G_GINT64_FORMAT " ns detected in"
3485 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
3486 "Sending updated SEGMENT events", diff,
3487 stream->index, GST_TIME_ARGS (stream->pos),
3488 GST_TIME_ARGS (lace_time));
3489 /* send segment events such that the gap is not accounted in
3490 * segment base time, hence running_time */
3491 /* close ahead of gap */
3492 segment = demux->common.segment;
3493 segment.start = demux->last_stop_end;
3494 segment.stop = demux->last_stop_end;
3495 segment.position = demux->last_stop_end;
3496 event1 = gst_event_new_segment (&segment);
3498 segment.start = lace_time;
3499 segment.stop = demux->common.segment.stop;
3500 segment.position = lace_time;
3501 event2 = gst_event_new_segment (&segment);
3502 GST_OBJECT_UNLOCK (demux);
3503 gst_matroska_demux_send_event (demux, event1);
3504 gst_matroska_demux_send_event (demux, event2);
3505 GST_OBJECT_LOCK (demux);
3506 /* align segment view with downstream,
3507 * prevents double-counting base time when closing segment */
3508 /* FIXME: in 0.10, the segment base/accum got updated here, but
3509 * maybe we don't need that because of the double accounting
3510 * mentioned above? */
3511 demux->common.segment = segment;
3515 if (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.position)
3516 || demux->common.segment.position < lace_time) {
3517 demux->common.segment.position = lace_time;
3519 GST_OBJECT_UNLOCK (demux);
3521 last_stop_end = lace_time;
3523 GST_BUFFER_DURATION (sub) = duration / laces;
3524 last_stop_end += GST_BUFFER_DURATION (sub);
3527 if (!GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) ||
3528 demux->last_stop_end < last_stop_end)
3529 demux->last_stop_end = last_stop_end;
3531 GST_OBJECT_LOCK (demux);
3532 if (demux->common.segment.duration == -1 ||
3533 demux->common.segment.duration <
3534 lace_time - demux->stream_start_time) {
3535 demux->common.segment.duration =
3536 last_stop_end - demux->stream_start_time;
3537 GST_OBJECT_UNLOCK (demux);
3538 gst_element_post_message (GST_ELEMENT_CAST (demux),
3539 gst_message_new_duration (GST_OBJECT_CAST (demux),
3540 GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
3542 GST_OBJECT_UNLOCK (demux);
3546 stream->pos = lace_time;
3548 gst_matroska_demux_sync_streams (demux);
3550 if (stream->set_discont) {
3551 GST_DEBUG_OBJECT (demux, "marking DISCONT");
3552 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
3553 stream->set_discont = FALSE;
3556 /* reverse playback book-keeping */
3557 if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
3558 stream->from_time = lace_time;
3559 if (stream->from_offset == -1)
3560 stream->from_offset = offset;
3562 GST_DEBUG_OBJECT (demux,
3563 "Pushing lace %d, data of size %d for stream %d, time=%"
3564 GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
3565 gst_buffer_get_size (sub), stream_num,
3566 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
3567 GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
3569 if (demux->common.element_index) {
3570 if (stream->index_writer_id == -1)
3571 gst_index_get_writer_id (demux->common.element_index,
3572 GST_OBJECT (stream->pad), &stream->index_writer_id);
3574 GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
3575 G_GUINT64_FORMAT " for writer id %d",
3576 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
3577 stream->index_writer_id);
3578 gst_index_add_association (demux->common.element_index,
3579 stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
3580 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
3581 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
3582 cluster_offset, NULL);
3585 /* Postprocess the buffers depending on the codec used */
3586 if (stream->postprocess_frame) {
3587 GST_LOG_OBJECT (demux, "running post process");
3588 ret = stream->postprocess_frame (GST_ELEMENT (demux), stream, &sub);
3591 /* At this point, we have a sub-buffer pointing at data within a larger
3592 buffer. This data might not be aligned with anything. If the data is
3593 raw samples though, we want it aligned to the raw type (eg, 4 bytes
3594 for 32 bit samples, etc), or bad things will happen downstream as
3595 elements typically assume minimal alignment.
3596 Therefore, create an aligned copy if necessary. */
3597 g_assert (stream->alignment <= G_MEM_ALIGN);
3598 sub = gst_matroska_demux_align_buffer (demux, sub, stream->alignment);
3600 ret = gst_pad_push (stream->pad, sub);
3601 if (demux->common.segment.rate < 0) {
3602 if (lace_time > demux->common.segment.stop
3603 && ret == GST_FLOW_UNEXPECTED) {
3604 /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
3605 * we are at the end of the segment, so we just need to jump
3606 * back to the previous section. */
3607 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
3612 ret = gst_matroska_demux_combine_flows (demux, stream, ret);
3615 size -= lace_size[n];
3616 if (lace_time != GST_CLOCK_TIME_NONE && duration)
3617 lace_time += duration / laces;
3619 lace_time = GST_CLOCK_TIME_NONE;
3625 gst_buffer_unmap (buf, buf_data, buf_size);
3626 gst_buffer_unref (buf);
3638 ret = gst_matroska_demux_combine_flows (demux, stream, ret);
3643 GST_ELEMENT_WARNING (demux, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
3644 /* non-fatal, try next block(group) */
3650 GST_ELEMENT_WARNING (demux, STREAM, DEMUX, (NULL), ("Data error"));
3651 /* non-fatal, try next block(group) */
3657 /* return FALSE if block(group) should be skipped (due to a seek) */
3658 static inline gboolean
3659 gst_matroska_demux_seek_block (GstMatroskaDemux * demux)
3661 if (G_UNLIKELY (demux->seek_block)) {
3662 if (!(--demux->seek_block)) {
3665 GST_LOG_OBJECT (demux, "should skip block due to seek");
3673 static GstFlowReturn
3674 gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
3678 guint64 seek_pos = (guint64) - 1;
3679 guint32 seek_id = 0;
3682 DEBUG_ELEMENT_START (demux, ebml, "Seek");
3684 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3685 DEBUG_ELEMENT_STOP (demux, ebml, "Seek", ret);
3689 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3690 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3694 case GST_MATROSKA_ID_SEEKID:
3698 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
3701 GST_DEBUG_OBJECT (demux, "SeekID: %" G_GUINT64_FORMAT, t);
3706 case GST_MATROSKA_ID_SEEKPOSITION:
3710 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
3713 if (t > G_MAXINT64) {
3714 GST_WARNING_OBJECT (demux,
3715 "Too large SeekPosition %" G_GUINT64_FORMAT, t);
3719 GST_DEBUG_OBJECT (demux, "SeekPosition: %" G_GUINT64_FORMAT, t);
3725 ret = gst_matroska_read_common_parse_skip (&demux->common, ebml,
3731 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
3734 if (!seek_id || seek_pos == (guint64) - 1) {
3735 GST_WARNING_OBJECT (demux, "Incomplete seekhead entry (0x%x/%"
3736 G_GUINT64_FORMAT ")", seek_id, seek_pos);
3741 case GST_MATROSKA_ID_SEEKHEAD:
3744 case GST_MATROSKA_ID_CUES:
3745 case GST_MATROSKA_ID_TAGS:
3746 case GST_MATROSKA_ID_TRACKS:
3747 case GST_MATROSKA_ID_SEGMENTINFO:
3748 case GST_MATROSKA_ID_ATTACHMENTS:
3749 case GST_MATROSKA_ID_CHAPTERS:
3751 guint64 before_pos, length;
3755 length = gst_matroska_read_common_get_length (&demux->common);
3756 before_pos = demux->common.offset;
3758 if (length == (guint64) - 1) {
3759 GST_DEBUG_OBJECT (demux, "no upstream length, skipping SeakHead entry");
3763 /* check for validity */
3764 if (seek_pos + demux->common.ebml_segment_start + 12 >= length) {
3765 GST_WARNING_OBJECT (demux,
3766 "SeekHead reference lies outside file!" " (%"
3767 G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
3768 G_GUINT64_FORMAT ")", seek_pos, demux->common.ebml_segment_start,
3773 /* only pick up index location when streaming */
3774 if (demux->streaming) {
3775 if (seek_id == GST_MATROSKA_ID_CUES) {
3776 demux->index_offset = seek_pos + demux->common.ebml_segment_start;
3777 GST_DEBUG_OBJECT (demux, "Cues located at offset %" G_GUINT64_FORMAT,
3778 demux->index_offset);
3784 demux->common.offset = seek_pos + demux->common.ebml_segment_start;
3787 if ((ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
3788 GST_ELEMENT_CAST (demux), &id, &length, &needed)) !=
3792 if (id != seek_id) {
3793 GST_WARNING_OBJECT (demux,
3794 "We looked for ID=0x%x but got ID=0x%x (pos=%" G_GUINT64_FORMAT ")",
3795 seek_id, id, seek_pos + demux->common.ebml_segment_start);
3798 ret = gst_matroska_demux_parse_id (demux, id, length, needed);
3803 demux->common.offset = before_pos;
3807 case GST_MATROSKA_ID_CLUSTER:
3809 guint64 pos = seek_pos + demux->common.ebml_segment_start;
3811 GST_LOG_OBJECT (demux, "Cluster position");
3812 if (G_UNLIKELY (!demux->clusters))
3813 demux->clusters = g_array_sized_new (TRUE, TRUE, sizeof (guint64), 100);
3814 g_array_append_val (demux->clusters, pos);
3819 GST_DEBUG_OBJECT (demux, "Ignoring Seek entry for ID=0x%x", seek_id);
3822 DEBUG_ELEMENT_STOP (demux, ebml, "Seek", ret);
3827 static GstFlowReturn
3828 gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, GstEbmlRead * ebml)
3830 GstFlowReturn ret = GST_FLOW_OK;
3833 DEBUG_ELEMENT_START (demux, ebml, "SeekHead");
3835 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3836 DEBUG_ELEMENT_STOP (demux, ebml, "SeekHead", ret);
3840 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3841 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3845 case GST_MATROSKA_ID_SEEKENTRY:
3847 ret = gst_matroska_demux_parse_contents_seekentry (demux, ebml);
3848 /* Ignore EOS and errors here */
3849 if (ret != GST_FLOW_OK) {
3850 GST_DEBUG_OBJECT (demux, "Ignoring %s", gst_flow_get_name (ret));
3857 ret = gst_matroska_read_common_parse_skip (&demux->common,
3858 ebml, "SeekHead", id);
3863 DEBUG_ELEMENT_STOP (demux, ebml, "SeekHead", ret);
3865 /* Sort clusters by position for easier searching */
3866 if (demux->clusters)
3867 g_array_sort (demux->clusters, (GCompareFunc) gst_matroska_cluster_compare);
3872 #define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
3874 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
3876 static inline GstFlowReturn
3877 gst_matroska_demux_check_read_size (GstMatroskaDemux * demux, guint64 bytes)
3879 if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
3880 /* only a few blocks are expected/allowed to be large,
3881 * and will be recursed into, whereas others will be read and must fit */
3882 if (demux->streaming) {
3883 /* fatal in streaming case, as we can't step over easily */
3884 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3885 ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
3886 "file might be corrupt.", bytes));
3887 return GST_FLOW_ERROR;
3889 /* indicate higher level to quietly give up */
3890 GST_DEBUG_OBJECT (demux,
3891 "too large block of size %" G_GUINT64_FORMAT, bytes);
3892 return GST_FLOW_ERROR;
3899 /* returns TRUE if we truely are in error state, and should give up */
3900 static inline gboolean
3901 gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
3903 if (!demux->streaming && demux->next_cluster_offset > 0) {
3904 /* just repositioning to where next cluster should be and try from there */
3905 GST_WARNING_OBJECT (demux, "parse error, trying next cluster expected at %"
3906 G_GUINT64_FORMAT, demux->next_cluster_offset);
3907 demux->common.offset = demux->next_cluster_offset;
3908 demux->next_cluster_offset = 0;
3913 /* sigh, one last attempt above and beyond call of duty ...;
3914 * search for cluster mark following current pos */
3915 pos = demux->common.offset;
3916 GST_WARNING_OBJECT (demux, "parse error, looking for next cluster");
3917 if (gst_matroska_demux_search_cluster (demux, &pos) != GST_FLOW_OK) {
3918 /* did not work, give up */
3921 GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos);
3922 /* try that position */
3923 demux->common.offset = pos;
3929 static inline GstFlowReturn
3930 gst_matroska_demux_flush (GstMatroskaDemux * demux, guint flush)
3932 GST_LOG_OBJECT (demux, "skipping %d bytes", flush);
3933 demux->common.offset += flush;
3934 if (demux->streaming) {
3937 /* hard to skip large blocks when streaming */
3938 ret = gst_matroska_demux_check_read_size (demux, flush);
3939 if (ret != GST_FLOW_OK)
3941 if (flush <= gst_adapter_available (demux->common.adapter))
3942 gst_adapter_flush (demux->common.adapter, flush);
3944 return GST_FLOW_UNEXPECTED;
3949 /* initializes @ebml with @bytes from input stream at current offset.
3950 * Returns UNEXPECTED if insufficient available,
3951 * ERROR if too much was attempted to read. */
3952 static inline GstFlowReturn
3953 gst_matroska_demux_take (GstMatroskaDemux * demux, guint64 bytes,
3956 GstBuffer *buffer = NULL;
3957 GstFlowReturn ret = GST_FLOW_OK;
3959 GST_LOG_OBJECT (demux, "taking %" G_GUINT64_FORMAT " bytes for parsing",
3961 ret = gst_matroska_demux_check_read_size (demux, bytes);
3962 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
3963 if (!demux->streaming) {
3964 /* in pull mode, we can skip */
3965 if ((ret = gst_matroska_demux_flush (demux, bytes)) == GST_FLOW_OK)
3966 ret = GST_FLOW_OVERFLOW;
3968 /* otherwise fatal */
3969 ret = GST_FLOW_ERROR;
3973 if (demux->streaming) {
3974 if (gst_adapter_available (demux->common.adapter) >= bytes)
3975 buffer = gst_adapter_take_buffer (demux->common.adapter, bytes);
3977 ret = GST_FLOW_UNEXPECTED;
3979 ret = gst_matroska_read_common_peek_bytes (&demux->common,
3980 demux->common.offset, bytes, &buffer, NULL);
3981 if (G_LIKELY (buffer)) {
3982 gst_ebml_read_init (ebml, GST_ELEMENT_CAST (demux), buffer,
3983 demux->common.offset);
3984 demux->common.offset += bytes;
3991 gst_matroska_demux_check_seekability (GstMatroskaDemux * demux)
3994 gboolean seekable = FALSE;
3995 gint64 start = -1, stop = -1;
3997 query = gst_query_new_seeking (GST_FORMAT_BYTES);
3998 if (!gst_pad_peer_query (demux->common.sinkpad, query)) {
3999 GST_DEBUG_OBJECT (demux, "seeking query failed");
4003 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
4005 /* try harder to query upstream size if we didn't get it the first time */
4006 if (seekable && stop == -1) {
4007 GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
4008 gst_pad_peer_query_duration (demux->common.sinkpad, GST_FORMAT_BYTES,
4012 /* if upstream doesn't know the size, it's likely that it's not seekable in
4013 * practice even if it technically may be seekable */
4014 if (seekable && (start != 0 || stop <= start)) {
4015 GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
4020 GST_INFO_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
4021 G_GUINT64_FORMAT ")", seekable, start, stop);
4022 demux->seekable = seekable;
4024 gst_query_unref (query);
4027 static GstFlowReturn
4028 gst_matroska_demux_find_tracks (GstMatroskaDemux * demux)
4034 GstFlowReturn ret = GST_FLOW_OK;
4036 GST_WARNING_OBJECT (demux,
4037 "Found Cluster element before Tracks, searching Tracks");
4040 before_pos = demux->common.offset;
4042 /* Search Tracks element */
4044 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
4045 GST_ELEMENT_CAST (demux), &id, &length, &needed);
4046 if (ret != GST_FLOW_OK)
4049 if (id != GST_MATROSKA_ID_TRACKS) {
4050 /* we may be skipping large cluster here, so forego size check etc */
4051 /* ... but we can't skip undefined size; force error */
4052 if (length == G_MAXUINT64) {
4053 ret = gst_matroska_demux_check_read_size (demux, length);
4056 demux->common.offset += needed;
4057 demux->common.offset += length;
4062 /* will lead to track parsing ... */
4063 ret = gst_matroska_demux_parse_id (demux, id, length, needed);
4068 demux->common.offset = before_pos;
4073 #define GST_READ_CHECK(stmt) \
4075 if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
4076 if (ret == GST_FLOW_OVERFLOW) { \
4077 ret = GST_FLOW_OK; \
4083 static GstFlowReturn
4084 gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
4085 guint64 length, guint needed)
4087 GstEbmlRead ebml = { 0, };
4088 GstFlowReturn ret = GST_FLOW_OK;
4091 GST_LOG_OBJECT (demux, "Parsing Element id 0x%x, "
4092 "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
4094 /* if we plan to read and parse this element, we need prefix (id + length)
4095 * and the contents */
4096 /* mind about overflow wrap-around when dealing with undefined size */
4098 if (G_LIKELY (length != G_MAXUINT64))
4101 switch (demux->common.state) {
4102 case GST_MATROSKA_READ_STATE_START:
4104 case GST_EBML_ID_HEADER:
4105 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4106 ret = gst_matroska_read_common_parse_header (&demux->common, &ebml);
4107 if (ret != GST_FLOW_OK)
4109 demux->common.state = GST_MATROSKA_READ_STATE_SEGMENT;
4110 gst_matroska_demux_check_seekability (demux);
4113 goto invalid_header;
4117 case GST_MATROSKA_READ_STATE_SEGMENT:
4119 case GST_MATROSKA_ID_SEGMENT:
4120 /* eat segment prefix */
4121 GST_READ_CHECK (gst_matroska_demux_flush (demux, needed));
4122 GST_DEBUG_OBJECT (demux,
4123 "Found Segment start at offset %" G_GUINT64_FORMAT,
4124 demux->common.offset);
4125 /* seeks are from the beginning of the segment,
4126 * after the segment ID/length */
4127 demux->common.ebml_segment_start = demux->common.offset;
4128 demux->common.state = GST_MATROSKA_READ_STATE_HEADER;
4131 GST_WARNING_OBJECT (demux,
4132 "Expected a Segment ID (0x%x), but received 0x%x!",
4133 GST_MATROSKA_ID_SEGMENT, id);
4134 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4138 case GST_MATROSKA_READ_STATE_SCANNING:
4139 if (id != GST_MATROSKA_ID_CLUSTER &&
4140 id != GST_MATROSKA_ID_CLUSTERTIMECODE)
4143 case GST_MATROSKA_READ_STATE_HEADER:
4144 case GST_MATROSKA_READ_STATE_DATA:
4145 case GST_MATROSKA_READ_STATE_SEEK:
4147 case GST_MATROSKA_ID_SEGMENTINFO:
4148 if (!demux->common.segmentinfo_parsed) {
4149 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4150 ret = gst_matroska_read_common_parse_info (&demux->common,
4151 GST_ELEMENT_CAST (demux), &ebml);
4153 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4156 case GST_MATROSKA_ID_TRACKS:
4157 if (!demux->tracks_parsed) {
4158 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4159 ret = gst_matroska_demux_parse_tracks (demux, &ebml);
4161 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4164 case GST_MATROSKA_ID_CLUSTER:
4165 if (G_UNLIKELY (!demux->tracks_parsed)) {
4166 if (demux->streaming) {
4167 GST_DEBUG_OBJECT (demux, "Cluster before Track");
4168 goto not_streamable;
4170 ret = gst_matroska_demux_find_tracks (demux);
4171 if (!demux->tracks_parsed)
4175 if (G_UNLIKELY (demux->common.state
4176 == GST_MATROSKA_READ_STATE_HEADER)) {
4177 demux->common.state = GST_MATROSKA_READ_STATE_DATA;
4178 demux->first_cluster_offset = demux->common.offset;
4179 GST_DEBUG_OBJECT (demux, "signaling no more pads");
4180 gst_element_no_more_pads (GST_ELEMENT (demux));
4181 /* send initial segment - we wait till we know the first
4182 incoming timestamp, so we can properly set the start of
4184 demux->need_segment = TRUE;
4186 demux->cluster_time = GST_CLOCK_TIME_NONE;
4187 demux->cluster_offset = demux->common.offset;
4188 if (G_UNLIKELY (!demux->seek_first && demux->seek_block)) {
4189 GST_DEBUG_OBJECT (demux, "seek target block %" G_GUINT64_FORMAT
4190 " not found in Cluster, trying next Cluster's first block instead",
4192 demux->seek_block = 0;
4194 demux->seek_first = FALSE;
4195 /* record next cluster for recovery */
4196 if (read != G_MAXUINT64)
4197 demux->next_cluster_offset = demux->cluster_offset + read;
4198 /* eat cluster prefix */
4199 gst_matroska_demux_flush (demux, needed);
4201 case GST_MATROSKA_ID_CLUSTERTIMECODE:
4205 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4206 if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
4208 GST_DEBUG_OBJECT (demux, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
4209 demux->cluster_time = num;
4210 if (demux->common.element_index) {
4211 if (demux->common.element_index_writer_id == -1)
4212 gst_index_get_writer_id (demux->common.element_index,
4213 GST_OBJECT (demux), &demux->common.element_index_writer_id);
4214 GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
4215 G_GUINT64_FORMAT " for writer id %d",
4216 GST_TIME_ARGS (demux->cluster_time), demux->cluster_offset,
4217 demux->common.element_index_writer_id);
4218 gst_index_add_association (demux->common.element_index,
4219 demux->common.element_index_writer_id,
4220 GST_ASSOCIATION_FLAG_KEY_UNIT,
4221 GST_FORMAT_TIME, demux->cluster_time,
4222 GST_FORMAT_BYTES, demux->cluster_offset, NULL);
4226 case GST_MATROSKA_ID_BLOCKGROUP:
4227 if (!gst_matroska_demux_seek_block (demux))
4229 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4230 DEBUG_ELEMENT_START (demux, &ebml, "BlockGroup");
4231 if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
4232 ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
4233 &ebml, demux->cluster_time, demux->cluster_offset, FALSE);
4235 DEBUG_ELEMENT_STOP (demux, &ebml, "BlockGroup", ret);
4237 case GST_MATROSKA_ID_SIMPLEBLOCK:
4238 if (!gst_matroska_demux_seek_block (demux))
4240 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4241 DEBUG_ELEMENT_START (demux, &ebml, "SimpleBlock");
4242 ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
4243 &ebml, demux->cluster_time, demux->cluster_offset, TRUE);
4244 DEBUG_ELEMENT_STOP (demux, &ebml, "SimpleBlock", ret);
4246 case GST_MATROSKA_ID_ATTACHMENTS:
4247 if (!demux->common.attachments_parsed) {
4248 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4249 ret = gst_matroska_read_common_parse_attachments (&demux->common,
4250 GST_ELEMENT_CAST (demux), &ebml);
4252 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4255 case GST_MATROSKA_ID_TAGS:
4256 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4257 ret = gst_matroska_read_common_parse_metadata (&demux->common,
4258 GST_ELEMENT_CAST (demux), &ebml);
4260 case GST_MATROSKA_ID_CHAPTERS:
4261 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4262 ret = gst_matroska_read_common_parse_chapters (&demux->common, &ebml);
4264 case GST_MATROSKA_ID_SEEKHEAD:
4265 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4266 ret = gst_matroska_demux_parse_contents (demux, &ebml);
4268 case GST_MATROSKA_ID_CUES:
4269 if (demux->common.index_parsed) {
4270 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4273 GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
4274 ret = gst_matroska_read_common_parse_index (&demux->common, &ebml);
4275 /* only push based; delayed index building */
4276 if (ret == GST_FLOW_OK
4277 && demux->common.state == GST_MATROSKA_READ_STATE_SEEK) {
4280 GST_OBJECT_LOCK (demux);
4281 event = demux->seek_event;
4282 demux->seek_event = NULL;
4283 GST_OBJECT_UNLOCK (demux);
4286 /* unlikely to fail, since we managed to seek to this point */
4287 if (!gst_matroska_demux_handle_seek_event (demux, NULL, event))
4289 /* resume data handling, main thread clear to seek again */
4290 GST_OBJECT_LOCK (demux);
4291 demux->common.state = GST_MATROSKA_READ_STATE_DATA;
4292 GST_OBJECT_UNLOCK (demux);
4295 case GST_MATROSKA_ID_POSITION:
4296 case GST_MATROSKA_ID_PREVSIZE:
4297 case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
4298 case GST_MATROSKA_ID_SILENTTRACKS:
4299 GST_DEBUG_OBJECT (demux,
4300 "Skipping Cluster subelement 0x%x - ignoring", id);
4304 GST_DEBUG_OBJECT (demux, "skipping Element 0x%x", id);
4305 GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
4311 if (ret == GST_FLOW_PARSE)
4315 gst_ebml_read_clear (&ebml);
4321 /* simply exit, maybe not enough data yet */
4322 /* no ebml to clear if read error */
4327 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
4328 ("Failed to parse Element 0x%x", id));
4329 ret = GST_FLOW_ERROR;
4334 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
4335 ("File layout does not permit streaming"));
4336 ret = GST_FLOW_ERROR;
4341 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
4342 ("No Tracks element found"));
4343 ret = GST_FLOW_ERROR;
4348 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Invalid header"));
4349 ret = GST_FLOW_ERROR;
4354 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Failed to seek"));
4355 ret = GST_FLOW_ERROR;
4361 gst_matroska_demux_loop (GstPad * pad)
4363 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (pad));
4369 /* If we have to close a segment, send a new segment to do this now */
4370 if (G_LIKELY (demux->common.state == GST_MATROSKA_READ_STATE_DATA)) {
4371 if (G_UNLIKELY (demux->close_segment)) {
4372 gst_matroska_demux_send_event (demux, demux->close_segment);
4373 demux->close_segment = NULL;
4375 if (G_UNLIKELY (demux->new_segment)) {
4376 gst_matroska_demux_send_event (demux, demux->new_segment);
4377 demux->new_segment = NULL;
4381 ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
4382 GST_ELEMENT_CAST (demux), &id, &length, &needed);
4383 if (ret == GST_FLOW_UNEXPECTED)
4385 if (ret != GST_FLOW_OK) {
4386 if (gst_matroska_demux_check_parse_error (demux))
4392 GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4393 "size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id,
4396 ret = gst_matroska_demux_parse_id (demux, id, length, needed);
4397 if (ret == GST_FLOW_UNEXPECTED)
4399 if (ret != GST_FLOW_OK)
4402 /* check if we're at the end of a configured segment */
4403 if (G_LIKELY (demux->common.src->len)) {
4406 g_assert (demux->common.num_streams == demux->common.src->len);
4407 for (i = 0; i < demux->common.src->len; i++) {
4408 GstMatroskaTrackContext *context = g_ptr_array_index (demux->common.src,
4410 GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
4411 GST_TIME_ARGS (context->pos));
4412 if (context->eos == FALSE)
4416 GST_INFO_OBJECT (demux, "All streams are EOS");
4417 ret = GST_FLOW_UNEXPECTED;
4422 if (G_UNLIKELY (demux->common.offset ==
4423 gst_matroska_read_common_get_length (&demux->common))) {
4424 GST_LOG_OBJECT (demux, "Reached end of stream");
4425 ret = GST_FLOW_UNEXPECTED;
4434 if (demux->common.segment.rate < 0.0) {
4435 ret = gst_matroska_demux_seek_to_previous_keyframe (demux);
4436 if (ret == GST_FLOW_OK)
4443 const gchar *reason = gst_flow_get_name (ret);
4444 gboolean push_eos = FALSE;
4446 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
4447 demux->segment_running = FALSE;
4448 gst_pad_pause_task (demux->common.sinkpad);
4450 if (ret == GST_FLOW_UNEXPECTED) {
4451 /* perform EOS logic */
4453 /* If we were in the headers, make sure we send no-more-pads.
4454 This will ensure decodebin2 does not get stuck thinking
4455 the chain is not complete yet, and waiting indefinitely. */
4456 if (G_UNLIKELY (demux->common.state == GST_MATROSKA_READ_STATE_HEADER)) {
4457 if (demux->common.src->len == 0) {
4458 GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL),
4459 ("No pads created"));
4461 GST_ELEMENT_WARNING (demux, STREAM, DEMUX, (NULL),
4462 ("Failed to finish reading headers"));
4464 gst_element_no_more_pads (GST_ELEMENT (demux));
4467 /* Close the segment, i.e. update segment stop with the duration
4468 * if no stop was set */
4469 if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
4470 !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) {
4471 GstSegment segment = demux->common.segment;
4474 segment.stop = MAX (demux->last_stop_end, segment.start);
4475 event = gst_event_new_segment (&segment);
4476 gst_matroska_demux_send_event (demux, event);
4479 if (demux->common.segment.flags & GST_SEEK_FLAG_SEGMENT) {
4482 /* for segment playback we need to post when (in stream time)
4483 * we stopped, this is either stop (when set) or the duration. */
4484 if ((stop = demux->common.segment.stop) == -1)
4485 stop = demux->last_stop_end;
4487 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
4488 gst_element_post_message (GST_ELEMENT (demux),
4489 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
4494 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
4495 /* for fatal errors we post an error message */
4496 GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL),
4497 ("stream stopped, reason %s", reason));
4501 /* send EOS, and prevent hanging if no streams yet */
4502 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
4503 if (!gst_matroska_demux_send_event (demux, gst_event_new_eos ()) &&
4504 (ret == GST_FLOW_UNEXPECTED)) {
4505 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
4506 (NULL), ("got eos but no streams (yet)"));
4514 * Create and push a flushing seek event upstream
4517 perform_seek_to_offset (GstMatroskaDemux * demux, guint64 offset)
4522 GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
4525 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
4526 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
4527 GST_SEEK_TYPE_NONE, -1);
4529 res = gst_pad_push_event (demux->common.sinkpad, event);
4531 /* segment event will update offset */
4535 static GstFlowReturn
4536 gst_matroska_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
4538 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
4540 GstFlowReturn ret = GST_FLOW_OK;
4545 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
4546 GST_DEBUG_OBJECT (demux, "got DISCONT");
4547 gst_adapter_clear (demux->common.adapter);
4548 GST_OBJECT_LOCK (demux);
4549 gst_matroska_read_common_reset_streams (&demux->common,
4550 GST_CLOCK_TIME_NONE, FALSE);
4551 GST_OBJECT_UNLOCK (demux);
4554 gst_adapter_push (demux->common.adapter, buffer);
4558 available = gst_adapter_available (demux->common.adapter);
4560 ret = gst_matroska_read_common_peek_id_length_push (&demux->common,
4561 GST_ELEMENT_CAST (demux), &id, &length, &needed);
4562 if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED))
4565 GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4566 "size %" G_GUINT64_FORMAT ", needed %d, available %d",
4567 demux->common.offset, id, length, needed, available);
4569 if (needed > available)
4572 ret = gst_matroska_demux_parse_id (demux, id, length, needed);
4573 if (ret == GST_FLOW_UNEXPECTED) {
4574 /* need more data */
4576 } else if (ret != GST_FLOW_OK) {
4583 gst_matroska_demux_handle_sink_event (GstPad * pad, GstObject * parent,
4586 gboolean res = TRUE;
4587 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
4589 GST_DEBUG_OBJECT (demux,
4590 "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
4592 switch (GST_EVENT_TYPE (event)) {
4593 case GST_EVENT_SEGMENT:
4595 const GstSegment *segment;
4597 /* some debug output */
4598 gst_event_parse_segment (event, &segment);
4599 /* FIXME: do we need to update segment base here (like accum in 0.10)? */
4600 GST_DEBUG_OBJECT (demux,
4601 "received format %d segment %" GST_SEGMENT_FORMAT, segment->format,
4604 if (demux->common.state < GST_MATROSKA_READ_STATE_DATA) {
4605 GST_DEBUG_OBJECT (demux, "still starting");
4609 /* we only expect a BYTE segment, e.g. following a seek */
4610 if (segment->format != GST_FORMAT_BYTES) {
4611 GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
4615 GST_DEBUG_OBJECT (demux, "clearing segment state");
4616 GST_OBJECT_LOCK (demux);
4617 /* clear current segment leftover */
4618 gst_adapter_clear (demux->common.adapter);
4619 /* and some streaming setup */
4620 demux->common.offset = segment->start;
4621 /* do not know where we are;
4622 * need to come across a cluster and generate segment */
4623 demux->common.segment.position = GST_CLOCK_TIME_NONE;
4624 demux->cluster_time = GST_CLOCK_TIME_NONE;
4625 demux->cluster_offset = 0;
4626 demux->need_segment = TRUE;
4627 /* but keep some of the upstream segment */
4628 demux->common.segment.rate = segment->rate;
4629 GST_OBJECT_UNLOCK (demux);
4631 /* chain will send initial segment after pads have been added,
4632 * or otherwise come up with one */
4633 GST_DEBUG_OBJECT (demux, "eating event");
4634 gst_event_unref (event);
4640 if (demux->common.state != GST_MATROSKA_READ_STATE_DATA) {
4641 gst_event_unref (event);
4642 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
4643 (NULL), ("got eos and didn't receive a complete header object"));
4644 } else if (demux->common.num_streams == 0) {
4645 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
4646 (NULL), ("got eos but no streams (yet)"));
4648 gst_matroska_demux_send_event (demux, event);
4652 case GST_EVENT_FLUSH_STOP:
4654 gst_adapter_clear (demux->common.adapter);
4655 GST_OBJECT_LOCK (demux);
4656 gst_matroska_read_common_reset_streams (&demux->common,
4657 GST_CLOCK_TIME_NONE, TRUE);
4658 demux->common.segment.position = GST_CLOCK_TIME_NONE;
4659 demux->cluster_time = GST_CLOCK_TIME_NONE;
4660 demux->cluster_offset = 0;
4661 GST_OBJECT_UNLOCK (demux);
4665 res = gst_pad_event_default (pad, parent, event);
4673 gst_matroska_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
4675 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
4677 gboolean pull_mode = FALSE;
4679 query = gst_query_new_scheduling ();
4681 if (gst_pad_peer_query (sinkpad, query))
4682 pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
4684 gst_query_unref (query);
4687 GST_DEBUG ("going to pull mode");
4688 demux->streaming = FALSE;
4689 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
4691 GST_DEBUG ("going to push (streaming) mode");
4692 demux->streaming = TRUE;
4693 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
4698 gst_matroska_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
4699 GstPadMode mode, gboolean active)
4701 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent);
4704 case GST_PAD_MODE_PULL:
4706 /* if we have a scheduler we can start the task */
4707 demux->segment_running = TRUE;
4708 gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
4711 demux->segment_running = FALSE;
4712 gst_pad_stop_task (sinkpad);
4715 case GST_PAD_MODE_PUSH:
4723 gst_duration_to_fraction (guint64 duration, gint * dest_n, gint * dest_d)
4725 static const int common_den[] = { 1, 2, 3, 4, 1001 };
4730 for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
4732 n = floor (0.5 + (d * 1e9) / duration);
4733 a = gst_util_uint64_scale_int (1000000000, d, n);
4734 if (duration >= a - 1 && duration <= a + 1) {
4739 gst_util_double_to_fraction (1e9 / duration, &n, &d);
4748 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
4749 videocontext, const gchar * codec_id, guint8 * data, guint size,
4750 gchar ** codec_name, guint32 * riff_fourcc)
4752 GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) videocontext;
4753 GstCaps *caps = NULL;
4755 g_assert (videocontext != NULL);
4756 g_assert (codec_name != NULL);
4758 context->send_xiph_headers = FALSE;
4759 context->send_flac_headers = FALSE;
4760 context->send_speex_headers = FALSE;
4765 /* TODO: check if we have all codec types from matroska-ids.h
4766 * check if we have to do more special things with codec_private
4769 * GST_MATROSKA_CODEC_ID_VIDEO_QUICKTIME
4770 * GST_MATROSKA_CODEC_ID_VIDEO_SNOW
4773 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
4774 gst_riff_strf_vids *vids = NULL;
4777 GstBuffer *buf = NULL;
4779 vids = (gst_riff_strf_vids *) data;
4781 /* assure size is big enough */
4783 GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
4786 if (size < sizeof (gst_riff_strf_vids)) {
4787 vids = g_new (gst_riff_strf_vids, 1);
4788 memcpy (vids, data, size);
4791 /* little-endian -> byte-order */
4792 vids->size = GUINT32_FROM_LE (vids->size);
4793 vids->width = GUINT32_FROM_LE (vids->width);
4794 vids->height = GUINT32_FROM_LE (vids->height);
4795 vids->planes = GUINT16_FROM_LE (vids->planes);
4796 vids->bit_cnt = GUINT16_FROM_LE (vids->bit_cnt);
4797 vids->compression = GUINT32_FROM_LE (vids->compression);
4798 vids->image_size = GUINT32_FROM_LE (vids->image_size);
4799 vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
4800 vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
4801 vids->num_colors = GUINT32_FROM_LE (vids->num_colors);
4802 vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors);
4804 if (size > sizeof (gst_riff_strf_vids)) { /* some extra_data */
4805 gsize offset = sizeof (gst_riff_strf_vids);
4808 gst_buffer_new_wrapped (g_memdup ((guint8 *) vids + offset,
4809 size - offset), size - offset);
4813 *riff_fourcc = vids->compression;
4815 caps = gst_riff_create_video_caps (vids->compression, NULL, vids,
4816 buf, NULL, codec_name);
4819 GST_WARNING ("Unhandled RIFF fourcc %" GST_FOURCC_FORMAT,
4820 GST_FOURCC_ARGS (vids->compression));
4824 gst_buffer_unref (buf);
4826 if (vids != (gst_riff_strf_vids *) data)
4829 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
4830 const gchar *format = NULL;
4832 switch (videocontext->fourcc) {
4833 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
4834 *codec_name = g_strdup ("Raw planar YUV 4:2:0");
4837 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
4838 *codec_name = g_strdup ("Raw packed YUV 4:2:2");
4841 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
4842 *codec_name = g_strdup ("Raw packed YUV 4:2:0");
4845 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
4846 *codec_name = g_strdup ("Raw packed YUV 4:2:2");
4849 case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
4850 *codec_name = g_strdup ("Raw packed YUV 4:4:4 with alpha channel");
4855 GST_DEBUG ("Unknown fourcc %" GST_FOURCC_FORMAT,
4856 GST_FOURCC_ARGS (videocontext->fourcc));
4860 caps = gst_caps_new_simple ("video/x-raw",
4861 "format", G_TYPE_STRING, format, NULL);
4862 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
4863 caps = gst_caps_new_simple ("video/x-divx",
4864 "divxversion", G_TYPE_INT, 4, NULL);
4865 *codec_name = g_strdup ("MPEG-4 simple profile");
4866 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
4867 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
4869 caps = gst_caps_new_full (gst_structure_new ("video/x-divx",
4870 "divxversion", G_TYPE_INT, 5, NULL),
4871 gst_structure_new ("video/x-xvid", NULL),
4872 gst_structure_new ("video/mpeg",
4873 "mpegversion", G_TYPE_INT, 4,
4874 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL), NULL);
4876 caps = gst_caps_new_simple ("video/mpeg",
4877 "mpegversion", G_TYPE_INT, 4,
4878 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4882 priv = gst_buffer_new_wrapped (g_memdup (data, size), size);
4883 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
4884 gst_buffer_unref (priv);
4886 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP))
4887 *codec_name = g_strdup ("MPEG-4 advanced simple profile");
4889 *codec_name = g_strdup ("MPEG-4 advanced profile");
4890 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
4892 caps = gst_caps_new_full (gst_structure_new ("video/x-divx",
4893 "divxversion", G_TYPE_INT, 3, NULL),
4894 gst_structure_new ("video/x-msmpeg",
4895 "msmpegversion", G_TYPE_INT, 43, NULL), NULL);
4897 caps = gst_caps_new_simple ("video/x-msmpeg",
4898 "msmpegversion", G_TYPE_INT, 43, NULL);
4899 *codec_name = g_strdup ("Microsoft MPEG-4 v.3");
4900 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
4901 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
4904 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
4909 caps = gst_caps_new_simple ("video/mpeg",
4910 "systemstream", G_TYPE_BOOLEAN, FALSE,
4911 "mpegversion", G_TYPE_INT, mpegversion, NULL);
4912 *codec_name = g_strdup_printf ("MPEG-%d video", mpegversion);
4913 context->postprocess_frame = gst_matroska_demux_add_mpeg_seq_header;
4914 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
4915 caps = gst_caps_new_empty_simple ("image/jpeg");
4916 *codec_name = g_strdup ("Motion-JPEG");
4917 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC)) {
4918 caps = gst_caps_new_empty_simple ("video/x-h264");
4922 /* First byte is the version, second is the profile indication, and third
4923 * is the 5 contraint_set_flags and 3 reserved bits. Fourth byte is the
4924 * level indication. */
4925 gst_codec_utils_h264_caps_set_level_and_profile (caps, data + 1,
4928 priv = gst_buffer_new_wrapped (g_memdup (data, size), size);
4929 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
4930 gst_buffer_unref (priv);
4932 gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING, "avc",
4933 "alignment", G_TYPE_STRING, "au", NULL);
4935 GST_WARNING ("No codec data found, assuming output is byte-stream");
4936 gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING, "byte-stream",
4939 *codec_name = g_strdup ("H264");
4940 } else if ((!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1)) ||
4941 (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2)) ||
4942 (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3)) ||
4943 (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4))) {
4944 gint rmversion = -1;
4946 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1))
4948 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2))
4950 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3))
4952 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4))
4955 caps = gst_caps_new_simple ("video/x-pn-realvideo",
4956 "rmversion", G_TYPE_INT, rmversion, NULL);
4957 GST_DEBUG ("data:%p, size:0x%x", data, size);
4958 /* We need to extract the extradata ! */
4959 if (data && (size >= 0x22)) {
4964 subformat = GST_READ_UINT32_BE (data + 0x1a);
4965 rformat = GST_READ_UINT32_BE (data + 0x1e);
4968 gst_buffer_new_wrapped (g_memdup (data + 0x1a, size - 0x1a),
4970 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, "format",
4971 G_TYPE_INT, rformat, "subformat", G_TYPE_INT, subformat, NULL);
4972 gst_buffer_unref (priv);
4975 *codec_name = g_strdup_printf ("RealVideo %d.0", rmversion);
4976 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) {
4977 caps = gst_caps_new_empty_simple ("video/x-theora");
4978 context->send_xiph_headers = TRUE;
4979 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC)) {
4980 caps = gst_caps_new_empty_simple ("video/x-dirac");
4981 *codec_name = g_strdup_printf ("Dirac");
4982 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP8)) {
4983 caps = gst_caps_new_empty_simple ("video/x-vp8");
4984 *codec_name = g_strdup_printf ("On2 VP8");
4986 GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id);
4992 GstStructure *structure;
4994 for (i = 0; i < gst_caps_get_size (caps); i++) {
4995 structure = gst_caps_get_structure (caps, i);
4997 /* FIXME: use the real unit here! */
4998 GST_DEBUG ("video size %dx%d, target display size %dx%d (any unit)",
4999 videocontext->pixel_width,
5000 videocontext->pixel_height,
5001 videocontext->display_width, videocontext->display_height);
5003 /* pixel width and height are the w and h of the video in pixels */
5004 if (videocontext->pixel_width > 0 && videocontext->pixel_height > 0) {
5005 gint w = videocontext->pixel_width;
5006 gint h = videocontext->pixel_height;
5008 gst_structure_set (structure,
5009 "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL);
5012 if (videocontext->display_width > 0 || videocontext->display_height > 0) {
5015 if (videocontext->display_width <= 0)
5016 videocontext->display_width = videocontext->pixel_width;
5017 if (videocontext->display_height <= 0)
5018 videocontext->display_height = videocontext->pixel_height;
5020 /* calculate the pixel aspect ratio using the display and pixel w/h */
5021 n = videocontext->display_width * videocontext->pixel_height;
5022 d = videocontext->display_height * videocontext->pixel_width;
5023 GST_DEBUG ("setting PAR to %d/%d", n, d);
5024 gst_structure_set (structure, "pixel-aspect-ratio",
5026 videocontext->display_width * videocontext->pixel_height,
5027 videocontext->display_height * videocontext->pixel_width, NULL);
5030 if (videocontext->default_fps > 0.0) {
5031 GValue fps_double = { 0, };
5032 GValue fps_fraction = { 0, };
5034 g_value_init (&fps_double, G_TYPE_DOUBLE);
5035 g_value_init (&fps_fraction, GST_TYPE_FRACTION);
5036 g_value_set_double (&fps_double, videocontext->default_fps);
5037 g_value_transform (&fps_double, &fps_fraction);
5039 GST_DEBUG ("using default fps %f", videocontext->default_fps);
5041 gst_structure_set_value (structure, "framerate", &fps_fraction);
5042 g_value_unset (&fps_double);
5043 g_value_unset (&fps_fraction);
5044 } else if (context->default_duration > 0) {
5047 gst_duration_to_fraction (context->default_duration, &fps_n, &fps_d);
5049 GST_INFO ("using default duration %" G_GUINT64_FORMAT
5050 " framerate %d/%d", context->default_duration, fps_n, fps_d);
5052 gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
5053 fps_n, fps_d, NULL);
5055 /* sort of a hack to get most codecs to support,
5056 * even if the default_duration is missing */
5057 gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
5061 if (videocontext->parent.flags & GST_MATROSKA_VIDEOTRACK_INTERLACED)
5062 gst_structure_set (structure, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
5065 gst_caps_do_simplify (caps);
5072 * Some AAC specific code... *sigh*
5073 * FIXME: maybe we should use '15' and code the sample rate explicitly
5074 * if the sample rate doesn't match the predefined rates exactly? (tpm)
5078 aac_rate_idx (gint rate)
5082 else if (75132 <= rate)
5084 else if (55426 <= rate)
5086 else if (46009 <= rate)
5088 else if (37566 <= rate)
5090 else if (27713 <= rate)
5092 else if (23004 <= rate)
5094 else if (18783 <= rate)
5096 else if (13856 <= rate)
5098 else if (11502 <= rate)
5100 else if (9391 <= rate)
5107 aac_profile_idx (const gchar * codec_id)
5111 if (strlen (codec_id) <= 12)
5113 else if (!strncmp (&codec_id[12], "MAIN", 4))
5115 else if (!strncmp (&codec_id[12], "LC", 2))
5117 else if (!strncmp (&codec_id[12], "SSR", 3))
5125 #define AAC_SYNC_EXTENSION_TYPE 0x02b7
5128 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
5129 audiocontext, const gchar * codec_id, guint8 * data, guint size,
5130 gchar ** codec_name, guint16 * riff_audio_fmt)
5132 GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) audiocontext;
5133 GstCaps *caps = NULL;
5135 g_assert (audiocontext != NULL);
5136 g_assert (codec_name != NULL);
5139 *riff_audio_fmt = 0;
5141 context->send_xiph_headers = FALSE;
5142 context->send_flac_headers = FALSE;
5143 context->send_speex_headers = FALSE;
5145 /* TODO: check if we have all codec types from matroska-ids.h
5146 * check if we have to do more special things with codec_private
5147 * check if we need bitdepth in different places too
5148 * implement channel position magic
5150 * GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID9
5151 * GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID10
5152 * GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDMC
5153 * GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDM2
5156 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
5157 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
5158 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
5161 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
5163 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
5168 caps = gst_caps_new_simple ("audio/mpeg",
5169 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
5170 *codec_name = g_strdup_printf ("MPEG-1 layer %d", layer);
5171 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
5172 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
5175 GstAudioFormat format;
5177 sign = (audiocontext->bitdepth != 8);
5178 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
5179 endianness = G_BIG_ENDIAN;
5181 endianness = G_LITTLE_ENDIAN;
5183 format = gst_audio_format_build_integer (sign, endianness,
5184 audiocontext->bitdepth, audiocontext->bitdepth);
5186 caps = gst_caps_new_simple ("audio/x-raw",
5187 "format", G_TYPE_STRING, gst_audio_format_to_string (format), NULL);
5189 *codec_name = g_strdup_printf ("Raw %d-bit PCM audio",
5190 audiocontext->bitdepth);
5191 context->alignment = audiocontext->bitdepth / 8;
5192 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
5193 const gchar *format;
5194 if (audiocontext->bitdepth == 32)
5198 caps = gst_caps_new_simple ("audio/x-raw",
5199 "format", G_TYPE_STRING, format, NULL);
5200 *codec_name = g_strdup_printf ("Raw %d-bit floating-point audio",
5201 audiocontext->bitdepth);
5202 context->alignment = audiocontext->bitdepth / 8;
5203 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3,
5204 strlen (GST_MATROSKA_CODEC_ID_AUDIO_AC3))) {
5205 caps = gst_caps_new_simple ("audio/x-ac3",
5206 "framed", G_TYPE_BOOLEAN, TRUE, NULL);
5207 *codec_name = g_strdup ("AC-3 audio");
5208 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_EAC3,
5209 strlen (GST_MATROSKA_CODEC_ID_AUDIO_EAC3))) {
5210 caps = gst_caps_new_simple ("audio/x-eac3",
5211 "framed", G_TYPE_BOOLEAN, TRUE, NULL);
5212 *codec_name = g_strdup ("E-AC-3 audio");
5213 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
5214 caps = gst_caps_new_empty_simple ("audio/x-dts");
5215 *codec_name = g_strdup ("DTS audio");
5216 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
5217 caps = gst_caps_new_empty_simple ("audio/x-vorbis");
5218 context->send_xiph_headers = TRUE;
5219 /* vorbis decoder does tags */
5220 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_FLAC)) {
5221 caps = gst_caps_new_empty_simple ("audio/x-flac");
5222 context->send_flac_headers = TRUE;
5223 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX)) {
5224 caps = gst_caps_new_empty_simple ("audio/x-speex");
5225 context->send_speex_headers = TRUE;
5226 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
5227 gst_riff_strf_auds auds;
5230 GstBuffer *codec_data;
5232 /* little-endian -> byte-order */
5233 auds.format = GST_READ_UINT16_LE (data);
5234 auds.channels = GST_READ_UINT16_LE (data + 2);
5235 auds.rate = GST_READ_UINT32_LE (data + 4);
5236 auds.av_bps = GST_READ_UINT32_LE (data + 8);
5237 auds.blockalign = GST_READ_UINT16_LE (data + 12);
5238 auds.size = GST_READ_UINT16_LE (data + 16);
5240 /* 18 is the waveformatex size */
5241 codec_data = gst_buffer_new_wrapped_full (data + 18, NULL, 0, auds.size);
5244 *riff_audio_fmt = auds.format;
5246 caps = gst_riff_create_audio_caps (auds.format, NULL, &auds, NULL,
5247 codec_data, codec_name);
5248 gst_buffer_unref (codec_data);
5251 GST_WARNING ("Unhandled RIFF audio format 0x%02x", auds.format);
5254 } else if (g_str_has_prefix (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC)) {
5255 GstBuffer *priv = NULL;
5257 gint rate_idx, profile;
5258 guint8 *data = NULL;
5260 /* unspecified AAC profile with opaque private codec data */
5261 if (strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC) == 0) {
5262 if (context->codec_priv_size >= 2) {
5263 guint obj_type, freq_index, explicit_freq_bytes = 0;
5265 codec_id = GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4;
5267 freq_index = (GST_READ_UINT16_BE (context->codec_priv) & 0x780) >> 7;
5268 obj_type = (GST_READ_UINT16_BE (context->codec_priv) & 0xF800) >> 11;
5269 if (freq_index == 15)
5270 explicit_freq_bytes = 3;
5271 GST_DEBUG ("obj_type = %u, freq_index = %u", obj_type, freq_index);
5272 priv = gst_buffer_new_wrapped (g_memdup (context->codec_priv,
5273 context->codec_priv_size), context->codec_priv_size);
5274 /* assume SBR if samplerate <= 24kHz */
5275 if (obj_type == 5 || (freq_index >= 6 && freq_index != 15) ||
5276 (context->codec_priv_size == (5 + explicit_freq_bytes))) {
5277 audiocontext->samplerate *= 2;
5280 GST_WARNING ("Opaque A_AAC codec ID, but no codec private data");
5281 /* this is pretty broken;
5282 * maybe we need to make up some default private,
5283 * or maybe ADTS data got dumped in.
5284 * Let's set up some private data now, and check actual data later */
5285 /* just try this and see what happens ... */
5286 codec_id = GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4;
5287 context->postprocess_frame = gst_matroska_demux_check_aac;
5291 /* make up decoder-specific data if it is not supplied */
5293 priv = gst_buffer_new_allocate (NULL, 5, 0);
5294 data = gst_buffer_map (priv, NULL, NULL, GST_MAP_WRITE);
5295 rate_idx = aac_rate_idx (audiocontext->samplerate);
5296 profile = aac_profile_idx (codec_id);
5298 data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
5299 data[1] = ((rate_idx & 0x1) << 7) | (audiocontext->channels << 3);
5301 if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2,
5302 strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2))) {
5304 gst_buffer_unmap (priv, data, 5);
5305 gst_buffer_set_size (priv, 2);
5306 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4,
5307 strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4))) {
5310 if (g_strrstr (codec_id, "SBR")) {
5311 /* HE-AAC (aka SBR AAC) */
5312 audiocontext->samplerate *= 2;
5313 rate_idx = aac_rate_idx (audiocontext->samplerate);
5314 data[2] = AAC_SYNC_EXTENSION_TYPE >> 3;
5315 data[3] = ((AAC_SYNC_EXTENSION_TYPE & 0x07) << 5) | 5;
5316 data[4] = (1 << 7) | (rate_idx << 3);
5317 gst_buffer_unmap (priv, data, 5);
5319 gst_buffer_unmap (priv, data, 5);
5320 gst_buffer_set_size (priv, 2);
5323 gst_buffer_unmap (priv, data, 5);
5324 gst_buffer_unref (priv);
5326 GST_ERROR ("Unknown AAC profile and no codec private data");
5331 caps = gst_caps_new_simple ("audio/mpeg",
5332 "mpegversion", G_TYPE_INT, mpegversion,
5333 "framed", G_TYPE_BOOLEAN, TRUE, NULL);
5334 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
5335 *codec_name = g_strdup_printf ("MPEG-%d AAC audio", mpegversion);
5336 gst_buffer_unref (priv);
5338 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_TTA)) {
5339 caps = gst_caps_new_simple ("audio/x-tta",
5340 "width", G_TYPE_INT, audiocontext->bitdepth, NULL);
5341 *codec_name = g_strdup ("TTA audio");
5342 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_WAVPACK4)) {
5343 caps = gst_caps_new_simple ("audio/x-wavpack",
5344 "width", G_TYPE_INT, audiocontext->bitdepth,
5345 "framed", G_TYPE_BOOLEAN, TRUE, NULL);
5346 *codec_name = g_strdup ("Wavpack audio");
5347 context->postprocess_frame = gst_matroska_demux_add_wvpk_header;
5348 audiocontext->wvpk_block_index = 0;
5349 } else if ((!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4)) ||
5350 (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4)) ||
5351 (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK))) {
5352 gint raversion = -1;
5354 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4))
5356 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK))
5361 caps = gst_caps_new_simple ("audio/x-pn-realaudio",
5362 "raversion", G_TYPE_INT, raversion, NULL);
5363 /* Extract extra information from caps, mapping varies based on codec */
5364 if (data && (size >= 0x50)) {
5371 guint extra_data_size;
5373 GST_ERROR ("real audio raversion:%d", raversion);
5374 if (raversion == 8) {
5376 flavor = GST_READ_UINT16_BE (data + 22);
5377 packet_size = GST_READ_UINT32_BE (data + 24);
5378 height = GST_READ_UINT16_BE (data + 40);
5379 leaf_size = GST_READ_UINT16_BE (data + 44);
5380 sample_width = GST_READ_UINT16_BE (data + 58);
5381 extra_data_size = GST_READ_UINT32_BE (data + 74);
5384 ("flavor:%d, packet_size:%d, height:%d, leaf_size:%d, sample_width:%d, extra_data_size:%d",
5385 flavor, packet_size, height, leaf_size, sample_width,
5387 gst_caps_set_simple (caps, "flavor", G_TYPE_INT, flavor, "packet_size",
5388 G_TYPE_INT, packet_size, "height", G_TYPE_INT, height, "leaf_size",
5389 G_TYPE_INT, leaf_size, "width", G_TYPE_INT, sample_width, NULL);
5391 if ((size - 78) >= extra_data_size) {
5392 priv = gst_buffer_new_wrapped (g_memdup (data + 78, extra_data_size),
5394 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
5395 gst_buffer_unref (priv);
5400 *codec_name = g_strdup_printf ("RealAudio %d.0", raversion);
5401 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR)) {
5402 caps = gst_caps_new_empty_simple ("audio/x-sipro");
5403 *codec_name = g_strdup ("Sipro/ACELP.NET Voice Codec");
5404 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF)) {
5405 caps = gst_caps_new_empty_simple ("audio/x-ralf-mpeg4-generic");
5406 *codec_name = g_strdup ("Real Audio Lossless");
5407 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC)) {
5408 caps = gst_caps_new_empty_simple ("audio/x-vnd.sony.atrac3");
5409 *codec_name = g_strdup ("Sony ATRAC3");
5411 GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id);
5416 if (audiocontext->samplerate > 0 && audiocontext->channels > 0) {
5419 for (i = 0; i < gst_caps_get_size (caps); i++) {
5420 gst_structure_set (gst_caps_get_structure (caps, i),
5421 "channels", G_TYPE_INT, audiocontext->channels,
5422 "rate", G_TYPE_INT, audiocontext->samplerate, NULL);
5426 gst_caps_do_simplify (caps);
5433 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
5434 subtitlecontext, const gchar * codec_id, gpointer data, guint size)
5436 GstCaps *caps = NULL;
5437 GstMatroskaTrackContext *context =
5438 (GstMatroskaTrackContext *) subtitlecontext;
5440 /* for backwards compatibility */
5441 if (!g_ascii_strcasecmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_ASCII))
5442 codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8;
5443 else if (!g_ascii_strcasecmp (codec_id, "S_SSA"))
5444 codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_SSA;
5445 else if (!g_ascii_strcasecmp (codec_id, "S_ASS"))
5446 codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_ASS;
5447 else if (!g_ascii_strcasecmp (codec_id, "S_USF"))
5448 codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_USF;
5450 /* TODO: Add GST_MATROSKA_CODEC_ID_SUBTITLE_BMP support
5451 * Check if we have to do something with codec_private */
5452 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8)) {
5453 /* well, plain text simply does not have a lot of markup ... */
5454 caps = gst_caps_new_empty_simple ("text/x-pango-markup");
5455 context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer;
5456 subtitlecontext->check_markup = TRUE;
5457 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA)) {
5458 caps = gst_caps_new_empty_simple ("application/x-ssa");
5459 context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer;
5460 subtitlecontext->check_markup = FALSE;
5461 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS)) {
5462 caps = gst_caps_new_empty_simple ("application/x-ass");
5463 context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer;
5464 subtitlecontext->check_markup = FALSE;
5465 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_USF)) {
5466 caps = gst_caps_new_empty_simple ("application/x-usf");
5467 context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer;
5468 subtitlecontext->check_markup = FALSE;
5469 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB)) {
5470 caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture");
5471 ((GstMatroskaTrackContext *) subtitlecontext)->send_dvd_event = TRUE;
5472 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_HDMVPGS)) {
5473 caps = gst_caps_new_empty_simple ("subpicture/x-pgs");
5474 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_KATE)) {
5475 caps = gst_caps_new_empty_simple ("subtitle/x-kate");
5476 context->send_xiph_headers = TRUE;
5478 GST_DEBUG ("Unknown subtitle stream: codec_id='%s'", codec_id);
5479 caps = gst_caps_new_empty_simple ("application/x-subtitle-unknown");
5482 if (data != NULL && size > 0) {
5485 buf = gst_buffer_new_wrapped (g_memdup (data, size), size);
5486 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
5487 gst_buffer_unref (buf);
5494 gst_matroska_demux_set_index (GstElement * element, GstIndex * index)
5496 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
5498 GST_OBJECT_LOCK (demux);
5499 if (demux->common.element_index)
5500 gst_object_unref (demux->common.element_index);
5501 demux->common.element_index = index ? gst_object_ref (index) : NULL;
5502 GST_OBJECT_UNLOCK (demux);
5503 GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT,
5504 demux->common.element_index);
5508 gst_matroska_demux_get_index (GstElement * element)
5510 GstIndex *result = NULL;
5511 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
5513 GST_OBJECT_LOCK (demux);
5514 if (demux->common.element_index)
5515 result = gst_object_ref (demux->common.element_index);
5516 GST_OBJECT_UNLOCK (demux);
5518 GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
5523 static GstStateChangeReturn
5524 gst_matroska_demux_change_state (GstElement * element,
5525 GstStateChange transition)
5527 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
5528 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
5530 /* handle upwards state changes here */
5531 switch (transition) {
5536 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5538 /* handle downwards state changes */
5539 switch (transition) {
5540 case GST_STATE_CHANGE_PAUSED_TO_READY:
5541 gst_matroska_demux_reset (GST_ELEMENT (demux));
5551 gst_matroska_demux_set_property (GObject * object,
5552 guint prop_id, const GValue * value, GParamSpec * pspec)
5554 GstMatroskaDemux *demux;
5556 g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
5557 demux = GST_MATROSKA_DEMUX (object);
5560 case ARG_MAX_GAP_TIME:
5561 GST_OBJECT_LOCK (demux);
5562 demux->max_gap_time = g_value_get_uint64 (value);
5563 GST_OBJECT_UNLOCK (demux);
5566 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5572 gst_matroska_demux_get_property (GObject * object,
5573 guint prop_id, GValue * value, GParamSpec * pspec)
5575 GstMatroskaDemux *demux;
5577 g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
5578 demux = GST_MATROSKA_DEMUX (object);
5581 case ARG_MAX_GAP_TIME:
5582 GST_OBJECT_LOCK (demux);
5583 g_value_set_uint64 (value, demux->max_gap_time);
5584 GST_OBJECT_UNLOCK (demux);
5587 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5593 gst_matroska_demux_plugin_init (GstPlugin * plugin)
5597 /* parser helper separate debug */
5598 GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
5599 0, "EBML stream helper class");
5601 /* create an elementfactory for the matroska_demux element */
5602 if (!gst_element_register (plugin, "matroskademux",
5603 GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))