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"
48 GST_DEBUG_CATEGORY (matroskareadcommon_debug);
49 #define GST_CAT_DEFAULT matroskareadcommon_debug
51 #define DEBUG_ELEMENT_START(common, ebml, element) \
52 GST_DEBUG_OBJECT (common, "Parsing " element " element at offset %" \
53 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
55 #define DEBUG_ELEMENT_STOP(common, ebml, element, ret) \
56 GST_DEBUG_OBJECT (common, "Parsing " element " element " \
57 " finished with '%s'", gst_flow_get_name (ret))
59 #define GST_MATROSKA_TOC_UID_CHAPTER "chapter"
60 #define GST_MATROSKA_TOC_UID_EDITION "edition"
61 #define GST_MATROSKA_TOC_UID_EMPTY "empty"
66 guint64 target_type_value;
73 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
74 gpointer * data_out, gsize * size_out,
75 GstMatroskaTrackCompressionAlgorithm algo)
77 guint8 *new_data = NULL;
79 guint8 *data = *data_out;
80 guint size = *size_out;
83 if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
85 /* zlib encoded data */
91 zstream.zalloc = (alloc_func) 0;
92 zstream.zfree = (free_func) 0;
93 zstream.opaque = (voidpf) 0;
94 if (inflateInit (&zstream) != Z_OK) {
95 GST_WARNING ("zlib initialization failed.");
99 zstream.next_in = (Bytef *) data;
100 zstream.avail_in = orig_size;
101 new_size = orig_size;
102 new_data = g_malloc (new_size);
103 zstream.avail_out = new_size;
104 zstream.next_out = (Bytef *) new_data;
107 result = inflate (&zstream, Z_NO_FLUSH);
108 if (result != Z_OK && result != Z_STREAM_END) {
109 GST_WARNING ("zlib decompression failed.");
111 inflateEnd (&zstream);
115 new_data = g_realloc (new_data, new_size);
116 zstream.next_out = (Bytef *) (new_data + zstream.total_out);
117 zstream.avail_out += 4000;
118 } while (zstream.avail_in != 0 && result != Z_STREAM_END);
120 if (result != Z_STREAM_END) {
124 new_size = zstream.total_out;
125 inflateEnd (&zstream);
128 GST_WARNING ("zlib encoded tracks not supported.");
132 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
134 /* bzip2 encoded data */
139 bzstream.bzalloc = NULL;
140 bzstream.bzfree = NULL;
141 bzstream.opaque = NULL;
144 if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
145 GST_WARNING ("bzip2 initialization failed.");
150 bzstream.next_in = (char *) data;
151 bzstream.avail_in = orig_size;
152 new_size = orig_size;
153 new_data = g_malloc (new_size);
154 bzstream.avail_out = new_size;
155 bzstream.next_out = (char *) new_data;
158 result = BZ2_bzDecompress (&bzstream);
159 if (result != BZ_OK && result != BZ_STREAM_END) {
160 GST_WARNING ("bzip2 decompression failed.");
162 BZ2_bzDecompressEnd (&bzstream);
166 new_data = g_realloc (new_data, new_size);
167 bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
168 bzstream.avail_out += 4000;
169 } while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
171 if (result != BZ_STREAM_END) {
175 new_size = bzstream.total_out_lo32;
176 BZ2_bzDecompressEnd (&bzstream);
179 GST_WARNING ("bzip2 encoded tracks not supported.");
183 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
184 /* lzo encoded data */
186 int orig_size, out_size;
191 new_data = g_malloc (new_size);
197 result = lzo1x_decode (new_data, &out_size, data, &orig_size);
201 new_data = g_realloc (new_data, new_size);
203 } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
205 new_size -= out_size;
207 if (result != LZO_OUTPUT_FULL) {
208 GST_WARNING ("lzo decompression failed");
215 } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
216 /* header stripped encoded data */
217 if (enc->comp_settings_length > 0) {
218 new_data = g_malloc (size + enc->comp_settings_length);
219 new_size = size + enc->comp_settings_length;
221 memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
222 memcpy (new_data + enc->comp_settings_length, data, size);
225 GST_ERROR ("invalid compression algorithm %d", algo);
235 *data_out = new_data;
236 *size_out = new_size;
243 gst_matroska_decode_content_encodings (GArray * encodings)
247 if (encodings == NULL)
250 for (i = 0; i < encodings->len; i++) {
251 GstMatroskaTrackEncoding *enc =
252 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
253 gpointer data = NULL;
256 if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
260 /* Encryption not supported yet */
262 return GST_FLOW_ERROR;
264 if (i + 1 >= encodings->len)
265 return GST_FLOW_ERROR;
267 if (enc->comp_settings_length == 0)
270 data = enc->comp_settings;
271 size = enc->comp_settings_length;
273 if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
274 return GST_FLOW_ERROR;
276 g_free (enc->comp_settings);
278 enc->comp_settings = data;
279 enc->comp_settings_length = size;
286 gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
287 gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
294 g_return_val_if_fail (encodings != NULL, FALSE);
295 g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
296 g_return_val_if_fail (size_out != NULL, FALSE);
301 for (i = 0; i < encodings->len; i++) {
302 GstMatroskaTrackEncoding *enc =
303 &g_array_index (encodings, GstMatroskaTrackEncoding, i);
304 gpointer new_data = NULL;
307 if ((enc->scope & scope) == 0)
310 /* Encryption not supported yet */
311 if (enc->type != 0) {
320 gst_matroska_decompress_data (enc, &new_data, &new_size,
326 if ((data == *data_out && free) || (data != *data_out))
334 if ((data == *data_out && free) || (data != *data_out))
348 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
350 if (i1->time < i2->time)
352 else if (i1->time > i2->time)
354 else if (i1->block < i2->block)
356 else if (i1->block > i2->block)
363 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
366 if (i1->time < *time)
368 else if (i1->time > *time)
375 gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
376 GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
377 gint * _entry_index, gboolean next)
379 GstMatroskaIndex *entry = NULL;
382 if (!common->index || !common->index->len)
385 /* find entry just before or at the requested position */
386 if (track && track->index_table)
387 index = track->index_table;
389 index = common->index;
392 gst_util_array_binary_search (index->data, index->len,
393 sizeof (GstMatroskaIndex),
394 (GCompareDataFunc) gst_matroska_index_seek_find,
395 next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL);
401 entry = &g_array_index (index, GstMatroskaIndex, 0);
408 *_entry_index = entry - (GstMatroskaIndex *) index->data;
414 gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
415 GstMatroskaTrackEncoding * b)
417 if (b->order > a->order)
419 else if (b->order < a->order)
426 gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
431 if (encodings == NULL || encodings->len == 0)
434 for (i = 0; i < encodings->len; i++)
435 if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
441 /* takes ownership of taglist */
443 gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
444 GstElement * el, GstTagList * taglist)
446 if (common->global_tags) {
447 /* nothing sent yet, add to cache */
448 gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
449 gst_tag_list_unref (taglist);
451 GstEvent *tag_event = gst_event_new_tag (taglist);
454 /* hm, already sent, no need to cache and wait anymore */
455 GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
458 for (i = 0; i < common->src->len; i++) {
459 GstMatroskaTrackContext *stream;
461 stream = g_ptr_array_index (common->src, i);
462 gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
465 gst_event_unref (tag_event);
470 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
474 if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
476 GST_DEBUG_OBJECT (common, "no upstream length");
481 /* determine track to seek in */
482 GstMatroskaTrackContext *
483 gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
484 GstMatroskaTrackContext * track)
488 if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
491 for (i = 0; i < common->src->len; i++) {
492 GstMatroskaTrackContext *stream;
494 stream = g_ptr_array_index (common->src, i);
495 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
502 /* skip unknown or alike element */
504 gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
505 GstEbmlRead * ebml, const gchar * parent_name, guint id)
507 if (id == GST_EBML_ID_VOID) {
508 GST_DEBUG_OBJECT (common, "Skipping EBML Void element");
509 } else if (id == GST_EBML_ID_CRC32) {
510 GST_DEBUG_OBJECT (common, "Skipping EBML CRC32 element");
512 GST_WARNING_OBJECT (common,
513 "Unknown %s subelement 0x%x - ignoring", parent_name, id);
516 return gst_ebml_read_skip (ebml);
520 gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
521 GstEbmlRead * ebml, GstTagList * taglist)
525 gchar *description = NULL;
526 gchar *filename = NULL;
527 gchar *mimetype = NULL;
531 DEBUG_ELEMENT_START (common, ebml, "AttachedFile");
533 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
534 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
538 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
539 /* read all sub-entries */
541 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
545 case GST_MATROSKA_ID_FILEDESCRIPTION:
547 GST_WARNING_OBJECT (common, "FileDescription can only appear once");
551 ret = gst_ebml_read_utf8 (ebml, &id, &description);
552 GST_DEBUG_OBJECT (common, "FileDescription: %s",
553 GST_STR_NULL (description));
555 case GST_MATROSKA_ID_FILENAME:
557 GST_WARNING_OBJECT (common, "FileName can only appear once");
561 ret = gst_ebml_read_utf8 (ebml, &id, &filename);
563 GST_DEBUG_OBJECT (common, "FileName: %s", GST_STR_NULL (filename));
565 case GST_MATROSKA_ID_FILEMIMETYPE:
567 GST_WARNING_OBJECT (common, "FileMimeType can only appear once");
571 ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
572 GST_DEBUG_OBJECT (common, "FileMimeType: %s", GST_STR_NULL (mimetype));
574 case GST_MATROSKA_ID_FILEDATA:
576 GST_WARNING_OBJECT (common, "FileData can only appear once");
580 ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
581 GST_DEBUG_OBJECT (common, "FileData of size %" G_GUINT64_FORMAT,
586 ret = gst_matroska_read_common_parse_skip (common, ebml,
589 case GST_MATROSKA_ID_FILEUID:
590 ret = gst_ebml_read_skip (ebml);
595 DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
597 if (filename && mimetype && data && datalen > 0) {
598 GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
599 GstBuffer *tagbuffer = NULL;
600 GstSample *tagsample = NULL;
601 GstStructure *info = NULL;
602 GstCaps *caps = NULL;
603 gchar *filename_lc = g_utf8_strdown (filename, -1);
605 GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
606 "filename '%s', mimetype '%s', description '%s', "
607 "size %" G_GUINT64_FORMAT, filename, mimetype,
608 GST_STR_NULL (description), datalen);
610 /* TODO: better heuristics for different image types */
611 if (strstr (filename_lc, "cover")) {
612 if (strstr (filename_lc, "back"))
613 image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
615 image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
616 } else if (g_str_has_prefix (mimetype, "image/") ||
617 g_str_has_suffix (filename_lc, "png") ||
618 g_str_has_suffix (filename_lc, "jpg") ||
619 g_str_has_suffix (filename_lc, "jpeg") ||
620 g_str_has_suffix (filename_lc, "gif") ||
621 g_str_has_suffix (filename_lc, "bmp")) {
622 image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
624 g_free (filename_lc);
626 /* First try to create an image tag buffer from this */
627 if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
629 gst_tag_image_data_to_image_sample (data, datalen, image_type);
632 image_type = GST_TAG_IMAGE_TYPE_NONE;
635 tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
636 caps = gst_caps_ref (gst_sample_get_caps (tagsample));
637 info = gst_structure_copy (gst_sample_get_info (tagsample));
638 gst_sample_unref (tagsample);
642 /* if this failed create an attachment buffer */
644 tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
646 caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
648 caps = gst_caps_new_empty_simple (mimetype);
651 /* Set filename and description in the info */
653 info = gst_structure_new_empty ("GstTagImageInfo");
655 gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
657 gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
659 tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
661 GST_DEBUG_OBJECT (common,
662 "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
664 /* and append to the tag list */
665 if (image_type != GST_TAG_IMAGE_TYPE_NONE)
666 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
669 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
672 /* the list adds it own ref */
673 gst_sample_unref (tagsample);
679 g_free (description);
685 gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
686 GstElement * el, GstEbmlRead * ebml)
689 GstFlowReturn ret = GST_FLOW_OK;
692 DEBUG_ELEMENT_START (common, ebml, "Attachments");
694 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
695 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
699 taglist = gst_tag_list_new_empty ();
700 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
702 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
703 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
707 case GST_MATROSKA_ID_ATTACHEDFILE:
708 ret = gst_matroska_read_common_parse_attached_file (common, ebml,
713 ret = gst_matroska_read_common_parse_skip (common, ebml,
718 DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
720 if (gst_tag_list_n_tags (taglist) > 0) {
721 GST_DEBUG_OBJECT (common, "Storing attachment tags");
722 gst_matroska_read_common_found_global_tag (common, el, taglist);
724 GST_DEBUG_OBJECT (common, "No valid attachments found");
725 gst_tag_list_unref (taglist);
728 common->attachments_parsed = TRUE;
734 gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
735 GArray * edition_targets, GArray * chapter_targtes, GstTagList * tags)
745 (gst_toc_entry_get_entry_type (entry) ==
746 GST_TOC_ENTRY_TYPE_EDITION) ? edition_targets : chapter_targtes;
748 etags = gst_tag_list_new_empty ();
750 for (i = 0; i < targets->len; ++i) {
751 tgt = g_array_index (targets, guint64, i);
754 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
756 uid = g_strdup_printf ("%" G_GUINT64_FORMAT, tgt);
757 if (g_strcmp0 (gst_toc_entry_get_uid (entry), uid) == 0)
758 gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
763 gst_toc_entry_merge_tags (entry, etags, GST_TAG_MERGE_APPEND);
765 cur = gst_toc_entry_get_sub_entries (entry);
766 while (cur != NULL) {
767 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
768 chapter_targtes, tags);
774 gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
775 GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
776 GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
778 GstFlowReturn ret = GST_FLOW_OK;
784 DEBUG_ELEMENT_START (common, ebml, "TagTargets");
786 *target_type_value = 50;
789 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
790 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
794 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
795 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
799 case GST_MATROSKA_ID_TARGETCHAPTERUID:
800 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
801 g_array_append_val (chapter_targets, uid);
804 case GST_MATROSKA_ID_TARGETEDITIONUID:
805 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
806 g_array_append_val (edition_targets, uid);
809 case GST_MATROSKA_ID_TARGETTRACKUID:
810 if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
811 g_array_append_val (track_targets, uid);
814 case GST_MATROSKA_ID_TARGETTYPEVALUE:
815 if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
816 *target_type_value = tmp;
819 case GST_MATROSKA_ID_TARGETTYPE:
820 if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
821 if (*target_type != NULL)
822 g_free (*target_type);
829 gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
835 DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
841 gst_matroska_read_common_postprocess_toc_entries (GList * toc_entries,
842 guint64 max, const gchar * parent_uid)
844 GstTocEntry *cur_info, *prev_info, *next_info;
845 GList *cur_list, *prev_list, *next_list;
846 gint64 cur_start, prev_start, stop;
848 cur_list = toc_entries;
849 while (cur_list != NULL) {
850 cur_info = cur_list->data;
852 switch (gst_toc_entry_get_entry_type (cur_info)) {
853 case GST_TOC_ENTRY_TYPE_ANGLE:
854 case GST_TOC_ENTRY_TYPE_VERSION:
855 case GST_TOC_ENTRY_TYPE_EDITION:
856 /* in Matroska terms edition has duration of full track */
857 gst_toc_entry_set_start_stop_times (cur_info, 0, max);
859 gst_matroska_read_common_postprocess_toc_entries
860 (gst_toc_entry_get_sub_entries (cur_info), max,
861 gst_toc_entry_get_uid (cur_info));
864 case GST_TOC_ENTRY_TYPE_TITLE:
865 case GST_TOC_ENTRY_TYPE_TRACK:
866 case GST_TOC_ENTRY_TYPE_CHAPTER:
867 prev_list = cur_list->prev;
868 next_list = cur_list->next;
870 if (prev_list != NULL)
871 prev_info = prev_list->data;
875 if (next_list != NULL)
876 next_info = next_list->data;
880 /* updated stop time in previous chapter and it's subchapters */
881 if (prev_info != NULL) {
882 gst_toc_entry_get_start_stop_times (prev_info, &prev_start, &stop);
883 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
886 gst_toc_entry_set_start_stop_times (prev_info, prev_start, stop);
888 gst_matroska_read_common_postprocess_toc_entries
889 (gst_toc_entry_get_sub_entries (prev_info), cur_start,
890 gst_toc_entry_get_uid (prev_info));
893 /* updated stop time in current chapter and it's subchapters */
894 if (next_info == NULL) {
895 gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
899 gst_toc_entry_set_start_stop_times (cur_info, cur_start, stop);
902 gst_matroska_read_common_postprocess_toc_entries
903 (gst_toc_entry_get_sub_entries (cur_info), stop,
904 gst_toc_entry_get_uid (cur_info));
907 case GST_TOC_ENTRY_TYPE_INVALID:
910 cur_list = cur_list->next;
915 gst_matroska_read_common_parse_chapter_titles (GstMatroskaReadCommon * common,
916 GstEbmlRead * ebml, GstTagList * titles)
920 GstFlowReturn ret = GST_FLOW_OK;
922 DEBUG_ELEMENT_START (common, ebml, "ChaptersTitles");
925 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
926 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
930 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
931 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
935 case GST_MATROSKA_ID_CHAPSTRING:
936 ret = gst_ebml_read_utf8 (ebml, &id, &title);
941 gst_matroska_read_common_parse_skip (common, ebml, "ChaptersTitles",
947 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
949 if (title != NULL && ret == GST_FLOW_OK)
950 gst_tag_list_add (titles, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title, NULL);
957 gst_matroska_read_common_parse_chapter_element (GstMatroskaReadCommon * common,
958 GstEbmlRead * ebml, GList ** subentries)
961 guint64 start_time = -1, stop_time = -1;
962 guint64 is_hidden = 0, is_enabled = 1, uid = 0;
963 GstFlowReturn ret = GST_FLOW_OK;
964 GstTocEntry *chapter_info;
967 GList *subsubentries = NULL, *l;
969 DEBUG_ELEMENT_START (common, ebml, "ChaptersElement");
971 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
972 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
976 tags = gst_tag_list_new_empty ();
978 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
979 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
983 case GST_MATROSKA_ID_CHAPTERUID:
984 ret = gst_ebml_read_uint (ebml, &id, &uid);
987 case GST_MATROSKA_ID_CHAPTERTIMESTART:
988 ret = gst_ebml_read_uint (ebml, &id, &start_time);
991 case GST_MATROSKA_ID_CHAPTERTIMESTOP:
992 ret = gst_ebml_read_uint (ebml, &id, &stop_time);
995 case GST_MATROSKA_ID_CHAPTERATOM:
997 gst_matroska_read_common_parse_chapter_element (common, ebml,
1001 case GST_MATROSKA_ID_CHAPTERDISPLAY:
1003 gst_matroska_read_common_parse_chapter_titles (common, ebml, tags);
1006 case GST_MATROSKA_ID_CHAPTERFLAGHIDDEN:
1007 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1010 case GST_MATROSKA_ID_CHAPTERFLAGENABLED:
1011 ret = gst_ebml_read_uint (ebml, &id, &is_enabled);
1016 gst_matroska_read_common_parse_skip (common, ebml,
1017 "ChaptersElement", id);
1023 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1024 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1025 chapter_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid_str);
1028 gst_toc_entry_set_tags (chapter_info, tags);
1029 gst_toc_entry_set_start_stop_times (chapter_info, start_time, stop_time);
1031 for (l = subsubentries; l; l = l->next)
1032 gst_toc_entry_append_sub_entry (chapter_info, l->data);
1033 g_list_free (subsubentries);
1035 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
1037 /* start time is mandatory and has no default value,
1038 * so we should skip chapters without it */
1039 if (is_hidden == 0 && is_enabled > 0 &&
1040 start_time != -1 && ret == GST_FLOW_OK) {
1041 *subentries = g_list_append (*subentries, chapter_info);
1043 gst_toc_entry_unref (chapter_info);
1048 static GstFlowReturn
1049 gst_matroska_read_common_parse_chapter_edition (GstMatroskaReadCommon * common,
1050 GstEbmlRead * ebml, GstToc * toc)
1053 guint64 is_hidden = 0, uid = 0;
1054 GstFlowReturn ret = GST_FLOW_OK;
1055 GstTocEntry *edition_info;
1056 GList *subentries = NULL, *l;
1059 DEBUG_ELEMENT_START (common, ebml, "ChaptersEdition");
1061 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1062 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1066 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1067 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1071 case GST_MATROSKA_ID_EDITIONUID:
1072 ret = gst_ebml_read_uint (ebml, &id, &uid);
1075 case GST_MATROSKA_ID_CHAPTERATOM:
1077 gst_matroska_read_common_parse_chapter_element (common, ebml,
1081 case GST_MATROSKA_ID_EDITIONFLAGHIDDEN:
1082 ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1087 gst_matroska_read_common_parse_skip (common, ebml,
1088 "ChaptersEdition", id);
1093 DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1096 uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1097 uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1098 edition_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, uid_str);
1099 gst_toc_entry_set_start_stop_times (edition_info, -1, -1);
1102 for (l = subentries; l; l = l->next)
1103 gst_toc_entry_append_sub_entry (edition_info, l->data);
1105 if (is_hidden == 0 && subentries != NULL && ret == GST_FLOW_OK)
1106 gst_toc_append_entry (toc, edition_info);
1108 GST_DEBUG_OBJECT (common,
1109 "Skipping empty or hidden edition in the chapters TOC");
1110 gst_toc_entry_unref (edition_info);
1117 gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common,
1121 GstFlowReturn ret = GST_FLOW_OK;
1124 DEBUG_ELEMENT_START (common, ebml, "Chapters");
1126 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1127 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1131 /* FIXME: create CURRENT toc as well */
1132 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1134 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1135 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1139 case GST_MATROSKA_ID_EDITIONENTRY:
1141 gst_matroska_read_common_parse_chapter_edition (common, ebml, toc);
1146 gst_matroska_read_common_parse_skip (common, ebml, "Chapters", id);
1151 if (gst_toc_get_entries (toc) != NULL) {
1152 gst_matroska_read_common_postprocess_toc_entries (gst_toc_get_entries (toc),
1153 common->segment.duration, "");
1157 gst_toc_unref (toc);
1159 common->chapters_parsed = TRUE;
1161 DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1166 gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
1174 /* this function is the first to be called */
1180 ret = gst_ebml_peek_id (ebml, &id);
1181 if (ret != GST_FLOW_OK)
1184 GST_DEBUG_OBJECT (common, "id: %08x", id);
1186 if (id != GST_EBML_ID_HEADER) {
1187 GST_ERROR_OBJECT (common, "Failed to read header");
1191 ret = gst_ebml_read_master (ebml, &id);
1192 if (ret != GST_FLOW_OK)
1195 while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1196 ret = gst_ebml_peek_id (ebml, &id);
1197 if (ret != GST_FLOW_OK)
1201 /* is our read version uptodate? */
1202 case GST_EBML_ID_EBMLREADVERSION:{
1205 ret = gst_ebml_read_uint (ebml, &id, &num);
1206 if (ret != GST_FLOW_OK)
1208 if (num != GST_EBML_VERSION) {
1209 GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
1211 return GST_FLOW_ERROR;
1214 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1218 /* we only handle 8 byte lengths at max */
1219 case GST_EBML_ID_EBMLMAXSIZELENGTH:{
1222 ret = gst_ebml_read_uint (ebml, &id, &num);
1223 if (ret != GST_FLOW_OK)
1225 if (num > sizeof (guint64)) {
1226 GST_ERROR_OBJECT (ebml,
1227 "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
1228 return GST_FLOW_ERROR;
1230 GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
1234 /* we handle 4 byte IDs at max */
1235 case GST_EBML_ID_EBMLMAXIDLENGTH:{
1238 ret = gst_ebml_read_uint (ebml, &id, &num);
1239 if (ret != GST_FLOW_OK)
1241 if (num > sizeof (guint32)) {
1242 GST_ERROR_OBJECT (ebml,
1243 "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
1244 return GST_FLOW_ERROR;
1246 GST_DEBUG_OBJECT (ebml, "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 (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
1265 case GST_EBML_ID_DOCTYPEREADVERSION:{
1268 ret = gst_ebml_read_uint (ebml, &id, &num);
1269 if (ret != GST_FLOW_OK)
1272 GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1277 ret = gst_matroska_read_common_parse_skip (common, ebml,
1279 if (ret != GST_FLOW_OK)
1283 /* we ignore these two, as they don't tell us anything we care about */
1284 case GST_EBML_ID_EBMLVERSION:
1285 case GST_EBML_ID_DOCTYPEVERSION:
1286 ret = gst_ebml_read_skip (ebml);
1287 if (ret != GST_FLOW_OK)
1295 if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
1296 (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
1297 (doctype == NULL)) {
1300 GST_INFO_OBJECT (common, "Input is %s version %d", doctype, version);
1302 GST_WARNING_OBJECT (common, "Input is EBML without doctype, assuming "
1303 "matroska (version %d)", version);
1307 GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
1308 ("Demuxer version (2) is too old to read %s version %d",
1309 GST_STR_NULL (doctype), version));
1310 ret = GST_FLOW_ERROR;
1314 GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
1315 ("Input is not a matroska stream (doctype=%s)", doctype));
1316 ret = GST_FLOW_ERROR;
1323 static GstFlowReturn
1324 gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
1325 GstEbmlRead * ebml, guint * nentries)
1329 GstMatroskaIndex idx;
1331 idx.pos = (guint64) - 1;
1333 idx.time = GST_CLOCK_TIME_NONE;
1336 DEBUG_ELEMENT_START (common, ebml, "CueTrackPositions");
1338 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1339 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1343 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1344 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1349 case GST_MATROSKA_ID_CUETRACK:
1353 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1358 GST_WARNING_OBJECT (common, "Invalid CueTrack 0");
1362 GST_DEBUG_OBJECT (common, "CueTrack: %" G_GUINT64_FORMAT, num);
1367 /* position in file */
1368 case GST_MATROSKA_ID_CUECLUSTERPOSITION:
1372 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1375 if (num > G_MAXINT64) {
1376 GST_WARNING_OBJECT (common, "CueClusterPosition %" G_GUINT64_FORMAT
1385 /* number of block in the cluster */
1386 case GST_MATROSKA_ID_CUEBLOCKNUMBER:
1390 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1394 GST_WARNING_OBJECT (common, "Invalid CueBlockNumber 0");
1398 GST_DEBUG_OBJECT (common, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
1401 /* mild sanity check, disregard strange cases ... */
1402 if (idx.block > G_MAXUINT16) {
1403 GST_DEBUG_OBJECT (common, "... looks suspicious, ignoring");
1410 ret = gst_matroska_read_common_parse_skip (common, ebml,
1411 "CueTrackPositions", id);
1414 case GST_MATROSKA_ID_CUECODECSTATE:
1415 case GST_MATROSKA_ID_CUEREFERENCE:
1416 ret = gst_ebml_read_skip (ebml);
1421 DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1423 /* (e.g.) lavf typically creates entries without a block number,
1424 * which is bogus and leads to contradictory information */
1425 if (common->index->len) {
1426 GstMatroskaIndex *last_idx;
1428 last_idx = &g_array_index (common->index, GstMatroskaIndex,
1429 common->index->len - 1);
1430 if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
1431 last_idx->track == idx.track && idx.time > last_idx->time) {
1432 GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
1433 "but has different time than previous entry; discarding");
1438 if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
1439 && idx.pos != (guint64) - 1 && idx.track > 0) {
1440 g_array_append_val (common->index, idx);
1442 } else if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) {
1443 GST_DEBUG_OBJECT (common, "CueTrackPositions without valid content");
1449 static GstFlowReturn
1450 gst_matroska_read_common_parse_index_pointentry (GstMatroskaReadCommon *
1451 common, GstEbmlRead * ebml)
1455 GstClockTime time = GST_CLOCK_TIME_NONE;
1458 DEBUG_ELEMENT_START (common, ebml, "CuePoint");
1460 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1461 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1465 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1466 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1470 /* one single index entry ('point') */
1471 case GST_MATROSKA_ID_CUETIME:
1473 if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
1476 GST_DEBUG_OBJECT (common, "CueTime: %" G_GUINT64_FORMAT, time);
1477 time = time * common->time_scale;
1481 /* position in the file + track to which it belongs */
1482 case GST_MATROSKA_ID_CUETRACKPOSITIONS:
1485 gst_matroska_read_common_parse_index_cuetrack (common, ebml,
1486 &nentries)) != GST_FLOW_OK)
1492 ret = gst_matroska_read_common_parse_skip (common, ebml, "CuePoint",
1498 DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1501 if (time == GST_CLOCK_TIME_NONE) {
1502 GST_WARNING_OBJECT (common, "CuePoint without valid time");
1503 g_array_remove_range (common->index, common->index->len - nentries,
1508 for (i = common->index->len - nentries; i < common->index->len; i++) {
1509 GstMatroskaIndex *idx =
1510 &g_array_index (common->index, GstMatroskaIndex, i);
1513 GST_DEBUG_OBJECT (common, "Index entry: pos=%" G_GUINT64_FORMAT
1514 ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
1515 GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
1519 GST_DEBUG_OBJECT (common, "Empty CuePoint");
1526 gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
1531 g_assert (common->src->len == common->num_streams);
1532 for (n = 0; n < common->src->len; n++) {
1533 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, n);
1535 if (context->num == track_num) {
1540 if (n == common->num_streams)
1541 GST_WARNING_OBJECT (common,
1542 "Failed to find corresponding pad for tracknum %d", track_num);
1548 gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
1552 GstFlowReturn ret = GST_FLOW_OK;
1556 g_array_free (common->index, TRUE);
1558 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1560 DEBUG_ELEMENT_START (common, ebml, "Cues");
1562 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1563 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1567 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1568 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1572 /* one single index entry ('point') */
1573 case GST_MATROSKA_ID_POINTENTRY:
1574 ret = gst_matroska_read_common_parse_index_pointentry (common, ebml);
1578 ret = gst_matroska_read_common_parse_skip (common, ebml, "Cues", id);
1582 DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1584 /* Sort index by time, smallest time first, for easier searching */
1585 g_array_sort (common->index, (GCompareFunc) gst_matroska_index_compare);
1587 /* Now sort the track specific index entries into their own arrays */
1588 for (i = 0; i < common->index->len; i++) {
1589 GstMatroskaIndex *idx = &g_array_index (common->index, GstMatroskaIndex,
1592 GstMatroskaTrackContext *ctx;
1595 if (common->element_index) {
1598 if (idx->track != 0 &&
1600 gst_matroska_read_common_stream_from_num (common,
1601 idx->track)) != -1) {
1602 ctx = g_ptr_array_index (common->src, track_num);
1604 if (ctx->index_writer_id == -1)
1605 gst_index_get_writer_id (common->element_index,
1606 GST_OBJECT (ctx->pad), &ctx->index_writer_id);
1607 writer_id = ctx->index_writer_id;
1609 if (common->element_index_writer_id == -1)
1610 gst_index_get_writer_id (common->element_index, GST_OBJECT (common),
1611 &common->element_index_writer_id);
1612 writer_id = common->element_index_writer_id;
1615 GST_LOG_OBJECT (common, "adding association %" GST_TIME_FORMAT "-> %"
1616 G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
1617 idx->pos, writer_id);
1618 gst_index_add_association (common->element_index, writer_id,
1619 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
1620 GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
1624 if (idx->track == 0)
1627 track_num = gst_matroska_read_common_stream_from_num (common, idx->track);
1628 if (track_num == -1)
1631 ctx = g_ptr_array_index (common->src, track_num);
1633 if (ctx->index_table == NULL)
1635 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1637 g_array_append_vals (ctx->index_table, idx, 1);
1640 common->index_parsed = TRUE;
1642 /* sanity check; empty index normalizes to no index */
1643 if (common->index->len == 0) {
1644 g_array_free (common->index, TRUE);
1645 common->index = NULL;
1652 gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
1653 GstElement * el, GstEbmlRead * ebml)
1655 GstFlowReturn ret = GST_FLOW_OK;
1656 gdouble dur_f = -1.0;
1659 DEBUG_ELEMENT_START (common, ebml, "SegmentInfo");
1661 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1662 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1666 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1667 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1671 /* cluster timecode */
1672 case GST_MATROSKA_ID_TIMECODESCALE:{
1675 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1679 GST_DEBUG_OBJECT (common, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
1680 common->time_scale = num;
1684 case GST_MATROSKA_ID_DURATION:{
1685 if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK)
1689 GST_WARNING_OBJECT (common, "Invalid duration %lf", dur_f);
1693 GST_DEBUG_OBJECT (common, "Duration: %lf", dur_f);
1697 case GST_MATROSKA_ID_WRITINGAPP:{
1700 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1703 GST_DEBUG_OBJECT (common, "WritingApp: %s", GST_STR_NULL (text));
1704 common->writing_app = text;
1708 case GST_MATROSKA_ID_MUXINGAPP:{
1711 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1714 GST_DEBUG_OBJECT (common, "MuxingApp: %s", GST_STR_NULL (text));
1715 common->muxing_app = text;
1719 case GST_MATROSKA_ID_DATEUTC:{
1722 if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
1725 GST_DEBUG_OBJECT (common, "DateUTC: %" G_GINT64_FORMAT, time);
1726 common->created = time;
1730 case GST_MATROSKA_ID_TITLE:{
1732 GstTagList *taglist;
1734 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1737 GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
1738 taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
1739 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
1740 gst_matroska_read_common_found_global_tag (common, el, taglist);
1746 ret = gst_matroska_read_common_parse_skip (common, ebml,
1751 case GST_MATROSKA_ID_SEGMENTUID:
1752 case GST_MATROSKA_ID_SEGMENTFILENAME:
1753 case GST_MATROSKA_ID_PREVUID:
1754 case GST_MATROSKA_ID_PREVFILENAME:
1755 case GST_MATROSKA_ID_NEXTUID:
1756 case GST_MATROSKA_ID_NEXTFILENAME:
1757 case GST_MATROSKA_ID_SEGMENTFAMILY:
1758 case GST_MATROSKA_ID_CHAPTERTRANSLATE:
1759 ret = gst_ebml_read_skip (ebml);
1767 dur_u = gst_gdouble_to_guint64 (dur_f *
1768 gst_guint64_to_gdouble (common->time_scale));
1769 if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
1770 common->segment.duration = dur_u;
1773 DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1775 common->segmentinfo_parsed = TRUE;
1780 static GstFlowReturn
1781 gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
1782 common, GstEbmlRead * ebml, GstTagList ** p_taglist, gchar * parent)
1784 /* FIXME: check if there are more useful mappings */
1787 const gchar *matroska_tagname;
1788 const gchar *gstreamer_tagname;
1792 /* The following list has the _same_ order as the one in Matroska spec. Please, don't mess it up. */
1793 /* TODO: Nesting information:
1794 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.
1795 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.
1796 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.
1799 /* Organizational Information */
1800 GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
1801 GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}, {
1802 /* 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) */
1805 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. */
1806 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
1807 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1809 /* TODO: Nested Information:
1810 URL URL corresponding to the tag it's included in.
1811 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).
1812 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.
1813 EMAIL Email corresponding to the tag it's included in.
1814 ADDRESS The physical address of the entity. The address should include a country code. It can be useful for a recording label.
1815 FAX The fax number corresponding to the tag it's included in. It can be useful for a recording label.
1816 PHONE The phone number corresponding to the tag it's included in. It can be useful for a recording label.
1820 GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
1821 GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
1822 GST_MATROSKA_TAG_ID_ACCOMPANIMENT, GST_TAG_PERFORMER}, { /* Band/orchestra/accompaniment/musician. This is akin to the TPE2 tag in ID3. */
1823 GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
1824 /* ARRANGER The person who arranged the piece, e.g., Ravel. */
1825 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. */
1826 /* LYRICIST The person who wrote the lyrics for a musical item. This is akin to the TEXT tag in ID3. */
1827 GST_MATROSKA_TAG_ID_CONDUCTOR, GST_TAG_PERFORMER}, { /* Conductor/performer refinement. This is akin to the TPE3 tag in ID3. */
1828 /* DIRECTOR This is akin to the IART tag in RIFF. */
1829 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
1830 /* ASSISTANT_DIRECTOR The name of the assistant director. */
1831 /* DIRECTOR_OF_PHOTOGRAPHY The name of the director of photography, also known as cinematographer. This is akin to the ICNM tag in Extended RIFF. */
1832 /* SOUND_ENGINEER The name of the sound engineer or sound recordist. */
1833 /* ART_DIRECTOR The person who oversees the artists and craftspeople who build the sets. */
1834 /* PRODUCTION_DESIGNER Artist responsible for designing the overall visual appearance of a movie. */
1835 /* CHOREGRAPHER The name of the choregrapher */
1836 /* COSTUME_DESIGNER The name of the costume designer */
1837 /* 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. */
1838 /* 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. */
1839 /* WRITTEN_BY The author of the story or script (used for movies and TV shows). */
1840 /* SCREENPLAY_BY The author of the screenplay or scenario (used for movies and TV shows). */
1841 /* EDITED_BY This is akin to the IEDT tag in Extended RIFF. */
1842 /* PRODUCER Produced by. This is akin to the IPRO tag in Extended RIFF. */
1843 /* COPRODUCER The name of a co-producer. */
1844 /* EXECUTIVE_PRODUCER The name of an executive producer. */
1845 /* DISTRIBUTED_BY This is akin to the IDST tag in Extended RIFF. */
1846 /* MASTERED_BY The engineer who mastered the content for a physical medium or for digital distribution. */
1847 GST_MATROSKA_TAG_ID_ENCODED_BY, GST_TAG_ENCODED_BY}, { /* This is akin to the TENC tag in ID3. */
1848 /* MIXED_BY DJ mix by the artist specified */
1849 /* REMIXED_BY Interpreted, remixed, or otherwise modified by. This is akin to the TPE4 tag in ID3. */
1850 /* PRODUCTION_STUDIO This is akin to the ISTD tag in Extended RIFF. */
1851 /* THANKS_TO A very general tag for everyone else that wants to be listed. */
1852 /* PUBLISHER This is akin to the TPUB tag in ID3. */
1853 /* LABEL The record label or imprint on the disc. */
1854 /* Search / Classification */
1855 GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
1856 /* 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. */
1857 /* 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. */
1858 /* CONTENT_TYPE The type of the item. e.g. Documentary, Feature Film, Cartoon, Music Video, Music, Sound FX, ... */
1859 /* SUBJECT Describes the topic of the file, such as "Aerial view of Seattle." */
1860 GST_MATROSKA_TAG_ID_DESCRIPTION, GST_TAG_DESCRIPTION}, { /* A short description of the content, such as "Two birds flying." */
1861 GST_MATROSKA_TAG_ID_KEYWORDS, GST_TAG_KEYWORDS}, { /* Keywords to the item separated by a comma, used for searching. */
1862 /* SUMMARY A plot outline or a summary of the story. */
1863 /* SYNOPSIS A description of the story line of the item. */
1864 /* INITIAL_KEY The initial key that a musical track starts in. The format is identical to ID3. */
1865 /* PERIOD Describes the period that the piece is from or about. For example, "Renaissance". */
1866 /* 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). */
1867 /* ICRA The ICRA content rating for parental control. (Previously RSACi) */
1869 /* Temporal Information */
1870 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. */
1871 GST_MATROSKA_TAG_ID_DATE_RECORDED, GST_TAG_DATE}, { /* The time that the recording began. This is akin to the TDRC tag in ID3. */
1872 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. */
1873 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. */
1874 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. */
1875 GST_MATROSKA_TAG_ID_DATE_WRITTEN, GST_TAG_DATE}, { /* The time that the writing of the music/script began. */
1876 GST_MATROSKA_TAG_ID_DATE_PURCHASED, GST_TAG_DATE}, { /* Information on when the file was purchased (see also purchase tags). */
1877 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1879 /* Spacial Information */
1880 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". */
1881 /* 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". */
1882 /* 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. */
1885 GST_MATROSKA_TAG_ID_COMMENT, GST_TAG_COMMENT}, { /* Any comment related to the content. */
1886 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1887 /* PLAY_COUNTER The number of time the item has been played. */
1888 /* 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. */
1890 /* Technical Information */
1891 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
1892 /* ENCODER_SETTINGS A list of the settings used for encoding this item. No specific format. */
1893 GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
1894 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1895 /* 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. */
1896 GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
1897 /* 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. */
1898 /* 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. */
1899 /* 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). */
1900 /* TODO: REPLAYGAIN_PEAK The maximum absolute peak value of the item. This is based on the Replay Gain standard. */
1903 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
1904 /* 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. */
1905 /* ISBN International Standard Book Number */
1906 /* BARCODE EAN-13 (European Article Numbering) or UPC-A (Universal Product Code) bar code identifier */
1907 /* CATALOG_NUMBER A label-specific string used to identify the release (TIC 01 for example). */
1908 /* 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). */
1909 /* LCCN Library of Congress Control Number */
1912 /* PURCHASE_ITEM URL to purchase this file. This is akin to the WPAY tag in ID3. */
1913 /* PURCHASE_INFO Information on where to purchase this album. This is akin to the WCOM tag in ID3. */
1914 /* PURCHASE_OWNER Information on the person who purchased the file. This is akin to the TOWN tag in ID3. */
1915 /* 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". */
1916 /* PURCHASE_CURRENCY The currency type used to pay for the entity. Use ISO-4217 for the 3 letter currency code. */
1919 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
1920 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. */
1921 GST_MATROSKA_TAG_ID_LICENSE, GST_TAG_LICENSE}, { /* The license applied to the content (like Creative Commons variants). */
1922 GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}
1926 const gchar *matroska_tagname;
1927 const gchar *gstreamer_tagname;
1929 child_tag_conv[] = {
1931 "TITLE/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1932 "ARTIST/SORT_WITH=", GST_TAG_ARTIST_SORTNAME}, {
1933 /* ALBUM-stuff is handled elsewhere */
1934 "COMPOSER/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1935 "ORIGINAL/URL=", GST_TAG_LOCATION}, {
1936 /* EMAIL, PHONE, FAX all can be mapped to GST_TAG_CONTACT, there is special
1937 * code for that later.
1939 "TITLE/URL=", GST_TAG_HOMEPAGE}, {
1940 "ARTIST/URL=", GST_TAG_HOMEPAGE}, {
1941 "COPYRIGHT/URL=", GST_TAG_COPYRIGHT_URI}, {
1942 "LICENSE/URL=", GST_TAG_LICENSE_URI}, {
1943 "LICENSE/URL=", GST_TAG_LICENSE_URI}
1947 gchar *value = NULL;
1949 gchar *name_with_parent = NULL;
1950 GstTagList *child_taglist = NULL;
1952 DEBUG_ELEMENT_START (common, ebml, "SimpleTag");
1954 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1955 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
1960 child_taglist = *p_taglist;
1962 child_taglist = gst_tag_list_new_empty ();
1964 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1965 /* read all sub-entries */
1967 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1971 case GST_MATROSKA_ID_TAGNAME:
1974 ret = gst_ebml_read_ascii (ebml, &id, &tag);
1975 GST_DEBUG_OBJECT (common, "TagName: %s", GST_STR_NULL (tag));
1976 g_free (name_with_parent);
1978 name_with_parent = g_strdup_printf ("%s/%s", parent, tag);
1980 name_with_parent = g_strdup (tag);
1983 case GST_MATROSKA_ID_TAGSTRING:
1986 ret = gst_ebml_read_utf8 (ebml, &id, &value);
1987 GST_DEBUG_OBJECT (common, "TagString: %s", GST_STR_NULL (value));
1990 case GST_MATROSKA_ID_SIMPLETAG:
1991 /* Recursive SimpleTag */
1992 /* This implementation requires tag name of _this_ tag to be known
1993 * in order to read its children. It's not in the spec, just the way
1994 * the code is written.
1996 if (name_with_parent != NULL) {
1997 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
1998 ebml, &child_taglist, name_with_parent);
2004 ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag",
2008 case GST_MATROSKA_ID_TAGLANGUAGE:
2009 case GST_MATROSKA_ID_TAGDEFAULT:
2010 case GST_MATROSKA_ID_TAGBINARY:
2011 ret = gst_ebml_read_skip (ebml);
2016 DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
2018 if (parent && tag && value && *value != '\0') {
2019 /* Don't bother mapping children tags - parent will do that */
2021 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2022 key_val = g_strdup_printf ("%s=%s", name_with_parent, value);
2023 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2024 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2025 } else if (tag && value && *value != '\0') {
2026 gboolean matched = FALSE;
2029 for (i = 0; !matched && i < G_N_ELEMENTS (tag_conv); i++) {
2030 const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2032 const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2034 if (strcmp (tagname_mkv, tag) == 0) {
2035 GValue dest = { 0, };
2036 GType dest_type = gst_tag_get_type (tagname_gst);
2038 /* Ensure that any date string is complete */
2039 if (dest_type == G_TYPE_DATE) {
2040 guint year = 1901, month = 1, day = 1;
2042 /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
2044 if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
2046 value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
2050 g_value_init (&dest, dest_type);
2051 if (gst_value_deserialize (&dest, value)) {
2052 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2053 tagname_gst, &dest, NULL);
2055 GST_WARNING_OBJECT (common, "Can't transform tag '%s' with "
2056 "value '%s' to target type '%s'", tag, value,
2057 g_type_name (dest_type));
2059 g_value_unset (&dest);
2065 /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2066 key_val = g_strdup_printf ("%s=%s", tag, value);
2067 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2068 GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2073 /* Map children tags. This only supports top-anchored mapping. That is,
2074 * we start at toplevel tag (this tag), and see how its combinations
2075 * with its children can be mapped. Which means that grandchildren
2076 * are also combined here, with _this_ tag taken into consideration.
2077 * If grandchildren can be combined only with children, that combination
2080 gint child_tags_n = gst_tag_list_n_tags (child_taglist);
2081 if (child_tags_n > 0) {
2083 for (i = 0; i < child_tags_n; i++) {
2085 const gchar *child_name = gst_tag_list_nth_tag_name (child_taglist, i);
2086 guint taglen = gst_tag_list_get_tag_size (child_taglist, child_name);
2087 for (j = 0; j < taglen; j++) {
2089 gboolean matched = FALSE;
2090 gchar *val_pre, *val_post;
2093 if (!gst_tag_list_get_string_index (child_taglist, child_name,
2096 if (!strchr (val, '=')) {
2100 val_post = g_strdup (strchr (val, '=') + 1);
2101 val_pre = g_strdup (val);
2102 *(strchr (val_pre, '=') + 1) = '\0';
2104 for (k = 0; !matched && k < G_N_ELEMENTS (child_tag_conv); k++) {
2105 const gchar *tagname_gst = child_tag_conv[k].gstreamer_tagname;
2107 const gchar *tagname_mkv = child_tag_conv[k].matroska_tagname;
2109 /* TODO: Once "key[lc]=value" form support is implemented,
2110 * strip [lc] here. It can't be used in combined tags.
2111 * If a tag is not combined, leave [lc] as it is.
2113 if (strcmp (tagname_mkv, val_pre) == 0) {
2114 GValue dest = { 0, };
2115 GType dest_type = gst_tag_get_type (tagname_gst);
2117 g_value_init (&dest, dest_type);
2118 if (gst_value_deserialize (&dest, val_post)) {
2119 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2120 tagname_gst, &dest, NULL);
2122 GST_WARNING_OBJECT (common, "Can't transform complex tag '%s' "
2123 "to target type '%s'", val, g_type_name (dest_type));
2125 g_value_unset (&dest);
2130 gchar *last_slash = strrchr (val_pre, '/');
2133 if (strcmp (last_slash, "EMAIL=") == 0 ||
2134 strcmp (last_slash, "PHONE=") == 0 ||
2135 strcmp (last_slash, "ADDRESS=") == 0 ||
2136 strcmp (last_slash, "FAX=") == 0) {
2137 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2138 GST_TAG_CONTACT, val_post, NULL);
2144 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2145 GST_TAG_EXTENDED_COMMENT, val, NULL);
2152 gst_tag_list_unref (child_taglist);
2157 g_free (name_with_parent);
2164 gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
2165 gint * a, gint * v, gint * s)
2168 gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
2170 for (i = 0; i < common->src->len; i++) {
2171 GstMatroskaTrackContext *stream;
2173 stream = g_ptr_array_index (common->src, i);
2174 if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
2176 else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
2178 else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
2179 subtitle_streams += 1;
2183 *v = subtitle_streams;
2188 gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
2189 const gchar * tag, gpointer user_data)
2193 TargetTypeContext *ctx = (TargetTypeContext *) user_data;
2195 vallen = gst_tag_list_get_tag_size (list, tag);
2199 for (i = 0; i < vallen; i++) {
2201 const GValue *val_ref;
2203 val_ref = gst_tag_list_get_value_index (list, tag, i);
2204 if (val_ref == NULL)
2206 g_value_init (&val, G_VALUE_TYPE (val_ref));
2207 g_value_copy (val_ref, &val);
2209 /* TODO: use the optional ctx->target_type somehow */
2210 if (strcmp (tag, GST_TAG_TITLE) == 0) {
2211 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2212 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2213 GST_TAG_SHOW_NAME, &val);
2215 } else if (ctx->target_type_value >= 50) {
2216 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2217 GST_TAG_ALBUM, &val);
2220 } else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
2221 if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2222 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2223 GST_TAG_SHOW_SORTNAME, &val);
2225 } else if (ctx->target_type_value >= 50) {
2226 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2227 GST_TAG_ALBUM_SORTNAME, &val);
2230 } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
2231 if (ctx->target_type_value >= 50) {
2232 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2233 GST_TAG_ALBUM_ARTIST, &val);
2236 } else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
2237 if (ctx->target_type_value >= 50) {
2238 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2239 GST_TAG_ALBUM_ARTIST_SORTNAME, &val);
2242 } else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
2243 if (ctx->target_type_value >= 60) {
2244 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2245 GST_TAG_ALBUM_VOLUME_COUNT, &val);
2248 } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
2249 if (ctx->target_type_value >= 60 && !ctx->audio_only) {
2250 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2251 GST_TAG_SHOW_SEASON_NUMBER, &val);
2253 } else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
2254 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2255 GST_TAG_SHOW_EPISODE_NUMBER, &val);
2257 } else if (ctx->target_type_value >= 50) {
2258 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2259 GST_TAG_ALBUM_VOLUME_NUMBER, &val);
2263 gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, &val);
2264 g_value_unset (&val);
2270 gst_matroska_read_common_apply_target_type (GstMatroskaReadCommon * common,
2271 GstTagList * taglist, guint64 target_type_value, gchar * target_type)
2273 TargetTypeContext ctx;
2278 gst_matroska_read_common_count_streams (common, &a, &v, &s);
2280 ctx.audio_only = (a > 0 && v == 0 && s == 0);
2281 ctx.result = gst_tag_list_new_empty ();
2282 ctx.target_type_value = target_type_value;
2283 ctx.target_type = target_type;
2285 gst_tag_list_foreach (taglist,
2286 gst_matroska_read_common_apply_target_type_foreach, &ctx);
2288 gst_tag_list_unref (taglist);
2293 static GstFlowReturn
2294 gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
2295 GstEbmlRead * ebml, GstTagList ** p_taglist)
2299 GArray *chapter_targets, *edition_targets, *track_targets;
2300 GstTagList *taglist;
2302 guint64 target_type_value = 50;
2303 gchar *target_type = NULL;
2305 DEBUG_ELEMENT_START (common, ebml, "Tag");
2307 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2308 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2312 edition_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2313 chapter_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2314 track_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2315 taglist = gst_tag_list_new_empty ();
2318 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2319 /* read all sub-entries */
2321 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2325 case GST_MATROSKA_ID_SIMPLETAG:
2326 ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2327 ebml, &taglist, NULL);
2330 case GST_MATROSKA_ID_TARGETS:
2331 g_free (target_type);
2333 target_type_value = 50;
2334 ret = gst_matroska_read_common_parse_metadata_targets (common, ebml,
2335 edition_targets, chapter_targets, track_targets,
2336 &target_type_value, &target_type);
2340 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tag", id);
2345 DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2347 taglist = gst_matroska_read_common_apply_target_type (common, taglist,
2348 target_type_value, target_type);
2349 g_free (target_type);
2351 /* if tag is chapter/edition specific - try to find that entry */
2352 if (G_UNLIKELY (chapter_targets->len > 0 || edition_targets->len > 0 ||
2353 track_targets->len > 0)) {
2355 if (chapter_targets->len > 0 || edition_targets->len > 0) {
2356 if (common->toc == NULL)
2357 GST_WARNING_OBJECT (common,
2358 "Found chapter/edition specific tag, but TOC is not present");
2360 cur = gst_toc_get_entries (common->toc);
2361 while (cur != NULL) {
2362 gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
2363 chapter_targets, taglist);
2366 common->toc_updated = TRUE;
2369 for (i = 0; i < track_targets->len; i++) {
2371 gboolean found = FALSE;
2372 guint64 tgt = g_array_index (track_targets, guint64, i);
2374 for (j = 0; j < common->src->len; j++) {
2375 GstMatroskaTrackContext *stream = g_ptr_array_index (common->src, j);
2377 if (stream->uid == tgt) {
2378 gst_tag_list_insert (stream->pending_tags, taglist,
2379 GST_TAG_MERGE_REPLACE);
2384 GST_WARNING_OBJECT (common,
2385 "Found track-specific tag(s), but track %" G_GUINT64_FORMAT
2386 " is not known (yet?)", tgt);
2390 gst_tag_list_insert (*p_taglist, taglist, GST_TAG_MERGE_APPEND);
2392 gst_tag_list_unref (taglist);
2393 g_array_unref (chapter_targets);
2394 g_array_unref (edition_targets);
2395 g_array_unref (track_targets);
2401 gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
2402 GstElement * el, GstEbmlRead * ebml)
2404 GstTagList *taglist;
2405 GstFlowReturn ret = GST_FLOW_OK;
2410 curpos = gst_ebml_read_get_pos (ebml);
2412 /* Make sure we don't parse a tags element twice and
2413 * post it's tags twice */
2414 curpos = gst_ebml_read_get_pos (ebml);
2415 for (l = common->tags_parsed; l; l = l->next) {
2416 guint64 *pos = l->data;
2418 if (*pos == curpos) {
2419 GST_DEBUG_OBJECT (common, "Skipping already parsed Tags at offset %"
2420 G_GUINT64_FORMAT, curpos);
2425 common->tags_parsed =
2426 g_list_prepend (common->tags_parsed, g_slice_new (guint64));
2427 *((guint64 *) common->tags_parsed->data) = curpos;
2430 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2431 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2435 taglist = gst_tag_list_new_empty ();
2436 gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
2437 common->toc_updated = FALSE;
2439 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2440 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2444 case GST_MATROSKA_ID_TAG:
2445 ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml,
2450 ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id);
2452 /* FIXME: Use to limit the tags to specific pads */
2456 DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2458 if (G_LIKELY (!gst_tag_list_is_empty (taglist)))
2459 gst_matroska_read_common_found_global_tag (common, el, taglist);
2461 gst_tag_list_unref (taglist);
2466 static GstFlowReturn
2467 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
2468 peek, const guint8 ** data)
2470 /* Caller needs to gst_adapter_unmap. */
2471 *data = gst_adapter_map (common->adapter, peek);
2473 return GST_FLOW_EOS;
2479 * Calls pull_range for (offset,size) without advancing our offset
2482 gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
2483 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
2487 /* Caching here actually makes much less difference than one would expect.
2488 * We do it mainly to avoid pulling buffers of 1 byte all the time */
2489 if (common->cached_buffer) {
2490 guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
2491 gsize cache_size = gst_buffer_get_size (common->cached_buffer);
2493 if (cache_offset <= common->offset &&
2494 (common->offset + size) <= (cache_offset + cache_size)) {
2496 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2497 GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
2499 if (!common->cached_data) {
2500 gst_buffer_map (common->cached_buffer, &common->cached_map,
2502 common->cached_data = common->cached_map.data;
2504 *bytes = common->cached_data + common->offset - cache_offset;
2508 /* not enough data in the cache, free cache and get a new one */
2509 if (common->cached_data) {
2510 gst_buffer_unmap (common->cached_buffer, &common->cached_map);
2511 common->cached_data = NULL;
2513 gst_buffer_unref (common->cached_buffer);
2514 common->cached_buffer = NULL;
2517 /* refill the cache */
2518 ret = gst_pad_pull_range (common->sinkpad, common->offset,
2519 MAX (size, 64 * 1024), &common->cached_buffer);
2520 if (ret != GST_FLOW_OK) {
2521 common->cached_buffer = NULL;
2525 if (gst_buffer_get_size (common->cached_buffer) >= size) {
2527 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2528 GST_BUFFER_COPY_ALL, 0, size);
2530 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2531 common->cached_data = common->cached_map.data;
2532 *bytes = common->cached_data;
2537 /* Not possible to get enough data, try a last time with
2538 * requesting exactly the size we need */
2539 gst_buffer_unref (common->cached_buffer);
2540 common->cached_buffer = NULL;
2543 gst_pad_pull_range (common->sinkpad, common->offset, size,
2544 &common->cached_buffer);
2545 if (ret != GST_FLOW_OK) {
2546 GST_DEBUG_OBJECT (common, "pull_range returned %d", ret);
2554 if (gst_buffer_get_size (common->cached_buffer) < size) {
2555 GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
2556 G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2557 common->offset, size, gst_buffer_get_size (common->cached_buffer));
2559 gst_buffer_unref (common->cached_buffer);
2560 common->cached_buffer = NULL;
2565 return GST_FLOW_EOS;
2569 *p_buf = gst_buffer_copy_region (common->cached_buffer,
2570 GST_BUFFER_COPY_ALL, 0, size);
2572 gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2573 common->cached_data = common->cached_map.data;
2574 *bytes = common->cached_data;
2580 static GstFlowReturn
2581 gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek,
2584 return gst_matroska_read_common_peek_bytes (common, common->offset, peek,
2589 gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
2590 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2592 return gst_ebml_peek_id_length (_id, _length, _needed,
2593 (GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
2598 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
2599 GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2603 ret = gst_ebml_peek_id_length (_id, _length, _needed,
2604 (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
2605 el, common->offset);
2607 gst_adapter_unmap (common->adapter);
2612 static GstFlowReturn
2613 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
2614 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2616 GstMatroskaTrackEncoding enc = { 0, };
2620 DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
2621 /* Set default values */
2623 /* All other default values are 0 */
2625 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2626 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2630 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2631 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2635 case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
2638 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2641 if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
2643 GST_ERROR_OBJECT (common, "ContentEncodingOrder %" G_GUINT64_FORMAT
2644 "is not unique for track %" G_GUINT64_FORMAT, num, context->num);
2645 ret = GST_FLOW_ERROR;
2649 GST_DEBUG_OBJECT (common, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
2654 case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
2657 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2660 if (num > 7 && num == 0) {
2661 GST_ERROR_OBJECT (common, "Invalid ContentEncodingScope %"
2662 G_GUINT64_FORMAT, num);
2663 ret = GST_FLOW_ERROR;
2667 GST_DEBUG_OBJECT (common, "ContentEncodingScope: %" G_GUINT64_FORMAT,
2673 case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
2676 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2680 GST_ERROR_OBJECT (common, "Invalid ContentEncodingType %"
2681 G_GUINT64_FORMAT, num);
2682 ret = GST_FLOW_ERROR;
2684 } else if (num != 0) {
2685 GST_ERROR_OBJECT (common, "Encrypted tracks are not supported yet");
2686 ret = GST_FLOW_ERROR;
2689 GST_DEBUG_OBJECT (common, "ContentEncodingType: %" G_GUINT64_FORMAT,
2694 case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
2696 DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
2698 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
2701 while (ret == GST_FLOW_OK &&
2702 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2703 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2707 case GST_MATROSKA_ID_CONTENTCOMPALGO:{
2710 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
2714 GST_ERROR_OBJECT (common, "Invalid ContentCompAlgo %"
2715 G_GUINT64_FORMAT, num);
2716 ret = GST_FLOW_ERROR;
2719 GST_DEBUG_OBJECT (common, "ContentCompAlgo: %" G_GUINT64_FORMAT,
2721 enc.comp_algo = num;
2725 case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
2730 gst_ebml_read_binary (ebml, &id, &data,
2731 &size)) != GST_FLOW_OK) {
2734 enc.comp_settings = data;
2735 enc.comp_settings_length = size;
2736 GST_DEBUG_OBJECT (common,
2737 "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
2741 GST_WARNING_OBJECT (common,
2742 "Unknown ContentCompression subelement 0x%x - ignoring", id);
2743 ret = gst_ebml_read_skip (ebml);
2747 DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
2751 case GST_MATROSKA_ID_CONTENTENCRYPTION:
2752 GST_ERROR_OBJECT (common, "Encrypted tracks not yet supported");
2753 gst_ebml_read_skip (ebml);
2754 ret = GST_FLOW_ERROR;
2757 GST_WARNING_OBJECT (common,
2758 "Unknown ContentEncoding subelement 0x%x - ignoring", id);
2759 ret = gst_ebml_read_skip (ebml);
2764 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2765 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2768 /* TODO: Check if the combination of values is valid */
2770 g_array_append_val (context->encodings, enc);
2776 gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
2777 GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2782 DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
2784 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2785 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2789 context->encodings =
2790 g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
2792 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2793 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2797 case GST_MATROSKA_ID_CONTENTENCODING:
2798 ret = gst_matroska_read_common_read_track_encoding (common, ebml,
2802 GST_WARNING_OBJECT (common,
2803 "Unknown ContentEncodings subelement 0x%x - ignoring", id);
2804 ret = gst_ebml_read_skip (ebml);
2809 DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2810 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2813 /* Sort encodings according to their order */
2814 g_array_sort (context->encodings,
2815 (GCompareFunc) gst_matroska_read_common_encoding_cmp);
2817 return gst_matroska_decode_content_encodings (context->encodings);
2820 /* call with object lock held */
2822 gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
2823 GstClockTime time, gboolean full)
2827 GST_DEBUG_OBJECT (common, "resetting stream state");
2829 g_assert (common->src->len == common->num_streams);
2830 for (i = 0; i < common->src->len; i++) {
2831 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2832 context->pos = time;
2833 context->set_discont = TRUE;
2834 context->eos = FALSE;
2835 context->from_time = GST_CLOCK_TIME_NONE;
2837 context->last_flow = GST_FLOW_OK;
2838 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2839 GstMatroskaTrackVideoContext *videocontext =
2840 (GstMatroskaTrackVideoContext *) context;
2841 /* demux object lock held by caller */
2842 videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2848 gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
2853 g_assert (common->src->len == common->num_streams);
2854 for (i = 0; i < common->src->len; i++) {
2855 GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2857 if (context->num == num)