1 /* GStreamer Matroska muxer/demuxer
2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * (c) 2006 Tim-Philipp Müller <tim centricular net>
4 * (c) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5 * (c) 2011 Debarshi Ray <rishi@gnu.org>
7 * matroska-read-common.c: shared by matroska file/stream demuxer and parser
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
40 #include <gst/tag/tag.h>
41 #include <gst/base/gsttypefindhelper.h>
45 #include "ebml-read.h"
46 #include "matroska-read-common.h"
47 #include "matroska-ids.h"
49 GST_DEBUG_CATEGORY (matroskareadcommon_debug);
50 #define GST_CAT_DEFAULT matroskareadcommon_debug
52 #define DEBUG_ELEMENT_START(common, ebml, element) \
53 GST_DEBUG_OBJECT (common->sinkpad, "Parsing " element " element at offset %" \
54 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
56 #define DEBUG_ELEMENT_STOP(common, ebml, element, ret) \
57 GST_DEBUG_OBJECT (common->sinkpad, "Parsing " element " element " \
58 " finished with '%s'", gst_flow_get_name (ret))
60 #define GST_MATROSKA_TOC_UID_CHAPTER "chapter"
61 #define GST_MATROSKA_TOC_UID_EDITION "edition"
62 #define GST_MATROSKA_TOC_UID_EMPTY "empty"
67 guint64 target_type_value;
74 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
75 gpointer * data_out, gsize * size_out,
76 GstMatroskaTrackCompressionAlgorithm algo)
78 guint8 *new_data = NULL;
80 guint8 *data = *data_out;
81 guint size = *size_out;
84 if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
86 /* zlib encoded data */
92 zstream.zalloc = (alloc_func) 0;
93 zstream.zfree = (free_func) 0;
94 zstream.opaque = (voidpf) 0;
95 if (inflateInit (&zstream) != Z_OK) {
96 GST_WARNING ("zlib initialization failed.");
100 zstream.next_in = (Bytef *) data;
101 zstream.avail_in = orig_size;
102 new_size = orig_size;
103 new_data = g_malloc (new_size);
104 zstream.avail_out = new_size;
105 zstream.next_out = (Bytef *) new_data;
108 result = inflate (&zstream, Z_NO_FLUSH);
109 if (result == Z_STREAM_END) {
111 } else if (result != Z_OK) {
112 GST_WARNING ("inflate() returned %d", result);
117 new_data = g_realloc (new_data, new_size);
118 zstream.next_out = (Bytef *) (new_data + zstream.total_out);
119 zstream.avail_out += 4096;
120 } while (zstream.avail_in > 0);
122 if (result != Z_STREAM_END) {
126 new_size = zstream.total_out;
128 inflateEnd (&zstream);
131 GST_WARNING ("zlib encoded tracks not supported.");
135 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
137 /* bzip2 encoded data */
142 bzstream.bzalloc = NULL;
143 bzstream.bzfree = NULL;
144 bzstream.opaque = NULL;
147 if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
148 GST_WARNING ("bzip2 initialization failed.");
153 bzstream.next_in = (char *) data;
154 bzstream.avail_in = orig_size;
155 new_size = orig_size;
156 new_data = g_malloc (new_size);
157 bzstream.avail_out = new_size;
158 bzstream.next_out = (char *) new_data;
161 result = BZ2_bzDecompress (&bzstream);
162 if (result == BZ_STREAM_END) {
164 } else if (result != BZ_OK) {
165 GST_WARNING ("BZ2_bzDecompress() returned %d", result);
170 new_data = g_realloc (new_data, new_size);
171 bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
172 bzstream.avail_out += 4096;
173 } while (bzstream.avail_in > 0);
175 if (result != BZ_STREAM_END) {
179 new_size = bzstream.total_out_lo32;
181 BZ2_bzDecompressEnd (&bzstream);
184 GST_WARNING ("bzip2 encoded tracks not supported.");
188 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
189 /* lzo encoded data */
191 int orig_size, out_size;
196 new_data = g_malloc (new_size);
202 result = lzo1x_decode (new_data, &out_size, data, &orig_size);
206 new_data = g_realloc (new_data, new_size);
208 } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
210 new_size -= out_size;
212 if (result != LZO_OUTPUT_FULL) {
213 GST_WARNING ("lzo decompression failed");
220 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
221 /* header stripped encoded data */
222 if (enc->comp_settings_length > 0) {
223 new_data = g_malloc (size + enc->comp_settings_length);
224 new_size = size + enc->comp_settings_length;
226 memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
227 memcpy (new_data + enc->comp_settings_length, data, size);
230 GST_ERROR ("invalid compression algorithm %d", algo);
240 *data_out = new_data;
241 *size_out = new_size;
248 gst_matroska_decode_content_encodings (GArray * encodings)
252 if (encodings == NULL)
255 for (i = 0; i < encodings->len; i++) {
256 GstMatroskaTrackEncoding *enc =
257 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
258 gpointer data = NULL;
261 if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
265 /* Encryption not supported yet */
267 return GST_FLOW_ERROR;
269 if (i + 1 >= encodings->len)
270 return GST_FLOW_ERROR;
272 if (enc->comp_settings_length == 0)
275 data = enc->comp_settings;
276 size = enc->comp_settings_length;
278 if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
279 return GST_FLOW_ERROR;
281 g_free (enc->comp_settings);
283 enc->comp_settings = data;
284 enc->comp_settings_length = size;
291 gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
292 gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
299 g_return_val_if_fail (encodings != NULL, FALSE);
300 g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
301 g_return_val_if_fail (size_out != NULL, FALSE);
306 for (i = 0; i < encodings->len; i++) {
307 GstMatroskaTrackEncoding *enc =
308 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
309 gpointer new_data = NULL;
312 if ((enc->scope & scope) == 0)
315 /* Encryption not supported yet */
316 if (enc->type != 0) {
325 gst_matroska_decompress_data (enc, &new_data, &new_size,
331 if ((data == *data_out && free) || (data != *data_out))
339 if ((data == *data_out && free) || (data != *data_out))
353 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
355 if (i1->time < i2->time)
357 else if (i1->time > i2->time)
359 else if (i1->block < i2->block)
361 else if (i1->block > i2->block)
368 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
371 if (i1->time < *time)
373 else if (i1->time > *time)
380 gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
381 GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
382 gint * _entry_index, GstSearchMode snap_dir)
384 GstMatroskaIndex *entry = NULL;
387 /* find entry just before or at the requested position */
388 if (track && track->index_table)
389 index = track->index_table;
391 index = common->index;
393 if (!index || !index->len)
397 gst_util_array_binary_search (index->data, index->len,
398 sizeof (GstMatroskaIndex),
399 (GCompareDataFunc) gst_matroska_index_seek_find, snap_dir, &seek_pos,
403 if (snap_dir == GST_SEARCH_MODE_AFTER) {
404 /* Can only happen with a reverse seek past the end */
405 entry = &g_array_index (index, GstMatroskaIndex, index->len - 1);
407 /* Can only happen with a forward seek before the start */
408 entry = &g_array_index (index, GstMatroskaIndex, 0);
415 *_entry_index = entry - (GstMatroskaIndex *) index->data;
421 gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
422 GstMatroskaTrackEncoding * b)
424 if (b->order > a->order)
426 else if (b->order < a->order)
433 gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
438 if (encodings == NULL || encodings->len == 0)
441 for (i = 0; i < encodings->len; i++)
442 if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
448 /* takes ownership of taglist */
450 gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
451 GstElement * el, GstTagList * taglist)
453 if (common->global_tags) {
454 gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
455 gst_tag_list_unref (taglist);
457 common->global_tags = taglist;
459 common->global_tags_changed = TRUE;
463 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
467 if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
469 GST_DEBUG_OBJECT (common->sinkpad, "no upstream length");
474 /* determine track to seek in */
475 GstMatroskaTrackContext *
476 gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
477 GstMatroskaTrackContext * track)
481 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
484 for (i = 0; i < common->src->len; i++) {
485 GstMatroskaTrackContext *stream;
487 stream = g_ptr_array_index (common->src, i);
488 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
495 /* skip unknown or alike element */
497 gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
498 GstEbmlRead * ebml, const gchar * parent_name, guint id)
500 if (id == GST_EBML_ID_VOID) {
501 GST_DEBUG_OBJECT (common->sinkpad, "Skipping EBML Void element");
502 } else if (id == GST_EBML_ID_CRC32) {
503 GST_DEBUG_OBJECT (common->sinkpad, "Skipping EBML CRC32 element");
505 GST_WARNING_OBJECT (common->sinkpad,
506 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
509 return gst_ebml_read_skip (ebml);
513 gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
514 GstEbmlRead * ebml, GstTagList * taglist)
518 gchar *description = NULL;
519 gchar *filename = NULL;
520 gchar *mimetype = NULL;
524 DEBUG_ELEMENT_START (common, ebml, "AttachedFile");
526 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
527 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
531 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
532 /* read all sub-entries */
534 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
538 case GST_MATROSKA_ID_FILEDESCRIPTION:
540 GST_WARNING_OBJECT (common->sinkpad,
541 "FileDescription can only appear once");
545 ret = gst_ebml_read_utf8 (ebml, &id, &description);
546 GST_DEBUG_OBJECT (common->sinkpad, "FileDescription: %s",
547 GST_STR_NULL (description));
549 case GST_MATROSKA_ID_FILENAME:
551 GST_WARNING_OBJECT (common->sinkpad, "FileName can only appear once");
555 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
557 GST_DEBUG_OBJECT (common->sinkpad, "FileName: %s",
558 GST_STR_NULL (filename));
560 case GST_MATROSKA_ID_FILEMIMETYPE:
562 GST_WARNING_OBJECT (common->sinkpad,
563 "FileMimeType can only appear once");
567 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
568 GST_DEBUG_OBJECT (common->sinkpad, "FileMimeType: %s",
569 GST_STR_NULL (mimetype));
571 case GST_MATROSKA_ID_FILEDATA:
573 GST_WARNING_OBJECT (common->sinkpad, "FileData can only appear once");
577 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
578 GST_DEBUG_OBJECT (common->sinkpad,
579 "FileData of size %" G_GUINT64_FORMAT, datalen);
583 ret = gst_matroska_read_common_parse_skip (common, ebml,
586 case GST_MATROSKA_ID_FILEUID:
587 ret = gst_ebml_read_skip (ebml);
592 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
594 if (filename && mimetype && data && datalen > 0) {
595 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
596 GstBuffer *tagbuffer = NULL;
597 GstSample *tagsample = NULL;
598 GstStructure *info = NULL;
599 GstCaps *caps = NULL;
600 gchar *filename_lc = g_utf8_strdown (filename, -1);
602 GST_DEBUG_OBJECT (common->sinkpad, "Creating tag for attachment with "
603 "filename '%s', mimetype '%s', description '%s', "
604 "size %" G_GUINT64_FORMAT, filename, mimetype,
605 GST_STR_NULL (description), datalen);
607 /* TODO: better heuristics for different image types */
608 if (strstr (filename_lc, "cover")) {
609 if (strstr (filename_lc, "back"))
610 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
612 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
613 } else if (g_str_has_prefix (mimetype, "image/") ||
614 g_str_has_suffix (filename_lc, "png") ||
615 g_str_has_suffix (filename_lc, "jpg") ||
616 g_str_has_suffix (filename_lc, "jpeg") ||
617 g_str_has_suffix (filename_lc, "gif") ||
618 g_str_has_suffix (filename_lc, "bmp")) {
619 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
621 g_free (filename_lc);
623 /* First try to create an image tag buffer from this */
624 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
626 gst_tag_image_data_to_image_sample (data, datalen, image_type);
629 image_type = GST_TAG_IMAGE_TYPE_NONE;
631 tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
632 caps = gst_caps_ref (gst_sample_get_caps (tagsample));
633 info = gst_structure_copy (gst_sample_get_info (tagsample));
634 gst_sample_unref (tagsample);
638 /* if this failed create an attachment buffer */
640 tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
642 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
644 caps = gst_caps_new_empty_simple (mimetype);
647 /* Set filename and description in the info */
649 info = gst_structure_new_empty ("GstTagImageInfo");
651 gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
653 gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
655 tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
657 gst_buffer_unref (tagbuffer);
658 gst_caps_unref (caps);
660 GST_DEBUG_OBJECT (common->sinkpad,
661 "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
663 /* and append to the tag list */
664 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
665 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
668 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
671 /* the list adds it own ref */
672 gst_sample_unref (tagsample);
678 g_free (description);
684 gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
685 GstElement * el, GstEbmlRead * ebml)
688 GstFlowReturn ret = GST_FLOW_OK;
691 DEBUG_ELEMENT_START (common, ebml, "Attachments");
693 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
694 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
698 taglist = gst_tag_list_new_empty ();
699 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
701 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
702 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
706 case GST_MATROSKA_ID_ATTACHEDFILE:
707 ret = gst_matroska_read_common_parse_attached_file (common, ebml,
712 ret = gst_matroska_read_common_parse_skip (common, ebml,
717 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
719 if (gst_tag_list_n_tags (taglist) > 0) {
720 GST_DEBUG_OBJECT (common->sinkpad, "Storing attachment tags");
721 gst_matroska_read_common_found_global_tag (common, el, taglist);
723 GST_DEBUG_OBJECT (common->sinkpad, "No valid attachments found");
724 gst_tag_list_unref (taglist);
727 common->attachments_parsed = TRUE;
733 gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
734 GArray * edition_targets, GArray * chapter_targtes, GstTagList * tags)
744 (gst_toc_entry_get_entry_type (entry) ==
745 GST_TOC_ENTRY_TYPE_EDITION) ? edition_targets : chapter_targtes;
747 etags = gst_tag_list_new_empty ();
749 for (i = 0; i < targets->len; ++i) {
750 tgt = g_array_index (targets, guint64, i);
753 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
755 uid = g_strdup_printf ("%" G_GUINT64_FORMAT, tgt);
756 if (g_strcmp0 (gst_toc_entry_get_uid (entry), uid) == 0)
757 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
762 gst_toc_entry_merge_tags (entry, etags, GST_TAG_MERGE_APPEND);
763 gst_tag_list_unref (etags);
765 cur = gst_toc_entry_get_sub_entries (entry);
766 while (cur != NULL) {
767 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
768 chapter_targtes, tags);
774 gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
775 GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
776 GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
778 GstFlowReturn ret = GST_FLOW_OK;
784 DEBUG_ELEMENT_START (common, ebml, "TagTargets");
786 *target_type_value = 50;
789 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
790 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
794 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
795 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
799 case GST_MATROSKA_ID_TARGETCHAPTERUID:
800 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
801 g_array_append_val (chapter_targets, uid);
804 case GST_MATROSKA_ID_TARGETEDITIONUID:
805 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
806 g_array_append_val (edition_targets, uid);
809 case GST_MATROSKA_ID_TARGETTRACKUID:
810 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
811 g_array_append_val (track_targets, uid);
814 case GST_MATROSKA_ID_TARGETTYPEVALUE:
815 if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
816 *target_type_value = tmp;
819 case GST_MATROSKA_ID_TARGETTYPE:
820 if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
821 g_free (*target_type);
828 gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
834 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
840 gst_matroska_read_common_postprocess_toc_entries (GList * toc_entries,
841 guint64 max, const gchar * parent_uid)
843 GstTocEntry *cur_info, *prev_info, *next_info;
844 GList *cur_list, *prev_list, *next_list;
845 gint64 cur_start, prev_start, stop;
847 cur_list = toc_entries;
848 while (cur_list != NULL) {
849 cur_info = cur_list->data;
851 switch (gst_toc_entry_get_entry_type (cur_info)) {
852 case GST_TOC_ENTRY_TYPE_ANGLE:
853 case GST_TOC_ENTRY_TYPE_VERSION:
854 case GST_TOC_ENTRY_TYPE_EDITION:
855 /* in Matroska terms edition has duration of full track */
856 gst_toc_entry_set_start_stop_times (cur_info, 0, max);
858 gst_matroska_read_common_postprocess_toc_entries
859 (gst_toc_entry_get_sub_entries (cur_info), max,
860 gst_toc_entry_get_uid (cur_info));
863 case GST_TOC_ENTRY_TYPE_TITLE:
864 case GST_TOC_ENTRY_TYPE_TRACK:
865 case GST_TOC_ENTRY_TYPE_CHAPTER:
866 prev_list = cur_list->prev;
867 next_list = cur_list->next;
869 if (prev_list != NULL)
870 prev_info = prev_list->data;
874 if (next_list != NULL)
875 next_info = next_list->data;
879 /* updated stop time in previous chapter and it's subchapters */
880 if (prev_info != NULL) {
881 gst_toc_entry_get_start_stop_times (prev_info, &prev_start, &stop);
882 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
885 gst_toc_entry_set_start_stop_times (prev_info, prev_start, stop);
887 gst_matroska_read_common_postprocess_toc_entries
888 (gst_toc_entry_get_sub_entries (prev_info), cur_start,
889 gst_toc_entry_get_uid (prev_info));
892 /* updated stop time in current chapter and it's subchapters */
893 if (next_info == NULL) {
894 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
898 gst_toc_entry_set_start_stop_times (cur_info, cur_start, stop);
901 gst_matroska_read_common_postprocess_toc_entries
902 (gst_toc_entry_get_sub_entries (cur_info), stop,
903 gst_toc_entry_get_uid (cur_info));
906 case GST_TOC_ENTRY_TYPE_INVALID:
909 cur_list = cur_list->next;
914 gst_matroska_read_common_parse_chapter_titles (GstMatroskaReadCommon * common,
915 GstEbmlRead * ebml, GstTagList * titles)
919 GstFlowReturn ret = GST_FLOW_OK;
921 DEBUG_ELEMENT_START (common, ebml, "ChaptersTitles");
924 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
925 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
929 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
930 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
934 case GST_MATROSKA_ID_CHAPSTRING:
935 ret = gst_ebml_read_utf8 (ebml, &id, &title);
940 gst_matroska_read_common_parse_skip (common, ebml, "ChaptersTitles",
946 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
948 if (title != NULL && ret == GST_FLOW_OK)
949 gst_tag_list_add (titles, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title, NULL);
956 gst_matroska_read_common_parse_chapter_element (GstMatroskaReadCommon * common,
957 GstEbmlRead * ebml, GList ** subentries)
960 guint64 start_time = -1, stop_time = -1;
961 guint64 is_hidden = 0, is_enabled = 1, uid = 0;
962 GstFlowReturn ret = GST_FLOW_OK;
963 GstTocEntry *chapter_info;
966 GList *subsubentries = NULL, *l;
968 DEBUG_ELEMENT_START (common, ebml, "ChaptersElement");
970 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
971 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
975 tags = gst_tag_list_new_empty ();
977 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
978 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
982 case GST_MATROSKA_ID_CHAPTERUID:
983 ret = gst_ebml_read_uint (ebml, &id, &uid);
986 case GST_MATROSKA_ID_CHAPTERTIMESTART:
987 ret = gst_ebml_read_uint (ebml, &id, &start_time);
990 case GST_MATROSKA_ID_CHAPTERTIMESTOP:
991 ret = gst_ebml_read_uint (ebml, &id, &stop_time);
994 case GST_MATROSKA_ID_CHAPTERATOM:
996 gst_matroska_read_common_parse_chapter_element (common, ebml,
1000 case GST_MATROSKA_ID_CHAPTERDISPLAY:
1002 gst_matroska_read_common_parse_chapter_titles (common, ebml, tags);
1005 case GST_MATROSKA_ID_CHAPTERFLAGHIDDEN:
1006 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1009 case GST_MATROSKA_ID_CHAPTERFLAGENABLED:
1010 ret = gst_ebml_read_uint (ebml, &id, &is_enabled);
1015 gst_matroska_read_common_parse_skip (common, ebml,
1016 "ChaptersElement", id);
1022 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1023 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1024 chapter_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid_str);
1027 gst_toc_entry_set_tags (chapter_info, tags);
1028 gst_toc_entry_set_start_stop_times (chapter_info, start_time, stop_time);
1030 for (l = subsubentries; l; l = l->next)
1031 gst_toc_entry_append_sub_entry (chapter_info, l->data);
1032 g_list_free (subsubentries);
1034 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
1036 /* start time is mandatory and has no default value,
1037 * so we should skip chapters without it */
1038 if (is_hidden == 0 && is_enabled > 0 &&
1039 start_time != -1 && ret == GST_FLOW_OK) {
1040 *subentries = g_list_append (*subentries, chapter_info);
1042 gst_toc_entry_unref (chapter_info);
1047 static GstFlowReturn
1048 gst_matroska_read_common_parse_chapter_edition (GstMatroskaReadCommon * common,
1049 GstEbmlRead * ebml, GstToc * toc)
1052 guint64 is_hidden = 0, uid = 0;
1053 GstFlowReturn ret = GST_FLOW_OK;
1054 GstTocEntry *edition_info;
1055 GList *subentries = NULL, *l;
1058 DEBUG_ELEMENT_START (common, ebml, "ChaptersEdition");
1060 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1061 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1065 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1066 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1070 case GST_MATROSKA_ID_EDITIONUID:
1071 ret = gst_ebml_read_uint (ebml, &id, &uid);
1074 case GST_MATROSKA_ID_CHAPTERATOM:
1076 gst_matroska_read_common_parse_chapter_element (common, ebml,
1080 case GST_MATROSKA_ID_EDITIONFLAGHIDDEN:
1081 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1086 gst_matroska_read_common_parse_skip (common, ebml,
1087 "ChaptersEdition", id);
1092 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1095 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1096 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1097 edition_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, uid_str);
1098 gst_toc_entry_set_start_stop_times (edition_info, -1, -1);
1101 for (l = subentries; l; l = l->next)
1102 gst_toc_entry_append_sub_entry (edition_info, l->data);
1103 g_list_free (subentries);
1105 if (is_hidden == 0 && subentries != NULL && ret == GST_FLOW_OK)
1106 gst_toc_append_entry (toc, edition_info);
1108 GST_DEBUG_OBJECT (common->sinkpad,
1109 "Skipping empty or hidden edition in the chapters TOC");
1110 gst_toc_entry_unref (edition_info);
1117 gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common,
1121 GstFlowReturn ret = GST_FLOW_OK;
1124 DEBUG_ELEMENT_START (common, ebml, "Chapters");
1126 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1127 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1131 /* FIXME: create CURRENT toc as well */
1132 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1134 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1135 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1139 case GST_MATROSKA_ID_EDITIONENTRY:
1141 gst_matroska_read_common_parse_chapter_edition (common, ebml, toc);
1146 gst_matroska_read_common_parse_skip (common, ebml, "Chapters", id);
1151 if (gst_toc_get_entries (toc) != NULL) {
1152 gst_matroska_read_common_postprocess_toc_entries (gst_toc_get_entries (toc),
1153 common->segment.duration, "");
1157 gst_toc_unref (toc);
1159 common->chapters_parsed = TRUE;
1161 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1166 gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
1174 /* this function is the first to be called */
1180 ret = gst_ebml_peek_id (ebml, &id);
1181 if (ret != GST_FLOW_OK)
1184 GST_DEBUG_OBJECT (common->sinkpad, "id: %08x", id);
1186 if (id != GST_EBML_ID_HEADER) {
1187 GST_ERROR_OBJECT (common->sinkpad, "Failed to read header");
1191 ret = gst_ebml_read_master (ebml, &id);
1192 if (ret != GST_FLOW_OK)
1195 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1196 ret = gst_ebml_peek_id (ebml, &id);
1197 if (ret != GST_FLOW_OK)
1201 /* is our read version uptodate? */
1202 case GST_EBML_ID_EBMLREADVERSION:{
1205 ret = gst_ebml_read_uint (ebml, &id, &num);
1206 if (ret != GST_FLOW_OK)
1208 if (num != GST_EBML_VERSION) {
1209 GST_ERROR_OBJECT (common->sinkpad,
1210 "Unsupported EBML version %" G_GUINT64_FORMAT, num);
1214 GST_DEBUG_OBJECT (common->sinkpad,
1215 "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1219 /* we only handle 8 byte lengths at max */
1220 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
1223 ret = gst_ebml_read_uint (ebml, &id, &num);
1224 if (ret != GST_FLOW_OK)
1226 if (num > sizeof (guint64)) {
1227 GST_ERROR_OBJECT (common->sinkpad,
1228 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
1229 return GST_FLOW_ERROR;
1231 GST_DEBUG_OBJECT (common->sinkpad,
1232 "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
1236 /* we handle 4 byte IDs at max */
1237 case GST_EBML_ID_EBMLMAXIDLENGTH:{
1240 ret = gst_ebml_read_uint (ebml, &id, &num);
1241 if (ret != GST_FLOW_OK)
1243 if (num > sizeof (guint32)) {
1244 GST_ERROR_OBJECT (common->sinkpad,
1245 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
1246 return GST_FLOW_ERROR;
1248 GST_DEBUG_OBJECT (common->sinkpad,
1249 "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
1253 case GST_EBML_ID_DOCTYPE:{
1256 ret = gst_ebml_read_ascii (ebml, &id, &text);
1257 if (ret != GST_FLOW_OK)
1260 GST_DEBUG_OBJECT (common->sinkpad, "EbmlDocType: %s",
1261 GST_STR_NULL (text));
1268 case GST_EBML_ID_DOCTYPEREADVERSION:{
1271 ret = gst_ebml_read_uint (ebml, &id, &num);
1272 if (ret != GST_FLOW_OK)
1275 GST_DEBUG_OBJECT (common->sinkpad,
1276 "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1281 ret = gst_matroska_read_common_parse_skip (common, ebml,
1283 if (ret != GST_FLOW_OK)
1287 /* we ignore these two, as they don't tell us anything we care about */
1288 case GST_EBML_ID_EBMLVERSION:
1289 case GST_EBML_ID_DOCTYPEVERSION:
1290 ret = gst_ebml_read_skip (ebml);
1291 if (ret != GST_FLOW_OK)
1299 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
1300 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
1301 (doctype == NULL)) {
1304 GST_INFO_OBJECT (common->sinkpad, "Input is %s version %d", doctype,
1306 if (!strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM))
1307 common->is_webm = TRUE;
1309 GST_WARNING_OBJECT (common->sinkpad,
1310 "Input is EBML without doctype, assuming " "matroska (version %d)",
1315 GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
1316 ("Demuxer version (2) is too old to read %s version %d",
1317 GST_STR_NULL (doctype), version));
1318 ret = GST_FLOW_ERROR;
1321 GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
1322 ("Input is not a matroska stream (doctype=%s)", doctype));
1323 ret = GST_FLOW_ERROR;
1333 static GstFlowReturn
1334 gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
1335 GstEbmlRead * ebml, guint * nentries)
1339 GstMatroskaIndex idx;
1341 idx.pos = (guint64) - 1;
1343 idx.time = GST_CLOCK_TIME_NONE;
1346 DEBUG_ELEMENT_START (common, ebml, "CueTrackPositions");
1348 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1349 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1353 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1354 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1359 case GST_MATROSKA_ID_CUETRACK:
1363 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1368 GST_WARNING_OBJECT (common->sinkpad, "Invalid CueTrack 0");
1372 GST_DEBUG_OBJECT (common->sinkpad, "CueTrack: %" G_GUINT64_FORMAT, num);
1377 /* position in file */
1378 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
1382 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1385 if (num > G_MAXINT64) {
1386 GST_WARNING_OBJECT (common->sinkpad,
1387 "CueClusterPosition %" G_GUINT64_FORMAT " too large", num);
1395 /* number of block in the cluster */
1396 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
1400 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1404 GST_WARNING_OBJECT (common->sinkpad, "Invalid CueBlockNumber 0");
1408 GST_DEBUG_OBJECT (common->sinkpad, "CueBlockNumber: %" G_GUINT64_FORMAT,
1412 /* mild sanity check, disregard strange cases ... */
1413 if (idx.block > G_MAXUINT16) {
1414 GST_DEBUG_OBJECT (common->sinkpad, "... looks suspicious, ignoring");
1421 ret = gst_matroska_read_common_parse_skip (common, ebml,
1422 "CueTrackPositions", id);
1425 case GST_MATROSKA_ID_CUECODECSTATE:
1426 case GST_MATROSKA_ID_CUEREFERENCE:
1427 ret = gst_ebml_read_skip (ebml);
1432 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1434 /* (e.g.) lavf typically creates entries without a block number,
1435 * which is bogus and leads to contradictory information */
1436 if (common->index->len) {
1437 GstMatroskaIndex *last_idx;
1439 last_idx = &g_array_index (common->index, GstMatroskaIndex,
1440 common->index->len - 1);
1441 if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
1442 last_idx->track == idx.track && idx.time > last_idx->time) {
1443 GST_DEBUG_OBJECT (common->sinkpad, "Cue entry refers to same location, "
1444 "but has different time than previous entry; discarding");
1449 if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
1450 && idx.pos != (guint64) - 1 && idx.track > 0) {
1451 g_array_append_val (common->index, idx);
1453 } else if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) {
1454 GST_DEBUG_OBJECT (common->sinkpad,
1455 "CueTrackPositions without valid content");
1461 static GstFlowReturn
1462 gst_matroska_read_common_parse_index_pointentry (GstMatroskaReadCommon *
1463 common, GstEbmlRead * ebml)
1467 GstClockTime time = GST_CLOCK_TIME_NONE;
1470 DEBUG_ELEMENT_START (common, ebml, "CuePoint");
1472 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1473 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1477 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1478 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1482 /* one single index entry ('point') */
1483 case GST_MATROSKA_ID_CUETIME:
1485 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
1488 GST_DEBUG_OBJECT (common->sinkpad, "CueTime: %" G_GUINT64_FORMAT, time);
1489 time = time * common->time_scale;
1493 /* position in the file + track to which it belongs */
1494 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
1496 ret = gst_matroska_read_common_parse_index_cuetrack (common, ebml,
1502 ret = gst_matroska_read_common_parse_skip (common, ebml, "CuePoint",
1508 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1511 if (time == GST_CLOCK_TIME_NONE) {
1512 GST_WARNING_OBJECT (common->sinkpad, "CuePoint without valid time");
1513 g_array_remove_range (common->index, common->index->len - nentries,
1518 for (i = common->index->len - nentries; i < common->index->len; i++) {
1519 GstMatroskaIndex *idx =
1520 &g_array_index (common->index, GstMatroskaIndex, i);
1523 GST_DEBUG_OBJECT (common->sinkpad, "Index entry: pos=%" G_GUINT64_FORMAT
1524 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
1525 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
1529 GST_DEBUG_OBJECT (common->sinkpad, "Empty CuePoint");
1536 gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
1541 g_assert (common->src->len == common->num_streams);
1542 for (n = 0; n < common->src->len; n++) {
1543 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, n);
1545 if (context->num == track_num) {
1550 if (n == common->num_streams)
1551 GST_WARNING_OBJECT (common->sinkpad,
1552 "Failed to find corresponding pad for tracknum %d", track_num);
1558 gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
1562 GstFlowReturn ret = GST_FLOW_OK;
1566 g_array_free (common->index, TRUE);
1568 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1570 DEBUG_ELEMENT_START (common, ebml, "Cues");
1572 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1573 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1577 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1578 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1582 /* one single index entry ('point') */
1583 case GST_MATROSKA_ID_POINTENTRY:
1584 ret = gst_matroska_read_common_parse_index_pointentry (common, ebml);
1588 ret = gst_matroska_read_common_parse_skip (common, ebml, "Cues", id);
1592 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1594 /* Sort index by time, smallest time first, for easier searching */
1595 g_array_sort (common->index, (GCompareFunc) gst_matroska_index_compare);
1597 /* Now sort the track specific index entries into their own arrays */
1598 for (i = 0; i < common->index->len; i++) {
1599 GstMatroskaIndex *idx = &g_array_index (common->index, GstMatroskaIndex,
1602 GstMatroskaTrackContext *ctx;
1605 if (common->element_index) {
1608 if (idx->track != 0 &&
1610 gst_matroska_read_common_stream_from_num (common,
1611 idx->track)) != -1) {
1612 ctx = g_ptr_array_index (common->src, track_num);
1614 if (ctx->index_writer_id == -1)
1615 gst_index_get_writer_id (common->element_index,
1616 GST_OBJECT (ctx->pad), &ctx->index_writer_id);
1617 writer_id = ctx->index_writer_id;
1619 if (common->element_index_writer_id == -1)
1620 gst_index_get_writer_id (common->element_index, GST_OBJECT (common),
1621 &common->element_index_writer_id);
1622 writer_id = common->element_index_writer_id;
1625 GST_LOG_OBJECT (common->sinkpad,
1626 "adding association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT
1627 " for writer id %d", GST_TIME_ARGS (idx->time), idx->pos, writer_id);
1628 gst_index_add_association (common->element_index, writer_id,
1629 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
1630 GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
1634 if (idx->track == 0)
1637 track_num = gst_matroska_read_common_stream_from_num (common, idx->track);
1638 if (track_num == -1)
1641 ctx = g_ptr_array_index (common->src, track_num);
1643 if (ctx->index_table == NULL)
1645 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1647 g_array_append_vals (ctx->index_table, idx, 1);
1650 common->index_parsed = TRUE;
1652 /* sanity check; empty index normalizes to no index */
1653 if (common->index->len == 0) {
1654 g_array_free (common->index, TRUE);
1655 common->index = NULL;
1662 gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
1663 GstElement * el, GstEbmlRead * ebml)
1665 GstFlowReturn ret = GST_FLOW_OK;
1666 gdouble dur_f = -1.0;
1669 DEBUG_ELEMENT_START (common, ebml, "SegmentInfo");
1671 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1672 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1676 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1677 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1681 /* cluster timecode */
1682 case GST_MATROSKA_ID_TIMECODESCALE:{
1685 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1689 GST_DEBUG_OBJECT (common->sinkpad, "TimeCodeScale: %" G_GUINT64_FORMAT,
1691 common->time_scale = num;
1695 case GST_MATROSKA_ID_DURATION:{
1696 if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK)
1700 GST_WARNING_OBJECT (common->sinkpad, "Invalid duration %lf", dur_f);
1704 GST_DEBUG_OBJECT (common->sinkpad, "Duration: %lf", dur_f);
1708 case GST_MATROSKA_ID_WRITINGAPP:{
1711 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1714 GST_DEBUG_OBJECT (common->sinkpad, "WritingApp: %s",
1715 GST_STR_NULL (text));
1716 common->writing_app = text;
1720 case GST_MATROSKA_ID_MUXINGAPP:{
1723 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1726 GST_DEBUG_OBJECT (common->sinkpad, "MuxingApp: %s",
1727 GST_STR_NULL (text));
1728 common->muxing_app = text;
1732 case GST_MATROSKA_ID_DATEUTC:{
1735 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
1738 GST_DEBUG_OBJECT (common->sinkpad, "DateUTC: %" G_GINT64_FORMAT, time);
1739 common->created = time;
1743 case GST_MATROSKA_ID_TITLE:{
1745 GstTagList *taglist;
1747 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1750 GST_DEBUG_OBJECT (common->sinkpad, "Title: %s", GST_STR_NULL (text));
1751 taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
1752 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
1753 gst_matroska_read_common_found_global_tag (common, el, taglist);
1759 ret = gst_matroska_read_common_parse_skip (common, ebml,
1764 case GST_MATROSKA_ID_SEGMENTUID:
1765 case GST_MATROSKA_ID_SEGMENTFILENAME:
1766 case GST_MATROSKA_ID_PREVUID:
1767 case GST_MATROSKA_ID_PREVFILENAME:
1768 case GST_MATROSKA_ID_NEXTUID:
1769 case GST_MATROSKA_ID_NEXTFILENAME:
1770 case GST_MATROSKA_ID_SEGMENTFAMILY:
1771 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
1772 ret = gst_ebml_read_skip (ebml);
1780 dur_u = gst_gdouble_to_guint64 (dur_f *
1781 gst_guint64_to_gdouble (common->time_scale));
1782 if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
1783 common->segment.duration = dur_u;
1786 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1788 common->segmentinfo_parsed = TRUE;
1793 static GstFlowReturn
1794 gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
1795 common, GstEbmlRead * ebml, GstTagList ** p_taglist, gchar * parent)
1797 /* FIXME: check if there are more useful mappings */
1800 const gchar *matroska_tagname;
1801 const gchar *gstreamer_tagname;
1805 /* The following list has the _same_ order as the one in Matroska spec. Please, don't mess it up. */
1806 /* TODO: Nesting information:
1807 ORIGINAL A special tag that is meant to have other tags inside (using nested tags) to describe the original work of art that this item is based on. All tags in this list can be used "under" the ORIGINAL tag like LYRICIST, PERFORMER, etc.
1808 SAMPLE A tag that contains other tags to describe a sample used in the targeted item taken from another work of art. All tags in this list can be used "under" the SAMPLE tag like TITLE, ARTIST, DATE_RELEASED, etc.
1809 COUNTRY The name of the country (biblio ISO-639-2) that is meant to have other tags inside (using nested tags) to country specific information about the item. All tags in this list can be used "under" the COUNTRY_SPECIFIC tag like LABEL, PUBLISH_RATING, etc.
1812 /* Organizational Information */
1813 GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
1814 GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}, {
1815 /* TODO: PART_OFFSET A number to add to PART_NUMBER when the parts at that level don't start at 1. (e.g. if TargetType is TRACK, the track number of the second audio CD) */
1818 GST_MATROSKA_TAG_ID_SUBTITLE, GST_TAG_TITLE}, { /* Sub Title of the entity. Since we're concat'ing all title-like entities anyway, might as well add the sub-title. */
1819 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
1820 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1822 /* TODO: Nested Information:
1823 URL URL corresponding to the tag it's included in.
1824 SORT_WITH A child element to indicate what alternative value the parent tag can have to be sorted, for example "Pet Shop Boys" instead of "The Pet Shop Boys". Or "Marley Bob" and "Marley Ziggy" (no comma needed).
1825 INSTRUMENTS The instruments that are being used/played, separated by a comma. It should be a child of the following tags: ARTIST, LEAD_PERFORMER or ACCOMPANIMENT.
1826 EMAIL Email corresponding to the tag it's included in.
1827 ADDRESS The physical address of the entity. The address should include a country code. It can be useful for a recording label.
1828 FAX The fax number corresponding to the tag it's included in. It can be useful for a recording label.
1829 PHONE The phone number corresponding to the tag it's included in. It can be useful for a recording label.
1833 GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
1834 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
1835 GST_MATROSKA_TAG_ID_ACCOMPANIMENT, GST_TAG_PERFORMER}, { /* Band/orchestra/accompaniment/musician. This is akin to the TPE2 tag in ID3. */
1836 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
1837 /* ARRANGER The person who arranged the piece, e.g., Ravel. */
1838 GST_MATROSKA_TAG_ID_LYRICS, GST_TAG_LYRICS}, { /* The lyrics corresponding to a song (in case audio synchronization is not known or as a doublon to a subtitle track). Editing this value when subtitles are found should also result in editing the subtitle track for more consistency. */
1839 /* LYRICIST The person who wrote the lyrics for a musical item. This is akin to the TEXT tag in ID3. */
1840 GST_MATROSKA_TAG_ID_CONDUCTOR, GST_TAG_PERFORMER}, { /* Conductor/performer refinement. This is akin to the TPE3 tag in ID3. */
1841 /* DIRECTOR This is akin to the IART tag in RIFF. */
1842 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
1843 /* ASSISTANT_DIRECTOR The name of the assistant director. */
1844 /* DIRECTOR_OF_PHOTOGRAPHY The name of the director of photography, also known as cinematographer. This is akin to the ICNM tag in Extended RIFF. */
1845 /* SOUND_ENGINEER The name of the sound engineer or sound recordist. */
1846 /* ART_DIRECTOR The person who oversees the artists and craftspeople who build the sets. */
1847 /* PRODUCTION_DESIGNER Artist responsible for designing the overall visual appearance of a movie. */
1848 /* CHOREGRAPHER The name of the choregrapher */
1849 /* COSTUME_DESIGNER The name of the costume designer */
1850 /* ACTOR An actor or actress playing a role in this movie. This is the person's real name, not the character's name the person is playing. */
1851 /* CHARACTER The name of the character an actor or actress plays in this movie. This should be a sub-tag of an ACTOR tag in order not to cause ambiguities. */
1852 /* WRITTEN_BY The author of the story or script (used for movies and TV shows). */
1853 /* SCREENPLAY_BY The author of the screenplay or scenario (used for movies and TV shows). */
1854 /* EDITED_BY This is akin to the IEDT tag in Extended RIFF. */
1855 /* PRODUCER Produced by. This is akin to the IPRO tag in Extended RIFF. */
1856 /* COPRODUCER The name of a co-producer. */
1857 /* EXECUTIVE_PRODUCER The name of an executive producer. */
1858 /* DISTRIBUTED_BY This is akin to the IDST tag in Extended RIFF. */
1859 /* MASTERED_BY The engineer who mastered the content for a physical medium or for digital distribution. */
1860 GST_MATROSKA_TAG_ID_ENCODED_BY, GST_TAG_ENCODED_BY}, { /* This is akin to the TENC tag in ID3. */
1861 /* MIXED_BY DJ mix by the artist specified */
1862 /* REMIXED_BY Interpreted, remixed, or otherwise modified by. This is akin to the TPE4 tag in ID3. */
1863 /* PRODUCTION_STUDIO This is akin to the ISTD tag in Extended RIFF. */
1864 /* THANKS_TO A very general tag for everyone else that wants to be listed. */
1865 /* PUBLISHER This is akin to the TPUB tag in ID3. */
1866 /* LABEL The record label or imprint on the disc. */
1867 /* Search / Classification */
1868 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
1869 /* MOOD Intended to reflect the mood of the item with a few keywords, e.g. "Romantic", "Sad" or "Uplifting". The format follows that of the TMOO tag in ID3. */
1870 /* ORIGINAL_MEDIA_TYPE Describes the original type of the media, such as, "DVD", "CD", "computer image," "drawing," "lithograph," and so forth. This is akin to the TMED tag in ID3. */
1871 /* CONTENT_TYPE The type of the item. e.g. Documentary, Feature Film, Cartoon, Music Video, Music, Sound FX, ... */
1872 /* SUBJECT Describes the topic of the file, such as "Aerial view of Seattle." */
1873 GST_MATROSKA_TAG_ID_DESCRIPTION, GST_TAG_DESCRIPTION}, { /* A short description of the content, such as "Two birds flying." */
1874 GST_MATROSKA_TAG_ID_KEYWORDS, GST_TAG_KEYWORDS}, { /* Keywords to the item separated by a comma, used for searching. */
1875 /* SUMMARY A plot outline or a summary of the story. */
1876 /* SYNOPSIS A description of the story line of the item. */
1877 /* INITIAL_KEY The initial key that a musical track starts in. The format is identical to ID3. */
1878 /* PERIOD Describes the period that the piece is from or about. For example, "Renaissance". */
1879 /* LAW_RATING Depending on the country it's the format of the rating of a movie (P, R, X in the USA, an age in other countries or a URI defining a logo). */
1880 /* ICRA The ICRA content rating for parental control. (Previously RSACi) */
1882 /* Temporal Information */
1883 GST_MATROSKA_TAG_ID_DATE_RELEASED, GST_TAG_DATE}, { /* The time that the item was originaly released. This is akin to the TDRL tag in ID3. */
1884 GST_MATROSKA_TAG_ID_DATE_RECORDED, GST_TAG_DATE}, { /* The time that the recording began. This is akin to the TDRC tag in ID3. */
1885 GST_MATROSKA_TAG_ID_DATE_ENCODED, GST_TAG_DATE}, { /* The time that the encoding of this item was completed began. This is akin to the TDEN tag in ID3. */
1886 GST_MATROSKA_TAG_ID_DATE_TAGGED, GST_TAG_DATE}, { /* The time that the tags were done for this item. This is akin to the TDTG tag in ID3. */
1887 GST_MATROSKA_TAG_ID_DATE_DIGITIZED, GST_TAG_DATE}, { /* The time that the item was tranfered to a digital medium. This is akin to the IDIT tag in RIFF. */
1888 GST_MATROSKA_TAG_ID_DATE_WRITTEN, GST_TAG_DATE}, { /* The time that the writing of the music/script began. */
1889 GST_MATROSKA_TAG_ID_DATE_PURCHASED, GST_TAG_DATE}, { /* Information on when the file was purchased (see also purchase tags). */
1890 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1892 /* Spacial Information */
1893 GST_MATROSKA_TAG_ID_RECORDING_LOCATION, GST_TAG_GEO_LOCATION_NAME}, { /* The location where the item was recorded. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. This code is followed by a comma, then more detailed information such as state/province, another comma, and then city. For example, "US, Texas, Austin". This will allow for easy sorting. It is okay to only store the country, or the country and the state/province. More detailed information can be added after the city through the use of additional commas. In cases where the province/state is unknown, but you want to store the city, simply leave a space between the two commas. For example, "US, , Austin". */
1894 /* COMPOSITION_LOCATION Location that the item was originaly designed/written. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. This code is followed by a comma, then more detailed information such as state/province, another comma, and then city. For example, "US, Texas, Austin". This will allow for easy sorting. It is okay to only store the country, or the country and the state/province. More detailed information can be added after the city through the use of additional commas. In cases where the province/state is unknown, but you want to store the city, simply leave a space between the two commas. For example, "US, , Austin". */
1895 /* COMPOSER_NATIONALITY Nationality of the main composer of the item, mostly for classical music. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. */
1898 GST_MATROSKA_TAG_ID_COMMENT, GST_TAG_COMMENT}, { /* Any comment related to the content. */
1899 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1900 /* PLAY_COUNTER The number of time the item has been played. */
1901 /* TODO: RATING A numeric value defining how much a person likes the song/movie. The number is between 0 and 5 with decimal values possible (e.g. 2.7), 5(.0) being the highest possible rating. Other rating systems with different ranges will have to be scaled. */
1903 /* Technical Information */
1904 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
1905 /* ENCODER_SETTINGS A list of the settings used for encoding this item. No specific format. */
1906 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
1907 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1908 /* WONTFIX (already handled in another way): FPS The average frames per second of the specified item. This is typically the average number of Blocks per second. In the event that lacing is used, each laced chunk is to be counted as a seperate frame. */
1909 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
1910 /* MEASURE In music, a measure is a unit of time in Western music like "4/4". It represents a regular grouping of beats, a meter, as indicated in musical notation by the time signature.. The majority of the contemporary rock and pop music you hear on the radio these days is written in the 4/4 time signature. */
1911 /* TUNING It is saved as a frequency in hertz to allow near-perfect tuning of instruments to the same tone as the musical piece (e.g. "441.34" in Hertz). The default value is 440.0 Hz. */
1912 /* TODO: REPLAYGAIN_GAIN The gain to apply to reach 89dB SPL on playback. This is based on the Replay Gain standard. Note that ReplayGain information can be found at all TargetType levels (track, album, etc). */
1913 /* TODO: REPLAYGAIN_PEAK The maximum absolute peak value of the item. This is based on the Replay Gain standard. */
1916 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
1917 /* MCDI This is a binary dump of the TOC of the CDROM that this item was taken from. This holds the same information as the MCDI in ID3. */
1918 /* ISBN International Standard Book Number */
1919 /* BARCODE EAN-13 (European Article Numbering) or UPC-A (Universal Product Code) bar code identifier */
1920 /* CATALOG_NUMBER A label-specific string used to identify the release (TIC 01 for example). */
1921 /* LABEL_CODE A 4-digit or 5-digit number to identify the record label, typically printed as (LC) xxxx or (LC) 0xxxx on CDs medias or covers (only the number is stored). */
1922 /* LCCN Library of Congress Control Number */
1925 /* PURCHASE_ITEM URL to purchase this file. This is akin to the WPAY tag in ID3. */
1926 /* PURCHASE_INFO Information on where to purchase this album. This is akin to the WCOM tag in ID3. */
1927 /* PURCHASE_OWNER Information on the person who purchased the file. This is akin to the TOWN tag in ID3. */
1928 /* PURCHASE_PRICE The amount paid for entity. There should only be a numeric value in here. Only numbers, no letters or symbols other than ".". For instance, you would store "15.59" instead of "$15.59USD". */
1929 /* PURCHASE_CURRENCY The currency type used to pay for the entity. Use ISO-4217 for the 3 letter currency code. */
1932 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
1933 GST_MATROSKA_TAG_ID_PRODUCTION_COPYRIGHT, GST_TAG_COPYRIGHT}, { /* The copyright information as per the production copyright holder. This is akin to the TPRO tag in ID3. */
1934 GST_MATROSKA_TAG_ID_LICENSE, GST_TAG_LICENSE}, { /* The license applied to the content (like Creative Commons variants). */
1935 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}
1939 const gchar *matroska_tagname;
1940 const gchar *gstreamer_tagname;
1942 child_tag_conv[] = {
1944 "TITLE/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1945 "ARTIST/SORT_WITH=", GST_TAG_ARTIST_SORTNAME}, {
1946 /* ALBUM-stuff is handled elsewhere */
1947 "COMPOSER/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1948 "ORIGINAL/URL=", GST_TAG_LOCATION}, {
1949 /* EMAIL, PHONE, FAX all can be mapped to GST_TAG_CONTACT, there is special
1950 * code for that later.
1952 "TITLE/URL=", GST_TAG_HOMEPAGE}, {
1953 "ARTIST/URL=", GST_TAG_HOMEPAGE}, {
1954 "COPYRIGHT/URL=", GST_TAG_COPYRIGHT_URI}, {
1955 "LICENSE/URL=", GST_TAG_LICENSE_URI}, {
1956 "LICENSE/URL=", GST_TAG_LICENSE_URI}
1960 gchar *value = NULL;
1962 gchar *name_with_parent = NULL;
1963 GstTagList *child_taglist = NULL;
1965 DEBUG_ELEMENT_START (common, ebml, "SimpleTag");
1967 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1968 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
1973 child_taglist = *p_taglist;
1975 child_taglist = gst_tag_list_new_empty ();
1977 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1978 /* read all sub-entries */
1980 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1984 case GST_MATROSKA_ID_TAGNAME:
1987 ret = gst_ebml_read_ascii (ebml, &id, &tag);
1988 GST_DEBUG_OBJECT (common->sinkpad, "TagName: %s", GST_STR_NULL (tag));
1989 g_free (name_with_parent);
1991 name_with_parent = g_strdup_printf ("%s/%s", parent, tag);
1993 name_with_parent = g_strdup (tag);
1996 case GST_MATROSKA_ID_TAGSTRING:
1999 ret = gst_ebml_read_utf8 (ebml, &id, &value);
2000 GST_DEBUG_OBJECT (common->sinkpad, "TagString: %s",
2001 GST_STR_NULL (value));
2004 case GST_MATROSKA_ID_SIMPLETAG:
2005 /* Recursive SimpleTag */
2006 /* This implementation requires tag name of _this_ tag to be known
2007 * in order to read its children. It's not in the spec, just the way
2008 * the code is written.
2010 if (name_with_parent != NULL) {
2011 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2012 ebml, &child_taglist, name_with_parent);
2018 ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag",
2022 case GST_MATROSKA_ID_TAGLANGUAGE:
2023 case GST_MATROSKA_ID_TAGDEFAULT:
2024 case GST_MATROSKA_ID_TAGBINARY:
2025 ret = gst_ebml_read_skip (ebml);
2030 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
2032 if (parent && tag && value && *value != '\0') {
2033 /* Don't bother mapping children tags - parent will do that */
2035 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2036 key_val = g_strdup_printf ("%s=%s", name_with_parent, value);
2037 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2038 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2040 } else if (tag && value && *value != '\0') {
2041 gboolean matched = FALSE;
2044 for (i = 0; !matched && i < G_N_ELEMENTS (tag_conv); i++) {
2045 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2047 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2049 if (strcmp (tagname_mkv, tag) == 0) {
2050 GValue dest = { 0, };
2051 GType dest_type = gst_tag_get_type (tagname_gst);
2053 /* Ensure that any date string is complete */
2054 if (dest_type == G_TYPE_DATE) {
2055 guint year = 1901, month = 1, day = 1;
2057 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
2059 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
2061 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
2065 g_value_init (&dest, dest_type);
2066 if (gst_value_deserialize (&dest, value)) {
2067 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2068 tagname_gst, &dest, NULL);
2070 GST_WARNING_OBJECT (common->sinkpad, "Can't transform tag '%s' with "
2071 "value '%s' to target type '%s'", tag, value,
2072 g_type_name (dest_type));
2074 g_value_unset (&dest);
2080 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2081 key_val = g_strdup_printf ("%s=%s", tag, value);
2082 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2083 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2089 /* Map children tags. This only supports top-anchored mapping. That is,
2090 * we start at toplevel tag (this tag), and see how its combinations
2091 * with its children can be mapped. Which means that grandchildren
2092 * are also combined here, with _this_ tag taken into consideration.
2093 * If grandchildren can be combined only with children, that combination
2096 gint child_tags_n = gst_tag_list_n_tags (child_taglist);
2097 if (child_tags_n > 0) {
2099 for (i = 0; i < child_tags_n; i++) {
2101 const gchar *child_name = gst_tag_list_nth_tag_name (child_taglist, i);
2102 guint taglen = gst_tag_list_get_tag_size (child_taglist, child_name);
2103 for (j = 0; j < taglen; j++) {
2105 gboolean matched = FALSE;
2106 gchar *val_pre, *val_post;
2109 if (!gst_tag_list_get_string_index (child_taglist, child_name,
2112 if (!strchr (val, '=')) {
2116 val_post = g_strdup (strchr (val, '=') + 1);
2117 val_pre = g_strdup (val);
2118 *(strchr (val_pre, '=') + 1) = '\0';
2120 for (k = 0; !matched && k < G_N_ELEMENTS (child_tag_conv); k++) {
2121 const gchar *tagname_gst = child_tag_conv[k].gstreamer_tagname;
2123 const gchar *tagname_mkv = child_tag_conv[k].matroska_tagname;
2125 /* TODO: Once "key[lc]=value" form support is implemented,
2126 * strip [lc] here. It can't be used in combined tags.
2127 * If a tag is not combined, leave [lc] as it is.
2129 if (strcmp (tagname_mkv, val_pre) == 0) {
2130 GValue dest = { 0, };
2131 GType dest_type = gst_tag_get_type (tagname_gst);
2133 g_value_init (&dest, dest_type);
2134 if (gst_value_deserialize (&dest, val_post)) {
2135 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2136 tagname_gst, &dest, NULL);
2138 GST_WARNING_OBJECT (common->sinkpad,
2139 "Can't transform complex tag '%s' " "to target type '%s'",
2140 val, g_type_name (dest_type));
2142 g_value_unset (&dest);
2147 gchar *last_slash = strrchr (val_pre, '/');
2150 if (strcmp (last_slash, "EMAIL=") == 0 ||
2151 strcmp (last_slash, "PHONE=") == 0 ||
2152 strcmp (last_slash, "ADDRESS=") == 0 ||
2153 strcmp (last_slash, "FAX=") == 0) {
2154 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2155 GST_TAG_CONTACT, val_post, NULL);
2161 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2162 GST_TAG_EXTENDED_COMMENT, val, NULL);
2169 gst_tag_list_unref (child_taglist);
2174 g_free (name_with_parent);
2181 gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
2182 gint * a, gint * v, gint * s)
2185 gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
2187 for (i = 0; i < common->src->len; i++) {
2188 GstMatroskaTrackContext *stream;
2190 stream = g_ptr_array_index (common->src, i);
2191 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
2193 else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
2195 else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
2196 subtitle_streams += 1;
2200 *s = subtitle_streams;
2205 gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
2206 const gchar * tag, gpointer user_data)
2210 TargetTypeContext *ctx = (TargetTypeContext *) user_data;
2212 vallen = gst_tag_list_get_tag_size (list, tag);
2216 for (i = 0; i < vallen; i++) {
2217 const GValue *val_ref;
2219 val_ref = gst_tag_list_get_value_index (list, tag, i);
2220 if (val_ref == NULL)
2223 /* TODO: use the optional ctx->target_type somehow */
2224 if (strcmp (tag, GST_TAG_TITLE) == 0) {
2225 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2226 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2227 GST_TAG_SHOW_NAME, val_ref);
2229 } else if (ctx->target_type_value >= 50) {
2230 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2231 GST_TAG_ALBUM, val_ref);
2234 } else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
2235 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2236 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2237 GST_TAG_SHOW_SORTNAME, val_ref);
2239 } else if (ctx->target_type_value >= 50) {
2240 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2241 GST_TAG_ALBUM_SORTNAME, val_ref);
2244 } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
2245 if (ctx->target_type_value >= 50) {
2246 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2247 GST_TAG_ALBUM_ARTIST, val_ref);
2250 } else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
2251 if (ctx->target_type_value >= 50) {
2252 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2253 GST_TAG_ALBUM_ARTIST_SORTNAME, val_ref);
2256 } else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
2257 if (ctx->target_type_value >= 60) {
2258 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2259 GST_TAG_ALBUM_VOLUME_COUNT, val_ref);
2262 } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
2263 if (ctx->target_type_value >= 60 && !ctx->audio_only) {
2264 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2265 GST_TAG_SHOW_SEASON_NUMBER, val_ref);
2267 } else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
2268 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2269 GST_TAG_SHOW_EPISODE_NUMBER, val_ref);
2271 } else if (ctx->target_type_value >= 50) {
2272 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2273 GST_TAG_ALBUM_VOLUME_NUMBER, val_ref);
2277 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, val_ref);
2283 gst_matroska_read_common_apply_target_type (GstMatroskaReadCommon * common,
2284 GstTagList * taglist, guint64 target_type_value, gchar * target_type)
2286 TargetTypeContext ctx;
2291 gst_matroska_read_common_count_streams (common, &a, &v, &s);
2293 ctx.audio_only = (a > 0 && v == 0 && s == 0);
2294 ctx.result = gst_tag_list_new_empty ();
2295 ctx.target_type_value = target_type_value;
2296 ctx.target_type = target_type;
2298 gst_tag_list_foreach (taglist,
2299 gst_matroska_read_common_apply_target_type_foreach, &ctx);
2301 gst_tag_list_unref (taglist);
2306 static GstFlowReturn
2307 gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
2308 GstEbmlRead * ebml, GstTagList ** p_taglist)
2312 GArray *chapter_targets, *edition_targets, *track_targets;
2313 GstTagList *taglist;
2315 guint64 target_type_value = 50;
2316 gchar *target_type = NULL;
2318 DEBUG_ELEMENT_START (common, ebml, "Tag");
2320 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2321 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2325 edition_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2326 chapter_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2327 track_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2328 taglist = gst_tag_list_new_empty ();
2331 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2332 /* read all sub-entries */
2334 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2338 case GST_MATROSKA_ID_SIMPLETAG:
2339 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2340 ebml, &taglist, NULL);
2343 case GST_MATROSKA_ID_TARGETS:
2344 g_free (target_type);
2346 target_type_value = 50;
2347 ret = gst_matroska_read_common_parse_metadata_targets (common, ebml,
2348 edition_targets, chapter_targets, track_targets,
2349 &target_type_value, &target_type);
2353 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tag", id);
2358 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2360 taglist = gst_matroska_read_common_apply_target_type (common, taglist,
2361 target_type_value, target_type);
2362 g_free (target_type);
2364 /* if tag is chapter/edition specific - try to find that entry */
2365 if (G_UNLIKELY (chapter_targets->len > 0 || edition_targets->len > 0 ||
2366 track_targets->len > 0)) {
2368 if (chapter_targets->len > 0 || edition_targets->len > 0) {
2369 if (common->toc == NULL)
2370 GST_WARNING_OBJECT (common->sinkpad,
2371 "Found chapter/edition specific tag, but TOC is not present");
2373 cur = gst_toc_get_entries (common->toc);
2374 while (cur != NULL) {
2375 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
2376 chapter_targets, taglist);
2379 common->toc_updated = TRUE;
2382 for (i = 0; i < track_targets->len; i++) {
2384 gboolean found = FALSE;
2385 guint64 tgt = g_array_index (track_targets, guint64, i);
2387 for (j = 0; j < common->src->len; j++) {
2388 GstMatroskaTrackContext *stream = g_ptr_array_index (common->src, j);
2390 if (stream->uid == tgt) {
2391 gst_tag_list_insert (stream->tags, taglist, GST_TAG_MERGE_REPLACE);
2392 stream->tags_changed = TRUE;
2397 /* Cache the track taglist: possibly belongs to a track that will be parsed
2398 later in gst_matroska_demux.c:gst_matroska_demux_add_stream (...) */
2399 gpointer track_uid = GUINT_TO_POINTER (tgt);
2400 GstTagList *cached_taglist =
2401 g_hash_table_lookup (common->cached_track_taglists, track_uid);
2403 gst_tag_list_insert (cached_taglist, taglist, GST_TAG_MERGE_REPLACE);
2405 gst_tag_list_ref (taglist);
2406 g_hash_table_insert (common->cached_track_taglists, track_uid,
2409 GST_DEBUG_OBJECT (common->sinkpad,
2410 "Found track-specific tag(s), but track %" G_GUINT64_FORMAT
2411 " is not known yet, caching", tgt);
2415 gst_tag_list_insert (*p_taglist, taglist, GST_TAG_MERGE_APPEND);
2417 gst_tag_list_unref (taglist);
2418 g_array_unref (chapter_targets);
2419 g_array_unref (edition_targets);
2420 g_array_unref (track_targets);
2426 gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
2427 GstElement * el, GstEbmlRead * ebml)
2429 GstTagList *taglist;
2430 GstFlowReturn ret = GST_FLOW_OK;
2435 /* Make sure we don't parse a tags element twice and
2436 * post it's tags twice */
2437 curpos = gst_ebml_read_get_pos (ebml);
2438 for (l = common->tags_parsed; l; l = l->next) {
2439 guint64 *pos = l->data;
2441 if (*pos == curpos) {
2442 GST_DEBUG_OBJECT (common->sinkpad,
2443 "Skipping already parsed Tags at offset %" G_GUINT64_FORMAT, curpos);
2448 common->tags_parsed =
2449 g_list_prepend (common->tags_parsed, g_slice_new (guint64));
2450 *((guint64 *) common->tags_parsed->data) = curpos;
2453 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2454 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2458 taglist = gst_tag_list_new_empty ();
2459 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
2460 common->toc_updated = FALSE;
2462 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2463 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2467 case GST_MATROSKA_ID_TAG:
2468 ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml,
2473 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id);
2475 /* FIXME: Use to limit the tags to specific pads */
2479 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2481 if (G_LIKELY (!gst_tag_list_is_empty (taglist)))
2482 gst_matroska_read_common_found_global_tag (common, el, taglist);
2484 gst_tag_list_unref (taglist);
2489 static GstFlowReturn
2490 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
2491 peek, const guint8 ** data)
2493 /* Caller needs to gst_adapter_unmap. */
2494 *data = gst_adapter_map (common->adapter, peek);
2496 return GST_FLOW_EOS;
2502 * Calls pull_range for (offset,size) without advancing our offset
2505 gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
2506 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
2510 /* Caching here actually makes much less difference than one would expect.
2511 * We do it mainly to avoid pulling buffers of 1 byte all the time */
2512 if (common->cached_buffer) {
2513 guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
2514 gsize cache_size = gst_buffer_get_size (common->cached_buffer);
2516 if (cache_offset <= common->offset &&
2517 (common->offset + size) <= (cache_offset + cache_size)) {
2519 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2520 GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
2522 if (!common->cached_data) {
2523 gst_buffer_map (common->cached_buffer, &common->cached_map,
2525 common->cached_data = common->cached_map.data;
2527 *bytes = common->cached_data + common->offset - cache_offset;
2531 /* not enough data in the cache, free cache and get a new one */
2532 if (common->cached_data) {
2533 gst_buffer_unmap (common->cached_buffer, &common->cached_map);
2534 common->cached_data = NULL;
2536 gst_buffer_unref (common->cached_buffer);
2537 common->cached_buffer = NULL;
2540 /* refill the cache */
2541 ret = gst_pad_pull_range (common->sinkpad, common->offset,
2542 MAX (size, 64 * 1024), &common->cached_buffer);
2543 if (ret != GST_FLOW_OK) {
2544 common->cached_buffer = NULL;
2548 if (gst_buffer_get_size (common->cached_buffer) >= size) {
2550 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2551 GST_BUFFER_COPY_ALL, 0, size);
2553 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2554 common->cached_data = common->cached_map.data;
2555 *bytes = common->cached_data;
2560 /* Not possible to get enough data, try a last time with
2561 * requesting exactly the size we need */
2562 gst_buffer_unref (common->cached_buffer);
2563 common->cached_buffer = NULL;
2566 gst_pad_pull_range (common->sinkpad, common->offset, size,
2567 &common->cached_buffer);
2568 if (ret != GST_FLOW_OK) {
2569 GST_DEBUG_OBJECT (common->sinkpad, "pull_range returned %d", ret);
2577 if (gst_buffer_get_size (common->cached_buffer) < size) {
2578 GST_WARNING_OBJECT (common->sinkpad, "Dropping short buffer at offset %"
2579 G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2580 common->offset, size, gst_buffer_get_size (common->cached_buffer));
2582 gst_buffer_unref (common->cached_buffer);
2583 common->cached_buffer = NULL;
2588 return GST_FLOW_EOS;
2592 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2593 GST_BUFFER_COPY_ALL, 0, size);
2595 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2596 common->cached_data = common->cached_map.data;
2597 *bytes = common->cached_data;
2603 static GstFlowReturn
2604 gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek,
2607 return gst_matroska_read_common_peek_bytes (common, common->offset, peek,
2612 gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
2613 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2615 return gst_ebml_peek_id_length (_id, _length, _needed,
2616 (GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
2621 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
2622 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2626 ret = gst_ebml_peek_id_length (_id, _length, _needed,
2627 (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
2628 el, common->offset);
2630 gst_adapter_unmap (common->adapter);
2635 static GstFlowReturn
2636 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
2637 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2639 GstMatroskaTrackEncoding enc = { 0, };
2643 DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
2644 /* Set default values */
2646 /* All other default values are 0 */
2648 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2649 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2653 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2654 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2658 case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
2661 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2664 if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
2666 GST_ERROR_OBJECT (common->sinkpad,
2667 "ContentEncodingOrder %" G_GUINT64_FORMAT
2668 "is not unique for track %" G_GUINT64_FORMAT, num, context->num);
2669 ret = GST_FLOW_ERROR;
2673 GST_DEBUG_OBJECT (common->sinkpad,
2674 "ContentEncodingOrder: %" G_GUINT64_FORMAT, num);
2678 case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
2681 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2684 if (num > 7 || num == 0) {
2685 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentEncodingScope %"
2686 G_GUINT64_FORMAT, num);
2687 ret = GST_FLOW_ERROR;
2691 GST_DEBUG_OBJECT (common->sinkpad,
2692 "ContentEncodingScope: %" G_GUINT64_FORMAT, num);
2697 case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
2700 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2704 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentEncodingType %"
2705 G_GUINT64_FORMAT, num);
2706 ret = GST_FLOW_ERROR;
2708 } else if (num != 0) {
2709 GST_ERROR_OBJECT (common->sinkpad,
2710 "Encrypted tracks are not supported yet");
2711 ret = GST_FLOW_ERROR;
2714 GST_DEBUG_OBJECT (common->sinkpad,
2715 "ContentEncodingType: %" G_GUINT64_FORMAT, num);
2719 case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
2721 DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
2723 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
2726 while (ret == GST_FLOW_OK &&
2727 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2728 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2732 case GST_MATROSKA_ID_CONTENTCOMPALGO:{
2735 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
2739 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentCompAlgo %"
2740 G_GUINT64_FORMAT, num);
2741 ret = GST_FLOW_ERROR;
2744 GST_DEBUG_OBJECT (common->sinkpad,
2745 "ContentCompAlgo: %" G_GUINT64_FORMAT, num);
2746 enc.comp_algo = num;
2750 case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
2755 gst_ebml_read_binary (ebml, &id, &data,
2756 &size)) != GST_FLOW_OK) {
2759 enc.comp_settings = data;
2760 enc.comp_settings_length = size;
2761 GST_DEBUG_OBJECT (common->sinkpad,
2762 "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
2766 GST_WARNING_OBJECT (common->sinkpad,
2767 "Unknown ContentCompression subelement 0x%x - ignoring", id);
2768 ret = gst_ebml_read_skip (ebml);
2772 DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
2776 case GST_MATROSKA_ID_CONTENTENCRYPTION:
2777 GST_ERROR_OBJECT (common->sinkpad,
2778 "Encrypted tracks not yet supported");
2779 gst_ebml_read_skip (ebml);
2780 ret = GST_FLOW_ERROR;
2783 GST_WARNING_OBJECT (common->sinkpad,
2784 "Unknown ContentEncoding subelement 0x%x - ignoring", id);
2785 ret = gst_ebml_read_skip (ebml);
2790 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2791 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2794 /* TODO: Check if the combination of values is valid */
2796 g_array_append_val (context->encodings, enc);
2802 gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
2803 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2808 DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
2810 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2811 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2815 context->encodings =
2816 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
2818 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2819 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2823 case GST_MATROSKA_ID_CONTENTENCODING:
2824 ret = gst_matroska_read_common_read_track_encoding (common, ebml,
2828 GST_WARNING_OBJECT (common->sinkpad,
2829 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
2830 ret = gst_ebml_read_skip (ebml);
2835 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2836 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2839 /* Sort encodings according to their order */
2840 g_array_sort (context->encodings,
2841 (GCompareFunc) gst_matroska_read_common_encoding_cmp);
2843 return gst_matroska_decode_content_encodings (context->encodings);
2847 gst_matroska_read_common_free_parsed_el (gpointer mem, gpointer user_data)
2849 g_slice_free (guint64, mem);
2853 gst_matroska_read_common_init (GstMatroskaReadCommon * ctx)
2856 ctx->writing_app = NULL;
2857 ctx->muxing_app = NULL;
2859 ctx->global_tags = NULL;
2860 ctx->adapter = gst_adapter_new ();
2861 ctx->cached_track_taglists =
2862 g_hash_table_new_full (NULL, NULL, NULL,
2863 (GDestroyNotify) gst_tag_list_unref);
2867 gst_matroska_read_common_finalize (GstMatroskaReadCommon * ctx)
2870 g_ptr_array_free (ctx->src, TRUE);
2874 if (ctx->global_tags) {
2875 gst_tag_list_unref (ctx->global_tags);
2876 ctx->global_tags = NULL;
2879 g_object_unref (ctx->adapter);
2880 g_hash_table_remove_all (ctx->cached_track_taglists);
2881 g_hash_table_unref (ctx->cached_track_taglists);
2886 gst_matroska_read_common_reset (GstElement * element,
2887 GstMatroskaReadCommon * ctx)
2891 GST_LOG_OBJECT (ctx->sinkpad, "resetting read context");
2894 ctx->state = GST_MATROSKA_READ_STATE_START;
2896 /* clean up existing streams if any */
2898 g_assert (ctx->src->len == ctx->num_streams);
2899 for (i = 0; i < ctx->src->len; i++) {
2900 GstMatroskaTrackContext *context = g_ptr_array_index (ctx->src, i);
2902 if (context->pad != NULL)
2903 gst_element_remove_pad (element, context->pad);
2905 gst_caps_replace (&context->caps, NULL);
2906 gst_matroska_track_free (context);
2908 g_ptr_array_free (ctx->src, TRUE);
2910 ctx->src = g_ptr_array_new ();
2911 ctx->num_streams = 0;
2913 /* reset media info */
2914 g_free (ctx->writing_app);
2915 ctx->writing_app = NULL;
2916 g_free (ctx->muxing_app);
2917 ctx->muxing_app = NULL;
2919 /* reset stream type */
2920 ctx->is_webm = FALSE;
2921 ctx->has_video = FALSE;
2925 g_array_free (ctx->index, TRUE);
2930 ctx->time_scale = 1000000;
2931 ctx->created = G_MININT64;
2933 /* cues/tracks/segmentinfo */
2934 ctx->index_parsed = FALSE;
2935 ctx->segmentinfo_parsed = FALSE;
2936 ctx->attachments_parsed = FALSE;
2937 ctx->chapters_parsed = FALSE;
2940 ctx->global_tags_changed = FALSE;
2941 g_list_foreach (ctx->tags_parsed,
2942 (GFunc) gst_matroska_read_common_free_parsed_el, NULL);
2943 g_list_free (ctx->tags_parsed);
2944 ctx->tags_parsed = NULL;
2945 if (ctx->global_tags) {
2946 gst_tag_list_unref (ctx->global_tags);
2948 ctx->global_tags = gst_tag_list_new_empty ();
2949 gst_tag_list_set_scope (ctx->global_tags, GST_TAG_SCOPE_GLOBAL);
2951 gst_segment_init (&ctx->segment, GST_FORMAT_TIME);
2953 ctx->start_resync_offset = -1;
2954 ctx->state_to_restore = -1;
2956 if (ctx->cached_buffer) {
2957 if (ctx->cached_data) {
2958 gst_buffer_unmap (ctx->cached_buffer, &ctx->cached_map);
2959 ctx->cached_data = NULL;
2961 gst_buffer_unref (ctx->cached_buffer);
2962 ctx->cached_buffer = NULL;
2965 /* free chapters TOC if any */
2967 gst_toc_unref (ctx->toc);
2972 /* call with object lock held */
2974 gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
2975 GstClockTime time, gboolean full)
2979 GST_DEBUG_OBJECT (common->sinkpad, "resetting stream state");
2981 g_assert (common->src->len == common->num_streams);
2982 for (i = 0; i < common->src->len; i++) {
2983 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2984 context->pos = time;
2985 context->set_discont = TRUE;
2986 context->eos = FALSE;
2987 context->from_time = GST_CLOCK_TIME_NONE;
2988 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2989 GstMatroskaTrackVideoContext *videocontext =
2990 (GstMatroskaTrackVideoContext *) context;
2991 /* demux object lock held by caller */
2992 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2998 gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
3003 g_assert (common->src->len == common->num_streams);
3004 for (i = 0; i < common->src->len; i++) {
3005 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
3007 if (context->num == num)