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>
6 * matroska-parse.c: matroska file/stream parser
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /* TODO: check CRC32 if present
25 * TODO: there can be a segment after the first segment. Handle like
26 * chained oggs. Fixes #334082
27 * TODO: Test samples: http://www.matroska.org/samples/matrix/index.html
28 * http://samples.mplayerhq.hu/Matroska/
29 * TODO: check if parseing is done correct for all codecs according to spec
30 * TODO: seeking with incomplete or without CUE
34 * SECTION:element-matroskaparse
36 * matroskaparse parsees a Matroska file into the different contained streams.
39 * <title>Example launch line</title>
41 * gst-launch -v filesrc location=/path/to/mkv ! matroskaparse ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
42 * ]| This pipeline parsees a Matroska file and outputs the contained Vorbis audio.
53 #include <glib/gprintf.h>
55 /* For AVI compatibility mode
56 and for fourcc stuff */
57 #include <gst/riff/riff-read.h>
58 #include <gst/riff/riff-ids.h>
59 #include <gst/riff/riff-media.h>
61 #include <gst/tag/tag.h>
63 #include <gst/base/gsttypefindhelper.h>
73 #include <gst/pbutils/pbutils.h>
77 #include "matroska-parse.h"
78 #include "matroska-ids.h"
80 GST_DEBUG_CATEGORY_STATIC (matroskaparse_debug);
81 #define GST_CAT_DEFAULT matroskaparse_debug
83 #define DEBUG_ELEMENT_START(parse, ebml, element) \
84 GST_DEBUG_OBJECT (parse, "Parsing " element " element at offset %" \
85 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
87 #define DEBUG_ELEMENT_STOP(parse, ebml, element, ret) \
88 GST_DEBUG_OBJECT (parse, "Parsing " element " element " \
89 " finished with '%s'", gst_flow_get_name (ret))
98 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
101 GST_STATIC_CAPS ("video/x-matroska; video/webm")
104 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
107 GST_STATIC_CAPS ("video/x-matroska; video/webm")
110 static GstFlowReturn gst_matroska_parse_parse_id (GstMatroskaParse * parse,
111 guint32 id, guint64 length, guint needed);
113 /* element functions */
114 //static void gst_matroska_parse_loop (GstPad * pad);
116 static gboolean gst_matroska_parse_element_send_event (GstElement * element,
118 static gboolean gst_matroska_parse_element_query (GstElement * element,
122 static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
123 GstPad * pad, GstEvent * event);
124 static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
126 static const GstQueryType *gst_matroska_parse_get_src_query_types (GstPad *
128 static gboolean gst_matroska_parse_handle_src_query (GstPad * pad,
131 static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
133 static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
136 static GstStateChangeReturn
137 gst_matroska_parse_change_state (GstElement * element,
138 GstStateChange transition);
140 gst_matroska_parse_set_index (GstElement * element, GstIndex * index);
141 static GstIndex *gst_matroska_parse_get_index (GstElement * element);
144 static void gst_matroska_parse_reset (GstElement * element);
145 static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
148 GType gst_matroska_parse_get_type (void);
149 GST_BOILERPLATE (GstMatroskaParse, gst_matroska_parse, GstElement,
153 gst_matroska_parse_base_init (gpointer klass)
155 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
157 gst_element_class_add_pad_template (element_class,
158 gst_static_pad_template_get (&src_templ));
159 gst_element_class_add_pad_template (element_class,
160 gst_static_pad_template_get (&sink_templ));
162 gst_element_class_set_details_simple (element_class, "Matroska parser",
164 "Parses Matroska/WebM streams into video/audio/subtitles",
165 "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
169 gst_matroska_parse_finalize (GObject * object)
171 GstMatroskaParse *parse = GST_MATROSKA_PARSE (object);
174 g_ptr_array_free (parse->src, TRUE);
178 if (parse->global_tags) {
179 gst_tag_list_free (parse->global_tags);
180 parse->global_tags = NULL;
183 g_object_unref (parse->adapter);
185 G_OBJECT_CLASS (parent_class)->finalize (object);
189 gst_matroska_parse_class_init (GstMatroskaParseClass * klass)
191 GObjectClass *gobject_class = (GObjectClass *) klass;
192 GstElementClass *gstelement_class = (GstElementClass *) klass;
194 GST_DEBUG_CATEGORY_INIT (matroskaparse_debug, "matroskaparse", 0,
197 gobject_class->finalize = gst_matroska_parse_finalize;
199 gstelement_class->change_state =
200 GST_DEBUG_FUNCPTR (gst_matroska_parse_change_state);
201 gstelement_class->send_event =
202 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_send_event);
203 gstelement_class->query =
204 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_query);
206 gstelement_class->set_index =
207 GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
208 gstelement_class->get_index =
209 GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index);
213 gst_matroska_parse_init (GstMatroskaParse * parse,
214 GstMatroskaParseClass * klass)
216 parse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
217 gst_pad_set_chain_function (parse->sinkpad,
218 GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
219 gst_pad_set_event_function (parse->sinkpad,
220 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
221 gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
223 parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
224 gst_pad_set_event_function (parse->srcpad,
225 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event));
226 gst_pad_set_query_type_function (parse->srcpad,
227 GST_DEBUG_FUNCPTR (gst_matroska_parse_get_src_query_types));
228 gst_pad_set_query_function (parse->srcpad,
229 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
230 gst_pad_use_fixed_caps (parse->srcpad);
232 gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
234 /* initial stream no. */
237 parse->writing_app = NULL;
238 parse->muxing_app = NULL;
240 parse->global_tags = NULL;
242 parse->adapter = gst_adapter_new ();
245 gst_matroska_parse_reset (GST_ELEMENT (parse));
249 gst_matroska_track_free (GstMatroskaTrackContext * track)
251 g_free (track->codec_id);
252 g_free (track->codec_name);
253 g_free (track->name);
254 g_free (track->language);
255 g_free (track->codec_priv);
256 g_free (track->codec_state);
258 if (track->encodings != NULL) {
261 for (i = 0; i < track->encodings->len; ++i) {
262 GstMatroskaTrackEncoding *enc = &g_array_index (track->encodings,
263 GstMatroskaTrackEncoding,
266 g_free (enc->comp_settings);
268 g_array_free (track->encodings, TRUE);
271 if (track->pending_tags)
272 gst_tag_list_free (track->pending_tags);
274 if (track->index_table)
275 g_array_free (track->index_table, TRUE);
281 gst_matroska_parse_free_parsed_el (gpointer mem, gpointer user_data)
283 g_slice_free (guint64, mem);
287 gst_matroska_parse_reset (GstElement * element)
289 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
292 GST_DEBUG_OBJECT (parse, "Resetting state");
295 parse->state = GST_MATROSKA_PARSE_STATE_START;
297 /* clean up existing streams */
299 g_assert (parse->src->len == parse->num_streams);
300 for (i = 0; i < parse->src->len; i++) {
301 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
303 gst_caps_replace (&context->caps, NULL);
304 gst_matroska_track_free (context);
306 g_ptr_array_free (parse->src, TRUE);
308 parse->src = g_ptr_array_new ();
310 parse->num_streams = 0;
311 parse->num_a_streams = 0;
312 parse->num_t_streams = 0;
313 parse->num_v_streams = 0;
315 /* reset media info */
316 g_free (parse->writing_app);
317 parse->writing_app = NULL;
318 g_free (parse->muxing_app);
319 parse->muxing_app = NULL;
323 g_array_free (parse->index, TRUE);
329 parse->time_scale = 1000000;
330 parse->created = G_MININT64;
332 parse->index_parsed = FALSE;
333 parse->tracks_parsed = FALSE;
334 parse->segmentinfo_parsed = FALSE;
335 parse->attachments_parsed = FALSE;
337 g_list_foreach (parse->tags_parsed,
338 (GFunc) gst_matroska_parse_free_parsed_el, NULL);
339 g_list_free (parse->tags_parsed);
340 parse->tags_parsed = NULL;
342 g_list_foreach (parse->seek_parsed,
343 (GFunc) gst_matroska_parse_free_parsed_el, NULL);
344 g_list_free (parse->seek_parsed);
345 parse->seek_parsed = NULL;
347 gst_segment_init (&parse->segment, GST_FORMAT_TIME);
348 parse->last_stop_end = GST_CLOCK_TIME_NONE;
349 parse->seek_block = 0;
352 parse->cluster_time = GST_CLOCK_TIME_NONE;
353 parse->cluster_offset = 0;
354 parse->next_cluster_offset = 0;
355 parse->index_offset = 0;
356 parse->seekable = FALSE;
357 parse->need_newsegment = FALSE;
358 parse->building_index = FALSE;
359 if (parse->seek_event) {
360 gst_event_unref (parse->seek_event);
361 parse->seek_event = NULL;
364 parse->seek_index = NULL;
365 parse->seek_entry = 0;
367 if (parse->close_segment) {
368 gst_event_unref (parse->close_segment);
369 parse->close_segment = NULL;
372 if (parse->new_segment) {
373 gst_event_unref (parse->new_segment);
374 parse->new_segment = NULL;
377 if (parse->element_index) {
378 gst_object_unref (parse->element_index);
379 parse->element_index = NULL;
381 parse->element_index_writer_id = -1;
383 if (parse->global_tags) {
384 gst_tag_list_free (parse->global_tags);
386 parse->global_tags = gst_tag_list_new ();
388 if (parse->cached_buffer) {
389 gst_buffer_unref (parse->cached_buffer);
390 parse->cached_buffer = NULL;
395 * Calls pull_range for (offset,size) without advancing our offset
398 gst_matroska_parse_peek_bytes (GstMatroskaParse * parse, guint64 offset,
399 guint size, GstBuffer ** p_buf, guint8 ** bytes)
403 /* Caching here actually makes much less difference than one would expect.
404 * We do it mainly to avoid pulling buffers of 1 byte all the time */
405 if (parse->cached_buffer) {
406 guint64 cache_offset = GST_BUFFER_OFFSET (parse->cached_buffer);
407 guint cache_size = GST_BUFFER_SIZE (parse->cached_buffer);
409 if (cache_offset <= parse->offset &&
410 (parse->offset + size) <= (cache_offset + cache_size)) {
412 *p_buf = gst_buffer_create_sub (parse->cached_buffer,
413 parse->offset - cache_offset, size);
415 *bytes = GST_BUFFER_DATA (parse->cached_buffer) + parse->offset -
419 /* not enough data in the cache, free cache and get a new one */
420 gst_buffer_unref (parse->cached_buffer);
421 parse->cached_buffer = NULL;
424 /* refill the cache */
425 ret = gst_pad_pull_range (parse->sinkpad, parse->offset,
426 MAX (size, 64 * 1024), &parse->cached_buffer);
427 if (ret != GST_FLOW_OK) {
428 parse->cached_buffer = NULL;
432 if (GST_BUFFER_SIZE (parse->cached_buffer) >= size) {
434 *p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
436 *bytes = GST_BUFFER_DATA (parse->cached_buffer);
440 /* Not possible to get enough data, try a last time with
441 * requesting exactly the size we need */
442 gst_buffer_unref (parse->cached_buffer);
443 parse->cached_buffer = NULL;
446 gst_pad_pull_range (parse->sinkpad, parse->offset, size,
447 &parse->cached_buffer);
448 if (ret != GST_FLOW_OK) {
449 GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
457 if (GST_BUFFER_SIZE (parse->cached_buffer) < size) {
458 GST_WARNING_OBJECT (parse, "Dropping short buffer at offset %"
459 G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->offset,
460 size, GST_BUFFER_SIZE (parse->cached_buffer));
462 gst_buffer_unref (parse->cached_buffer);
463 parse->cached_buffer = NULL;
468 return GST_FLOW_UNEXPECTED;
472 *p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
474 *bytes = GST_BUFFER_DATA (parse->cached_buffer);
479 static const guint8 *
480 gst_matroska_parse_peek_pull (GstMatroskaParse * parse, guint peek)
484 gst_matroska_parse_peek_bytes (parse, parse->offset, peek, NULL, &data);
489 gst_matroska_parse_peek_id_length_pull (GstMatroskaParse * parse, guint32 * _id,
490 guint64 * _length, guint * _needed)
492 return gst_ebml_peek_id_length (_id, _length, _needed,
493 (GstPeekData) gst_matroska_parse_peek_pull, (gpointer) parse,
494 GST_ELEMENT_CAST (parse), parse->offset);
498 gst_matroska_parse_get_length (GstMatroskaParse * parse)
500 GstFormat fmt = GST_FORMAT_BYTES;
503 if (!gst_pad_query_peer_duration (parse->sinkpad, &fmt, &end) ||
504 fmt != GST_FORMAT_BYTES || end < 0)
505 GST_DEBUG_OBJECT (parse, "no upstream length");
511 gst_matroska_parse_stream_from_num (GstMatroskaParse * parse, guint track_num)
515 g_assert (parse->src->len == parse->num_streams);
516 for (n = 0; n < parse->src->len; n++) {
517 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, n);
519 if (context->num == track_num) {
524 if (n == parse->num_streams)
525 GST_WARNING_OBJECT (parse,
526 "Failed to find corresponding pad for tracknum %d", track_num);
532 gst_matroska_parse_encoding_cmp (GstMatroskaTrackEncoding * a,
533 GstMatroskaTrackEncoding * b)
535 if (b->order > a->order)
537 else if (b->order < a->order)
544 gst_matroska_parse_encoding_order_unique (GArray * encodings, guint64 order)
548 if (encodings == NULL || encodings->len == 0)
551 for (i = 0; i < encodings->len; i++)
552 if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
559 gst_matroska_parse_read_track_encoding (GstMatroskaParse * parse,
560 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
562 GstMatroskaTrackEncoding enc = { 0, };
566 DEBUG_ELEMENT_START (parse, ebml, "ContentEncoding");
567 /* Set default values */
569 /* All other default values are 0 */
571 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
572 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncoding", ret);
576 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
577 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
581 case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
584 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
587 if (!gst_matroska_parse_encoding_order_unique (context->encodings, num)) {
588 GST_ERROR_OBJECT (parse, "ContentEncodingOrder %" G_GUINT64_FORMAT
589 "is not unique for track %d", num, context->num);
590 ret = GST_FLOW_ERROR;
594 GST_DEBUG_OBJECT (parse, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
599 case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
602 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
605 if (num > 7 && num == 0) {
606 GST_ERROR_OBJECT (parse, "Invalid ContentEncodingScope %"
607 G_GUINT64_FORMAT, num);
608 ret = GST_FLOW_ERROR;
612 GST_DEBUG_OBJECT (parse, "ContentEncodingScope: %" G_GUINT64_FORMAT,
618 case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
621 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
625 GST_ERROR_OBJECT (parse, "Invalid ContentEncodingType %"
626 G_GUINT64_FORMAT, num);
627 ret = GST_FLOW_ERROR;
629 } else if (num != 0) {
630 GST_ERROR_OBJECT (parse, "Encrypted tracks are not supported yet");
631 ret = GST_FLOW_ERROR;
634 GST_DEBUG_OBJECT (parse, "ContentEncodingType: %" G_GUINT64_FORMAT,
639 case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
641 DEBUG_ELEMENT_START (parse, ebml, "ContentCompression");
643 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
646 while (ret == GST_FLOW_OK &&
647 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
648 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
652 case GST_MATROSKA_ID_CONTENTCOMPALGO:{
655 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
659 GST_ERROR_OBJECT (parse, "Invalid ContentCompAlgo %"
660 G_GUINT64_FORMAT, num);
661 ret = GST_FLOW_ERROR;
664 GST_DEBUG_OBJECT (parse, "ContentCompAlgo: %" G_GUINT64_FORMAT,
670 case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
675 gst_ebml_read_binary (ebml, &id, &data,
676 &size)) != GST_FLOW_OK) {
679 enc.comp_settings = data;
680 enc.comp_settings_length = size;
681 GST_DEBUG_OBJECT (parse,
682 "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
686 GST_WARNING_OBJECT (parse,
687 "Unknown ContentCompression subelement 0x%x - ignoring", id);
688 ret = gst_ebml_read_skip (ebml);
692 DEBUG_ELEMENT_STOP (parse, ebml, "ContentCompression", ret);
696 case GST_MATROSKA_ID_CONTENTENCRYPTION:
697 GST_ERROR_OBJECT (parse, "Encrypted tracks not yet supported");
698 gst_ebml_read_skip (ebml);
699 ret = GST_FLOW_ERROR;
702 GST_WARNING_OBJECT (parse,
703 "Unknown ContentEncoding subelement 0x%x - ignoring", id);
704 ret = gst_ebml_read_skip (ebml);
709 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncoding", ret);
710 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
713 /* TODO: Check if the combination of values is valid */
715 g_array_append_val (context->encodings, enc);
721 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
722 guint8 ** data_out, guint * size_out,
723 GstMatroskaTrackCompressionAlgorithm algo)
725 guint8 *new_data = NULL;
727 guint8 *data = *data_out;
728 guint size = *size_out;
731 if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
733 /* zlib encoded data */
739 zstream.zalloc = (alloc_func) 0;
740 zstream.zfree = (free_func) 0;
741 zstream.opaque = (voidpf) 0;
742 if (inflateInit (&zstream) != Z_OK) {
743 GST_WARNING ("zlib initialization failed.");
747 zstream.next_in = (Bytef *) data;
748 zstream.avail_in = orig_size;
749 new_size = orig_size;
750 new_data = g_malloc (new_size);
751 zstream.avail_out = new_size;
752 zstream.next_out = (Bytef *) new_data;
755 result = inflate (&zstream, Z_NO_FLUSH);
756 if (result != Z_OK && result != Z_STREAM_END) {
757 GST_WARNING ("zlib decompression failed.");
759 inflateEnd (&zstream);
763 new_data = g_realloc (new_data, new_size);
764 zstream.next_out = (Bytef *) (new_data + zstream.total_out);
765 zstream.avail_out += 4000;
766 } while (zstream.avail_in != 0 && result != Z_STREAM_END);
768 if (result != Z_STREAM_END) {
772 new_size = zstream.total_out;
773 inflateEnd (&zstream);
776 GST_WARNING ("zlib encoded tracks not supported.");
780 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
782 /* bzip2 encoded data */
787 bzstream.bzalloc = NULL;
788 bzstream.bzfree = NULL;
789 bzstream.opaque = NULL;
792 if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
793 GST_WARNING ("bzip2 initialization failed.");
798 bzstream.next_in = (char *) data;
799 bzstream.avail_in = orig_size;
800 new_size = orig_size;
801 new_data = g_malloc (new_size);
802 bzstream.avail_out = new_size;
803 bzstream.next_out = (char *) new_data;
806 result = BZ2_bzDecompress (&bzstream);
807 if (result != BZ_OK && result != BZ_STREAM_END) {
808 GST_WARNING ("bzip2 decompression failed.");
810 BZ2_bzDecompressEnd (&bzstream);
814 new_data = g_realloc (new_data, new_size);
815 bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
816 bzstream.avail_out += 4000;
817 } while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
819 if (result != BZ_STREAM_END) {
823 new_size = bzstream.total_out_lo32;
824 BZ2_bzDecompressEnd (&bzstream);
827 GST_WARNING ("bzip2 encoded tracks not supported.");
831 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
832 /* lzo encoded data */
834 int orig_size, out_size;
839 new_data = g_malloc (new_size);
845 result = lzo1x_decode (new_data, &out_size, data, &orig_size);
849 new_data = g_realloc (new_data, new_size);
851 } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
853 new_size -= out_size;
855 if (result != LZO_OUTPUT_FULL) {
856 GST_WARNING ("lzo decompression failed");
863 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
864 /* header stripped encoded data */
865 if (enc->comp_settings_length > 0) {
866 new_data = g_malloc (size + enc->comp_settings_length);
867 new_size = size + enc->comp_settings_length;
869 memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
870 memcpy (new_data + enc->comp_settings_length, data, size);
873 GST_ERROR ("invalid compression algorithm %d", algo);
883 *data_out = new_data;
884 *size_out = new_size;
891 gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
892 guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
899 g_return_val_if_fail (encodings != NULL, FALSE);
900 g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
901 g_return_val_if_fail (size_out != NULL, FALSE);
906 for (i = 0; i < encodings->len; i++) {
907 GstMatroskaTrackEncoding *enc =
908 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
909 guint8 *new_data = NULL;
912 if ((enc->scope & scope) == 0)
915 /* Encryption not supported yet */
916 if (enc->type != 0) {
925 gst_matroska_decompress_data (enc, &new_data, &new_size,
931 if ((data == *data_out && free) || (data != *data_out))
939 if ((data == *data_out && free) || (data != *data_out))
953 gst_matroska_decode_content_encodings (GArray * encodings)
957 if (encodings == NULL)
960 for (i = 0; i < encodings->len; i++) {
961 GstMatroskaTrackEncoding *enc =
962 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
963 GstMatroskaTrackEncoding *enc2;
967 if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
971 /* Encryption not supported yet */
973 return GST_FLOW_ERROR;
975 if (i + 1 >= encodings->len)
976 return GST_FLOW_ERROR;
978 enc2 = &g_array_index (encodings, GstMatroskaTrackEncoding, i + 1);
980 if (enc->comp_settings_length == 0)
983 data = enc->comp_settings;
984 size = enc->comp_settings_length;
986 if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
987 return GST_FLOW_ERROR;
989 g_free (enc->comp_settings);
991 enc->comp_settings = data;
992 enc->comp_settings_length = size;
999 gst_matroska_parse_read_track_encodings (GstMatroskaParse * parse,
1000 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
1005 DEBUG_ELEMENT_START (parse, ebml, "ContentEncodings");
1007 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1008 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1012 context->encodings =
1013 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
1015 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1016 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1020 case GST_MATROSKA_ID_CONTENTENCODING:
1021 ret = gst_matroska_parse_read_track_encoding (parse, ebml, context);
1024 GST_WARNING_OBJECT (parse,
1025 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
1026 ret = gst_ebml_read_skip (ebml);
1031 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1032 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
1035 /* Sort encodings according to their order */
1036 g_array_sort (context->encodings,
1037 (GCompareFunc) gst_matroska_parse_encoding_cmp);
1039 return gst_matroska_decode_content_encodings (context->encodings);
1043 gst_matroska_parse_tracknumber_unique (GstMatroskaParse * parse, guint64 num)
1047 g_assert (parse->src->len == parse->num_streams);
1048 for (i = 0; i < parse->src->len; i++) {
1049 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1051 if (context->num == num)
1058 static GstFlowReturn
1059 gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
1061 GstMatroskaTrackContext *context;
1065 DEBUG_ELEMENT_START (parse, ebml, "TrackEntry");
1067 /* start with the master */
1068 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1069 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1073 /* allocate generic... if we know the type, we'll g_renew()
1074 * with the precise type */
1075 context = g_new0 (GstMatroskaTrackContext, 1);
1076 g_ptr_array_add (parse->src, context);
1077 context->index = parse->num_streams;
1078 context->index_writer_id = -1;
1079 context->type = 0; /* no type yet */
1080 context->default_duration = 0;
1082 context->set_discont = TRUE;
1083 context->timecodescale = 1.0;
1085 GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
1086 GST_MATROSKA_TRACK_LACING;
1087 context->last_flow = GST_FLOW_OK;
1088 context->to_offset = G_MAXINT64;
1089 parse->num_streams++;
1090 g_assert (parse->src->len == parse->num_streams);
1092 GST_DEBUG_OBJECT (parse, "Stream number %d", context->index);
1094 /* try reading the trackentry headers */
1095 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1096 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1100 /* track number (unique stream ID) */
1101 case GST_MATROSKA_ID_TRACKNUMBER:{
1104 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1108 GST_ERROR_OBJECT (parse, "Invalid TrackNumber 0");
1109 ret = GST_FLOW_ERROR;
1111 } else if (!gst_matroska_parse_tracknumber_unique (parse, num)) {
1112 GST_ERROR_OBJECT (parse, "TrackNumber %" G_GUINT64_FORMAT
1113 " is not unique", num);
1114 ret = GST_FLOW_ERROR;
1118 GST_DEBUG_OBJECT (parse, "TrackNumber: %" G_GUINT64_FORMAT, num);
1122 /* track UID (unique identifier) */
1123 case GST_MATROSKA_ID_TRACKUID:{
1126 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1130 GST_ERROR_OBJECT (parse, "Invalid TrackUID 0");
1131 ret = GST_FLOW_ERROR;
1135 GST_DEBUG_OBJECT (parse, "TrackUID: %" G_GUINT64_FORMAT, num);
1140 /* track type (video, audio, combined, subtitle, etc.) */
1141 case GST_MATROSKA_ID_TRACKTYPE:{
1144 if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
1148 if (context->type != 0 && context->type != track_type) {
1149 GST_WARNING_OBJECT (parse,
1150 "More than one tracktype defined in a TrackEntry - skipping");
1152 } else if (track_type < 1 || track_type > 254) {
1153 GST_WARNING_OBJECT (parse, "Invalid TrackType %" G_GUINT64_FORMAT,
1158 GST_DEBUG_OBJECT (parse, "TrackType: %" G_GUINT64_FORMAT, track_type);
1160 /* ok, so we're actually going to reallocate this thing */
1161 switch (track_type) {
1162 case GST_MATROSKA_TRACK_TYPE_VIDEO:
1163 gst_matroska_track_init_video_context (&context);
1165 case GST_MATROSKA_TRACK_TYPE_AUDIO:
1166 gst_matroska_track_init_audio_context (&context);
1168 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
1169 gst_matroska_track_init_subtitle_context (&context);
1171 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
1172 case GST_MATROSKA_TRACK_TYPE_LOGO:
1173 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
1174 case GST_MATROSKA_TRACK_TYPE_CONTROL:
1176 GST_WARNING_OBJECT (parse,
1177 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
1182 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1186 /* tracktype specific stuff for video */
1187 case GST_MATROSKA_ID_TRACKVIDEO:{
1188 GstMatroskaTrackVideoContext *videocontext;
1190 DEBUG_ELEMENT_START (parse, ebml, "TrackVideo");
1192 if (!gst_matroska_track_init_video_context (&context)) {
1193 GST_WARNING_OBJECT (parse,
1194 "TrackVideo element in non-video track - ignoring track");
1195 ret = GST_FLOW_ERROR;
1197 } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1200 videocontext = (GstMatroskaTrackVideoContext *) context;
1201 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1203 while (ret == GST_FLOW_OK &&
1204 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1205 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1209 /* Should be one level up but some broken muxers write it here. */
1210 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1213 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1217 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1221 GST_DEBUG_OBJECT (parse,
1222 "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
1223 context->default_duration = num;
1227 /* video framerate */
1228 /* NOTE: This one is here only for backward compatibility.
1229 * Use _TRACKDEFAULDURATION one level up. */
1230 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
1233 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1237 GST_WARNING_OBJECT (parse, "Invalid TrackVideoFPS %lf", num);
1241 GST_DEBUG_OBJECT (parse, "TrackVideoFrameRate: %lf", num);
1242 if (context->default_duration == 0)
1243 context->default_duration =
1244 gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
1245 videocontext->default_fps = num;
1249 /* width of the size to display the video at */
1250 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
1253 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1257 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayWidth 0");
1261 GST_DEBUG_OBJECT (parse,
1262 "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
1263 videocontext->display_width = num;
1267 /* height of the size to display the video at */
1268 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
1271 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1275 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayHeight 0");
1279 GST_DEBUG_OBJECT (parse,
1280 "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
1281 videocontext->display_height = num;
1285 /* width of the video in the file */
1286 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
1289 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1293 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelWidth 0");
1297 GST_DEBUG_OBJECT (parse,
1298 "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
1299 videocontext->pixel_width = num;
1303 /* height of the video in the file */
1304 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
1307 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1311 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelHeight 0");
1315 GST_DEBUG_OBJECT (parse,
1316 "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
1317 videocontext->pixel_height = num;
1321 /* whether the video is interlaced */
1322 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
1325 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1329 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
1331 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
1332 GST_DEBUG_OBJECT (parse, "TrackVideoInterlaced: %d",
1333 (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 :
1338 /* aspect ratio behaviour */
1339 case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
1342 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1345 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
1346 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
1347 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
1348 GST_WARNING_OBJECT (parse,
1349 "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
1352 GST_DEBUG_OBJECT (parse,
1353 "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
1354 videocontext->asr_mode = num;
1358 /* colourspace (only matters for raw video) fourcc */
1359 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
1364 gst_ebml_read_binary (ebml, &id, &data,
1365 &datalen)) != GST_FLOW_OK)
1370 GST_WARNING_OBJECT (parse,
1371 "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
1376 memcpy (&videocontext->fourcc, data, 4);
1377 GST_DEBUG_OBJECT (parse,
1378 "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
1379 GST_FOURCC_ARGS (videocontext->fourcc));
1385 GST_WARNING_OBJECT (parse,
1386 "Unknown TrackVideo subelement 0x%x - ignoring", id);
1388 case GST_MATROSKA_ID_VIDEOSTEREOMODE:
1389 case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
1390 case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
1391 case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
1392 case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
1393 case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
1394 case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
1395 ret = gst_ebml_read_skip (ebml);
1400 DEBUG_ELEMENT_STOP (parse, ebml, "TrackVideo", ret);
1404 /* tracktype specific stuff for audio */
1405 case GST_MATROSKA_ID_TRACKAUDIO:{
1406 GstMatroskaTrackAudioContext *audiocontext;
1408 DEBUG_ELEMENT_START (parse, ebml, "TrackAudio");
1410 if (!gst_matroska_track_init_audio_context (&context)) {
1411 GST_WARNING_OBJECT (parse,
1412 "TrackAudio element in non-audio track - ignoring track");
1413 ret = GST_FLOW_ERROR;
1417 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
1420 audiocontext = (GstMatroskaTrackAudioContext *) context;
1421 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1423 while (ret == GST_FLOW_OK &&
1424 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1425 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1430 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
1433 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1438 GST_WARNING_OBJECT (parse,
1439 "Invalid TrackAudioSamplingFrequency %lf", num);
1443 GST_DEBUG_OBJECT (parse, "TrackAudioSamplingFrequency: %lf", num);
1444 audiocontext->samplerate = num;
1449 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
1452 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1456 GST_WARNING_OBJECT (parse, "Invalid TrackAudioBitDepth 0");
1460 GST_DEBUG_OBJECT (parse, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
1462 audiocontext->bitdepth = num;
1467 case GST_MATROSKA_ID_AUDIOCHANNELS:{
1470 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1474 GST_WARNING_OBJECT (parse, "Invalid TrackAudioChannels 0");
1478 GST_DEBUG_OBJECT (parse, "TrackAudioChannels: %" G_GUINT64_FORMAT,
1480 audiocontext->channels = num;
1485 GST_WARNING_OBJECT (parse,
1486 "Unknown TrackAudio subelement 0x%x - ignoring", id);
1488 case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
1489 case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
1490 ret = gst_ebml_read_skip (ebml);
1495 DEBUG_ELEMENT_STOP (parse, ebml, "TrackAudio", ret);
1500 /* codec identifier */
1501 case GST_MATROSKA_ID_CODECID:{
1504 if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
1507 GST_DEBUG_OBJECT (parse, "CodecID: %s", GST_STR_NULL (text));
1508 context->codec_id = text;
1512 /* codec private data */
1513 case GST_MATROSKA_ID_CODECPRIVATE:{
1518 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
1521 context->codec_priv = data;
1522 context->codec_priv_size = size;
1524 GST_DEBUG_OBJECT (parse, "CodecPrivate of size %" G_GUINT64_FORMAT,
1529 /* name of the codec */
1530 case GST_MATROSKA_ID_CODECNAME:{
1533 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1536 GST_DEBUG_OBJECT (parse, "CodecName: %s", GST_STR_NULL (text));
1537 context->codec_name = text;
1541 /* name of this track */
1542 case GST_MATROSKA_ID_TRACKNAME:{
1545 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1548 context->name = text;
1549 GST_DEBUG_OBJECT (parse, "TrackName: %s", GST_STR_NULL (text));
1553 /* language (matters for audio/subtitles, mostly) */
1554 case GST_MATROSKA_ID_TRACKLANGUAGE:{
1557 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1561 context->language = text;
1564 if (strlen (context->language) >= 4 && context->language[3] == '-')
1565 context->language[3] = '\0';
1567 GST_DEBUG_OBJECT (parse, "TrackLanguage: %s",
1568 GST_STR_NULL (context->language));
1572 /* whether this is actually used */
1573 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
1576 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1580 context->flags |= GST_MATROSKA_TRACK_ENABLED;
1582 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
1584 GST_DEBUG_OBJECT (parse, "TrackEnabled: %d",
1585 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1589 /* whether it's the default for this track type */
1590 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
1593 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1597 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
1599 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
1601 GST_DEBUG_OBJECT (parse, "TrackDefault: %d",
1602 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1606 /* whether the track must be used during playback */
1607 case GST_MATROSKA_ID_TRACKFLAGFORCED:{
1610 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1614 context->flags |= GST_MATROSKA_TRACK_FORCED;
1616 context->flags &= ~GST_MATROSKA_TRACK_FORCED;
1618 GST_DEBUG_OBJECT (parse, "TrackForced: %d",
1619 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1623 /* lacing (like MPEG, where blocks don't end/start on frame
1625 case GST_MATROSKA_ID_TRACKFLAGLACING:{
1628 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1632 context->flags |= GST_MATROSKA_TRACK_LACING;
1634 context->flags &= ~GST_MATROSKA_TRACK_LACING;
1636 GST_DEBUG_OBJECT (parse, "TrackLacing: %d",
1637 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1641 /* default length (in time) of one data block in this track */
1642 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1645 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1650 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1654 GST_DEBUG_OBJECT (parse, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
1656 context->default_duration = num;
1660 case GST_MATROSKA_ID_CONTENTENCODINGS:{
1661 ret = gst_matroska_parse_read_track_encodings (parse, ebml, context);
1665 case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
1668 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1672 GST_WARNING_OBJECT (parse, "Invalid TrackTimeCodeScale %lf", num);
1676 GST_DEBUG_OBJECT (parse, "TrackTimeCodeScale: %lf", num);
1677 context->timecodescale = num;
1682 GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
1685 /* we ignore these because they're nothing useful (i.e. crap)
1686 * or simply not implemented yet. */
1687 case GST_MATROSKA_ID_TRACKMINCACHE:
1688 case GST_MATROSKA_ID_TRACKMAXCACHE:
1689 case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
1690 case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
1691 case GST_MATROSKA_ID_TRACKOVERLAY:
1692 case GST_MATROSKA_ID_TRACKTRANSLATE:
1693 case GST_MATROSKA_ID_TRACKOFFSET:
1694 case GST_MATROSKA_ID_CODECSETTINGS:
1695 case GST_MATROSKA_ID_CODECINFOURL:
1696 case GST_MATROSKA_ID_CODECDOWNLOADURL:
1697 case GST_MATROSKA_ID_CODECDECODEALL:
1698 ret = gst_ebml_read_skip (ebml);
1703 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1705 /* Decode codec private data if necessary */
1706 if (context->encodings && context->encodings->len > 0 && context->codec_priv
1707 && context->codec_priv_size > 0) {
1708 if (!gst_matroska_decode_data (context->encodings,
1709 &context->codec_priv, &context->codec_priv_size,
1710 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
1711 GST_WARNING_OBJECT (parse, "Decoding codec private data failed");
1712 ret = GST_FLOW_ERROR;
1716 if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
1717 && ret != GST_FLOW_UNEXPECTED)) {
1718 if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
1719 GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
1721 parse->num_streams--;
1722 g_ptr_array_remove_index (parse->src, parse->num_streams);
1723 g_assert (parse->src->len == parse->num_streams);
1725 gst_matroska_track_free (context);
1731 if ((context->language == NULL || *context->language == '\0') &&
1732 (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
1733 context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
1734 GST_LOG ("stream %d: language=eng (assuming default)", context->index);
1735 context->language = g_strdup ("eng");
1743 static const GstQueryType *
1744 gst_matroska_parse_get_src_query_types (GstPad * pad)
1746 static const GstQueryType query_types[] = {
1757 gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
1760 gboolean res = FALSE;
1761 GstMatroskaTrackContext *context = NULL;
1764 context = gst_pad_get_element_private (pad);
1767 switch (GST_QUERY_TYPE (query)) {
1768 case GST_QUERY_POSITION:
1772 gst_query_parse_position (query, &format, NULL);
1774 if (format == GST_FORMAT_TIME) {
1775 GST_OBJECT_LOCK (parse);
1777 gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
1779 gst_query_set_position (query, GST_FORMAT_TIME,
1780 parse->segment.last_stop);
1781 GST_OBJECT_UNLOCK (parse);
1782 } else if (format == GST_FORMAT_DEFAULT && context
1783 && context->default_duration) {
1784 GST_OBJECT_LOCK (parse);
1785 gst_query_set_position (query, GST_FORMAT_DEFAULT,
1786 context->pos / context->default_duration);
1787 GST_OBJECT_UNLOCK (parse);
1789 GST_DEBUG_OBJECT (parse,
1790 "only position query in TIME and DEFAULT format is supported");
1796 case GST_QUERY_DURATION:
1800 gst_query_parse_duration (query, &format, NULL);
1802 if (format == GST_FORMAT_TIME) {
1803 GST_OBJECT_LOCK (parse);
1804 gst_query_set_duration (query, GST_FORMAT_TIME,
1805 parse->segment.duration);
1806 GST_OBJECT_UNLOCK (parse);
1807 } else if (format == GST_FORMAT_DEFAULT && context
1808 && context->default_duration) {
1809 GST_OBJECT_LOCK (parse);
1810 gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1811 parse->segment.duration / context->default_duration);
1812 GST_OBJECT_UNLOCK (parse);
1814 GST_DEBUG_OBJECT (parse,
1815 "only duration query in TIME and DEFAULT format is supported");
1822 case GST_QUERY_SEEKING:
1826 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1827 if (fmt == GST_FORMAT_TIME) {
1830 /* assuming we'll be able to get an index ... */
1831 seekable = parse->seekable;
1833 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1834 0, parse->segment.duration);
1840 res = gst_pad_query_default (pad, query);
1848 gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
1850 return gst_matroska_parse_query (GST_MATROSKA_PARSE (element), NULL, query);
1854 gst_matroska_parse_handle_src_query (GstPad * pad, GstQuery * query)
1857 GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
1859 ret = gst_matroska_parse_query (parse, pad, query);
1861 gst_object_unref (parse);
1867 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
1870 if (i1->time < *time)
1872 else if (i1->time > *time)
1878 static GstMatroskaIndex *
1879 gst_matroskaparse_do_index_seek (GstMatroskaParse * parse,
1880 GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
1881 gint * _entry_index)
1883 GstMatroskaIndex *entry = NULL;
1886 if (!parse->index || !parse->index->len)
1889 /* find entry just before or at the requested position */
1890 if (track && track->index_table)
1891 index = track->index_table;
1893 index = parse->index;
1896 gst_util_array_binary_search (index->data, index->len,
1897 sizeof (GstMatroskaIndex),
1898 (GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE,
1902 entry = &g_array_index (index, GstMatroskaIndex, 0);
1907 *_entry_index = entry - (GstMatroskaIndex *) index->data;
1912 /* takes ownership of taglist */
1914 gst_matroska_parse_found_global_tag (GstMatroskaParse * parse,
1915 GstTagList * taglist)
1917 if (parse->global_tags) {
1918 /* nothing sent yet, add to cache */
1919 gst_tag_list_insert (parse->global_tags, taglist, GST_TAG_MERGE_APPEND);
1920 gst_tag_list_free (taglist);
1922 /* hm, already sent, no need to cache and wait anymore */
1923 GST_DEBUG_OBJECT (parse, "Sending late global tags %" GST_PTR_FORMAT,
1925 gst_element_found_tags (GST_ELEMENT (parse), taglist);
1929 /* returns FALSE if there are no pads to deliver event to,
1930 * otherwise TRUE (whatever the outcome of event sending),
1931 * takes ownership of the passed event! */
1933 gst_matroska_parse_send_event (GstMatroskaParse * parse, GstEvent * event)
1935 gboolean ret = FALSE;
1937 g_return_val_if_fail (event != NULL, FALSE);
1939 GST_DEBUG_OBJECT (parse, "Sending event of type %s to all source pads",
1940 GST_EVENT_TYPE_NAME (event));
1942 gst_pad_push_event (parse->srcpad, event);
1948 gst_matroska_parse_element_send_event (GstElement * element, GstEvent * event)
1950 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
1953 g_return_val_if_fail (event != NULL, FALSE);
1955 if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1956 res = gst_matroska_parse_handle_seek_event (parse, NULL, event);
1958 GST_WARNING_OBJECT (parse, "Unhandled event of type %s",
1959 GST_EVENT_TYPE_NAME (event));
1962 gst_event_unref (event);
1966 /* determine track to seek in */
1967 static GstMatroskaTrackContext *
1968 gst_matroska_parse_get_seek_track (GstMatroskaParse * parse,
1969 GstMatroskaTrackContext * track)
1973 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
1976 for (i = 0; i < parse->src->len; i++) {
1977 GstMatroskaTrackContext *stream;
1979 stream = g_ptr_array_index (parse->src, i);
1980 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
1988 gst_matroska_parse_reset_streams (GstMatroskaParse * parse, GstClockTime time,
1993 GST_DEBUG_OBJECT (parse, "resetting stream state");
1995 g_assert (parse->src->len == parse->num_streams);
1996 for (i = 0; i < parse->src->len; i++) {
1997 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1998 context->pos = time;
1999 context->set_discont = TRUE;
2000 context->eos = FALSE;
2001 context->from_time = GST_CLOCK_TIME_NONE;
2003 context->last_flow = GST_FLOW_OK;
2004 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2005 GstMatroskaTrackVideoContext *videocontext =
2006 (GstMatroskaTrackVideoContext *) context;
2007 /* parse object lock held by caller */
2008 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2013 /* searches for a cluster start from @pos,
2014 * return GST_FLOW_OK and cluster position in @pos if found */
2015 static GstFlowReturn
2016 gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
2018 gint64 newpos = *pos;
2020 GstFlowReturn ret = GST_FLOW_OK;
2021 const guint chunk = 64 * 1024;
2022 GstBuffer *buf = NULL;
2027 orig_offset = parse->offset;
2029 /* read in at newpos and scan for ebml cluster id */
2031 GstByteReader reader;
2034 ret = gst_pad_pull_range (parse->sinkpad, newpos, chunk, &buf);
2035 if (ret != GST_FLOW_OK)
2037 GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
2038 GST_BUFFER_SIZE (buf), newpos);
2039 gst_byte_reader_init_from_buffer (&reader, buf);
2042 cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
2043 GST_MATROSKA_ID_CLUSTER, cluster_pos,
2044 GST_BUFFER_SIZE (buf) - cluster_pos);
2045 if (cluster_pos >= 0) {
2046 newpos += cluster_pos;
2047 GST_DEBUG_OBJECT (parse,
2048 "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
2049 /* extra checks whether we really sync'ed to a cluster:
2050 * - either it is the first and only cluster
2051 * - either there is a cluster after this one
2052 * - either cluster length is undefined
2054 /* ok if first cluster (there may not a subsequent one) */
2055 if (newpos == parse->first_cluster_offset) {
2056 GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
2059 parse->offset = newpos;
2061 gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2062 if (ret != GST_FLOW_OK)
2064 g_assert (id == GST_MATROSKA_ID_CLUSTER);
2065 GST_DEBUG_OBJECT (parse, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
2067 /* ok if undefined length or first cluster */
2068 if (length == G_MAXUINT64) {
2069 GST_DEBUG_OBJECT (parse, "cluster has undefined length -> OK");
2073 parse->offset += length + needed;
2075 gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2076 if (ret != GST_FLOW_OK)
2078 GST_DEBUG_OBJECT (parse, "next element is %scluster",
2079 id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
2080 if (id == GST_MATROSKA_ID_CLUSTER)
2082 /* not ok, resume */
2085 /* partial cluster id may have been in tail of buffer */
2086 newpos += MAX (GST_BUFFER_SIZE (buf), 4) - 3;
2087 gst_buffer_unref (buf);
2093 gst_buffer_unref (buf);
2097 parse->offset = orig_offset;
2104 gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
2105 GstPad * pad, GstEvent * event)
2107 GstMatroskaIndex *entry = NULL;
2109 GstSeekType cur_type, stop_type;
2113 GstMatroskaTrackContext *track = NULL;
2114 GstSegment seeksegment = { 0, };
2118 track = gst_pad_get_element_private (pad);
2120 track = gst_matroska_parse_get_seek_track (parse, track);
2122 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2125 /* we can only seek on time */
2126 if (format != GST_FORMAT_TIME) {
2127 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2131 /* copy segment, we need this because we still need the old
2132 * segment when we close the current segment. */
2133 memcpy (&seeksegment, &parse->segment, sizeof (GstSegment));
2136 GST_DEBUG_OBJECT (parse, "configuring seek");
2137 gst_segment_set_seek (&seeksegment, rate, format, flags,
2138 cur_type, cur, stop_type, stop, &update);
2141 GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
2143 /* check sanity before we start flushing and all that */
2144 GST_OBJECT_LOCK (parse);
2145 if ((entry = gst_matroskaparse_do_index_seek (parse, track,
2146 seeksegment.last_stop, &parse->seek_index, &parse->seek_entry)) ==
2148 /* pull mode without index can scan later on */
2149 GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
2150 GST_OBJECT_UNLOCK (parse);
2153 GST_DEBUG_OBJECT (parse, "Seek position looks sane");
2154 GST_OBJECT_UNLOCK (parse);
2156 /* need to seek to cluster start to pick up cluster time */
2157 /* upstream takes care of flushing and all that
2158 * ... and newsegment event handling takes care of the rest */
2159 return perform_seek_to_offset (parse, entry->pos + parse->ebml_segment_start);
2163 * Handle whether we can perform the seek event or if we have to let the chain
2164 * function handle seeks to build the seek indexes first.
2167 gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
2171 GstSeekType cur_type, stop_type;
2176 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2181 /* we can only seek on time */
2182 if (format != GST_FORMAT_TIME) {
2183 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2187 if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
2188 GST_DEBUG_OBJECT (parse, "Seek end-time not supported in streaming mode");
2192 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
2193 GST_DEBUG_OBJECT (parse,
2194 "Non-flushing seek not supported in streaming mode");
2198 if (flags & GST_SEEK_FLAG_SEGMENT) {
2199 GST_DEBUG_OBJECT (parse, "Segment seek not supported in streaming mode");
2203 /* check for having parsed index already */
2204 if (!parse->index_parsed) {
2205 gboolean building_index;
2208 if (!parse->index_offset) {
2209 GST_DEBUG_OBJECT (parse, "no index (location); no seek in push mode");
2213 GST_OBJECT_LOCK (parse);
2214 /* handle the seek event in the chain function */
2215 parse->state = GST_MATROSKA_PARSE_STATE_SEEK;
2216 /* no more seek can be issued until state reset to _DATA */
2218 /* copy the event */
2219 if (parse->seek_event)
2220 gst_event_unref (parse->seek_event);
2221 parse->seek_event = gst_event_ref (event);
2223 /* set the building_index flag so that only one thread can setup the
2224 * structures for index seeking. */
2225 building_index = parse->building_index;
2226 if (!building_index) {
2227 parse->building_index = TRUE;
2228 offset = parse->index_offset;
2230 GST_OBJECT_UNLOCK (parse);
2232 if (!building_index) {
2233 /* seek to the first subindex or legacy index */
2234 GST_INFO_OBJECT (parse, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
2235 return perform_seek_to_offset (parse, offset);
2238 /* well, we are handling it already */
2242 /* delegate to tweaked regular seek */
2243 return gst_matroska_parse_handle_seek_event (parse, pad, event);
2247 gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
2249 GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
2250 gboolean res = TRUE;
2252 switch (GST_EVENT_TYPE (event)) {
2253 case GST_EVENT_SEEK:
2254 /* no seeking until we are (safely) ready */
2255 if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
2256 GST_DEBUG_OBJECT (parse, "not ready for seeking yet");
2259 res = gst_matroska_parse_handle_seek_push (parse, pad, event);
2260 gst_event_unref (event);
2265 GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
2266 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2267 GstMatroskaTrackVideoContext *videocontext =
2268 (GstMatroskaTrackVideoContext *) context;
2270 GstClockTimeDiff diff;
2271 GstClockTime timestamp;
2273 gst_event_parse_qos (event, &proportion, &diff, ×tamp);
2275 GST_OBJECT_LOCK (parse);
2276 videocontext->earliest_time = timestamp + diff;
2277 GST_OBJECT_UNLOCK (parse);
2280 gst_event_unref (event);
2284 /* events we don't need to handle */
2285 case GST_EVENT_NAVIGATION:
2286 gst_event_unref (event);
2290 case GST_EVENT_LATENCY:
2292 res = gst_pad_push_event (parse->sinkpad, event);
2296 gst_object_unref (parse);
2302 /* skip unknown or alike element */
2303 static GstFlowReturn
2304 gst_matroska_parse_parse_skip (GstMatroskaParse * parse, GstEbmlRead * ebml,
2305 const gchar * parent_name, guint id)
2307 if (id == GST_EBML_ID_VOID) {
2308 GST_DEBUG_OBJECT (parse, "Skipping EBML Void element");
2309 } else if (id == GST_EBML_ID_CRC32) {
2310 GST_DEBUG_OBJECT (parse, "Skipping EBML CRC32 element");
2312 GST_WARNING_OBJECT (parse,
2313 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
2316 return gst_ebml_read_skip (ebml);
2319 static GstFlowReturn
2320 gst_matroska_parse_parse_header (GstMatroskaParse * parse, GstEbmlRead * ebml)
2327 /* this function is the first to be called */
2333 ret = gst_ebml_peek_id (ebml, &id);
2334 if (ret != GST_FLOW_OK)
2337 GST_DEBUG_OBJECT (parse, "id: %08x", id);
2339 if (id != GST_EBML_ID_HEADER) {
2340 GST_ERROR_OBJECT (parse, "Failed to read header");
2344 ret = gst_ebml_read_master (ebml, &id);
2345 if (ret != GST_FLOW_OK)
2348 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2349 ret = gst_ebml_peek_id (ebml, &id);
2350 if (ret != GST_FLOW_OK)
2354 /* is our read version uptodate? */
2355 case GST_EBML_ID_EBMLREADVERSION:{
2358 ret = gst_ebml_read_uint (ebml, &id, &num);
2359 if (ret != GST_FLOW_OK)
2361 if (num != GST_EBML_VERSION) {
2362 GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
2364 return GST_FLOW_ERROR;
2367 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2371 /* we only handle 8 byte lengths at max */
2372 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
2375 ret = gst_ebml_read_uint (ebml, &id, &num);
2376 if (ret != GST_FLOW_OK)
2378 if (num > sizeof (guint64)) {
2379 GST_ERROR_OBJECT (ebml,
2380 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
2381 return GST_FLOW_ERROR;
2383 GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
2387 /* we handle 4 byte IDs at max */
2388 case GST_EBML_ID_EBMLMAXIDLENGTH:{
2391 ret = gst_ebml_read_uint (ebml, &id, &num);
2392 if (ret != GST_FLOW_OK)
2394 if (num > sizeof (guint32)) {
2395 GST_ERROR_OBJECT (ebml,
2396 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
2397 return GST_FLOW_ERROR;
2399 GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
2403 case GST_EBML_ID_DOCTYPE:{
2406 ret = gst_ebml_read_ascii (ebml, &id, &text);
2407 if (ret != GST_FLOW_OK)
2410 GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
2418 case GST_EBML_ID_DOCTYPEREADVERSION:{
2421 ret = gst_ebml_read_uint (ebml, &id, &num);
2422 if (ret != GST_FLOW_OK)
2425 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2430 ret = gst_matroska_parse_parse_skip (parse, ebml, "EBML header", id);
2431 if (ret != GST_FLOW_OK)
2435 /* we ignore these two, as they don't tell us anything we care about */
2436 case GST_EBML_ID_EBMLVERSION:
2437 case GST_EBML_ID_DOCTYPEVERSION:
2438 ret = gst_ebml_read_skip (ebml);
2439 if (ret != GST_FLOW_OK)
2447 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
2448 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
2449 (doctype == NULL)) {
2452 GST_INFO_OBJECT (parse, "Input is %s version %d", doctype, version);
2454 GST_WARNING_OBJECT (parse, "Input is EBML without doctype, assuming "
2455 "matroska (version %d)", version);
2459 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2460 ("Parser version (2) is too old to read %s version %d",
2461 GST_STR_NULL (doctype), version));
2462 ret = GST_FLOW_ERROR;
2466 GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, (NULL),
2467 ("Input is not a matroska stream (doctype=%s)", doctype));
2468 ret = GST_FLOW_ERROR;
2475 static GstFlowReturn
2476 gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml)
2478 GstFlowReturn ret = GST_FLOW_OK;
2481 DEBUG_ELEMENT_START (parse, ebml, "Tracks");
2483 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2484 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2488 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2489 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2493 /* one track within the "all-tracks" header */
2494 case GST_MATROSKA_ID_TRACKENTRY:
2495 ret = gst_matroska_parse_add_stream (parse, ebml);
2499 ret = gst_matroska_parse_parse_skip (parse, ebml, "Track", id);
2503 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2505 parse->tracks_parsed = TRUE;
2510 static GstFlowReturn
2511 gst_matroska_parse_parse_index_cuetrack (GstMatroskaParse * parse,
2512 GstEbmlRead * ebml, guint * nentries)
2516 GstMatroskaIndex idx;
2518 idx.pos = (guint64) - 1;
2520 idx.time = GST_CLOCK_TIME_NONE;
2523 DEBUG_ELEMENT_START (parse, ebml, "CueTrackPositions");
2525 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2526 DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2530 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2531 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2536 case GST_MATROSKA_ID_CUETRACK:
2540 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2545 GST_WARNING_OBJECT (parse, "Invalid CueTrack 0");
2549 GST_DEBUG_OBJECT (parse, "CueTrack: %" G_GUINT64_FORMAT, num);
2554 /* position in file */
2555 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
2559 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2562 if (num > G_MAXINT64) {
2563 GST_WARNING_OBJECT (parse, "CueClusterPosition %" G_GUINT64_FORMAT
2572 /* number of block in the cluster */
2573 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
2577 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2581 GST_WARNING_OBJECT (parse, "Invalid CueBlockNumber 0");
2585 GST_DEBUG_OBJECT (parse, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
2588 /* mild sanity check, disregard strange cases ... */
2589 if (idx.block > G_MAXUINT16) {
2590 GST_DEBUG_OBJECT (parse, "... looks suspicious, ignoring");
2597 ret = gst_matroska_parse_parse_skip (parse, ebml, "CueTrackPositions",
2601 case GST_MATROSKA_ID_CUECODECSTATE:
2602 case GST_MATROSKA_ID_CUEREFERENCE:
2603 ret = gst_ebml_read_skip (ebml);
2608 DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2610 if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
2611 && idx.pos != (guint64) - 1 && idx.track > 0) {
2612 g_array_append_val (parse->index, idx);
2614 } else if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) {
2615 GST_DEBUG_OBJECT (parse, "CueTrackPositions without valid content");
2621 static GstFlowReturn
2622 gst_matroska_parse_parse_index_pointentry (GstMatroskaParse * parse,
2627 GstClockTime time = GST_CLOCK_TIME_NONE;
2630 DEBUG_ELEMENT_START (parse, ebml, "CuePoint");
2632 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2633 DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2637 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2638 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2642 /* one single index entry ('point') */
2643 case GST_MATROSKA_ID_CUETIME:
2645 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
2648 GST_DEBUG_OBJECT (parse, "CueTime: %" G_GUINT64_FORMAT, time);
2649 time = time * parse->time_scale;
2653 /* position in the file + track to which it belongs */
2654 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
2657 gst_matroska_parse_parse_index_cuetrack (parse, ebml,
2658 &nentries)) != GST_FLOW_OK)
2664 ret = gst_matroska_parse_parse_skip (parse, ebml, "CuePoint", id);
2669 DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2672 if (time == GST_CLOCK_TIME_NONE) {
2673 GST_WARNING_OBJECT (parse, "CuePoint without valid time");
2674 g_array_remove_range (parse->index, parse->index->len - nentries,
2679 for (i = parse->index->len - nentries; i < parse->index->len; i++) {
2680 GstMatroskaIndex *idx =
2681 &g_array_index (parse->index, GstMatroskaIndex, i);
2684 GST_DEBUG_OBJECT (parse, "Index entry: pos=%" G_GUINT64_FORMAT
2685 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
2686 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
2690 GST_DEBUG_OBJECT (parse, "Empty CuePoint");
2697 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
2699 if (i1->time < i2->time)
2701 else if (i1->time > i2->time)
2703 else if (i1->block < i2->block)
2705 else if (i1->block > i2->block)
2711 static GstFlowReturn
2712 gst_matroska_parse_parse_index (GstMatroskaParse * parse, GstEbmlRead * ebml)
2715 GstFlowReturn ret = GST_FLOW_OK;
2719 g_array_free (parse->index, TRUE);
2721 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2723 DEBUG_ELEMENT_START (parse, ebml, "Cues");
2725 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2726 DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2730 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2731 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2735 /* one single index entry ('point') */
2736 case GST_MATROSKA_ID_POINTENTRY:
2737 ret = gst_matroska_parse_parse_index_pointentry (parse, ebml);
2741 ret = gst_matroska_parse_parse_skip (parse, ebml, "Cues", id);
2745 DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2747 /* Sort index by time, smallest time first, for easier searching */
2748 g_array_sort (parse->index, (GCompareFunc) gst_matroska_index_compare);
2750 /* Now sort the track specific index entries into their own arrays */
2751 for (i = 0; i < parse->index->len; i++) {
2752 GstMatroskaIndex *idx = &g_array_index (parse->index, GstMatroskaIndex, i);
2754 GstMatroskaTrackContext *ctx;
2756 if (parse->element_index) {
2759 if (idx->track != 0 &&
2761 gst_matroska_parse_stream_from_num (parse, idx->track)) != -1) {
2762 ctx = g_ptr_array_index (parse->src, track_num);
2764 if (ctx->index_writer_id == -1)
2765 gst_index_get_writer_id (parse->element_index, GST_OBJECT (ctx->pad),
2766 &ctx->index_writer_id);
2767 writer_id = ctx->index_writer_id;
2769 if (parse->element_index_writer_id == -1)
2770 gst_index_get_writer_id (parse->element_index, GST_OBJECT (parse),
2771 &parse->element_index_writer_id);
2772 writer_id = parse->element_index_writer_id;
2775 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2776 G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
2777 idx->pos, writer_id);
2778 gst_index_add_association (parse->element_index, writer_id,
2779 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
2780 GST_FORMAT_BYTES, idx->pos + parse->ebml_segment_start, NULL);
2783 if (idx->track == 0)
2786 track_num = gst_matroska_parse_stream_from_num (parse, idx->track);
2787 if (track_num == -1)
2790 ctx = g_ptr_array_index (parse->src, track_num);
2792 if (ctx->index_table == NULL)
2794 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2796 g_array_append_vals (ctx->index_table, idx, 1);
2799 parse->index_parsed = TRUE;
2801 /* sanity check; empty index normalizes to no index */
2802 if (parse->index->len == 0) {
2803 g_array_free (parse->index, TRUE);
2804 parse->index = NULL;
2810 static GstFlowReturn
2811 gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml)
2813 GstFlowReturn ret = GST_FLOW_OK;
2816 DEBUG_ELEMENT_START (parse, ebml, "SegmentInfo");
2818 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2819 DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2823 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2824 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2828 /* cluster timecode */
2829 case GST_MATROSKA_ID_TIMECODESCALE:{
2832 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2836 GST_DEBUG_OBJECT (parse, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
2837 parse->time_scale = num;
2841 case GST_MATROSKA_ID_DURATION:{
2845 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
2849 GST_WARNING_OBJECT (parse, "Invalid duration %lf", num);
2853 GST_DEBUG_OBJECT (parse, "Duration: %lf", num);
2855 dur = gst_gdouble_to_guint64 (num *
2856 gst_guint64_to_gdouble (parse->time_scale));
2857 if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
2858 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME, dur);
2862 case GST_MATROSKA_ID_WRITINGAPP:{
2865 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2868 GST_DEBUG_OBJECT (parse, "WritingApp: %s", GST_STR_NULL (text));
2869 parse->writing_app = text;
2873 case GST_MATROSKA_ID_MUXINGAPP:{
2876 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2879 GST_DEBUG_OBJECT (parse, "MuxingApp: %s", GST_STR_NULL (text));
2880 parse->muxing_app = text;
2884 case GST_MATROSKA_ID_DATEUTC:{
2887 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
2890 GST_DEBUG_OBJECT (parse, "DateUTC: %" G_GINT64_FORMAT, time);
2891 parse->created = time;
2895 case GST_MATROSKA_ID_TITLE:{
2897 GstTagList *taglist;
2899 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2902 GST_DEBUG_OBJECT (parse, "Title: %s", GST_STR_NULL (text));
2903 taglist = gst_tag_list_new ();
2904 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
2906 gst_matroska_parse_found_global_tag (parse, taglist);
2912 ret = gst_matroska_parse_parse_skip (parse, ebml, "SegmentInfo", id);
2916 case GST_MATROSKA_ID_SEGMENTUID:
2917 case GST_MATROSKA_ID_SEGMENTFILENAME:
2918 case GST_MATROSKA_ID_PREVUID:
2919 case GST_MATROSKA_ID_PREVFILENAME:
2920 case GST_MATROSKA_ID_NEXTUID:
2921 case GST_MATROSKA_ID_NEXTFILENAME:
2922 case GST_MATROSKA_ID_SEGMENTFAMILY:
2923 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
2924 ret = gst_ebml_read_skip (ebml);
2929 DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2931 parse->segmentinfo_parsed = TRUE;
2936 static GstFlowReturn
2937 gst_matroska_parse_parse_metadata_id_simple_tag (GstMatroskaParse * parse,
2938 GstEbmlRead * ebml, GstTagList ** p_taglist)
2940 /* FIXME: check if there are more useful mappings */
2943 const gchar *matroska_tagname;
2944 const gchar *gstreamer_tagname;
2948 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2949 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
2950 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2951 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2952 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2953 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2954 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2955 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2956 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2957 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2958 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2959 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2960 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2961 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2962 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2966 gchar *value = NULL;
2969 DEBUG_ELEMENT_START (parse, ebml, "SimpleTag");
2971 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2972 DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
2976 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2977 /* read all sub-entries */
2979 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2983 case GST_MATROSKA_ID_TAGNAME:
2986 ret = gst_ebml_read_ascii (ebml, &id, &tag);
2987 GST_DEBUG_OBJECT (parse, "TagName: %s", GST_STR_NULL (tag));
2990 case GST_MATROSKA_ID_TAGSTRING:
2993 ret = gst_ebml_read_utf8 (ebml, &id, &value);
2994 GST_DEBUG_OBJECT (parse, "TagString: %s", GST_STR_NULL (value));
2998 ret = gst_matroska_parse_parse_skip (parse, ebml, "SimpleTag", id);
3002 case GST_MATROSKA_ID_TAGLANGUAGE:
3003 case GST_MATROSKA_ID_TAGDEFAULT:
3004 case GST_MATROSKA_ID_TAGBINARY:
3005 ret = gst_ebml_read_skip (ebml);
3010 DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
3015 for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
3016 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
3018 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
3020 if (strcmp (tagname_mkv, tag) == 0) {
3021 GValue dest = { 0, };
3022 GType dest_type = gst_tag_get_type (tagname_gst);
3024 /* Ensure that any date string is complete */
3025 if (dest_type == GST_TYPE_DATE) {
3026 guint year = 1901, month = 1, day = 1;
3028 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
3030 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
3032 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
3036 g_value_init (&dest, dest_type);
3037 if (gst_value_deserialize (&dest, value)) {
3038 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
3039 tagname_gst, &dest, NULL);
3041 GST_WARNING_OBJECT (parse, "Can't transform tag '%s' with "
3042 "value '%s' to target type '%s'", tag, value,
3043 g_type_name (dest_type));
3045 g_value_unset (&dest);
3057 static GstFlowReturn
3058 gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse,
3059 GstEbmlRead * ebml, GstTagList ** p_taglist)
3064 DEBUG_ELEMENT_START (parse, ebml, "Tag");
3066 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3067 DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3071 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3072 /* read all sub-entries */
3074 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3078 case GST_MATROSKA_ID_SIMPLETAG:
3079 ret = gst_matroska_parse_parse_metadata_id_simple_tag (parse, ebml,
3084 ret = gst_matroska_parse_parse_skip (parse, ebml, "Tag", id);
3089 DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3094 static GstFlowReturn
3095 gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml)
3097 GstTagList *taglist;
3098 GstFlowReturn ret = GST_FLOW_OK;
3103 curpos = gst_ebml_read_get_pos (ebml);
3105 /* Make sure we don't parse a tags element twice and
3106 * post it's tags twice */
3107 curpos = gst_ebml_read_get_pos (ebml);
3108 for (l = parse->tags_parsed; l; l = l->next) {
3109 guint64 *pos = l->data;
3111 if (*pos == curpos) {
3112 GST_DEBUG_OBJECT (parse, "Skipping already parsed Tags at offset %"
3113 G_GUINT64_FORMAT, curpos);
3118 parse->tags_parsed =
3119 g_list_prepend (parse->tags_parsed, g_slice_new (guint64));
3120 *((guint64 *) parse->tags_parsed->data) = curpos;
3123 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3124 DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3128 taglist = gst_tag_list_new ();
3130 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3131 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3135 case GST_MATROSKA_ID_TAG:
3136 ret = gst_matroska_parse_parse_metadata_id_tag (parse, ebml, &taglist);
3140 ret = gst_matroska_parse_parse_skip (parse, ebml, "Tags", id);
3142 /* FIXME: Use to limit the tags to specific pads */
3143 case GST_MATROSKA_ID_TARGETS:
3144 ret = gst_ebml_read_skip (ebml);
3149 DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3151 gst_matroska_parse_found_global_tag (parse, taglist);
3156 static GstFlowReturn
3157 gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse,
3158 GstEbmlRead * ebml, GstTagList * taglist)
3162 gchar *description = NULL;
3163 gchar *filename = NULL;
3164 gchar *mimetype = NULL;
3165 guint8 *data = NULL;
3166 guint64 datalen = 0;
3168 DEBUG_ELEMENT_START (parse, ebml, "AttachedFile");
3170 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3171 DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3175 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3176 /* read all sub-entries */
3178 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3182 case GST_MATROSKA_ID_FILEDESCRIPTION:
3184 GST_WARNING_OBJECT (parse, "FileDescription can only appear once");
3188 ret = gst_ebml_read_utf8 (ebml, &id, &description);
3189 GST_DEBUG_OBJECT (parse, "FileDescription: %s",
3190 GST_STR_NULL (description));
3192 case GST_MATROSKA_ID_FILENAME:
3194 GST_WARNING_OBJECT (parse, "FileName can only appear once");
3198 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
3200 GST_DEBUG_OBJECT (parse, "FileName: %s", GST_STR_NULL (filename));
3202 case GST_MATROSKA_ID_FILEMIMETYPE:
3204 GST_WARNING_OBJECT (parse, "FileMimeType can only appear once");
3208 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
3209 GST_DEBUG_OBJECT (parse, "FileMimeType: %s", GST_STR_NULL (mimetype));
3211 case GST_MATROSKA_ID_FILEDATA:
3213 GST_WARNING_OBJECT (parse, "FileData can only appear once");
3217 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
3218 GST_DEBUG_OBJECT (parse, "FileData of size %" G_GUINT64_FORMAT,
3223 ret = gst_matroska_parse_parse_skip (parse, ebml, "AttachedFile", id);
3225 case GST_MATROSKA_ID_FILEUID:
3226 ret = gst_ebml_read_skip (ebml);
3231 DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3233 if (filename && mimetype && data && datalen > 0) {
3234 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
3235 GstBuffer *tagbuffer = NULL;
3237 gchar *filename_lc = g_utf8_strdown (filename, -1);
3239 GST_DEBUG_OBJECT (parse, "Creating tag for attachment with filename '%s', "
3240 "mimetype '%s', description '%s', size %" G_GUINT64_FORMAT, filename,
3241 mimetype, GST_STR_NULL (description), datalen);
3243 /* TODO: better heuristics for different image types */
3244 if (strstr (filename_lc, "cover")) {
3245 if (strstr (filename_lc, "back"))
3246 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
3248 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
3249 } else if (g_str_has_prefix (mimetype, "image/") ||
3250 g_str_has_suffix (filename_lc, "png") ||
3251 g_str_has_suffix (filename_lc, "jpg") ||
3252 g_str_has_suffix (filename_lc, "jpeg") ||
3253 g_str_has_suffix (filename_lc, "gif") ||
3254 g_str_has_suffix (filename_lc, "bmp")) {
3255 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
3257 g_free (filename_lc);
3259 /* First try to create an image tag buffer from this */
3260 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
3262 gst_tag_image_data_to_image_buffer (data, datalen, image_type);
3265 image_type = GST_TAG_IMAGE_TYPE_NONE;
3268 /* if this failed create an attachment buffer */
3270 tagbuffer = gst_buffer_new_and_alloc (datalen);
3272 memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen);
3273 GST_BUFFER_SIZE (tagbuffer) = datalen;
3275 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
3277 caps = gst_caps_new_simple (mimetype, NULL);
3278 gst_buffer_set_caps (tagbuffer, caps);
3279 gst_caps_unref (caps);
3282 /* Set filename and description on the caps */
3283 caps = GST_BUFFER_CAPS (tagbuffer);
3284 gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL);
3286 gst_caps_set_simple (caps, "description", G_TYPE_STRING, description,
3289 GST_DEBUG_OBJECT (parse,
3290 "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps);
3292 /* and append to the tag list */
3293 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
3294 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer,
3297 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
3304 g_free (description);
3309 static GstFlowReturn
3310 gst_matroska_parse_parse_attachments (GstMatroskaParse * parse,
3314 GstFlowReturn ret = GST_FLOW_OK;
3315 GstTagList *taglist;
3317 DEBUG_ELEMENT_START (parse, ebml, "Attachments");
3319 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3320 DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3324 taglist = gst_tag_list_new ();
3326 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3327 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3331 case GST_MATROSKA_ID_ATTACHEDFILE:
3332 ret = gst_matroska_parse_parse_attached_file (parse, ebml, taglist);
3336 ret = gst_matroska_parse_parse_skip (parse, ebml, "Attachments", id);
3340 DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3342 if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) {
3343 GST_DEBUG_OBJECT (parse, "Storing attachment tags");
3344 gst_matroska_parse_found_global_tag (parse, taglist);
3346 GST_DEBUG_OBJECT (parse, "No valid attachments found");
3347 gst_tag_list_free (taglist);
3350 parse->attachments_parsed = TRUE;
3355 static GstFlowReturn
3356 gst_matroska_parse_parse_chapters (GstMatroskaParse * parse, GstEbmlRead * ebml)
3359 GstFlowReturn ret = GST_FLOW_OK;
3361 GST_WARNING_OBJECT (parse, "Parsing of chapters not implemented yet");
3363 /* TODO: implement parsing of chapters */
3365 DEBUG_ELEMENT_START (parse, ebml, "Chapters");
3367 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3368 DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3372 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3373 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3378 ret = gst_ebml_read_skip (ebml);
3383 DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3388 * Read signed/unsigned "EBML" numbers.
3389 * Return: number of bytes processed.
3393 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
3395 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
3403 while (read <= 8 && !(total & len_mask)) {
3410 if ((total &= (len_mask - 1)) == len_mask - 1)
3415 if (data[n] == 0xff)
3417 total = (total << 8) | data[n];
3421 if (read == num_ffs && total != 0)
3430 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
3435 /* read as unsigned number first */
3436 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
3440 if (unum == G_MAXUINT64)
3443 *num = unum - ((1 << ((7 * res) - 1)) - 1);
3448 static GstFlowReturn
3449 gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
3450 GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
3451 gboolean is_simpleblock)
3453 GstMatroskaTrackContext *stream = NULL;
3454 GstFlowReturn ret = GST_FLOW_OK;
3455 gboolean readblock = FALSE;
3457 guint64 block_duration = 0;
3458 GstBuffer *buf = NULL;
3459 gint stream_num = -1, n, laces = 0;
3461 gint *lace_size = NULL;
3464 gint64 referenceblock = 0;
3467 offset = gst_ebml_read_get_offset (ebml);
3469 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3470 if (!is_simpleblock) {
3471 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
3475 id = GST_MATROSKA_ID_SIMPLEBLOCK;
3479 /* one block inside the group. Note, block parsing is one
3480 * of the harder things, so this code is a bit complicated.
3481 * See http://www.matroska.org/ for documentation. */
3482 case GST_MATROSKA_ID_SIMPLEBLOCK:
3483 case GST_MATROSKA_ID_BLOCK:
3489 gst_buffer_unref (buf);
3492 if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
3495 data = GST_BUFFER_DATA (buf);
3496 size = GST_BUFFER_SIZE (buf);
3498 /* first byte(s): blocknum */
3499 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3504 /* fetch stream from num */
3505 stream_num = gst_matroska_parse_stream_from_num (parse, num);
3506 if (G_UNLIKELY (size < 3)) {
3507 GST_WARNING_OBJECT (parse, "Invalid size %u", size);
3508 /* non-fatal, try next block(group) */
3511 } else if (G_UNLIKELY (stream_num < 0 ||
3512 stream_num >= parse->num_streams)) {
3513 /* let's not give up on a stray invalid track number */
3514 GST_WARNING_OBJECT (parse,
3515 "Invalid stream %d for track number %" G_GUINT64_FORMAT
3516 "; ignoring block", stream_num, num);
3520 stream = g_ptr_array_index (parse->src, stream_num);
3522 /* time (relative to cluster time) */
3523 time = ((gint16) GST_READ_UINT16_BE (data));
3526 flags = GST_READ_UINT8 (data);
3530 GST_LOG_OBJECT (parse, "time %" G_GUINT64_FORMAT ", flags %d", time,
3533 switch ((flags & 0x06) >> 1) {
3534 case 0x0: /* no lacing */
3536 lace_size = g_new (gint, 1);
3537 lace_size[0] = size;
3540 case 0x1: /* xiph lacing */
3541 case 0x2: /* fixed-size lacing */
3542 case 0x3: /* EBML lacing */
3544 goto invalid_lacing;
3545 laces = GST_READ_UINT8 (data) + 1;
3548 lace_size = g_new0 (gint, laces);
3550 switch ((flags & 0x06) >> 1) {
3551 case 0x1: /* xiph lacing */ {
3552 guint temp, total = 0;
3554 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
3557 goto invalid_lacing;
3558 temp = GST_READ_UINT8 (data);
3559 lace_size[n] += temp;
3565 total += lace_size[n];
3567 lace_size[n] = size - total;
3571 case 0x2: /* fixed-size lacing */
3572 for (n = 0; n < laces; n++)
3573 lace_size[n] = size / laces;
3576 case 0x3: /* EBML lacing */ {
3579 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3583 total = lace_size[0] = num;
3584 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
3588 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
3592 lace_size[n] = lace_size[n - 1] + snum;
3593 total += lace_size[n];
3596 lace_size[n] = size - total;
3603 if (ret != GST_FLOW_OK)
3610 case GST_MATROSKA_ID_BLOCKDURATION:{
3611 ret = gst_ebml_read_uint (ebml, &id, &block_duration);
3612 GST_DEBUG_OBJECT (parse, "BlockDuration: %" G_GUINT64_FORMAT,
3617 case GST_MATROSKA_ID_REFERENCEBLOCK:{
3618 ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
3619 GST_DEBUG_OBJECT (parse, "ReferenceBlock: %" G_GINT64_FORMAT,
3624 case GST_MATROSKA_ID_CODECSTATE:{
3626 guint64 data_len = 0;
3629 gst_ebml_read_binary (ebml, &id, &data,
3630 &data_len)) != GST_FLOW_OK)
3633 if (G_UNLIKELY (stream == NULL)) {
3634 GST_WARNING_OBJECT (parse,
3635 "Unexpected CodecState subelement - ignoring");
3639 g_free (stream->codec_state);
3640 stream->codec_state = data;
3641 stream->codec_state_size = data_len;
3647 ret = gst_matroska_parse_parse_skip (parse, ebml, "BlockGroup", id);
3650 case GST_MATROSKA_ID_BLOCKVIRTUAL:
3651 case GST_MATROSKA_ID_BLOCKADDITIONS:
3652 case GST_MATROSKA_ID_REFERENCEPRIORITY:
3653 case GST_MATROSKA_ID_REFERENCEVIRTUAL:
3654 case GST_MATROSKA_ID_SLICES:
3655 GST_DEBUG_OBJECT (parse,
3656 "Skipping BlockGroup subelement 0x%x - ignoring", id);
3657 ret = gst_ebml_read_skip (ebml);
3665 /* reading a number or so could have failed */
3666 if (ret != GST_FLOW_OK)
3669 if (ret == GST_FLOW_OK && readblock) {
3670 guint64 duration = 0;
3671 gint64 lace_time = 0;
3672 gboolean delta_unit;
3674 stream = g_ptr_array_index (parse->src, stream_num);
3676 if (cluster_time != GST_CLOCK_TIME_NONE) {
3677 /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
3678 * Drop unless the lace contains timestamp 0? */
3679 if (time < 0 && (-time) > cluster_time) {
3682 if (stream->timecodescale == 1.0)
3683 lace_time = (cluster_time + time) * parse->time_scale;
3686 gst_util_guint64_to_gdouble ((cluster_time + time) *
3687 parse->time_scale) * stream->timecodescale;
3690 lace_time = GST_CLOCK_TIME_NONE;
3693 if (lace_time != GST_CLOCK_TIME_NONE) {
3694 parse->last_timestamp = lace_time;
3696 /* need to refresh segment info ASAP */
3697 if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
3698 GST_DEBUG_OBJECT (parse,
3699 "generating segment starting at %" GST_TIME_FORMAT,
3700 GST_TIME_ARGS (lace_time));
3701 /* pretend we seeked here */
3702 gst_segment_set_seek (&parse->segment, parse->segment.rate,
3703 GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
3704 GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
3705 /* now convey our segment notion downstream */
3706 gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE,
3707 parse->segment.rate, parse->segment.format, parse->segment.start,
3708 parse->segment.stop, parse->segment.start));
3709 parse->need_newsegment = FALSE;
3712 if (block_duration) {
3713 if (stream->timecodescale == 1.0)
3714 duration = gst_util_uint64_scale (block_duration, parse->time_scale, 1);
3717 gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
3718 (gst_util_uint64_scale (block_duration, parse->time_scale,
3719 1)) * stream->timecodescale);
3720 } else if (stream->default_duration) {
3721 duration = stream->default_duration * laces;
3723 /* else duration is diff between timecode of this and next block */
3725 /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
3726 a ReferenceBlock implies that this is not a keyframe. In either
3727 case, it only makes sense for video streams. */
3728 delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3729 ((is_simpleblock && !(flags & 0x80)) || referenceblock);
3731 if (delta_unit && stream->set_discont) {
3732 /* When doing seeks or such, we need to restart on key frames or
3733 * decoders might choke. */
3734 GST_DEBUG_OBJECT (parse, "skipping delta unit");
3738 for (n = 0; n < laces; n++) {
3739 if (G_UNLIKELY (lace_size[n] > size)) {
3740 GST_WARNING_OBJECT (parse, "Invalid lace size");
3744 /* QoS for video track with an index. the assumption is that
3745 index entries point to keyframes, but if that is not true we
3746 will instad skip until the next keyframe. */
3747 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3748 stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3749 stream->index_table && parse->segment.rate > 0.0) {
3750 GstMatroskaTrackVideoContext *videocontext =
3751 (GstMatroskaTrackVideoContext *) stream;
3752 GstClockTime earliest_time;
3753 GstClockTime earliest_stream_time;
3755 GST_OBJECT_LOCK (parse);
3756 earliest_time = videocontext->earliest_time;
3757 GST_OBJECT_UNLOCK (parse);
3758 earliest_stream_time = gst_segment_to_position (&parse->segment,
3759 GST_FORMAT_TIME, earliest_time);
3761 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3762 GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
3763 lace_time <= earliest_stream_time) {
3764 /* find index entry (keyframe) <= earliest_stream_time */
3765 GstMatroskaIndex *entry =
3766 gst_util_array_binary_search (stream->index_table->data,
3767 stream->index_table->len, sizeof (GstMatroskaIndex),
3768 (GCompareDataFunc) gst_matroska_index_seek_find,
3769 GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
3771 /* if that entry (keyframe) is after the current the current
3772 buffer, we can skip pushing (and thus decoding) all
3773 buffers until that keyframe. */
3774 if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
3775 entry->time > lace_time) {
3776 GST_LOG_OBJECT (parse, "Skipping lace before late keyframe");
3777 stream->set_discont = TRUE;
3783 sub = gst_buffer_create_sub (buf,
3784 GST_BUFFER_SIZE (buf) - size, lace_size[n]);
3785 GST_DEBUG_OBJECT (parse, "created subbuffer %p", sub);
3788 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3790 GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3792 if (stream->encodings != NULL && stream->encodings->len > 0)
3793 sub = gst_matroska_decode_buffer (stream, sub);
3796 GST_WARNING_OBJECT (parse, "Decoding buffer failed");
3800 GST_BUFFER_TIMESTAMP (sub) = lace_time;
3802 if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
3803 GstClockTime last_stop_end;
3805 /* Check if this stream is after segment stop */
3806 if (GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
3807 lace_time >= parse->segment.stop) {
3808 GST_DEBUG_OBJECT (parse,
3809 "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
3810 GST_TIME_ARGS (parse->segment.stop));
3811 gst_buffer_unref (sub);
3814 if (offset >= stream->to_offset) {
3815 GST_DEBUG_OBJECT (parse, "Stream %d after playback section",
3817 gst_buffer_unref (sub);
3821 /* handle gaps, e.g. non-zero start-time, or an cue index entry
3822 * that landed us with timestamps not quite intended */
3823 if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
3824 parse->segment.rate > 0.0) {
3825 GstClockTimeDiff diff;
3827 /* only send newsegments with increasing start times,
3828 * otherwise if these go back and forth downstream (sinks) increase
3829 * accumulated time and running_time */
3830 diff = GST_CLOCK_DIFF (parse->segment.last_stop, lace_time);
3831 if (diff > 2 * GST_SECOND && lace_time > parse->segment.start &&
3832 (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
3833 lace_time < parse->segment.stop)) {
3834 GST_DEBUG_OBJECT (parse,
3835 "Gap of %" G_GINT64_FORMAT " ns detected in"
3836 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
3837 "Sending updated NEWSEGMENT events", diff,
3838 stream->index, GST_TIME_ARGS (stream->pos),
3839 GST_TIME_ARGS (lace_time));
3840 /* send newsegment events such that the gap is not accounted in
3841 * accum time, hence running_time */
3842 /* close ahead of gap */
3843 gst_matroska_parse_send_event (parse,
3844 gst_event_new_new_segment (TRUE, parse->segment.rate,
3845 parse->segment.format, parse->segment.last_stop,
3846 parse->segment.last_stop, parse->segment.last_stop));
3848 gst_matroska_parse_send_event (parse,
3849 gst_event_new_new_segment (FALSE, parse->segment.rate,
3850 parse->segment.format, lace_time, parse->segment.stop,
3852 /* align segment view with downstream,
3853 * prevents double-counting accum when closing segment */
3854 gst_segment_set_newsegment (&parse->segment, FALSE,
3855 parse->segment.rate, parse->segment.format, lace_time,
3856 parse->segment.stop, lace_time);
3857 parse->segment.last_stop = lace_time;
3861 if (!GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)
3862 || parse->segment.last_stop < lace_time) {
3863 parse->segment.last_stop = lace_time;
3866 last_stop_end = lace_time;
3868 GST_BUFFER_DURATION (sub) = duration / laces;
3869 last_stop_end += GST_BUFFER_DURATION (sub);
3872 if (!GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) ||
3873 parse->last_stop_end < last_stop_end)
3874 parse->last_stop_end = last_stop_end;
3876 if (parse->segment.duration == -1 ||
3877 parse->segment.duration < lace_time) {
3878 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME,
3880 gst_element_post_message (GST_ELEMENT_CAST (parse),
3881 gst_message_new_duration (GST_OBJECT_CAST (parse),
3882 GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
3886 stream->pos = lace_time;
3888 gst_matroska_parse_sync_streams (parse);
3890 if (stream->set_discont) {
3891 GST_DEBUG_OBJECT (parse, "marking DISCONT");
3892 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
3893 stream->set_discont = FALSE;
3896 /* reverse playback book-keeping */
3897 if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
3898 stream->from_time = lace_time;
3899 if (stream->from_offset == -1)
3900 stream->from_offset = offset;
3902 GST_DEBUG_OBJECT (parse,
3903 "Pushing lace %d, data of size %d for stream %d, time=%"
3904 GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
3905 GST_BUFFER_SIZE (sub), stream_num,
3906 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
3907 GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
3909 if (parse->element_index) {
3910 if (stream->index_writer_id == -1)
3911 gst_index_get_writer_id (parse->element_index,
3912 GST_OBJECT (stream->pad), &stream->index_writer_id);
3914 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
3915 G_GUINT64_FORMAT " for writer id %d",
3916 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
3917 stream->index_writer_id);
3918 gst_index_add_association (parse->element_index,
3919 stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
3920 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
3921 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
3922 cluster_offset, NULL);
3925 gst_buffer_set_caps (sub, GST_PAD_CAPS (parse->srcpad));
3927 /* Postprocess the buffers depending on the codec used */
3928 if (stream->postprocess_frame) {
3929 GST_LOG_OBJECT (parse, "running post process");
3930 ret = stream->postprocess_frame (GST_ELEMENT (parse), stream, &sub);
3933 ret = gst_pad_push (stream->pad, sub);
3934 if (parse->segment.rate < 0) {
3935 if (lace_time > parse->segment.stop && ret == GST_FLOW_UNEXPECTED) {
3936 /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
3937 * we are at the end of the segment, so we just need to jump
3938 * back to the previous section. */
3939 GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
3944 ret = gst_matroska_parse_combine_flows (parse, stream, ret);
3948 size -= lace_size[n];
3949 if (lace_time != GST_CLOCK_TIME_NONE && duration)
3950 lace_time += duration / laces;
3952 lace_time = GST_CLOCK_TIME_NONE;
3958 gst_buffer_unref (buf);
3966 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
3967 /* non-fatal, try next block(group) */
3973 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Data error"));
3974 /* non-fatal, try next block(group) */
3980 /* return FALSE if block(group) should be skipped (due to a seek) */
3981 static inline gboolean
3982 gst_matroska_parse_seek_block (GstMatroskaParse * parse)
3984 if (G_UNLIKELY (parse->seek_block)) {
3985 if (!(--parse->seek_block)) {
3988 GST_LOG_OBJECT (parse, "should skip block due to seek");
3996 static GstFlowReturn
3997 gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
4001 guint64 seek_pos = (guint64) - 1;
4002 guint32 seek_id = 0;
4005 DEBUG_ELEMENT_START (parse, ebml, "Seek");
4007 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4008 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4012 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4013 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4017 case GST_MATROSKA_ID_SEEKID:
4021 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4024 GST_DEBUG_OBJECT (parse, "SeekID: %" G_GUINT64_FORMAT, t);
4029 case GST_MATROSKA_ID_SEEKPOSITION:
4033 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4036 if (t > G_MAXINT64) {
4037 GST_WARNING_OBJECT (parse,
4038 "Too large SeekPosition %" G_GUINT64_FORMAT, t);
4042 GST_DEBUG_OBJECT (parse, "SeekPosition: %" G_GUINT64_FORMAT, t);
4048 ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4053 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
4056 if (!seek_id || seek_pos == (guint64) - 1) {
4057 GST_WARNING_OBJECT (parse, "Incomplete seekhead entry (0x%x/%"
4058 G_GUINT64_FORMAT ")", seek_id, seek_pos);
4063 case GST_MATROSKA_ID_SEEKHEAD:
4066 case GST_MATROSKA_ID_CUES:
4067 case GST_MATROSKA_ID_TAGS:
4068 case GST_MATROSKA_ID_TRACKS:
4069 case GST_MATROSKA_ID_SEGMENTINFO:
4070 case GST_MATROSKA_ID_ATTACHMENTS:
4071 case GST_MATROSKA_ID_CHAPTERS:
4073 guint64 before_pos, length;
4076 length = gst_matroska_parse_get_length (parse);
4077 before_pos = parse->offset;
4079 if (length == (guint64) - 1) {
4080 GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
4084 /* check for validity */
4085 if (seek_pos + parse->ebml_segment_start + 12 >= length) {
4086 GST_WARNING_OBJECT (parse,
4087 "SeekHead reference lies outside file!" " (%"
4088 G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
4089 G_GUINT64_FORMAT ")", seek_pos, parse->ebml_segment_start, length);
4093 /* only pick up index location when streaming */
4094 if (seek_id == GST_MATROSKA_ID_CUES) {
4095 parse->index_offset = seek_pos + parse->ebml_segment_start;
4096 GST_DEBUG_OBJECT (parse, "Cues located at offset %" G_GUINT64_FORMAT,
4097 parse->index_offset);
4103 GST_DEBUG_OBJECT (parse, "Ignoring Seek entry for ID=0x%x", seek_id);
4106 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4111 static GstFlowReturn
4112 gst_matroska_parse_parse_contents (GstMatroskaParse * parse, GstEbmlRead * ebml)
4114 GstFlowReturn ret = GST_FLOW_OK;
4117 DEBUG_ELEMENT_START (parse, ebml, "SeekHead");
4119 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4120 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4124 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4125 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4129 case GST_MATROSKA_ID_SEEKENTRY:
4131 ret = gst_matroska_parse_parse_contents_seekentry (parse, ebml);
4132 /* Ignore EOS and errors here */
4133 if (ret != GST_FLOW_OK) {
4134 GST_DEBUG_OBJECT (parse, "Ignoring %s", gst_flow_get_name (ret));
4141 ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4146 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4151 #define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
4153 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
4155 static inline GstFlowReturn
4156 gst_matroska_parse_check_read_size (GstMatroskaParse * parse, guint64 bytes)
4158 if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
4159 /* only a few blocks are expected/allowed to be large,
4160 * and will be recursed into, whereas others will be read and must fit */
4161 /* fatal in streaming case, as we can't step over easily */
4162 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4163 ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
4164 "file might be corrupt.", bytes));
4165 return GST_FLOW_ERROR;
4171 /* returns TRUE if we truely are in error state, and should give up */
4172 static inline gboolean
4173 gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
4177 /* sigh, one last attempt above and beyond call of duty ...;
4178 * search for cluster mark following current pos */
4179 pos = parse->offset;
4180 GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
4181 if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
4182 /* did not work, give up */
4185 GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
4186 /* try that position */
4187 parse->offset = pos;
4192 /* initializes @ebml with @bytes from input stream at current offset.
4193 * Returns UNEXPECTED if insufficient available,
4194 * ERROR if too much was attempted to read. */
4195 static inline GstFlowReturn
4196 gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
4199 GstBuffer *buffer = NULL;
4200 GstFlowReturn ret = GST_FLOW_OK;
4202 GST_LOG_OBJECT (parse, "taking %" G_GUINT64_FORMAT " bytes for parsing",
4204 ret = gst_matroska_parse_check_read_size (parse, bytes);
4205 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
4206 /* otherwise fatal */
4207 ret = GST_FLOW_ERROR;
4210 if (gst_adapter_available (parse->adapter) >= bytes)
4211 buffer = gst_adapter_take_buffer (parse->adapter, bytes);
4213 ret = GST_FLOW_UNEXPECTED;
4214 if (G_LIKELY (buffer)) {
4215 gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, parse->offset);
4216 parse->offset += bytes;
4223 gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
4226 gboolean seekable = FALSE;
4227 gint64 start = -1, stop = -1;
4229 query = gst_query_new_seeking (GST_FORMAT_BYTES);
4230 if (!gst_pad_peer_query (parse->sinkpad, query)) {
4231 GST_DEBUG_OBJECT (parse, "seeking query failed");
4235 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
4237 /* try harder to query upstream size if we didn't get it the first time */
4238 if (seekable && stop == -1) {
4239 GstFormat fmt = GST_FORMAT_BYTES;
4241 GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
4242 gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
4245 /* if upstream doesn't know the size, it's likely that it's not seekable in
4246 * practice even if it technically may be seekable */
4247 if (seekable && (start != 0 || stop <= start)) {
4248 GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
4253 GST_INFO_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
4254 G_GUINT64_FORMAT ")", seekable, start, stop);
4255 parse->seekable = seekable;
4257 gst_query_unref (query);
4261 static GstFlowReturn
4262 gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
4268 GstFlowReturn ret = GST_FLOW_OK;
4270 GST_WARNING_OBJECT (parse,
4271 "Found Cluster element before Tracks, searching Tracks");
4274 before_pos = parse->offset;
4276 /* Search Tracks element */
4278 ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4279 if (ret != GST_FLOW_OK)
4282 if (id != GST_MATROSKA_ID_TRACKS) {
4283 /* we may be skipping large cluster here, so forego size check etc */
4284 /* ... but we can't skip undefined size; force error */
4285 if (length == G_MAXUINT64) {
4286 ret = gst_matroska_parse_check_read_size (parse, length);
4289 parse->offset += needed;
4290 parse->offset += length;
4295 /* will lead to track parsing ... */
4296 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4301 parse->offset = before_pos;
4307 #define GST_READ_CHECK(stmt) \
4309 if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
4310 if (ret == GST_FLOW_OVERFLOW) { \
4311 ret = GST_FLOW_OK; \
4318 gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
4321 if (parse->streamheader) {
4324 buf = gst_buffer_span (parse->streamheader, 0, buffer,
4325 GST_BUFFER_SIZE (parse->streamheader) + GST_BUFFER_SIZE (buffer));
4326 gst_buffer_unref (parse->streamheader);
4327 parse->streamheader = buf;
4329 parse->streamheader = gst_buffer_ref (buffer);
4332 GST_DEBUG ("%d", GST_BUFFER_SIZE (parse->streamheader));
4335 static GstFlowReturn
4336 gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
4339 GstFlowReturn ret = GST_FLOW_OK;
4341 if (!parse->pushed_headers) {
4344 GValue streamheader = { 0 };
4345 GValue bufval = { 0 };
4348 caps = gst_caps_new_simple ("video/x-matroska", NULL);
4349 s = gst_caps_get_structure (caps, 0);
4350 g_value_init (&streamheader, GST_TYPE_ARRAY);
4351 g_value_init (&bufval, GST_TYPE_BUFFER);
4352 GST_BUFFER_FLAG_SET (parse->streamheader, GST_BUFFER_FLAG_IN_CAPS);
4353 gst_value_set_buffer (&bufval, parse->streamheader);
4354 gst_value_array_append_value (&streamheader, &bufval);
4355 g_value_unset (&bufval);
4356 gst_structure_set_value (s, "streamheader", &streamheader);
4357 g_value_unset (&streamheader);
4358 //gst_caps_replace (parse->caps, caps);
4359 gst_pad_set_caps (parse->srcpad, caps);
4361 buf = gst_buffer_make_metadata_writable (parse->streamheader);
4362 gst_buffer_set_caps (buf, caps);
4363 gst_caps_unref (caps);
4365 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4366 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
4367 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4369 ret = gst_pad_push (parse->srcpad, buf);
4371 parse->pushed_headers = TRUE;
4375 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4377 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4379 if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
4380 parse->last_timestamp = GST_BUFFER_TIMESTAMP (buffer);
4382 GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
4384 gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
4385 ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
4390 static GstFlowReturn
4391 gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
4392 guint64 length, guint needed)
4394 GstEbmlRead ebml = { 0, };
4395 GstFlowReturn ret = GST_FLOW_OK;
4397 //GstBuffer *buffer;
4399 GST_DEBUG_OBJECT (parse, "Parsing Element id 0x%x, "
4400 "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
4403 if (gst_adapter_available (parse->adapter) >= length + needed) {
4404 buffer = gst_adapter_take_buffer (parse->adapter, length + needed);
4405 gst_pad_push (parse->srcpad, buffer);
4407 ret = GST_FLOW_UNEXPECTED;
4409 //GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4416 /* if we plan to read and parse this element, we need prefix (id + length)
4417 * and the contents */
4418 /* mind about overflow wrap-around when dealing with undefined size */
4420 if (G_LIKELY (length != G_MAXUINT64))
4423 switch (parse->state) {
4424 case GST_MATROSKA_PARSE_STATE_START:
4426 case GST_EBML_ID_HEADER:
4427 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4428 ret = gst_matroska_parse_parse_header (parse, &ebml);
4429 if (ret != GST_FLOW_OK)
4431 parse->state = GST_MATROSKA_PARSE_STATE_SEGMENT;
4432 gst_matroska_parse_check_seekability (parse);
4433 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4436 goto invalid_header;
4440 case GST_MATROSKA_PARSE_STATE_SEGMENT:
4442 case GST_MATROSKA_ID_SEGMENT:
4443 /* eat segment prefix */
4444 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4445 GST_DEBUG_OBJECT (parse,
4446 "Found Segment start at offset %" G_GUINT64_FORMAT,
4448 /* seeks are from the beginning of the segment,
4449 * after the segment ID/length */
4450 parse->ebml_segment_start = parse->offset;
4451 parse->state = GST_MATROSKA_PARSE_STATE_HEADER;
4452 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4455 GST_WARNING_OBJECT (parse,
4456 "Expected a Segment ID (0x%x), but received 0x%x!",
4457 GST_MATROSKA_ID_SEGMENT, id);
4458 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4459 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4463 case GST_MATROSKA_PARSE_STATE_SCANNING:
4464 if (id != GST_MATROSKA_ID_CLUSTER &&
4465 id != GST_MATROSKA_ID_CLUSTERTIMECODE)
4468 case GST_MATROSKA_PARSE_STATE_HEADER:
4469 case GST_MATROSKA_PARSE_STATE_DATA:
4470 case GST_MATROSKA_PARSE_STATE_SEEK:
4472 case GST_MATROSKA_ID_SEGMENTINFO:
4473 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4474 if (!parse->segmentinfo_parsed) {
4475 ret = gst_matroska_parse_parse_info (parse, &ebml);
4477 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4479 case GST_MATROSKA_ID_TRACKS:
4480 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4481 if (!parse->tracks_parsed) {
4482 ret = gst_matroska_parse_parse_tracks (parse, &ebml);
4484 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4486 case GST_MATROSKA_ID_CLUSTER:
4487 if (G_UNLIKELY (!parse->tracks_parsed)) {
4488 GST_DEBUG_OBJECT (parse, "Cluster before Track");
4489 goto not_streamable;
4491 if (G_UNLIKELY (parse->state == GST_MATROSKA_PARSE_STATE_HEADER)) {
4492 parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4493 parse->first_cluster_offset = parse->offset;
4494 GST_DEBUG_OBJECT (parse, "signaling no more pads");
4496 parse->cluster_time = GST_CLOCK_TIME_NONE;
4497 parse->cluster_offset = parse->offset;
4498 if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
4499 GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
4500 " not found in Cluster, trying next Cluster's first block instead",
4502 parse->seek_block = 0;
4504 parse->seek_first = FALSE;
4505 /* record next cluster for recovery */
4506 if (read != G_MAXUINT64)
4507 parse->next_cluster_offset = parse->cluster_offset + read;
4508 /* eat cluster prefix */
4509 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4510 ret = gst_matroska_parse_output (parse, ebml.buf, TRUE);
4511 //gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4513 case GST_MATROSKA_ID_CLUSTERTIMECODE:
4517 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4518 if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
4520 GST_DEBUG_OBJECT (parse, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
4521 parse->cluster_time = num;
4522 if (parse->element_index) {
4523 if (parse->element_index_writer_id == -1)
4524 gst_index_get_writer_id (parse->element_index,
4525 GST_OBJECT (parse), &parse->element_index_writer_id);
4526 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
4527 G_GUINT64_FORMAT " for writer id %d",
4528 GST_TIME_ARGS (parse->cluster_time), parse->cluster_offset,
4529 parse->element_index_writer_id);
4530 gst_index_add_association (parse->element_index,
4531 parse->element_index_writer_id, GST_ASSOCIATION_FLAG_KEY_UNIT,
4532 GST_FORMAT_TIME, parse->cluster_time,
4533 GST_FORMAT_BYTES, parse->cluster_offset, NULL);
4535 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4538 case GST_MATROSKA_ID_BLOCKGROUP:
4539 if (!gst_matroska_parse_seek_block (parse))
4541 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4542 DEBUG_ELEMENT_START (parse, &ebml, "BlockGroup");
4543 if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
4544 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4545 &ebml, parse->cluster_time, parse->cluster_offset, FALSE);
4547 DEBUG_ELEMENT_STOP (parse, &ebml, "BlockGroup", ret);
4548 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4550 case GST_MATROSKA_ID_SIMPLEBLOCK:
4551 if (!gst_matroska_parse_seek_block (parse))
4553 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4554 DEBUG_ELEMENT_START (parse, &ebml, "SimpleBlock");
4555 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4556 &ebml, parse->cluster_time, parse->cluster_offset, TRUE);
4557 DEBUG_ELEMENT_STOP (parse, &ebml, "SimpleBlock", ret);
4558 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4560 case GST_MATROSKA_ID_ATTACHMENTS:
4561 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4562 if (!parse->attachments_parsed) {
4563 ret = gst_matroska_parse_parse_attachments (parse, &ebml);
4565 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4567 case GST_MATROSKA_ID_TAGS:
4568 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4569 ret = gst_matroska_parse_parse_metadata (parse, &ebml);
4570 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4572 case GST_MATROSKA_ID_CHAPTERS:
4573 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4574 ret = gst_matroska_parse_parse_chapters (parse, &ebml);
4575 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4577 case GST_MATROSKA_ID_SEEKHEAD:
4578 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4579 ret = gst_matroska_parse_parse_contents (parse, &ebml);
4580 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4582 case GST_MATROSKA_ID_CUES:
4583 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4584 if (!parse->index_parsed) {
4585 ret = gst_matroska_parse_parse_index (parse, &ebml);
4586 /* only push based; delayed index building */
4587 if (ret == GST_FLOW_OK
4588 && parse->state == GST_MATROSKA_PARSE_STATE_SEEK) {
4591 GST_OBJECT_LOCK (parse);
4592 event = parse->seek_event;
4593 parse->seek_event = NULL;
4594 GST_OBJECT_UNLOCK (parse);
4597 /* unlikely to fail, since we managed to seek to this point */
4598 if (!gst_matroska_parse_handle_seek_event (parse, NULL, event))
4600 /* resume data handling, main thread clear to seek again */
4601 GST_OBJECT_LOCK (parse);
4602 parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4603 GST_OBJECT_UNLOCK (parse);
4606 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4608 case GST_MATROSKA_ID_POSITION:
4609 case GST_MATROSKA_ID_PREVSIZE:
4610 case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
4611 case GST_MATROSKA_ID_SILENTTRACKS:
4612 GST_DEBUG_OBJECT (parse,
4613 "Skipping Cluster subelement 0x%x - ignoring", id);
4617 GST_DEBUG_OBJECT (parse, "skipping Element 0x%x", id);
4618 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4619 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4625 if (ret == GST_FLOW_PARSE)
4629 gst_ebml_read_clear (&ebml);
4635 /* simply exit, maybe not enough data yet */
4636 /* no ebml to clear if read error */
4641 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4642 ("Failed to parse Element 0x%x", id));
4643 ret = GST_FLOW_ERROR;
4648 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4649 ("File layout does not permit streaming"));
4650 ret = GST_FLOW_ERROR;
4656 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4657 ("No Tracks element found"));
4658 ret = GST_FLOW_ERROR;
4664 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Invalid header"));
4665 ret = GST_FLOW_ERROR;
4670 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Failed to seek"));
4671 ret = GST_FLOW_ERROR;
4678 gst_matroska_parse_loop (GstPad * pad)
4680 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4686 /* If we have to close a segment, send a new segment to do this now */
4687 if (G_LIKELY (parse->state == GST_MATROSKA_PARSE_STATE_DATA)) {
4688 if (G_UNLIKELY (parse->close_segment)) {
4689 gst_matroska_parse_send_event (parse, parse->close_segment);
4690 parse->close_segment = NULL;
4692 if (G_UNLIKELY (parse->new_segment)) {
4693 gst_matroska_parse_send_event (parse, parse->new_segment);
4694 parse->new_segment = NULL;
4698 ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4699 if (ret == GST_FLOW_UNEXPECTED)
4701 if (ret != GST_FLOW_OK) {
4702 if (gst_matroska_parse_check_parse_error (parse))
4708 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4709 "size %" G_GUINT64_FORMAT ", needed %d", parse->offset, id,
4712 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4713 if (ret == GST_FLOW_UNEXPECTED)
4715 if (ret != GST_FLOW_OK)
4718 /* check if we're at the end of a configured segment */
4719 if (G_LIKELY (parse->src->len)) {
4722 g_assert (parse->num_streams == parse->src->len);
4723 for (i = 0; i < parse->src->len; i++) {
4724 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
4725 GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
4726 GST_TIME_ARGS (context->pos));
4727 if (context->eos == FALSE)
4731 GST_INFO_OBJECT (parse, "All streams are EOS");
4732 ret = GST_FLOW_UNEXPECTED;
4737 if (G_UNLIKELY (parse->offset == gst_matroska_parse_get_length (parse))) {
4738 GST_LOG_OBJECT (parse, "Reached end of stream");
4739 ret = GST_FLOW_UNEXPECTED;
4748 if (parse->segment.rate < 0.0) {
4749 ret = gst_matroska_parse_seek_to_previous_keyframe (parse);
4750 if (ret == GST_FLOW_OK)
4757 const gchar *reason = gst_flow_get_name (ret);
4758 gboolean push_eos = FALSE;
4760 GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
4761 parse->segment_running = FALSE;
4762 gst_pad_pause_task (parse->sinkpad);
4764 if (ret == GST_FLOW_UNEXPECTED) {
4765 /* perform EOS logic */
4767 /* Close the segment, i.e. update segment stop with the duration
4768 * if no stop was set */
4769 if (GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) &&
4770 !GST_CLOCK_TIME_IS_VALID (parse->segment.stop)) {
4772 gst_event_new_new_segment_full (TRUE, parse->segment.rate,
4773 parse->segment.applied_rate, parse->segment.format,
4774 parse->segment.start,
4775 MAX (parse->last_stop_end, parse->segment.start),
4776 parse->segment.time);
4777 gst_matroska_parse_send_event (parse, event);
4780 if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
4783 /* for segment playback we need to post when (in stream time)
4784 * we stopped, this is either stop (when set) or the duration. */
4785 if ((stop = parse->segment.stop) == -1)
4786 stop = parse->last_stop_end;
4788 GST_LOG_OBJECT (parse, "Sending segment done, at end of segment");
4789 gst_element_post_message (GST_ELEMENT (parse),
4790 gst_message_new_segment_done (GST_OBJECT (parse), GST_FORMAT_TIME,
4795 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
4796 /* for fatal errors we post an error message */
4797 GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
4798 ("stream stopped, reason %s", reason));
4802 /* send EOS, and prevent hanging if no streams yet */
4803 GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
4804 if (!gst_matroska_parse_send_event (parse, gst_event_new_eos ()) &&
4805 (ret == GST_FLOW_UNEXPECTED)) {
4806 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4807 (NULL), ("got eos but no streams (yet)"));
4816 * Create and push a flushing seek event upstream
4819 perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
4824 GST_DEBUG_OBJECT (parse, "Seeking to %" G_GUINT64_FORMAT, offset);
4827 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
4828 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
4829 GST_SEEK_TYPE_NONE, -1);
4831 res = gst_pad_push_event (parse->sinkpad, event);
4833 /* newsegment event will update offset */
4837 static const guint8 *
4838 gst_matroska_parse_peek_adapter (GstMatroskaParse * parse, guint peek)
4840 return gst_adapter_peek (parse->adapter, peek);
4843 static GstFlowReturn
4844 gst_matroska_parse_peek_id_length_push (GstMatroskaParse * parse, guint32 * _id,
4845 guint64 * _length, guint * _needed)
4847 return gst_ebml_peek_id_length (_id, _length, _needed,
4848 (GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse,
4849 GST_ELEMENT_CAST (parse), parse->offset);
4852 static GstFlowReturn
4853 gst_matroska_parse_chain (GstPad * pad, GstBuffer * buffer)
4855 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4857 GstFlowReturn ret = GST_FLOW_OK;
4862 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
4863 GST_DEBUG_OBJECT (parse, "got DISCONT");
4864 gst_adapter_clear (parse->adapter);
4865 GST_OBJECT_LOCK (parse);
4866 gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, FALSE);
4867 GST_OBJECT_UNLOCK (parse);
4870 gst_adapter_push (parse->adapter, buffer);
4874 available = gst_adapter_available (parse->adapter);
4876 ret = gst_matroska_parse_peek_id_length_push (parse, &id, &length, &needed);
4877 if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED))
4880 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4881 "size %" G_GUINT64_FORMAT ", needed %d, available %d", parse->offset, id,
4882 length, needed, available);
4884 if (needed > available)
4887 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4888 if (ret == GST_FLOW_UNEXPECTED) {
4889 /* need more data */
4891 } else if (ret != GST_FLOW_OK) {
4898 gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
4900 gboolean res = TRUE;
4901 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4903 GST_DEBUG_OBJECT (parse,
4904 "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
4906 switch (GST_EVENT_TYPE (event)) {
4907 case GST_EVENT_NEWSEGMENT:
4910 gdouble rate, arate;
4911 gint64 start, stop, time = 0;
4915 /* some debug output */
4916 gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
4917 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
4918 &start, &stop, &time);
4919 gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
4921 GST_DEBUG_OBJECT (parse,
4922 "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
4925 if (parse->state < GST_MATROSKA_PARSE_STATE_DATA) {
4926 GST_DEBUG_OBJECT (parse, "still starting");
4930 /* we only expect a BYTE segment, e.g. following a seek */
4931 if (format != GST_FORMAT_BYTES) {
4932 GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
4936 GST_DEBUG_OBJECT (parse, "clearing segment state");
4937 /* clear current segment leftover */
4938 gst_adapter_clear (parse->adapter);
4939 /* and some streaming setup */
4940 parse->offset = start;
4941 /* do not know where we are;
4942 * need to come across a cluster and generate newsegment */
4943 parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4944 parse->cluster_time = GST_CLOCK_TIME_NONE;
4945 parse->cluster_offset = 0;
4946 parse->need_newsegment = TRUE;
4947 /* but keep some of the upstream segment */
4948 parse->segment.rate = rate;
4950 /* chain will send initial newsegment after pads have been added,
4951 * or otherwise come up with one */
4952 GST_DEBUG_OBJECT (parse, "eating event");
4953 gst_event_unref (event);
4959 if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
4960 gst_event_unref (event);
4961 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4962 (NULL), ("got eos and didn't receive a complete header object"));
4963 } else if (parse->num_streams == 0) {
4964 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4965 (NULL), ("got eos but no streams (yet)"));
4967 gst_matroska_parse_send_event (parse, event);
4971 case GST_EVENT_FLUSH_STOP:
4973 gst_adapter_clear (parse->adapter);
4974 GST_OBJECT_LOCK (parse);
4975 gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, TRUE);
4976 GST_OBJECT_UNLOCK (parse);
4977 parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4978 parse->cluster_time = GST_CLOCK_TIME_NONE;
4979 parse->cluster_offset = 0;
4983 res = gst_pad_event_default (pad, event);
4991 gst_matroska_parse_set_index (GstElement * element, GstIndex * index)
4993 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
4995 GST_OBJECT_LOCK (parse);
4996 if (parse->element_index)
4997 gst_object_unref (parse->element_index);
4998 parse->element_index = index ? gst_object_ref (index) : NULL;
4999 GST_OBJECT_UNLOCK (parse);
5000 GST_DEBUG_OBJECT (parse, "Set index %" GST_PTR_FORMAT, parse->element_index);
5004 gst_matroska_parse_get_index (GstElement * element)
5006 GstIndex *result = NULL;
5007 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5009 GST_OBJECT_LOCK (parse);
5010 if (parse->element_index)
5011 result = gst_object_ref (parse->element_index);
5012 GST_OBJECT_UNLOCK (parse);
5014 GST_DEBUG_OBJECT (parse, "Returning index %" GST_PTR_FORMAT, result);
5019 static GstStateChangeReturn
5020 gst_matroska_parse_change_state (GstElement * element,
5021 GstStateChange transition)
5023 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5024 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
5026 /* handle upwards state changes here */
5027 switch (transition) {
5032 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5034 /* handle downwards state changes */
5035 switch (transition) {
5036 case GST_STATE_CHANGE_PAUSED_TO_READY:
5037 gst_matroska_parse_reset (GST_ELEMENT (parse));
5047 gst_matroska_parse_plugin_init (GstPlugin * plugin)
5051 /* create an elementfactory for the matroska_parse element */
5052 if (!gst_element_register (plugin, "matroskaparse",
5053 GST_RANK_NONE, GST_TYPE_MATROSKA_PARSE))