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, "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, "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_OK && result != Z_STREAM_END) {
110 GST_WARNING ("zlib decompression failed.");
112 inflateEnd (&zstream);
116 new_data = g_realloc (new_data, new_size);
117 zstream.next_out = (Bytef *) (new_data + zstream.total_out);
118 zstream.avail_out += 4000;
119 } while (zstream.avail_in != 0 && result != Z_STREAM_END);
121 if (result != Z_STREAM_END) {
125 new_size = zstream.total_out;
126 inflateEnd (&zstream);
129 GST_WARNING ("zlib encoded tracks not supported.");
133 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
135 /* bzip2 encoded data */
140 bzstream.bzalloc = NULL;
141 bzstream.bzfree = NULL;
142 bzstream.opaque = NULL;
145 if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
146 GST_WARNING ("bzip2 initialization failed.");
151 bzstream.next_in = (char *) data;
152 bzstream.avail_in = orig_size;
153 new_size = orig_size;
154 new_data = g_malloc (new_size);
155 bzstream.avail_out = new_size;
156 bzstream.next_out = (char *) new_data;
159 result = BZ2_bzDecompress (&bzstream);
160 if (result != BZ_OK && result != BZ_STREAM_END) {
161 GST_WARNING ("bzip2 decompression failed.");
163 BZ2_bzDecompressEnd (&bzstream);
167 new_data = g_realloc (new_data, new_size);
168 bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
169 bzstream.avail_out += 4000;
170 } while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
172 if (result != BZ_STREAM_END) {
176 new_size = bzstream.total_out_lo32;
177 BZ2_bzDecompressEnd (&bzstream);
180 GST_WARNING ("bzip2 encoded tracks not supported.");
184 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
185 /* lzo encoded data */
187 int orig_size, out_size;
192 new_data = g_malloc (new_size);
198 result = lzo1x_decode (new_data, &out_size, data, &orig_size);
202 new_data = g_realloc (new_data, new_size);
204 } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
206 new_size -= out_size;
208 if (result != LZO_OUTPUT_FULL) {
209 GST_WARNING ("lzo decompression failed");
216 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
217 /* header stripped encoded data */
218 if (enc->comp_settings_length > 0) {
219 new_data = g_malloc (size + enc->comp_settings_length);
220 new_size = size + enc->comp_settings_length;
222 memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
223 memcpy (new_data + enc->comp_settings_length, data, size);
226 GST_ERROR ("invalid compression algorithm %d", algo);
236 *data_out = new_data;
237 *size_out = new_size;
244 gst_matroska_decode_content_encodings (GArray * encodings)
248 if (encodings == NULL)
251 for (i = 0; i < encodings->len; i++) {
252 GstMatroskaTrackEncoding *enc =
253 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
254 gpointer data = NULL;
257 if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
261 /* Encryption not supported yet */
263 return GST_FLOW_ERROR;
265 if (i + 1 >= encodings->len)
266 return GST_FLOW_ERROR;
268 if (enc->comp_settings_length == 0)
271 data = enc->comp_settings;
272 size = enc->comp_settings_length;
274 if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
275 return GST_FLOW_ERROR;
277 g_free (enc->comp_settings);
279 enc->comp_settings = data;
280 enc->comp_settings_length = size;
287 gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
288 gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
295 g_return_val_if_fail (encodings != NULL, FALSE);
296 g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
297 g_return_val_if_fail (size_out != NULL, FALSE);
302 for (i = 0; i < encodings->len; i++) {
303 GstMatroskaTrackEncoding *enc =
304 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
305 gpointer new_data = NULL;
308 if ((enc->scope & scope) == 0)
311 /* Encryption not supported yet */
312 if (enc->type != 0) {
321 gst_matroska_decompress_data (enc, &new_data, &new_size,
327 if ((data == *data_out && free) || (data != *data_out))
335 if ((data == *data_out && free) || (data != *data_out))
349 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
351 if (i1->time < i2->time)
353 else if (i1->time > i2->time)
355 else if (i1->block < i2->block)
357 else if (i1->block > i2->block)
364 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
367 if (i1->time < *time)
369 else if (i1->time > *time)
376 gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
377 GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
378 gint * _entry_index, gboolean next)
380 GstMatroskaIndex *entry = NULL;
383 if (!common->index || !common->index->len)
386 /* find entry just before or at the requested position */
387 if (track && track->index_table)
388 index = track->index_table;
390 index = common->index;
393 gst_util_array_binary_search (index->data, index->len,
394 sizeof (GstMatroskaIndex),
395 (GCompareDataFunc) gst_matroska_index_seek_find,
396 next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL);
402 entry = &g_array_index (index, GstMatroskaIndex, 0);
409 *_entry_index = entry - (GstMatroskaIndex *) index->data;
415 gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
416 GstMatroskaTrackEncoding * b)
418 if (b->order > a->order)
420 else if (b->order < a->order)
427 gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
432 if (encodings == NULL || encodings->len == 0)
435 for (i = 0; i < encodings->len; i++)
436 if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
442 /* takes ownership of taglist */
444 gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
445 GstElement * el, GstTagList * taglist)
447 if (common->global_tags) {
448 /* nothing sent yet, add to cache */
449 gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
450 gst_tag_list_unref (taglist);
452 GstEvent *tag_event = gst_event_new_tag (taglist);
455 /* hm, already sent, no need to cache and wait anymore */
456 GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
459 for (i = 0; i < common->src->len; i++) {
460 GstMatroskaTrackContext *stream;
462 stream = g_ptr_array_index (common->src, i);
463 gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
466 gst_event_unref (tag_event);
471 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
475 if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
477 GST_DEBUG_OBJECT (common, "no upstream length");
482 /* determine track to seek in */
483 GstMatroskaTrackContext *
484 gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
485 GstMatroskaTrackContext * track)
489 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
492 for (i = 0; i < common->src->len; i++) {
493 GstMatroskaTrackContext *stream;
495 stream = g_ptr_array_index (common->src, i);
496 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
503 /* skip unknown or alike element */
505 gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
506 GstEbmlRead * ebml, const gchar * parent_name, guint id)
508 if (id == GST_EBML_ID_VOID) {
509 GST_DEBUG_OBJECT (common, "Skipping EBML Void element");
510 } else if (id == GST_EBML_ID_CRC32) {
511 GST_DEBUG_OBJECT (common, "Skipping EBML CRC32 element");
513 GST_WARNING_OBJECT (common,
514 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
517 return gst_ebml_read_skip (ebml);
521 gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
522 GstEbmlRead * ebml, GstTagList * taglist)
526 gchar *description = NULL;
527 gchar *filename = NULL;
528 gchar *mimetype = NULL;
532 DEBUG_ELEMENT_START (common, ebml, "AttachedFile");
534 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
535 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
539 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
540 /* read all sub-entries */
542 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
546 case GST_MATROSKA_ID_FILEDESCRIPTION:
548 GST_WARNING_OBJECT (common, "FileDescription can only appear once");
552 ret = gst_ebml_read_utf8 (ebml, &id, &description);
553 GST_DEBUG_OBJECT (common, "FileDescription: %s",
554 GST_STR_NULL (description));
556 case GST_MATROSKA_ID_FILENAME:
558 GST_WARNING_OBJECT (common, "FileName can only appear once");
562 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
564 GST_DEBUG_OBJECT (common, "FileName: %s", GST_STR_NULL (filename));
566 case GST_MATROSKA_ID_FILEMIMETYPE:
568 GST_WARNING_OBJECT (common, "FileMimeType can only appear once");
572 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
573 GST_DEBUG_OBJECT (common, "FileMimeType: %s", GST_STR_NULL (mimetype));
575 case GST_MATROSKA_ID_FILEDATA:
577 GST_WARNING_OBJECT (common, "FileData can only appear once");
581 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
582 GST_DEBUG_OBJECT (common, "FileData of size %" G_GUINT64_FORMAT,
587 ret = gst_matroska_read_common_parse_skip (common, ebml,
590 case GST_MATROSKA_ID_FILEUID:
591 ret = gst_ebml_read_skip (ebml);
596 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
598 if (filename && mimetype && data && datalen > 0) {
599 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
600 GstBuffer *tagbuffer = NULL;
601 GstSample *tagsample = NULL;
602 GstStructure *info = NULL;
603 GstCaps *caps = NULL;
604 gchar *filename_lc = g_utf8_strdown (filename, -1);
606 GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
607 "filename '%s', mimetype '%s', description '%s', "
608 "size %" G_GUINT64_FORMAT, filename, mimetype,
609 GST_STR_NULL (description), datalen);
611 /* TODO: better heuristics for different image types */
612 if (strstr (filename_lc, "cover")) {
613 if (strstr (filename_lc, "back"))
614 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
616 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
617 } else if (g_str_has_prefix (mimetype, "image/") ||
618 g_str_has_suffix (filename_lc, "png") ||
619 g_str_has_suffix (filename_lc, "jpg") ||
620 g_str_has_suffix (filename_lc, "jpeg") ||
621 g_str_has_suffix (filename_lc, "gif") ||
622 g_str_has_suffix (filename_lc, "bmp")) {
623 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
625 g_free (filename_lc);
627 /* First try to create an image tag buffer from this */
628 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
630 gst_tag_image_data_to_image_sample (data, datalen, image_type);
633 image_type = GST_TAG_IMAGE_TYPE_NONE;
636 tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
637 caps = gst_caps_ref (gst_sample_get_caps (tagsample));
638 info = gst_structure_copy (gst_sample_get_info (tagsample));
639 gst_sample_unref (tagsample);
643 /* if this failed create an attachment buffer */
645 tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
647 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
649 caps = gst_caps_new_empty_simple (mimetype);
652 /* Set filename and description in the info */
654 info = gst_structure_new_empty ("GstTagImageInfo");
656 gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
658 gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
660 tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
662 gst_buffer_unref (tagbuffer);
663 gst_caps_unref (caps);
665 GST_DEBUG_OBJECT (common,
666 "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
668 /* and append to the tag list */
669 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
670 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
673 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
676 /* the list adds it own ref */
677 gst_sample_unref (tagsample);
683 g_free (description);
689 gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
690 GstElement * el, GstEbmlRead * ebml)
693 GstFlowReturn ret = GST_FLOW_OK;
696 DEBUG_ELEMENT_START (common, ebml, "Attachments");
698 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
699 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
703 taglist = gst_tag_list_new_empty ();
704 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
706 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
707 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
711 case GST_MATROSKA_ID_ATTACHEDFILE:
712 ret = gst_matroska_read_common_parse_attached_file (common, ebml,
717 ret = gst_matroska_read_common_parse_skip (common, ebml,
722 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
724 if (gst_tag_list_n_tags (taglist) > 0) {
725 GST_DEBUG_OBJECT (common, "Storing attachment tags");
726 gst_matroska_read_common_found_global_tag (common, el, taglist);
728 GST_DEBUG_OBJECT (common, "No valid attachments found");
729 gst_tag_list_unref (taglist);
732 common->attachments_parsed = TRUE;
738 gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
739 GArray * edition_targets, GArray * chapter_targtes, GstTagList * tags)
749 (gst_toc_entry_get_entry_type (entry) ==
750 GST_TOC_ENTRY_TYPE_EDITION) ? edition_targets : chapter_targtes;
752 etags = gst_tag_list_new_empty ();
754 for (i = 0; i < targets->len; ++i) {
755 tgt = g_array_index (targets, guint64, i);
758 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
760 uid = g_strdup_printf ("%" G_GUINT64_FORMAT, tgt);
761 if (g_strcmp0 (gst_toc_entry_get_uid (entry), uid) == 0)
762 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
767 gst_toc_entry_merge_tags (entry, etags, GST_TAG_MERGE_APPEND);
769 cur = gst_toc_entry_get_sub_entries (entry);
770 while (cur != NULL) {
771 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
772 chapter_targtes, tags);
778 gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
779 GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
780 GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
782 GstFlowReturn ret = GST_FLOW_OK;
788 DEBUG_ELEMENT_START (common, ebml, "TagTargets");
790 *target_type_value = 50;
793 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
794 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
798 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
799 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
803 case GST_MATROSKA_ID_TARGETCHAPTERUID:
804 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
805 g_array_append_val (chapter_targets, uid);
808 case GST_MATROSKA_ID_TARGETEDITIONUID:
809 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
810 g_array_append_val (edition_targets, uid);
813 case GST_MATROSKA_ID_TARGETTRACKUID:
814 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
815 g_array_append_val (track_targets, uid);
818 case GST_MATROSKA_ID_TARGETTYPEVALUE:
819 if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
820 *target_type_value = tmp;
823 case GST_MATROSKA_ID_TARGETTYPE:
824 if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
825 if (*target_type != NULL)
826 g_free (*target_type);
833 gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
839 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
845 gst_matroska_read_common_postprocess_toc_entries (GList * toc_entries,
846 guint64 max, const gchar * parent_uid)
848 GstTocEntry *cur_info, *prev_info, *next_info;
849 GList *cur_list, *prev_list, *next_list;
850 gint64 cur_start, prev_start, stop;
852 cur_list = toc_entries;
853 while (cur_list != NULL) {
854 cur_info = cur_list->data;
856 switch (gst_toc_entry_get_entry_type (cur_info)) {
857 case GST_TOC_ENTRY_TYPE_ANGLE:
858 case GST_TOC_ENTRY_TYPE_VERSION:
859 case GST_TOC_ENTRY_TYPE_EDITION:
860 /* in Matroska terms edition has duration of full track */
861 gst_toc_entry_set_start_stop_times (cur_info, 0, max);
863 gst_matroska_read_common_postprocess_toc_entries
864 (gst_toc_entry_get_sub_entries (cur_info), max,
865 gst_toc_entry_get_uid (cur_info));
868 case GST_TOC_ENTRY_TYPE_TITLE:
869 case GST_TOC_ENTRY_TYPE_TRACK:
870 case GST_TOC_ENTRY_TYPE_CHAPTER:
871 prev_list = cur_list->prev;
872 next_list = cur_list->next;
874 if (prev_list != NULL)
875 prev_info = prev_list->data;
879 if (next_list != NULL)
880 next_info = next_list->data;
884 /* updated stop time in previous chapter and it's subchapters */
885 if (prev_info != NULL) {
886 gst_toc_entry_get_start_stop_times (prev_info, &prev_start, &stop);
887 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
890 gst_toc_entry_set_start_stop_times (prev_info, prev_start, stop);
892 gst_matroska_read_common_postprocess_toc_entries
893 (gst_toc_entry_get_sub_entries (prev_info), cur_start,
894 gst_toc_entry_get_uid (prev_info));
897 /* updated stop time in current chapter and it's subchapters */
898 if (next_info == NULL) {
899 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
903 gst_toc_entry_set_start_stop_times (cur_info, cur_start, stop);
906 gst_matroska_read_common_postprocess_toc_entries
907 (gst_toc_entry_get_sub_entries (cur_info), stop,
908 gst_toc_entry_get_uid (cur_info));
911 case GST_TOC_ENTRY_TYPE_INVALID:
914 cur_list = cur_list->next;
919 gst_matroska_read_common_parse_chapter_titles (GstMatroskaReadCommon * common,
920 GstEbmlRead * ebml, GstTagList * titles)
924 GstFlowReturn ret = GST_FLOW_OK;
926 DEBUG_ELEMENT_START (common, ebml, "ChaptersTitles");
929 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
930 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
934 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
935 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
939 case GST_MATROSKA_ID_CHAPSTRING:
940 ret = gst_ebml_read_utf8 (ebml, &id, &title);
945 gst_matroska_read_common_parse_skip (common, ebml, "ChaptersTitles",
951 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
953 if (title != NULL && ret == GST_FLOW_OK)
954 gst_tag_list_add (titles, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title, NULL);
961 gst_matroska_read_common_parse_chapter_element (GstMatroskaReadCommon * common,
962 GstEbmlRead * ebml, GList ** subentries)
965 guint64 start_time = -1, stop_time = -1;
966 guint64 is_hidden = 0, is_enabled = 1, uid = 0;
967 GstFlowReturn ret = GST_FLOW_OK;
968 GstTocEntry *chapter_info;
971 GList *subsubentries = NULL, *l;
973 DEBUG_ELEMENT_START (common, ebml, "ChaptersElement");
975 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
976 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
980 tags = gst_tag_list_new_empty ();
982 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
983 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
987 case GST_MATROSKA_ID_CHAPTERUID:
988 ret = gst_ebml_read_uint (ebml, &id, &uid);
991 case GST_MATROSKA_ID_CHAPTERTIMESTART:
992 ret = gst_ebml_read_uint (ebml, &id, &start_time);
995 case GST_MATROSKA_ID_CHAPTERTIMESTOP:
996 ret = gst_ebml_read_uint (ebml, &id, &stop_time);
999 case GST_MATROSKA_ID_CHAPTERATOM:
1001 gst_matroska_read_common_parse_chapter_element (common, ebml,
1005 case GST_MATROSKA_ID_CHAPTERDISPLAY:
1007 gst_matroska_read_common_parse_chapter_titles (common, ebml, tags);
1010 case GST_MATROSKA_ID_CHAPTERFLAGHIDDEN:
1011 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1014 case GST_MATROSKA_ID_CHAPTERFLAGENABLED:
1015 ret = gst_ebml_read_uint (ebml, &id, &is_enabled);
1020 gst_matroska_read_common_parse_skip (common, ebml,
1021 "ChaptersElement", id);
1027 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1028 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1029 chapter_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid_str);
1032 gst_toc_entry_set_tags (chapter_info, tags);
1033 gst_toc_entry_set_start_stop_times (chapter_info, start_time, stop_time);
1035 for (l = subsubentries; l; l = l->next)
1036 gst_toc_entry_append_sub_entry (chapter_info, l->data);
1037 g_list_free (subsubentries);
1039 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
1041 /* start time is mandatory and has no default value,
1042 * so we should skip chapters without it */
1043 if (is_hidden == 0 && is_enabled > 0 &&
1044 start_time != -1 && ret == GST_FLOW_OK) {
1045 *subentries = g_list_append (*subentries, chapter_info);
1047 gst_toc_entry_unref (chapter_info);
1052 static GstFlowReturn
1053 gst_matroska_read_common_parse_chapter_edition (GstMatroskaReadCommon * common,
1054 GstEbmlRead * ebml, GstToc * toc)
1057 guint64 is_hidden = 0, uid = 0;
1058 GstFlowReturn ret = GST_FLOW_OK;
1059 GstTocEntry *edition_info;
1060 GList *subentries = NULL, *l;
1063 DEBUG_ELEMENT_START (common, ebml, "ChaptersEdition");
1065 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1066 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1070 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1071 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1075 case GST_MATROSKA_ID_EDITIONUID:
1076 ret = gst_ebml_read_uint (ebml, &id, &uid);
1079 case GST_MATROSKA_ID_CHAPTERATOM:
1081 gst_matroska_read_common_parse_chapter_element (common, ebml,
1085 case GST_MATROSKA_ID_EDITIONFLAGHIDDEN:
1086 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1091 gst_matroska_read_common_parse_skip (common, ebml,
1092 "ChaptersEdition", id);
1097 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1100 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1101 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1102 edition_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, uid_str);
1103 gst_toc_entry_set_start_stop_times (edition_info, -1, -1);
1106 for (l = subentries; l; l = l->next)
1107 gst_toc_entry_append_sub_entry (edition_info, l->data);
1108 g_list_free (subentries);
1110 if (is_hidden == 0 && subentries != NULL && ret == GST_FLOW_OK)
1111 gst_toc_append_entry (toc, edition_info);
1113 GST_DEBUG_OBJECT (common,
1114 "Skipping empty or hidden edition in the chapters TOC");
1115 gst_toc_entry_unref (edition_info);
1122 gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common,
1126 GstFlowReturn ret = GST_FLOW_OK;
1129 DEBUG_ELEMENT_START (common, ebml, "Chapters");
1131 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1132 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1136 /* FIXME: create CURRENT toc as well */
1137 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1139 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1140 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1144 case GST_MATROSKA_ID_EDITIONENTRY:
1146 gst_matroska_read_common_parse_chapter_edition (common, ebml, toc);
1151 gst_matroska_read_common_parse_skip (common, ebml, "Chapters", id);
1156 if (gst_toc_get_entries (toc) != NULL) {
1157 gst_matroska_read_common_postprocess_toc_entries (gst_toc_get_entries (toc),
1158 common->segment.duration, "");
1162 gst_toc_unref (toc);
1164 common->chapters_parsed = TRUE;
1166 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1171 gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
1179 /* this function is the first to be called */
1185 ret = gst_ebml_peek_id (ebml, &id);
1186 if (ret != GST_FLOW_OK)
1189 GST_DEBUG_OBJECT (common, "id: %08x", id);
1191 if (id != GST_EBML_ID_HEADER) {
1192 GST_ERROR_OBJECT (common, "Failed to read header");
1196 ret = gst_ebml_read_master (ebml, &id);
1197 if (ret != GST_FLOW_OK)
1200 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1201 ret = gst_ebml_peek_id (ebml, &id);
1202 if (ret != GST_FLOW_OK)
1206 /* is our read version uptodate? */
1207 case GST_EBML_ID_EBMLREADVERSION:{
1210 ret = gst_ebml_read_uint (ebml, &id, &num);
1211 if (ret != GST_FLOW_OK)
1213 if (num != GST_EBML_VERSION) {
1214 GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
1219 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1223 /* we only handle 8 byte lengths at max */
1224 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
1227 ret = gst_ebml_read_uint (ebml, &id, &num);
1228 if (ret != GST_FLOW_OK)
1230 if (num > sizeof (guint64)) {
1231 GST_ERROR_OBJECT (ebml,
1232 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
1233 return GST_FLOW_ERROR;
1235 GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
1239 /* we handle 4 byte IDs at max */
1240 case GST_EBML_ID_EBMLMAXIDLENGTH:{
1243 ret = gst_ebml_read_uint (ebml, &id, &num);
1244 if (ret != GST_FLOW_OK)
1246 if (num > sizeof (guint32)) {
1247 GST_ERROR_OBJECT (ebml,
1248 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
1249 return GST_FLOW_ERROR;
1251 GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
1255 case GST_EBML_ID_DOCTYPE:{
1258 ret = gst_ebml_read_ascii (ebml, &id, &text);
1259 if (ret != GST_FLOW_OK)
1262 GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
1270 case GST_EBML_ID_DOCTYPEREADVERSION:{
1273 ret = gst_ebml_read_uint (ebml, &id, &num);
1274 if (ret != GST_FLOW_OK)
1277 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1282 ret = gst_matroska_read_common_parse_skip (common, ebml,
1284 if (ret != GST_FLOW_OK)
1288 /* we ignore these two, as they don't tell us anything we care about */
1289 case GST_EBML_ID_EBMLVERSION:
1290 case GST_EBML_ID_DOCTYPEVERSION:
1291 ret = gst_ebml_read_skip (ebml);
1292 if (ret != GST_FLOW_OK)
1300 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
1301 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
1302 (doctype == NULL)) {
1305 GST_INFO_OBJECT (common, "Input is %s version %d", doctype, version);
1306 if (!strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM))
1307 common->is_webm = TRUE;
1309 GST_WARNING_OBJECT (common, "Input is EBML without doctype, assuming "
1310 "matroska (version %d)", version);
1314 GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
1315 ("Demuxer version (2) is too old to read %s version %d",
1316 GST_STR_NULL (doctype), version));
1317 ret = GST_FLOW_ERROR;
1320 GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
1321 ("Input is not a matroska stream (doctype=%s)", doctype));
1322 ret = GST_FLOW_ERROR;
1332 static GstFlowReturn
1333 gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
1334 GstEbmlRead * ebml, guint * nentries)
1338 GstMatroskaIndex idx;
1340 idx.pos = (guint64) - 1;
1342 idx.time = GST_CLOCK_TIME_NONE;
1345 DEBUG_ELEMENT_START (common, ebml, "CueTrackPositions");
1347 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1348 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1352 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1353 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1358 case GST_MATROSKA_ID_CUETRACK:
1362 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1367 GST_WARNING_OBJECT (common, "Invalid CueTrack 0");
1371 GST_DEBUG_OBJECT (common, "CueTrack: %" G_GUINT64_FORMAT, num);
1376 /* position in file */
1377 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
1381 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1384 if (num > G_MAXINT64) {
1385 GST_WARNING_OBJECT (common, "CueClusterPosition %" G_GUINT64_FORMAT
1394 /* number of block in the cluster */
1395 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
1399 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1403 GST_WARNING_OBJECT (common, "Invalid CueBlockNumber 0");
1407 GST_DEBUG_OBJECT (common, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
1410 /* mild sanity check, disregard strange cases ... */
1411 if (idx.block > G_MAXUINT16) {
1412 GST_DEBUG_OBJECT (common, "... looks suspicious, ignoring");
1419 ret = gst_matroska_read_common_parse_skip (common, ebml,
1420 "CueTrackPositions", id);
1423 case GST_MATROSKA_ID_CUECODECSTATE:
1424 case GST_MATROSKA_ID_CUEREFERENCE:
1425 ret = gst_ebml_read_skip (ebml);
1430 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1432 /* (e.g.) lavf typically creates entries without a block number,
1433 * which is bogus and leads to contradictory information */
1434 if (common->index->len) {
1435 GstMatroskaIndex *last_idx;
1437 last_idx = &g_array_index (common->index, GstMatroskaIndex,
1438 common->index->len - 1);
1439 if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
1440 last_idx->track == idx.track && idx.time > last_idx->time) {
1441 GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
1442 "but has different time than previous entry; discarding");
1447 if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
1448 && idx.pos != (guint64) - 1 && idx.track > 0) {
1449 g_array_append_val (common->index, idx);
1451 } else if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) {
1452 GST_DEBUG_OBJECT (common, "CueTrackPositions without valid content");
1458 static GstFlowReturn
1459 gst_matroska_read_common_parse_index_pointentry (GstMatroskaReadCommon *
1460 common, GstEbmlRead * ebml)
1464 GstClockTime time = GST_CLOCK_TIME_NONE;
1467 DEBUG_ELEMENT_START (common, ebml, "CuePoint");
1469 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1470 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1474 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1475 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1479 /* one single index entry ('point') */
1480 case GST_MATROSKA_ID_CUETIME:
1482 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
1485 GST_DEBUG_OBJECT (common, "CueTime: %" G_GUINT64_FORMAT, time);
1486 time = time * common->time_scale;
1490 /* position in the file + track to which it belongs */
1491 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
1494 gst_matroska_read_common_parse_index_cuetrack (common, ebml,
1495 &nentries)) != GST_FLOW_OK)
1501 ret = gst_matroska_read_common_parse_skip (common, ebml, "CuePoint",
1507 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1510 if (time == GST_CLOCK_TIME_NONE) {
1511 GST_WARNING_OBJECT (common, "CuePoint without valid time");
1512 g_array_remove_range (common->index, common->index->len - nentries,
1517 for (i = common->index->len - nentries; i < common->index->len; i++) {
1518 GstMatroskaIndex *idx =
1519 &g_array_index (common->index, GstMatroskaIndex, i);
1522 GST_DEBUG_OBJECT (common, "Index entry: pos=%" G_GUINT64_FORMAT
1523 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
1524 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
1528 GST_DEBUG_OBJECT (common, "Empty CuePoint");
1535 gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
1540 g_assert (common->src->len == common->num_streams);
1541 for (n = 0; n < common->src->len; n++) {
1542 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, n);
1544 if (context->num == track_num) {
1549 if (n == common->num_streams)
1550 GST_WARNING_OBJECT (common,
1551 "Failed to find corresponding pad for tracknum %d", track_num);
1557 gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
1561 GstFlowReturn ret = GST_FLOW_OK;
1565 g_array_free (common->index, TRUE);
1567 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1569 DEBUG_ELEMENT_START (common, ebml, "Cues");
1571 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1572 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1576 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1577 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1581 /* one single index entry ('point') */
1582 case GST_MATROSKA_ID_POINTENTRY:
1583 ret = gst_matroska_read_common_parse_index_pointentry (common, ebml);
1587 ret = gst_matroska_read_common_parse_skip (common, ebml, "Cues", id);
1591 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1593 /* Sort index by time, smallest time first, for easier searching */
1594 g_array_sort (common->index, (GCompareFunc) gst_matroska_index_compare);
1596 /* Now sort the track specific index entries into their own arrays */
1597 for (i = 0; i < common->index->len; i++) {
1598 GstMatroskaIndex *idx = &g_array_index (common->index, GstMatroskaIndex,
1601 GstMatroskaTrackContext *ctx;
1604 if (common->element_index) {
1607 if (idx->track != 0 &&
1609 gst_matroska_read_common_stream_from_num (common,
1610 idx->track)) != -1) {
1611 ctx = g_ptr_array_index (common->src, track_num);
1613 if (ctx->index_writer_id == -1)
1614 gst_index_get_writer_id (common->element_index,
1615 GST_OBJECT (ctx->pad), &ctx->index_writer_id);
1616 writer_id = ctx->index_writer_id;
1618 if (common->element_index_writer_id == -1)
1619 gst_index_get_writer_id (common->element_index, GST_OBJECT (common),
1620 &common->element_index_writer_id);
1621 writer_id = common->element_index_writer_id;
1624 GST_LOG_OBJECT (common, "adding association %" GST_TIME_FORMAT "-> %"
1625 G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
1626 idx->pos, writer_id);
1627 gst_index_add_association (common->element_index, writer_id,
1628 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
1629 GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
1633 if (idx->track == 0)
1636 track_num = gst_matroska_read_common_stream_from_num (common, idx->track);
1637 if (track_num == -1)
1640 ctx = g_ptr_array_index (common->src, track_num);
1642 if (ctx->index_table == NULL)
1644 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1646 g_array_append_vals (ctx->index_table, idx, 1);
1649 common->index_parsed = TRUE;
1651 /* sanity check; empty index normalizes to no index */
1652 if (common->index->len == 0) {
1653 g_array_free (common->index, TRUE);
1654 common->index = NULL;
1661 gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
1662 GstElement * el, GstEbmlRead * ebml)
1664 GstFlowReturn ret = GST_FLOW_OK;
1665 gdouble dur_f = -1.0;
1668 DEBUG_ELEMENT_START (common, ebml, "SegmentInfo");
1670 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1671 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1675 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1676 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1680 /* cluster timecode */
1681 case GST_MATROSKA_ID_TIMECODESCALE:{
1684 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1688 GST_DEBUG_OBJECT (common, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
1689 common->time_scale = num;
1693 case GST_MATROSKA_ID_DURATION:{
1694 if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK)
1698 GST_WARNING_OBJECT (common, "Invalid duration %lf", dur_f);
1702 GST_DEBUG_OBJECT (common, "Duration: %lf", dur_f);
1706 case GST_MATROSKA_ID_WRITINGAPP:{
1709 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1712 GST_DEBUG_OBJECT (common, "WritingApp: %s", GST_STR_NULL (text));
1713 common->writing_app = text;
1717 case GST_MATROSKA_ID_MUXINGAPP:{
1720 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1723 GST_DEBUG_OBJECT (common, "MuxingApp: %s", GST_STR_NULL (text));
1724 common->muxing_app = text;
1728 case GST_MATROSKA_ID_DATEUTC:{
1731 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
1734 GST_DEBUG_OBJECT (common, "DateUTC: %" G_GINT64_FORMAT, time);
1735 common->created = time;
1739 case GST_MATROSKA_ID_TITLE:{
1741 GstTagList *taglist;
1743 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1746 GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
1747 taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
1748 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
1749 gst_matroska_read_common_found_global_tag (common, el, taglist);
1755 ret = gst_matroska_read_common_parse_skip (common, ebml,
1760 case GST_MATROSKA_ID_SEGMENTUID:
1761 case GST_MATROSKA_ID_SEGMENTFILENAME:
1762 case GST_MATROSKA_ID_PREVUID:
1763 case GST_MATROSKA_ID_PREVFILENAME:
1764 case GST_MATROSKA_ID_NEXTUID:
1765 case GST_MATROSKA_ID_NEXTFILENAME:
1766 case GST_MATROSKA_ID_SEGMENTFAMILY:
1767 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
1768 ret = gst_ebml_read_skip (ebml);
1776 dur_u = gst_gdouble_to_guint64 (dur_f *
1777 gst_guint64_to_gdouble (common->time_scale));
1778 if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
1779 common->segment.duration = dur_u;
1782 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1784 common->segmentinfo_parsed = TRUE;
1789 static GstFlowReturn
1790 gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
1791 common, GstEbmlRead * ebml, GstTagList ** p_taglist, gchar * parent)
1793 /* FIXME: check if there are more useful mappings */
1796 const gchar *matroska_tagname;
1797 const gchar *gstreamer_tagname;
1801 /* The following list has the _same_ order as the one in Matroska spec. Please, don't mess it up. */
1802 /* TODO: Nesting information:
1803 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.
1804 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.
1805 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.
1808 /* Organizational Information */
1809 GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
1810 GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}, {
1811 /* 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) */
1814 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. */
1815 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
1816 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1818 /* TODO: Nested Information:
1819 URL URL corresponding to the tag it's included in.
1820 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).
1821 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.
1822 EMAIL Email corresponding to the tag it's included in.
1823 ADDRESS The physical address of the entity. The address should include a country code. It can be useful for a recording label.
1824 FAX The fax number corresponding to the tag it's included in. It can be useful for a recording label.
1825 PHONE The phone number corresponding to the tag it's included in. It can be useful for a recording label.
1829 GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
1830 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
1831 GST_MATROSKA_TAG_ID_ACCOMPANIMENT, GST_TAG_PERFORMER}, { /* Band/orchestra/accompaniment/musician. This is akin to the TPE2 tag in ID3. */
1832 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
1833 /* ARRANGER The person who arranged the piece, e.g., Ravel. */
1834 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. */
1835 /* LYRICIST The person who wrote the lyrics for a musical item. This is akin to the TEXT tag in ID3. */
1836 GST_MATROSKA_TAG_ID_CONDUCTOR, GST_TAG_PERFORMER}, { /* Conductor/performer refinement. This is akin to the TPE3 tag in ID3. */
1837 /* DIRECTOR This is akin to the IART tag in RIFF. */
1838 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
1839 /* ASSISTANT_DIRECTOR The name of the assistant director. */
1840 /* DIRECTOR_OF_PHOTOGRAPHY The name of the director of photography, also known as cinematographer. This is akin to the ICNM tag in Extended RIFF. */
1841 /* SOUND_ENGINEER The name of the sound engineer or sound recordist. */
1842 /* ART_DIRECTOR The person who oversees the artists and craftspeople who build the sets. */
1843 /* PRODUCTION_DESIGNER Artist responsible for designing the overall visual appearance of a movie. */
1844 /* CHOREGRAPHER The name of the choregrapher */
1845 /* COSTUME_DESIGNER The name of the costume designer */
1846 /* 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. */
1847 /* 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. */
1848 /* WRITTEN_BY The author of the story or script (used for movies and TV shows). */
1849 /* SCREENPLAY_BY The author of the screenplay or scenario (used for movies and TV shows). */
1850 /* EDITED_BY This is akin to the IEDT tag in Extended RIFF. */
1851 /* PRODUCER Produced by. This is akin to the IPRO tag in Extended RIFF. */
1852 /* COPRODUCER The name of a co-producer. */
1853 /* EXECUTIVE_PRODUCER The name of an executive producer. */
1854 /* DISTRIBUTED_BY This is akin to the IDST tag in Extended RIFF. */
1855 /* MASTERED_BY The engineer who mastered the content for a physical medium or for digital distribution. */
1856 GST_MATROSKA_TAG_ID_ENCODED_BY, GST_TAG_ENCODED_BY}, { /* This is akin to the TENC tag in ID3. */
1857 /* MIXED_BY DJ mix by the artist specified */
1858 /* REMIXED_BY Interpreted, remixed, or otherwise modified by. This is akin to the TPE4 tag in ID3. */
1859 /* PRODUCTION_STUDIO This is akin to the ISTD tag in Extended RIFF. */
1860 /* THANKS_TO A very general tag for everyone else that wants to be listed. */
1861 /* PUBLISHER This is akin to the TPUB tag in ID3. */
1862 /* LABEL The record label or imprint on the disc. */
1863 /* Search / Classification */
1864 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
1865 /* 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. */
1866 /* 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. */
1867 /* CONTENT_TYPE The type of the item. e.g. Documentary, Feature Film, Cartoon, Music Video, Music, Sound FX, ... */
1868 /* SUBJECT Describes the topic of the file, such as "Aerial view of Seattle." */
1869 GST_MATROSKA_TAG_ID_DESCRIPTION, GST_TAG_DESCRIPTION}, { /* A short description of the content, such as "Two birds flying." */
1870 GST_MATROSKA_TAG_ID_KEYWORDS, GST_TAG_KEYWORDS}, { /* Keywords to the item separated by a comma, used for searching. */
1871 /* SUMMARY A plot outline or a summary of the story. */
1872 /* SYNOPSIS A description of the story line of the item. */
1873 /* INITIAL_KEY The initial key that a musical track starts in. The format is identical to ID3. */
1874 /* PERIOD Describes the period that the piece is from or about. For example, "Renaissance". */
1875 /* 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). */
1876 /* ICRA The ICRA content rating for parental control. (Previously RSACi) */
1878 /* Temporal Information */
1879 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. */
1880 GST_MATROSKA_TAG_ID_DATE_RECORDED, GST_TAG_DATE}, { /* The time that the recording began. This is akin to the TDRC tag in ID3. */
1881 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. */
1882 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. */
1883 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. */
1884 GST_MATROSKA_TAG_ID_DATE_WRITTEN, GST_TAG_DATE}, { /* The time that the writing of the music/script began. */
1885 GST_MATROSKA_TAG_ID_DATE_PURCHASED, GST_TAG_DATE}, { /* Information on when the file was purchased (see also purchase tags). */
1886 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1888 /* Spacial Information */
1889 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". */
1890 /* 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". */
1891 /* 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. */
1894 GST_MATROSKA_TAG_ID_COMMENT, GST_TAG_COMMENT}, { /* Any comment related to the content. */
1895 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1896 /* PLAY_COUNTER The number of time the item has been played. */
1897 /* 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. */
1899 /* Technical Information */
1900 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
1901 /* ENCODER_SETTINGS A list of the settings used for encoding this item. No specific format. */
1902 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
1903 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1904 /* 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. */
1905 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
1906 /* 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. */
1907 /* 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. */
1908 /* 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). */
1909 /* TODO: REPLAYGAIN_PEAK The maximum absolute peak value of the item. This is based on the Replay Gain standard. */
1912 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
1913 /* 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. */
1914 /* ISBN International Standard Book Number */
1915 /* BARCODE EAN-13 (European Article Numbering) or UPC-A (Universal Product Code) bar code identifier */
1916 /* CATALOG_NUMBER A label-specific string used to identify the release (TIC 01 for example). */
1917 /* 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). */
1918 /* LCCN Library of Congress Control Number */
1921 /* PURCHASE_ITEM URL to purchase this file. This is akin to the WPAY tag in ID3. */
1922 /* PURCHASE_INFO Information on where to purchase this album. This is akin to the WCOM tag in ID3. */
1923 /* PURCHASE_OWNER Information on the person who purchased the file. This is akin to the TOWN tag in ID3. */
1924 /* 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". */
1925 /* PURCHASE_CURRENCY The currency type used to pay for the entity. Use ISO-4217 for the 3 letter currency code. */
1928 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
1929 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. */
1930 GST_MATROSKA_TAG_ID_LICENSE, GST_TAG_LICENSE}, { /* The license applied to the content (like Creative Commons variants). */
1931 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}
1935 const gchar *matroska_tagname;
1936 const gchar *gstreamer_tagname;
1938 child_tag_conv[] = {
1940 "TITLE/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1941 "ARTIST/SORT_WITH=", GST_TAG_ARTIST_SORTNAME}, {
1942 /* ALBUM-stuff is handled elsewhere */
1943 "COMPOSER/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1944 "ORIGINAL/URL=", GST_TAG_LOCATION}, {
1945 /* EMAIL, PHONE, FAX all can be mapped to GST_TAG_CONTACT, there is special
1946 * code for that later.
1948 "TITLE/URL=", GST_TAG_HOMEPAGE}, {
1949 "ARTIST/URL=", GST_TAG_HOMEPAGE}, {
1950 "COPYRIGHT/URL=", GST_TAG_COPYRIGHT_URI}, {
1951 "LICENSE/URL=", GST_TAG_LICENSE_URI}, {
1952 "LICENSE/URL=", GST_TAG_LICENSE_URI}
1956 gchar *value = NULL;
1958 gchar *name_with_parent = NULL;
1959 GstTagList *child_taglist = NULL;
1961 DEBUG_ELEMENT_START (common, ebml, "SimpleTag");
1963 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1964 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
1969 child_taglist = *p_taglist;
1971 child_taglist = gst_tag_list_new_empty ();
1973 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1974 /* read all sub-entries */
1976 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1980 case GST_MATROSKA_ID_TAGNAME:
1983 ret = gst_ebml_read_ascii (ebml, &id, &tag);
1984 GST_DEBUG_OBJECT (common, "TagName: %s", GST_STR_NULL (tag));
1985 g_free (name_with_parent);
1987 name_with_parent = g_strdup_printf ("%s/%s", parent, tag);
1989 name_with_parent = g_strdup (tag);
1992 case GST_MATROSKA_ID_TAGSTRING:
1995 ret = gst_ebml_read_utf8 (ebml, &id, &value);
1996 GST_DEBUG_OBJECT (common, "TagString: %s", GST_STR_NULL (value));
1999 case GST_MATROSKA_ID_SIMPLETAG:
2000 /* Recursive SimpleTag */
2001 /* This implementation requires tag name of _this_ tag to be known
2002 * in order to read its children. It's not in the spec, just the way
2003 * the code is written.
2005 if (name_with_parent != NULL) {
2006 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2007 ebml, &child_taglist, name_with_parent);
2013 ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag",
2017 case GST_MATROSKA_ID_TAGLANGUAGE:
2018 case GST_MATROSKA_ID_TAGDEFAULT:
2019 case GST_MATROSKA_ID_TAGBINARY:
2020 ret = gst_ebml_read_skip (ebml);
2025 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
2027 if (parent && tag && value && *value != '\0') {
2028 /* Don't bother mapping children tags - parent will do that */
2030 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2031 key_val = g_strdup_printf ("%s=%s", name_with_parent, value);
2032 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2033 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2034 } else if (tag && value && *value != '\0') {
2035 gboolean matched = FALSE;
2038 for (i = 0; !matched && i < G_N_ELEMENTS (tag_conv); i++) {
2039 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2041 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2043 if (strcmp (tagname_mkv, tag) == 0) {
2044 GValue dest = { 0, };
2045 GType dest_type = gst_tag_get_type (tagname_gst);
2047 /* Ensure that any date string is complete */
2048 if (dest_type == G_TYPE_DATE) {
2049 guint year = 1901, month = 1, day = 1;
2051 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
2053 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
2055 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
2059 g_value_init (&dest, dest_type);
2060 if (gst_value_deserialize (&dest, value)) {
2061 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2062 tagname_gst, &dest, NULL);
2064 GST_WARNING_OBJECT (common, "Can't transform tag '%s' with "
2065 "value '%s' to target type '%s'", tag, value,
2066 g_type_name (dest_type));
2068 g_value_unset (&dest);
2074 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2075 key_val = g_strdup_printf ("%s=%s", tag, value);
2076 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2077 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2082 /* Map children tags. This only supports top-anchored mapping. That is,
2083 * we start at toplevel tag (this tag), and see how its combinations
2084 * with its children can be mapped. Which means that grandchildren
2085 * are also combined here, with _this_ tag taken into consideration.
2086 * If grandchildren can be combined only with children, that combination
2089 gint child_tags_n = gst_tag_list_n_tags (child_taglist);
2090 if (child_tags_n > 0) {
2092 for (i = 0; i < child_tags_n; i++) {
2094 const gchar *child_name = gst_tag_list_nth_tag_name (child_taglist, i);
2095 guint taglen = gst_tag_list_get_tag_size (child_taglist, child_name);
2096 for (j = 0; j < taglen; j++) {
2098 gboolean matched = FALSE;
2099 gchar *val_pre, *val_post;
2102 if (!gst_tag_list_get_string_index (child_taglist, child_name,
2105 if (!strchr (val, '=')) {
2109 val_post = g_strdup (strchr (val, '=') + 1);
2110 val_pre = g_strdup (val);
2111 *(strchr (val_pre, '=') + 1) = '\0';
2113 for (k = 0; !matched && k < G_N_ELEMENTS (child_tag_conv); k++) {
2114 const gchar *tagname_gst = child_tag_conv[k].gstreamer_tagname;
2116 const gchar *tagname_mkv = child_tag_conv[k].matroska_tagname;
2118 /* TODO: Once "key[lc]=value" form support is implemented,
2119 * strip [lc] here. It can't be used in combined tags.
2120 * If a tag is not combined, leave [lc] as it is.
2122 if (strcmp (tagname_mkv, val_pre) == 0) {
2123 GValue dest = { 0, };
2124 GType dest_type = gst_tag_get_type (tagname_gst);
2126 g_value_init (&dest, dest_type);
2127 if (gst_value_deserialize (&dest, val_post)) {
2128 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2129 tagname_gst, &dest, NULL);
2131 GST_WARNING_OBJECT (common, "Can't transform complex tag '%s' "
2132 "to target type '%s'", val, g_type_name (dest_type));
2134 g_value_unset (&dest);
2139 gchar *last_slash = strrchr (val_pre, '/');
2142 if (strcmp (last_slash, "EMAIL=") == 0 ||
2143 strcmp (last_slash, "PHONE=") == 0 ||
2144 strcmp (last_slash, "ADDRESS=") == 0 ||
2145 strcmp (last_slash, "FAX=") == 0) {
2146 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2147 GST_TAG_CONTACT, val_post, NULL);
2153 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2154 GST_TAG_EXTENDED_COMMENT, val, NULL);
2161 gst_tag_list_unref (child_taglist);
2166 g_free (name_with_parent);
2173 gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
2174 gint * a, gint * v, gint * s)
2177 gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
2179 for (i = 0; i < common->src->len; i++) {
2180 GstMatroskaTrackContext *stream;
2182 stream = g_ptr_array_index (common->src, i);
2183 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
2185 else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
2187 else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
2188 subtitle_streams += 1;
2192 *v = subtitle_streams;
2197 gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
2198 const gchar * tag, gpointer user_data)
2202 TargetTypeContext *ctx = (TargetTypeContext *) user_data;
2204 vallen = gst_tag_list_get_tag_size (list, tag);
2208 for (i = 0; i < vallen; i++) {
2210 const GValue *val_ref;
2212 val_ref = gst_tag_list_get_value_index (list, tag, i);
2213 if (val_ref == NULL)
2215 g_value_init (&val, G_VALUE_TYPE (val_ref));
2216 g_value_copy (val_ref, &val);
2218 /* TODO: use the optional ctx->target_type somehow */
2219 if (strcmp (tag, GST_TAG_TITLE) == 0) {
2220 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2221 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2222 GST_TAG_SHOW_NAME, &val);
2224 } else if (ctx->target_type_value >= 50) {
2225 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2226 GST_TAG_ALBUM, &val);
2229 } else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
2230 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2231 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2232 GST_TAG_SHOW_SORTNAME, &val);
2234 } else if (ctx->target_type_value >= 50) {
2235 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2236 GST_TAG_ALBUM_SORTNAME, &val);
2239 } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
2240 if (ctx->target_type_value >= 50) {
2241 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2242 GST_TAG_ALBUM_ARTIST, &val);
2245 } else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
2246 if (ctx->target_type_value >= 50) {
2247 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2248 GST_TAG_ALBUM_ARTIST_SORTNAME, &val);
2251 } else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
2252 if (ctx->target_type_value >= 60) {
2253 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2254 GST_TAG_ALBUM_VOLUME_COUNT, &val);
2257 } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
2258 if (ctx->target_type_value >= 60 && !ctx->audio_only) {
2259 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2260 GST_TAG_SHOW_SEASON_NUMBER, &val);
2262 } else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
2263 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2264 GST_TAG_SHOW_EPISODE_NUMBER, &val);
2266 } else if (ctx->target_type_value >= 50) {
2267 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2268 GST_TAG_ALBUM_VOLUME_NUMBER, &val);
2272 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, &val);
2273 g_value_unset (&val);
2279 gst_matroska_read_common_apply_target_type (GstMatroskaReadCommon * common,
2280 GstTagList * taglist, guint64 target_type_value, gchar * target_type)
2282 TargetTypeContext ctx;
2287 gst_matroska_read_common_count_streams (common, &a, &v, &s);
2289 ctx.audio_only = (a > 0 && v == 0 && s == 0);
2290 ctx.result = gst_tag_list_new_empty ();
2291 ctx.target_type_value = target_type_value;
2292 ctx.target_type = target_type;
2294 gst_tag_list_foreach (taglist,
2295 gst_matroska_read_common_apply_target_type_foreach, &ctx);
2297 gst_tag_list_unref (taglist);
2302 static GstFlowReturn
2303 gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
2304 GstEbmlRead * ebml, GstTagList ** p_taglist)
2308 GArray *chapter_targets, *edition_targets, *track_targets;
2309 GstTagList *taglist;
2311 guint64 target_type_value = 50;
2312 gchar *target_type = NULL;
2314 DEBUG_ELEMENT_START (common, ebml, "Tag");
2316 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2317 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2321 edition_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2322 chapter_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2323 track_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2324 taglist = gst_tag_list_new_empty ();
2327 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2328 /* read all sub-entries */
2330 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2334 case GST_MATROSKA_ID_SIMPLETAG:
2335 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2336 ebml, &taglist, NULL);
2339 case GST_MATROSKA_ID_TARGETS:
2340 g_free (target_type);
2342 target_type_value = 50;
2343 ret = gst_matroska_read_common_parse_metadata_targets (common, ebml,
2344 edition_targets, chapter_targets, track_targets,
2345 &target_type_value, &target_type);
2349 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tag", id);
2354 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2356 taglist = gst_matroska_read_common_apply_target_type (common, taglist,
2357 target_type_value, target_type);
2358 g_free (target_type);
2360 /* if tag is chapter/edition specific - try to find that entry */
2361 if (G_UNLIKELY (chapter_targets->len > 0 || edition_targets->len > 0 ||
2362 track_targets->len > 0)) {
2364 if (chapter_targets->len > 0 || edition_targets->len > 0) {
2365 if (common->toc == NULL)
2366 GST_WARNING_OBJECT (common,
2367 "Found chapter/edition specific tag, but TOC is not present");
2369 cur = gst_toc_get_entries (common->toc);
2370 while (cur != NULL) {
2371 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
2372 chapter_targets, taglist);
2375 common->toc_updated = TRUE;
2378 for (i = 0; i < track_targets->len; i++) {
2380 gboolean found = FALSE;
2381 guint64 tgt = g_array_index (track_targets, guint64, i);
2383 for (j = 0; j < common->src->len; j++) {
2384 GstMatroskaTrackContext *stream = g_ptr_array_index (common->src, j);
2386 if (stream->uid == tgt) {
2387 gst_tag_list_insert (stream->pending_tags, taglist,
2388 GST_TAG_MERGE_REPLACE);
2393 GST_WARNING_OBJECT (common,
2394 "Found track-specific tag(s), but track %" G_GUINT64_FORMAT
2395 " is not known (yet?)", tgt);
2399 gst_tag_list_insert (*p_taglist, taglist, GST_TAG_MERGE_APPEND);
2401 gst_tag_list_unref (taglist);
2402 g_array_unref (chapter_targets);
2403 g_array_unref (edition_targets);
2404 g_array_unref (track_targets);
2410 gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
2411 GstElement * el, GstEbmlRead * ebml)
2413 GstTagList *taglist;
2414 GstFlowReturn ret = GST_FLOW_OK;
2419 curpos = gst_ebml_read_get_pos (ebml);
2421 /* Make sure we don't parse a tags element twice and
2422 * post it's tags twice */
2423 curpos = gst_ebml_read_get_pos (ebml);
2424 for (l = common->tags_parsed; l; l = l->next) {
2425 guint64 *pos = l->data;
2427 if (*pos == curpos) {
2428 GST_DEBUG_OBJECT (common, "Skipping already parsed Tags at offset %"
2429 G_GUINT64_FORMAT, curpos);
2434 common->tags_parsed =
2435 g_list_prepend (common->tags_parsed, g_slice_new (guint64));
2436 *((guint64 *) common->tags_parsed->data) = curpos;
2439 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2440 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2444 taglist = gst_tag_list_new_empty ();
2445 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
2446 common->toc_updated = FALSE;
2448 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2449 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2453 case GST_MATROSKA_ID_TAG:
2454 ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml,
2459 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id);
2461 /* FIXME: Use to limit the tags to specific pads */
2465 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2467 if (G_LIKELY (!gst_tag_list_is_empty (taglist)))
2468 gst_matroska_read_common_found_global_tag (common, el, taglist);
2470 gst_tag_list_unref (taglist);
2475 static GstFlowReturn
2476 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
2477 peek, const guint8 ** data)
2479 /* Caller needs to gst_adapter_unmap. */
2480 *data = gst_adapter_map (common->adapter, peek);
2482 return GST_FLOW_EOS;
2488 * Calls pull_range for (offset,size) without advancing our offset
2491 gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
2492 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
2496 /* Caching here actually makes much less difference than one would expect.
2497 * We do it mainly to avoid pulling buffers of 1 byte all the time */
2498 if (common->cached_buffer) {
2499 guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
2500 gsize cache_size = gst_buffer_get_size (common->cached_buffer);
2502 if (cache_offset <= common->offset &&
2503 (common->offset + size) <= (cache_offset + cache_size)) {
2505 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2506 GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
2508 if (!common->cached_data) {
2509 gst_buffer_map (common->cached_buffer, &common->cached_map,
2511 common->cached_data = common->cached_map.data;
2513 *bytes = common->cached_data + common->offset - cache_offset;
2517 /* not enough data in the cache, free cache and get a new one */
2518 if (common->cached_data) {
2519 gst_buffer_unmap (common->cached_buffer, &common->cached_map);
2520 common->cached_data = NULL;
2522 gst_buffer_unref (common->cached_buffer);
2523 common->cached_buffer = NULL;
2526 /* refill the cache */
2527 ret = gst_pad_pull_range (common->sinkpad, common->offset,
2528 MAX (size, 64 * 1024), &common->cached_buffer);
2529 if (ret != GST_FLOW_OK) {
2530 common->cached_buffer = NULL;
2534 if (gst_buffer_get_size (common->cached_buffer) >= size) {
2536 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2537 GST_BUFFER_COPY_ALL, 0, size);
2539 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2540 common->cached_data = common->cached_map.data;
2541 *bytes = common->cached_data;
2546 /* Not possible to get enough data, try a last time with
2547 * requesting exactly the size we need */
2548 gst_buffer_unref (common->cached_buffer);
2549 common->cached_buffer = NULL;
2552 gst_pad_pull_range (common->sinkpad, common->offset, size,
2553 &common->cached_buffer);
2554 if (ret != GST_FLOW_OK) {
2555 GST_DEBUG_OBJECT (common, "pull_range returned %d", ret);
2563 if (gst_buffer_get_size (common->cached_buffer) < size) {
2564 GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
2565 G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2566 common->offset, size, gst_buffer_get_size (common->cached_buffer));
2568 gst_buffer_unref (common->cached_buffer);
2569 common->cached_buffer = NULL;
2574 return GST_FLOW_EOS;
2578 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2579 GST_BUFFER_COPY_ALL, 0, size);
2581 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2582 common->cached_data = common->cached_map.data;
2583 *bytes = common->cached_data;
2589 static GstFlowReturn
2590 gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek,
2593 return gst_matroska_read_common_peek_bytes (common, common->offset, peek,
2598 gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
2599 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2601 return gst_ebml_peek_id_length (_id, _length, _needed,
2602 (GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
2607 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
2608 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2612 ret = gst_ebml_peek_id_length (_id, _length, _needed,
2613 (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
2614 el, common->offset);
2616 gst_adapter_unmap (common->adapter);
2621 static GstFlowReturn
2622 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
2623 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2625 GstMatroskaTrackEncoding enc = { 0, };
2629 DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
2630 /* Set default values */
2632 /* All other default values are 0 */
2634 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2635 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2639 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2640 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2644 case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
2647 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2650 if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
2652 GST_ERROR_OBJECT (common, "ContentEncodingOrder %" G_GUINT64_FORMAT
2653 "is not unique for track %" G_GUINT64_FORMAT, num, context->num);
2654 ret = GST_FLOW_ERROR;
2658 GST_DEBUG_OBJECT (common, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
2663 case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
2666 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2669 if (num > 7 || num == 0) {
2670 GST_ERROR_OBJECT (common, "Invalid ContentEncodingScope %"
2671 G_GUINT64_FORMAT, num);
2672 ret = GST_FLOW_ERROR;
2676 GST_DEBUG_OBJECT (common, "ContentEncodingScope: %" G_GUINT64_FORMAT,
2682 case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
2685 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2689 GST_ERROR_OBJECT (common, "Invalid ContentEncodingType %"
2690 G_GUINT64_FORMAT, num);
2691 ret = GST_FLOW_ERROR;
2693 } else if (num != 0) {
2694 GST_ERROR_OBJECT (common, "Encrypted tracks are not supported yet");
2695 ret = GST_FLOW_ERROR;
2698 GST_DEBUG_OBJECT (common, "ContentEncodingType: %" G_GUINT64_FORMAT,
2703 case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
2705 DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
2707 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
2710 while (ret == GST_FLOW_OK &&
2711 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2712 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2716 case GST_MATROSKA_ID_CONTENTCOMPALGO:{
2719 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
2723 GST_ERROR_OBJECT (common, "Invalid ContentCompAlgo %"
2724 G_GUINT64_FORMAT, num);
2725 ret = GST_FLOW_ERROR;
2728 GST_DEBUG_OBJECT (common, "ContentCompAlgo: %" G_GUINT64_FORMAT,
2730 enc.comp_algo = num;
2734 case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
2739 gst_ebml_read_binary (ebml, &id, &data,
2740 &size)) != GST_FLOW_OK) {
2743 enc.comp_settings = data;
2744 enc.comp_settings_length = size;
2745 GST_DEBUG_OBJECT (common,
2746 "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
2750 GST_WARNING_OBJECT (common,
2751 "Unknown ContentCompression subelement 0x%x - ignoring", id);
2752 ret = gst_ebml_read_skip (ebml);
2756 DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
2760 case GST_MATROSKA_ID_CONTENTENCRYPTION:
2761 GST_ERROR_OBJECT (common, "Encrypted tracks not yet supported");
2762 gst_ebml_read_skip (ebml);
2763 ret = GST_FLOW_ERROR;
2766 GST_WARNING_OBJECT (common,
2767 "Unknown ContentEncoding subelement 0x%x - ignoring", id);
2768 ret = gst_ebml_read_skip (ebml);
2773 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2774 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2777 /* TODO: Check if the combination of values is valid */
2779 g_array_append_val (context->encodings, enc);
2785 gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
2786 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2791 DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
2793 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2794 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2798 context->encodings =
2799 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
2801 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2802 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2806 case GST_MATROSKA_ID_CONTENTENCODING:
2807 ret = gst_matroska_read_common_read_track_encoding (common, ebml,
2811 GST_WARNING_OBJECT (common,
2812 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
2813 ret = gst_ebml_read_skip (ebml);
2818 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2819 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2822 /* Sort encodings according to their order */
2823 g_array_sort (context->encodings,
2824 (GCompareFunc) gst_matroska_read_common_encoding_cmp);
2826 return gst_matroska_decode_content_encodings (context->encodings);
2830 gst_matroska_read_common_free_parsed_el (gpointer mem, gpointer user_data)
2832 g_slice_free (guint64, mem);
2836 gst_matroska_read_common_init (GstMatroskaReadCommon * ctx)
2839 ctx->writing_app = NULL;
2840 ctx->muxing_app = NULL;
2842 ctx->global_tags = NULL;
2843 ctx->adapter = gst_adapter_new ();
2847 gst_matroska_read_common_finalize (GstMatroskaReadCommon * ctx)
2850 g_ptr_array_free (ctx->src, TRUE);
2854 if (ctx->global_tags) {
2855 gst_tag_list_unref (ctx->global_tags);
2856 ctx->global_tags = NULL;
2859 g_object_unref (ctx->adapter);
2863 gst_matroska_read_common_reset (GstElement * element,
2864 GstMatroskaReadCommon * ctx)
2868 GST_LOG_OBJECT (ctx, "resetting read context");
2871 ctx->state = GST_MATROSKA_READ_STATE_START;
2873 /* clean up existing streams if any */
2875 g_assert (ctx->src->len == ctx->num_streams);
2876 for (i = 0; i < ctx->src->len; i++) {
2877 GstMatroskaTrackContext *context = g_ptr_array_index (ctx->src, i);
2879 if (context->pad != NULL)
2880 gst_element_remove_pad (element, context->pad);
2882 gst_caps_replace (&context->caps, NULL);
2883 gst_matroska_track_free (context);
2885 g_ptr_array_free (ctx->src, TRUE);
2887 ctx->src = g_ptr_array_new ();
2888 ctx->num_streams = 0;
2890 /* reset media info */
2891 g_free (ctx->writing_app);
2892 ctx->writing_app = NULL;
2893 g_free (ctx->muxing_app);
2894 ctx->muxing_app = NULL;
2896 /* reset stream type */
2897 ctx->is_webm = FALSE;
2898 ctx->has_video = FALSE;
2902 g_array_free (ctx->index, TRUE);
2907 ctx->time_scale = 1000000;
2908 ctx->created = G_MININT64;
2910 /* cues/tracks/segmentinfo */
2911 ctx->index_parsed = FALSE;
2912 ctx->segmentinfo_parsed = FALSE;
2913 ctx->attachments_parsed = FALSE;
2914 ctx->chapters_parsed = FALSE;
2917 g_list_foreach (ctx->tags_parsed,
2918 (GFunc) gst_matroska_read_common_free_parsed_el, NULL);
2919 g_list_free (ctx->tags_parsed);
2920 ctx->tags_parsed = NULL;
2921 if (ctx->global_tags) {
2922 gst_tag_list_unref (ctx->global_tags);
2924 ctx->global_tags = gst_tag_list_new_empty ();
2925 gst_tag_list_set_scope (ctx->global_tags, GST_TAG_SCOPE_GLOBAL);
2927 gst_segment_init (&ctx->segment, GST_FORMAT_TIME);
2930 if (ctx->cached_buffer) {
2931 if (ctx->cached_data) {
2932 gst_buffer_unmap (ctx->cached_buffer, &ctx->cached_map);
2933 ctx->cached_data = NULL;
2935 gst_buffer_unref (ctx->cached_buffer);
2936 ctx->cached_buffer = NULL;
2939 /* free chapters TOC if any */
2941 gst_toc_unref (ctx->toc);
2946 /* call with object lock held */
2948 gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
2949 GstClockTime time, gboolean full)
2953 GST_DEBUG_OBJECT (common, "resetting stream state");
2955 g_assert (common->src->len == common->num_streams);
2956 for (i = 0; i < common->src->len; i++) {
2957 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2958 context->pos = time;
2959 context->set_discont = TRUE;
2960 context->eos = FALSE;
2961 context->from_time = GST_CLOCK_TIME_NONE;
2962 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2963 GstMatroskaTrackVideoContext *videocontext =
2964 (GstMatroskaTrackVideoContext *) context;
2965 /* demux object lock held by caller */
2966 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2972 gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
2977 g_assert (common->src->len == common->num_streams);
2978 for (i = 0; i < common->src->len; i++) {
2979 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2981 if (context->num == num)