Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2006-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / ISO Media File Format sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/internal/isomedia_dev.h>
27 :
28 : #ifndef GPAC_DISABLE_ISOM
29 :
30 121 : void ilst_box_del(GF_Box *s)
31 : {
32 : GF_ItemListBox *ptr = (GF_ItemListBox *)s;
33 121 : if (ptr == NULL) return;
34 121 : gf_free(ptr);
35 : }
36 :
37 118 : GF_Err ilst_box_read(GF_Box *s, GF_BitStream *bs)
38 : {
39 : GF_Err e;
40 : u32 sub_type;
41 : GF_Box *a;
42 : GF_ItemListBox *ptr = (GF_ItemListBox *)s;
43 1235 : while (ptr->size) {
44 : /*if no ilst type coded, break*/
45 999 : sub_type = gf_bs_peek_bits(bs, 32, 0);
46 999 : if (sub_type) {
47 999 : e = gf_isom_box_parse_ex(&a, bs, s->type, GF_FALSE);
48 :
49 : /* the macro will return in this case before we can free */
50 999 : if (!e && ptr->size < a->size) {
51 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d)\n", gf_4cc_to_str(ptr->type), ptr->size, a->size, __FILE__, __LINE__ )); \
52 : e = GF_ISOM_INVALID_FILE;
53 : }
54 999 : if (e) {
55 0 : if (a) gf_isom_box_del(a);
56 : return e;
57 : }
58 :
59 999 : ISOM_DECREASE_SIZE(ptr, a->size);
60 999 : gf_list_add(ptr->child_boxes, a);
61 : } else {
62 0 : gf_bs_read_u32(bs);
63 0 : ISOM_DECREASE_SIZE(ptr, 4);
64 : }
65 : }
66 : return GF_OK;
67 : }
68 :
69 121 : GF_Box *ilst_box_new()
70 : {
71 242 : ISOM_DECL_BOX_ALLOC(GF_ItemListBox, GF_ISOM_BOX_TYPE_ILST);
72 121 : tmp->child_boxes = gf_list_new();
73 121 : return (GF_Box *)tmp;
74 : }
75 :
76 : #ifndef GPAC_DISABLE_ISOM_WRITE
77 :
78 88 : GF_Err ilst_box_write(GF_Box *s, GF_BitStream *bs)
79 : {
80 : GF_Err e;
81 : // GF_ItemListBox *ptr = (GF_ItemListBox *)s;
82 :
83 88 : e = gf_isom_box_write_header(s, bs);
84 88 : if (e) return e;
85 :
86 88 : return GF_OK;
87 : }
88 :
89 :
90 150 : GF_Err ilst_box_size(GF_Box *s)
91 : {
92 150 : return GF_OK;
93 : }
94 :
95 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
96 :
97 166 : void ilst_item_box_del(GF_Box *s)
98 : {
99 : GF_ListItemBox *ptr = (GF_ListItemBox *) s;
100 166 : if (ptr == NULL) return;
101 166 : gf_free(ptr);
102 : }
103 :
104 75 : GF_Err ilst_item_box_read(GF_Box *s,GF_BitStream *bs)
105 : {
106 : GF_Err e;
107 : u32 sub_type;
108 75 : GF_Box *a = NULL;
109 : GF_ListItemBox *ptr = (GF_ListItemBox *)s;
110 :
111 : /*iTunes way: there's a data atom containing the data*/
112 75 : sub_type = gf_bs_peek_bits(bs, 32, 4);
113 75 : if (sub_type == GF_ISOM_BOX_TYPE_DATA ) {
114 31 : e = gf_isom_box_parse(&a, bs);
115 :
116 31 : if (!e && a && (ptr->size < a->size)) {
117 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d)\n", gf_4cc_to_str(ptr->type), ptr->size, a->size, __FILE__, __LINE__ )); \
118 : e = GF_ISOM_INVALID_FILE;
119 : }
120 31 : if (!a) e = GF_ISOM_INVALID_FILE;
121 :
122 31 : if (e) {
123 0 : if (a) gf_isom_box_del(a);
124 : return e;
125 : }
126 : if (!a) return GF_NON_COMPLIANT_BITSTREAM;
127 :
128 31 : ISOM_DECREASE_SIZE(ptr, a->size);
129 :
130 31 : if (ptr->data) gf_isom_box_del_parent(&ptr->child_boxes, (GF_Box *) ptr->data);
131 :
132 : /* otherwise a->data will always overflow */
133 31 : if (a->size > 4 && (a->type != GF_ISOM_BOX_TYPE_VOID)) {
134 31 : ptr->data = (GF_DataBox *)a;
135 31 : if (!ptr->child_boxes) ptr->child_boxes = gf_list_new();
136 31 : gf_list_add(ptr->child_boxes, ptr->data);
137 : } else {
138 0 : ptr->data = NULL;
139 0 : gf_isom_box_del(a);
140 : }
141 : }
142 : /*QT way*/
143 : else {
144 44 : u64 pos = gf_bs_get_position(bs);
145 44 : u64 prev_size = s->size;
146 : /*try parsing as generic box list*/
147 44 : e = gf_isom_box_array_read(s, bs);
148 44 : if (e==GF_OK) return GF_OK;
149 : //reset content and retry - this deletes ptr->data !!
150 0 : gf_isom_box_array_del(s->child_boxes);
151 0 : s->child_boxes=NULL;
152 0 : gf_bs_seek(bs, pos);
153 0 : s->size = prev_size;
154 :
155 0 : ptr->data = (GF_DataBox *)gf_isom_box_new_parent(&ptr->child_boxes, GF_ISOM_BOX_TYPE_DATA);
156 : //nope, check qt-style
157 0 : ptr->data->qt_style = GF_TRUE;
158 0 : ISOM_DECREASE_SIZE(ptr, 2);
159 0 : ptr->data->dataSize = gf_bs_read_u16(bs);
160 0 : gf_bs_read_u16(bs);
161 :
162 0 : ptr->data->data = (char *) gf_malloc(sizeof(char)*(ptr->data->dataSize + 1));
163 0 : if (!ptr->data->data) return GF_OUT_OF_MEM;
164 :
165 0 : gf_bs_read_data(bs, ptr->data->data, ptr->data->dataSize);
166 0 : ptr->data->data[ptr->data->dataSize] = 0;
167 0 : ISOM_DECREASE_SIZE(ptr, ptr->data->dataSize);
168 : }
169 : return GF_OK;
170 : }
171 :
172 166 : GF_Box *ilst_item_box_new()
173 : {
174 332 : ISOM_DECL_BOX_ALLOC(GF_ListItemBox, GF_ISOM_ITUNE_NAME); //type will be overwrite
175 166 : return (GF_Box *)tmp;
176 : }
177 :
178 : #ifndef GPAC_DISABLE_ISOM_WRITE
179 :
180 68 : GF_Err ilst_item_box_write(GF_Box *s, GF_BitStream *bs)
181 : {
182 : GF_Err e;
183 : GF_ListItemBox *ptr = (GF_ListItemBox *) s;
184 :
185 68 : e = gf_isom_box_write_header(s, bs);
186 68 : if (e) return e;
187 :
188 : /*generic box list*/
189 68 : if (ptr->child_boxes && !ptr->data) {
190 : }
191 : //empty ilst
192 68 : else if (!ptr->data) {
193 : }
194 : /*iTune way: data-box-encapsulated box list*/
195 24 : else if (!ptr->data->qt_style) {
196 : }
197 : /*QT way: raw data*/
198 : else {
199 0 : gf_bs_write_u16(bs, ptr->data->dataSize);
200 0 : gf_bs_write_u16(bs, 0);
201 0 : gf_bs_write_data(bs, ptr->data->data, ptr->data->dataSize);
202 0 : ptr->size = 0; //abort
203 : }
204 : return GF_OK;
205 : }
206 :
207 84 : GF_Err ilst_item_box_size(GF_Box *s)
208 : {
209 : GF_ListItemBox *ptr = (GF_ListItemBox *)s;
210 :
211 : /*generic box list*/
212 84 : if (ptr->child_boxes && !ptr->data) {
213 : }
214 : /*iTune way: data-box-encapsulated box list*/
215 124 : else if (ptr->data && !ptr->data->qt_style) {
216 40 : u32 pos=0;
217 40 : gf_isom_check_position(s, (GF_Box* ) ptr->data, &pos);
218 : }
219 : /*QT way: raw data*/
220 44 : else if (ptr->data) {
221 0 : ptr->size += ptr->data->dataSize + 4;
222 : }
223 84 : return GF_OK;
224 : }
225 :
226 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
227 :
228 1004 : void databox_box_del(GF_Box *s)
229 : {
230 : GF_DataBox *ptr = (GF_DataBox *) s;
231 1004 : if (ptr == NULL) return;
232 1004 : if (ptr->data)
233 1001 : gf_free(ptr->data);
234 1004 : gf_free(ptr);
235 :
236 : }
237 :
238 1000 : GF_Err databox_box_read(GF_Box *s,GF_BitStream *bs)
239 : {
240 : GF_DataBox *ptr = (GF_DataBox *)s;
241 :
242 1000 : ISOM_DECREASE_SIZE(ptr, 4);
243 1000 : ptr->reserved = gf_bs_read_u32(bs);
244 :
245 1000 : if (ptr->size) {
246 999 : ptr->dataSize = (u32) ptr->size;
247 999 : ptr->data = (char*)gf_malloc(ptr->dataSize * sizeof(ptr->data[0]) + 1);
248 999 : if (!ptr->data) return GF_OUT_OF_MEM;
249 999 : ptr->data[ptr->dataSize] = 0;
250 999 : gf_bs_read_data(bs, ptr->data, ptr->dataSize);
251 : }
252 :
253 : return GF_OK;
254 : }
255 :
256 1004 : GF_Box *databox_box_new()
257 : {
258 2008 : ISOM_DECL_BOX_ALLOC(GF_DataBox, GF_ISOM_BOX_TYPE_DATA);
259 :
260 1004 : return (GF_Box *)tmp;
261 : }
262 :
263 : #ifndef GPAC_DISABLE_ISOM_WRITE
264 :
265 729 : GF_Err databox_box_write(GF_Box *s, GF_BitStream *bs)
266 : {
267 : GF_Err e;
268 : GF_DataBox *ptr = (GF_DataBox *) s;
269 :
270 729 : e = gf_isom_full_box_write(s, bs);
271 729 : if (e) return e;
272 729 : gf_bs_write_int(bs, ptr->reserved, 32);
273 729 : if(ptr->data != NULL && ptr->dataSize > 0) {
274 728 : gf_bs_write_data(bs, ptr->data, ptr->dataSize);
275 : }
276 : return GF_OK;
277 : }
278 :
279 1273 : GF_Err databox_box_size(GF_Box *s)
280 : {
281 : GF_DataBox *ptr = (GF_DataBox *)s;
282 :
283 1273 : ptr->size += 4;
284 1273 : if(ptr->data != NULL && ptr->dataSize > 0) {
285 1272 : ptr->size += ptr->dataSize;
286 : }
287 1273 : return GF_OK;
288 : }
289 :
290 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
291 :
292 14 : void alis_box_del(GF_Box *s)
293 : {
294 : GF_DataEntryAliasBox *ptr = (GF_DataEntryAliasBox *)s;
295 14 : if (ptr == NULL) return;
296 14 : gf_free(ptr);
297 : }
298 :
299 12 : GF_Err alis_box_read(GF_Box *s, GF_BitStream *bs)
300 : {
301 : // GF_DataEntryAliasBox *ptr = (GF_DataEntryAliasBox *)s;
302 12 : return GF_OK;
303 : }
304 :
305 14 : GF_Box *alis_box_new()
306 : {
307 28 : ISOM_DECL_BOX_ALLOC(GF_DataEntryAliasBox, GF_QT_BOX_TYPE_ALIS);
308 14 : return (GF_Box *)tmp;
309 : }
310 :
311 : #ifndef GPAC_DISABLE_ISOM_WRITE
312 :
313 1 : GF_Err alis_box_write(GF_Box *s, GF_BitStream *bs)
314 : {
315 : GF_Err e;
316 : // GF_DataEntryAliasBox *ptr = (GF_DataEntryAliasBox *)s;
317 :
318 1 : e = gf_isom_full_box_write(s, bs);
319 1 : if (e) return e;
320 1 : return GF_OK;
321 : }
322 :
323 1 : GF_Err alis_box_size(GF_Box *s)
324 : {
325 1 : return GF_OK;
326 : }
327 :
328 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
329 :
330 5 : void wide_box_del(GF_Box *s)
331 : {
332 5 : if (s == NULL) return;
333 5 : gf_free(s);
334 : }
335 :
336 :
337 3 : GF_Err wide_box_read(GF_Box *s, GF_BitStream *bs)
338 : {
339 3 : gf_bs_skip_bytes(bs, s->size);
340 3 : s->size = 0;
341 3 : return GF_OK;
342 : }
343 :
344 5 : GF_Box *wide_box_new()
345 : {
346 10 : ISOM_DECL_BOX_ALLOC(GF_WideBox, GF_QT_BOX_TYPE_WIDE);
347 5 : return (GF_Box *)tmp;
348 : }
349 :
350 : #ifndef GPAC_DISABLE_ISOM_WRITE
351 :
352 1 : GF_Err wide_box_write(GF_Box *s, GF_BitStream *bs)
353 : {
354 : GF_Err e;
355 1 : e = gf_isom_box_write_header(s, bs);
356 1 : if (e) return e;
357 1 : return GF_OK;
358 : }
359 :
360 1 : GF_Err wide_box_size(GF_Box *s)
361 : {
362 1 : return GF_OK;
363 : }
364 :
365 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
366 :
367 2465 : GF_Box *gf_isom_get_meta_extensions(GF_ISOFile *mov, Bool for_xtra)
368 : {
369 : u32 i;
370 : GF_UserDataMap *map;
371 :
372 2465 : if (!mov || !mov->moov) return NULL;
373 :
374 2435 : if (!mov->moov->udta) return NULL;
375 26 : map = udta_getEntry(mov->moov->udta, for_xtra ? GF_ISOM_BOX_TYPE_XTRA : GF_ISOM_BOX_TYPE_META, NULL);
376 26 : if (!map) return NULL;
377 :
378 0 : for(i = 0; i < gf_list_count(map->boxes); i++) {
379 23 : GF_MetaBox *meta = (GF_MetaBox*)gf_list_get(map->boxes, i);
380 23 : if (for_xtra && (meta->type==GF_ISOM_BOX_TYPE_XTRA)) return (GF_Box *) meta;
381 :
382 23 : if(meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return (GF_Box *) meta;
383 : }
384 : return NULL;
385 : }
386 :
387 : #ifndef GPAC_DISABLE_ISOM_WRITE
388 2 : GF_Box *gf_isom_create_meta_extensions(GF_ISOFile *mov, Bool for_xtra)
389 : {
390 : GF_Err e;
391 : u32 i;
392 : GF_MetaBox *meta;
393 : GF_UserDataMap *map;
394 2 : u32 udta_subtype = for_xtra ? GF_ISOM_BOX_TYPE_XTRA : GF_ISOM_BOX_TYPE_META;
395 :
396 2 : if (!mov || !mov->moov) return NULL;
397 :
398 2 : if (!mov->moov->udta) {
399 1 : e = moov_on_child_box((GF_Box*)mov->moov, gf_isom_box_new_parent(&mov->moov->child_boxes, GF_ISOM_BOX_TYPE_UDTA), GF_FALSE);
400 1 : if (e) return NULL;
401 : }
402 :
403 2 : map = udta_getEntry(mov->moov->udta, udta_subtype, NULL);
404 2 : if (map) {
405 0 : for (i=0; i<gf_list_count(map->boxes); i++) {
406 1 : meta = (GF_MetaBox*)gf_list_get(map->boxes, i);
407 1 : if (for_xtra) return (GF_Box *) meta;
408 :
409 1 : if (meta && meta->handler && (meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR)) return (GF_Box *) meta;
410 : }
411 : }
412 :
413 : //udta handles children boxes through maps
414 1 : meta = (GF_MetaBox *)gf_isom_box_new(udta_subtype);
415 :
416 1 : if (meta) {
417 1 : udta_on_child_box((GF_Box *)mov->moov->udta, (GF_Box *)meta, GF_FALSE);
418 1 : if (!for_xtra) {
419 1 : meta->handler = (GF_HandlerBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_HDLR);
420 1 : if(meta->handler == NULL) {
421 0 : gf_isom_box_del((GF_Box *)meta);
422 0 : return NULL;
423 : }
424 1 : meta->handler->handlerType = GF_ISOM_HANDLER_TYPE_MDIR;
425 1 : gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_ILST);
426 : }
427 : }
428 : return (GF_Box *) meta;
429 : }
430 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
431 :
432 :
433 :
434 35 : void gmin_box_del(GF_Box *s)
435 : {
436 35 : gf_free(s);
437 35 : }
438 :
439 30 : GF_Err gmin_box_read(GF_Box *s, GF_BitStream *bs)
440 : {
441 : GF_GenericMediaHeaderInfoBox *ptr = (GF_GenericMediaHeaderInfoBox *)s;
442 30 : ISOM_DECREASE_SIZE(ptr, 12);
443 30 : ptr->graphics_mode = gf_bs_read_u16(bs);
444 30 : ptr->op_color_red = gf_bs_read_u16(bs);
445 30 : ptr->op_color_green = gf_bs_read_u16(bs);
446 30 : ptr->op_color_blue = gf_bs_read_u16(bs);
447 30 : ptr->balance = gf_bs_read_u16(bs);
448 30 : ptr->reserved = gf_bs_read_u16(bs);
449 30 : return GF_OK;
450 : }
451 :
452 35 : GF_Box *gmin_box_new()
453 : {
454 70 : ISOM_DECL_BOX_ALLOC(GF_GenericMediaHeaderInfoBox, GF_QT_BOX_TYPE_GMIN);
455 35 : return (GF_Box *)tmp;
456 : }
457 :
458 :
459 :
460 : #ifndef GPAC_DISABLE_ISOM_WRITE
461 :
462 21 : GF_Err gmin_box_write(GF_Box *s, GF_BitStream *bs)
463 : {
464 : GF_Err e;
465 : GF_GenericMediaHeaderInfoBox *ptr = (GF_GenericMediaHeaderInfoBox *)s;
466 :
467 21 : e = gf_isom_full_box_write(s, bs);
468 21 : if (e) return e;
469 :
470 21 : gf_bs_write_u16(bs, ptr->graphics_mode);
471 21 : gf_bs_write_u16(bs, ptr->op_color_red);
472 21 : gf_bs_write_u16(bs, ptr->op_color_green);
473 21 : gf_bs_write_u16(bs, ptr->op_color_blue);
474 21 : gf_bs_write_u16(bs, ptr->balance);
475 21 : gf_bs_write_u16(bs, ptr->reserved);
476 21 : return GF_OK;
477 : }
478 :
479 39 : GF_Err gmin_box_size(GF_Box *s)
480 : {
481 : GF_VideoMediaHeaderBox *ptr = (GF_VideoMediaHeaderBox *)s;
482 39 : ptr->size += 12;
483 39 : return GF_OK;
484 : }
485 :
486 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
487 :
488 :
489 :
490 :
491 48 : void clef_box_del(GF_Box *s)
492 : {
493 48 : gf_free(s);
494 48 : }
495 :
496 36 : GF_Err clef_box_read(GF_Box *s, GF_BitStream *bs)
497 : {
498 : GF_ApertureBox *ptr = (GF_ApertureBox *)s;
499 36 : ISOM_DECREASE_SIZE(ptr, 8);
500 36 : ptr->width = gf_bs_read_u32(bs);
501 36 : ptr->height = gf_bs_read_u32(bs);
502 36 : return GF_OK;
503 : }
504 :
505 48 : GF_Box *clef_box_new()
506 : {
507 96 : ISOM_DECL_BOX_ALLOC(GF_ApertureBox, GF_QT_BOX_TYPE_CLEF);
508 48 : return (GF_Box *)tmp;
509 : }
510 :
511 :
512 : #ifndef GPAC_DISABLE_ISOM_WRITE
513 :
514 33 : GF_Err clef_box_write(GF_Box *s, GF_BitStream *bs)
515 : {
516 : GF_Err e;
517 : GF_ApertureBox *ptr = (GF_ApertureBox *)s;
518 :
519 33 : e = gf_isom_full_box_write(s, bs);
520 33 : if (e) return e;
521 33 : gf_bs_write_u32(bs, ptr->width);
522 33 : gf_bs_write_u32(bs, ptr->height);
523 33 : return GF_OK;
524 : }
525 :
526 63 : GF_Err clef_box_size(GF_Box *s)
527 : {
528 63 : s->size += 8;
529 63 : return GF_OK;
530 : }
531 :
532 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
533 :
534 :
535 16 : void tmcd_box_del(GF_Box *s)
536 : {
537 16 : if (s == NULL) return;
538 16 : gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s);
539 16 : gf_free(s);
540 : }
541 :
542 :
543 12 : GF_Err tmcd_box_read(GF_Box *s, GF_BitStream *bs)
544 : {
545 : GF_TimeCodeSampleEntryBox *ptr = (GF_TimeCodeSampleEntryBox *)s;
546 12 : GF_Err e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)s, bs);
547 12 : if (e) return e;
548 :
549 12 : ISOM_DECREASE_SIZE(s, 26);
550 12 : gf_bs_read_u32(bs); //reserved
551 12 : ptr->flags = gf_bs_read_u32(bs);
552 12 : ptr->timescale = gf_bs_read_u32(bs);
553 12 : ptr->frame_duration = gf_bs_read_u32(bs);
554 12 : ptr->frames_per_counter_tick = gf_bs_read_u8(bs);
555 12 : gf_bs_read_u8(bs); //reserved
556 :
557 12 : return gf_isom_box_array_read(s, bs);
558 : }
559 :
560 16 : GF_Box *tmcd_box_new()
561 : {
562 32 : ISOM_DECL_BOX_ALLOC(GF_TimeCodeSampleEntryBox, GF_QT_BOX_TYPE_TMCD);
563 16 : gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp);
564 16 : return (GF_Box *)tmp;
565 : }
566 :
567 :
568 : #ifndef GPAC_DISABLE_ISOM_WRITE
569 :
570 12 : GF_Err tmcd_box_write(GF_Box *s, GF_BitStream *bs)
571 : {
572 : GF_Err e;
573 : GF_TimeCodeSampleEntryBox *ptr = (GF_TimeCodeSampleEntryBox *)s;
574 12 : e = gf_isom_box_write_header(s, bs);
575 12 : if (e) return e;
576 :
577 12 : gf_bs_write_data(bs, ptr->reserved, 6);
578 12 : gf_bs_write_u16(bs, ptr->dataReferenceIndex);
579 :
580 12 : gf_bs_write_u32(bs, 0); //reserved
581 12 : gf_bs_write_u32(bs, ptr->flags);
582 12 : gf_bs_write_u32(bs, ptr->timescale);
583 12 : gf_bs_write_u32(bs, ptr->frame_duration);
584 12 : gf_bs_write_u8(bs, ptr->frames_per_counter_tick);
585 12 : gf_bs_write_u8(bs, 0); //reserved
586 :
587 12 : return GF_OK;
588 : }
589 :
590 24 : GF_Err tmcd_box_size(GF_Box *s)
591 : {
592 : GF_SampleEntryBox *ptr = (GF_SampleEntryBox *)s;
593 24 : ptr->size += 8 + 18;
594 24 : return GF_OK;
595 : }
596 :
597 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
598 :
599 :
600 18 : void tcmi_box_del(GF_Box *s)
601 : {
602 : GF_TimeCodeMediaInformationBox *ptr = (GF_TimeCodeMediaInformationBox *)s;
603 18 : if (ptr->font) gf_free(ptr->font);
604 18 : gf_free(s);
605 18 : }
606 :
607 :
608 13 : GF_Err tcmi_box_read(GF_Box *s, GF_BitStream *bs)
609 : {
610 : u32 len;
611 : GF_TimeCodeMediaInformationBox *ptr = (GF_TimeCodeMediaInformationBox *)s;
612 :
613 : //don't remove font name len field, some writers just skip it if no font ...
614 13 : ISOM_DECREASE_SIZE(s, 20);
615 :
616 13 : ptr->text_font = gf_bs_read_u16(bs);
617 13 : ptr->text_face = gf_bs_read_u16(bs);
618 13 : ptr->text_size = gf_bs_read_u16(bs);
619 13 : gf_bs_read_u16(bs);
620 13 : ptr->text_color_red = gf_bs_read_u16(bs);
621 13 : ptr->text_color_green = gf_bs_read_u16(bs);
622 13 : ptr->text_color_blue = gf_bs_read_u16(bs);
623 13 : ptr->back_color_red = gf_bs_read_u16(bs);
624 13 : ptr->back_color_green = gf_bs_read_u16(bs);
625 13 : ptr->back_color_blue = gf_bs_read_u16(bs);
626 13 : if (!ptr->size) {
627 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] broken tmci box, missing font name length field\n" ));
628 : return GF_OK;
629 : }
630 13 : ISOM_DECREASE_SIZE(s, 1);
631 :
632 13 : len = gf_bs_read_u8(bs);
633 13 : if (len > ptr->size)
634 0 : len = (u32) ptr->size;
635 13 : if (len) {
636 11 : ptr->font = gf_malloc(len+1);
637 11 : if (!ptr->font) return GF_OUT_OF_MEM;
638 11 : gf_bs_read_data(bs, ptr->font, len);
639 11 : ptr->size -= len;
640 11 : ptr->font[len]=0;
641 : }
642 : return GF_OK;
643 : }
644 :
645 18 : GF_Box *tcmi_box_new()
646 : {
647 36 : ISOM_DECL_BOX_ALLOC(GF_TimeCodeMediaInformationBox, GF_QT_BOX_TYPE_TCMI);
648 18 : tmp->text_size = 12;
649 18 : tmp->text_color_red = 0xFFFF;
650 18 : tmp->text_color_green = 0xFFFF;
651 18 : tmp->text_color_blue = 0xFFFF;
652 18 : return (GF_Box *)tmp;
653 : }
654 :
655 :
656 : #ifndef GPAC_DISABLE_ISOM_WRITE
657 :
658 13 : GF_Err tcmi_box_write(GF_Box *s, GF_BitStream *bs)
659 : {
660 : GF_Err e;
661 : u32 len;
662 : GF_TimeCodeMediaInformationBox *ptr = (GF_TimeCodeMediaInformationBox *)s;
663 :
664 13 : e = gf_isom_full_box_write(s, bs);
665 13 : if (e) return e;
666 13 : gf_bs_write_u16(bs, ptr->text_font);
667 13 : gf_bs_write_u16(bs, ptr->text_face);
668 13 : gf_bs_write_u16(bs, ptr->text_size);
669 13 : gf_bs_write_u16(bs, 0);
670 13 : gf_bs_write_u16(bs, ptr->text_color_red);
671 13 : gf_bs_write_u16(bs, ptr->text_color_green);
672 13 : gf_bs_write_u16(bs, ptr->text_color_blue);
673 13 : gf_bs_write_u16(bs, ptr->back_color_red);
674 13 : gf_bs_write_u16(bs, ptr->back_color_green);
675 13 : gf_bs_write_u16(bs, ptr->back_color_blue);
676 13 : len = ptr->font ? (u32) strlen(ptr->font) : 0;
677 13 : gf_bs_write_u8(bs, len);
678 13 : if (ptr->font)
679 8 : gf_bs_write_data(bs, ptr->font, len);
680 :
681 : return GF_OK;
682 : }
683 :
684 25 : GF_Err tcmi_box_size(GF_Box *s)
685 : {
686 : GF_TimeCodeMediaInformationBox *ptr = (GF_TimeCodeMediaInformationBox *)s;
687 25 : ptr->size += 21;
688 25 : if (ptr->font)
689 14 : ptr->size += strlen(ptr->font);
690 25 : return GF_OK;
691 : }
692 :
693 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
694 :
695 :
696 28 : void fiel_box_del(GF_Box *s)
697 : {
698 28 : gf_free(s);
699 28 : }
700 :
701 :
702 26 : GF_Err fiel_box_read(GF_Box *s, GF_BitStream *bs)
703 : {
704 : GF_FieldInfoBox *ptr = (GF_FieldInfoBox *)s;
705 :
706 26 : ISOM_DECREASE_SIZE(s, 2);
707 :
708 26 : ptr->field_count = gf_bs_read_u8(bs);
709 26 : ptr->field_order = gf_bs_read_u8(bs);
710 26 : return GF_OK;
711 : }
712 :
713 28 : GF_Box *fiel_box_new()
714 : {
715 56 : ISOM_DECL_BOX_ALLOC(GF_FieldInfoBox, GF_QT_BOX_TYPE_FIEL);
716 28 : return (GF_Box *)tmp;
717 : }
718 :
719 :
720 : #ifndef GPAC_DISABLE_ISOM_WRITE
721 :
722 18 : GF_Err fiel_box_write(GF_Box *s, GF_BitStream *bs)
723 : {
724 : GF_Err e;
725 : GF_FieldInfoBox *ptr = (GF_FieldInfoBox *)s;
726 18 : e = gf_isom_box_write_header(s, bs);
727 18 : if (e) return e;
728 18 : gf_bs_write_u8(bs, ptr->field_count);
729 18 : gf_bs_write_u8(bs, ptr->field_order);
730 18 : return GF_OK;
731 : }
732 :
733 30 : GF_Err fiel_box_size(GF_Box *s)
734 : {
735 30 : s->size += 2;
736 30 : return GF_OK;
737 : }
738 :
739 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
740 :
741 :
742 16 : void gama_box_del(GF_Box *s)
743 : {
744 16 : gf_free(s);
745 16 : }
746 :
747 :
748 14 : GF_Err gama_box_read(GF_Box *s, GF_BitStream *bs)
749 : {
750 : GF_GamaInfoBox *ptr = (GF_GamaInfoBox *)s;
751 :
752 14 : ISOM_DECREASE_SIZE(s, 4);
753 :
754 14 : ptr->gama = gf_bs_read_u32(bs);
755 14 : return GF_OK;
756 : }
757 :
758 16 : GF_Box *gama_box_new()
759 : {
760 32 : ISOM_DECL_BOX_ALLOC(GF_GamaInfoBox, GF_QT_BOX_TYPE_GAMA);
761 16 : return (GF_Box *)tmp;
762 : }
763 :
764 :
765 : #ifndef GPAC_DISABLE_ISOM_WRITE
766 :
767 10 : GF_Err gama_box_write(GF_Box *s, GF_BitStream *bs)
768 : {
769 : GF_GamaInfoBox *ptr = (GF_GamaInfoBox *)s;
770 10 : GF_Err e = gf_isom_box_write_header(s, bs);
771 10 : if (e) return e;
772 10 : gf_bs_write_u32(bs, ptr->gama);
773 10 : return GF_OK;
774 : }
775 :
776 16 : GF_Err gama_box_size(GF_Box *s)
777 : {
778 16 : s->size += 4;
779 16 : return GF_OK;
780 : }
781 :
782 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
783 :
784 :
785 96 : void chrm_box_del(GF_Box *s)
786 : {
787 96 : gf_free(s);
788 96 : }
789 :
790 :
791 91 : GF_Err chrm_box_read(GF_Box *s, GF_BitStream *bs)
792 : {
793 : GF_ChromaInfoBox *ptr = (GF_ChromaInfoBox *)s;
794 :
795 91 : ISOM_DECREASE_SIZE(s, 2);
796 :
797 91 : ptr->chroma = gf_bs_read_u16(bs);
798 91 : return GF_OK;
799 : }
800 :
801 96 : GF_Box *chrm_box_new()
802 : {
803 192 : ISOM_DECL_BOX_ALLOC(GF_ChromaInfoBox, GF_QT_BOX_TYPE_CHRM);
804 96 : return (GF_Box *)tmp;
805 : }
806 :
807 :
808 : #ifndef GPAC_DISABLE_ISOM_WRITE
809 :
810 67 : GF_Err chrm_box_write(GF_Box *s, GF_BitStream *bs)
811 : {
812 : GF_ChromaInfoBox *ptr = (GF_ChromaInfoBox *)s;
813 67 : GF_Err e = gf_isom_box_write_header(s, bs);
814 67 : if (e) return e;
815 67 : gf_bs_write_u16(bs, ptr->chroma);
816 67 : return GF_OK;
817 : }
818 :
819 117 : GF_Err chrm_box_size(GF_Box *s)
820 : {
821 117 : s->size += 2;
822 117 : return GF_OK;
823 : }
824 :
825 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
826 :
827 :
828 91 : void chan_box_del(GF_Box *s)
829 : {
830 : GF_ChannelLayoutInfoBox *ptr = (GF_ChannelLayoutInfoBox *)s;
831 91 : if (ptr->audio_descs) gf_free(ptr->audio_descs);
832 91 : if (ptr->ext_data) gf_free(ptr->ext_data);
833 91 : gf_free(s);
834 91 : }
835 :
836 :
837 89 : GF_Err chan_box_read(GF_Box *s, GF_BitStream *bs)
838 : {
839 : u32 i;
840 : GF_ChannelLayoutInfoBox *ptr = (GF_ChannelLayoutInfoBox *)s;
841 :
842 89 : ISOM_DECREASE_SIZE(s, 12);
843 89 : ptr->layout_tag = gf_bs_read_u32(bs);
844 89 : ptr->bitmap = gf_bs_read_u32(bs);
845 89 : ptr->num_audio_description = gf_bs_read_u32(bs);
846 :
847 89 : if (ptr->size / 20 < ptr->num_audio_description)
848 : return GF_ISOM_INVALID_FILE;
849 :
850 89 : ptr->audio_descs = gf_malloc(sizeof(GF_AudioChannelDescription) * ptr->num_audio_description);
851 89 : if (!ptr->audio_descs) return GF_OUT_OF_MEM;
852 :
853 0 : for (i=0; i<ptr->num_audio_description; i++) {
854 0 : GF_AudioChannelDescription *adesc = &ptr->audio_descs[i];
855 0 : ISOM_DECREASE_SIZE(s, 20);
856 0 : adesc->label = gf_bs_read_u32(bs);
857 0 : adesc->flags = gf_bs_read_u32(bs);
858 0 : adesc->coordinates[0] = gf_bs_read_float(bs);
859 0 : adesc->coordinates[1] = gf_bs_read_float(bs);
860 0 : adesc->coordinates[2] = gf_bs_read_float(bs);
861 : }
862 : //avoids warning on most files
863 89 : if (ptr->size==20) {
864 0 : ptr->size=0;
865 0 : gf_bs_skip_bytes(bs, 20);
866 : }
867 89 : if (ptr->size<10000) {
868 89 : ptr->ext_data_size = (u32) ptr->size;
869 89 : ptr->ext_data = gf_malloc(sizeof(u8) * ptr->ext_data_size);
870 89 : if (!ptr->ext_data) return GF_OUT_OF_MEM;
871 89 : gf_bs_read_data(bs, (char *)ptr->ext_data, (u32) ptr->size);
872 89 : ptr->size = 0;
873 : }
874 : return GF_OK;
875 : }
876 :
877 91 : GF_Box *chan_box_new()
878 : {
879 182 : ISOM_DECL_BOX_ALLOC(GF_ChannelLayoutInfoBox, GF_QT_BOX_TYPE_CHAN);
880 91 : return (GF_Box *)tmp;
881 : }
882 :
883 :
884 : #ifndef GPAC_DISABLE_ISOM_WRITE
885 :
886 65 : GF_Err chan_box_write(GF_Box *s, GF_BitStream *bs)
887 : {
888 : GF_Err e;
889 : u32 i;
890 : GF_ChannelLayoutInfoBox *ptr = (GF_ChannelLayoutInfoBox *)s;
891 :
892 65 : e = gf_isom_full_box_write(s, bs);
893 65 : if (e) return e;
894 :
895 :
896 65 : gf_bs_write_u32(bs, ptr->layout_tag);
897 65 : gf_bs_write_u32(bs, ptr->bitmap);
898 65 : gf_bs_write_u32(bs, ptr->num_audio_description);
899 65 : for (i=0; i<ptr->num_audio_description; i++) {
900 0 : GF_AudioChannelDescription *adesc = &ptr->audio_descs[i];
901 0 : gf_bs_write_u32(bs, adesc->label);
902 0 : gf_bs_write_u32(bs, adesc->flags);
903 0 : gf_bs_write_float(bs, adesc->coordinates[0]);
904 0 : gf_bs_write_float(bs, adesc->coordinates[1]);
905 0 : gf_bs_write_float(bs, adesc->coordinates[2]);
906 : }
907 65 : if (ptr->ext_data) {
908 64 : gf_bs_write_data(bs, ptr->ext_data, ptr->ext_data_size);
909 : }
910 : return GF_OK;
911 : }
912 :
913 113 : GF_Err chan_box_size(GF_Box *s)
914 : {
915 : GF_ChannelLayoutInfoBox *ptr = (GF_ChannelLayoutInfoBox *)s;
916 113 : s->size += 12 + 20 * ptr->num_audio_description;
917 113 : if (ptr->ext_data) {
918 112 : s->size += ptr->ext_data_size;
919 : }
920 113 : return GF_OK;
921 : }
922 :
923 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
924 :
925 :
926 :
927 3 : void load_box_del(GF_Box *s)
928 : {
929 3 : gf_free(s);
930 3 : }
931 :
932 :
933 1 : GF_Err load_box_read(GF_Box *s, GF_BitStream *bs)
934 : {
935 : GF_TrackLoadBox *ptr = (GF_TrackLoadBox *)s;
936 1 : ISOM_DECREASE_SIZE(s, 16);
937 1 : ptr->preload_start_time = gf_bs_read_u32(bs);
938 1 : ptr->preload_duration = gf_bs_read_u32(bs);
939 1 : ptr->preload_flags = gf_bs_read_u32(bs);
940 1 : ptr->default_hints = gf_bs_read_u32(bs);
941 1 : return GF_OK;
942 : }
943 :
944 3 : GF_Box *load_box_new()
945 : {
946 6 : ISOM_DECL_BOX_ALLOC(GF_TrackLoadBox, GF_QT_BOX_TYPE_LOAD);
947 3 : return (GF_Box *)tmp;
948 : }
949 :
950 :
951 : #ifndef GPAC_DISABLE_ISOM_WRITE
952 :
953 1 : GF_Err load_box_write(GF_Box *s, GF_BitStream *bs)
954 : {
955 : GF_TrackLoadBox *ptr = (GF_TrackLoadBox *)s;
956 :
957 1 : GF_Err e = gf_isom_box_write_header(s, bs);
958 1 : if (e) return e;
959 :
960 1 : gf_bs_write_u32(bs, ptr->preload_start_time);
961 1 : gf_bs_write_u32(bs, ptr->preload_duration);
962 1 : gf_bs_write_u32(bs, ptr->preload_flags);
963 1 : gf_bs_write_u32(bs, ptr->default_hints);
964 1 : return GF_OK;
965 : }
966 :
967 1 : GF_Err load_box_size(GF_Box *s)
968 : {
969 1 : s->size += 16;
970 1 : return GF_OK;
971 : }
972 :
973 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
974 :
975 :
976 : #endif /*GPAC_DISABLE_ISOM*/
|