📄 box_funcs.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * 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>//Add this funct to handle incomplete files...//bytesExpected is 0 most of the time. If the file is incomplete, bytesExpected//is the number of bytes missing to parse the box...GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpected){ GF_Err ret; u64 start; //first make sure we can at least get the box size and type... //18 = size (int32) + type (int32) if (gf_bs_available(bs) < 8) { *bytesExpected = 8; return GF_ISOM_INCOMPLETE_FILE; } start = gf_bs_get_position(bs); ret = gf_isom_parse_box(outBox, bs); if (ret == GF_ISOM_INCOMPLETE_FILE) { *bytesExpected = (*outBox)->size; gf_bs_seek(bs, start); gf_isom_box_del(*outBox); *outBox = NULL; } return ret;}GF_Err gf_isom_parse_box(GF_Box **outBox, GF_BitStream *bs){ u32 type, hdr_size; u64 size, start, end; char uuid[16]; GF_Err e; GF_Box *newBox; e = GF_OK; if ((bs == NULL) || (outBox == NULL) ) return GF_BAD_PARAM; *outBox = NULL; start = gf_bs_get_position(bs); size = (u64) gf_bs_read_u32(bs); hdr_size = 4; /*fix for some boxes found in some old hinted files*/ if ((size >= 2) && (size <= 4)) { size = 4; type = GF_ISOM_BOX_TYPE_VOID; } else { /*now here's a bad thing: some files use size 0 for void atoms, some for "till end of file" indictaion..*/ if (!size) { type = gf_bs_peek_bits(bs, 32, 0); if (!isalnum((type>>24)&0xFF) || !isalnum((type>>16)&0xFF) || !isalnum((type>>8)&0xFF) || !isalnum(type&0xFF)) { size = 4; type = GF_ISOM_BOX_TYPE_VOID; } else { goto proceed_box; } } else {proceed_box: type = gf_bs_read_u32(bs); hdr_size += 4; /*no size means till end of file - EXCEPT FOR some old QuickTime boxes...*/ if (type == GF_ISOM_BOX_TYPE_TOTL) size = 12; if (!size) size = gf_bs_available(bs) + 8; } } /*handle uuid*/ memset(uuid, 0, 16); if (type == GF_ISOM_BOX_TYPE_UUID ) { gf_bs_read_data(bs, uuid, 16); hdr_size += 16; } //handle large box if (size == 1) { size = gf_bs_read_u64(bs); hdr_size += 8; } GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Read Box type %s size "LLD" start "LLD"\n", gf_4cc_to_str(type), LLD_CAST size, LLD_CAST start)); if ( size < hdr_size ) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Box size "LLD" less than box header size %d\n", LLD_CAST size, hdr_size)); return GF_ISOM_INVALID_FILE; } //OK, create the box based on the type newBox = gf_isom_box_new(type); if (!newBox) return GF_OUT_OF_MEM; //OK, init and read this box if (type==GF_ISOM_BOX_TYPE_UUID) memcpy(((GF_UUIDBox *)newBox)->uuid, uuid, 16); if (!newBox->type) newBox->type = type; end = gf_bs_available(bs); if (size - hdr_size > end ) { newBox->size = size - hdr_size - end; *outBox = newBox; return GF_ISOM_INCOMPLETE_FILE; } //we need a special reading for these boxes... if ((newBox->type == GF_ISOM_BOX_TYPE_STDP) || (newBox->type == GF_ISOM_BOX_TYPE_SDTP)) { newBox->size = size; *outBox = newBox; return GF_OK; } newBox->size = size - hdr_size; e = gf_isom_box_read(newBox, bs); newBox->size = size; end = gf_bs_get_position(bs); if (e && (e != GF_ISOM_INCOMPLETE_FILE)) { gf_isom_box_del(newBox); *outBox = NULL; GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Read Box \"%s\" failed (%s)\n", gf_4cc_to_str(type), gf_error_to_string(e))); return e; } if (end-start > size) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Box \"%s\" size "LLU" invalid (read "LLU")\n", gf_4cc_to_str(type), LLU_CAST size, LLU_CAST (end-start) )); /*let's still try to load the file since no error was notified*/ gf_bs_seek(bs, start+size); } else if (end-start < size) { u32 to_skip = (u32) (size-(end-start)); GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Box \"%s\" has %d extra bytes\n", gf_4cc_to_str(type), to_skip)); gf_bs_skip_bytes(bs, to_skip); } *outBox = newBox; return e;}GF_Err gf_isom_full_box_read(GF_Box *ptr, GF_BitStream *bs){ GF_FullBox *self = (GF_FullBox *) ptr; if (ptr->size<4) return GF_ISOM_INVALID_FILE; self->version = gf_bs_read_u8(bs); self->flags = gf_bs_read_u24(bs); ptr->size -= 4; return GF_OK;}void gf_isom_full_box_init(GF_Box *a){ GF_FullBox *ptr = (GF_FullBox *)a; if (! ptr) return; ptr->flags = 0; ptr->version = 0;}void gf_isom_box_array_del(GF_List *boxList){ u32 count, i; GF_Box *a; if (!boxList) return; count = gf_list_count(boxList); for (i = 0; i < count; i++) { a = (GF_Box *)gf_list_get(boxList, i); if (a) gf_isom_box_del(a); } gf_list_del(boxList);}GF_Err gf_isom_read_box_list(GF_Box *parent, GF_BitStream *bs, GF_Err (*add_box)(GF_Box *par, GF_Box *b)){ GF_Err e; GF_Box *a; while (parent->size) { e = gf_isom_parse_box(&a, bs); if (e) { if (a) gf_isom_box_del(a); return e; } if (parent->size < a->size) { if (a) gf_isom_box_del(a); return GF_OK; //return GF_ISOM_INVALID_FILE; } parent->size -= a->size; e = add_box(parent, a); if (e) { gf_isom_box_del(a); return e; } } return GF_OK;}//from here, for write/edit versions#ifndef GPAC_READ_ONLYGF_Err gf_isom_box_get_size(GF_Box *ptr){ ptr->size = 8; if (ptr->type == GF_ISOM_BOX_TYPE_UUID) { ptr->size += 16; } //the large size is handled during write, cause at this stage we don't know the size return GF_OK;}GF_Err gf_isom_full_box_get_size(GF_Box *ptr){ GF_Err e; e = gf_isom_box_get_size(ptr); if (e) return e; ptr->size += 4; return GF_OK;}GF_Err gf_isom_box_write_header(GF_Box *ptr, GF_BitStream *bs){ if (! bs || !ptr) return GF_BAD_PARAM; if (!ptr->size) return GF_ISOM_INVALID_FILE; if (ptr->size > 0xFFFFFFFF) { gf_bs_write_u32(bs, 1); } else { gf_bs_write_u32(bs, (u32) ptr->size); } gf_bs_write_u32(bs, ptr->type); if (ptr->type == GF_ISOM_BOX_TYPE_UUID) gf_bs_write_data(bs, (char*)((GF_UUIDBox*)ptr)->uuid, 16); if (ptr->size > 0xFFFFFFFF) gf_bs_write_u64(bs, ptr->size); return GF_OK;}GF_Err gf_isom_full_box_write(GF_Box *s, GF_BitStream *bs){ GF_Err e; GF_FullBox *ptr = (GF_FullBox *)s; e = gf_isom_box_write_header(s, bs); if (e) return e; gf_bs_write_u8(bs, ptr->version); gf_bs_write_u24(bs, ptr->flags); return GF_OK;}GF_Err gf_isom_box_array_write(GF_Box *parent, GF_List *list, GF_BitStream *bs){ u32 count, i; GF_Box *a; GF_Err e; if (!list) return GF_BAD_PARAM; count = gf_list_count(list); for (i = 0; i < count; i++) { a = (GF_Box *)gf_list_get(list, i); if (a) { e = gf_isom_box_write(a, bs); if (e) return e; } } return GF_OK;}GF_Err gf_isom_box_array_size(GF_Box *parent, GF_List *list){ GF_Err e; u32 count, i; GF_Box *a; if (! list) return GF_BAD_PARAM; count = gf_list_count(list); for (i = 0; i < count; i++) { a = (GF_Box *)gf_list_get(list, i); if (a) { e = gf_isom_box_size(a); if (e) return e; parent->size += a->size; } } return GF_OK;}#endif //GPAC_READ_ONLYGF_Box *gf_isom_box_new(u32 boxType){ GF_Box *a; switch (boxType) { case GF_ISOM_BOX_TYPE_HINT: case GF_ISOM_BOX_TYPE_DPND: case GF_ISOM_BOX_TYPE_MPOD: case GF_ISOM_BOX_TYPE_SYNC: case GF_ISOM_BOX_TYPE_IPIR: case GF_ISOM_BOX_TYPE_CHAP: a = reftype_New(); if (a) a->type = boxType; return a; case GF_ISOM_BOX_TYPE_FREE: return free_New(); case GF_ISOM_BOX_TYPE_SKIP: a = free_New(); if (a) a->type = GF_ISOM_BOX_TYPE_SKIP; return a; case GF_ISOM_BOX_TYPE_MDAT: return mdat_New(); case GF_ISOM_BOX_TYPE_MOOV: return moov_New(); case GF_ISOM_BOX_TYPE_MVHD: return mvhd_New(); case GF_ISOM_BOX_TYPE_MDHD: return mdhd_New(); case GF_ISOM_BOX_TYPE_VMHD: return vmhd_New(); case GF_ISOM_BOX_TYPE_SMHD: return smhd_New(); case GF_ISOM_BOX_TYPE_HMHD: return hmhd_New(); case GF_ISOM_BOX_TYPE_ODHD: case GF_ISOM_BOX_TYPE_CRHD: case GF_ISOM_BOX_TYPE_SDHD: case GF_ISOM_BOX_TYPE_NMHD: a = nmhd_New(); if (a) a->type = boxType; return a; case GF_ISOM_BOX_TYPE_STBL: return stbl_New(); case GF_ISOM_BOX_TYPE_DINF: return dinf_New();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -