2 * ISO File Format parsing library
6 * Copyright (C) 2015 Samsung Electronics. All rights reserved.
7 * Author: Thiago Santos <thiagoss@osg.samsung.com>
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.1 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 (COPYING); if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 #include <gst/base/gstbytereader.h>
29 gst_isoff_qt_sidx_parser_init (GstSidxParser * parser)
31 parser->status = GST_ISOFF_QT_SIDX_PARSER_INIT;
32 parser->cumulative_entry_size = 0;
33 parser->sidx.entries = NULL;
34 parser->sidx.entries_count = 0;
38 gst_isoff_qt_sidx_parser_clear (GstSidxParser * parser)
40 g_free (parser->sidx.entries);
41 parser->sidx.entries = NULL;
45 gst_isoff_qt_parse_sidx_entry (GstSidxBoxEntry * entry, GstByteReader * reader)
49 aux = gst_byte_reader_get_uint32_be_unchecked (reader);
50 entry->ref_type = aux >> 31;
51 entry->size = aux & 0x7FFFFFFF;
52 entry->duration = gst_byte_reader_get_uint32_be_unchecked (reader);
53 aux = gst_byte_reader_get_uint32_be_unchecked (reader);
54 entry->starts_with_sap = aux >> 31;
55 entry->sap_type = ((aux >> 28) & 0x7);
56 entry->sap_delta_time = aux & 0xFFFFFFF;
60 gst_isoff_qt_sidx_parser_add_data (GstSidxParser * parser,
61 const guint8 * buffer, gint length, guint * consumed)
63 GstIsoffParserResult res = GST_ISOFF_QT_PARSER_OK;
68 gst_byte_reader_init (&reader, buffer, length);
70 switch (parser->status) {
71 case GST_ISOFF_QT_SIDX_PARSER_INIT:
72 if (gst_byte_reader_get_remaining (&reader) < GST_ISOFF_QT_FULL_BOX_SIZE) {
76 parser->size = gst_byte_reader_get_uint32_be_unchecked (&reader);
77 fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
78 if (fourcc != GST_ISOFF_QT_FOURCC_SIDX) {
79 res = GST_ISOFF_QT_PARSER_UNEXPECTED;
80 gst_byte_reader_set_pos (&reader, 0);
83 if (parser->size == 1) {
84 if (gst_byte_reader_get_remaining (&reader) < 12) {
85 gst_byte_reader_set_pos (&reader, 0);
89 parser->size = gst_byte_reader_get_uint64_be_unchecked (&reader);
91 if (parser->size == 0) {
92 res = GST_ISOFF_QT_PARSER_ERROR;
93 gst_byte_reader_set_pos (&reader, 0);
96 parser->sidx.version = gst_byte_reader_get_uint8_unchecked (&reader);
97 parser->sidx.flags = gst_byte_reader_get_uint24_le_unchecked (&reader);
99 parser->status = GST_ISOFF_QT_SIDX_PARSER_HEADER;
101 case GST_ISOFF_QT_SIDX_PARSER_HEADER:
102 remaining = gst_byte_reader_get_remaining (&reader);
103 if (remaining < 12 + (parser->sidx.version == 0 ? 8 : 16)) {
107 parser->sidx.ref_id = gst_byte_reader_get_uint32_be_unchecked (&reader);
108 parser->sidx.timescale =
109 gst_byte_reader_get_uint32_be_unchecked (&reader);
110 if (parser->sidx.version == 0) {
111 parser->sidx.earliest_pts =
112 gst_byte_reader_get_uint32_be_unchecked (&reader);
113 parser->sidx.first_offset = parser->sidx.earliest_pts =
114 gst_byte_reader_get_uint32_be_unchecked (&reader);
116 parser->sidx.earliest_pts =
117 gst_byte_reader_get_uint64_be_unchecked (&reader);
118 parser->sidx.first_offset =
119 gst_byte_reader_get_uint64_be_unchecked (&reader);
121 /* skip 2 reserved bytes */
122 gst_byte_reader_skip_unchecked (&reader, 2);
123 parser->sidx.entries_count =
124 gst_byte_reader_get_uint16_be_unchecked (&reader);
126 GST_LOG ("Timescale: %" G_GUINT32_FORMAT, parser->sidx.timescale);
127 GST_LOG ("Earliest pts: %" G_GUINT64_FORMAT, parser->sidx.earliest_pts);
128 GST_LOG ("First offset: %" G_GUINT64_FORMAT, parser->sidx.first_offset);
130 parser->cumulative_pts =
131 gst_util_uint64_scale_int_round (parser->sidx.earliest_pts,
132 GST_SECOND, parser->sidx.timescale);
134 if (parser->sidx.entries_count) {
135 parser->sidx.entries =
136 g_malloc (sizeof (GstSidxBoxEntry) * parser->sidx.entries_count);
138 parser->sidx.entry_index = 0;
140 parser->status = GST_ISOFF_QT_SIDX_PARSER_DATA;
142 case GST_ISOFF_QT_SIDX_PARSER_DATA:
143 while (parser->sidx.entry_index < parser->sidx.entries_count) {
144 GstSidxBoxEntry *entry =
145 &parser->sidx.entries[parser->sidx.entry_index];
147 remaining = gst_byte_reader_get_remaining (&reader);;
151 entry->offset = parser->cumulative_entry_size;
152 entry->pts = parser->cumulative_pts;
153 gst_isoff_qt_parse_sidx_entry (entry, &reader);
154 entry->duration = gst_util_uint64_scale_int_round (entry->duration,
155 GST_SECOND, parser->sidx.timescale);
156 parser->cumulative_entry_size += entry->size;
157 parser->cumulative_pts += entry->duration;
159 GST_LOG ("Sidx entry %d) offset: %" G_GUINT64_FORMAT ", pts: %"
160 GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT " - size %"
161 G_GUINT32_FORMAT, parser->sidx.entry_index, entry->offset,
162 GST_TIME_ARGS (entry->pts), GST_TIME_ARGS (entry->duration),
165 parser->sidx.entry_index++;
168 if (parser->sidx.entry_index == parser->sidx.entries_count)
169 parser->status = GST_ISOFF_QT_SIDX_PARSER_FINISHED;
172 case GST_ISOFF_QT_SIDX_PARSER_FINISHED:
173 parser->sidx.entry_index = 0;
174 res = GST_ISOFF_QT_PARSER_DONE;
178 *consumed = gst_byte_reader_get_pos (&reader);
183 gst_isoff_qt_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer,
186 GstIsoffParserResult res = GST_ISOFF_QT_PARSER_OK;
189 if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
191 return GST_ISOFF_QT_PARSER_ERROR;
195 gst_isoff_qt_sidx_parser_add_data (parser, info.data, info.size,
198 gst_buffer_unmap (buffer, &info);