1 /* Quicktime muxer plugin for GStreamer
2 * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19 /*
20 * Unless otherwise indicated, Source Code is licensed under MIT license.
21 * See further explanation attached in License Statement (distributed in the file
22 * LICENSE).
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy of
25 * this software and associated documentation files (the "Software"), to deal in
26 * the Software without restriction, including without limitation the rights to
27 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28 * of the Software, and to permit persons to whom the Software is furnished to do
29 * so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in all
32 * copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40 * SOFTWARE.
41 */
42
43 #include "descriptors.h"
44
45 /*
46 * Some mp4 structures (descriptors) use a coding scheme for
47 * representing its size.
48 * It is grouped in bytes. The 1st bit set to 1 means we need another byte,
49 * 0 otherwise. The remaining 7 bits are the useful values.
50 *
51 * The next set of functions handle those values
52 */
53
54 /*
55 * Gets an unsigned integer and packs it into a 'expandable size' format
56 * (as used by mp4 descriptors)
57 * @size: the integer to be parsed
58 * @ptr: the array to place the result
59 * @array_size: the size of ptr array
60 */
61 static void
expandable_size_parse(guint64 size,guint8 * ptr,guint32 array_size)62 expandable_size_parse (guint64 size, guint8 * ptr, guint32 array_size)
63 {
64 int index = 0;
65
66 memset (ptr, 0, sizeof (array_size));
67 while (size > 0 && index < array_size) {
68 ptr[index++] = (size > 0x7F ? 0x80 : 0x0) | (size & 0x7F);
69 size = size >> 7;
70 }
71 }
72
73 /*
74 * Gets how many positions in an array holding an 'expandable size'
75 * are really used
76 *
77 * @ptr: the array with the 'expandable size'
78 * @array_size: the size of ptr array
79 *
80 * Returns: the number of really used positions
81 */
82 static guint64
expandable_size_get_length(guint8 * ptr,guint32 array_size)83 expandable_size_get_length (guint8 * ptr, guint32 array_size)
84 {
85 gboolean next = TRUE;
86 guint32 index = 0;
87
88 while (next && index < array_size) {
89 next = (ptr[index] & 0x80);
90 index++;
91 }
92 return index;
93 }
94
95 /*
96 * Initializers below
97 */
98
99 static void
desc_base_descriptor_init(BaseDescriptor * bd,guint8 tag,guint32 size)100 desc_base_descriptor_init (BaseDescriptor * bd, guint8 tag, guint32 size)
101 {
102 bd->tag = tag;
103 expandable_size_parse (size, bd->size, 4);
104 }
105
106 static void
desc_dec_specific_info_init(DecoderSpecificInfoDescriptor * dsid)107 desc_dec_specific_info_init (DecoderSpecificInfoDescriptor * dsid)
108 {
109 desc_base_descriptor_init (&dsid->base, DECODER_SPECIFIC_INFO_TAG, 0);
110 dsid->length = 0;
111 dsid->data = NULL;
112 }
113
114 DecoderSpecificInfoDescriptor *
desc_dec_specific_info_new(void)115 desc_dec_specific_info_new (void)
116 {
117 DecoderSpecificInfoDescriptor *desc =
118 g_new0 (DecoderSpecificInfoDescriptor, 1);
119 desc_dec_specific_info_init (desc);
120 return desc;
121 }
122
123 static void
desc_dec_conf_desc_init(DecoderConfigDescriptor * dcd)124 desc_dec_conf_desc_init (DecoderConfigDescriptor * dcd)
125 {
126 desc_base_descriptor_init (&dcd->base, DECODER_CONFIG_DESC_TAG, 0);
127 dcd->dec_specific_info = NULL;
128 }
129
130 static void
desc_sl_conf_desc_init(SLConfigDescriptor * sl)131 desc_sl_conf_desc_init (SLConfigDescriptor * sl)
132 {
133 desc_base_descriptor_init (&sl->base, SL_CONFIG_DESC_TAG, 0);
134 sl->predefined = 0x2;
135 }
136
137 void
desc_es_init(ESDescriptor * es)138 desc_es_init (ESDescriptor * es)
139 {
140 desc_base_descriptor_init (&es->base, ES_DESCRIPTOR_TAG, 0);
141
142 es->id = 0;
143 es->flags = 0;
144 es->depends_on_es_id = 0;
145 es->ocr_es_id = 0;
146 es->url_length = 0;
147 es->url_string = NULL;
148
149 desc_dec_conf_desc_init (&es->dec_conf_desc);
150 desc_sl_conf_desc_init (&es->sl_conf_desc);
151 }
152
153 ESDescriptor *
desc_es_descriptor_new(void)154 desc_es_descriptor_new (void)
155 {
156 ESDescriptor *es = g_new0 (ESDescriptor, 1);
157
158 desc_es_init (es);
159 return es;
160 }
161
162 /*
163 * Deinitializers/Destructors below
164 */
165
166 static void
desc_base_descriptor_clear(BaseDescriptor * base)167 desc_base_descriptor_clear (BaseDescriptor * base)
168 {
169 }
170
171 void
desc_dec_specific_info_free(DecoderSpecificInfoDescriptor * dsid)172 desc_dec_specific_info_free (DecoderSpecificInfoDescriptor * dsid)
173 {
174 desc_base_descriptor_clear (&dsid->base);
175 if (dsid->data) {
176 g_free (dsid->data);
177 dsid->data = NULL;
178 }
179 g_free (dsid);
180 }
181
182 static void
desc_dec_conf_desc_clear(DecoderConfigDescriptor * dec)183 desc_dec_conf_desc_clear (DecoderConfigDescriptor * dec)
184 {
185 desc_base_descriptor_clear (&dec->base);
186 if (dec->dec_specific_info) {
187 desc_dec_specific_info_free (dec->dec_specific_info);
188 }
189 }
190
191 static void
desc_sl_config_descriptor_clear(SLConfigDescriptor * sl)192 desc_sl_config_descriptor_clear (SLConfigDescriptor * sl)
193 {
194 desc_base_descriptor_clear (&sl->base);
195 }
196
197 void
desc_es_descriptor_clear(ESDescriptor * es)198 desc_es_descriptor_clear (ESDescriptor * es)
199 {
200 desc_base_descriptor_clear (&es->base);
201 if (es->url_string) {
202 g_free (es->url_string);
203 es->url_string = NULL;
204 }
205 desc_dec_conf_desc_clear (&es->dec_conf_desc);
206 desc_sl_config_descriptor_clear (&es->sl_conf_desc);
207 }
208
209 /*
210 * Size handling functions below
211 */
212
213 void
desc_dec_specific_info_alloc_data(DecoderSpecificInfoDescriptor * dsid,guint32 size)214 desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor * dsid,
215 guint32 size)
216 {
217 if (dsid->data) {
218 g_free (dsid->data);
219 }
220 dsid->data = g_new0 (guint8, size);
221 dsid->length = size;
222 }
223
224 static void
desc_base_descriptor_set_size(BaseDescriptor * bd,guint32 size)225 desc_base_descriptor_set_size (BaseDescriptor * bd, guint32 size)
226 {
227 expandable_size_parse (size, bd->size, 4);
228 }
229
230 static guint64
desc_base_descriptor_get_size(BaseDescriptor * bd)231 desc_base_descriptor_get_size (BaseDescriptor * bd)
232 {
233 guint64 size = 0;
234
235 size += sizeof (guint8);
236 size += expandable_size_get_length (bd->size, 4) * sizeof (guint8);
237 return size;
238 }
239
240 static guint64
desc_sl_config_descriptor_get_size(SLConfigDescriptor * sl_desc)241 desc_sl_config_descriptor_get_size (SLConfigDescriptor * sl_desc)
242 {
243 guint64 size = 0;
244 guint64 extra_size = 0;
245
246 size += desc_base_descriptor_get_size (&sl_desc->base);
247 /* predefined */
248 extra_size += sizeof (guint8);
249
250 desc_base_descriptor_set_size (&sl_desc->base, extra_size);
251
252 return size + extra_size;
253 }
254
255 static guint64
desc_dec_specific_info_get_size(DecoderSpecificInfoDescriptor * dsid)256 desc_dec_specific_info_get_size (DecoderSpecificInfoDescriptor * dsid)
257 {
258 guint64 size = 0;
259 guint64 extra_size = 0;
260
261 size += desc_base_descriptor_get_size (&dsid->base);
262 extra_size += sizeof (guint8) * dsid->length;
263 desc_base_descriptor_set_size (&dsid->base, extra_size);
264 return size + extra_size;
265 }
266
267 static guint64
desc_dec_config_descriptor_get_size(DecoderConfigDescriptor * dec_desc)268 desc_dec_config_descriptor_get_size (DecoderConfigDescriptor * dec_desc)
269 {
270 guint64 size = 0;
271 guint64 extra_size = 0;
272
273 size += desc_base_descriptor_get_size (&dec_desc->base);
274 /* object type */
275 extra_size += sizeof (guint8);
276 /* stream type */
277 extra_size += sizeof (guint8);
278 /* buffer size */
279 extra_size += sizeof (guint8) * 3;
280 /* max bitrate */
281 extra_size += sizeof (guint32);
282 /* avg bitrate */
283 extra_size += sizeof (guint32);
284 if (dec_desc->dec_specific_info) {
285 extra_size += desc_dec_specific_info_get_size (dec_desc->dec_specific_info);
286 }
287
288 desc_base_descriptor_set_size (&dec_desc->base, extra_size);
289 return size + extra_size;
290 }
291
292 static guint64
desc_es_descriptor_get_size(ESDescriptor * es)293 desc_es_descriptor_get_size (ESDescriptor * es)
294 {
295 guint64 size = 0;
296 guint64 extra_size = 0;
297
298 size += desc_base_descriptor_get_size (&es->base);
299 /* id */
300 extra_size += sizeof (guint16);
301 /* flags */
302 extra_size += sizeof (guint8);
303 /* depends_on_es_id */
304 if (es->flags & 0x80) {
305 extra_size += sizeof (guint16);
306 }
307 if (es->flags & 0x40) {
308 /* url_length */
309 extra_size += sizeof (guint8);
310 /* url */
311 extra_size += sizeof (gchar) * es->url_length;
312 }
313 if (es->flags & 0x20) {
314 /* ocr_es_id */
315 extra_size += sizeof (guint16);
316 }
317
318 extra_size += desc_dec_config_descriptor_get_size (&es->dec_conf_desc);
319 extra_size += desc_sl_config_descriptor_get_size (&es->sl_conf_desc);
320
321 desc_base_descriptor_set_size (&es->base, extra_size);
322
323 return size + extra_size;
324 }
325
326 static gboolean
desc_es_descriptor_check_stream_dependency(ESDescriptor * es)327 desc_es_descriptor_check_stream_dependency (ESDescriptor * es)
328 {
329 return es->flags & 0x80;
330 }
331
332 static gboolean
desc_es_descriptor_check_url_flag(ESDescriptor * es)333 desc_es_descriptor_check_url_flag (ESDescriptor * es)
334 {
335 return es->flags & 0x40;
336 }
337
338 static gboolean
desc_es_descriptor_check_ocr(ESDescriptor * es)339 desc_es_descriptor_check_ocr (ESDescriptor * es)
340 {
341 return es->flags & 0x20;
342 }
343
344 /* Copy/Serializations Functions below */
345
346 static guint64
desc_base_descriptor_copy_data(BaseDescriptor * desc,guint8 ** buffer,guint64 * size,guint64 * offset)347 desc_base_descriptor_copy_data (BaseDescriptor * desc, guint8 ** buffer,
348 guint64 * size, guint64 * offset)
349 {
350 guint64 original_offset = *offset;
351
352 prop_copy_uint8 (desc->tag, buffer, size, offset);
353 prop_copy_uint8_array (desc->size, expandable_size_get_length (desc->size, 4),
354 buffer, size, offset);
355 return original_offset - *offset;
356 }
357
358 static guint64
desc_sl_config_descriptor_copy_data(SLConfigDescriptor * desc,guint8 ** buffer,guint64 * size,guint64 * offset)359 desc_sl_config_descriptor_copy_data (SLConfigDescriptor * desc,
360 guint8 ** buffer, guint64 * size, guint64 * offset)
361 {
362 guint64 original_offset = *offset;
363
364 if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
365 return 0;
366 }
367 /* predefined attribute */
368 prop_copy_uint8 (desc->predefined, buffer, size, offset);
369
370 return *offset - original_offset;
371 }
372
373 static guint64
desc_dec_specific_info_copy_data(DecoderSpecificInfoDescriptor * desc,guint8 ** buffer,guint64 * size,guint64 * offset)374 desc_dec_specific_info_copy_data (DecoderSpecificInfoDescriptor * desc,
375 guint8 ** buffer, guint64 * size, guint64 * offset)
376 {
377 guint64 original_offset = *offset;
378
379 if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
380 return 0;
381 }
382 prop_copy_uint8_array (desc->data, desc->length, buffer, size, offset);
383
384 return *offset - original_offset;
385 }
386
387 static guint64
desc_dec_config_descriptor_copy_data(DecoderConfigDescriptor * desc,guint8 ** buffer,guint64 * size,guint64 * offset)388 desc_dec_config_descriptor_copy_data (DecoderConfigDescriptor * desc,
389 guint8 ** buffer, guint64 * size, guint64 * offset)
390 {
391 guint64 original_offset = *offset;
392
393 if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
394 return 0;
395 }
396
397 prop_copy_uint8 (desc->object_type, buffer, size, offset);
398
399 prop_copy_uint8 (desc->stream_type, buffer, size, offset);
400 prop_copy_uint8_array (desc->buffer_size_DB, 3, buffer, size, offset);
401
402 prop_copy_uint32 (desc->max_bitrate, buffer, size, offset);
403 prop_copy_uint32 (desc->avg_bitrate, buffer, size, offset);
404
405 if (desc->dec_specific_info) {
406 if (!desc_dec_specific_info_copy_data (desc->dec_specific_info, buffer,
407 size, offset)) {
408 return 0;
409 }
410 }
411
412 return *offset - original_offset;
413 }
414
415 guint64
desc_es_descriptor_copy_data(ESDescriptor * desc,guint8 ** buffer,guint64 * size,guint64 * offset)416 desc_es_descriptor_copy_data (ESDescriptor * desc, guint8 ** buffer,
417 guint64 * size, guint64 * offset)
418 {
419 guint64 original_offset = *offset;
420
421 /* must call this twice to have size fields of all contained descriptors set
422 * correctly, and to have the size of the size fields taken into account */
423 desc_es_descriptor_get_size (desc);
424 desc_es_descriptor_get_size (desc);
425
426 if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
427 return 0;
428 }
429 /* id and flags */
430 prop_copy_uint16 (desc->id, buffer, size, offset);
431 prop_copy_uint8 (desc->flags, buffer, size, offset);
432
433 if (desc_es_descriptor_check_stream_dependency (desc)) {
434 prop_copy_uint16 (desc->depends_on_es_id, buffer, size, offset);
435 }
436
437 if (desc_es_descriptor_check_url_flag (desc)) {
438 prop_copy_size_string (desc->url_string, desc->url_length, buffer, size,
439 offset);
440 }
441
442 if (desc_es_descriptor_check_ocr (desc)) {
443 prop_copy_uint16 (desc->ocr_es_id, buffer, size, offset);
444 }
445
446 if (!desc_dec_config_descriptor_copy_data (&desc->dec_conf_desc, buffer, size,
447 offset)) {
448 return 0;
449 }
450
451 if (!desc_sl_config_descriptor_copy_data (&desc->sl_conf_desc, buffer, size,
452 offset)) {
453 return 0;
454 }
455
456 return *offset - original_offset;
457 }
458