📄 odf_code.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor 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/odf_dev.h>#include <gpac/utf.h>#define DATE_CODING_BIT_LEN 40static GFINLINE GF_Err OD_ReadUTF8String(GF_BitStream *bs, char **string, Bool isUTF8, u32 *read){ u32 len; *read = 1; len = gf_bs_read_int(bs, 8) + 1; if (!isUTF8) len *= 2; (*string) = (char *) malloc(sizeof(char)*len); if (! (*string) ) return GF_OUT_OF_MEM; gf_bs_read_data(bs, (*string), len); *read += len; return GF_OK;}static GFINLINE u32 OD_SizeUTF8String(char *string, Bool isUTF8){ if (isUTF8) return 1 + strlen(string); return 1 + 2*gf_utf8_wcslen((const unsigned short *)string);}static GFINLINE void OD_WriteUTF8String(GF_BitStream *bs, char *string, Bool isUTF8){ u32 len; if (isUTF8) { len = strlen(string); gf_bs_write_int(bs, len, 8); gf_bs_write_data(bs, string, len); } else { len = gf_utf8_wcslen((const unsigned short *)string); gf_bs_write_int(bs, len, 8); gf_bs_write_data(bs, string, len*2); }}/*use to parse strings read the length as well - Warning : the alloc is done here !!*/GF_Err gf_odf_read_url_string(GF_BitStream *bs, char **string, u32 *readBytes){ u32 length; *readBytes = 0; /*if the string is not NULL, return an error...*/ if (*string != NULL) return GF_BAD_PARAM; /*the len is always on 8 bits*/ length = gf_bs_read_int(bs, 8); *readBytes = 1; /*JLF AMD to MPEG-4 systems :) - This is not conformant at all, just hoping MPEG will accept it soon since 255bytes URL is a real pain in the neck*/ if (!length) { length = gf_bs_read_int(bs, 32); *readBytes += 4; } /*we want to use strlen to get rid of "stringLength" => we need an extra 0*/ (*string) = (char *) malloc(length + 1); if (! string) return GF_OUT_OF_MEM; gf_bs_read_data(bs, (*string), length); *readBytes += length; (*string)[length] = 0; return GF_OK;}/*writes string*/GF_Err gf_odf_write_url_string(GF_BitStream *bs, char *string){ u32 len; /*we accept NULL strings now*/ if (!string) { gf_bs_write_int(bs, 0, 8); return GF_OK; } len = strlen(string); if (len > 255) { gf_bs_write_int(bs, 0, 8); gf_bs_write_int(bs, len, 32); } else { gf_bs_write_int(bs, len, 8); } gf_bs_write_data(bs, string, len); return GF_OK;}u32 gf_odf_size_url_string(char *string){ u32 len = strlen(string); if (len>255) return len+5; return len+1;}GF_Descriptor *gf_odf_new_esd(){ GF_ESD *newDesc = (GF_ESD *) malloc(sizeof(GF_ESD)); if (!newDesc) return NULL; memset(newDesc, 0, sizeof(GF_ESD)); newDesc->IPIDataSet = gf_list_new(); newDesc->IPMPDescriptorPointers = gf_list_new(); newDesc->extensionDescriptors = gf_list_new(); newDesc->tag = GF_ODF_ESD_TAG; return (GF_Descriptor *) newDesc;}GF_Err gf_odf_del_esd(GF_ESD *esd){ GF_Err e; if (!esd) return GF_BAD_PARAM; if (esd->URLString) free(esd->URLString); if (esd->decoderConfig) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->decoderConfig); if (e) return e; } if (esd->slConfig) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->slConfig); if (e) return e; } if (esd->ipiPtr) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->ipiPtr); if (e) return e; } if (esd->qos) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->qos); if (e) return e; } if (esd->RegDescriptor) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->RegDescriptor); if (e) return e; } if (esd->langDesc) { e = gf_odf_delete_descriptor((GF_Descriptor *) esd->langDesc); if (e) return e; } e = gf_odf_delete_descriptor_list(esd->IPIDataSet); if (e) return e; e = gf_odf_delete_descriptor_list(esd->IPMPDescriptorPointers); if (e) return e; e = gf_odf_delete_descriptor_list(esd->extensionDescriptors); if (e) return e; free(esd); return GF_OK;}GF_Err AddDescriptorToESD(GF_ESD *esd, GF_Descriptor *desc){ if (!esd || !desc) return GF_BAD_PARAM; switch (desc->tag) { case GF_ODF_DCD_TAG: if (esd->decoderConfig) return GF_ODF_INVALID_DESCRIPTOR; esd->decoderConfig = (GF_DecoderConfig *) desc; break; case GF_ODF_SLC_TAG: if (esd->slConfig) return GF_ODF_INVALID_DESCRIPTOR; esd->slConfig = (GF_SLConfig *) desc; break; //the GF_ODF_ISOM_IPI_PTR_TAG is only used in the file format and replaces GF_ODF_IPI_PTR_TAG... case GF_ODF_ISOM_IPI_PTR_TAG: case GF_ODF_IPI_PTR_TAG: if (esd->ipiPtr) return GF_ODF_INVALID_DESCRIPTOR; esd->ipiPtr = (GF_IPIPtr *) desc; break; case GF_ODF_QOS_TAG: if (esd->qos) return GF_ODF_INVALID_DESCRIPTOR; esd->qos =(GF_QoS_Descriptor *) desc; break; case GF_ODF_LANG_TAG: if (esd->langDesc) return GF_ODF_INVALID_DESCRIPTOR; esd->langDesc = (GF_Language *) desc; break; case GF_ODF_CI_TAG: case GF_ODF_SCI_TAG: return gf_list_add(esd->IPIDataSet, desc); //we use the same struct for v1 and v2 IPMP DPs case GF_ODF_IPMP_PTR_TAG: return gf_list_add(esd->IPMPDescriptorPointers, desc); case GF_ODF_REG_TAG: if (esd->RegDescriptor) return GF_ODF_INVALID_DESCRIPTOR; esd->RegDescriptor =(GF_Registration *) desc; break; case GF_ODF_MUXINFO_TAG: gf_list_add(esd->extensionDescriptors, desc); break; default: if ( (desc->tag >= GF_ODF_EXT_BEGIN_TAG) && (desc->tag <= GF_ODF_EXT_END_TAG) ) { return gf_list_add(esd->extensionDescriptors, desc); } gf_odf_delete_descriptor(desc); return GF_OK; } return GF_OK;}GF_Err gf_odf_read_esd(GF_BitStream *bs, GF_ESD *esd, u32 DescSize){ GF_Err e = GF_OK; u32 ocrflag, urlflag, streamdependflag, tmp_size, nbBytes, read; if (! esd) return GF_BAD_PARAM; nbBytes = 0; esd->ESID = gf_bs_read_int(bs, 16); streamdependflag = gf_bs_read_int(bs, 1); urlflag = gf_bs_read_int(bs, 1); ocrflag = gf_bs_read_int(bs, 1); esd->streamPriority = gf_bs_read_int(bs, 5); nbBytes += 3; if (streamdependflag) { esd->dependsOnESID = gf_bs_read_int(bs, 16); nbBytes += 2; } if (urlflag) { e = gf_odf_read_url_string(bs, & esd->URLString, &read); if (e) return e; nbBytes += read; } if (ocrflag) { esd->OCRESID = gf_bs_read_int(bs, 16); nbBytes += 2; } /*fix broken sync*/// if (esd->OCRESID == esd->ESID) esd->OCRESID = 0; while (nbBytes < DescSize) { GF_Descriptor *tmp = NULL; e = gf_odf_parse_descriptor(bs, &tmp, &tmp_size); /*fix for iPod files*/ if (e==GF_ODF_INVALID_DESCRIPTOR) { nbBytes += tmp_size; if (nbBytes>DescSize) return e; gf_bs_read_int(bs, DescSize-nbBytes); return GF_OK; } if (e) return e; if (!tmp) return GF_ODF_INVALID_DESCRIPTOR; e = AddDescriptorToESD(esd, tmp); if (e) return e; nbBytes += tmp_size + gf_odf_size_field_size(tmp_size); //apple fix if (!tmp_size) nbBytes = DescSize; } if (DescSize != nbBytes) return GF_ODF_INVALID_DESCRIPTOR; return e;}GF_Err gf_odf_size_esd(GF_ESD *esd, u32 *outSize){ GF_Err e; u32 tmpSize; if (! esd) return GF_BAD_PARAM; *outSize = 0; *outSize += 3; /*this helps keeping proper sync: some people argue that OCR_ES_ID == ES_ID is a circular reference of streams. Since this is equivalent to no OCR_ES_ID, keep it that way*/// if (esd->OCRESID == esd->ESID) esd->OCRESID = 0; if (esd->dependsOnESID) *outSize += 2; if (esd->URLString) *outSize += gf_odf_size_url_string(esd->URLString); if (esd->OCRESID) *outSize += 2; if (esd->decoderConfig) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->decoderConfig, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } if (esd->slConfig) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->slConfig, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } if (esd->ipiPtr) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->ipiPtr, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } if (esd->langDesc) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->langDesc, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } e = gf_odf_size_descriptor_list(esd->IPIDataSet, outSize); if (e) return e; e = gf_odf_size_descriptor_list(esd->IPMPDescriptorPointers, outSize); if (e) return e; if (esd->qos) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->qos, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } if (esd->RegDescriptor) { e = gf_odf_size_descriptor((GF_Descriptor *) esd->RegDescriptor, &tmpSize); if (e) return e; *outSize += tmpSize + gf_odf_size_field_size(tmpSize); } return gf_odf_size_descriptor_list(esd->extensionDescriptors, outSize);}GF_Err gf_odf_write_esd(GF_BitStream *bs, GF_ESD *esd){ GF_Err e; u32 size; if (! esd) return GF_BAD_PARAM; e = gf_odf_size_descriptor((GF_Descriptor *)esd, &size); if (e) return e; e = gf_odf_write_base_descriptor(bs, esd->tag, size); if (e) return e; gf_bs_write_int(bs, esd->ESID, 16); gf_bs_write_int(bs, esd->dependsOnESID ? 1 : 0, 1); gf_bs_write_int(bs, esd->URLString != NULL ? 1 : 0, 1); gf_bs_write_int(bs, esd->OCRESID ? 1 : 0, 1); gf_bs_write_int(bs, esd->streamPriority, 5); if (esd->dependsOnESID) { gf_bs_write_int(bs, esd->dependsOnESID, 16); } if (esd->URLString) { e = gf_odf_write_url_string(bs, esd->URLString); if (e) return e; } if (esd->OCRESID) { gf_bs_write_int(bs, esd->OCRESID, 16); } if (esd->decoderConfig) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->decoderConfig); if (e) return e; } if (esd->slConfig) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->slConfig); if (e) return e; } if (esd->ipiPtr) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->ipiPtr); if (e) return e; } if (esd->langDesc) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->langDesc); if (e) return e; } e = gf_odf_write_descriptor_list(bs, esd->IPIDataSet); if (e) return e; e = gf_odf_write_descriptor_list(bs, esd->IPMPDescriptorPointers); if (e) return e; if (esd->qos) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->qos); if (e) return e; } if (esd->RegDescriptor) { e = gf_odf_write_descriptor(bs, (GF_Descriptor *) esd->RegDescriptor); if (e) return e; } return gf_odf_write_descriptor_list(bs, esd->extensionDescriptors);}GF_Descriptor *gf_odf_new_iod(){ GF_InitialObjectDescriptor *newDesc = (GF_InitialObjectDescriptor *) malloc(sizeof(GF_InitialObjectDescriptor)); if (!newDesc) return NULL; memset(newDesc, 0, sizeof(GF_InitialObjectDescriptor)); newDesc->ESDescriptors = gf_list_new(); newDesc->OCIDescriptors = gf_list_new(); newDesc->IPMP_Descriptors = gf_list_new(); newDesc->extensionDescriptors = gf_list_new(); newDesc->tag = GF_ODF_IOD_TAG; return (GF_Descriptor *) newDesc;}GF_Err gf_odf_del_iod(GF_InitialObjectDescriptor *iod){ GF_Err e; if (!iod) return GF_BAD_PARAM; if (iod->URLString) free(iod->URLString); e = gf_odf_delete_descriptor_list(iod->ESDescriptors); if (e) return e; e = gf_odf_delete_descriptor_list(iod->OCIDescriptors); if (e) return e; e = gf_odf_delete_descriptor_list(iod->IPMP_Descriptors); if (e) return e; e = gf_odf_delete_descriptor_list(iod->extensionDescriptors); if (e) return e; if (iod->IPMPToolList) gf_odf_delete_descriptor((GF_Descriptor *) iod->IPMPToolList); free(iod); return GF_OK;}GF_Err AddDescriptorToIOD(GF_InitialObjectDescriptor *iod, GF_Descriptor *desc){ if (!iod || !desc) return GF_BAD_PARAM; switch (desc->tag) { case GF_ODF_ESD_TAG: return gf_list_add(iod->ESDescriptors, desc); //we use the same struct for v1 and v2 IPMP DPs case GF_ODF_IPMP_PTR_TAG: /*IPMPX*/ case GF_ODF_IPMP_TAG: return gf_list_add(iod->IPMP_Descriptors, desc); /*IPMPX*/ case GF_ODF_IPMP_TL_TAG: if (iod->IPMPToolList) gf_odf_desc_del((GF_Descriptor *)iod->IPMPToolList); iod->IPMPToolList = (GF_IPMP_ToolList *)desc; return GF_OK; default: break; } if ( (desc->tag >= GF_ODF_OCI_BEGIN_TAG) && (desc->tag <= GF_ODF_OCI_END_TAG) ) return gf_list_add(iod->OCIDescriptors, desc); if ( (desc->tag >= GF_ODF_EXT_BEGIN_TAG) && (desc->tag <= GF_ODF_EXT_END_TAG) ) return gf_list_add(iod->extensionDescriptors, desc); return GF_BAD_PARAM;}GF_Err gf_odf_read_iod(GF_BitStream *bs, GF_InitialObjectDescriptor *iod, u32 DescSize){ GF_Err e; u32 reserved, urlflag, read;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -