| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Authors: Cyril Concolato / Jean Le Feuvre | |
| * Copyright (c) Telecom ParisTech 2005-2019 | |
| * All rights reserved | |
| * | |
| * This file is part of GPAC / ISO Media File Format sub-project | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include <gpac/internal/isomedia_dev.h> | |
| #include <gpac/constants.h> | |
| #ifndef GPAC_DISABLE_ISOM | |
| GF_Box *meta_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_MetaBox, GF_ISOM_BOX_TYPE_META); | |
| tmp->child_boxes = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| void meta_reset(GF_Box *s) | |
| { | |
| GF_MetaBox *ptr = (GF_MetaBox *)s; | |
| if (ptr == NULL) return; | |
| //destroy all boxes | |
| if (ptr->child_boxes) gf_isom_box_array_del(ptr->child_boxes); | |
| ptr->child_boxes = NULL; | |
| //reset pointers (destroyed above) | |
| ptr->handler = NULL; | |
| ptr->primary_resource = NULL; | |
| ptr->file_locations = NULL; | |
| ptr->item_locations = NULL; | |
| ptr->protections = NULL; | |
| ptr->item_infos = NULL; | |
| ptr->IPMP_control = NULL; | |
| ptr->item_refs = NULL; | |
| ptr->item_props = NULL; | |
| ptr->groups_list = NULL; | |
| } | |
| void meta_box_del(GF_Box *s) | |
| { | |
| meta_reset(s); | |
| gf_free(s); | |
| } | |
| GF_Err meta_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem) | |
| { | |
| GF_MetaBox *ptr = (GF_MetaBox *)s; | |
| switch (a->type) { | |
| case GF_ISOM_BOX_TYPE_HDLR: | |
| BOX_FIELD_ASSIGN(handler, GF_HandlerBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_PITM: | |
| BOX_FIELD_ASSIGN(primary_resource, GF_PrimaryItemBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_DINF: | |
| BOX_FIELD_ASSIGN(file_locations, GF_DataInformationBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_ILOC: | |
| BOX_FIELD_ASSIGN(item_locations, GF_ItemLocationBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_IPRO: | |
| BOX_FIELD_ASSIGN(protections, GF_ItemProtectionBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_IINF: | |
| BOX_FIELD_ASSIGN(item_infos, GF_ItemInfoBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_IREF: | |
| BOX_FIELD_ASSIGN(item_refs, GF_ItemReferenceBox); | |
| break; | |
| case GF_ISOM_BOX_TYPE_IPRP: | |
| BOX_FIELD_ASSIGN(item_props, GF_ItemPropertiesBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_GRPL: | |
| BOX_FIELD_ASSIGN(groups_list, GF_GroupListBox) | |
| break; | |
| case GF_ISOM_BOX_TYPE_KEYS: | |
| BOX_FIELD_ASSIGN(keys, GF_MetaKeysBox) | |
| ptr->keys->meta = ptr; | |
| break; | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err meta_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_MetaBox *ptr = (GF_MetaBox *)s; | |
| u64 pos = gf_bs_get_position(bs); | |
| u64 size = s->size; | |
| //probe 4->8 bytes, if equal to one of the following this is a QT meta | |
| u32 qt_type = (pos>8) ? gf_bs_peek_bits(bs, 32, 4) : 0; | |
| switch (qt_type) { | |
| case GF_4CC('h', 'd', 'l', 'r'): | |
| case GF_4CC('m', 'h', 'd', 'r'): | |
| case GF_4CC('k', 'e', 'y', 's'): | |
| case GF_4CC('i', 'l', 's', 't'): | |
| case GF_4CC('c', 't', 'r', 'y'): | |
| case GF_4CC('l', 'a', 'n', 'g'): | |
| break; | |
| default: | |
| qt_type = 0; | |
| break; | |
| } | |
| GF_Err e = GF_EOS; | |
| if (!qt_type) { | |
| ISOM_DECREASE_SIZE(s, 4) | |
| ptr->version = gf_bs_read_u8(bs); | |
| ptr->flags = gf_bs_read_u24(bs); | |
| e = gf_isom_box_array_read(s, bs); | |
| } | |
| /*try to hack around QT files which don't use a full box for meta, reparse*/ | |
| if (e && (pos>8) ) { | |
| gf_bs_seek(bs, pos); | |
| meta_reset(s); | |
| s->size = size+4; | |
| ptr->is_qt = GF_TRUE; | |
| e = gf_isom_box_array_read(s, bs); | |
| } | |
| return e; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err meta_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_MetaBox *ptr = (GF_MetaBox *)s; | |
| if (ptr->write_qt) { | |
| return gf_isom_box_write_header(s, bs); | |
| } | |
| return gf_isom_full_box_write(s, bs); | |
| } | |
| GF_Err meta_box_size(GF_Box *s) | |
| { | |
| u32 pos=0; | |
| GF_MetaBox *ptr = (GF_MetaBox *)s; | |
| gf_isom_check_position(s, (GF_Box *)ptr->handler, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->primary_resource, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->file_locations, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->item_locations, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->protections, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->item_infos, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->item_refs, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->item_props, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->groups_list, &pos); | |
| gf_isom_check_position(s, (GF_Box *)ptr->keys, &pos); | |
| if (!ptr->write_qt) | |
| s->size+=4; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *xml_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_XMLBox, GF_ISOM_BOX_TYPE_XML); | |
| return (GF_Box *)tmp; | |
| } | |
| void xml_box_del(GF_Box *s) | |
| { | |
| GF_XMLBox *ptr = (GF_XMLBox *)s; | |
| if (ptr == NULL) return; | |
| if (ptr->xml) gf_free(ptr->xml); | |
| gf_free(ptr); | |
| } | |
| GF_Err xml_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_XMLBox *ptr = (GF_XMLBox *)s; | |
| return gf_isom_read_null_terminated_string(s, bs, s->size, &ptr->xml); | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err xml_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| GF_XMLBox *ptr = (GF_XMLBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| if (ptr->xml) gf_bs_write_data(bs, ptr->xml, (u32) strlen(ptr->xml)); | |
| gf_bs_write_u8(bs, 0); | |
| return GF_OK; | |
| } | |
| GF_Err xml_box_size(GF_Box *s) | |
| { | |
| GF_XMLBox *ptr = (GF_XMLBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| ptr->size += (ptr->xml ? strlen(ptr->xml) : 0) + 1; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *bxml_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_BinaryXMLBox, GF_ISOM_BOX_TYPE_BXML); | |
| return (GF_Box *)tmp; | |
| } | |
| void bxml_box_del(GF_Box *s) | |
| { | |
| GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s; | |
| if (ptr == NULL) return; | |
| if (ptr->data) gf_free(ptr->data); | |
| gf_free(ptr); | |
| } | |
| GF_Err bxml_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s; | |
| ptr->data_length = (u32)(ptr->size); | |
| ptr->data = (char*)gf_malloc(sizeof(char)*ptr->data_length); | |
| if (!ptr->data) return GF_OUT_OF_MEM; | |
| gf_bs_read_data(bs, ptr->data, ptr->data_length); | |
| return GF_OK; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err bxml_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| if (ptr->data_length) gf_bs_write_data(bs, ptr->data, ptr->data_length); | |
| return GF_OK; | |
| } | |
| GF_Err bxml_box_size(GF_Box *s) | |
| { | |
| GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| ptr->size += ptr->data_length; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *iloc_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemLocationBox, GF_ISOM_BOX_TYPE_ILOC); | |
| tmp->location_entries = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| void iloc_entry_del(GF_ItemLocationEntry *location) | |
| { | |
| u32 j, extent_count; | |
| extent_count = gf_list_count(location->extent_entries); | |
| for (j = 0; j < extent_count; j++) { | |
| GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j); | |
| gf_free(extent); | |
| } | |
| gf_list_del(location->extent_entries); | |
| gf_free(location); | |
| } | |
| void iloc_box_del(GF_Box *s) | |
| { | |
| u32 i, item_count; | |
| GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; | |
| if (ptr == NULL) return; | |
| item_count = gf_list_count(ptr->location_entries); | |
| for (i = 0; i < item_count; i++) { | |
| GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i); | |
| iloc_entry_del(location); | |
| } | |
| gf_list_del(ptr->location_entries); | |
| gf_free(ptr); | |
| } | |
| GF_Err iloc_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| u32 item_count, extent_count, i, j; | |
| GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| ptr->offset_size = gf_bs_read_int(bs, 4); | |
| ptr->length_size = gf_bs_read_int(bs, 4); | |
| ptr->base_offset_size = gf_bs_read_int(bs, 4); | |
| if (ptr->version == 1 || ptr->version == 2) { | |
| ptr->index_size = gf_bs_read_int(bs, 4); | |
| } else { | |
| gf_bs_read_int(bs, 4); | |
| } | |
| if (ptr->version < 2) { | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| item_count = gf_bs_read_u16(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| item_count = gf_bs_read_u32(bs); | |
| } | |
| u32 base_size; | |
| if (ptr->version < 2) { | |
| base_size=2; | |
| } else { | |
| base_size=4; | |
| } | |
| if (ptr->version == 1 || ptr->version == 2) { | |
| base_size+=2; | |
| } | |
| if ((u64)base_size*item_count>ptr->size) { | |
| ISOM_DECREASE_SIZE(ptr, (u64)base_size*item_count) | |
| } | |
| for (i = 0; i < item_count; i++) { | |
| u32 bpe; | |
| GF_ItemLocationEntry *location_entry; | |
| GF_SAFEALLOC(location_entry, GF_ItemLocationEntry); | |
| if (!location_entry) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->location_entries, location_entry); | |
| if (ptr->version < 2) { | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| location_entry->item_ID = gf_bs_read_u16(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| location_entry->item_ID = gf_bs_read_u32(bs); | |
| } | |
| if (ptr->version == 1 || ptr->version == 2) { | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| location_entry->construction_method = gf_bs_read_u16(bs); | |
| } | |
| else { | |
| location_entry->construction_method = 0; | |
| } | |
| ISOM_DECREASE_SIZE(ptr, (2 + ptr->base_offset_size) ) | |
| location_entry->data_reference_index = gf_bs_read_u16(bs); | |
| location_entry->base_offset = gf_bs_read_int(bs, 8*ptr->base_offset_size); | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| location_entry->original_base_offset = location_entry->base_offset; | |
| #endif | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| extent_count = gf_bs_read_u16(bs); | |
| location_entry->extent_entries = gf_list_new(); | |
| bpe = (ptr->offset_size+ptr->length_size); | |
| if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) | |
| bpe = ptr->index_size; | |
| if ((u64)bpe * extent_count > ptr->size) { | |
| ISOM_DECREASE_SIZE(ptr, (u64)bpe * extent_count) | |
| } | |
| for (j = 0; j < extent_count; j++) { | |
| GF_ItemExtentEntry *extent_entry; | |
| GF_SAFEALLOC(extent_entry, GF_ItemExtentEntry); | |
| if (!extent_entry) return GF_OUT_OF_MEM; | |
| gf_list_add(location_entry->extent_entries, extent_entry); | |
| if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) { | |
| ISOM_DECREASE_SIZE(ptr, ptr->index_size) | |
| extent_entry->extent_index = gf_bs_read_int(bs, 8 * ptr->index_size); | |
| } | |
| else { | |
| extent_entry->extent_index = 0; | |
| } | |
| ISOM_DECREASE_SIZE(ptr, (ptr->offset_size+ptr->length_size) ) | |
| extent_entry->extent_offset = gf_bs_read_int(bs, 8*ptr->offset_size); | |
| extent_entry->extent_length = gf_bs_read_int(bs, 8*ptr->length_size); | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| extent_entry->original_extent_offset = extent_entry->extent_offset; | |
| #endif | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err iloc_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| u32 i, j, item_count, extent_count; | |
| GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_int(bs, ptr->offset_size, 4); | |
| gf_bs_write_int(bs, ptr->length_size, 4); | |
| gf_bs_write_int(bs, ptr->base_offset_size, 4); | |
| gf_bs_write_int(bs, ptr->index_size, 4); | |
| item_count = gf_list_count(ptr->location_entries); | |
| if (ptr->version < 2) { | |
| gf_bs_write_u16(bs, item_count); | |
| } | |
| else { | |
| gf_bs_write_u32(bs, item_count); | |
| } | |
| for (i = 0; i < item_count; i++) { | |
| GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i); | |
| if (ptr->version < 2) { | |
| gf_bs_write_u16(bs, location->item_ID); | |
| } | |
| else { | |
| gf_bs_write_u32(bs, location->item_ID); | |
| } | |
| if (ptr->version == 1 || ptr->version == 2) { | |
| gf_bs_write_u16(bs, location->construction_method); | |
| } | |
| gf_bs_write_u16(bs, location->data_reference_index); | |
| gf_bs_write_long_int(bs, location->base_offset, 8*ptr->base_offset_size); | |
| extent_count = gf_list_count(location->extent_entries); | |
| gf_bs_write_u16(bs, extent_count); | |
| for (j=0; j<extent_count; j++) { | |
| GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j); | |
| if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) { | |
| gf_bs_write_long_int(bs, extent->extent_index, 8 * ptr->index_size); | |
| } | |
| gf_bs_write_long_int(bs, extent->extent_offset, 8*ptr->offset_size); | |
| gf_bs_write_long_int(bs, extent->extent_length, 8*ptr->length_size); | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err iloc_box_size(GF_Box *s) | |
| { | |
| u32 i, item_count, extent_count; | |
| GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| if (ptr->index_size) { | |
| ptr->version = 1; | |
| } | |
| item_count = gf_list_count(ptr->location_entries); | |
| for (i = 0; i < item_count; i++) { | |
| GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i); | |
| if (location->construction_method) { | |
| ptr->version = 1; | |
| } | |
| if (location->item_ID > 0xFFFF) { | |
| ptr->version = 2; | |
| } | |
| } | |
| ptr->size += 4; | |
| if (ptr->version == 2) { | |
| ptr->size += 2; // 32 bits item count instead of 16 bits | |
| } | |
| for (i = 0; i < item_count; i++) { | |
| GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i); | |
| extent_count = gf_list_count(location->extent_entries); | |
| ptr->size += 6 + ptr->base_offset_size + extent_count*(ptr->offset_size + ptr->length_size); | |
| if (ptr->version == 2) { | |
| ptr->size += 2; //32 bits item ID instead of 16 bits | |
| } | |
| if (ptr->version == 1 || ptr->version == 2) { | |
| ptr->size += 2; // construction_method | |
| ptr->size += extent_count*ptr->index_size; | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *pitm_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_PrimaryItemBox, GF_ISOM_BOX_TYPE_PITM); | |
| return (GF_Box *)tmp; | |
| } | |
| void pitm_box_del(GF_Box *s) | |
| { | |
| GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s; | |
| if (ptr == NULL) return; | |
| gf_free(ptr); | |
| } | |
| GF_Err pitm_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| ptr->item_ID = gf_bs_read_u16(bs); | |
| return GF_OK; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err pitm_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_u16(bs, ptr->item_ID); | |
| return GF_OK; | |
| } | |
| GF_Err pitm_box_size(GF_Box *s) | |
| { | |
| GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| ptr->size += 2; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *ipro_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemProtectionBox, GF_ISOM_BOX_TYPE_IPRO); | |
| tmp->protection_information = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| void ipro_box_del(GF_Box *s) | |
| { | |
| GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s; | |
| if (ptr == NULL) return; | |
| gf_list_del(ptr->protection_information); | |
| gf_free(ptr); | |
| } | |
| GF_Err ipro_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem) | |
| { | |
| GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s; | |
| if (a->type == GF_ISOM_BOX_TYPE_SINF) { | |
| BOX_FIELD_LIST_ASSIGN(protection_information) | |
| return GF_OK; | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err ipro_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| ISOM_DECREASE_SIZE(s, 2) | |
| gf_bs_read_u16(bs); | |
| return gf_isom_box_array_read(s, bs); | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err ipro_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| u32 count; | |
| GF_Err e; | |
| GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| count = gf_list_count(ptr->protection_information); | |
| gf_bs_write_u16(bs, count); | |
| return GF_OK; | |
| } | |
| GF_Err ipro_box_size(GF_Box *s) | |
| { | |
| GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s; | |
| u32 pos=0; | |
| gf_isom_check_position_list(s, ptr->protection_information, &pos); | |
| s->size += 2; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *infe_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemInfoEntryBox, GF_ISOM_BOX_TYPE_INFE); | |
| return (GF_Box *)tmp; | |
| } | |
| void infe_box_del(GF_Box *s) | |
| { | |
| GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s; | |
| if (ptr == NULL) return; | |
| if (ptr->item_name) gf_free(ptr->item_name); | |
| if (ptr->full_path) gf_free(ptr->full_path); | |
| if (ptr->content_type) gf_free(ptr->content_type); | |
| if (ptr->content_encoding) gf_free(ptr->content_encoding); | |
| gf_free(ptr); | |
| } | |
| GF_Err infe_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| char *buf; | |
| u32 buf_len, i, string_len, string_start; | |
| GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 4); | |
| ptr->item_ID = gf_bs_read_u16(bs); | |
| ptr->item_protection_index = gf_bs_read_u16(bs); | |
| if (ptr->version == 2) { | |
| ISOM_DECREASE_SIZE(ptr, 4); | |
| ptr->item_type = gf_bs_read_u32(bs); | |
| } | |
| buf_len = (u32) (ptr->size); | |
| buf = (char*)gf_malloc(buf_len); | |
| if (!buf) return GF_OUT_OF_MEM; | |
| if (buf_len != gf_bs_read_data(bs, buf, buf_len)) { | |
| gf_free(buf); | |
| return GF_ISOM_INVALID_FILE; | |
| } | |
| string_len = 1; | |
| string_start = 0; | |
| for (i = 0; i < buf_len; i++) { | |
| if (buf[i] == 0) { | |
| if (!ptr->item_name) { | |
| ptr->item_name = (char*)gf_malloc(sizeof(char)*string_len); | |
| if (!ptr->item_name) return GF_OUT_OF_MEM; | |
| memcpy(ptr->item_name, buf+string_start, string_len); | |
| } else if (!ptr->content_type) { | |
| ptr->content_type = (char*)gf_malloc(sizeof(char)*string_len); | |
| if (!ptr->content_type) return GF_OUT_OF_MEM; | |
| memcpy(ptr->content_type, buf+string_start, string_len); | |
| } else if (!ptr->content_encoding) { | |
| ptr->content_encoding = (char*)gf_malloc(sizeof(char)*string_len); | |
| if (!ptr->content_encoding) return GF_OUT_OF_MEM; | |
| memcpy(ptr->content_encoding, buf+string_start, string_len); | |
| } else { | |
| //we could throw an error but we silently accept this infe | |
| break; | |
| } | |
| string_start += string_len; | |
| string_len = 0; | |
| if (ptr->content_encoding && ptr->version == 1) { | |
| break; | |
| } | |
| } | |
| string_len++; | |
| } | |
| gf_free(buf); | |
| if (!ptr->item_name || (!ptr->content_type && ptr->version < 2)) { | |
| GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[isoff] Infe without name or content type !\n")); | |
| } | |
| if (ptr->item_name && !ptr->item_name[0]) { | |
| gf_free(ptr->item_name); | |
| ptr->item_name = NULL; | |
| } | |
| if (ptr->content_type && !ptr->content_type[0]) { | |
| gf_free(ptr->content_type); | |
| ptr->content_type = NULL; | |
| } | |
| if (ptr->content_encoding && !ptr->content_encoding[0]) { | |
| gf_free(ptr->content_encoding); | |
| ptr->content_encoding = NULL; | |
| } | |
| return GF_OK; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err infe_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| u32 len; | |
| GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| if (ptr->version == 3) { | |
| gf_bs_write_u32(bs, ptr->item_ID); | |
| } | |
| else { | |
| gf_bs_write_u16(bs, ptr->item_ID); | |
| } | |
| gf_bs_write_u16(bs, ptr->item_protection_index); | |
| if (ptr->version >= 2) { | |
| gf_bs_write_u32(bs, ptr->item_type); | |
| } | |
| if (ptr->item_name) { | |
| len = (u32) strlen(ptr->item_name)+1; | |
| gf_bs_write_data(bs, ptr->item_name, len); | |
| } else { | |
| gf_bs_write_byte(bs, 0, 1); | |
| } | |
| if (ptr->item_type == GF_META_ITEM_TYPE_MIME || ptr->item_type == GF_META_ITEM_TYPE_URI) { | |
| if (ptr->content_type) { | |
| len = (u32)strlen(ptr->content_type) + 1; | |
| gf_bs_write_data(bs, ptr->content_type, len); | |
| } | |
| else { | |
| gf_bs_write_byte(bs, 0, 1); | |
| } | |
| } | |
| if (ptr->item_type == GF_META_ITEM_TYPE_MIME) { | |
| if (ptr->content_encoding) { | |
| len = (u32)strlen(ptr->content_encoding) + 1; | |
| gf_bs_write_data(bs, ptr->content_encoding, len); | |
| } | |
| else { | |
| gf_bs_write_byte(bs, 0, 1); | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err infe_box_size(GF_Box *s) | |
| { | |
| GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| if (ptr->item_type) { | |
| ptr->version = 2; | |
| if (ptr->item_ID > 0xFFFF) { | |
| ptr->version = 3; | |
| } | |
| } | |
| else { | |
| ptr->version = 0; | |
| } | |
| ptr->size += 4; | |
| if (ptr->version == 3) { | |
| ptr->size += 2; // item_ID on 32 bits (+2 bytes) | |
| } | |
| if (ptr->version >= 2) { | |
| ptr->size += 4; // item_type size | |
| } | |
| if (ptr->item_name) ptr->size += strlen(ptr->item_name)+1; | |
| else ptr->size += 1; | |
| if (ptr->item_type == GF_META_ITEM_TYPE_MIME || ptr->item_type == GF_META_ITEM_TYPE_URI) { | |
| if (ptr->content_type) ptr->size += strlen(ptr->content_type) + 1; | |
| else ptr->size += 1; | |
| } | |
| if (ptr->item_type == GF_META_ITEM_TYPE_MIME) { | |
| if (ptr->content_encoding) ptr->size += strlen(ptr->content_encoding) + 1; | |
| else ptr->size += 1; | |
| } | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *iinf_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemInfoBox, GF_ISOM_BOX_TYPE_IINF); | |
| tmp->item_infos = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| void iinf_box_del(GF_Box *s) | |
| { | |
| GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s; | |
| if (ptr == NULL) return; | |
| gf_list_del(ptr->item_infos); | |
| gf_free(ptr); | |
| } | |
| GF_Err iinf_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem) | |
| { | |
| GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s; | |
| if (a->type == GF_ISOM_BOX_TYPE_INFE) { | |
| BOX_FIELD_LIST_ASSIGN(item_infos) | |
| return GF_OK; | |
| } else { | |
| return GF_OK; | |
| } | |
| } | |
| GF_Err iinf_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s; | |
| if (ptr->version == 0) { | |
| ISOM_DECREASE_SIZE(s, 2) | |
| gf_bs_read_u16(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(s, 4) | |
| gf_bs_read_u32(bs); | |
| } | |
| return gf_isom_box_array_read(s, bs); | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err iinf_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| u32 count; | |
| GF_Err e; | |
| GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| count = gf_list_count(ptr->item_infos); | |
| if (ptr->version == 0) | |
| gf_bs_write_u16(bs, count); | |
| else | |
| gf_bs_write_u32(bs, count); | |
| return GF_OK; | |
| } | |
| GF_Err iinf_box_size(GF_Box *s) | |
| { | |
| u32 pos=0; | |
| GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s; | |
| if (!s) return GF_BAD_PARAM; | |
| ptr->size += (ptr->version == 0) ? 2 : 4; | |
| gf_isom_check_position_list(s, ptr->item_infos, &pos); | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Err iref_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem) | |
| { | |
| GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s; | |
| BOX_FIELD_LIST_ASSIGN(references) | |
| return GF_OK; | |
| } | |
| void iref_box_del(GF_Box *s) | |
| { | |
| GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s; | |
| if (ptr == NULL) return; | |
| gf_list_del(ptr->references); | |
| gf_free(ptr); | |
| } | |
| GF_Err iref_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| return gf_isom_box_array_read(s, bs); | |
| } | |
| GF_Box *iref_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemReferenceBox, GF_ISOM_BOX_TYPE_IREF); | |
| tmp->references = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err iref_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| return gf_isom_full_box_write(s, bs); | |
| } | |
| GF_Err iref_box_size(GF_Box *s) | |
| { | |
| u32 pos=0; | |
| GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s; | |
| gf_isom_check_position_list(s, ptr->references, &pos); | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| void ireftype_box_del(GF_Box *s) | |
| { | |
| GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s; | |
| if (!ptr) return; | |
| if (ptr->to_item_IDs) gf_free(ptr->to_item_IDs); | |
| gf_free(ptr); | |
| } | |
| GF_Err ireftype_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| u32 i; | |
| GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ptr->from_item_id = gf_bs_read_u16(bs); | |
| ptr->reference_count = gf_bs_read_u16(bs); | |
| if (ptr->size / 2 < ptr->reference_count) | |
| return GF_ISOM_INVALID_FILE; | |
| ptr->to_item_IDs = (u32 *)gf_malloc(ptr->reference_count * sizeof(u32)); | |
| if (!ptr->to_item_IDs) return GF_OUT_OF_MEM; | |
| for (i=0; i < ptr->reference_count; i++) { | |
| ISOM_DECREASE_SIZE(ptr, 2) | |
| ptr->to_item_IDs[i] = gf_bs_read_u16(bs); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Box *ireftype_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_ItemReferenceTypeBox, GF_ISOM_BOX_TYPE_REFI); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err ireftype_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| u32 i; | |
| GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s; | |
| ptr->type = ptr->reference_type; | |
| e = gf_isom_box_write_header(s, bs); | |
| ptr->type = GF_ISOM_BOX_TYPE_REFI; | |
| if (e) return e; | |
| gf_bs_write_u16(bs, ptr->from_item_id); | |
| gf_bs_write_u16(bs, ptr->reference_count); | |
| for (i = 0; i < ptr->reference_count; i++) { | |
| gf_bs_write_u16(bs, ptr->to_item_IDs[i]); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err ireftype_box_size(GF_Box *s) | |
| { | |
| GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s; | |
| ptr->size += 4 + (ptr->reference_count * sizeof(u16)); | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| GF_Box *amve_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_AmbientViewingEnvBox, GF_ISOM_BOX_TYPE_AMVE); | |
| return (GF_Box *)tmp; | |
| } | |
| void amve_box_del(GF_Box *s) | |
| { | |
| GF_AmbientViewingEnvBox *ptr = (GF_AmbientViewingEnvBox*)s; | |
| if (ptr == NULL) return; | |
| gf_free(ptr); | |
| } | |
| GF_Err amve_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_AmbientViewingEnvBox *ptr = (GF_AmbientViewingEnvBox*)s; | |
| ptr->ambient_illuminance = gf_bs_read_int(bs, 32); | |
| ptr->ambient_light_x = gf_bs_read_int(bs, 16); | |
| ptr->ambient_light_y = gf_bs_read_int(bs, 16); | |
| return GF_OK; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err amve_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_AmbientViewingEnvBox *ptr = (GF_AmbientViewingEnvBox *)s; | |
| GF_Err e = gf_isom_box_write_header(s, bs); | |
| if (e) return e; | |
| gf_bs_write_int(bs, ptr->ambient_illuminance, 32); | |
| gf_bs_write_int(bs, ptr->ambient_light_x, 16); | |
| gf_bs_write_int(bs, ptr->ambient_light_y, 16); | |
| return GF_OK; | |
| } | |
| GF_Err amve_box_size(GF_Box *s) | |
| { | |
| s->size += 8; | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| #endif /*GPAC_DISABLE_ISOM*/ | |