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-parse.c: matroska file/stream parser
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 parseing is done correct for all codecs according to spec
31 * TODO: seeking with incomplete or without CUE
35 * SECTION:element-matroskaparse
37 * matroskaparse parsees a Matroska file into the different contained streams.
40 * <title>Example launch line</title>
42 * gst-launch -v filesrc location=/path/to/mkv ! matroskaparse ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
43 * ]| This pipeline parsees 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/tag/tag.h>
64 #include <gst/pbutils/pbutils.h>
66 #include "matroska-parse.h"
67 #include "matroska-ids.h"
69 GST_DEBUG_CATEGORY_STATIC (matroskaparse_debug);
70 #define GST_CAT_DEFAULT matroskaparse_debug
72 #define DEBUG_ELEMENT_START(parse, ebml, element) \
73 GST_DEBUG_OBJECT (parse, "Parsing " element " element at offset %" \
74 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
76 #define DEBUG_ELEMENT_STOP(parse, ebml, element, ret) \
77 GST_DEBUG_OBJECT (parse, "Parsing " element " element " \
78 " finished with '%s'", gst_flow_get_name (ret))
87 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
90 GST_STATIC_CAPS ("video/x-matroska; video/webm")
93 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
96 GST_STATIC_CAPS ("video/x-matroska; video/webm")
99 static GstFlowReturn gst_matroska_parse_parse_id (GstMatroskaParse * parse,
100 guint32 id, guint64 length, guint needed);
102 /* element functions */
103 //static void gst_matroska_parse_loop (GstPad * pad);
105 static gboolean gst_matroska_parse_element_send_event (GstElement * element,
107 static gboolean gst_matroska_parse_element_query (GstElement * element,
111 static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
112 GstPad * pad, GstEvent * event);
113 static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
114 GstObject * parent, GstEvent * event);
115 static gboolean gst_matroska_parse_handle_src_query (GstPad * pad,
116 GstObject * parent, GstQuery * query);
118 static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
119 GstObject * parent, GstEvent * event);
120 static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
121 GstObject * parent, GstBuffer * buffer);
123 static GstStateChangeReturn
124 gst_matroska_parse_change_state (GstElement * element,
125 GstStateChange transition);
128 gst_matroska_parse_set_index (GstElement * element, GstIndex * index);
129 static GstIndex *gst_matroska_parse_get_index (GstElement * element);
133 static void gst_matroska_parse_reset (GstElement * element);
134 static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
137 GType gst_matroska_parse_get_type (void);
138 #define parent_class gst_matroska_parse_parent_class
139 G_DEFINE_TYPE (GstMatroskaParse, gst_matroska_parse, GST_TYPE_ELEMENT);
142 gst_matroska_parse_finalize (GObject * object)
144 GstMatroskaParse *parse = GST_MATROSKA_PARSE (object);
146 if (parse->common.src) {
147 g_ptr_array_free (parse->common.src, TRUE);
148 parse->common.src = NULL;
151 if (parse->common.global_tags) {
152 gst_tag_list_free (parse->common.global_tags);
153 parse->common.global_tags = NULL;
156 g_object_unref (parse->common.adapter);
158 G_OBJECT_CLASS (parent_class)->finalize (object);
162 gst_matroska_parse_class_init (GstMatroskaParseClass * klass)
164 GObjectClass *gobject_class = (GObjectClass *) klass;
165 GstElementClass *gstelement_class = (GstElementClass *) klass;
167 GST_DEBUG_CATEGORY_INIT (matroskaparse_debug, "matroskaparse", 0,
170 gobject_class->finalize = gst_matroska_parse_finalize;
172 gstelement_class->change_state =
173 GST_DEBUG_FUNCPTR (gst_matroska_parse_change_state);
174 gstelement_class->send_event =
175 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_send_event);
176 gstelement_class->query =
177 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_query);
180 gstelement_class->set_index =
181 GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
182 gstelement_class->get_index =
183 GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index);
186 gst_element_class_add_pad_template (gstelement_class,
187 gst_static_pad_template_get (&src_templ));
188 gst_element_class_add_pad_template (gstelement_class,
189 gst_static_pad_template_get (&sink_templ));
191 gst_element_class_set_static_metadata (gstelement_class,
192 "Matroska parser", "Codec/Parser",
193 "Parses Matroska/WebM streams into video/audio/subtitles",
194 "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
198 gst_matroska_parse_init (GstMatroskaParse * parse)
200 parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
202 gst_pad_set_chain_function (parse->common.sinkpad,
203 GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
204 gst_pad_set_event_function (parse->common.sinkpad,
205 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
206 gst_element_add_pad (GST_ELEMENT (parse), parse->common.sinkpad);
208 parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
209 gst_pad_set_event_function (parse->srcpad,
210 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event));
211 gst_pad_set_query_function (parse->srcpad,
212 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
213 gst_pad_use_fixed_caps (parse->srcpad);
215 gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
217 /* initial stream no. */
218 parse->common.src = NULL;
220 parse->common.writing_app = NULL;
221 parse->common.muxing_app = NULL;
222 parse->common.index = NULL;
223 parse->common.global_tags = NULL;
225 parse->common.adapter = gst_adapter_new ();
227 GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
230 gst_matroska_parse_reset (GST_ELEMENT (parse));
234 gst_matroska_track_free (GstMatroskaTrackContext * track)
236 g_free (track->codec_id);
237 g_free (track->codec_name);
238 g_free (track->name);
239 g_free (track->language);
240 g_free (track->codec_priv);
241 g_free (track->codec_state);
243 if (track->encodings != NULL) {
246 for (i = 0; i < track->encodings->len; ++i) {
247 GstMatroskaTrackEncoding *enc = &g_array_index (track->encodings,
248 GstMatroskaTrackEncoding,
251 g_free (enc->comp_settings);
253 g_array_free (track->encodings, TRUE);
256 if (track->pending_tags)
257 gst_tag_list_free (track->pending_tags);
259 if (track->index_table)
260 g_array_free (track->index_table, TRUE);
266 gst_matroska_parse_free_parsed_el (gpointer mem, gpointer user_data)
268 g_slice_free (guint64, mem);
272 gst_matroska_parse_reset (GstElement * element)
274 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
277 GST_DEBUG_OBJECT (parse, "Resetting state");
280 parse->common.state = GST_MATROSKA_READ_STATE_START;
282 /* clean up existing streams */
283 if (parse->common.src) {
284 g_assert (parse->common.src->len == parse->common.num_streams);
285 for (i = 0; i < parse->common.src->len; i++) {
286 GstMatroskaTrackContext *context = g_ptr_array_index (parse->common.src,
289 gst_caps_replace (&context->caps, NULL);
290 gst_matroska_track_free (context);
292 g_ptr_array_free (parse->common.src, TRUE);
294 parse->common.src = g_ptr_array_new ();
296 parse->common.num_streams = 0;
297 parse->num_a_streams = 0;
298 parse->num_t_streams = 0;
299 parse->num_v_streams = 0;
301 /* reset media info */
302 g_free (parse->common.writing_app);
303 parse->common.writing_app = NULL;
304 g_free (parse->common.muxing_app);
305 parse->common.muxing_app = NULL;
308 if (parse->common.index) {
309 g_array_free (parse->common.index, TRUE);
310 parse->common.index = NULL;
315 parse->common.time_scale = 1000000;
316 parse->common.created = G_MININT64;
318 parse->common.index_parsed = FALSE;
319 parse->tracks_parsed = FALSE;
320 parse->common.segmentinfo_parsed = FALSE;
321 parse->common.attachments_parsed = FALSE;
323 g_list_foreach (parse->common.tags_parsed,
324 (GFunc) gst_matroska_parse_free_parsed_el, NULL);
325 g_list_free (parse->common.tags_parsed);
326 parse->common.tags_parsed = NULL;
328 g_list_foreach (parse->seek_parsed,
329 (GFunc) gst_matroska_parse_free_parsed_el, NULL);
330 g_list_free (parse->seek_parsed);
331 parse->seek_parsed = NULL;
333 gst_segment_init (&parse->common.segment, GST_FORMAT_TIME);
334 parse->last_stop_end = GST_CLOCK_TIME_NONE;
335 parse->seek_block = 0;
337 parse->common.offset = 0;
338 parse->cluster_time = GST_CLOCK_TIME_NONE;
339 parse->cluster_offset = 0;
340 parse->next_cluster_offset = 0;
341 parse->index_offset = 0;
342 parse->seekable = FALSE;
343 parse->need_newsegment = FALSE;
344 parse->building_index = FALSE;
345 if (parse->seek_event) {
346 gst_event_unref (parse->seek_event);
347 parse->seek_event = NULL;
350 parse->seek_index = NULL;
351 parse->seek_entry = 0;
353 if (parse->close_segment) {
354 gst_event_unref (parse->close_segment);
355 parse->close_segment = NULL;
358 if (parse->new_segment) {
359 gst_event_unref (parse->new_segment);
360 parse->new_segment = NULL;
363 if (parse->common.element_index) {
364 gst_object_unref (parse->common.element_index);
365 parse->common.element_index = NULL;
367 parse->common.element_index_writer_id = -1;
370 if (parse->common.global_tags) {
371 gst_tag_list_free (parse->common.global_tags);
373 parse->common.global_tags = gst_tag_list_new_empty ();
375 if (parse->common.cached_buffer) {
376 gst_buffer_unref (parse->common.cached_buffer);
377 parse->common.cached_buffer = NULL;
380 if (parse->streamheader != NULL) {
381 gst_buffer_unref (parse->streamheader);
382 parse->streamheader = NULL;
387 gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
389 GstMatroskaTrackContext *context;
393 DEBUG_ELEMENT_START (parse, ebml, "TrackEntry");
395 /* start with the master */
396 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
397 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
401 /* allocate generic... if we know the type, we'll g_renew()
402 * with the precise type */
403 context = g_new0 (GstMatroskaTrackContext, 1);
404 g_ptr_array_add (parse->common.src, context);
405 context->index = parse->common.num_streams;
406 context->index_writer_id = -1;
407 context->type = 0; /* no type yet */
408 context->default_duration = 0;
410 context->set_discont = TRUE;
411 context->timecodescale = 1.0;
413 GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
414 GST_MATROSKA_TRACK_LACING;
415 context->last_flow = GST_FLOW_OK;
416 context->to_offset = G_MAXINT64;
417 context->alignment = 1;
418 parse->common.num_streams++;
419 g_assert (parse->common.src->len == parse->common.num_streams);
421 GST_DEBUG_OBJECT (parse, "Stream number %d", context->index);
423 /* try reading the trackentry headers */
424 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
425 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
429 /* track number (unique stream ID) */
430 case GST_MATROSKA_ID_TRACKNUMBER:{
433 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
437 GST_ERROR_OBJECT (parse, "Invalid TrackNumber 0");
438 ret = GST_FLOW_ERROR;
440 } else if (!gst_matroska_read_common_tracknumber_unique (&parse->common,
442 GST_ERROR_OBJECT (parse, "TrackNumber %" G_GUINT64_FORMAT
443 " is not unique", num);
444 ret = GST_FLOW_ERROR;
448 GST_DEBUG_OBJECT (parse, "TrackNumber: %" G_GUINT64_FORMAT, num);
452 /* track UID (unique identifier) */
453 case GST_MATROSKA_ID_TRACKUID:{
456 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
460 GST_ERROR_OBJECT (parse, "Invalid TrackUID 0");
461 ret = GST_FLOW_ERROR;
465 GST_DEBUG_OBJECT (parse, "TrackUID: %" G_GUINT64_FORMAT, num);
470 /* track type (video, audio, combined, subtitle, etc.) */
471 case GST_MATROSKA_ID_TRACKTYPE:{
474 if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
478 if (context->type != 0 && context->type != track_type) {
479 GST_WARNING_OBJECT (parse,
480 "More than one tracktype defined in a TrackEntry - skipping");
482 } else if (track_type < 1 || track_type > 254) {
483 GST_WARNING_OBJECT (parse, "Invalid TrackType %" G_GUINT64_FORMAT,
488 GST_DEBUG_OBJECT (parse, "TrackType: %" G_GUINT64_FORMAT, track_type);
490 /* ok, so we're actually going to reallocate this thing */
491 switch (track_type) {
492 case GST_MATROSKA_TRACK_TYPE_VIDEO:
493 gst_matroska_track_init_video_context (&context);
495 case GST_MATROSKA_TRACK_TYPE_AUDIO:
496 gst_matroska_track_init_audio_context (&context);
498 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
499 gst_matroska_track_init_subtitle_context (&context);
501 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
502 case GST_MATROSKA_TRACK_TYPE_LOGO:
503 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
504 case GST_MATROSKA_TRACK_TYPE_CONTROL:
506 GST_WARNING_OBJECT (parse,
507 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
512 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
517 /* tracktype specific stuff for video */
518 case GST_MATROSKA_ID_TRACKVIDEO:{
519 GstMatroskaTrackVideoContext *videocontext;
521 DEBUG_ELEMENT_START (parse, ebml, "TrackVideo");
523 if (!gst_matroska_track_init_video_context (&context)) {
524 GST_WARNING_OBJECT (parse,
525 "TrackVideo element in non-video track - ignoring track");
526 ret = GST_FLOW_ERROR;
528 } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
531 videocontext = (GstMatroskaTrackVideoContext *) context;
532 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
535 while (ret == GST_FLOW_OK &&
536 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
537 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
541 /* Should be one level up but some broken muxers write it here. */
542 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
545 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
549 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
553 GST_DEBUG_OBJECT (parse,
554 "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
555 context->default_duration = num;
559 /* video framerate */
560 /* NOTE: This one is here only for backward compatibility.
561 * Use _TRACKDEFAULDURATION one level up. */
562 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
565 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
569 GST_WARNING_OBJECT (parse, "Invalid TrackVideoFPS %lf", num);
573 GST_DEBUG_OBJECT (parse, "TrackVideoFrameRate: %lf", num);
574 if (context->default_duration == 0)
575 context->default_duration =
576 gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
577 videocontext->default_fps = num;
581 /* width of the size to display the video at */
582 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
585 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
589 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayWidth 0");
593 GST_DEBUG_OBJECT (parse,
594 "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
595 videocontext->display_width = num;
599 /* height of the size to display the video at */
600 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
603 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
607 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayHeight 0");
611 GST_DEBUG_OBJECT (parse,
612 "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
613 videocontext->display_height = num;
617 /* width of the video in the file */
618 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
621 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
625 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelWidth 0");
629 GST_DEBUG_OBJECT (parse,
630 "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
631 videocontext->pixel_width = num;
635 /* height of the video in the file */
636 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
639 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
643 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelHeight 0");
647 GST_DEBUG_OBJECT (parse,
648 "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
649 videocontext->pixel_height = num;
653 /* whether the video is interlaced */
654 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
657 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
661 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
663 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
664 GST_DEBUG_OBJECT (parse, "TrackVideoInterlaced: %d",
665 (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 :
670 /* aspect ratio behaviour */
671 case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
674 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
677 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
678 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
679 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
680 GST_WARNING_OBJECT (parse,
681 "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
684 GST_DEBUG_OBJECT (parse,
685 "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
686 videocontext->asr_mode = num;
690 /* colourspace (only matters for raw video) fourcc */
691 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
696 gst_ebml_read_binary (ebml, &id, &data,
697 &datalen)) != GST_FLOW_OK)
702 GST_WARNING_OBJECT (parse,
703 "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
708 memcpy (&videocontext->fourcc, data, 4);
709 GST_DEBUG_OBJECT (parse,
710 "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
711 GST_FOURCC_ARGS (videocontext->fourcc));
717 GST_WARNING_OBJECT (parse,
718 "Unknown TrackVideo subelement 0x%x - ignoring", id);
720 case GST_MATROSKA_ID_VIDEOSTEREOMODE:
721 case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
722 case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
723 case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
724 case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
725 case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
726 case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
727 ret = gst_ebml_read_skip (ebml);
732 DEBUG_ELEMENT_STOP (parse, ebml, "TrackVideo", ret);
736 /* tracktype specific stuff for audio */
737 case GST_MATROSKA_ID_TRACKAUDIO:{
738 GstMatroskaTrackAudioContext *audiocontext;
740 DEBUG_ELEMENT_START (parse, ebml, "TrackAudio");
742 if (!gst_matroska_track_init_audio_context (&context)) {
743 GST_WARNING_OBJECT (parse,
744 "TrackAudio element in non-audio track - ignoring track");
745 ret = GST_FLOW_ERROR;
749 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
752 audiocontext = (GstMatroskaTrackAudioContext *) context;
753 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
756 while (ret == GST_FLOW_OK &&
757 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
758 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
763 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
766 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
771 GST_WARNING_OBJECT (parse,
772 "Invalid TrackAudioSamplingFrequency %lf", num);
776 GST_DEBUG_OBJECT (parse, "TrackAudioSamplingFrequency: %lf", num);
777 audiocontext->samplerate = num;
782 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
785 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
789 GST_WARNING_OBJECT (parse, "Invalid TrackAudioBitDepth 0");
793 GST_DEBUG_OBJECT (parse, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
795 audiocontext->bitdepth = num;
800 case GST_MATROSKA_ID_AUDIOCHANNELS:{
803 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
807 GST_WARNING_OBJECT (parse, "Invalid TrackAudioChannels 0");
811 GST_DEBUG_OBJECT (parse, "TrackAudioChannels: %" G_GUINT64_FORMAT,
813 audiocontext->channels = num;
818 GST_WARNING_OBJECT (parse,
819 "Unknown TrackAudio subelement 0x%x - ignoring", id);
821 case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
822 case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
823 ret = gst_ebml_read_skip (ebml);
828 DEBUG_ELEMENT_STOP (parse, ebml, "TrackAudio", ret);
833 /* codec identifier */
834 case GST_MATROSKA_ID_CODECID:{
837 if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
840 GST_DEBUG_OBJECT (parse, "CodecID: %s", GST_STR_NULL (text));
841 context->codec_id = text;
845 /* codec private data */
846 case GST_MATROSKA_ID_CODECPRIVATE:{
851 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
854 context->codec_priv = data;
855 context->codec_priv_size = size;
857 GST_DEBUG_OBJECT (parse, "CodecPrivate of size %" G_GUINT64_FORMAT,
862 /* name of the codec */
863 case GST_MATROSKA_ID_CODECNAME:{
866 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
869 GST_DEBUG_OBJECT (parse, "CodecName: %s", GST_STR_NULL (text));
870 context->codec_name = text;
874 /* name of this track */
875 case GST_MATROSKA_ID_TRACKNAME:{
878 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
881 context->name = text;
882 GST_DEBUG_OBJECT (parse, "TrackName: %s", GST_STR_NULL (text));
886 /* language (matters for audio/subtitles, mostly) */
887 case GST_MATROSKA_ID_TRACKLANGUAGE:{
890 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
894 context->language = text;
897 if (strlen (context->language) >= 4 && context->language[3] == '-')
898 context->language[3] = '\0';
900 GST_DEBUG_OBJECT (parse, "TrackLanguage: %s",
901 GST_STR_NULL (context->language));
905 /* whether this is actually used */
906 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
909 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
913 context->flags |= GST_MATROSKA_TRACK_ENABLED;
915 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
917 GST_DEBUG_OBJECT (parse, "TrackEnabled: %d",
918 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
922 /* whether it's the default for this track type */
923 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
926 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
930 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
932 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
934 GST_DEBUG_OBJECT (parse, "TrackDefault: %d",
935 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
939 /* whether the track must be used during playback */
940 case GST_MATROSKA_ID_TRACKFLAGFORCED:{
943 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
947 context->flags |= GST_MATROSKA_TRACK_FORCED;
949 context->flags &= ~GST_MATROSKA_TRACK_FORCED;
951 GST_DEBUG_OBJECT (parse, "TrackForced: %d",
952 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
956 /* lacing (like MPEG, where blocks don't end/start on frame
958 case GST_MATROSKA_ID_TRACKFLAGLACING:{
961 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
965 context->flags |= GST_MATROSKA_TRACK_LACING;
967 context->flags &= ~GST_MATROSKA_TRACK_LACING;
969 GST_DEBUG_OBJECT (parse, "TrackLacing: %d",
970 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
974 /* default length (in time) of one data block in this track */
975 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
978 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
983 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
987 GST_DEBUG_OBJECT (parse, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
989 context->default_duration = num;
993 case GST_MATROSKA_ID_CONTENTENCODINGS:{
994 ret = gst_matroska_read_common_read_track_encodings (&parse->common,
999 case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
1002 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1006 GST_WARNING_OBJECT (parse, "Invalid TrackTimeCodeScale %lf", num);
1010 GST_DEBUG_OBJECT (parse, "TrackTimeCodeScale: %lf", num);
1011 context->timecodescale = num;
1016 GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
1019 /* we ignore these because they're nothing useful (i.e. crap)
1020 * or simply not implemented yet. */
1021 case GST_MATROSKA_ID_TRACKMINCACHE:
1022 case GST_MATROSKA_ID_TRACKMAXCACHE:
1023 case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
1024 case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
1025 case GST_MATROSKA_ID_TRACKOVERLAY:
1026 case GST_MATROSKA_ID_TRACKTRANSLATE:
1027 case GST_MATROSKA_ID_TRACKOFFSET:
1028 case GST_MATROSKA_ID_CODECSETTINGS:
1029 case GST_MATROSKA_ID_CODECINFOURL:
1030 case GST_MATROSKA_ID_CODECDOWNLOADURL:
1031 case GST_MATROSKA_ID_CODECDECODEALL:
1032 ret = gst_ebml_read_skip (ebml);
1037 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1039 /* Decode codec private data if necessary */
1040 if (context->encodings && context->encodings->len > 0 && context->codec_priv
1041 && context->codec_priv_size > 0) {
1042 if (!gst_matroska_decode_data (context->encodings,
1043 &context->codec_priv, &context->codec_priv_size,
1044 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
1045 GST_WARNING_OBJECT (parse, "Decoding codec private data failed");
1046 ret = GST_FLOW_ERROR;
1050 if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
1051 && ret != GST_FLOW_EOS)) {
1052 if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
1053 GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
1055 parse->common.num_streams--;
1056 g_ptr_array_remove_index (parse->common.src, parse->common.num_streams);
1057 g_assert (parse->common.src->len == parse->common.num_streams);
1059 gst_matroska_track_free (context);
1065 if ((context->language == NULL || *context->language == '\0') &&
1066 (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
1067 context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
1068 GST_LOG ("stream %d: language=eng (assuming default)", context->index);
1069 context->language = g_strdup ("eng");
1078 gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
1081 gboolean res = FALSE;
1082 GstMatroskaTrackContext *context = NULL;
1085 context = gst_pad_get_element_private (pad);
1088 switch (GST_QUERY_TYPE (query)) {
1089 case GST_QUERY_POSITION:
1093 gst_query_parse_position (query, &format, NULL);
1095 if (format == GST_FORMAT_TIME) {
1096 GST_OBJECT_LOCK (parse);
1098 gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
1100 gst_query_set_position (query, GST_FORMAT_TIME,
1101 parse->common.segment.position);
1102 GST_OBJECT_UNLOCK (parse);
1103 } else if (format == GST_FORMAT_DEFAULT && context
1104 && context->default_duration) {
1105 GST_OBJECT_LOCK (parse);
1106 gst_query_set_position (query, GST_FORMAT_DEFAULT,
1107 context->pos / context->default_duration);
1108 GST_OBJECT_UNLOCK (parse);
1110 GST_DEBUG_OBJECT (parse,
1111 "only position query in TIME and DEFAULT format is supported");
1117 case GST_QUERY_DURATION:
1121 gst_query_parse_duration (query, &format, NULL);
1123 if (format == GST_FORMAT_TIME) {
1124 GST_OBJECT_LOCK (parse);
1125 gst_query_set_duration (query, GST_FORMAT_TIME,
1126 parse->common.segment.duration);
1127 GST_OBJECT_UNLOCK (parse);
1128 } else if (format == GST_FORMAT_DEFAULT && context
1129 && context->default_duration) {
1130 GST_OBJECT_LOCK (parse);
1131 gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1132 parse->common.segment.duration / context->default_duration);
1133 GST_OBJECT_UNLOCK (parse);
1135 GST_DEBUG_OBJECT (parse,
1136 "only duration query in TIME and DEFAULT format is supported");
1143 case GST_QUERY_SEEKING:
1147 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1148 if (fmt == GST_FORMAT_TIME) {
1151 /* assuming we'll be able to get an index ... */
1152 seekable = parse->seekable;
1154 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1155 0, parse->common.segment.duration);
1161 res = gst_pad_query_default (pad, (GstObject *) parse, query);
1169 gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
1171 return gst_matroska_parse_query (GST_MATROSKA_PARSE (element), NULL, query);
1175 gst_matroska_parse_handle_src_query (GstPad * pad, GstObject * parent,
1179 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
1181 ret = gst_matroska_parse_query (parse, pad, query);
1186 /* returns FALSE if there are no pads to deliver event to,
1187 * otherwise TRUE (whatever the outcome of event sending),
1188 * takes ownership of the passed event! */
1190 gst_matroska_parse_send_event (GstMatroskaParse * parse, GstEvent * event)
1192 gboolean ret = FALSE;
1194 g_return_val_if_fail (event != NULL, FALSE);
1196 GST_DEBUG_OBJECT (parse, "Sending event of type %s to all source pads",
1197 GST_EVENT_TYPE_NAME (event));
1199 gst_pad_push_event (parse->srcpad, event);
1205 gst_matroska_parse_element_send_event (GstElement * element, GstEvent * event)
1207 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
1210 g_return_val_if_fail (event != NULL, FALSE);
1212 if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1213 res = gst_matroska_parse_handle_seek_event (parse, NULL, event);
1215 GST_WARNING_OBJECT (parse, "Unhandled event of type %s",
1216 GST_EVENT_TYPE_NAME (event));
1219 gst_event_unref (event);
1223 /* searches for a cluster start from @pos,
1224 * return GST_FLOW_OK and cluster position in @pos if found */
1225 static GstFlowReturn
1226 gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
1228 gint64 newpos = *pos;
1230 GstFlowReturn ret = GST_FLOW_OK;
1231 const guint chunk = 64 * 1024;
1240 orig_offset = parse->common.offset;
1242 /* read in at newpos and scan for ebml cluster id */
1244 GstByteReader reader;
1248 ret = gst_pad_pull_range (parse->common.sinkpad, newpos, chunk, &buf);
1249 if (ret != GST_FLOW_OK)
1251 GST_DEBUG_OBJECT (parse,
1252 "read buffer size %" G_GSIZE_FORMAT " at offset %" G_GINT64_FORMAT,
1253 gst_buffer_get_size (buf), newpos);
1254 gst_buffer_map (buf, &map, GST_MAP_READ);
1257 gst_byte_reader_init (&reader, data, size);
1260 cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
1261 GST_MATROSKA_ID_CLUSTER, cluster_pos, size - cluster_pos);
1262 if (cluster_pos >= 0) {
1263 newpos += cluster_pos;
1264 GST_DEBUG_OBJECT (parse,
1265 "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
1266 /* extra checks whether we really sync'ed to a cluster:
1267 * - either it is the first and only cluster
1268 * - either there is a cluster after this one
1269 * - either cluster length is undefined
1271 /* ok if first cluster (there may not a subsequent one) */
1272 if (newpos == parse->first_cluster_offset) {
1273 GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
1276 parse->common.offset = newpos;
1277 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
1278 GST_ELEMENT_CAST (parse), &id, &length, &needed);
1279 if (ret != GST_FLOW_OK)
1281 g_assert (id == GST_MATROSKA_ID_CLUSTER);
1282 GST_DEBUG_OBJECT (parse, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
1284 /* ok if undefined length or first cluster */
1285 if (length == G_MAXUINT64) {
1286 GST_DEBUG_OBJECT (parse, "cluster has undefined length -> OK");
1290 parse->common.offset += length + needed;
1291 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
1292 GST_ELEMENT_CAST (parse), &id, &length, &needed);
1293 if (ret != GST_FLOW_OK)
1295 GST_DEBUG_OBJECT (parse, "next element is %scluster",
1296 id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
1297 if (id == GST_MATROSKA_ID_CLUSTER)
1299 /* not ok, resume */
1302 /* partial cluster id may have been in tail of buffer */
1303 newpos += MAX (size, 4) - 3;
1304 gst_buffer_unmap (buf, &map);
1305 gst_buffer_unref (buf);
1311 gst_buffer_unmap (buf, &map);
1312 gst_buffer_unref (buf);
1316 parse->common.offset = orig_offset;
1323 gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
1324 GstPad * pad, GstEvent * event)
1326 GstMatroskaIndex *entry = NULL;
1328 GstSeekType cur_type, stop_type;
1332 GstMatroskaTrackContext *track = NULL;
1333 GstSegment seeksegment = { 0, };
1337 track = gst_pad_get_element_private (pad);
1339 track = gst_matroska_read_common_get_seek_track (&parse->common, track);
1341 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1344 /* we can only seek on time */
1345 if (format != GST_FORMAT_TIME) {
1346 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
1350 /* copy segment, we need this because we still need the old
1351 * segment when we close the current segment. */
1352 memcpy (&seeksegment, &parse->common.segment, sizeof (GstSegment));
1355 GST_DEBUG_OBJECT (parse, "configuring seek");
1356 gst_segment_do_seek (&seeksegment, rate, format, flags,
1357 cur_type, cur, stop_type, stop, &update);
1360 GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
1362 /* check sanity before we start flushing and all that */
1363 GST_OBJECT_LOCK (parse);
1364 if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track,
1365 seeksegment.position, &parse->seek_index, &parse->seek_entry)) ==
1367 /* pull mode without index can scan later on */
1368 GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
1369 GST_OBJECT_UNLOCK (parse);
1372 GST_DEBUG_OBJECT (parse, "Seek position looks sane");
1373 GST_OBJECT_UNLOCK (parse);
1375 /* need to seek to cluster start to pick up cluster time */
1376 /* upstream takes care of flushing and all that
1377 * ... and newsegment event handling takes care of the rest */
1378 return perform_seek_to_offset (parse, entry->pos
1379 + parse->common.ebml_segment_start);
1383 * Handle whether we can perform the seek event or if we have to let the chain
1384 * function handle seeks to build the seek indexes first.
1387 gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
1391 GstSeekType cur_type, stop_type;
1396 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1401 /* we can only seek on time */
1402 if (format != GST_FORMAT_TIME) {
1403 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
1407 if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
1408 GST_DEBUG_OBJECT (parse, "Seek end-time not supported in streaming mode");
1412 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
1413 GST_DEBUG_OBJECT (parse,
1414 "Non-flushing seek not supported in streaming mode");
1418 if (flags & GST_SEEK_FLAG_SEGMENT) {
1419 GST_DEBUG_OBJECT (parse, "Segment seek not supported in streaming mode");
1423 /* check for having parsed index already */
1424 if (!parse->common.index_parsed) {
1425 gboolean building_index;
1428 if (!parse->index_offset) {
1429 GST_DEBUG_OBJECT (parse, "no index (location); no seek in push mode");
1433 GST_OBJECT_LOCK (parse);
1434 /* handle the seek event in the chain function */
1435 parse->common.state = GST_MATROSKA_READ_STATE_SEEK;
1436 /* no more seek can be issued until state reset to _DATA */
1438 /* copy the event */
1439 if (parse->seek_event)
1440 gst_event_unref (parse->seek_event);
1441 parse->seek_event = gst_event_ref (event);
1443 /* set the building_index flag so that only one thread can setup the
1444 * structures for index seeking. */
1445 building_index = parse->building_index;
1446 if (!building_index) {
1447 parse->building_index = TRUE;
1448 offset = parse->index_offset;
1450 GST_OBJECT_UNLOCK (parse);
1452 if (!building_index) {
1453 /* seek to the first subindex or legacy index */
1454 GST_INFO_OBJECT (parse, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
1455 return perform_seek_to_offset (parse, offset);
1458 /* well, we are handling it already */
1462 /* delegate to tweaked regular seek */
1463 return gst_matroska_parse_handle_seek_event (parse, pad, event);
1467 gst_matroska_parse_handle_src_event (GstPad * pad, GstObject * parent,
1470 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
1471 gboolean res = TRUE;
1473 switch (GST_EVENT_TYPE (event)) {
1474 case GST_EVENT_SEEK:
1475 /* no seeking until we are (safely) ready */
1476 if (parse->common.state != GST_MATROSKA_READ_STATE_DATA) {
1477 GST_DEBUG_OBJECT (parse, "not ready for seeking yet");
1480 res = gst_matroska_parse_handle_seek_push (parse, pad, event);
1481 gst_event_unref (event);
1486 GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
1487 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
1488 GstMatroskaTrackVideoContext *videocontext =
1489 (GstMatroskaTrackVideoContext *) context;
1491 GstClockTimeDiff diff;
1492 GstClockTime timestamp;
1494 gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
1496 GST_OBJECT_LOCK (parse);
1497 videocontext->earliest_time = timestamp + diff;
1498 GST_OBJECT_UNLOCK (parse);
1501 gst_event_unref (event);
1505 /* events we don't need to handle */
1506 case GST_EVENT_NAVIGATION:
1507 gst_event_unref (event);
1511 case GST_EVENT_LATENCY:
1513 res = gst_pad_push_event (parse->common.sinkpad, event);
1520 static GstFlowReturn
1521 gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml)
1523 GstFlowReturn ret = GST_FLOW_OK;
1526 DEBUG_ELEMENT_START (parse, ebml, "Tracks");
1528 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1529 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
1533 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1534 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1538 /* one track within the "all-tracks" header */
1539 case GST_MATROSKA_ID_TRACKENTRY:
1540 ret = gst_matroska_parse_add_stream (parse, ebml);
1544 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
1549 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
1551 parse->tracks_parsed = TRUE;
1557 * Read signed/unsigned "EBML" numbers.
1558 * Return: number of bytes processed.
1562 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
1564 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1572 while (read <= 8 && !(total & len_mask)) {
1579 if ((total &= (len_mask - 1)) == len_mask - 1)
1584 if (data[n] == 0xff)
1586 total = (total << 8) | data[n];
1590 if (read == num_ffs && total != 0)
1599 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
1604 /* read as unsigned number first */
1605 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1609 if (unum == G_MAXUINT64)
1612 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1617 static GstFlowReturn
1618 gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
1619 GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
1620 gboolean is_simpleblock)
1622 GstMatroskaTrackContext *stream = NULL;
1623 GstFlowReturn ret = GST_FLOW_OK;
1624 gboolean readblock = FALSE;
1626 guint64 block_duration = 0;
1627 GstBuffer *buf = NULL;
1629 gint stream_num = -1, n, laces = 0;
1631 gint *lace_size = NULL;
1634 gint64 referenceblock = 0;
1636 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1637 if (!is_simpleblock) {
1638 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
1642 id = GST_MATROSKA_ID_SIMPLEBLOCK;
1646 /* one block inside the group. Note, block parsing is one
1647 * of the harder things, so this code is a bit complicated.
1648 * See http://www.matroska.org/ for documentation. */
1649 case GST_MATROSKA_ID_SIMPLEBLOCK:
1650 case GST_MATROSKA_ID_BLOCK:
1656 gst_buffer_unref (buf);
1659 if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
1662 gst_buffer_map (buf, &map, GST_MAP_READ);
1666 /* first byte(s): blocknum */
1667 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
1672 /* fetch stream from num */
1673 stream_num = gst_matroska_read_common_stream_from_num (&parse->common,
1675 if (G_UNLIKELY (size < 3)) {
1676 GST_WARNING_OBJECT (parse, "Invalid size %u", size);
1677 /* non-fatal, try next block(group) */
1680 } else if (G_UNLIKELY (stream_num < 0 ||
1681 stream_num >= parse->common.num_streams)) {
1682 /* let's not give up on a stray invalid track number */
1683 GST_WARNING_OBJECT (parse,
1684 "Invalid stream %d for track number %" G_GUINT64_FORMAT
1685 "; ignoring block", stream_num, num);
1689 stream = g_ptr_array_index (parse->common.src, stream_num);
1691 /* time (relative to cluster time) */
1692 time = ((gint16) GST_READ_UINT16_BE (data));
1695 flags = GST_READ_UINT8 (data);
1699 GST_LOG_OBJECT (parse, "time %" G_GUINT64_FORMAT ", flags %d", time,
1702 switch ((flags & 0x06) >> 1) {
1703 case 0x0: /* no lacing */
1705 lace_size = g_new (gint, 1);
1706 lace_size[0] = size;
1709 case 0x1: /* xiph lacing */
1710 case 0x2: /* fixed-size lacing */
1711 case 0x3: /* EBML lacing */
1713 goto invalid_lacing;
1714 laces = GST_READ_UINT8 (data) + 1;
1717 lace_size = g_new0 (gint, laces);
1719 switch ((flags & 0x06) >> 1) {
1720 case 0x1: /* xiph lacing */ {
1721 guint temp, total = 0;
1723 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
1726 goto invalid_lacing;
1727 temp = GST_READ_UINT8 (data);
1728 lace_size[n] += temp;
1734 total += lace_size[n];
1736 lace_size[n] = size - total;
1740 case 0x2: /* fixed-size lacing */
1741 for (n = 0; n < laces; n++)
1742 lace_size[n] = size / laces;
1745 case 0x3: /* EBML lacing */ {
1748 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
1752 total = lace_size[0] = num;
1753 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
1757 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
1761 lace_size[n] = lace_size[n - 1] + snum;
1762 total += lace_size[n];
1765 lace_size[n] = size - total;
1772 if (ret != GST_FLOW_OK)
1779 case GST_MATROSKA_ID_BLOCKDURATION:{
1780 ret = gst_ebml_read_uint (ebml, &id, &block_duration);
1781 GST_DEBUG_OBJECT (parse, "BlockDuration: %" G_GUINT64_FORMAT,
1786 case GST_MATROSKA_ID_REFERENCEBLOCK:{
1787 ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
1788 GST_DEBUG_OBJECT (parse, "ReferenceBlock: %" G_GINT64_FORMAT,
1793 case GST_MATROSKA_ID_CODECSTATE:{
1795 guint64 data_len = 0;
1798 gst_ebml_read_binary (ebml, &id, &data,
1799 &data_len)) != GST_FLOW_OK)
1802 if (G_UNLIKELY (stream == NULL)) {
1803 GST_WARNING_OBJECT (parse,
1804 "Unexpected CodecState subelement - ignoring");
1808 g_free (stream->codec_state);
1809 stream->codec_state = data;
1810 stream->codec_state_size = data_len;
1816 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
1820 case GST_MATROSKA_ID_BLOCKVIRTUAL:
1821 case GST_MATROSKA_ID_BLOCKADDITIONS:
1822 case GST_MATROSKA_ID_REFERENCEPRIORITY:
1823 case GST_MATROSKA_ID_REFERENCEVIRTUAL:
1824 case GST_MATROSKA_ID_SLICES:
1825 GST_DEBUG_OBJECT (parse,
1826 "Skipping BlockGroup subelement 0x%x - ignoring", id);
1827 ret = gst_ebml_read_skip (ebml);
1835 /* reading a number or so could have failed */
1836 if (ret != GST_FLOW_OK)
1839 if (ret == GST_FLOW_OK && readblock) {
1840 guint64 duration = 0;
1841 gint64 lace_time = 0;
1842 gboolean delta_unit;
1844 stream = g_ptr_array_index (parse->common.src, stream_num);
1846 if (cluster_time != GST_CLOCK_TIME_NONE) {
1847 /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
1848 * Drop unless the lace contains timestamp 0? */
1849 if (time < 0 && (-time) > cluster_time) {
1852 if (stream->timecodescale == 1.0)
1853 lace_time = (cluster_time + time) * parse->common.time_scale;
1856 gst_util_guint64_to_gdouble ((cluster_time + time) *
1857 parse->common.time_scale) * stream->timecodescale;
1860 lace_time = GST_CLOCK_TIME_NONE;
1863 if (lace_time != GST_CLOCK_TIME_NONE) {
1864 parse->last_timestamp = lace_time;
1866 /* need to refresh segment info ASAP */
1867 if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
1869 GST_DEBUG_OBJECT (parse,
1870 "generating segment starting at %" GST_TIME_FORMAT,
1871 GST_TIME_ARGS (lace_time));
1872 /* pretend we seeked here */
1873 gst_segment_do_seek (&parse->common.segment, parse->common.segment.rate,
1874 GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
1875 GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
1876 /* now convey our segment notion downstream */
1877 segment = parse->common.segment;
1878 segment.position = segment.start;
1879 gst_matroska_parse_send_event (parse, gst_event_new_segment (&segment));
1880 parse->need_newsegment = FALSE;
1883 if (block_duration) {
1884 if (stream->timecodescale == 1.0)
1885 duration = gst_util_uint64_scale (block_duration,
1886 parse->common.time_scale, 1);
1889 gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
1890 (gst_util_uint64_scale (block_duration, parse->common.time_scale,
1891 1)) * stream->timecodescale);
1892 } else if (stream->default_duration) {
1893 duration = stream->default_duration * laces;
1895 /* else duration is diff between timecode of this and next block */
1897 /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
1898 a ReferenceBlock implies that this is not a keyframe. In either
1899 case, it only makes sense for video streams. */
1900 delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
1901 ((is_simpleblock && !(flags & 0x80)) || referenceblock);
1903 if (delta_unit && stream->set_discont) {
1904 /* When doing seeks or such, we need to restart on key frames or
1905 * decoders might choke. */
1906 GST_DEBUG_OBJECT (parse, "skipping delta unit");
1910 for (n = 0; n < laces; n++) {
1911 if (G_UNLIKELY (lace_size[n] > size)) {
1912 GST_WARNING_OBJECT (parse, "Invalid lace size");
1916 /* QoS for video track with an index. the assumption is that
1917 index entries point to keyframes, but if that is not true we
1918 will instad skip until the next keyframe. */
1919 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
1920 stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
1921 stream->index_table && parse->common.segment.rate > 0.0) {
1922 GstMatroskaTrackVideoContext *videocontext =
1923 (GstMatroskaTrackVideoContext *) stream;
1924 GstClockTime earliest_time;
1925 GstClockTime earliest_stream_time;
1927 GST_OBJECT_LOCK (parse);
1928 earliest_time = videocontext->earliest_time;
1929 GST_OBJECT_UNLOCK (parse);
1930 earliest_stream_time = gst_segment_to_position (&parse->common.segment,
1931 GST_FORMAT_TIME, earliest_time);
1933 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
1934 GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
1935 lace_time <= earliest_stream_time) {
1936 /* find index entry (keyframe) <= earliest_stream_time */
1937 GstMatroskaIndex *entry =
1938 gst_util_array_binary_search (stream->index_table->data,
1939 stream->index_table->len, sizeof (GstMatroskaIndex),
1940 (GCompareDataFunc) gst_matroska_index_seek_find,
1941 GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
1943 /* if that entry (keyframe) is after the current the current
1944 buffer, we can skip pushing (and thus decoding) all
1945 buffers until that keyframe. */
1946 if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
1947 entry->time > lace_time) {
1948 GST_LOG_OBJECT (parse, "Skipping lace before late keyframe");
1949 stream->set_discont = TRUE;
1955 sub = gst_buffer_create_sub (buf,
1956 GST_BUFFER_SIZE (buf) - size, lace_size[n]);
1957 GST_DEBUG_OBJECT (parse, "created subbuffer %p", sub);
1960 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
1962 GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
1964 if (stream->encodings != NULL && stream->encodings->len > 0)
1965 sub = gst_matroska_decode_buffer (stream, sub);
1968 GST_WARNING_OBJECT (parse, "Decoding buffer failed");
1972 GST_BUFFER_TIMESTAMP (sub) = lace_time;
1974 if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
1975 GstClockTime last_stop_end;
1977 /* Check if this stream is after segment stop */
1978 if (GST_CLOCK_TIME_IS_VALID (parse->common.segment.stop) &&
1979 lace_time >= parse->common.segment.stop) {
1980 GST_DEBUG_OBJECT (parse,
1981 "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
1982 GST_TIME_ARGS (parse->common.segment.stop));
1983 gst_buffer_unref (sub);
1986 if (offset >= stream->to_offset) {
1987 GST_DEBUG_OBJECT (parse, "Stream %d after playback section",
1989 gst_buffer_unref (sub);
1993 /* handle gaps, e.g. non-zero start-time, or an cue index entry
1994 * that landed us with timestamps not quite intended */
1995 if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
1996 parse->segment.rate > 0.0) {
1997 GstClockTimeDiff diff;
1999 /* only send newsegments with increasing start times,
2000 * otherwise if these go back and forth downstream (sinks) increase
2001 * accumulated time and running_time */
2002 diff = GST_CLOCK_DIFF (parse->segment.last_stop, lace_time);
2003 if (diff > 2 * GST_SECOND && lace_time > parse->segment.start &&
2004 (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
2005 lace_time < parse->segment.stop)) {
2006 GST_DEBUG_OBJECT (parse,
2007 "Gap of %" G_GINT64_FORMAT " ns detected in"
2008 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
2009 "Sending updated NEWSEGMENT events", diff,
2010 stream->index, GST_TIME_ARGS (stream->pos),
2011 GST_TIME_ARGS (lace_time));
2012 /* send newsegment events such that the gap is not accounted in
2013 * accum time, hence running_time */
2014 /* close ahead of gap */
2015 gst_matroska_parse_send_event (parse,
2016 gst_event_new_new_segment (TRUE, parse->segment.rate,
2017 parse->segment.format, parse->segment.last_stop,
2018 parse->segment.last_stop, parse->segment.last_stop));
2020 gst_matroska_parse_send_event (parse,
2021 gst_event_new_new_segment (FALSE, parse->segment.rate,
2022 parse->segment.format, lace_time, parse->segment.stop,
2024 /* align segment view with downstream,
2025 * prevents double-counting accum when closing segment */
2026 gst_segment_set_newsegment (&parse->segment, FALSE,
2027 parse->segment.rate, parse->segment.format, lace_time,
2028 parse->segment.stop, lace_time);
2029 parse->segment.last_stop = lace_time;
2033 if (!GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)
2034 || parse->segment.last_stop < lace_time) {
2035 parse->segment.last_stop = lace_time;
2038 last_stop_end = lace_time;
2040 GST_BUFFER_DURATION (sub) = duration / laces;
2041 last_stop_end += GST_BUFFER_DURATION (sub);
2044 if (!GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) ||
2045 parse->last_stop_end < last_stop_end)
2046 parse->last_stop_end = last_stop_end;
2048 if (parse->segment.duration == -1 ||
2049 parse->segment.duration < lace_time) {
2050 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME,
2052 gst_element_post_message (GST_ELEMENT_CAST (parse),
2053 gst_message_new_duration (GST_OBJECT_CAST (parse),
2054 GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
2058 stream->pos = lace_time;
2060 gst_matroska_parse_sync_streams (parse);
2062 if (stream->set_discont) {
2063 GST_DEBUG_OBJECT (parse, "marking DISCONT");
2064 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
2065 stream->set_discont = FALSE;
2068 /* reverse playback book-keeping */
2069 if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
2070 stream->from_time = lace_time;
2071 if (stream->from_offset == -1)
2072 stream->from_offset = offset;
2074 GST_DEBUG_OBJECT (parse,
2075 "Pushing lace %d, data of size %d for stream %d, time=%"
2076 GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
2077 GST_BUFFER_SIZE (sub), stream_num,
2078 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
2079 GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
2081 if (parse->element_index) {
2082 if (stream->index_writer_id == -1)
2083 gst_index_get_writer_id (parse->element_index,
2084 GST_OBJECT (stream->pad), &stream->index_writer_id);
2086 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2087 G_GUINT64_FORMAT " for writer id %d",
2088 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
2089 stream->index_writer_id);
2090 gst_index_add_association (parse->element_index,
2091 stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
2092 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
2093 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
2094 cluster_offset, NULL);
2097 gst_buffer_set_caps (sub, GST_PAD_CAPS (parse->srcpad));
2099 /* Postprocess the buffers depending on the codec used */
2100 if (stream->postprocess_frame) {
2101 GST_LOG_OBJECT (parse, "running post process");
2102 ret = stream->postprocess_frame (GST_ELEMENT (parse), stream, &sub);
2105 ret = gst_pad_push (stream->pad, sub);
2106 if (parse->segment.rate < 0) {
2107 if (lace_time > parse->segment.stop && ret == GST_FLOW_EOS) {
2108 /* In reverse playback we can get a GST_FLOW_EOS when
2109 * we are at the end of the segment, so we just need to jump
2110 * back to the previous section. */
2111 GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
2116 ret = gst_matroska_parse_combine_flows (parse, stream, ret);
2120 size -= lace_size[n];
2121 if (lace_time != GST_CLOCK_TIME_NONE && duration)
2122 lace_time += duration / laces;
2124 lace_time = GST_CLOCK_TIME_NONE;
2130 gst_buffer_unmap (buf, &map);
2131 gst_buffer_unref (buf);
2140 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
2141 /* non-fatal, try next block(group) */
2147 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Data error"));
2148 /* non-fatal, try next block(group) */
2154 /* return FALSE if block(group) should be skipped (due to a seek) */
2155 static inline gboolean
2156 gst_matroska_parse_seek_block (GstMatroskaParse * parse)
2158 if (G_UNLIKELY (parse->seek_block)) {
2159 if (!(--parse->seek_block)) {
2162 GST_LOG_OBJECT (parse, "should skip block due to seek");
2170 static GstFlowReturn
2171 gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
2175 guint64 seek_pos = (guint64) - 1;
2176 guint32 seek_id = 0;
2179 DEBUG_ELEMENT_START (parse, ebml, "Seek");
2181 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2182 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
2186 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2187 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2191 case GST_MATROSKA_ID_SEEKID:
2195 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
2198 GST_DEBUG_OBJECT (parse, "SeekID: %" G_GUINT64_FORMAT, t);
2203 case GST_MATROSKA_ID_SEEKPOSITION:
2207 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
2210 if (t > G_MAXINT64) {
2211 GST_WARNING_OBJECT (parse,
2212 "Too large SeekPosition %" G_GUINT64_FORMAT, t);
2216 GST_DEBUG_OBJECT (parse, "SeekPosition: %" G_GUINT64_FORMAT, t);
2222 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
2228 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2231 if (!seek_id || seek_pos == (guint64) - 1) {
2232 GST_WARNING_OBJECT (parse, "Incomplete seekhead entry (0x%x/%"
2233 G_GUINT64_FORMAT ")", seek_id, seek_pos);
2238 case GST_MATROSKA_ID_SEEKHEAD:
2241 case GST_MATROSKA_ID_CUES:
2242 case GST_MATROSKA_ID_TAGS:
2243 case GST_MATROSKA_ID_TRACKS:
2244 case GST_MATROSKA_ID_SEGMENTINFO:
2245 case GST_MATROSKA_ID_ATTACHMENTS:
2246 case GST_MATROSKA_ID_CHAPTERS:
2251 length = gst_matroska_read_common_get_length (&parse->common);
2253 if (length == (guint64) - 1) {
2254 GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
2258 /* check for validity */
2259 if (seek_pos + parse->common.ebml_segment_start + 12 >= length) {
2260 GST_WARNING_OBJECT (parse,
2261 "SeekHead reference lies outside file!" " (%"
2262 G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
2263 G_GUINT64_FORMAT ")", seek_pos, parse->common.ebml_segment_start,
2268 /* only pick up index location when streaming */
2269 if (seek_id == GST_MATROSKA_ID_CUES) {
2270 parse->index_offset = seek_pos + parse->common.ebml_segment_start;
2271 GST_DEBUG_OBJECT (parse, "Cues located at offset %" G_GUINT64_FORMAT,
2272 parse->index_offset);
2278 GST_DEBUG_OBJECT (parse, "Ignoring Seek entry for ID=0x%x", seek_id);
2281 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
2286 static GstFlowReturn
2287 gst_matroska_parse_parse_contents (GstMatroskaParse * parse, GstEbmlRead * ebml)
2289 GstFlowReturn ret = GST_FLOW_OK;
2292 DEBUG_ELEMENT_START (parse, ebml, "SeekHead");
2294 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2295 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
2299 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2300 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2304 case GST_MATROSKA_ID_SEEKENTRY:
2306 ret = gst_matroska_parse_parse_contents_seekentry (parse, ebml);
2307 /* Ignore EOS and errors here */
2308 if (ret != GST_FLOW_OK) {
2309 GST_DEBUG_OBJECT (parse, "Ignoring %s", gst_flow_get_name (ret));
2316 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
2322 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
2327 #define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
2329 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
2331 static inline GstFlowReturn
2332 gst_matroska_parse_check_read_size (GstMatroskaParse * parse, guint64 bytes)
2334 if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
2335 /* only a few blocks are expected/allowed to be large,
2336 * and will be recursed into, whereas others will be read and must fit */
2337 /* fatal in streaming case, as we can't step over easily */
2338 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2339 ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
2340 "file might be corrupt.", bytes));
2341 return GST_FLOW_ERROR;
2347 /* returns TRUE if we truely are in error state, and should give up */
2348 static inline gboolean
2349 gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
2353 /* sigh, one last attempt above and beyond call of duty ...;
2354 * search for cluster mark following current pos */
2355 pos = parse->common.offset;
2356 GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
2357 if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
2358 /* did not work, give up */
2361 GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
2362 /* try that position */
2363 parse->common.offset = pos;
2368 /* initializes @ebml with @bytes from input stream at current offset.
2369 * Returns EOS if insufficient available,
2370 * ERROR if too much was attempted to read. */
2371 static inline GstFlowReturn
2372 gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
2375 GstBuffer *buffer = NULL;
2376 GstFlowReturn ret = GST_FLOW_OK;
2378 GST_LOG_OBJECT (parse, "taking %" G_GUINT64_FORMAT " bytes for parsing",
2380 ret = gst_matroska_parse_check_read_size (parse, bytes);
2381 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2382 /* otherwise fatal */
2383 ret = GST_FLOW_ERROR;
2386 if (gst_adapter_available (parse->common.adapter) >= bytes)
2387 buffer = gst_adapter_take_buffer (parse->common.adapter, bytes);
2390 if (G_LIKELY (buffer)) {
2391 gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer,
2392 parse->common.offset);
2393 parse->common.offset += bytes;
2400 gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
2403 gboolean seekable = FALSE;
2404 gint64 start = -1, stop = -1;
2406 query = gst_query_new_seeking (GST_FORMAT_BYTES);
2407 if (!gst_pad_peer_query (parse->common.sinkpad, query)) {
2408 GST_DEBUG_OBJECT (parse, "seeking query failed");
2412 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
2414 /* try harder to query upstream size if we didn't get it the first time */
2415 if (seekable && stop == -1) {
2416 GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
2417 gst_pad_peer_query_duration (parse->common.sinkpad, GST_FORMAT_BYTES,
2421 /* if upstream doesn't know the size, it's likely that it's not seekable in
2422 * practice even if it technically may be seekable */
2423 if (seekable && (start != 0 || stop <= start)) {
2424 GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
2429 GST_INFO_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
2430 G_GUINT64_FORMAT ")", seekable, start, stop);
2431 parse->seekable = seekable;
2433 gst_query_unref (query);
2437 static GstFlowReturn
2438 gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
2444 GstFlowReturn ret = GST_FLOW_OK;
2446 GST_WARNING_OBJECT (parse,
2447 "Found Cluster element before Tracks, searching Tracks");
2450 before_pos = parse->common.offset;
2452 /* Search Tracks element */
2454 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
2455 GST_ELEMENT_CAST (parse), &id, &length, &needed);
2456 if (ret != GST_FLOW_OK)
2459 if (id != GST_MATROSKA_ID_TRACKS) {
2460 /* we may be skipping large cluster here, so forego size check etc */
2461 /* ... but we can't skip undefined size; force error */
2462 if (length == G_MAXUINT64) {
2463 ret = gst_matroska_parse_check_read_size (parse, length);
2466 parse->common.offset += needed;
2467 parse->offset += length;
2472 /* will lead to track parsing ... */
2473 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
2478 parse->offset = before_pos;
2484 #define GST_READ_CHECK(stmt) \
2486 if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
2487 if (ret == GST_FLOW_OVERFLOW) { \
2488 ret = GST_FLOW_OK; \
2495 gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
2498 if (parse->pushed_headers) {
2499 GST_WARNING_OBJECT (parse,
2500 "Accumulating headers, but headers are already pushed");
2503 if (parse->streamheader) {
2504 parse->streamheader = gst_buffer_append (parse->streamheader,
2505 gst_buffer_ref (buffer));
2507 parse->streamheader = gst_buffer_ref (buffer);
2510 GST_DEBUG ("%" G_GSIZE_FORMAT, gst_buffer_get_size (parse->streamheader));
2513 static GstFlowReturn
2514 gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
2517 GstFlowReturn ret = GST_FLOW_OK;
2519 if (!parse->pushed_headers) {
2522 GValue streamheader = { 0 };
2523 GValue bufval = { 0 };
2526 caps = gst_caps_new_empty_simple ("video/x-matroska");
2527 s = gst_caps_get_structure (caps, 0);
2528 g_value_init (&streamheader, GST_TYPE_ARRAY);
2529 g_value_init (&bufval, GST_TYPE_BUFFER);
2530 buf = gst_buffer_copy (parse->streamheader);
2531 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2532 gst_value_set_buffer (&bufval, buf);
2533 gst_buffer_unref (buf);
2534 gst_value_array_append_value (&streamheader, &bufval);
2535 g_value_unset (&bufval);
2536 gst_structure_set_value (s, "streamheader", &streamheader);
2537 g_value_unset (&streamheader);
2538 //gst_caps_replace (parse->caps, caps);
2539 gst_pad_set_caps (parse->srcpad, caps);
2541 buf = gst_buffer_copy (parse->streamheader);
2542 gst_caps_unref (caps);
2544 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
2545 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2546 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
2548 ret = gst_pad_push (parse->srcpad, buf);
2550 parse->pushed_headers = TRUE;
2554 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2556 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2558 if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
2559 parse->last_timestamp = GST_BUFFER_TIMESTAMP (buffer);
2561 GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
2563 ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
2568 static GstFlowReturn
2569 gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
2570 guint64 length, guint needed)
2572 GstEbmlRead ebml = { 0, };
2573 GstFlowReturn ret = GST_FLOW_OK;
2575 //GstBuffer *buffer;
2577 GST_DEBUG_OBJECT (parse, "Parsing Element id 0x%x, "
2578 "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
2581 if (gst_adapter_available (parse->adapter) >= length + needed) {
2582 buffer = gst_adapter_take_buffer (parse->adapter, length + needed);
2583 gst_pad_push (parse->srcpad, buffer);
2587 //GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2594 /* if we plan to read and parse this element, we need prefix (id + length)
2595 * and the contents */
2596 /* mind about overflow wrap-around when dealing with undefined size */
2598 if (G_LIKELY (length != G_MAXUINT64))
2601 switch (parse->common.state) {
2602 case GST_MATROSKA_READ_STATE_START:
2604 case GST_EBML_ID_HEADER:
2605 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2606 ret = gst_matroska_read_common_parse_header (&parse->common, &ebml);
2607 if (ret != GST_FLOW_OK)
2609 parse->common.state = GST_MATROSKA_READ_STATE_SEGMENT;
2610 gst_matroska_parse_check_seekability (parse);
2611 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2614 goto invalid_header;
2618 case GST_MATROSKA_READ_STATE_SEGMENT:
2620 case GST_MATROSKA_ID_SEGMENT:
2621 /* eat segment prefix */
2622 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2623 GST_DEBUG_OBJECT (parse,
2624 "Found Segment start at offset %" G_GUINT64_FORMAT,
2625 parse->common.offset);
2626 /* seeks are from the beginning of the segment,
2627 * after the segment ID/length */
2628 parse->common.ebml_segment_start = parse->common.offset;
2629 parse->common.state = GST_MATROSKA_READ_STATE_HEADER;
2630 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2633 GST_WARNING_OBJECT (parse,
2634 "Expected a Segment ID (0x%x), but received 0x%x!",
2635 GST_MATROSKA_ID_SEGMENT, id);
2636 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2637 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2641 case GST_MATROSKA_READ_STATE_SCANNING:
2642 if (id != GST_MATROSKA_ID_CLUSTER &&
2643 id != GST_MATROSKA_ID_CLUSTERTIMECODE)
2646 case GST_MATROSKA_READ_STATE_HEADER:
2647 case GST_MATROSKA_READ_STATE_DATA:
2648 case GST_MATROSKA_READ_STATE_SEEK:
2650 case GST_MATROSKA_ID_SEGMENTINFO:
2651 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2652 if (!parse->common.segmentinfo_parsed) {
2653 ret = gst_matroska_read_common_parse_info (&parse->common,
2654 GST_ELEMENT_CAST (parse), &ebml);
2656 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2658 case GST_MATROSKA_ID_TRACKS:
2659 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2660 if (!parse->tracks_parsed) {
2661 ret = gst_matroska_parse_parse_tracks (parse, &ebml);
2663 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2665 case GST_MATROSKA_ID_CLUSTER:
2666 if (G_UNLIKELY (!parse->tracks_parsed)) {
2667 GST_DEBUG_OBJECT (parse, "Cluster before Track");
2668 goto not_streamable;
2670 if (G_UNLIKELY (parse->common.state
2671 == GST_MATROSKA_READ_STATE_HEADER)) {
2672 parse->common.state = GST_MATROSKA_READ_STATE_DATA;
2673 parse->first_cluster_offset = parse->common.offset;
2674 GST_DEBUG_OBJECT (parse, "signaling no more pads");
2676 parse->cluster_time = GST_CLOCK_TIME_NONE;
2677 parse->cluster_offset = parse->common.offset;
2678 if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
2679 GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
2680 " not found in Cluster, trying next Cluster's first block instead",
2682 parse->seek_block = 0;
2684 parse->seek_first = FALSE;
2685 /* record next cluster for recovery */
2686 if (read != G_MAXUINT64)
2687 parse->next_cluster_offset = parse->cluster_offset + read;
2688 /* eat cluster prefix */
2689 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2690 ret = gst_matroska_parse_output (parse, ebml.buf, TRUE);
2691 //gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2693 case GST_MATROSKA_ID_CLUSTERTIMECODE:
2697 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2698 if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
2700 GST_DEBUG_OBJECT (parse, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
2701 parse->cluster_time = num;
2703 if (parse->common.element_index) {
2704 if (parse->common.element_index_writer_id == -1)
2705 gst_index_get_writer_id (parse->common.element_index,
2706 GST_OBJECT (parse), &parse->common.element_index_writer_id);
2707 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2708 G_GUINT64_FORMAT " for writer id %d",
2709 GST_TIME_ARGS (parse->cluster_time), parse->cluster_offset,
2710 parse->common.element_index_writer_id);
2711 gst_index_add_association (parse->common.element_index,
2712 parse->common.element_index_writer_id,
2713 GST_ASSOCIATION_FLAG_KEY_UNIT,
2714 GST_FORMAT_TIME, parse->cluster_time,
2715 GST_FORMAT_BYTES, parse->cluster_offset, NULL);
2718 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2721 case GST_MATROSKA_ID_BLOCKGROUP:
2722 if (!gst_matroska_parse_seek_block (parse))
2724 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2725 DEBUG_ELEMENT_START (parse, &ebml, "BlockGroup");
2726 if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
2727 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
2728 &ebml, parse->cluster_time, parse->cluster_offset, FALSE);
2730 DEBUG_ELEMENT_STOP (parse, &ebml, "BlockGroup", ret);
2731 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2733 case GST_MATROSKA_ID_SIMPLEBLOCK:
2734 if (!gst_matroska_parse_seek_block (parse))
2736 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2737 DEBUG_ELEMENT_START (parse, &ebml, "SimpleBlock");
2738 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
2739 &ebml, parse->cluster_time, parse->cluster_offset, TRUE);
2740 DEBUG_ELEMENT_STOP (parse, &ebml, "SimpleBlock", ret);
2741 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2743 case GST_MATROSKA_ID_ATTACHMENTS:
2744 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2745 if (!parse->common.attachments_parsed) {
2746 ret = gst_matroska_read_common_parse_attachments (&parse->common,
2747 GST_ELEMENT_CAST (parse), &ebml);
2749 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2751 case GST_MATROSKA_ID_TAGS:
2752 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2753 ret = gst_matroska_read_common_parse_metadata (&parse->common,
2754 GST_ELEMENT_CAST (parse), &ebml);
2755 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2757 case GST_MATROSKA_ID_CHAPTERS:
2758 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2759 ret = gst_matroska_read_common_parse_chapters (&parse->common, &ebml);
2760 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2762 case GST_MATROSKA_ID_SEEKHEAD:
2763 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2764 ret = gst_matroska_parse_parse_contents (parse, &ebml);
2765 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2767 case GST_MATROSKA_ID_CUES:
2768 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2769 if (!parse->common.index_parsed) {
2770 ret = gst_matroska_read_common_parse_index (&parse->common, &ebml);
2771 /* only push based; delayed index building */
2772 if (ret == GST_FLOW_OK
2773 && parse->common.state == GST_MATROSKA_READ_STATE_SEEK) {
2776 GST_OBJECT_LOCK (parse);
2777 event = parse->seek_event;
2778 parse->seek_event = NULL;
2779 GST_OBJECT_UNLOCK (parse);
2782 /* unlikely to fail, since we managed to seek to this point */
2783 if (!gst_matroska_parse_handle_seek_event (parse, NULL, event))
2785 /* resume data handling, main thread clear to seek again */
2786 GST_OBJECT_LOCK (parse);
2787 parse->common.state = GST_MATROSKA_READ_STATE_DATA;
2788 GST_OBJECT_UNLOCK (parse);
2791 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2793 case GST_MATROSKA_ID_POSITION:
2794 case GST_MATROSKA_ID_PREVSIZE:
2795 case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
2796 case GST_MATROSKA_ID_SILENTTRACKS:
2797 GST_DEBUG_OBJECT (parse,
2798 "Skipping Cluster subelement 0x%x - ignoring", id);
2802 GST_DEBUG_OBJECT (parse, "skipping Element 0x%x", id);
2803 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2804 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2810 if (ret == GST_FLOW_PARSE)
2814 gst_ebml_read_clear (&ebml);
2820 /* simply exit, maybe not enough data yet */
2821 /* no ebml to clear if read error */
2826 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2827 ("Failed to parse Element 0x%x", id));
2828 ret = GST_FLOW_ERROR;
2833 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2834 ("File layout does not permit streaming"));
2835 ret = GST_FLOW_ERROR;
2841 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2842 ("No Tracks element found"));
2843 ret = GST_FLOW_ERROR;
2849 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Invalid header"));
2850 ret = GST_FLOW_ERROR;
2855 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Failed to seek"));
2856 ret = GST_FLOW_ERROR;
2863 gst_matroska_parse_loop (GstPad * pad)
2865 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
2871 /* If we have to close a segment, send a new segment to do this now */
2872 if (G_LIKELY (parse->common.state == GST_MATROSKA_READ_STATE_DATA)) {
2873 if (G_UNLIKELY (parse->close_segment)) {
2874 gst_matroska_parse_send_event (parse, parse->close_segment);
2875 parse->close_segment = NULL;
2877 if (G_UNLIKELY (parse->new_segment)) {
2878 gst_matroska_parse_send_event (parse, parse->new_segment);
2879 parse->new_segment = NULL;
2883 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
2884 GST_ELEMENT_CAST (parse), &id, &length, &needed);
2885 if (ret == GST_FLOW_EOS)
2887 if (ret != GST_FLOW_OK) {
2888 if (gst_matroska_parse_check_parse_error (parse))
2894 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
2895 "size %" G_GUINT64_FORMAT ", needed %d", parse->offset, id,
2898 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
2899 if (ret == GST_FLOW_EOS)
2901 if (ret != GST_FLOW_OK)
2904 /* check if we're at the end of a configured segment */
2905 if (G_LIKELY (parse->src->len)) {
2908 g_assert (parse->num_streams == parse->src->len);
2909 for (i = 0; i < parse->src->len; i++) {
2910 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
2911 GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
2912 GST_TIME_ARGS (context->pos));
2913 if (context->eos == FALSE)
2917 GST_INFO_OBJECT (parse, "All streams are EOS");
2923 if (G_UNLIKELY (parse->offset ==
2924 gst_matroska_read_common_get_length (&parse->common))) {
2925 GST_LOG_OBJECT (parse, "Reached end of stream");
2935 if (parse->segment.rate < 0.0) {
2936 ret = gst_matroska_parse_seek_to_previous_keyframe (parse);
2937 if (ret == GST_FLOW_OK)
2944 const gchar *reason = gst_flow_get_name (ret);
2945 gboolean push_eos = FALSE;
2947 GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
2948 parse->segment_running = FALSE;
2949 gst_pad_pause_task (parse->common.sinkpad);
2951 if (ret == GST_FLOW_EOS) {
2952 /* perform EOS logic */
2954 /* Close the segment, i.e. update segment stop with the duration
2955 * if no stop was set */
2956 if (GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) &&
2957 !GST_CLOCK_TIME_IS_VALID (parse->segment.stop)) {
2959 gst_event_new_new_segment_full (TRUE, parse->segment.rate,
2960 parse->segment.applied_rate, parse->segment.format,
2961 parse->segment.start,
2962 MAX (parse->last_stop_end, parse->segment.start),
2963 parse->segment.time);
2964 gst_matroska_parse_send_event (parse, event);
2967 if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2970 /* for segment playback we need to post when (in stream time)
2971 * we stopped, this is either stop (when set) or the duration. */
2972 if ((stop = parse->segment.stop) == -1)
2973 stop = parse->last_stop_end;
2975 GST_LOG_OBJECT (parse, "Sending segment done, at end of segment");
2976 gst_element_post_message (GST_ELEMENT (parse),
2977 gst_message_new_segment_done (GST_OBJECT (parse), GST_FORMAT_TIME,
2982 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2983 /* for fatal errors we post an error message */
2984 GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
2985 ("stream stopped, reason %s", reason));
2989 /* send EOS, and prevent hanging if no streams yet */
2990 GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
2991 if (!gst_matroska_parse_send_event (parse, gst_event_new_eos ()) &&
2992 (ret == GST_FLOW_EOS)) {
2993 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
2994 (NULL), ("got eos but no streams (yet)"));
3003 * Create and push a flushing seek event upstream
3006 perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
3011 GST_DEBUG_OBJECT (parse, "Seeking to %" G_GUINT64_FORMAT, offset);
3014 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
3015 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
3016 GST_SEEK_TYPE_NONE, -1);
3018 res = gst_pad_push_event (parse->common.sinkpad, event);
3020 /* newsegment event will update offset */
3024 static GstFlowReturn
3025 gst_matroska_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
3027 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
3029 GstFlowReturn ret = GST_FLOW_OK;
3034 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
3035 GST_DEBUG_OBJECT (parse, "got DISCONT");
3036 gst_adapter_clear (parse->common.adapter);
3037 GST_OBJECT_LOCK (parse);
3038 gst_matroska_read_common_reset_streams (&parse->common,
3039 GST_CLOCK_TIME_NONE, FALSE);
3040 GST_OBJECT_UNLOCK (parse);
3043 gst_adapter_push (parse->common.adapter, buffer);
3047 available = gst_adapter_available (parse->common.adapter);
3049 ret = gst_matroska_read_common_peek_id_length_push (&parse->common,
3050 GST_ELEMENT_CAST (parse), &id, &length, &needed);
3051 if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_EOS))
3054 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
3055 "size %" G_GUINT64_FORMAT ", needed %d, available %d",
3056 parse->common.offset, id, length, needed, available);
3058 if (needed > available)
3061 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
3062 if (ret == GST_FLOW_EOS) {
3063 /* need more data */
3065 } else if (ret != GST_FLOW_OK) {
3072 gst_matroska_parse_handle_sink_event (GstPad * pad, GstObject * parent,
3075 gboolean res = TRUE;
3076 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
3078 GST_DEBUG_OBJECT (parse,
3079 "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
3081 switch (GST_EVENT_TYPE (event)) {
3082 case GST_EVENT_SEGMENT:
3084 const GstSegment *segment;
3086 /* some debug output */
3087 gst_event_parse_segment (event, &segment);
3088 GST_DEBUG_OBJECT (parse,
3089 "received format %d newsegment %" GST_SEGMENT_FORMAT,
3090 segment->format, segment);
3092 if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) {
3093 GST_DEBUG_OBJECT (parse, "still starting");
3097 /* we only expect a BYTE segment, e.g. following a seek */
3098 if (segment->format != GST_FORMAT_BYTES) {
3099 GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
3103 GST_DEBUG_OBJECT (parse, "clearing segment state");
3104 /* clear current segment leftover */
3105 gst_adapter_clear (parse->common.adapter);
3106 /* and some streaming setup */
3107 parse->common.offset = segment->start;
3108 /* do not know where we are;
3109 * need to come across a cluster and generate newsegment */
3110 parse->common.segment.position = GST_CLOCK_TIME_NONE;
3111 parse->cluster_time = GST_CLOCK_TIME_NONE;
3112 parse->cluster_offset = 0;
3113 parse->need_newsegment = TRUE;
3114 /* but keep some of the upstream segment */
3115 parse->common.segment.rate = segment->rate;
3117 /* chain will send initial newsegment after pads have been added,
3118 * or otherwise come up with one */
3119 GST_DEBUG_OBJECT (parse, "eating event");
3120 gst_event_unref (event);
3126 if (parse->common.state != GST_MATROSKA_READ_STATE_DATA) {
3127 gst_event_unref (event);
3128 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
3129 (NULL), ("got eos and didn't receive a complete header object"));
3130 } else if (parse->common.num_streams == 0) {
3131 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
3132 (NULL), ("got eos but no streams (yet)"));
3134 gst_matroska_parse_send_event (parse, event);
3138 case GST_EVENT_FLUSH_STOP:
3140 gst_adapter_clear (parse->common.adapter);
3141 GST_OBJECT_LOCK (parse);
3142 gst_matroska_read_common_reset_streams (&parse->common,
3143 GST_CLOCK_TIME_NONE, TRUE);
3144 GST_OBJECT_UNLOCK (parse);
3145 parse->common.segment.position = GST_CLOCK_TIME_NONE;
3146 parse->cluster_time = GST_CLOCK_TIME_NONE;
3147 parse->cluster_offset = 0;
3151 res = gst_pad_event_default (pad, parent, event);
3160 gst_matroska_parse_set_index (GstElement * element, GstIndex * index)
3162 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3164 GST_OBJECT_LOCK (parse);
3165 if (parse->common.element_index)
3166 gst_object_unref (parse->common.element_index);
3167 parse->common.element_index = index ? gst_object_ref (index) : NULL;
3168 GST_OBJECT_UNLOCK (parse);
3169 GST_DEBUG_OBJECT (parse, "Set index %" GST_PTR_FORMAT,
3170 parse->common.element_index);
3174 gst_matroska_parse_get_index (GstElement * element)
3176 GstIndex *result = NULL;
3177 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3179 GST_OBJECT_LOCK (parse);
3180 if (parse->common.element_index)
3181 result = gst_object_ref (parse->common.element_index);
3182 GST_OBJECT_UNLOCK (parse);
3184 GST_DEBUG_OBJECT (parse, "Returning index %" GST_PTR_FORMAT, result);
3190 static GstStateChangeReturn
3191 gst_matroska_parse_change_state (GstElement * element,
3192 GstStateChange transition)
3194 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3195 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3197 /* handle upwards state changes here */
3198 switch (transition) {
3203 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3205 /* handle downwards state changes */
3206 switch (transition) {
3207 case GST_STATE_CHANGE_PAUSED_TO_READY:
3208 gst_matroska_parse_reset (GST_ELEMENT (parse));
3218 gst_matroska_parse_plugin_init (GstPlugin * plugin)
3222 /* create an elementfactory for the matroska_parse element */
3223 if (!gst_element_register (plugin, "matroskaparse",
3224 GST_RANK_NONE, GST_TYPE_MATROSKA_PARSE))