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_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, GstSearchMode snap_dir)
380 GstMatroskaIndex *entry = NULL;
383 /* find entry just before or at the requested position */
384 if (track && track->index_table)
385 index = track->index_table;
387 index = common->index;
389 if (!index || !index->len)
393 gst_util_array_binary_search (index->data, index->len,
394 sizeof (GstMatroskaIndex),
395 (GCompareDataFunc) gst_matroska_index_seek_find, snap_dir, &seek_pos,
399 if (snap_dir == GST_SEARCH_MODE_AFTER) {
400 /* Can only happen with a reverse seek past the end */
401 entry = &g_array_index (index, GstMatroskaIndex, index->len - 1);
403 /* Can only happen with a forward seek before the start */
404 entry = &g_array_index (index, GstMatroskaIndex, 0);
411 *_entry_index = entry - (GstMatroskaIndex *) index->data;
417 gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
418 GstMatroskaTrackEncoding * b)
420 if (b->order > a->order)
422 else if (b->order < a->order)
429 gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
434 if (encodings == NULL || encodings->len == 0)
437 for (i = 0; i < encodings->len; i++)
438 if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
444 /* takes ownership of taglist */
446 gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
447 GstElement * el, GstTagList * taglist)
449 if (common->global_tags) {
450 gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
451 gst_tag_list_unref (taglist);
453 common->global_tags = taglist;
455 common->global_tags_changed = TRUE;
459 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
463 if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
465 GST_DEBUG_OBJECT (common->sinkpad, "no upstream length");
470 /* determine track to seek in */
471 GstMatroskaTrackContext *
472 gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
473 GstMatroskaTrackContext * track)
477 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
480 for (i = 0; i < common->src->len; i++) {
481 GstMatroskaTrackContext *stream;
483 stream = g_ptr_array_index (common->src, i);
484 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
491 /* skip unknown or alike element */
493 gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
494 GstEbmlRead * ebml, const gchar * parent_name, guint id)
496 if (id == GST_EBML_ID_VOID) {
497 GST_DEBUG_OBJECT (common->sinkpad, "Skipping EBML Void element");
498 } else if (id == GST_EBML_ID_CRC32) {
499 GST_DEBUG_OBJECT (common->sinkpad, "Skipping EBML CRC32 element");
501 GST_WARNING_OBJECT (common->sinkpad,
502 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
505 return gst_ebml_read_skip (ebml);
509 gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
510 GstEbmlRead * ebml, GstTagList * taglist)
514 gchar *description = NULL;
515 gchar *filename = NULL;
516 gchar *mimetype = NULL;
520 DEBUG_ELEMENT_START (common, ebml, "AttachedFile");
522 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
523 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
527 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
528 /* read all sub-entries */
530 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
534 case GST_MATROSKA_ID_FILEDESCRIPTION:
536 GST_WARNING_OBJECT (common->sinkpad,
537 "FileDescription can only appear once");
541 ret = gst_ebml_read_utf8 (ebml, &id, &description);
542 GST_DEBUG_OBJECT (common->sinkpad, "FileDescription: %s",
543 GST_STR_NULL (description));
545 case GST_MATROSKA_ID_FILENAME:
547 GST_WARNING_OBJECT (common->sinkpad, "FileName can only appear once");
551 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
553 GST_DEBUG_OBJECT (common->sinkpad, "FileName: %s",
554 GST_STR_NULL (filename));
556 case GST_MATROSKA_ID_FILEMIMETYPE:
558 GST_WARNING_OBJECT (common->sinkpad,
559 "FileMimeType can only appear once");
563 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
564 GST_DEBUG_OBJECT (common->sinkpad, "FileMimeType: %s",
565 GST_STR_NULL (mimetype));
567 case GST_MATROSKA_ID_FILEDATA:
569 GST_WARNING_OBJECT (common->sinkpad, "FileData can only appear once");
573 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
574 GST_DEBUG_OBJECT (common->sinkpad,
575 "FileData of size %" G_GUINT64_FORMAT, datalen);
579 ret = gst_matroska_read_common_parse_skip (common, ebml,
582 case GST_MATROSKA_ID_FILEUID:
583 ret = gst_ebml_read_skip (ebml);
588 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
590 if (filename && mimetype && data && datalen > 0) {
591 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
592 GstBuffer *tagbuffer = NULL;
593 GstSample *tagsample = NULL;
594 GstStructure *info = NULL;
595 GstCaps *caps = NULL;
596 gchar *filename_lc = g_utf8_strdown (filename, -1);
598 GST_DEBUG_OBJECT (common->sinkpad, "Creating tag for attachment with "
599 "filename '%s', mimetype '%s', description '%s', "
600 "size %" G_GUINT64_FORMAT, filename, mimetype,
601 GST_STR_NULL (description), datalen);
603 /* TODO: better heuristics for different image types */
604 if (strstr (filename_lc, "cover")) {
605 if (strstr (filename_lc, "back"))
606 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
608 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
609 } else if (g_str_has_prefix (mimetype, "image/") ||
610 g_str_has_suffix (filename_lc, "png") ||
611 g_str_has_suffix (filename_lc, "jpg") ||
612 g_str_has_suffix (filename_lc, "jpeg") ||
613 g_str_has_suffix (filename_lc, "gif") ||
614 g_str_has_suffix (filename_lc, "bmp")) {
615 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
617 g_free (filename_lc);
619 /* First try to create an image tag buffer from this */
620 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
622 gst_tag_image_data_to_image_sample (data, datalen, image_type);
625 image_type = GST_TAG_IMAGE_TYPE_NONE;
628 tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
629 caps = gst_caps_ref (gst_sample_get_caps (tagsample));
630 info = gst_structure_copy (gst_sample_get_info (tagsample));
631 gst_sample_unref (tagsample);
635 /* if this failed create an attachment buffer */
637 tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
639 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
641 caps = gst_caps_new_empty_simple (mimetype);
644 /* Set filename and description in the info */
646 info = gst_structure_new_empty ("GstTagImageInfo");
648 gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
650 gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
652 tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
654 gst_buffer_unref (tagbuffer);
655 gst_caps_unref (caps);
657 GST_DEBUG_OBJECT (common->sinkpad,
658 "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
660 /* and append to the tag list */
661 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
662 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
665 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
668 /* the list adds it own ref */
669 gst_sample_unref (tagsample);
675 g_free (description);
681 gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
682 GstElement * el, GstEbmlRead * ebml)
685 GstFlowReturn ret = GST_FLOW_OK;
688 DEBUG_ELEMENT_START (common, ebml, "Attachments");
690 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
691 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
695 taglist = gst_tag_list_new_empty ();
696 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
698 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
699 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
703 case GST_MATROSKA_ID_ATTACHEDFILE:
704 ret = gst_matroska_read_common_parse_attached_file (common, ebml,
709 ret = gst_matroska_read_common_parse_skip (common, ebml,
714 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
716 if (gst_tag_list_n_tags (taglist) > 0) {
717 GST_DEBUG_OBJECT (common->sinkpad, "Storing attachment tags");
718 gst_matroska_read_common_found_global_tag (common, el, taglist);
720 GST_DEBUG_OBJECT (common->sinkpad, "No valid attachments found");
721 gst_tag_list_unref (taglist);
724 common->attachments_parsed = TRUE;
730 gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
731 GArray * edition_targets, GArray * chapter_targtes, GstTagList * tags)
741 (gst_toc_entry_get_entry_type (entry) ==
742 GST_TOC_ENTRY_TYPE_EDITION) ? edition_targets : chapter_targtes;
744 etags = gst_tag_list_new_empty ();
746 for (i = 0; i < targets->len; ++i) {
747 tgt = g_array_index (targets, guint64, i);
750 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
752 uid = g_strdup_printf ("%" G_GUINT64_FORMAT, tgt);
753 if (g_strcmp0 (gst_toc_entry_get_uid (entry), uid) == 0)
754 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
759 gst_toc_entry_merge_tags (entry, etags, GST_TAG_MERGE_APPEND);
761 cur = gst_toc_entry_get_sub_entries (entry);
762 while (cur != NULL) {
763 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
764 chapter_targtes, tags);
770 gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
771 GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
772 GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
774 GstFlowReturn ret = GST_FLOW_OK;
780 DEBUG_ELEMENT_START (common, ebml, "TagTargets");
782 *target_type_value = 50;
785 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
786 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
790 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
791 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
795 case GST_MATROSKA_ID_TARGETCHAPTERUID:
796 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
797 g_array_append_val (chapter_targets, uid);
800 case GST_MATROSKA_ID_TARGETEDITIONUID:
801 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
802 g_array_append_val (edition_targets, uid);
805 case GST_MATROSKA_ID_TARGETTRACKUID:
806 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
807 g_array_append_val (track_targets, uid);
810 case GST_MATROSKA_ID_TARGETTYPEVALUE:
811 if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
812 *target_type_value = tmp;
815 case GST_MATROSKA_ID_TARGETTYPE:
816 if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
817 if (*target_type != NULL)
818 g_free (*target_type);
825 gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
831 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
837 gst_matroska_read_common_postprocess_toc_entries (GList * toc_entries,
838 guint64 max, const gchar * parent_uid)
840 GstTocEntry *cur_info, *prev_info, *next_info;
841 GList *cur_list, *prev_list, *next_list;
842 gint64 cur_start, prev_start, stop;
844 cur_list = toc_entries;
845 while (cur_list != NULL) {
846 cur_info = cur_list->data;
848 switch (gst_toc_entry_get_entry_type (cur_info)) {
849 case GST_TOC_ENTRY_TYPE_ANGLE:
850 case GST_TOC_ENTRY_TYPE_VERSION:
851 case GST_TOC_ENTRY_TYPE_EDITION:
852 /* in Matroska terms edition has duration of full track */
853 gst_toc_entry_set_start_stop_times (cur_info, 0, max);
855 gst_matroska_read_common_postprocess_toc_entries
856 (gst_toc_entry_get_sub_entries (cur_info), max,
857 gst_toc_entry_get_uid (cur_info));
860 case GST_TOC_ENTRY_TYPE_TITLE:
861 case GST_TOC_ENTRY_TYPE_TRACK:
862 case GST_TOC_ENTRY_TYPE_CHAPTER:
863 prev_list = cur_list->prev;
864 next_list = cur_list->next;
866 if (prev_list != NULL)
867 prev_info = prev_list->data;
871 if (next_list != NULL)
872 next_info = next_list->data;
876 /* updated stop time in previous chapter and it's subchapters */
877 if (prev_info != NULL) {
878 gst_toc_entry_get_start_stop_times (prev_info, &prev_start, &stop);
879 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
882 gst_toc_entry_set_start_stop_times (prev_info, prev_start, stop);
884 gst_matroska_read_common_postprocess_toc_entries
885 (gst_toc_entry_get_sub_entries (prev_info), cur_start,
886 gst_toc_entry_get_uid (prev_info));
889 /* updated stop time in current chapter and it's subchapters */
890 if (next_info == NULL) {
891 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
895 gst_toc_entry_set_start_stop_times (cur_info, cur_start, stop);
898 gst_matroska_read_common_postprocess_toc_entries
899 (gst_toc_entry_get_sub_entries (cur_info), stop,
900 gst_toc_entry_get_uid (cur_info));
903 case GST_TOC_ENTRY_TYPE_INVALID:
906 cur_list = cur_list->next;
911 gst_matroska_read_common_parse_chapter_titles (GstMatroskaReadCommon * common,
912 GstEbmlRead * ebml, GstTagList * titles)
916 GstFlowReturn ret = GST_FLOW_OK;
918 DEBUG_ELEMENT_START (common, ebml, "ChaptersTitles");
921 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
922 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
926 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
927 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
931 case GST_MATROSKA_ID_CHAPSTRING:
932 ret = gst_ebml_read_utf8 (ebml, &id, &title);
937 gst_matroska_read_common_parse_skip (common, ebml, "ChaptersTitles",
943 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
945 if (title != NULL && ret == GST_FLOW_OK)
946 gst_tag_list_add (titles, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title, NULL);
953 gst_matroska_read_common_parse_chapter_element (GstMatroskaReadCommon * common,
954 GstEbmlRead * ebml, GList ** subentries)
957 guint64 start_time = -1, stop_time = -1;
958 guint64 is_hidden = 0, is_enabled = 1, uid = 0;
959 GstFlowReturn ret = GST_FLOW_OK;
960 GstTocEntry *chapter_info;
963 GList *subsubentries = NULL, *l;
965 DEBUG_ELEMENT_START (common, ebml, "ChaptersElement");
967 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
968 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
972 tags = gst_tag_list_new_empty ();
974 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
975 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
979 case GST_MATROSKA_ID_CHAPTERUID:
980 ret = gst_ebml_read_uint (ebml, &id, &uid);
983 case GST_MATROSKA_ID_CHAPTERTIMESTART:
984 ret = gst_ebml_read_uint (ebml, &id, &start_time);
987 case GST_MATROSKA_ID_CHAPTERTIMESTOP:
988 ret = gst_ebml_read_uint (ebml, &id, &stop_time);
991 case GST_MATROSKA_ID_CHAPTERATOM:
993 gst_matroska_read_common_parse_chapter_element (common, ebml,
997 case GST_MATROSKA_ID_CHAPTERDISPLAY:
999 gst_matroska_read_common_parse_chapter_titles (common, ebml, tags);
1002 case GST_MATROSKA_ID_CHAPTERFLAGHIDDEN:
1003 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1006 case GST_MATROSKA_ID_CHAPTERFLAGENABLED:
1007 ret = gst_ebml_read_uint (ebml, &id, &is_enabled);
1012 gst_matroska_read_common_parse_skip (common, ebml,
1013 "ChaptersElement", id);
1019 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1020 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1021 chapter_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid_str);
1024 gst_toc_entry_set_tags (chapter_info, tags);
1025 gst_toc_entry_set_start_stop_times (chapter_info, start_time, stop_time);
1027 for (l = subsubentries; l; l = l->next)
1028 gst_toc_entry_append_sub_entry (chapter_info, l->data);
1029 g_list_free (subsubentries);
1031 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
1033 /* start time is mandatory and has no default value,
1034 * so we should skip chapters without it */
1035 if (is_hidden == 0 && is_enabled > 0 &&
1036 start_time != -1 && ret == GST_FLOW_OK) {
1037 *subentries = g_list_append (*subentries, chapter_info);
1039 gst_toc_entry_unref (chapter_info);
1044 static GstFlowReturn
1045 gst_matroska_read_common_parse_chapter_edition (GstMatroskaReadCommon * common,
1046 GstEbmlRead * ebml, GstToc * toc)
1049 guint64 is_hidden = 0, uid = 0;
1050 GstFlowReturn ret = GST_FLOW_OK;
1051 GstTocEntry *edition_info;
1052 GList *subentries = NULL, *l;
1055 DEBUG_ELEMENT_START (common, ebml, "ChaptersEdition");
1057 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1058 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1062 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1063 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1067 case GST_MATROSKA_ID_EDITIONUID:
1068 ret = gst_ebml_read_uint (ebml, &id, &uid);
1071 case GST_MATROSKA_ID_CHAPTERATOM:
1073 gst_matroska_read_common_parse_chapter_element (common, ebml,
1077 case GST_MATROSKA_ID_EDITIONFLAGHIDDEN:
1078 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1083 gst_matroska_read_common_parse_skip (common, ebml,
1084 "ChaptersEdition", id);
1089 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1092 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1093 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1094 edition_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, uid_str);
1095 gst_toc_entry_set_start_stop_times (edition_info, -1, -1);
1098 for (l = subentries; l; l = l->next)
1099 gst_toc_entry_append_sub_entry (edition_info, l->data);
1100 g_list_free (subentries);
1102 if (is_hidden == 0 && subentries != NULL && ret == GST_FLOW_OK)
1103 gst_toc_append_entry (toc, edition_info);
1105 GST_DEBUG_OBJECT (common->sinkpad,
1106 "Skipping empty or hidden edition in the chapters TOC");
1107 gst_toc_entry_unref (edition_info);
1114 gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common,
1118 GstFlowReturn ret = GST_FLOW_OK;
1121 DEBUG_ELEMENT_START (common, ebml, "Chapters");
1123 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1124 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1128 /* FIXME: create CURRENT toc as well */
1129 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1131 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1132 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1136 case GST_MATROSKA_ID_EDITIONENTRY:
1138 gst_matroska_read_common_parse_chapter_edition (common, ebml, toc);
1143 gst_matroska_read_common_parse_skip (common, ebml, "Chapters", id);
1148 if (gst_toc_get_entries (toc) != NULL) {
1149 gst_matroska_read_common_postprocess_toc_entries (gst_toc_get_entries (toc),
1150 common->segment.duration, "");
1154 gst_toc_unref (toc);
1156 common->chapters_parsed = TRUE;
1158 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1163 gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
1171 /* this function is the first to be called */
1177 ret = gst_ebml_peek_id (ebml, &id);
1178 if (ret != GST_FLOW_OK)
1181 GST_DEBUG_OBJECT (common->sinkpad, "id: %08x", id);
1183 if (id != GST_EBML_ID_HEADER) {
1184 GST_ERROR_OBJECT (common->sinkpad, "Failed to read header");
1188 ret = gst_ebml_read_master (ebml, &id);
1189 if (ret != GST_FLOW_OK)
1192 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1193 ret = gst_ebml_peek_id (ebml, &id);
1194 if (ret != GST_FLOW_OK)
1198 /* is our read version uptodate? */
1199 case GST_EBML_ID_EBMLREADVERSION:{
1202 ret = gst_ebml_read_uint (ebml, &id, &num);
1203 if (ret != GST_FLOW_OK)
1205 if (num != GST_EBML_VERSION) {
1206 GST_ERROR_OBJECT (common->sinkpad,
1207 "Unsupported EBML version %" G_GUINT64_FORMAT, num);
1211 GST_DEBUG_OBJECT (common->sinkpad,
1212 "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1216 /* we only handle 8 byte lengths at max */
1217 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
1220 ret = gst_ebml_read_uint (ebml, &id, &num);
1221 if (ret != GST_FLOW_OK)
1223 if (num > sizeof (guint64)) {
1224 GST_ERROR_OBJECT (common->sinkpad,
1225 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
1226 return GST_FLOW_ERROR;
1228 GST_DEBUG_OBJECT (common->sinkpad,
1229 "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
1233 /* we handle 4 byte IDs at max */
1234 case GST_EBML_ID_EBMLMAXIDLENGTH:{
1237 ret = gst_ebml_read_uint (ebml, &id, &num);
1238 if (ret != GST_FLOW_OK)
1240 if (num > sizeof (guint32)) {
1241 GST_ERROR_OBJECT (common->sinkpad,
1242 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
1243 return GST_FLOW_ERROR;
1245 GST_DEBUG_OBJECT (common->sinkpad,
1246 "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
1250 case GST_EBML_ID_DOCTYPE:{
1253 ret = gst_ebml_read_ascii (ebml, &id, &text);
1254 if (ret != GST_FLOW_OK)
1257 GST_DEBUG_OBJECT (common->sinkpad, "EbmlDocType: %s",
1258 GST_STR_NULL (text));
1266 case GST_EBML_ID_DOCTYPEREADVERSION:{
1269 ret = gst_ebml_read_uint (ebml, &id, &num);
1270 if (ret != GST_FLOW_OK)
1273 GST_DEBUG_OBJECT (common->sinkpad,
1274 "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1279 ret = gst_matroska_read_common_parse_skip (common, ebml,
1281 if (ret != GST_FLOW_OK)
1285 /* we ignore these two, as they don't tell us anything we care about */
1286 case GST_EBML_ID_EBMLVERSION:
1287 case GST_EBML_ID_DOCTYPEVERSION:
1288 ret = gst_ebml_read_skip (ebml);
1289 if (ret != GST_FLOW_OK)
1297 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
1298 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
1299 (doctype == NULL)) {
1302 GST_INFO_OBJECT (common->sinkpad, "Input is %s version %d", doctype,
1304 if (!strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM))
1305 common->is_webm = TRUE;
1307 GST_WARNING_OBJECT (common->sinkpad,
1308 "Input is EBML without doctype, assuming " "matroska (version %d)",
1313 GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
1314 ("Demuxer version (2) is too old to read %s version %d",
1315 GST_STR_NULL (doctype), version));
1316 ret = GST_FLOW_ERROR;
1319 GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
1320 ("Input is not a matroska stream (doctype=%s)", doctype));
1321 ret = GST_FLOW_ERROR;
1331 static GstFlowReturn
1332 gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
1333 GstEbmlRead * ebml, guint * nentries)
1337 GstMatroskaIndex idx;
1339 idx.pos = (guint64) - 1;
1341 idx.time = GST_CLOCK_TIME_NONE;
1344 DEBUG_ELEMENT_START (common, ebml, "CueTrackPositions");
1346 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1347 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1351 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1352 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1357 case GST_MATROSKA_ID_CUETRACK:
1361 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1366 GST_WARNING_OBJECT (common->sinkpad, "Invalid CueTrack 0");
1370 GST_DEBUG_OBJECT (common->sinkpad, "CueTrack: %" G_GUINT64_FORMAT, num);
1375 /* position in file */
1376 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
1380 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1383 if (num > G_MAXINT64) {
1384 GST_WARNING_OBJECT (common->sinkpad,
1385 "CueClusterPosition %" G_GUINT64_FORMAT " too large", num);
1393 /* number of block in the cluster */
1394 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
1398 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1402 GST_WARNING_OBJECT (common->sinkpad, "Invalid CueBlockNumber 0");
1406 GST_DEBUG_OBJECT (common->sinkpad, "CueBlockNumber: %" G_GUINT64_FORMAT,
1410 /* mild sanity check, disregard strange cases ... */
1411 if (idx.block > G_MAXUINT16) {
1412 GST_DEBUG_OBJECT (common->sinkpad, "... 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->sinkpad, "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->sinkpad,
1453 "CueTrackPositions without valid content");
1459 static GstFlowReturn
1460 gst_matroska_read_common_parse_index_pointentry (GstMatroskaReadCommon *
1461 common, GstEbmlRead * ebml)
1465 GstClockTime time = GST_CLOCK_TIME_NONE;
1468 DEBUG_ELEMENT_START (common, ebml, "CuePoint");
1470 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1471 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1475 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1476 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1480 /* one single index entry ('point') */
1481 case GST_MATROSKA_ID_CUETIME:
1483 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
1486 GST_DEBUG_OBJECT (common->sinkpad, "CueTime: %" G_GUINT64_FORMAT, time);
1487 time = time * common->time_scale;
1491 /* position in the file + track to which it belongs */
1492 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
1494 ret = gst_matroska_read_common_parse_index_cuetrack (common, ebml,
1500 ret = gst_matroska_read_common_parse_skip (common, ebml, "CuePoint",
1506 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1509 if (time == GST_CLOCK_TIME_NONE) {
1510 GST_WARNING_OBJECT (common->sinkpad, "CuePoint without valid time");
1511 g_array_remove_range (common->index, common->index->len - nentries,
1516 for (i = common->index->len - nentries; i < common->index->len; i++) {
1517 GstMatroskaIndex *idx =
1518 &g_array_index (common->index, GstMatroskaIndex, i);
1521 GST_DEBUG_OBJECT (common->sinkpad, "Index entry: pos=%" G_GUINT64_FORMAT
1522 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
1523 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
1527 GST_DEBUG_OBJECT (common->sinkpad, "Empty CuePoint");
1534 gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
1539 g_assert (common->src->len == common->num_streams);
1540 for (n = 0; n < common->src->len; n++) {
1541 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, n);
1543 if (context->num == track_num) {
1548 if (n == common->num_streams)
1549 GST_WARNING_OBJECT (common->sinkpad,
1550 "Failed to find corresponding pad for tracknum %d", track_num);
1556 gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
1560 GstFlowReturn ret = GST_FLOW_OK;
1564 g_array_free (common->index, TRUE);
1566 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1568 DEBUG_ELEMENT_START (common, ebml, "Cues");
1570 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1571 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1575 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1576 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1580 /* one single index entry ('point') */
1581 case GST_MATROSKA_ID_POINTENTRY:
1582 ret = gst_matroska_read_common_parse_index_pointentry (common, ebml);
1586 ret = gst_matroska_read_common_parse_skip (common, ebml, "Cues", id);
1590 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1592 /* Sort index by time, smallest time first, for easier searching */
1593 g_array_sort (common->index, (GCompareFunc) gst_matroska_index_compare);
1595 /* Now sort the track specific index entries into their own arrays */
1596 for (i = 0; i < common->index->len; i++) {
1597 GstMatroskaIndex *idx = &g_array_index (common->index, GstMatroskaIndex,
1600 GstMatroskaTrackContext *ctx;
1603 if (common->element_index) {
1606 if (idx->track != 0 &&
1608 gst_matroska_read_common_stream_from_num (common,
1609 idx->track)) != -1) {
1610 ctx = g_ptr_array_index (common->src, track_num);
1612 if (ctx->index_writer_id == -1)
1613 gst_index_get_writer_id (common->element_index,
1614 GST_OBJECT (ctx->pad), &ctx->index_writer_id);
1615 writer_id = ctx->index_writer_id;
1617 if (common->element_index_writer_id == -1)
1618 gst_index_get_writer_id (common->element_index, GST_OBJECT (common),
1619 &common->element_index_writer_id);
1620 writer_id = common->element_index_writer_id;
1623 GST_LOG_OBJECT (common->sinkpad,
1624 "adding association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT
1625 " for writer id %d", GST_TIME_ARGS (idx->time), idx->pos, writer_id);
1626 gst_index_add_association (common->element_index, writer_id,
1627 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
1628 GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
1632 if (idx->track == 0)
1635 track_num = gst_matroska_read_common_stream_from_num (common, idx->track);
1636 if (track_num == -1)
1639 ctx = g_ptr_array_index (common->src, track_num);
1641 if (ctx->index_table == NULL)
1643 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1645 g_array_append_vals (ctx->index_table, idx, 1);
1648 common->index_parsed = TRUE;
1650 /* sanity check; empty index normalizes to no index */
1651 if (common->index->len == 0) {
1652 g_array_free (common->index, TRUE);
1653 common->index = NULL;
1660 gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
1661 GstElement * el, GstEbmlRead * ebml)
1663 GstFlowReturn ret = GST_FLOW_OK;
1664 gdouble dur_f = -1.0;
1667 DEBUG_ELEMENT_START (common, ebml, "SegmentInfo");
1669 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1670 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1674 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1675 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1679 /* cluster timecode */
1680 case GST_MATROSKA_ID_TIMECODESCALE:{
1683 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1687 GST_DEBUG_OBJECT (common->sinkpad, "TimeCodeScale: %" G_GUINT64_FORMAT,
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->sinkpad, "Invalid duration %lf", dur_f);
1702 GST_DEBUG_OBJECT (common->sinkpad, "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->sinkpad, "WritingApp: %s",
1713 GST_STR_NULL (text));
1714 common->writing_app = text;
1718 case GST_MATROSKA_ID_MUXINGAPP:{
1721 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1724 GST_DEBUG_OBJECT (common->sinkpad, "MuxingApp: %s",
1725 GST_STR_NULL (text));
1726 common->muxing_app = text;
1730 case GST_MATROSKA_ID_DATEUTC:{
1733 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
1736 GST_DEBUG_OBJECT (common->sinkpad, "DateUTC: %" G_GINT64_FORMAT, time);
1737 common->created = time;
1741 case GST_MATROSKA_ID_TITLE:{
1743 GstTagList *taglist;
1745 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1748 GST_DEBUG_OBJECT (common->sinkpad, "Title: %s", GST_STR_NULL (text));
1749 taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
1750 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
1751 gst_matroska_read_common_found_global_tag (common, el, taglist);
1757 ret = gst_matroska_read_common_parse_skip (common, ebml,
1762 case GST_MATROSKA_ID_SEGMENTUID:
1763 case GST_MATROSKA_ID_SEGMENTFILENAME:
1764 case GST_MATROSKA_ID_PREVUID:
1765 case GST_MATROSKA_ID_PREVFILENAME:
1766 case GST_MATROSKA_ID_NEXTUID:
1767 case GST_MATROSKA_ID_NEXTFILENAME:
1768 case GST_MATROSKA_ID_SEGMENTFAMILY:
1769 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
1770 ret = gst_ebml_read_skip (ebml);
1778 dur_u = gst_gdouble_to_guint64 (dur_f *
1779 gst_guint64_to_gdouble (common->time_scale));
1780 if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
1781 common->segment.duration = dur_u;
1784 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1786 common->segmentinfo_parsed = TRUE;
1791 static GstFlowReturn
1792 gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
1793 common, GstEbmlRead * ebml, GstTagList ** p_taglist, gchar * parent)
1795 /* FIXME: check if there are more useful mappings */
1798 const gchar *matroska_tagname;
1799 const gchar *gstreamer_tagname;
1803 /* The following list has the _same_ order as the one in Matroska spec. Please, don't mess it up. */
1804 /* TODO: Nesting information:
1805 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.
1806 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.
1807 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.
1810 /* Organizational Information */
1811 GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
1812 GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}, {
1813 /* 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) */
1816 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. */
1817 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
1818 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1820 /* TODO: Nested Information:
1821 URL URL corresponding to the tag it's included in.
1822 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).
1823 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.
1824 EMAIL Email corresponding to the tag it's included in.
1825 ADDRESS The physical address of the entity. The address should include a country code. It can be useful for a recording label.
1826 FAX The fax number corresponding to the tag it's included in. It can be useful for a recording label.
1827 PHONE The phone number corresponding to the tag it's included in. It can be useful for a recording label.
1831 GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
1832 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
1833 GST_MATROSKA_TAG_ID_ACCOMPANIMENT, GST_TAG_PERFORMER}, { /* Band/orchestra/accompaniment/musician. This is akin to the TPE2 tag in ID3. */
1834 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
1835 /* ARRANGER The person who arranged the piece, e.g., Ravel. */
1836 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. */
1837 /* LYRICIST The person who wrote the lyrics for a musical item. This is akin to the TEXT tag in ID3. */
1838 GST_MATROSKA_TAG_ID_CONDUCTOR, GST_TAG_PERFORMER}, { /* Conductor/performer refinement. This is akin to the TPE3 tag in ID3. */
1839 /* DIRECTOR This is akin to the IART tag in RIFF. */
1840 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
1841 /* ASSISTANT_DIRECTOR The name of the assistant director. */
1842 /* DIRECTOR_OF_PHOTOGRAPHY The name of the director of photography, also known as cinematographer. This is akin to the ICNM tag in Extended RIFF. */
1843 /* SOUND_ENGINEER The name of the sound engineer or sound recordist. */
1844 /* ART_DIRECTOR The person who oversees the artists and craftspeople who build the sets. */
1845 /* PRODUCTION_DESIGNER Artist responsible for designing the overall visual appearance of a movie. */
1846 /* CHOREGRAPHER The name of the choregrapher */
1847 /* COSTUME_DESIGNER The name of the costume designer */
1848 /* 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. */
1849 /* 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. */
1850 /* WRITTEN_BY The author of the story or script (used for movies and TV shows). */
1851 /* SCREENPLAY_BY The author of the screenplay or scenario (used for movies and TV shows). */
1852 /* EDITED_BY This is akin to the IEDT tag in Extended RIFF. */
1853 /* PRODUCER Produced by. This is akin to the IPRO tag in Extended RIFF. */
1854 /* COPRODUCER The name of a co-producer. */
1855 /* EXECUTIVE_PRODUCER The name of an executive producer. */
1856 /* DISTRIBUTED_BY This is akin to the IDST tag in Extended RIFF. */
1857 /* MASTERED_BY The engineer who mastered the content for a physical medium or for digital distribution. */
1858 GST_MATROSKA_TAG_ID_ENCODED_BY, GST_TAG_ENCODED_BY}, { /* This is akin to the TENC tag in ID3. */
1859 /* MIXED_BY DJ mix by the artist specified */
1860 /* REMIXED_BY Interpreted, remixed, or otherwise modified by. This is akin to the TPE4 tag in ID3. */
1861 /* PRODUCTION_STUDIO This is akin to the ISTD tag in Extended RIFF. */
1862 /* THANKS_TO A very general tag for everyone else that wants to be listed. */
1863 /* PUBLISHER This is akin to the TPUB tag in ID3. */
1864 /* LABEL The record label or imprint on the disc. */
1865 /* Search / Classification */
1866 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
1867 /* 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. */
1868 /* 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. */
1869 /* CONTENT_TYPE The type of the item. e.g. Documentary, Feature Film, Cartoon, Music Video, Music, Sound FX, ... */
1870 /* SUBJECT Describes the topic of the file, such as "Aerial view of Seattle." */
1871 GST_MATROSKA_TAG_ID_DESCRIPTION, GST_TAG_DESCRIPTION}, { /* A short description of the content, such as "Two birds flying." */
1872 GST_MATROSKA_TAG_ID_KEYWORDS, GST_TAG_KEYWORDS}, { /* Keywords to the item separated by a comma, used for searching. */
1873 /* SUMMARY A plot outline or a summary of the story. */
1874 /* SYNOPSIS A description of the story line of the item. */
1875 /* INITIAL_KEY The initial key that a musical track starts in. The format is identical to ID3. */
1876 /* PERIOD Describes the period that the piece is from or about. For example, "Renaissance". */
1877 /* 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). */
1878 /* ICRA The ICRA content rating for parental control. (Previously RSACi) */
1880 /* Temporal Information */
1881 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. */
1882 GST_MATROSKA_TAG_ID_DATE_RECORDED, GST_TAG_DATE}, { /* The time that the recording began. This is akin to the TDRC tag in ID3. */
1883 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. */
1884 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. */
1885 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. */
1886 GST_MATROSKA_TAG_ID_DATE_WRITTEN, GST_TAG_DATE}, { /* The time that the writing of the music/script began. */
1887 GST_MATROSKA_TAG_ID_DATE_PURCHASED, GST_TAG_DATE}, { /* Information on when the file was purchased (see also purchase tags). */
1888 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1890 /* Spacial Information */
1891 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". */
1892 /* 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". */
1893 /* 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. */
1896 GST_MATROSKA_TAG_ID_COMMENT, GST_TAG_COMMENT}, { /* Any comment related to the content. */
1897 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1898 /* PLAY_COUNTER The number of time the item has been played. */
1899 /* 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. */
1901 /* Technical Information */
1902 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
1903 /* ENCODER_SETTINGS A list of the settings used for encoding this item. No specific format. */
1904 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
1905 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1906 /* 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. */
1907 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
1908 /* 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. */
1909 /* 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. */
1910 /* 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). */
1911 /* TODO: REPLAYGAIN_PEAK The maximum absolute peak value of the item. This is based on the Replay Gain standard. */
1914 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
1915 /* 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. */
1916 /* ISBN International Standard Book Number */
1917 /* BARCODE EAN-13 (European Article Numbering) or UPC-A (Universal Product Code) bar code identifier */
1918 /* CATALOG_NUMBER A label-specific string used to identify the release (TIC 01 for example). */
1919 /* 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). */
1920 /* LCCN Library of Congress Control Number */
1923 /* PURCHASE_ITEM URL to purchase this file. This is akin to the WPAY tag in ID3. */
1924 /* PURCHASE_INFO Information on where to purchase this album. This is akin to the WCOM tag in ID3. */
1925 /* PURCHASE_OWNER Information on the person who purchased the file. This is akin to the TOWN tag in ID3. */
1926 /* 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". */
1927 /* PURCHASE_CURRENCY The currency type used to pay for the entity. Use ISO-4217 for the 3 letter currency code. */
1930 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
1931 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. */
1932 GST_MATROSKA_TAG_ID_LICENSE, GST_TAG_LICENSE}, { /* The license applied to the content (like Creative Commons variants). */
1933 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}
1937 const gchar *matroska_tagname;
1938 const gchar *gstreamer_tagname;
1940 child_tag_conv[] = {
1942 "TITLE/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1943 "ARTIST/SORT_WITH=", GST_TAG_ARTIST_SORTNAME}, {
1944 /* ALBUM-stuff is handled elsewhere */
1945 "COMPOSER/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1946 "ORIGINAL/URL=", GST_TAG_LOCATION}, {
1947 /* EMAIL, PHONE, FAX all can be mapped to GST_TAG_CONTACT, there is special
1948 * code for that later.
1950 "TITLE/URL=", GST_TAG_HOMEPAGE}, {
1951 "ARTIST/URL=", GST_TAG_HOMEPAGE}, {
1952 "COPYRIGHT/URL=", GST_TAG_COPYRIGHT_URI}, {
1953 "LICENSE/URL=", GST_TAG_LICENSE_URI}, {
1954 "LICENSE/URL=", GST_TAG_LICENSE_URI}
1958 gchar *value = NULL;
1960 gchar *name_with_parent = NULL;
1961 GstTagList *child_taglist = NULL;
1963 DEBUG_ELEMENT_START (common, ebml, "SimpleTag");
1965 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1966 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
1971 child_taglist = *p_taglist;
1973 child_taglist = gst_tag_list_new_empty ();
1975 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1976 /* read all sub-entries */
1978 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1982 case GST_MATROSKA_ID_TAGNAME:
1985 ret = gst_ebml_read_ascii (ebml, &id, &tag);
1986 GST_DEBUG_OBJECT (common->sinkpad, "TagName: %s", GST_STR_NULL (tag));
1987 g_free (name_with_parent);
1989 name_with_parent = g_strdup_printf ("%s/%s", parent, tag);
1991 name_with_parent = g_strdup (tag);
1994 case GST_MATROSKA_ID_TAGSTRING:
1997 ret = gst_ebml_read_utf8 (ebml, &id, &value);
1998 GST_DEBUG_OBJECT (common->sinkpad, "TagString: %s",
1999 GST_STR_NULL (value));
2002 case GST_MATROSKA_ID_SIMPLETAG:
2003 /* Recursive SimpleTag */
2004 /* This implementation requires tag name of _this_ tag to be known
2005 * in order to read its children. It's not in the spec, just the way
2006 * the code is written.
2008 if (name_with_parent != NULL) {
2009 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2010 ebml, &child_taglist, name_with_parent);
2016 ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag",
2020 case GST_MATROSKA_ID_TAGLANGUAGE:
2021 case GST_MATROSKA_ID_TAGDEFAULT:
2022 case GST_MATROSKA_ID_TAGBINARY:
2023 ret = gst_ebml_read_skip (ebml);
2028 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
2030 if (parent && tag && value && *value != '\0') {
2031 /* Don't bother mapping children tags - parent will do that */
2033 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2034 key_val = g_strdup_printf ("%s=%s", name_with_parent, value);
2035 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2036 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2037 } else if (tag && value && *value != '\0') {
2038 gboolean matched = FALSE;
2041 for (i = 0; !matched && i < G_N_ELEMENTS (tag_conv); i++) {
2042 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2044 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2046 if (strcmp (tagname_mkv, tag) == 0) {
2047 GValue dest = { 0, };
2048 GType dest_type = gst_tag_get_type (tagname_gst);
2050 /* Ensure that any date string is complete */
2051 if (dest_type == G_TYPE_DATE) {
2052 guint year = 1901, month = 1, day = 1;
2054 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
2056 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
2058 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
2062 g_value_init (&dest, dest_type);
2063 if (gst_value_deserialize (&dest, value)) {
2064 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2065 tagname_gst, &dest, NULL);
2067 GST_WARNING_OBJECT (common->sinkpad, "Can't transform tag '%s' with "
2068 "value '%s' to target type '%s'", tag, value,
2069 g_type_name (dest_type));
2071 g_value_unset (&dest);
2077 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2078 key_val = g_strdup_printf ("%s=%s", tag, value);
2079 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2080 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2085 /* Map children tags. This only supports top-anchored mapping. That is,
2086 * we start at toplevel tag (this tag), and see how its combinations
2087 * with its children can be mapped. Which means that grandchildren
2088 * are also combined here, with _this_ tag taken into consideration.
2089 * If grandchildren can be combined only with children, that combination
2092 gint child_tags_n = gst_tag_list_n_tags (child_taglist);
2093 if (child_tags_n > 0) {
2095 for (i = 0; i < child_tags_n; i++) {
2097 const gchar *child_name = gst_tag_list_nth_tag_name (child_taglist, i);
2098 guint taglen = gst_tag_list_get_tag_size (child_taglist, child_name);
2099 for (j = 0; j < taglen; j++) {
2101 gboolean matched = FALSE;
2102 gchar *val_pre, *val_post;
2105 if (!gst_tag_list_get_string_index (child_taglist, child_name,
2108 if (!strchr (val, '=')) {
2112 val_post = g_strdup (strchr (val, '=') + 1);
2113 val_pre = g_strdup (val);
2114 *(strchr (val_pre, '=') + 1) = '\0';
2116 for (k = 0; !matched && k < G_N_ELEMENTS (child_tag_conv); k++) {
2117 const gchar *tagname_gst = child_tag_conv[k].gstreamer_tagname;
2119 const gchar *tagname_mkv = child_tag_conv[k].matroska_tagname;
2121 /* TODO: Once "key[lc]=value" form support is implemented,
2122 * strip [lc] here. It can't be used in combined tags.
2123 * If a tag is not combined, leave [lc] as it is.
2125 if (strcmp (tagname_mkv, val_pre) == 0) {
2126 GValue dest = { 0, };
2127 GType dest_type = gst_tag_get_type (tagname_gst);
2129 g_value_init (&dest, dest_type);
2130 if (gst_value_deserialize (&dest, val_post)) {
2131 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2132 tagname_gst, &dest, NULL);
2134 GST_WARNING_OBJECT (common->sinkpad,
2135 "Can't transform complex tag '%s' " "to target type '%s'",
2136 val, g_type_name (dest_type));
2138 g_value_unset (&dest);
2143 gchar *last_slash = strrchr (val_pre, '/');
2146 if (strcmp (last_slash, "EMAIL=") == 0 ||
2147 strcmp (last_slash, "PHONE=") == 0 ||
2148 strcmp (last_slash, "ADDRESS=") == 0 ||
2149 strcmp (last_slash, "FAX=") == 0) {
2150 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2151 GST_TAG_CONTACT, val_post, NULL);
2157 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2158 GST_TAG_EXTENDED_COMMENT, val, NULL);
2165 gst_tag_list_unref (child_taglist);
2170 g_free (name_with_parent);
2177 gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
2178 gint * a, gint * v, gint * s)
2181 gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
2183 for (i = 0; i < common->src->len; i++) {
2184 GstMatroskaTrackContext *stream;
2186 stream = g_ptr_array_index (common->src, i);
2187 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
2189 else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
2191 else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
2192 subtitle_streams += 1;
2196 *v = subtitle_streams;
2201 gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
2202 const gchar * tag, gpointer user_data)
2206 TargetTypeContext *ctx = (TargetTypeContext *) user_data;
2208 vallen = gst_tag_list_get_tag_size (list, tag);
2212 for (i = 0; i < vallen; i++) {
2214 const GValue *val_ref;
2216 val_ref = gst_tag_list_get_value_index (list, tag, i);
2217 if (val_ref == NULL)
2219 g_value_init (&val, G_VALUE_TYPE (val_ref));
2220 g_value_copy (val_ref, &val);
2222 /* TODO: use the optional ctx->target_type somehow */
2223 if (strcmp (tag, GST_TAG_TITLE) == 0) {
2224 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2225 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2226 GST_TAG_SHOW_NAME, &val);
2228 } else if (ctx->target_type_value >= 50) {
2229 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2230 GST_TAG_ALBUM, &val);
2233 } else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
2234 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2235 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2236 GST_TAG_SHOW_SORTNAME, &val);
2238 } else if (ctx->target_type_value >= 50) {
2239 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2240 GST_TAG_ALBUM_SORTNAME, &val);
2243 } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
2244 if (ctx->target_type_value >= 50) {
2245 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2246 GST_TAG_ALBUM_ARTIST, &val);
2249 } else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
2250 if (ctx->target_type_value >= 50) {
2251 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2252 GST_TAG_ALBUM_ARTIST_SORTNAME, &val);
2255 } else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
2256 if (ctx->target_type_value >= 60) {
2257 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2258 GST_TAG_ALBUM_VOLUME_COUNT, &val);
2261 } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
2262 if (ctx->target_type_value >= 60 && !ctx->audio_only) {
2263 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2264 GST_TAG_SHOW_SEASON_NUMBER, &val);
2266 } else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
2267 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2268 GST_TAG_SHOW_EPISODE_NUMBER, &val);
2270 } else if (ctx->target_type_value >= 50) {
2271 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2272 GST_TAG_ALBUM_VOLUME_NUMBER, &val);
2276 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, &val);
2277 g_value_unset (&val);
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 GST_FIXME_OBJECT (common->sinkpad,
2398 "Found track-specific tag(s), but track %" G_GUINT64_FORMAT
2399 " is not known (yet?)", tgt);
2403 gst_tag_list_insert (*p_taglist, taglist, GST_TAG_MERGE_APPEND);
2405 gst_tag_list_unref (taglist);
2406 g_array_unref (chapter_targets);
2407 g_array_unref (edition_targets);
2408 g_array_unref (track_targets);
2414 gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
2415 GstElement * el, GstEbmlRead * ebml)
2417 GstTagList *taglist;
2418 GstFlowReturn ret = GST_FLOW_OK;
2423 curpos = gst_ebml_read_get_pos (ebml);
2425 /* Make sure we don't parse a tags element twice and
2426 * post it's tags twice */
2427 curpos = gst_ebml_read_get_pos (ebml);
2428 for (l = common->tags_parsed; l; l = l->next) {
2429 guint64 *pos = l->data;
2431 if (*pos == curpos) {
2432 GST_DEBUG_OBJECT (common->sinkpad,
2433 "Skipping already parsed Tags at offset %" G_GUINT64_FORMAT, curpos);
2438 common->tags_parsed =
2439 g_list_prepend (common->tags_parsed, g_slice_new (guint64));
2440 *((guint64 *) common->tags_parsed->data) = curpos;
2443 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2444 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2448 taglist = gst_tag_list_new_empty ();
2449 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
2450 common->toc_updated = FALSE;
2452 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2453 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2457 case GST_MATROSKA_ID_TAG:
2458 ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml,
2463 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id);
2465 /* FIXME: Use to limit the tags to specific pads */
2469 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2471 if (G_LIKELY (!gst_tag_list_is_empty (taglist)))
2472 gst_matroska_read_common_found_global_tag (common, el, taglist);
2474 gst_tag_list_unref (taglist);
2479 static GstFlowReturn
2480 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
2481 peek, const guint8 ** data)
2483 /* Caller needs to gst_adapter_unmap. */
2484 *data = gst_adapter_map (common->adapter, peek);
2486 return GST_FLOW_EOS;
2492 * Calls pull_range for (offset,size) without advancing our offset
2495 gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
2496 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
2500 /* Caching here actually makes much less difference than one would expect.
2501 * We do it mainly to avoid pulling buffers of 1 byte all the time */
2502 if (common->cached_buffer) {
2503 guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
2504 gsize cache_size = gst_buffer_get_size (common->cached_buffer);
2506 if (cache_offset <= common->offset &&
2507 (common->offset + size) <= (cache_offset + cache_size)) {
2509 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2510 GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
2512 if (!common->cached_data) {
2513 gst_buffer_map (common->cached_buffer, &common->cached_map,
2515 common->cached_data = common->cached_map.data;
2517 *bytes = common->cached_data + common->offset - cache_offset;
2521 /* not enough data in the cache, free cache and get a new one */
2522 if (common->cached_data) {
2523 gst_buffer_unmap (common->cached_buffer, &common->cached_map);
2524 common->cached_data = NULL;
2526 gst_buffer_unref (common->cached_buffer);
2527 common->cached_buffer = NULL;
2530 /* refill the cache */
2531 ret = gst_pad_pull_range (common->sinkpad, common->offset,
2532 MAX (size, 64 * 1024), &common->cached_buffer);
2533 if (ret != GST_FLOW_OK) {
2534 common->cached_buffer = NULL;
2538 if (gst_buffer_get_size (common->cached_buffer) >= size) {
2540 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2541 GST_BUFFER_COPY_ALL, 0, size);
2543 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2544 common->cached_data = common->cached_map.data;
2545 *bytes = common->cached_data;
2550 /* Not possible to get enough data, try a last time with
2551 * requesting exactly the size we need */
2552 gst_buffer_unref (common->cached_buffer);
2553 common->cached_buffer = NULL;
2556 gst_pad_pull_range (common->sinkpad, common->offset, size,
2557 &common->cached_buffer);
2558 if (ret != GST_FLOW_OK) {
2559 GST_DEBUG_OBJECT (common->sinkpad, "pull_range returned %d", ret);
2567 if (gst_buffer_get_size (common->cached_buffer) < size) {
2568 GST_WARNING_OBJECT (common->sinkpad, "Dropping short buffer at offset %"
2569 G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2570 common->offset, size, gst_buffer_get_size (common->cached_buffer));
2572 gst_buffer_unref (common->cached_buffer);
2573 common->cached_buffer = NULL;
2578 return GST_FLOW_EOS;
2582 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2583 GST_BUFFER_COPY_ALL, 0, size);
2585 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2586 common->cached_data = common->cached_map.data;
2587 *bytes = common->cached_data;
2593 static GstFlowReturn
2594 gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek,
2597 return gst_matroska_read_common_peek_bytes (common, common->offset, peek,
2602 gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
2603 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2605 return gst_ebml_peek_id_length (_id, _length, _needed,
2606 (GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
2611 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
2612 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2616 ret = gst_ebml_peek_id_length (_id, _length, _needed,
2617 (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
2618 el, common->offset);
2620 gst_adapter_unmap (common->adapter);
2625 static GstFlowReturn
2626 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
2627 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2629 GstMatroskaTrackEncoding enc = { 0, };
2633 DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
2634 /* Set default values */
2636 /* All other default values are 0 */
2638 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2639 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2643 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2644 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2648 case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
2651 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2654 if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
2656 GST_ERROR_OBJECT (common->sinkpad,
2657 "ContentEncodingOrder %" G_GUINT64_FORMAT
2658 "is not unique for track %" G_GUINT64_FORMAT, num, context->num);
2659 ret = GST_FLOW_ERROR;
2663 GST_DEBUG_OBJECT (common->sinkpad,
2664 "ContentEncodingOrder: %" G_GUINT64_FORMAT, num);
2668 case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
2671 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2674 if (num > 7 || num == 0) {
2675 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentEncodingScope %"
2676 G_GUINT64_FORMAT, num);
2677 ret = GST_FLOW_ERROR;
2681 GST_DEBUG_OBJECT (common->sinkpad,
2682 "ContentEncodingScope: %" G_GUINT64_FORMAT, num);
2687 case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
2690 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2694 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentEncodingType %"
2695 G_GUINT64_FORMAT, num);
2696 ret = GST_FLOW_ERROR;
2698 } else if (num != 0) {
2699 GST_ERROR_OBJECT (common->sinkpad,
2700 "Encrypted tracks are not supported yet");
2701 ret = GST_FLOW_ERROR;
2704 GST_DEBUG_OBJECT (common->sinkpad,
2705 "ContentEncodingType: %" G_GUINT64_FORMAT, num);
2709 case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
2711 DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
2713 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
2716 while (ret == GST_FLOW_OK &&
2717 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2718 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2722 case GST_MATROSKA_ID_CONTENTCOMPALGO:{
2725 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
2729 GST_ERROR_OBJECT (common->sinkpad, "Invalid ContentCompAlgo %"
2730 G_GUINT64_FORMAT, num);
2731 ret = GST_FLOW_ERROR;
2734 GST_DEBUG_OBJECT (common->sinkpad,
2735 "ContentCompAlgo: %" G_GUINT64_FORMAT, num);
2736 enc.comp_algo = num;
2740 case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
2745 gst_ebml_read_binary (ebml, &id, &data,
2746 &size)) != GST_FLOW_OK) {
2749 enc.comp_settings = data;
2750 enc.comp_settings_length = size;
2751 GST_DEBUG_OBJECT (common->sinkpad,
2752 "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
2756 GST_WARNING_OBJECT (common->sinkpad,
2757 "Unknown ContentCompression subelement 0x%x - ignoring", id);
2758 ret = gst_ebml_read_skip (ebml);
2762 DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
2766 case GST_MATROSKA_ID_CONTENTENCRYPTION:
2767 GST_ERROR_OBJECT (common->sinkpad,
2768 "Encrypted tracks not yet supported");
2769 gst_ebml_read_skip (ebml);
2770 ret = GST_FLOW_ERROR;
2773 GST_WARNING_OBJECT (common->sinkpad,
2774 "Unknown ContentEncoding subelement 0x%x - ignoring", id);
2775 ret = gst_ebml_read_skip (ebml);
2780 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2781 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2784 /* TODO: Check if the combination of values is valid */
2786 g_array_append_val (context->encodings, enc);
2792 gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
2793 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2798 DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
2800 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2801 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2805 context->encodings =
2806 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
2808 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2809 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2813 case GST_MATROSKA_ID_CONTENTENCODING:
2814 ret = gst_matroska_read_common_read_track_encoding (common, ebml,
2818 GST_WARNING_OBJECT (common->sinkpad,
2819 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
2820 ret = gst_ebml_read_skip (ebml);
2825 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2826 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2829 /* Sort encodings according to their order */
2830 g_array_sort (context->encodings,
2831 (GCompareFunc) gst_matroska_read_common_encoding_cmp);
2833 return gst_matroska_decode_content_encodings (context->encodings);
2837 gst_matroska_read_common_free_parsed_el (gpointer mem, gpointer user_data)
2839 g_slice_free (guint64, mem);
2843 gst_matroska_read_common_init (GstMatroskaReadCommon * ctx)
2846 ctx->writing_app = NULL;
2847 ctx->muxing_app = NULL;
2849 ctx->global_tags = NULL;
2850 ctx->adapter = gst_adapter_new ();
2854 gst_matroska_read_common_finalize (GstMatroskaReadCommon * ctx)
2857 g_ptr_array_free (ctx->src, TRUE);
2861 if (ctx->global_tags) {
2862 gst_tag_list_unref (ctx->global_tags);
2863 ctx->global_tags = NULL;
2866 g_object_unref (ctx->adapter);
2870 gst_matroska_read_common_reset (GstElement * element,
2871 GstMatroskaReadCommon * ctx)
2875 GST_LOG_OBJECT (ctx->sinkpad, "resetting read context");
2878 ctx->state = GST_MATROSKA_READ_STATE_START;
2880 /* clean up existing streams if any */
2882 g_assert (ctx->src->len == ctx->num_streams);
2883 for (i = 0; i < ctx->src->len; i++) {
2884 GstMatroskaTrackContext *context = g_ptr_array_index (ctx->src, i);
2886 if (context->pad != NULL)
2887 gst_element_remove_pad (element, context->pad);
2889 gst_caps_replace (&context->caps, NULL);
2890 gst_matroska_track_free (context);
2892 g_ptr_array_free (ctx->src, TRUE);
2894 ctx->src = g_ptr_array_new ();
2895 ctx->num_streams = 0;
2897 /* reset media info */
2898 g_free (ctx->writing_app);
2899 ctx->writing_app = NULL;
2900 g_free (ctx->muxing_app);
2901 ctx->muxing_app = NULL;
2903 /* reset stream type */
2904 ctx->is_webm = FALSE;
2905 ctx->has_video = FALSE;
2909 g_array_free (ctx->index, TRUE);
2914 ctx->time_scale = 1000000;
2915 ctx->created = G_MININT64;
2917 /* cues/tracks/segmentinfo */
2918 ctx->index_parsed = FALSE;
2919 ctx->segmentinfo_parsed = FALSE;
2920 ctx->attachments_parsed = FALSE;
2921 ctx->chapters_parsed = FALSE;
2924 ctx->global_tags_changed = FALSE;
2925 g_list_foreach (ctx->tags_parsed,
2926 (GFunc) gst_matroska_read_common_free_parsed_el, NULL);
2927 g_list_free (ctx->tags_parsed);
2928 ctx->tags_parsed = NULL;
2929 if (ctx->global_tags) {
2930 gst_tag_list_unref (ctx->global_tags);
2932 ctx->global_tags = gst_tag_list_new_empty ();
2933 gst_tag_list_set_scope (ctx->global_tags, GST_TAG_SCOPE_GLOBAL);
2935 gst_segment_init (&ctx->segment, GST_FORMAT_TIME);
2938 if (ctx->cached_buffer) {
2939 if (ctx->cached_data) {
2940 gst_buffer_unmap (ctx->cached_buffer, &ctx->cached_map);
2941 ctx->cached_data = NULL;
2943 gst_buffer_unref (ctx->cached_buffer);
2944 ctx->cached_buffer = NULL;
2947 /* free chapters TOC if any */
2949 gst_toc_unref (ctx->toc);
2954 /* call with object lock held */
2956 gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
2957 GstClockTime time, gboolean full)
2961 GST_DEBUG_OBJECT (common->sinkpad, "resetting stream state");
2963 g_assert (common->src->len == common->num_streams);
2964 for (i = 0; i < common->src->len; i++) {
2965 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2966 context->pos = time;
2967 context->set_discont = TRUE;
2968 context->eos = FALSE;
2969 context->from_time = GST_CLOCK_TIME_NONE;
2970 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2971 GstMatroskaTrackVideoContext *videocontext =
2972 (GstMatroskaTrackVideoContext *) context;
2973 /* demux object lock held by caller */
2974 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2980 gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
2985 g_assert (common->src->len == common->num_streams);
2986 for (i = 0; i < common->src->len; i++) {
2987 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2989 if (context->num == num)