GF_EXPORT GF_Err gf_odf_desc_list_read(char *raw_list, u32 raw_size, GF_List *descList) { GF_BitStream *bs; u32 size, desc_size; GF_Descriptor *desc; GF_Err e = GF_OK; if (!descList || !raw_list || !raw_size) return GF_BAD_PARAM; bs = gf_bs_new(raw_list, raw_size, GF_BITSTREAM_READ); if (!bs) return GF_OUT_OF_MEM; size = 0; while (size < raw_size) { e = gf_odf_parse_descriptor(bs, &desc, &desc_size); if (e) goto exit; gf_list_add(descList, desc); size += desc_size + gf_odf_size_field_size(desc_size); } exit: //then delete our bitstream gf_bs_del(bs); if (size != raw_size) e = GF_ODF_INVALID_DESCRIPTOR; return e; }
//use this function to decode a standalone descriptor //the desc MUST be formatted with tag and size field!!! GF_EXPORT GF_Err gf_odf_desc_read(char *raw_desc, u32 descSize, GF_Descriptor **outDesc) { GF_Err e; u32 size; GF_BitStream *bs; if (!raw_desc || !descSize) return GF_BAD_PARAM; bs = gf_bs_new(raw_desc, (u64)descSize, GF_BITSTREAM_READ); if (!bs) return GF_OUT_OF_MEM; size = 0; e = gf_odf_parse_descriptor(bs, outDesc, &size); //the size dosn't have the header in it size += gf_odf_size_field_size(size); /* if (size != descSize) { if (*outDesc) gf_odf_delete_descriptor(*outDesc); *outDesc = NULL; e = GF_ODF_INVALID_DESCRIPTOR; } */ gf_bs_del(bs); return e; }
GF_Err gf_odf_read_esd_update(GF_BitStream *bs, GF_ESDUpdate *esdUp, u32 gf_odf_size_command) { GF_Descriptor *tmp; u32 tmpSize = 0, nbBits = 0; GF_Err e = GF_OK; if (!esdUp) return GF_BAD_PARAM; esdUp->ODID = gf_bs_read_int(bs, 10); nbBits += 10; //very tricky, we're at the bit level here... while (1) { e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize); if (e) return e; e = AddToESDUpdate(esdUp, tmp); if (e) return e; nbBits += (tmpSize + gf_odf_size_field_size(tmpSize)) * 8; //our com is aligned, so nbBits is between (gf_odf_size_command-1)*8 and gf_odf_size_command*8 if (((nbBits >(gf_odf_size_command - 1) * 8) && (nbBits <= gf_odf_size_command * 8)) || (nbBits > gf_odf_size_command * 8)) { //this one is a security break break; } } if (nbBits > gf_odf_size_command * 8) return GF_ODF_INVALID_COMMAND; //Align our bitstream nbBits += gf_bs_align(bs); if (nbBits != gf_odf_size_command * 8) return GF_ODF_INVALID_COMMAND; return e; }
GF_Err gf_odf_read_ipmp_update(GF_BitStream *bs, GF_IPMPUpdate *ipmpUp, u32 gf_odf_size_command) { GF_Descriptor *tmp; u32 tmpSize = 0, nbBytes = 0; GF_Err e = GF_OK; if (!ipmpUp) return GF_BAD_PARAM; while (nbBytes < gf_odf_size_command) { e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize); if (e) return e; e = AddToIPMPDUpdate(ipmpUp, tmp); if (e) return e; nbBytes += tmpSize + gf_odf_size_field_size(tmpSize); } //OD commands are aligned gf_bs_align(bs); if (nbBytes != gf_odf_size_command) return GF_ODF_INVALID_COMMAND; return e; }
GF_EXPORT GF_Err gf_oci_codec_decode(OCICodec *codec, char *au, u32 au_length) { OCIEvent *ev; GF_BitStream *bs; u32 size, hdrS, desc_size, tot_size, tmp_size, val; GF_Descriptor *tmp; GF_Err e; //must be decoder if (!codec || codec->Mode || !au) return GF_BAD_PARAM; bs = gf_bs_new(au, au_length, GF_BITSTREAM_READ); ev = 0; tot_size = 0; while (tot_size < au_length) { //create an event ev = gf_oci_event_new(0); if (!ev) { e = GF_OUT_OF_MEM; goto err_exit; } //FIX IM1 gf_bs_read_int(bs, 8); size = 0; //get its size hdrS = 0; do { val = gf_bs_read_int(bs, 8); hdrS += 1; size <<= 7; size |= val & 0x7F; } while ( val & 0x80 ); //parse event vars ev->EventID = gf_bs_read_int(bs, 15); ev->AbsoluteTimeFlag = gf_bs_read_int(bs, 1); gf_bs_read_data(bs, ev->StartingTime, 4); gf_bs_read_data(bs, ev->duration, 4); desc_size = 0; //parse descriptor list while (desc_size < size - 10) { e = gf_odf_parse_descriptor(bs, &tmp, &tmp_size); //RE-FIX IM1 if (e || !tmp) goto err_exit; if (!OCI_IsOCIDesc(tmp)) { gf_odf_delete_descriptor(tmp); e = GF_ODF_INVALID_DESCRIPTOR; goto err_exit; } gf_list_add(ev->OCIDescriptors, tmp); desc_size += tmp_size + gf_odf_size_field_size(tmp_size); } if (desc_size != size - 10) { e = GF_CORRUPTED_DATA; goto err_exit; } gf_list_add(codec->OCIEvents, ev); //FIX IM1 size += 1; tot_size += size + hdrS; ev = NULL; } if (tot_size != au_length) { e = GF_CORRUPTED_DATA; goto err_exit; } gf_bs_del(bs); return GF_OK; err_exit: gf_bs_del(bs); if (ev) gf_oci_event_del(ev); //delete everything while (gf_list_count(codec->OCIEvents)) { ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0); gf_list_rem(codec->OCIEvents, 0); gf_oci_event_del(ev); } return e; }