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);
966 if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
970 /* Encryption not supported yet */
972 return GST_FLOW_ERROR;
974 if (i + 1 >= encodings->len)
975 return GST_FLOW_ERROR;
977 if (enc->comp_settings_length == 0)
980 data = enc->comp_settings;
981 size = enc->comp_settings_length;
983 if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
984 return GST_FLOW_ERROR;
986 g_free (enc->comp_settings);
988 enc->comp_settings = data;
989 enc->comp_settings_length = size;
996 gst_matroska_parse_read_track_encodings (GstMatroskaParse * parse,
997 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
1002 DEBUG_ELEMENT_START (parse, ebml, "ContentEncodings");
1004 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1005 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1009 context->encodings =
1010 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
1012 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1013 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1017 case GST_MATROSKA_ID_CONTENTENCODING:
1018 ret = gst_matroska_parse_read_track_encoding (parse, ebml, context);
1021 GST_WARNING_OBJECT (parse,
1022 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
1023 ret = gst_ebml_read_skip (ebml);
1028 DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1029 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
1032 /* Sort encodings according to their order */
1033 g_array_sort (context->encodings,
1034 (GCompareFunc) gst_matroska_parse_encoding_cmp);
1036 return gst_matroska_decode_content_encodings (context->encodings);
1040 gst_matroska_parse_tracknumber_unique (GstMatroskaParse * parse, guint64 num)
1044 g_assert (parse->src->len == parse->num_streams);
1045 for (i = 0; i < parse->src->len; i++) {
1046 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1048 if (context->num == num)
1055 static GstFlowReturn
1056 gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
1058 GstMatroskaTrackContext *context;
1062 DEBUG_ELEMENT_START (parse, ebml, "TrackEntry");
1064 /* start with the master */
1065 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1066 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1070 /* allocate generic... if we know the type, we'll g_renew()
1071 * with the precise type */
1072 context = g_new0 (GstMatroskaTrackContext, 1);
1073 g_ptr_array_add (parse->src, context);
1074 context->index = parse->num_streams;
1075 context->index_writer_id = -1;
1076 context->type = 0; /* no type yet */
1077 context->default_duration = 0;
1079 context->set_discont = TRUE;
1080 context->timecodescale = 1.0;
1082 GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
1083 GST_MATROSKA_TRACK_LACING;
1084 context->last_flow = GST_FLOW_OK;
1085 context->to_offset = G_MAXINT64;
1086 parse->num_streams++;
1087 g_assert (parse->src->len == parse->num_streams);
1089 GST_DEBUG_OBJECT (parse, "Stream number %d", context->index);
1091 /* try reading the trackentry headers */
1092 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1093 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1097 /* track number (unique stream ID) */
1098 case GST_MATROSKA_ID_TRACKNUMBER:{
1101 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1105 GST_ERROR_OBJECT (parse, "Invalid TrackNumber 0");
1106 ret = GST_FLOW_ERROR;
1108 } else if (!gst_matroska_parse_tracknumber_unique (parse, num)) {
1109 GST_ERROR_OBJECT (parse, "TrackNumber %" G_GUINT64_FORMAT
1110 " is not unique", num);
1111 ret = GST_FLOW_ERROR;
1115 GST_DEBUG_OBJECT (parse, "TrackNumber: %" G_GUINT64_FORMAT, num);
1119 /* track UID (unique identifier) */
1120 case GST_MATROSKA_ID_TRACKUID:{
1123 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1127 GST_ERROR_OBJECT (parse, "Invalid TrackUID 0");
1128 ret = GST_FLOW_ERROR;
1132 GST_DEBUG_OBJECT (parse, "TrackUID: %" G_GUINT64_FORMAT, num);
1137 /* track type (video, audio, combined, subtitle, etc.) */
1138 case GST_MATROSKA_ID_TRACKTYPE:{
1141 if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
1145 if (context->type != 0 && context->type != track_type) {
1146 GST_WARNING_OBJECT (parse,
1147 "More than one tracktype defined in a TrackEntry - skipping");
1149 } else if (track_type < 1 || track_type > 254) {
1150 GST_WARNING_OBJECT (parse, "Invalid TrackType %" G_GUINT64_FORMAT,
1155 GST_DEBUG_OBJECT (parse, "TrackType: %" G_GUINT64_FORMAT, track_type);
1157 /* ok, so we're actually going to reallocate this thing */
1158 switch (track_type) {
1159 case GST_MATROSKA_TRACK_TYPE_VIDEO:
1160 gst_matroska_track_init_video_context (&context);
1162 case GST_MATROSKA_TRACK_TYPE_AUDIO:
1163 gst_matroska_track_init_audio_context (&context);
1165 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
1166 gst_matroska_track_init_subtitle_context (&context);
1168 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
1169 case GST_MATROSKA_TRACK_TYPE_LOGO:
1170 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
1171 case GST_MATROSKA_TRACK_TYPE_CONTROL:
1173 GST_WARNING_OBJECT (parse,
1174 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
1179 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1183 /* tracktype specific stuff for video */
1184 case GST_MATROSKA_ID_TRACKVIDEO:{
1185 GstMatroskaTrackVideoContext *videocontext;
1187 DEBUG_ELEMENT_START (parse, ebml, "TrackVideo");
1189 if (!gst_matroska_track_init_video_context (&context)) {
1190 GST_WARNING_OBJECT (parse,
1191 "TrackVideo element in non-video track - ignoring track");
1192 ret = GST_FLOW_ERROR;
1194 } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1197 videocontext = (GstMatroskaTrackVideoContext *) context;
1198 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1200 while (ret == GST_FLOW_OK &&
1201 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1202 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1206 /* Should be one level up but some broken muxers write it here. */
1207 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1210 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1214 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1218 GST_DEBUG_OBJECT (parse,
1219 "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
1220 context->default_duration = num;
1224 /* video framerate */
1225 /* NOTE: This one is here only for backward compatibility.
1226 * Use _TRACKDEFAULDURATION one level up. */
1227 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
1230 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1234 GST_WARNING_OBJECT (parse, "Invalid TrackVideoFPS %lf", num);
1238 GST_DEBUG_OBJECT (parse, "TrackVideoFrameRate: %lf", num);
1239 if (context->default_duration == 0)
1240 context->default_duration =
1241 gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
1242 videocontext->default_fps = num;
1246 /* width of the size to display the video at */
1247 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
1250 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1254 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayWidth 0");
1258 GST_DEBUG_OBJECT (parse,
1259 "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
1260 videocontext->display_width = num;
1264 /* height of the size to display the video at */
1265 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
1268 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1272 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayHeight 0");
1276 GST_DEBUG_OBJECT (parse,
1277 "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
1278 videocontext->display_height = num;
1282 /* width of the video in the file */
1283 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
1286 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1290 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelWidth 0");
1294 GST_DEBUG_OBJECT (parse,
1295 "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
1296 videocontext->pixel_width = num;
1300 /* height of the video in the file */
1301 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
1304 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1308 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelHeight 0");
1312 GST_DEBUG_OBJECT (parse,
1313 "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
1314 videocontext->pixel_height = num;
1318 /* whether the video is interlaced */
1319 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
1322 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1326 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
1328 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
1329 GST_DEBUG_OBJECT (parse, "TrackVideoInterlaced: %d",
1330 (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 :
1335 /* aspect ratio behaviour */
1336 case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
1339 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1342 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
1343 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
1344 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
1345 GST_WARNING_OBJECT (parse,
1346 "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
1349 GST_DEBUG_OBJECT (parse,
1350 "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
1351 videocontext->asr_mode = num;
1355 /* colourspace (only matters for raw video) fourcc */
1356 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
1361 gst_ebml_read_binary (ebml, &id, &data,
1362 &datalen)) != GST_FLOW_OK)
1367 GST_WARNING_OBJECT (parse,
1368 "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
1373 memcpy (&videocontext->fourcc, data, 4);
1374 GST_DEBUG_OBJECT (parse,
1375 "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
1376 GST_FOURCC_ARGS (videocontext->fourcc));
1382 GST_WARNING_OBJECT (parse,
1383 "Unknown TrackVideo subelement 0x%x - ignoring", id);
1385 case GST_MATROSKA_ID_VIDEOSTEREOMODE:
1386 case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
1387 case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
1388 case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
1389 case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
1390 case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
1391 case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
1392 ret = gst_ebml_read_skip (ebml);
1397 DEBUG_ELEMENT_STOP (parse, ebml, "TrackVideo", ret);
1401 /* tracktype specific stuff for audio */
1402 case GST_MATROSKA_ID_TRACKAUDIO:{
1403 GstMatroskaTrackAudioContext *audiocontext;
1405 DEBUG_ELEMENT_START (parse, ebml, "TrackAudio");
1407 if (!gst_matroska_track_init_audio_context (&context)) {
1408 GST_WARNING_OBJECT (parse,
1409 "TrackAudio element in non-audio track - ignoring track");
1410 ret = GST_FLOW_ERROR;
1414 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
1417 audiocontext = (GstMatroskaTrackAudioContext *) context;
1418 g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1420 while (ret == GST_FLOW_OK &&
1421 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1422 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1427 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
1430 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1435 GST_WARNING_OBJECT (parse,
1436 "Invalid TrackAudioSamplingFrequency %lf", num);
1440 GST_DEBUG_OBJECT (parse, "TrackAudioSamplingFrequency: %lf", num);
1441 audiocontext->samplerate = num;
1446 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
1449 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1453 GST_WARNING_OBJECT (parse, "Invalid TrackAudioBitDepth 0");
1457 GST_DEBUG_OBJECT (parse, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
1459 audiocontext->bitdepth = num;
1464 case GST_MATROSKA_ID_AUDIOCHANNELS:{
1467 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1471 GST_WARNING_OBJECT (parse, "Invalid TrackAudioChannels 0");
1475 GST_DEBUG_OBJECT (parse, "TrackAudioChannels: %" G_GUINT64_FORMAT,
1477 audiocontext->channels = num;
1482 GST_WARNING_OBJECT (parse,
1483 "Unknown TrackAudio subelement 0x%x - ignoring", id);
1485 case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
1486 case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
1487 ret = gst_ebml_read_skip (ebml);
1492 DEBUG_ELEMENT_STOP (parse, ebml, "TrackAudio", ret);
1497 /* codec identifier */
1498 case GST_MATROSKA_ID_CODECID:{
1501 if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
1504 GST_DEBUG_OBJECT (parse, "CodecID: %s", GST_STR_NULL (text));
1505 context->codec_id = text;
1509 /* codec private data */
1510 case GST_MATROSKA_ID_CODECPRIVATE:{
1515 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
1518 context->codec_priv = data;
1519 context->codec_priv_size = size;
1521 GST_DEBUG_OBJECT (parse, "CodecPrivate of size %" G_GUINT64_FORMAT,
1526 /* name of the codec */
1527 case GST_MATROSKA_ID_CODECNAME:{
1530 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1533 GST_DEBUG_OBJECT (parse, "CodecName: %s", GST_STR_NULL (text));
1534 context->codec_name = text;
1538 /* name of this track */
1539 case GST_MATROSKA_ID_TRACKNAME:{
1542 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1545 context->name = text;
1546 GST_DEBUG_OBJECT (parse, "TrackName: %s", GST_STR_NULL (text));
1550 /* language (matters for audio/subtitles, mostly) */
1551 case GST_MATROSKA_ID_TRACKLANGUAGE:{
1554 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1558 context->language = text;
1561 if (strlen (context->language) >= 4 && context->language[3] == '-')
1562 context->language[3] = '\0';
1564 GST_DEBUG_OBJECT (parse, "TrackLanguage: %s",
1565 GST_STR_NULL (context->language));
1569 /* whether this is actually used */
1570 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
1573 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1577 context->flags |= GST_MATROSKA_TRACK_ENABLED;
1579 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
1581 GST_DEBUG_OBJECT (parse, "TrackEnabled: %d",
1582 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1586 /* whether it's the default for this track type */
1587 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
1590 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1594 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
1596 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
1598 GST_DEBUG_OBJECT (parse, "TrackDefault: %d",
1599 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1603 /* whether the track must be used during playback */
1604 case GST_MATROSKA_ID_TRACKFLAGFORCED:{
1607 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1611 context->flags |= GST_MATROSKA_TRACK_FORCED;
1613 context->flags &= ~GST_MATROSKA_TRACK_FORCED;
1615 GST_DEBUG_OBJECT (parse, "TrackForced: %d",
1616 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1620 /* lacing (like MPEG, where blocks don't end/start on frame
1622 case GST_MATROSKA_ID_TRACKFLAGLACING:{
1625 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1629 context->flags |= GST_MATROSKA_TRACK_LACING;
1631 context->flags &= ~GST_MATROSKA_TRACK_LACING;
1633 GST_DEBUG_OBJECT (parse, "TrackLacing: %d",
1634 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1638 /* default length (in time) of one data block in this track */
1639 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1642 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1647 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1651 GST_DEBUG_OBJECT (parse, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
1653 context->default_duration = num;
1657 case GST_MATROSKA_ID_CONTENTENCODINGS:{
1658 ret = gst_matroska_parse_read_track_encodings (parse, ebml, context);
1662 case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
1665 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1669 GST_WARNING_OBJECT (parse, "Invalid TrackTimeCodeScale %lf", num);
1673 GST_DEBUG_OBJECT (parse, "TrackTimeCodeScale: %lf", num);
1674 context->timecodescale = num;
1679 GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
1682 /* we ignore these because they're nothing useful (i.e. crap)
1683 * or simply not implemented yet. */
1684 case GST_MATROSKA_ID_TRACKMINCACHE:
1685 case GST_MATROSKA_ID_TRACKMAXCACHE:
1686 case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
1687 case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
1688 case GST_MATROSKA_ID_TRACKOVERLAY:
1689 case GST_MATROSKA_ID_TRACKTRANSLATE:
1690 case GST_MATROSKA_ID_TRACKOFFSET:
1691 case GST_MATROSKA_ID_CODECSETTINGS:
1692 case GST_MATROSKA_ID_CODECINFOURL:
1693 case GST_MATROSKA_ID_CODECDOWNLOADURL:
1694 case GST_MATROSKA_ID_CODECDECODEALL:
1695 ret = gst_ebml_read_skip (ebml);
1700 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1702 /* Decode codec private data if necessary */
1703 if (context->encodings && context->encodings->len > 0 && context->codec_priv
1704 && context->codec_priv_size > 0) {
1705 if (!gst_matroska_decode_data (context->encodings,
1706 &context->codec_priv, &context->codec_priv_size,
1707 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
1708 GST_WARNING_OBJECT (parse, "Decoding codec private data failed");
1709 ret = GST_FLOW_ERROR;
1713 if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
1714 && ret != GST_FLOW_UNEXPECTED)) {
1715 if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
1716 GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
1718 parse->num_streams--;
1719 g_ptr_array_remove_index (parse->src, parse->num_streams);
1720 g_assert (parse->src->len == parse->num_streams);
1722 gst_matroska_track_free (context);
1728 if ((context->language == NULL || *context->language == '\0') &&
1729 (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
1730 context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
1731 GST_LOG ("stream %d: language=eng (assuming default)", context->index);
1732 context->language = g_strdup ("eng");
1740 static const GstQueryType *
1741 gst_matroska_parse_get_src_query_types (GstPad * pad)
1743 static const GstQueryType query_types[] = {
1754 gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
1757 gboolean res = FALSE;
1758 GstMatroskaTrackContext *context = NULL;
1761 context = gst_pad_get_element_private (pad);
1764 switch (GST_QUERY_TYPE (query)) {
1765 case GST_QUERY_POSITION:
1769 gst_query_parse_position (query, &format, NULL);
1771 if (format == GST_FORMAT_TIME) {
1772 GST_OBJECT_LOCK (parse);
1774 gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
1776 gst_query_set_position (query, GST_FORMAT_TIME,
1777 parse->segment.last_stop);
1778 GST_OBJECT_UNLOCK (parse);
1779 } else if (format == GST_FORMAT_DEFAULT && context
1780 && context->default_duration) {
1781 GST_OBJECT_LOCK (parse);
1782 gst_query_set_position (query, GST_FORMAT_DEFAULT,
1783 context->pos / context->default_duration);
1784 GST_OBJECT_UNLOCK (parse);
1786 GST_DEBUG_OBJECT (parse,
1787 "only position query in TIME and DEFAULT format is supported");
1793 case GST_QUERY_DURATION:
1797 gst_query_parse_duration (query, &format, NULL);
1799 if (format == GST_FORMAT_TIME) {
1800 GST_OBJECT_LOCK (parse);
1801 gst_query_set_duration (query, GST_FORMAT_TIME,
1802 parse->segment.duration);
1803 GST_OBJECT_UNLOCK (parse);
1804 } else if (format == GST_FORMAT_DEFAULT && context
1805 && context->default_duration) {
1806 GST_OBJECT_LOCK (parse);
1807 gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1808 parse->segment.duration / context->default_duration);
1809 GST_OBJECT_UNLOCK (parse);
1811 GST_DEBUG_OBJECT (parse,
1812 "only duration query in TIME and DEFAULT format is supported");
1819 case GST_QUERY_SEEKING:
1823 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1824 if (fmt == GST_FORMAT_TIME) {
1827 /* assuming we'll be able to get an index ... */
1828 seekable = parse->seekable;
1830 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1831 0, parse->segment.duration);
1837 res = gst_pad_query_default (pad, query);
1845 gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
1847 return gst_matroska_parse_query (GST_MATROSKA_PARSE (element), NULL, query);
1851 gst_matroska_parse_handle_src_query (GstPad * pad, GstQuery * query)
1854 GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
1856 ret = gst_matroska_parse_query (parse, pad, query);
1858 gst_object_unref (parse);
1864 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
1867 if (i1->time < *time)
1869 else if (i1->time > *time)
1875 static GstMatroskaIndex *
1876 gst_matroskaparse_do_index_seek (GstMatroskaParse * parse,
1877 GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
1878 gint * _entry_index)
1880 GstMatroskaIndex *entry = NULL;
1883 if (!parse->index || !parse->index->len)
1886 /* find entry just before or at the requested position */
1887 if (track && track->index_table)
1888 index = track->index_table;
1890 index = parse->index;
1893 gst_util_array_binary_search (index->data, index->len,
1894 sizeof (GstMatroskaIndex),
1895 (GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE,
1899 entry = &g_array_index (index, GstMatroskaIndex, 0);
1904 *_entry_index = entry - (GstMatroskaIndex *) index->data;
1909 /* takes ownership of taglist */
1911 gst_matroska_parse_found_global_tag (GstMatroskaParse * parse,
1912 GstTagList * taglist)
1914 if (parse->global_tags) {
1915 /* nothing sent yet, add to cache */
1916 gst_tag_list_insert (parse->global_tags, taglist, GST_TAG_MERGE_APPEND);
1917 gst_tag_list_free (taglist);
1919 /* hm, already sent, no need to cache and wait anymore */
1920 GST_DEBUG_OBJECT (parse, "Sending late global tags %" GST_PTR_FORMAT,
1922 gst_element_found_tags (GST_ELEMENT (parse), taglist);
1926 /* returns FALSE if there are no pads to deliver event to,
1927 * otherwise TRUE (whatever the outcome of event sending),
1928 * takes ownership of the passed event! */
1930 gst_matroska_parse_send_event (GstMatroskaParse * parse, GstEvent * event)
1932 gboolean ret = FALSE;
1934 g_return_val_if_fail (event != NULL, FALSE);
1936 GST_DEBUG_OBJECT (parse, "Sending event of type %s to all source pads",
1937 GST_EVENT_TYPE_NAME (event));
1939 gst_pad_push_event (parse->srcpad, event);
1945 gst_matroska_parse_element_send_event (GstElement * element, GstEvent * event)
1947 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
1950 g_return_val_if_fail (event != NULL, FALSE);
1952 if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1953 res = gst_matroska_parse_handle_seek_event (parse, NULL, event);
1955 GST_WARNING_OBJECT (parse, "Unhandled event of type %s",
1956 GST_EVENT_TYPE_NAME (event));
1959 gst_event_unref (event);
1963 /* determine track to seek in */
1964 static GstMatroskaTrackContext *
1965 gst_matroska_parse_get_seek_track (GstMatroskaParse * parse,
1966 GstMatroskaTrackContext * track)
1970 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
1973 for (i = 0; i < parse->src->len; i++) {
1974 GstMatroskaTrackContext *stream;
1976 stream = g_ptr_array_index (parse->src, i);
1977 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
1985 gst_matroska_parse_reset_streams (GstMatroskaParse * parse, GstClockTime time,
1990 GST_DEBUG_OBJECT (parse, "resetting stream state");
1992 g_assert (parse->src->len == parse->num_streams);
1993 for (i = 0; i < parse->src->len; i++) {
1994 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1995 context->pos = time;
1996 context->set_discont = TRUE;
1997 context->eos = FALSE;
1998 context->from_time = GST_CLOCK_TIME_NONE;
2000 context->last_flow = GST_FLOW_OK;
2001 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2002 GstMatroskaTrackVideoContext *videocontext =
2003 (GstMatroskaTrackVideoContext *) context;
2004 /* parse object lock held by caller */
2005 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2010 /* searches for a cluster start from @pos,
2011 * return GST_FLOW_OK and cluster position in @pos if found */
2012 static GstFlowReturn
2013 gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
2015 gint64 newpos = *pos;
2017 GstFlowReturn ret = GST_FLOW_OK;
2018 const guint chunk = 64 * 1024;
2019 GstBuffer *buf = NULL;
2024 orig_offset = parse->offset;
2026 /* read in at newpos and scan for ebml cluster id */
2028 GstByteReader reader;
2031 ret = gst_pad_pull_range (parse->sinkpad, newpos, chunk, &buf);
2032 if (ret != GST_FLOW_OK)
2034 GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
2035 GST_BUFFER_SIZE (buf), newpos);
2036 gst_byte_reader_init_from_buffer (&reader, buf);
2039 cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
2040 GST_MATROSKA_ID_CLUSTER, cluster_pos,
2041 GST_BUFFER_SIZE (buf) - cluster_pos);
2042 if (cluster_pos >= 0) {
2043 newpos += cluster_pos;
2044 GST_DEBUG_OBJECT (parse,
2045 "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
2046 /* extra checks whether we really sync'ed to a cluster:
2047 * - either it is the first and only cluster
2048 * - either there is a cluster after this one
2049 * - either cluster length is undefined
2051 /* ok if first cluster (there may not a subsequent one) */
2052 if (newpos == parse->first_cluster_offset) {
2053 GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
2056 parse->offset = newpos;
2058 gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2059 if (ret != GST_FLOW_OK)
2061 g_assert (id == GST_MATROSKA_ID_CLUSTER);
2062 GST_DEBUG_OBJECT (parse, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
2064 /* ok if undefined length or first cluster */
2065 if (length == G_MAXUINT64) {
2066 GST_DEBUG_OBJECT (parse, "cluster has undefined length -> OK");
2070 parse->offset += length + needed;
2072 gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2073 if (ret != GST_FLOW_OK)
2075 GST_DEBUG_OBJECT (parse, "next element is %scluster",
2076 id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
2077 if (id == GST_MATROSKA_ID_CLUSTER)
2079 /* not ok, resume */
2082 /* partial cluster id may have been in tail of buffer */
2083 newpos += MAX (GST_BUFFER_SIZE (buf), 4) - 3;
2084 gst_buffer_unref (buf);
2090 gst_buffer_unref (buf);
2094 parse->offset = orig_offset;
2101 gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
2102 GstPad * pad, GstEvent * event)
2104 GstMatroskaIndex *entry = NULL;
2106 GstSeekType cur_type, stop_type;
2110 GstMatroskaTrackContext *track = NULL;
2111 GstSegment seeksegment = { 0, };
2115 track = gst_pad_get_element_private (pad);
2117 track = gst_matroska_parse_get_seek_track (parse, track);
2119 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2122 /* we can only seek on time */
2123 if (format != GST_FORMAT_TIME) {
2124 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2128 /* copy segment, we need this because we still need the old
2129 * segment when we close the current segment. */
2130 memcpy (&seeksegment, &parse->segment, sizeof (GstSegment));
2133 GST_DEBUG_OBJECT (parse, "configuring seek");
2134 gst_segment_set_seek (&seeksegment, rate, format, flags,
2135 cur_type, cur, stop_type, stop, &update);
2138 GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
2140 /* check sanity before we start flushing and all that */
2141 GST_OBJECT_LOCK (parse);
2142 if ((entry = gst_matroskaparse_do_index_seek (parse, track,
2143 seeksegment.last_stop, &parse->seek_index, &parse->seek_entry)) ==
2145 /* pull mode without index can scan later on */
2146 GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
2147 GST_OBJECT_UNLOCK (parse);
2150 GST_DEBUG_OBJECT (parse, "Seek position looks sane");
2151 GST_OBJECT_UNLOCK (parse);
2153 /* need to seek to cluster start to pick up cluster time */
2154 /* upstream takes care of flushing and all that
2155 * ... and newsegment event handling takes care of the rest */
2156 return perform_seek_to_offset (parse, entry->pos + parse->ebml_segment_start);
2160 * Handle whether we can perform the seek event or if we have to let the chain
2161 * function handle seeks to build the seek indexes first.
2164 gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
2168 GstSeekType cur_type, stop_type;
2173 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2178 /* we can only seek on time */
2179 if (format != GST_FORMAT_TIME) {
2180 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2184 if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
2185 GST_DEBUG_OBJECT (parse, "Seek end-time not supported in streaming mode");
2189 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
2190 GST_DEBUG_OBJECT (parse,
2191 "Non-flushing seek not supported in streaming mode");
2195 if (flags & GST_SEEK_FLAG_SEGMENT) {
2196 GST_DEBUG_OBJECT (parse, "Segment seek not supported in streaming mode");
2200 /* check for having parsed index already */
2201 if (!parse->index_parsed) {
2202 gboolean building_index;
2205 if (!parse->index_offset) {
2206 GST_DEBUG_OBJECT (parse, "no index (location); no seek in push mode");
2210 GST_OBJECT_LOCK (parse);
2211 /* handle the seek event in the chain function */
2212 parse->state = GST_MATROSKA_PARSE_STATE_SEEK;
2213 /* no more seek can be issued until state reset to _DATA */
2215 /* copy the event */
2216 if (parse->seek_event)
2217 gst_event_unref (parse->seek_event);
2218 parse->seek_event = gst_event_ref (event);
2220 /* set the building_index flag so that only one thread can setup the
2221 * structures for index seeking. */
2222 building_index = parse->building_index;
2223 if (!building_index) {
2224 parse->building_index = TRUE;
2225 offset = parse->index_offset;
2227 GST_OBJECT_UNLOCK (parse);
2229 if (!building_index) {
2230 /* seek to the first subindex or legacy index */
2231 GST_INFO_OBJECT (parse, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
2232 return perform_seek_to_offset (parse, offset);
2235 /* well, we are handling it already */
2239 /* delegate to tweaked regular seek */
2240 return gst_matroska_parse_handle_seek_event (parse, pad, event);
2244 gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
2246 GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
2247 gboolean res = TRUE;
2249 switch (GST_EVENT_TYPE (event)) {
2250 case GST_EVENT_SEEK:
2251 /* no seeking until we are (safely) ready */
2252 if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
2253 GST_DEBUG_OBJECT (parse, "not ready for seeking yet");
2256 res = gst_matroska_parse_handle_seek_push (parse, pad, event);
2257 gst_event_unref (event);
2262 GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
2263 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2264 GstMatroskaTrackVideoContext *videocontext =
2265 (GstMatroskaTrackVideoContext *) context;
2267 GstClockTimeDiff diff;
2268 GstClockTime timestamp;
2270 gst_event_parse_qos (event, &proportion, &diff, ×tamp);
2272 GST_OBJECT_LOCK (parse);
2273 videocontext->earliest_time = timestamp + diff;
2274 GST_OBJECT_UNLOCK (parse);
2277 gst_event_unref (event);
2281 /* events we don't need to handle */
2282 case GST_EVENT_NAVIGATION:
2283 gst_event_unref (event);
2287 case GST_EVENT_LATENCY:
2289 res = gst_pad_push_event (parse->sinkpad, event);
2293 gst_object_unref (parse);
2299 /* skip unknown or alike element */
2300 static GstFlowReturn
2301 gst_matroska_parse_parse_skip (GstMatroskaParse * parse, GstEbmlRead * ebml,
2302 const gchar * parent_name, guint id)
2304 if (id == GST_EBML_ID_VOID) {
2305 GST_DEBUG_OBJECT (parse, "Skipping EBML Void element");
2306 } else if (id == GST_EBML_ID_CRC32) {
2307 GST_DEBUG_OBJECT (parse, "Skipping EBML CRC32 element");
2309 GST_WARNING_OBJECT (parse,
2310 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
2313 return gst_ebml_read_skip (ebml);
2316 static GstFlowReturn
2317 gst_matroska_parse_parse_header (GstMatroskaParse * parse, GstEbmlRead * ebml)
2324 /* this function is the first to be called */
2330 ret = gst_ebml_peek_id (ebml, &id);
2331 if (ret != GST_FLOW_OK)
2334 GST_DEBUG_OBJECT (parse, "id: %08x", id);
2336 if (id != GST_EBML_ID_HEADER) {
2337 GST_ERROR_OBJECT (parse, "Failed to read header");
2341 ret = gst_ebml_read_master (ebml, &id);
2342 if (ret != GST_FLOW_OK)
2345 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2346 ret = gst_ebml_peek_id (ebml, &id);
2347 if (ret != GST_FLOW_OK)
2351 /* is our read version uptodate? */
2352 case GST_EBML_ID_EBMLREADVERSION:{
2355 ret = gst_ebml_read_uint (ebml, &id, &num);
2356 if (ret != GST_FLOW_OK)
2358 if (num != GST_EBML_VERSION) {
2359 GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
2361 return GST_FLOW_ERROR;
2364 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2368 /* we only handle 8 byte lengths at max */
2369 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
2372 ret = gst_ebml_read_uint (ebml, &id, &num);
2373 if (ret != GST_FLOW_OK)
2375 if (num > sizeof (guint64)) {
2376 GST_ERROR_OBJECT (ebml,
2377 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
2378 return GST_FLOW_ERROR;
2380 GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
2384 /* we handle 4 byte IDs at max */
2385 case GST_EBML_ID_EBMLMAXIDLENGTH:{
2388 ret = gst_ebml_read_uint (ebml, &id, &num);
2389 if (ret != GST_FLOW_OK)
2391 if (num > sizeof (guint32)) {
2392 GST_ERROR_OBJECT (ebml,
2393 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
2394 return GST_FLOW_ERROR;
2396 GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
2400 case GST_EBML_ID_DOCTYPE:{
2403 ret = gst_ebml_read_ascii (ebml, &id, &text);
2404 if (ret != GST_FLOW_OK)
2407 GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
2415 case GST_EBML_ID_DOCTYPEREADVERSION:{
2418 ret = gst_ebml_read_uint (ebml, &id, &num);
2419 if (ret != GST_FLOW_OK)
2422 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2427 ret = gst_matroska_parse_parse_skip (parse, ebml, "EBML header", id);
2428 if (ret != GST_FLOW_OK)
2432 /* we ignore these two, as they don't tell us anything we care about */
2433 case GST_EBML_ID_EBMLVERSION:
2434 case GST_EBML_ID_DOCTYPEVERSION:
2435 ret = gst_ebml_read_skip (ebml);
2436 if (ret != GST_FLOW_OK)
2444 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
2445 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
2446 (doctype == NULL)) {
2449 GST_INFO_OBJECT (parse, "Input is %s version %d", doctype, version);
2451 GST_WARNING_OBJECT (parse, "Input is EBML without doctype, assuming "
2452 "matroska (version %d)", version);
2456 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2457 ("Parser version (2) is too old to read %s version %d",
2458 GST_STR_NULL (doctype), version));
2459 ret = GST_FLOW_ERROR;
2463 GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, (NULL),
2464 ("Input is not a matroska stream (doctype=%s)", doctype));
2465 ret = GST_FLOW_ERROR;
2472 static GstFlowReturn
2473 gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml)
2475 GstFlowReturn ret = GST_FLOW_OK;
2478 DEBUG_ELEMENT_START (parse, ebml, "Tracks");
2480 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2481 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2485 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2486 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2490 /* one track within the "all-tracks" header */
2491 case GST_MATROSKA_ID_TRACKENTRY:
2492 ret = gst_matroska_parse_add_stream (parse, ebml);
2496 ret = gst_matroska_parse_parse_skip (parse, ebml, "Track", id);
2500 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2502 parse->tracks_parsed = TRUE;
2507 static GstFlowReturn
2508 gst_matroska_parse_parse_index_cuetrack (GstMatroskaParse * parse,
2509 GstEbmlRead * ebml, guint * nentries)
2513 GstMatroskaIndex idx;
2515 idx.pos = (guint64) - 1;
2517 idx.time = GST_CLOCK_TIME_NONE;
2520 DEBUG_ELEMENT_START (parse, ebml, "CueTrackPositions");
2522 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2523 DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2527 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2528 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2533 case GST_MATROSKA_ID_CUETRACK:
2537 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2542 GST_WARNING_OBJECT (parse, "Invalid CueTrack 0");
2546 GST_DEBUG_OBJECT (parse, "CueTrack: %" G_GUINT64_FORMAT, num);
2551 /* position in file */
2552 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
2556 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2559 if (num > G_MAXINT64) {
2560 GST_WARNING_OBJECT (parse, "CueClusterPosition %" G_GUINT64_FORMAT
2569 /* number of block in the cluster */
2570 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
2574 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2578 GST_WARNING_OBJECT (parse, "Invalid CueBlockNumber 0");
2582 GST_DEBUG_OBJECT (parse, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
2585 /* mild sanity check, disregard strange cases ... */
2586 if (idx.block > G_MAXUINT16) {
2587 GST_DEBUG_OBJECT (parse, "... looks suspicious, ignoring");
2594 ret = gst_matroska_parse_parse_skip (parse, ebml, "CueTrackPositions",
2598 case GST_MATROSKA_ID_CUECODECSTATE:
2599 case GST_MATROSKA_ID_CUEREFERENCE:
2600 ret = gst_ebml_read_skip (ebml);
2605 DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2607 if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
2608 && idx.pos != (guint64) - 1 && idx.track > 0) {
2609 g_array_append_val (parse->index, idx);
2611 } else if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) {
2612 GST_DEBUG_OBJECT (parse, "CueTrackPositions without valid content");
2618 static GstFlowReturn
2619 gst_matroska_parse_parse_index_pointentry (GstMatroskaParse * parse,
2624 GstClockTime time = GST_CLOCK_TIME_NONE;
2627 DEBUG_ELEMENT_START (parse, ebml, "CuePoint");
2629 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2630 DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2634 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2635 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2639 /* one single index entry ('point') */
2640 case GST_MATROSKA_ID_CUETIME:
2642 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
2645 GST_DEBUG_OBJECT (parse, "CueTime: %" G_GUINT64_FORMAT, time);
2646 time = time * parse->time_scale;
2650 /* position in the file + track to which it belongs */
2651 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
2654 gst_matroska_parse_parse_index_cuetrack (parse, ebml,
2655 &nentries)) != GST_FLOW_OK)
2661 ret = gst_matroska_parse_parse_skip (parse, ebml, "CuePoint", id);
2666 DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2669 if (time == GST_CLOCK_TIME_NONE) {
2670 GST_WARNING_OBJECT (parse, "CuePoint without valid time");
2671 g_array_remove_range (parse->index, parse->index->len - nentries,
2676 for (i = parse->index->len - nentries; i < parse->index->len; i++) {
2677 GstMatroskaIndex *idx =
2678 &g_array_index (parse->index, GstMatroskaIndex, i);
2681 GST_DEBUG_OBJECT (parse, "Index entry: pos=%" G_GUINT64_FORMAT
2682 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
2683 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
2687 GST_DEBUG_OBJECT (parse, "Empty CuePoint");
2694 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
2696 if (i1->time < i2->time)
2698 else if (i1->time > i2->time)
2700 else if (i1->block < i2->block)
2702 else if (i1->block > i2->block)
2708 static GstFlowReturn
2709 gst_matroska_parse_parse_index (GstMatroskaParse * parse, GstEbmlRead * ebml)
2712 GstFlowReturn ret = GST_FLOW_OK;
2716 g_array_free (parse->index, TRUE);
2718 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2720 DEBUG_ELEMENT_START (parse, ebml, "Cues");
2722 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2723 DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2727 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2728 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2732 /* one single index entry ('point') */
2733 case GST_MATROSKA_ID_POINTENTRY:
2734 ret = gst_matroska_parse_parse_index_pointentry (parse, ebml);
2738 ret = gst_matroska_parse_parse_skip (parse, ebml, "Cues", id);
2742 DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2744 /* Sort index by time, smallest time first, for easier searching */
2745 g_array_sort (parse->index, (GCompareFunc) gst_matroska_index_compare);
2747 /* Now sort the track specific index entries into their own arrays */
2748 for (i = 0; i < parse->index->len; i++) {
2749 GstMatroskaIndex *idx = &g_array_index (parse->index, GstMatroskaIndex, i);
2751 GstMatroskaTrackContext *ctx;
2753 if (parse->element_index) {
2756 if (idx->track != 0 &&
2758 gst_matroska_parse_stream_from_num (parse, idx->track)) != -1) {
2759 ctx = g_ptr_array_index (parse->src, track_num);
2761 if (ctx->index_writer_id == -1)
2762 gst_index_get_writer_id (parse->element_index, GST_OBJECT (ctx->pad),
2763 &ctx->index_writer_id);
2764 writer_id = ctx->index_writer_id;
2766 if (parse->element_index_writer_id == -1)
2767 gst_index_get_writer_id (parse->element_index, GST_OBJECT (parse),
2768 &parse->element_index_writer_id);
2769 writer_id = parse->element_index_writer_id;
2772 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2773 G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
2774 idx->pos, writer_id);
2775 gst_index_add_association (parse->element_index, writer_id,
2776 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
2777 GST_FORMAT_BYTES, idx->pos + parse->ebml_segment_start, NULL);
2780 if (idx->track == 0)
2783 track_num = gst_matroska_parse_stream_from_num (parse, idx->track);
2784 if (track_num == -1)
2787 ctx = g_ptr_array_index (parse->src, track_num);
2789 if (ctx->index_table == NULL)
2791 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2793 g_array_append_vals (ctx->index_table, idx, 1);
2796 parse->index_parsed = TRUE;
2798 /* sanity check; empty index normalizes to no index */
2799 if (parse->index->len == 0) {
2800 g_array_free (parse->index, TRUE);
2801 parse->index = NULL;
2807 static GstFlowReturn
2808 gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml)
2810 GstFlowReturn ret = GST_FLOW_OK;
2813 DEBUG_ELEMENT_START (parse, ebml, "SegmentInfo");
2815 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2816 DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2820 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2821 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2825 /* cluster timecode */
2826 case GST_MATROSKA_ID_TIMECODESCALE:{
2829 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2833 GST_DEBUG_OBJECT (parse, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
2834 parse->time_scale = num;
2838 case GST_MATROSKA_ID_DURATION:{
2842 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
2846 GST_WARNING_OBJECT (parse, "Invalid duration %lf", num);
2850 GST_DEBUG_OBJECT (parse, "Duration: %lf", num);
2852 dur = gst_gdouble_to_guint64 (num *
2853 gst_guint64_to_gdouble (parse->time_scale));
2854 if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
2855 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME, dur);
2859 case GST_MATROSKA_ID_WRITINGAPP:{
2862 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2865 GST_DEBUG_OBJECT (parse, "WritingApp: %s", GST_STR_NULL (text));
2866 parse->writing_app = text;
2870 case GST_MATROSKA_ID_MUXINGAPP:{
2873 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2876 GST_DEBUG_OBJECT (parse, "MuxingApp: %s", GST_STR_NULL (text));
2877 parse->muxing_app = text;
2881 case GST_MATROSKA_ID_DATEUTC:{
2884 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
2887 GST_DEBUG_OBJECT (parse, "DateUTC: %" G_GINT64_FORMAT, time);
2888 parse->created = time;
2892 case GST_MATROSKA_ID_TITLE:{
2894 GstTagList *taglist;
2896 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2899 GST_DEBUG_OBJECT (parse, "Title: %s", GST_STR_NULL (text));
2900 taglist = gst_tag_list_new ();
2901 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
2903 gst_matroska_parse_found_global_tag (parse, taglist);
2909 ret = gst_matroska_parse_parse_skip (parse, ebml, "SegmentInfo", id);
2913 case GST_MATROSKA_ID_SEGMENTUID:
2914 case GST_MATROSKA_ID_SEGMENTFILENAME:
2915 case GST_MATROSKA_ID_PREVUID:
2916 case GST_MATROSKA_ID_PREVFILENAME:
2917 case GST_MATROSKA_ID_NEXTUID:
2918 case GST_MATROSKA_ID_NEXTFILENAME:
2919 case GST_MATROSKA_ID_SEGMENTFAMILY:
2920 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
2921 ret = gst_ebml_read_skip (ebml);
2926 DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2928 parse->segmentinfo_parsed = TRUE;
2933 static GstFlowReturn
2934 gst_matroska_parse_parse_metadata_id_simple_tag (GstMatroskaParse * parse,
2935 GstEbmlRead * ebml, GstTagList ** p_taglist)
2937 /* FIXME: check if there are more useful mappings */
2940 const gchar *matroska_tagname;
2941 const gchar *gstreamer_tagname;
2945 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2946 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
2947 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2948 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2949 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2950 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2951 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2952 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2953 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2954 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2955 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2956 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2957 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2958 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2959 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2963 gchar *value = NULL;
2966 DEBUG_ELEMENT_START (parse, ebml, "SimpleTag");
2968 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2969 DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
2973 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2974 /* read all sub-entries */
2976 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2980 case GST_MATROSKA_ID_TAGNAME:
2983 ret = gst_ebml_read_ascii (ebml, &id, &tag);
2984 GST_DEBUG_OBJECT (parse, "TagName: %s", GST_STR_NULL (tag));
2987 case GST_MATROSKA_ID_TAGSTRING:
2990 ret = gst_ebml_read_utf8 (ebml, &id, &value);
2991 GST_DEBUG_OBJECT (parse, "TagString: %s", GST_STR_NULL (value));
2995 ret = gst_matroska_parse_parse_skip (parse, ebml, "SimpleTag", id);
2999 case GST_MATROSKA_ID_TAGLANGUAGE:
3000 case GST_MATROSKA_ID_TAGDEFAULT:
3001 case GST_MATROSKA_ID_TAGBINARY:
3002 ret = gst_ebml_read_skip (ebml);
3007 DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
3012 for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
3013 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
3015 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
3017 if (strcmp (tagname_mkv, tag) == 0) {
3018 GValue dest = { 0, };
3019 GType dest_type = gst_tag_get_type (tagname_gst);
3021 /* Ensure that any date string is complete */
3022 if (dest_type == GST_TYPE_DATE) {
3023 guint year = 1901, month = 1, day = 1;
3025 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
3027 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
3029 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
3033 g_value_init (&dest, dest_type);
3034 if (gst_value_deserialize (&dest, value)) {
3035 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
3036 tagname_gst, &dest, NULL);
3038 GST_WARNING_OBJECT (parse, "Can't transform tag '%s' with "
3039 "value '%s' to target type '%s'", tag, value,
3040 g_type_name (dest_type));
3042 g_value_unset (&dest);
3054 static GstFlowReturn
3055 gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse,
3056 GstEbmlRead * ebml, GstTagList ** p_taglist)
3061 DEBUG_ELEMENT_START (parse, ebml, "Tag");
3063 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3064 DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3068 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3069 /* read all sub-entries */
3071 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3075 case GST_MATROSKA_ID_SIMPLETAG:
3076 ret = gst_matroska_parse_parse_metadata_id_simple_tag (parse, ebml,
3081 ret = gst_matroska_parse_parse_skip (parse, ebml, "Tag", id);
3086 DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3091 static GstFlowReturn
3092 gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml)
3094 GstTagList *taglist;
3095 GstFlowReturn ret = GST_FLOW_OK;
3100 curpos = gst_ebml_read_get_pos (ebml);
3102 /* Make sure we don't parse a tags element twice and
3103 * post it's tags twice */
3104 curpos = gst_ebml_read_get_pos (ebml);
3105 for (l = parse->tags_parsed; l; l = l->next) {
3106 guint64 *pos = l->data;
3108 if (*pos == curpos) {
3109 GST_DEBUG_OBJECT (parse, "Skipping already parsed Tags at offset %"
3110 G_GUINT64_FORMAT, curpos);
3115 parse->tags_parsed =
3116 g_list_prepend (parse->tags_parsed, g_slice_new (guint64));
3117 *((guint64 *) parse->tags_parsed->data) = curpos;
3120 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3121 DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3125 taglist = gst_tag_list_new ();
3127 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3128 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3132 case GST_MATROSKA_ID_TAG:
3133 ret = gst_matroska_parse_parse_metadata_id_tag (parse, ebml, &taglist);
3137 ret = gst_matroska_parse_parse_skip (parse, ebml, "Tags", id);
3139 /* FIXME: Use to limit the tags to specific pads */
3140 case GST_MATROSKA_ID_TARGETS:
3141 ret = gst_ebml_read_skip (ebml);
3146 DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3148 gst_matroska_parse_found_global_tag (parse, taglist);
3153 static GstFlowReturn
3154 gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse,
3155 GstEbmlRead * ebml, GstTagList * taglist)
3159 gchar *description = NULL;
3160 gchar *filename = NULL;
3161 gchar *mimetype = NULL;
3162 guint8 *data = NULL;
3163 guint64 datalen = 0;
3165 DEBUG_ELEMENT_START (parse, ebml, "AttachedFile");
3167 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3168 DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3172 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3173 /* read all sub-entries */
3175 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3179 case GST_MATROSKA_ID_FILEDESCRIPTION:
3181 GST_WARNING_OBJECT (parse, "FileDescription can only appear once");
3185 ret = gst_ebml_read_utf8 (ebml, &id, &description);
3186 GST_DEBUG_OBJECT (parse, "FileDescription: %s",
3187 GST_STR_NULL (description));
3189 case GST_MATROSKA_ID_FILENAME:
3191 GST_WARNING_OBJECT (parse, "FileName can only appear once");
3195 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
3197 GST_DEBUG_OBJECT (parse, "FileName: %s", GST_STR_NULL (filename));
3199 case GST_MATROSKA_ID_FILEMIMETYPE:
3201 GST_WARNING_OBJECT (parse, "FileMimeType can only appear once");
3205 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
3206 GST_DEBUG_OBJECT (parse, "FileMimeType: %s", GST_STR_NULL (mimetype));
3208 case GST_MATROSKA_ID_FILEDATA:
3210 GST_WARNING_OBJECT (parse, "FileData can only appear once");
3214 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
3215 GST_DEBUG_OBJECT (parse, "FileData of size %" G_GUINT64_FORMAT,
3220 ret = gst_matroska_parse_parse_skip (parse, ebml, "AttachedFile", id);
3222 case GST_MATROSKA_ID_FILEUID:
3223 ret = gst_ebml_read_skip (ebml);
3228 DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3230 if (filename && mimetype && data && datalen > 0) {
3231 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
3232 GstBuffer *tagbuffer = NULL;
3234 gchar *filename_lc = g_utf8_strdown (filename, -1);
3236 GST_DEBUG_OBJECT (parse, "Creating tag for attachment with filename '%s', "
3237 "mimetype '%s', description '%s', size %" G_GUINT64_FORMAT, filename,
3238 mimetype, GST_STR_NULL (description), datalen);
3240 /* TODO: better heuristics for different image types */
3241 if (strstr (filename_lc, "cover")) {
3242 if (strstr (filename_lc, "back"))
3243 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
3245 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
3246 } else if (g_str_has_prefix (mimetype, "image/") ||
3247 g_str_has_suffix (filename_lc, "png") ||
3248 g_str_has_suffix (filename_lc, "jpg") ||
3249 g_str_has_suffix (filename_lc, "jpeg") ||
3250 g_str_has_suffix (filename_lc, "gif") ||
3251 g_str_has_suffix (filename_lc, "bmp")) {
3252 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
3254 g_free (filename_lc);
3256 /* First try to create an image tag buffer from this */
3257 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
3259 gst_tag_image_data_to_image_buffer (data, datalen, image_type);
3262 image_type = GST_TAG_IMAGE_TYPE_NONE;
3265 /* if this failed create an attachment buffer */
3267 tagbuffer = gst_buffer_new_and_alloc (datalen);
3269 memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen);
3270 GST_BUFFER_SIZE (tagbuffer) = datalen;
3272 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
3274 caps = gst_caps_new_simple (mimetype, NULL);
3275 gst_buffer_set_caps (tagbuffer, caps);
3276 gst_caps_unref (caps);
3279 /* Set filename and description on the caps */
3280 caps = GST_BUFFER_CAPS (tagbuffer);
3281 gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL);
3283 gst_caps_set_simple (caps, "description", G_TYPE_STRING, description,
3286 GST_DEBUG_OBJECT (parse,
3287 "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps);
3289 /* and append to the tag list */
3290 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
3291 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer,
3294 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
3301 g_free (description);
3306 static GstFlowReturn
3307 gst_matroska_parse_parse_attachments (GstMatroskaParse * parse,
3311 GstFlowReturn ret = GST_FLOW_OK;
3312 GstTagList *taglist;
3314 DEBUG_ELEMENT_START (parse, ebml, "Attachments");
3316 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3317 DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3321 taglist = gst_tag_list_new ();
3323 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3324 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3328 case GST_MATROSKA_ID_ATTACHEDFILE:
3329 ret = gst_matroska_parse_parse_attached_file (parse, ebml, taglist);
3333 ret = gst_matroska_parse_parse_skip (parse, ebml, "Attachments", id);
3337 DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3339 if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) {
3340 GST_DEBUG_OBJECT (parse, "Storing attachment tags");
3341 gst_matroska_parse_found_global_tag (parse, taglist);
3343 GST_DEBUG_OBJECT (parse, "No valid attachments found");
3344 gst_tag_list_free (taglist);
3347 parse->attachments_parsed = TRUE;
3352 static GstFlowReturn
3353 gst_matroska_parse_parse_chapters (GstMatroskaParse * parse, GstEbmlRead * ebml)
3356 GstFlowReturn ret = GST_FLOW_OK;
3358 GST_WARNING_OBJECT (parse, "Parsing of chapters not implemented yet");
3360 /* TODO: implement parsing of chapters */
3362 DEBUG_ELEMENT_START (parse, ebml, "Chapters");
3364 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3365 DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3369 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3370 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3375 ret = gst_ebml_read_skip (ebml);
3380 DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3385 * Read signed/unsigned "EBML" numbers.
3386 * Return: number of bytes processed.
3390 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
3392 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
3400 while (read <= 8 && !(total & len_mask)) {
3407 if ((total &= (len_mask - 1)) == len_mask - 1)
3412 if (data[n] == 0xff)
3414 total = (total << 8) | data[n];
3418 if (read == num_ffs && total != 0)
3427 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
3432 /* read as unsigned number first */
3433 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
3437 if (unum == G_MAXUINT64)
3440 *num = unum - ((1 << ((7 * res) - 1)) - 1);
3445 static GstFlowReturn
3446 gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
3447 GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
3448 gboolean is_simpleblock)
3450 GstMatroskaTrackContext *stream = NULL;
3451 GstFlowReturn ret = GST_FLOW_OK;
3452 gboolean readblock = FALSE;
3454 guint64 block_duration = 0;
3455 GstBuffer *buf = NULL;
3456 gint stream_num = -1, n, laces = 0;
3458 gint *lace_size = NULL;
3461 gint64 referenceblock = 0;
3463 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3464 if (!is_simpleblock) {
3465 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
3469 id = GST_MATROSKA_ID_SIMPLEBLOCK;
3473 /* one block inside the group. Note, block parsing is one
3474 * of the harder things, so this code is a bit complicated.
3475 * See http://www.matroska.org/ for documentation. */
3476 case GST_MATROSKA_ID_SIMPLEBLOCK:
3477 case GST_MATROSKA_ID_BLOCK:
3483 gst_buffer_unref (buf);
3486 if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
3489 data = GST_BUFFER_DATA (buf);
3490 size = GST_BUFFER_SIZE (buf);
3492 /* first byte(s): blocknum */
3493 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3498 /* fetch stream from num */
3499 stream_num = gst_matroska_parse_stream_from_num (parse, num);
3500 if (G_UNLIKELY (size < 3)) {
3501 GST_WARNING_OBJECT (parse, "Invalid size %u", size);
3502 /* non-fatal, try next block(group) */
3505 } else if (G_UNLIKELY (stream_num < 0 ||
3506 stream_num >= parse->num_streams)) {
3507 /* let's not give up on a stray invalid track number */
3508 GST_WARNING_OBJECT (parse,
3509 "Invalid stream %d for track number %" G_GUINT64_FORMAT
3510 "; ignoring block", stream_num, num);
3514 stream = g_ptr_array_index (parse->src, stream_num);
3516 /* time (relative to cluster time) */
3517 time = ((gint16) GST_READ_UINT16_BE (data));
3520 flags = GST_READ_UINT8 (data);
3524 GST_LOG_OBJECT (parse, "time %" G_GUINT64_FORMAT ", flags %d", time,
3527 switch ((flags & 0x06) >> 1) {
3528 case 0x0: /* no lacing */
3530 lace_size = g_new (gint, 1);
3531 lace_size[0] = size;
3534 case 0x1: /* xiph lacing */
3535 case 0x2: /* fixed-size lacing */
3536 case 0x3: /* EBML lacing */
3538 goto invalid_lacing;
3539 laces = GST_READ_UINT8 (data) + 1;
3542 lace_size = g_new0 (gint, laces);
3544 switch ((flags & 0x06) >> 1) {
3545 case 0x1: /* xiph lacing */ {
3546 guint temp, total = 0;
3548 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
3551 goto invalid_lacing;
3552 temp = GST_READ_UINT8 (data);
3553 lace_size[n] += temp;
3559 total += lace_size[n];
3561 lace_size[n] = size - total;
3565 case 0x2: /* fixed-size lacing */
3566 for (n = 0; n < laces; n++)
3567 lace_size[n] = size / laces;
3570 case 0x3: /* EBML lacing */ {
3573 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3577 total = lace_size[0] = num;
3578 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
3582 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
3586 lace_size[n] = lace_size[n - 1] + snum;
3587 total += lace_size[n];
3590 lace_size[n] = size - total;
3597 if (ret != GST_FLOW_OK)
3604 case GST_MATROSKA_ID_BLOCKDURATION:{
3605 ret = gst_ebml_read_uint (ebml, &id, &block_duration);
3606 GST_DEBUG_OBJECT (parse, "BlockDuration: %" G_GUINT64_FORMAT,
3611 case GST_MATROSKA_ID_REFERENCEBLOCK:{
3612 ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
3613 GST_DEBUG_OBJECT (parse, "ReferenceBlock: %" G_GINT64_FORMAT,
3618 case GST_MATROSKA_ID_CODECSTATE:{
3620 guint64 data_len = 0;
3623 gst_ebml_read_binary (ebml, &id, &data,
3624 &data_len)) != GST_FLOW_OK)
3627 if (G_UNLIKELY (stream == NULL)) {
3628 GST_WARNING_OBJECT (parse,
3629 "Unexpected CodecState subelement - ignoring");
3633 g_free (stream->codec_state);
3634 stream->codec_state = data;
3635 stream->codec_state_size = data_len;
3641 ret = gst_matroska_parse_parse_skip (parse, ebml, "BlockGroup", id);
3644 case GST_MATROSKA_ID_BLOCKVIRTUAL:
3645 case GST_MATROSKA_ID_BLOCKADDITIONS:
3646 case GST_MATROSKA_ID_REFERENCEPRIORITY:
3647 case GST_MATROSKA_ID_REFERENCEVIRTUAL:
3648 case GST_MATROSKA_ID_SLICES:
3649 GST_DEBUG_OBJECT (parse,
3650 "Skipping BlockGroup subelement 0x%x - ignoring", id);
3651 ret = gst_ebml_read_skip (ebml);
3659 /* reading a number or so could have failed */
3660 if (ret != GST_FLOW_OK)
3663 if (ret == GST_FLOW_OK && readblock) {
3664 guint64 duration = 0;
3665 gint64 lace_time = 0;
3666 gboolean delta_unit;
3668 stream = g_ptr_array_index (parse->src, stream_num);
3670 if (cluster_time != GST_CLOCK_TIME_NONE) {
3671 /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
3672 * Drop unless the lace contains timestamp 0? */
3673 if (time < 0 && (-time) > cluster_time) {
3676 if (stream->timecodescale == 1.0)
3677 lace_time = (cluster_time + time) * parse->time_scale;
3680 gst_util_guint64_to_gdouble ((cluster_time + time) *
3681 parse->time_scale) * stream->timecodescale;
3684 lace_time = GST_CLOCK_TIME_NONE;
3687 if (lace_time != GST_CLOCK_TIME_NONE) {
3688 parse->last_timestamp = lace_time;
3690 /* need to refresh segment info ASAP */
3691 if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
3692 GST_DEBUG_OBJECT (parse,
3693 "generating segment starting at %" GST_TIME_FORMAT,
3694 GST_TIME_ARGS (lace_time));
3695 /* pretend we seeked here */
3696 gst_segment_set_seek (&parse->segment, parse->segment.rate,
3697 GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
3698 GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
3699 /* now convey our segment notion downstream */
3700 gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE,
3701 parse->segment.rate, parse->segment.format, parse->segment.start,
3702 parse->segment.stop, parse->segment.start));
3703 parse->need_newsegment = FALSE;
3706 if (block_duration) {
3707 if (stream->timecodescale == 1.0)
3708 duration = gst_util_uint64_scale (block_duration, parse->time_scale, 1);
3711 gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
3712 (gst_util_uint64_scale (block_duration, parse->time_scale,
3713 1)) * stream->timecodescale);
3714 } else if (stream->default_duration) {
3715 duration = stream->default_duration * laces;
3717 /* else duration is diff between timecode of this and next block */
3719 /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
3720 a ReferenceBlock implies that this is not a keyframe. In either
3721 case, it only makes sense for video streams. */
3722 delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3723 ((is_simpleblock && !(flags & 0x80)) || referenceblock);
3725 if (delta_unit && stream->set_discont) {
3726 /* When doing seeks or such, we need to restart on key frames or
3727 * decoders might choke. */
3728 GST_DEBUG_OBJECT (parse, "skipping delta unit");
3732 for (n = 0; n < laces; n++) {
3733 if (G_UNLIKELY (lace_size[n] > size)) {
3734 GST_WARNING_OBJECT (parse, "Invalid lace size");
3738 /* QoS for video track with an index. the assumption is that
3739 index entries point to keyframes, but if that is not true we
3740 will instad skip until the next keyframe. */
3741 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3742 stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3743 stream->index_table && parse->segment.rate > 0.0) {
3744 GstMatroskaTrackVideoContext *videocontext =
3745 (GstMatroskaTrackVideoContext *) stream;
3746 GstClockTime earliest_time;
3747 GstClockTime earliest_stream_time;
3749 GST_OBJECT_LOCK (parse);
3750 earliest_time = videocontext->earliest_time;
3751 GST_OBJECT_UNLOCK (parse);
3752 earliest_stream_time = gst_segment_to_position (&parse->segment,
3753 GST_FORMAT_TIME, earliest_time);
3755 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3756 GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
3757 lace_time <= earliest_stream_time) {
3758 /* find index entry (keyframe) <= earliest_stream_time */
3759 GstMatroskaIndex *entry =
3760 gst_util_array_binary_search (stream->index_table->data,
3761 stream->index_table->len, sizeof (GstMatroskaIndex),
3762 (GCompareDataFunc) gst_matroska_index_seek_find,
3763 GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
3765 /* if that entry (keyframe) is after the current the current
3766 buffer, we can skip pushing (and thus decoding) all
3767 buffers until that keyframe. */
3768 if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
3769 entry->time > lace_time) {
3770 GST_LOG_OBJECT (parse, "Skipping lace before late keyframe");
3771 stream->set_discont = TRUE;
3777 sub = gst_buffer_create_sub (buf,
3778 GST_BUFFER_SIZE (buf) - size, lace_size[n]);
3779 GST_DEBUG_OBJECT (parse, "created subbuffer %p", sub);
3782 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3784 GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3786 if (stream->encodings != NULL && stream->encodings->len > 0)
3787 sub = gst_matroska_decode_buffer (stream, sub);
3790 GST_WARNING_OBJECT (parse, "Decoding buffer failed");
3794 GST_BUFFER_TIMESTAMP (sub) = lace_time;
3796 if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
3797 GstClockTime last_stop_end;
3799 /* Check if this stream is after segment stop */
3800 if (GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
3801 lace_time >= parse->segment.stop) {
3802 GST_DEBUG_OBJECT (parse,
3803 "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
3804 GST_TIME_ARGS (parse->segment.stop));
3805 gst_buffer_unref (sub);
3808 if (offset >= stream->to_offset) {
3809 GST_DEBUG_OBJECT (parse, "Stream %d after playback section",
3811 gst_buffer_unref (sub);
3815 /* handle gaps, e.g. non-zero start-time, or an cue index entry
3816 * that landed us with timestamps not quite intended */
3817 if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
3818 parse->segment.rate > 0.0) {
3819 GstClockTimeDiff diff;
3821 /* only send newsegments with increasing start times,
3822 * otherwise if these go back and forth downstream (sinks) increase
3823 * accumulated time and running_time */
3824 diff = GST_CLOCK_DIFF (parse->segment.last_stop, lace_time);
3825 if (diff > 2 * GST_SECOND && lace_time > parse->segment.start &&
3826 (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
3827 lace_time < parse->segment.stop)) {
3828 GST_DEBUG_OBJECT (parse,
3829 "Gap of %" G_GINT64_FORMAT " ns detected in"
3830 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
3831 "Sending updated NEWSEGMENT events", diff,
3832 stream->index, GST_TIME_ARGS (stream->pos),
3833 GST_TIME_ARGS (lace_time));
3834 /* send newsegment events such that the gap is not accounted in
3835 * accum time, hence running_time */
3836 /* close ahead of gap */
3837 gst_matroska_parse_send_event (parse,
3838 gst_event_new_new_segment (TRUE, parse->segment.rate,
3839 parse->segment.format, parse->segment.last_stop,
3840 parse->segment.last_stop, parse->segment.last_stop));
3842 gst_matroska_parse_send_event (parse,
3843 gst_event_new_new_segment (FALSE, parse->segment.rate,
3844 parse->segment.format, lace_time, parse->segment.stop,
3846 /* align segment view with downstream,
3847 * prevents double-counting accum when closing segment */
3848 gst_segment_set_newsegment (&parse->segment, FALSE,
3849 parse->segment.rate, parse->segment.format, lace_time,
3850 parse->segment.stop, lace_time);
3851 parse->segment.last_stop = lace_time;
3855 if (!GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)
3856 || parse->segment.last_stop < lace_time) {
3857 parse->segment.last_stop = lace_time;
3860 last_stop_end = lace_time;
3862 GST_BUFFER_DURATION (sub) = duration / laces;
3863 last_stop_end += GST_BUFFER_DURATION (sub);
3866 if (!GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) ||
3867 parse->last_stop_end < last_stop_end)
3868 parse->last_stop_end = last_stop_end;
3870 if (parse->segment.duration == -1 ||
3871 parse->segment.duration < lace_time) {
3872 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME,
3874 gst_element_post_message (GST_ELEMENT_CAST (parse),
3875 gst_message_new_duration (GST_OBJECT_CAST (parse),
3876 GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
3880 stream->pos = lace_time;
3882 gst_matroska_parse_sync_streams (parse);
3884 if (stream->set_discont) {
3885 GST_DEBUG_OBJECT (parse, "marking DISCONT");
3886 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
3887 stream->set_discont = FALSE;
3890 /* reverse playback book-keeping */
3891 if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
3892 stream->from_time = lace_time;
3893 if (stream->from_offset == -1)
3894 stream->from_offset = offset;
3896 GST_DEBUG_OBJECT (parse,
3897 "Pushing lace %d, data of size %d for stream %d, time=%"
3898 GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
3899 GST_BUFFER_SIZE (sub), stream_num,
3900 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
3901 GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
3903 if (parse->element_index) {
3904 if (stream->index_writer_id == -1)
3905 gst_index_get_writer_id (parse->element_index,
3906 GST_OBJECT (stream->pad), &stream->index_writer_id);
3908 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
3909 G_GUINT64_FORMAT " for writer id %d",
3910 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
3911 stream->index_writer_id);
3912 gst_index_add_association (parse->element_index,
3913 stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
3914 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
3915 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
3916 cluster_offset, NULL);
3919 gst_buffer_set_caps (sub, GST_PAD_CAPS (parse->srcpad));
3921 /* Postprocess the buffers depending on the codec used */
3922 if (stream->postprocess_frame) {
3923 GST_LOG_OBJECT (parse, "running post process");
3924 ret = stream->postprocess_frame (GST_ELEMENT (parse), stream, &sub);
3927 ret = gst_pad_push (stream->pad, sub);
3928 if (parse->segment.rate < 0) {
3929 if (lace_time > parse->segment.stop && ret == GST_FLOW_UNEXPECTED) {
3930 /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
3931 * we are at the end of the segment, so we just need to jump
3932 * back to the previous section. */
3933 GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
3938 ret = gst_matroska_parse_combine_flows (parse, stream, ret);
3942 size -= lace_size[n];
3943 if (lace_time != GST_CLOCK_TIME_NONE && duration)
3944 lace_time += duration / laces;
3946 lace_time = GST_CLOCK_TIME_NONE;
3952 gst_buffer_unref (buf);
3960 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
3961 /* non-fatal, try next block(group) */
3967 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Data error"));
3968 /* non-fatal, try next block(group) */
3974 /* return FALSE if block(group) should be skipped (due to a seek) */
3975 static inline gboolean
3976 gst_matroska_parse_seek_block (GstMatroskaParse * parse)
3978 if (G_UNLIKELY (parse->seek_block)) {
3979 if (!(--parse->seek_block)) {
3982 GST_LOG_OBJECT (parse, "should skip block due to seek");
3990 static GstFlowReturn
3991 gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
3995 guint64 seek_pos = (guint64) - 1;
3996 guint32 seek_id = 0;
3999 DEBUG_ELEMENT_START (parse, ebml, "Seek");
4001 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4002 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4006 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4007 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4011 case GST_MATROSKA_ID_SEEKID:
4015 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4018 GST_DEBUG_OBJECT (parse, "SeekID: %" G_GUINT64_FORMAT, t);
4023 case GST_MATROSKA_ID_SEEKPOSITION:
4027 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4030 if (t > G_MAXINT64) {
4031 GST_WARNING_OBJECT (parse,
4032 "Too large SeekPosition %" G_GUINT64_FORMAT, t);
4036 GST_DEBUG_OBJECT (parse, "SeekPosition: %" G_GUINT64_FORMAT, t);
4042 ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4047 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
4050 if (!seek_id || seek_pos == (guint64) - 1) {
4051 GST_WARNING_OBJECT (parse, "Incomplete seekhead entry (0x%x/%"
4052 G_GUINT64_FORMAT ")", seek_id, seek_pos);
4057 case GST_MATROSKA_ID_SEEKHEAD:
4060 case GST_MATROSKA_ID_CUES:
4061 case GST_MATROSKA_ID_TAGS:
4062 case GST_MATROSKA_ID_TRACKS:
4063 case GST_MATROSKA_ID_SEGMENTINFO:
4064 case GST_MATROSKA_ID_ATTACHMENTS:
4065 case GST_MATROSKA_ID_CHAPTERS:
4070 length = gst_matroska_parse_get_length (parse);
4072 if (length == (guint64) - 1) {
4073 GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
4077 /* check for validity */
4078 if (seek_pos + parse->ebml_segment_start + 12 >= length) {
4079 GST_WARNING_OBJECT (parse,
4080 "SeekHead reference lies outside file!" " (%"
4081 G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
4082 G_GUINT64_FORMAT ")", seek_pos, parse->ebml_segment_start, length);
4086 /* only pick up index location when streaming */
4087 if (seek_id == GST_MATROSKA_ID_CUES) {
4088 parse->index_offset = seek_pos + parse->ebml_segment_start;
4089 GST_DEBUG_OBJECT (parse, "Cues located at offset %" G_GUINT64_FORMAT,
4090 parse->index_offset);
4096 GST_DEBUG_OBJECT (parse, "Ignoring Seek entry for ID=0x%x", seek_id);
4099 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4104 static GstFlowReturn
4105 gst_matroska_parse_parse_contents (GstMatroskaParse * parse, GstEbmlRead * ebml)
4107 GstFlowReturn ret = GST_FLOW_OK;
4110 DEBUG_ELEMENT_START (parse, ebml, "SeekHead");
4112 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4113 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4117 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4118 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4122 case GST_MATROSKA_ID_SEEKENTRY:
4124 ret = gst_matroska_parse_parse_contents_seekentry (parse, ebml);
4125 /* Ignore EOS and errors here */
4126 if (ret != GST_FLOW_OK) {
4127 GST_DEBUG_OBJECT (parse, "Ignoring %s", gst_flow_get_name (ret));
4134 ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4139 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4144 #define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
4146 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
4148 static inline GstFlowReturn
4149 gst_matroska_parse_check_read_size (GstMatroskaParse * parse, guint64 bytes)
4151 if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
4152 /* only a few blocks are expected/allowed to be large,
4153 * and will be recursed into, whereas others will be read and must fit */
4154 /* fatal in streaming case, as we can't step over easily */
4155 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4156 ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
4157 "file might be corrupt.", bytes));
4158 return GST_FLOW_ERROR;
4164 /* returns TRUE if we truely are in error state, and should give up */
4165 static inline gboolean
4166 gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
4170 /* sigh, one last attempt above and beyond call of duty ...;
4171 * search for cluster mark following current pos */
4172 pos = parse->offset;
4173 GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
4174 if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
4175 /* did not work, give up */
4178 GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
4179 /* try that position */
4180 parse->offset = pos;
4185 /* initializes @ebml with @bytes from input stream at current offset.
4186 * Returns UNEXPECTED if insufficient available,
4187 * ERROR if too much was attempted to read. */
4188 static inline GstFlowReturn
4189 gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
4192 GstBuffer *buffer = NULL;
4193 GstFlowReturn ret = GST_FLOW_OK;
4195 GST_LOG_OBJECT (parse, "taking %" G_GUINT64_FORMAT " bytes for parsing",
4197 ret = gst_matroska_parse_check_read_size (parse, bytes);
4198 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
4199 /* otherwise fatal */
4200 ret = GST_FLOW_ERROR;
4203 if (gst_adapter_available (parse->adapter) >= bytes)
4204 buffer = gst_adapter_take_buffer (parse->adapter, bytes);
4206 ret = GST_FLOW_UNEXPECTED;
4207 if (G_LIKELY (buffer)) {
4208 gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, parse->offset);
4209 parse->offset += bytes;
4216 gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
4219 gboolean seekable = FALSE;
4220 gint64 start = -1, stop = -1;
4222 query = gst_query_new_seeking (GST_FORMAT_BYTES);
4223 if (!gst_pad_peer_query (parse->sinkpad, query)) {
4224 GST_DEBUG_OBJECT (parse, "seeking query failed");
4228 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
4230 /* try harder to query upstream size if we didn't get it the first time */
4231 if (seekable && stop == -1) {
4232 GstFormat fmt = GST_FORMAT_BYTES;
4234 GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
4235 gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
4238 /* if upstream doesn't know the size, it's likely that it's not seekable in
4239 * practice even if it technically may be seekable */
4240 if (seekable && (start != 0 || stop <= start)) {
4241 GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
4246 GST_INFO_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
4247 G_GUINT64_FORMAT ")", seekable, start, stop);
4248 parse->seekable = seekable;
4250 gst_query_unref (query);
4254 static GstFlowReturn
4255 gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
4261 GstFlowReturn ret = GST_FLOW_OK;
4263 GST_WARNING_OBJECT (parse,
4264 "Found Cluster element before Tracks, searching Tracks");
4267 before_pos = parse->offset;
4269 /* Search Tracks element */
4271 ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4272 if (ret != GST_FLOW_OK)
4275 if (id != GST_MATROSKA_ID_TRACKS) {
4276 /* we may be skipping large cluster here, so forego size check etc */
4277 /* ... but we can't skip undefined size; force error */
4278 if (length == G_MAXUINT64) {
4279 ret = gst_matroska_parse_check_read_size (parse, length);
4282 parse->offset += needed;
4283 parse->offset += length;
4288 /* will lead to track parsing ... */
4289 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4294 parse->offset = before_pos;
4300 #define GST_READ_CHECK(stmt) \
4302 if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
4303 if (ret == GST_FLOW_OVERFLOW) { \
4304 ret = GST_FLOW_OK; \
4311 gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
4314 if (parse->streamheader) {
4317 buf = gst_buffer_span (parse->streamheader, 0, buffer,
4318 GST_BUFFER_SIZE (parse->streamheader) + GST_BUFFER_SIZE (buffer));
4319 gst_buffer_unref (parse->streamheader);
4320 parse->streamheader = buf;
4322 parse->streamheader = gst_buffer_ref (buffer);
4325 GST_DEBUG ("%d", GST_BUFFER_SIZE (parse->streamheader));
4328 static GstFlowReturn
4329 gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
4332 GstFlowReturn ret = GST_FLOW_OK;
4334 if (!parse->pushed_headers) {
4337 GValue streamheader = { 0 };
4338 GValue bufval = { 0 };
4341 caps = gst_caps_new_simple ("video/x-matroska", NULL);
4342 s = gst_caps_get_structure (caps, 0);
4343 g_value_init (&streamheader, GST_TYPE_ARRAY);
4344 g_value_init (&bufval, GST_TYPE_BUFFER);
4345 GST_BUFFER_FLAG_SET (parse->streamheader, GST_BUFFER_FLAG_IN_CAPS);
4346 gst_value_set_buffer (&bufval, parse->streamheader);
4347 gst_value_array_append_value (&streamheader, &bufval);
4348 g_value_unset (&bufval);
4349 gst_structure_set_value (s, "streamheader", &streamheader);
4350 g_value_unset (&streamheader);
4351 //gst_caps_replace (parse->caps, caps);
4352 gst_pad_set_caps (parse->srcpad, caps);
4354 buf = gst_buffer_make_metadata_writable (parse->streamheader);
4355 gst_buffer_set_caps (buf, caps);
4356 gst_caps_unref (caps);
4358 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4359 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
4360 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4362 ret = gst_pad_push (parse->srcpad, buf);
4364 parse->pushed_headers = TRUE;
4368 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4370 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4372 if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
4373 parse->last_timestamp = GST_BUFFER_TIMESTAMP (buffer);
4375 GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
4377 gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
4378 ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
4383 static GstFlowReturn
4384 gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
4385 guint64 length, guint needed)
4387 GstEbmlRead ebml = { 0, };
4388 GstFlowReturn ret = GST_FLOW_OK;
4390 //GstBuffer *buffer;
4392 GST_DEBUG_OBJECT (parse, "Parsing Element id 0x%x, "
4393 "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
4396 if (gst_adapter_available (parse->adapter) >= length + needed) {
4397 buffer = gst_adapter_take_buffer (parse->adapter, length + needed);
4398 gst_pad_push (parse->srcpad, buffer);
4400 ret = GST_FLOW_UNEXPECTED;
4402 //GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4409 /* if we plan to read and parse this element, we need prefix (id + length)
4410 * and the contents */
4411 /* mind about overflow wrap-around when dealing with undefined size */
4413 if (G_LIKELY (length != G_MAXUINT64))
4416 switch (parse->state) {
4417 case GST_MATROSKA_PARSE_STATE_START:
4419 case GST_EBML_ID_HEADER:
4420 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4421 ret = gst_matroska_parse_parse_header (parse, &ebml);
4422 if (ret != GST_FLOW_OK)
4424 parse->state = GST_MATROSKA_PARSE_STATE_SEGMENT;
4425 gst_matroska_parse_check_seekability (parse);
4426 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4429 goto invalid_header;
4433 case GST_MATROSKA_PARSE_STATE_SEGMENT:
4435 case GST_MATROSKA_ID_SEGMENT:
4436 /* eat segment prefix */
4437 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4438 GST_DEBUG_OBJECT (parse,
4439 "Found Segment start at offset %" G_GUINT64_FORMAT,
4441 /* seeks are from the beginning of the segment,
4442 * after the segment ID/length */
4443 parse->ebml_segment_start = parse->offset;
4444 parse->state = GST_MATROSKA_PARSE_STATE_HEADER;
4445 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4448 GST_WARNING_OBJECT (parse,
4449 "Expected a Segment ID (0x%x), but received 0x%x!",
4450 GST_MATROSKA_ID_SEGMENT, id);
4451 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4452 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4456 case GST_MATROSKA_PARSE_STATE_SCANNING:
4457 if (id != GST_MATROSKA_ID_CLUSTER &&
4458 id != GST_MATROSKA_ID_CLUSTERTIMECODE)
4461 case GST_MATROSKA_PARSE_STATE_HEADER:
4462 case GST_MATROSKA_PARSE_STATE_DATA:
4463 case GST_MATROSKA_PARSE_STATE_SEEK:
4465 case GST_MATROSKA_ID_SEGMENTINFO:
4466 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4467 if (!parse->segmentinfo_parsed) {
4468 ret = gst_matroska_parse_parse_info (parse, &ebml);
4470 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4472 case GST_MATROSKA_ID_TRACKS:
4473 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4474 if (!parse->tracks_parsed) {
4475 ret = gst_matroska_parse_parse_tracks (parse, &ebml);
4477 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4479 case GST_MATROSKA_ID_CLUSTER:
4480 if (G_UNLIKELY (!parse->tracks_parsed)) {
4481 GST_DEBUG_OBJECT (parse, "Cluster before Track");
4482 goto not_streamable;
4484 if (G_UNLIKELY (parse->state == GST_MATROSKA_PARSE_STATE_HEADER)) {
4485 parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4486 parse->first_cluster_offset = parse->offset;
4487 GST_DEBUG_OBJECT (parse, "signaling no more pads");
4489 parse->cluster_time = GST_CLOCK_TIME_NONE;
4490 parse->cluster_offset = parse->offset;
4491 if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
4492 GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
4493 " not found in Cluster, trying next Cluster's first block instead",
4495 parse->seek_block = 0;
4497 parse->seek_first = FALSE;
4498 /* record next cluster for recovery */
4499 if (read != G_MAXUINT64)
4500 parse->next_cluster_offset = parse->cluster_offset + read;
4501 /* eat cluster prefix */
4502 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4503 ret = gst_matroska_parse_output (parse, ebml.buf, TRUE);
4504 //gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4506 case GST_MATROSKA_ID_CLUSTERTIMECODE:
4510 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4511 if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
4513 GST_DEBUG_OBJECT (parse, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
4514 parse->cluster_time = num;
4515 if (parse->element_index) {
4516 if (parse->element_index_writer_id == -1)
4517 gst_index_get_writer_id (parse->element_index,
4518 GST_OBJECT (parse), &parse->element_index_writer_id);
4519 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
4520 G_GUINT64_FORMAT " for writer id %d",
4521 GST_TIME_ARGS (parse->cluster_time), parse->cluster_offset,
4522 parse->element_index_writer_id);
4523 gst_index_add_association (parse->element_index,
4524 parse->element_index_writer_id, GST_ASSOCIATION_FLAG_KEY_UNIT,
4525 GST_FORMAT_TIME, parse->cluster_time,
4526 GST_FORMAT_BYTES, parse->cluster_offset, NULL);
4528 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4531 case GST_MATROSKA_ID_BLOCKGROUP:
4532 if (!gst_matroska_parse_seek_block (parse))
4534 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4535 DEBUG_ELEMENT_START (parse, &ebml, "BlockGroup");
4536 if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
4537 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4538 &ebml, parse->cluster_time, parse->cluster_offset, FALSE);
4540 DEBUG_ELEMENT_STOP (parse, &ebml, "BlockGroup", ret);
4541 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4543 case GST_MATROSKA_ID_SIMPLEBLOCK:
4544 if (!gst_matroska_parse_seek_block (parse))
4546 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4547 DEBUG_ELEMENT_START (parse, &ebml, "SimpleBlock");
4548 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4549 &ebml, parse->cluster_time, parse->cluster_offset, TRUE);
4550 DEBUG_ELEMENT_STOP (parse, &ebml, "SimpleBlock", ret);
4551 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4553 case GST_MATROSKA_ID_ATTACHMENTS:
4554 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4555 if (!parse->attachments_parsed) {
4556 ret = gst_matroska_parse_parse_attachments (parse, &ebml);
4558 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4560 case GST_MATROSKA_ID_TAGS:
4561 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4562 ret = gst_matroska_parse_parse_metadata (parse, &ebml);
4563 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4565 case GST_MATROSKA_ID_CHAPTERS:
4566 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4567 ret = gst_matroska_parse_parse_chapters (parse, &ebml);
4568 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4570 case GST_MATROSKA_ID_SEEKHEAD:
4571 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4572 ret = gst_matroska_parse_parse_contents (parse, &ebml);
4573 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4575 case GST_MATROSKA_ID_CUES:
4576 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4577 if (!parse->index_parsed) {
4578 ret = gst_matroska_parse_parse_index (parse, &ebml);
4579 /* only push based; delayed index building */
4580 if (ret == GST_FLOW_OK
4581 && parse->state == GST_MATROSKA_PARSE_STATE_SEEK) {
4584 GST_OBJECT_LOCK (parse);
4585 event = parse->seek_event;
4586 parse->seek_event = NULL;
4587 GST_OBJECT_UNLOCK (parse);
4590 /* unlikely to fail, since we managed to seek to this point */
4591 if (!gst_matroska_parse_handle_seek_event (parse, NULL, event))
4593 /* resume data handling, main thread clear to seek again */
4594 GST_OBJECT_LOCK (parse);
4595 parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4596 GST_OBJECT_UNLOCK (parse);
4599 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4601 case GST_MATROSKA_ID_POSITION:
4602 case GST_MATROSKA_ID_PREVSIZE:
4603 case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
4604 case GST_MATROSKA_ID_SILENTTRACKS:
4605 GST_DEBUG_OBJECT (parse,
4606 "Skipping Cluster subelement 0x%x - ignoring", id);
4610 GST_DEBUG_OBJECT (parse, "skipping Element 0x%x", id);
4611 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4612 gst_matroska_parse_output (parse, ebml.buf, FALSE);
4618 if (ret == GST_FLOW_PARSE)
4622 gst_ebml_read_clear (&ebml);
4628 /* simply exit, maybe not enough data yet */
4629 /* no ebml to clear if read error */
4634 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4635 ("Failed to parse Element 0x%x", id));
4636 ret = GST_FLOW_ERROR;
4641 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4642 ("File layout does not permit streaming"));
4643 ret = GST_FLOW_ERROR;
4649 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4650 ("No Tracks element found"));
4651 ret = GST_FLOW_ERROR;
4657 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Invalid header"));
4658 ret = GST_FLOW_ERROR;
4663 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Failed to seek"));
4664 ret = GST_FLOW_ERROR;
4671 gst_matroska_parse_loop (GstPad * pad)
4673 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4679 /* If we have to close a segment, send a new segment to do this now */
4680 if (G_LIKELY (parse->state == GST_MATROSKA_PARSE_STATE_DATA)) {
4681 if (G_UNLIKELY (parse->close_segment)) {
4682 gst_matroska_parse_send_event (parse, parse->close_segment);
4683 parse->close_segment = NULL;
4685 if (G_UNLIKELY (parse->new_segment)) {
4686 gst_matroska_parse_send_event (parse, parse->new_segment);
4687 parse->new_segment = NULL;
4691 ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4692 if (ret == GST_FLOW_UNEXPECTED)
4694 if (ret != GST_FLOW_OK) {
4695 if (gst_matroska_parse_check_parse_error (parse))
4701 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4702 "size %" G_GUINT64_FORMAT ", needed %d", parse->offset, id,
4705 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4706 if (ret == GST_FLOW_UNEXPECTED)
4708 if (ret != GST_FLOW_OK)
4711 /* check if we're at the end of a configured segment */
4712 if (G_LIKELY (parse->src->len)) {
4715 g_assert (parse->num_streams == parse->src->len);
4716 for (i = 0; i < parse->src->len; i++) {
4717 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
4718 GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
4719 GST_TIME_ARGS (context->pos));
4720 if (context->eos == FALSE)
4724 GST_INFO_OBJECT (parse, "All streams are EOS");
4725 ret = GST_FLOW_UNEXPECTED;
4730 if (G_UNLIKELY (parse->offset == gst_matroska_parse_get_length (parse))) {
4731 GST_LOG_OBJECT (parse, "Reached end of stream");
4732 ret = GST_FLOW_UNEXPECTED;
4741 if (parse->segment.rate < 0.0) {
4742 ret = gst_matroska_parse_seek_to_previous_keyframe (parse);
4743 if (ret == GST_FLOW_OK)
4750 const gchar *reason = gst_flow_get_name (ret);
4751 gboolean push_eos = FALSE;
4753 GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
4754 parse->segment_running = FALSE;
4755 gst_pad_pause_task (parse->sinkpad);
4757 if (ret == GST_FLOW_UNEXPECTED) {
4758 /* perform EOS logic */
4760 /* Close the segment, i.e. update segment stop with the duration
4761 * if no stop was set */
4762 if (GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) &&
4763 !GST_CLOCK_TIME_IS_VALID (parse->segment.stop)) {
4765 gst_event_new_new_segment_full (TRUE, parse->segment.rate,
4766 parse->segment.applied_rate, parse->segment.format,
4767 parse->segment.start,
4768 MAX (parse->last_stop_end, parse->segment.start),
4769 parse->segment.time);
4770 gst_matroska_parse_send_event (parse, event);
4773 if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
4776 /* for segment playback we need to post when (in stream time)
4777 * we stopped, this is either stop (when set) or the duration. */
4778 if ((stop = parse->segment.stop) == -1)
4779 stop = parse->last_stop_end;
4781 GST_LOG_OBJECT (parse, "Sending segment done, at end of segment");
4782 gst_element_post_message (GST_ELEMENT (parse),
4783 gst_message_new_segment_done (GST_OBJECT (parse), GST_FORMAT_TIME,
4788 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
4789 /* for fatal errors we post an error message */
4790 GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
4791 ("stream stopped, reason %s", reason));
4795 /* send EOS, and prevent hanging if no streams yet */
4796 GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
4797 if (!gst_matroska_parse_send_event (parse, gst_event_new_eos ()) &&
4798 (ret == GST_FLOW_UNEXPECTED)) {
4799 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4800 (NULL), ("got eos but no streams (yet)"));
4809 * Create and push a flushing seek event upstream
4812 perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
4817 GST_DEBUG_OBJECT (parse, "Seeking to %" G_GUINT64_FORMAT, offset);
4820 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
4821 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
4822 GST_SEEK_TYPE_NONE, -1);
4824 res = gst_pad_push_event (parse->sinkpad, event);
4826 /* newsegment event will update offset */
4830 static const guint8 *
4831 gst_matroska_parse_peek_adapter (GstMatroskaParse * parse, guint peek)
4833 return gst_adapter_peek (parse->adapter, peek);
4836 static GstFlowReturn
4837 gst_matroska_parse_peek_id_length_push (GstMatroskaParse * parse, guint32 * _id,
4838 guint64 * _length, guint * _needed)
4840 return gst_ebml_peek_id_length (_id, _length, _needed,
4841 (GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse,
4842 GST_ELEMENT_CAST (parse), parse->offset);
4845 static GstFlowReturn
4846 gst_matroska_parse_chain (GstPad * pad, GstBuffer * buffer)
4848 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4850 GstFlowReturn ret = GST_FLOW_OK;
4855 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
4856 GST_DEBUG_OBJECT (parse, "got DISCONT");
4857 gst_adapter_clear (parse->adapter);
4858 GST_OBJECT_LOCK (parse);
4859 gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, FALSE);
4860 GST_OBJECT_UNLOCK (parse);
4863 gst_adapter_push (parse->adapter, buffer);
4867 available = gst_adapter_available (parse->adapter);
4869 ret = gst_matroska_parse_peek_id_length_push (parse, &id, &length, &needed);
4870 if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED))
4873 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4874 "size %" G_GUINT64_FORMAT ", needed %d, available %d", parse->offset, id,
4875 length, needed, available);
4877 if (needed > available)
4880 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4881 if (ret == GST_FLOW_UNEXPECTED) {
4882 /* need more data */
4884 } else if (ret != GST_FLOW_OK) {
4891 gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
4893 gboolean res = TRUE;
4894 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4896 GST_DEBUG_OBJECT (parse,
4897 "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
4899 switch (GST_EVENT_TYPE (event)) {
4900 case GST_EVENT_NEWSEGMENT:
4903 gdouble rate, arate;
4904 gint64 start, stop, time = 0;
4908 /* some debug output */
4909 gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
4910 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
4911 &start, &stop, &time);
4912 gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
4914 GST_DEBUG_OBJECT (parse,
4915 "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
4918 if (parse->state < GST_MATROSKA_PARSE_STATE_DATA) {
4919 GST_DEBUG_OBJECT (parse, "still starting");
4923 /* we only expect a BYTE segment, e.g. following a seek */
4924 if (format != GST_FORMAT_BYTES) {
4925 GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
4929 GST_DEBUG_OBJECT (parse, "clearing segment state");
4930 /* clear current segment leftover */
4931 gst_adapter_clear (parse->adapter);
4932 /* and some streaming setup */
4933 parse->offset = start;
4934 /* do not know where we are;
4935 * need to come across a cluster and generate newsegment */
4936 parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4937 parse->cluster_time = GST_CLOCK_TIME_NONE;
4938 parse->cluster_offset = 0;
4939 parse->need_newsegment = TRUE;
4940 /* but keep some of the upstream segment */
4941 parse->segment.rate = rate;
4943 /* chain will send initial newsegment after pads have been added,
4944 * or otherwise come up with one */
4945 GST_DEBUG_OBJECT (parse, "eating event");
4946 gst_event_unref (event);
4952 if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
4953 gst_event_unref (event);
4954 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4955 (NULL), ("got eos and didn't receive a complete header object"));
4956 } else if (parse->num_streams == 0) {
4957 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4958 (NULL), ("got eos but no streams (yet)"));
4960 gst_matroska_parse_send_event (parse, event);
4964 case GST_EVENT_FLUSH_STOP:
4966 gst_adapter_clear (parse->adapter);
4967 GST_OBJECT_LOCK (parse);
4968 gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, TRUE);
4969 GST_OBJECT_UNLOCK (parse);
4970 parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4971 parse->cluster_time = GST_CLOCK_TIME_NONE;
4972 parse->cluster_offset = 0;
4976 res = gst_pad_event_default (pad, event);
4984 gst_matroska_parse_set_index (GstElement * element, GstIndex * index)
4986 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
4988 GST_OBJECT_LOCK (parse);
4989 if (parse->element_index)
4990 gst_object_unref (parse->element_index);
4991 parse->element_index = index ? gst_object_ref (index) : NULL;
4992 GST_OBJECT_UNLOCK (parse);
4993 GST_DEBUG_OBJECT (parse, "Set index %" GST_PTR_FORMAT, parse->element_index);
4997 gst_matroska_parse_get_index (GstElement * element)
4999 GstIndex *result = NULL;
5000 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5002 GST_OBJECT_LOCK (parse);
5003 if (parse->element_index)
5004 result = gst_object_ref (parse->element_index);
5005 GST_OBJECT_UNLOCK (parse);
5007 GST_DEBUG_OBJECT (parse, "Returning index %" GST_PTR_FORMAT, result);
5012 static GstStateChangeReturn
5013 gst_matroska_parse_change_state (GstElement * element,
5014 GstStateChange transition)
5016 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5017 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
5019 /* handle upwards state changes here */
5020 switch (transition) {
5025 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5027 /* handle downwards state changes */
5028 switch (transition) {
5029 case GST_STATE_CHANGE_PAUSED_TO_READY:
5030 gst_matroska_parse_reset (GST_ELEMENT (parse));
5040 gst_matroska_parse_plugin_init (GstPlugin * plugin)
5044 /* create an elementfactory for the matroska_parse element */
5045 if (!gst_element_register (plugin, "matroskaparse",
5046 GST_RANK_NONE, GST_TYPE_MATROSKA_PARSE))