// Rewrite the good dependancies when an OD AU is extracted from the file static u32 Media_FindOD_ID(GF_MediaBox *mdia, GF_ISOSample *sample, u32 track_id) { GF_Err e; GF_ODCodec *ODdecode; GF_ODCom *com; u32 the_od_id; GF_ODUpdate *odU; GF_ESD *esd; GF_Descriptor *desc; GF_TrackReferenceTypeBox *mpod; u32 i, j; if (!mdia || !sample || !sample->data || !sample->dataLength) return 0; mpod = NULL; e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod); if (e) return 0; //no references, nothing to do... if (!mpod) return 0; the_od_id = 0; ODdecode = gf_odf_codec_new(); if (!ODdecode) return 0; e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength); if (e) goto err_exit; e = gf_odf_codec_decode(ODdecode); if (e) goto err_exit; while (1) { GF_List *esd_list = NULL; com = gf_odf_codec_get_com(ODdecode); if (!com) break; if (com->tag != GF_ODF_OD_UPDATE_TAG) continue; odU = (GF_ODUpdate *) com; i=0; while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) { switch (desc->tag) { case GF_ODF_OD_TAG: case GF_ODF_IOD_TAG: esd_list = ((GF_ObjectDescriptor *)desc)->ESDescriptors; break; default: continue; } j=0; while ((esd = (GF_ESD*)gf_list_enum( esd_list, &j))){ if (esd->ESID==track_id) { the_od_id = ((GF_IsomObjectDescriptor*)desc)->objectDescriptorID; break; } } if (the_od_id) break; } gf_odf_com_del((GF_ODCom **)&odU); if (the_od_id) break; } err_exit: gf_odf_codec_del(ODdecode); if (e) return 0; return the_od_id; }
// Rewrite the good dependancies when an OD AU is extracted from the file GF_Err Media_RewriteODFrame(GF_MediaBox *mdia, GF_ISOSample *sample) { GF_Err e; GF_ODCodec *ODdecode; GF_ODCodec *ODencode; GF_ODCom *com; //the commands we proceed GF_ESDUpdate *esdU, *esdU2; GF_ESDRemove *esdR, *esdR2; GF_ODUpdate *odU, *odU2; //the desc they contain GF_ObjectDescriptor *od; GF_IsomObjectDescriptor *isom_od; GF_ESD *esd; GF_ES_ID_Ref *ref; GF_Descriptor *desc; GF_TrackReferenceTypeBox *mpod; u32 i, j, skipped; if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM; mpod = NULL; e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod); if (e) return e; //no references, nothing to do... if (!mpod) return GF_OK; ODdecode = gf_odf_codec_new(); if (!ODdecode) return GF_OUT_OF_MEM; ODencode = gf_odf_codec_new(); if (!ODencode) { gf_odf_codec_del(ODdecode); return GF_OUT_OF_MEM; } e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength); if (e) goto err_exit; e = gf_odf_codec_decode(ODdecode); if (e) goto err_exit; while (1) { com = gf_odf_codec_get_com(ODdecode); if (!com) break; //we only need to rewrite commands with ESDs inside: ESDUpdate and ODUpdate switch (com->tag) { case GF_ODF_OD_UPDATE_TAG: odU = (GF_ODUpdate *) com; odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); i=0; while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) { switch (desc->tag) { case GF_ODF_OD_TAG: case GF_ODF_ISOM_OD_TAG: //IOD can be used in OD streams case GF_ODF_ISOM_IOD_TAG: break; default: return GF_ISOM_INVALID_FILE; } e = gf_odf_desc_copy(desc, (GF_Descriptor **)&isom_od); if (e) goto err_exit; //create our OD... if (desc->tag == GF_ODF_ISOM_IOD_TAG) { od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_InitialObjectDescriptor)); } else { od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_ObjectDescriptor)); } if (!od) { e = GF_OUT_OF_MEM; goto err_exit; } od->ESDescriptors = gf_list_new(); //and duplicate... od->objectDescriptorID = isom_od->objectDescriptorID; od->tag = GF_ODF_OD_TAG; od->URLString = isom_od->URLString; isom_od->URLString = NULL; od->extensionDescriptors = isom_od->extensionDescriptors; isom_od->extensionDescriptors = NULL; od->IPMP_Descriptors = isom_od->IPMP_Descriptors; isom_od->IPMP_Descriptors = NULL; od->OCIDescriptors = isom_od->OCIDescriptors; isom_od->OCIDescriptors = NULL; //init as IOD if (isom_od->tag == GF_ODF_ISOM_IOD_TAG) { ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel; ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag = ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag; ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel; ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel; ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel; ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel; ((GF_InitialObjectDescriptor *)od)->IPMPToolList = ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList; ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = NULL; } //then rewrite the ESDesc j=0; while ((ref = (GF_ES_ID_Ref*)gf_list_enum(isom_od->ES_ID_RefDescriptors, &j))){ //if the ref index is not valid, skip this desc... if (!mpod->trackIDs || gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue; //OK, get the esd e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd); if (!e) e = gf_odf_desc_add_desc((GF_Descriptor *) od, (GF_Descriptor *) esd); if (e) { gf_odf_desc_del((GF_Descriptor *)od); gf_odf_com_del((GF_ODCom **)&odU2); gf_odf_desc_del((GF_Descriptor *)isom_od); gf_odf_com_del((GF_ODCom **)&odU); goto err_exit; } } //delete our desc gf_odf_desc_del((GF_Descriptor *)isom_od); gf_list_add(odU2->objectDescriptors, od); } //clean a bit gf_odf_com_del((GF_ODCom **)&odU); gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2); break; case GF_ODF_ESD_UPDATE_TAG: esdU = (GF_ESDUpdate *) com; esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG); esdU2->ODID = esdU->ODID; i=0; while ((ref = (GF_ES_ID_Ref*)gf_list_enum(esdU->ESDescriptors, &i))) { //if the ref index is not valid, skip this desc... if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue; //OK, get the esd e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd); if (e) goto err_exit; gf_list_add(esdU2->ESDescriptors, esd); } gf_odf_com_del((GF_ODCom **)&esdU); gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2); break; //brand new case: the ESRemove follows the same principle according to the spec... case GF_ODF_ESD_REMOVE_REF_TAG: //both commands have the same structure, only the tags change esdR = (GF_ESDRemove *) com; esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG); esdR2->ODID = esdR->ODID; esdR2->NbESDs = esdR->NbESDs; //alloc our stuff esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs); if (!esdR2->ES_ID) { e = GF_OUT_OF_MEM; goto err_exit; } skipped = 0; //get the ES_ID in the mpod indicated in the ES_ID[] for (i = 0; i < esdR->NbESDs; i++) { //if the ref index is not valid, remove this desc... if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[esdR->ES_ID[i] - 1]) == NULL) { skipped ++; } else { //the command in the file has the ref index of the trackID in the mpod esdR2->ES_ID[i - skipped] = mpod->trackIDs[esdR->ES_ID[i] - 1]; } } //gf_realloc... if (skipped && (skipped != esdR2->NbESDs) ) { esdR2->NbESDs -= skipped; esdR2->ES_ID = (unsigned short*)gf_realloc(esdR2->ES_ID, sizeof(u32) * esdR2->NbESDs); } gf_odf_com_del((GF_ODCom **)&esdR); gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2); break; default: e = gf_odf_codec_add_com(ODencode, com); if (e) goto err_exit; } } //encode our new AU e = gf_odf_codec_encode(ODencode, 1); if (e) goto err_exit; //and set the buffer in the sample gf_free(sample->data); sample->data = NULL; sample->dataLength = 0; e = gf_odf_codec_get_au(ODencode, &sample->data, &sample->dataLength); err_exit: gf_odf_codec_del(ODdecode); gf_odf_codec_del(ODencode); return e; }
static GF_Err gf_sm_load_run_isom(GF_SceneLoader *load) { GF_Err e; FILE *logs; u32 i, j, di, nbBifs, nbLaser, nb_samp, samp_done, init_offset; GF_StreamContext *sc; GF_ESD *esd; GF_ODCodec *od_dec; #ifndef GPAC_DISABLE_BIFS GF_BifsDecoder *bifs_dec; #endif #ifndef GPAC_DISABLE_LASER GF_LASeRCodec *lsr_dec; #endif if (!load || !load->isom) return GF_BAD_PARAM; nbBifs = nbLaser = 0; e = GF_OK; #ifndef GPAC_DISABLE_BIFS bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1); gf_bifs_decoder_set_extraction_path(bifs_dec, load->localPath, load->fileName); #endif od_dec = gf_odf_codec_new(); logs = NULL; #ifndef GPAC_DISABLE_LASER lsr_dec = gf_laser_decoder_new(load->scene_graph); #endif esd = NULL; /*load each stream*/ nb_samp = 0; for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); switch (type) { case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_OD: nb_samp += gf_isom_get_sample_count(load->isom, i+1); break; default: break; } } samp_done = 1; gf_isom_text_set_streaming_mode(load->isom, 1); for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); switch (type) { case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_OD: break; default: continue; } esd = gf_isom_get_esd(load->isom, i+1, 1); if (!esd) continue; if ((esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_AFX) || (esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE) ) { nb_samp += gf_isom_get_sample_count(load->isom, i+1); continue; } sc = gf_sm_stream_new(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); sc->streamType = esd->decoderConfig->streamType; sc->ESID = esd->ESID; sc->objectType = esd->decoderConfig->objectTypeIndication; sc->timeScale = gf_isom_get_media_timescale(load->isom, i+1); /*we still need to reconfig the BIFS*/ if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { #ifndef GPAC_DISABLE_BIFS /*BIFS*/ if (esd->decoderConfig->objectTypeIndication<=2) { if (!esd->dependsOnESID && nbBifs && !i) mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect"); if (!esd->decoderConfig->decoderSpecificInfo) { /* Hack for T-DMB non compliant streams */ e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, NULL, 0, esd->decoderConfig->objectTypeIndication); } else { e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication); } if (e) goto exit; nbBifs++; } #endif #ifndef GPAC_DISABLE_LASER /*LASER*/ if (esd->decoderConfig->objectTypeIndication==0x09) { if (!esd->dependsOnESID && nbBifs && !i) mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect"); e = gf_laser_decoder_configure_stream(lsr_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); if (e) goto exit; nbLaser++; } #endif } init_offset = 0; /*dump all AUs*/ for (j=0; j<gf_isom_get_sample_count(load->isom, i+1); j++) { GF_AUContext *au; GF_ISOSample *samp = gf_isom_get_sample(load->isom, i+1, j+1, &di); if (!samp) { mp4_report(load, gf_isom_last_error(load->isom), "Unable to fetch sample %d from track ID %d - aborting track import", j+1, gf_isom_get_track_id(load->isom, i+1)); break; } /*check if track has initial offset*/ if (!j && gf_isom_get_edit_segment_count(load->isom, i+1)) { u64 EditTime, dur, mtime; u8 mode; gf_isom_get_edit_segment(load->isom, i+1, 1, &EditTime, &dur, &mtime, &mode); if (mode==GF_ISOM_EDIT_EMPTY) { init_offset = (u32) (dur * sc->timeScale / gf_isom_get_timescale(load->isom) ); } } samp->DTS += init_offset; au = gf_sm_stream_au_new(sc, samp->DTS, ((Double)(s64) samp->DTS) / sc->timeScale, (samp->IsRAP==RAP) ? 1 : 0); if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { #ifndef GPAC_DISABLE_BIFS if (esd->decoderConfig->objectTypeIndication<=2) e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands); #endif #ifndef GPAC_DISABLE_LASER if (esd->decoderConfig->objectTypeIndication==0x09) e = gf_laser_decode_command_list(lsr_dec, esd->ESID, samp->data, samp->dataLength, au->commands); #endif } else { e = gf_odf_codec_set_au(od_dec, samp->data, samp->dataLength); if (!e) e = gf_odf_codec_decode(od_dec); if (!e) { while (1) { GF_ODCom *odc = gf_odf_codec_get_com(od_dec); if (!odc) break; /*update ESDs if any*/ UpdateODCommand(load->isom, odc); gf_list_add(au->commands, odc); } } } gf_isom_sample_del(&samp); if (e) { mp4_report(load, gf_isom_last_error(load->isom), "decoding sample %d from track ID %d failed", j+1, gf_isom_get_track_id(load->isom, i+1)); goto exit; } samp_done++; gf_set_progress("MP4 Loading", samp_done, nb_samp); } gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; } gf_isom_text_set_streaming_mode(load->isom, 0); exit: #ifndef GPAC_DISABLE_BIFS gf_bifs_decoder_del(bifs_dec); #endif gf_odf_codec_del(od_dec); #ifndef GPAC_DISABLE_LASER gf_laser_decoder_del(lsr_dec); #endif if (esd) gf_odf_desc_del((GF_Descriptor *) esd); if (logs) gf_fclose(logs); return e; }
// Update the dependancies when an OD AU is inserted in the file GF_Err Media_ParseODFrame(GF_MediaBox *mdia, GF_ISOSample *sample, GF_ISOSample **od_samp) { GF_TrackReferenceBox *tref; GF_TrackReferenceTypeBox *mpod; GF_Err e; GF_ODCom *com; GF_ODCodec *ODencode; GF_ODCodec *ODdecode; u32 i, j; //the commands we proceed GF_ESDUpdate *esdU, *esdU2; GF_ESDRemove *esdR, *esdR2; GF_ODUpdate *odU, *odU2; //the desc they contain GF_ObjectDescriptor *od; GF_IsomObjectDescriptor *isom_od; GF_ESD *esd; GF_ES_ID_Ref *ref; GF_Descriptor *desc; *od_samp = NULL; if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM; //First find the references, and create them if none tref = mdia->mediaTrack->References; if (!tref) { tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF); e = trak_AddBox((GF_Box*)mdia->mediaTrack, (GF_Box *) tref); if (e) return e; } //then find the OD reference, and create it if none e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod); if (e) return e; if (!mpod) { mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT); mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD; e = tref_AddBox((GF_Box*)tref, (GF_Box *)mpod); if (e) return e; } //OK, create our codecs ODencode = gf_odf_codec_new(); if (!ODencode) return GF_OUT_OF_MEM; ODdecode = gf_odf_codec_new(); if (!ODdecode) return GF_OUT_OF_MEM; e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength); if (e) goto err_exit; e = gf_odf_codec_decode(ODdecode); if (e) goto err_exit; while (1) { com = gf_odf_codec_get_com(ODdecode); if (!com) break; //check our commands switch (com->tag) { //Rewrite OD Update case GF_ODF_OD_UPDATE_TAG: //duplicate our command odU = (GF_ODUpdate *) com; odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); i=0; while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) { //both OD and IODs are accepted switch (desc->tag) { case GF_ODF_OD_TAG: case GF_ODF_IOD_TAG: break; default: e = GF_ODF_INVALID_DESCRIPTOR; goto err_exit; } //get the esd e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od); if (e) goto err_exit; if (desc->tag == GF_ODF_OD_TAG) { isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor)); isom_od->tag = GF_ODF_ISOM_OD_TAG; } else { isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor)); isom_od->tag = GF_ODF_ISOM_IOD_TAG; //copy PL ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag; ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel; ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel; ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel; ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel; ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel; ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList; ((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL; } //in OD stream only ref desc are accepted isom_od->ES_ID_RefDescriptors = gf_list_new(); isom_od->ES_ID_IncDescriptors = NULL; //TO DO: check that a given sampleDescription exists isom_od->extensionDescriptors = od->extensionDescriptors; od->extensionDescriptors = NULL; isom_od->IPMP_Descriptors = od->IPMP_Descriptors; od->IPMP_Descriptors = NULL; isom_od->OCIDescriptors = od->OCIDescriptors; od->OCIDescriptors = NULL; isom_od->URLString = od->URLString; od->URLString = NULL; isom_od->objectDescriptorID = od->objectDescriptorID; j=0; while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) { ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG); //1 to 1 mapping trackID and ESID. Add this track to MPOD //if track does not exist, this will be remove while reading the OD stream e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef); e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref); if (e) goto err_exit; } //delete our desc gf_odf_desc_del((GF_Descriptor *)od); //and add the new one to our command gf_list_add(odU2->objectDescriptors, isom_od); } //delete the command gf_odf_com_del((GF_ODCom **)&odU); //and add the new one to the codec gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2); break; //Rewrite ESD Update case GF_ODF_ESD_UPDATE_TAG: esdU = (GF_ESDUpdate *) com; esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG); esdU2->ODID = esdU->ODID; i=0; while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) { ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG); //1 to 1 mapping trackID and ESID e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef); e = gf_list_add(esdU2->ESDescriptors, ref); if (e) goto err_exit; } gf_odf_com_del((GF_ODCom **)&esdU); gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2); break; //Brand new case: the ESRemove has to be rewritten too according to the specs... case GF_ODF_ESD_REMOVE_TAG: esdR = (GF_ESDRemove *) com; esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG); //change the tag for the file format esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG; esdR2->ODID = esdR->ODID; esdR2->NbESDs = esdR->NbESDs; if (esdR->NbESDs) { //alloc our stuff esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs); if (!esdR2->ES_ID) { e = GF_OUT_OF_MEM; goto err_exit; } for (i = 0; i < esdR->NbESDs; i++) { //1 to 1 mapping trackID and ESID e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]); if (e) goto err_exit; } } gf_odf_com_del(&com); gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2); break; //Add the command as is default: e = gf_odf_codec_add_com(ODencode, com); if (e) goto err_exit; } } //encode our new AU e = gf_odf_codec_encode(ODencode, 1); if (e) goto err_exit; //and set the buffer in the sample *od_samp = gf_isom_sample_new(); (*od_samp)->CTS_Offset = sample->CTS_Offset; (*od_samp)->DTS = sample->DTS; (*od_samp)->IsRAP = sample->IsRAP; e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength); if (e) { gf_isom_sample_del(od_samp); *od_samp = NULL; } err_exit: gf_odf_codec_del(ODencode); gf_odf_codec_del(ODdecode); return e; }
static GF_Err ODF_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 AU_time, u32 mmlevel) { GF_Err e; GF_ODCom *com; GF_ODCodec *oddec; ODPriv *priv = (ODPriv *)plug->privateStack; oddec = gf_odf_codec_new(); e = gf_odf_codec_set_au(oddec, inBuffer, inBufferLength); if (!e) e = gf_odf_codec_decode(oddec); if (e) goto err_exit; //3- process all the commands in this AU, in order while (1) { com = gf_odf_codec_get_com(oddec); if (!com) break; //ok, we have a command switch (com->tag) { case GF_ODF_OD_UPDATE_TAG: e = ODS_ODUpdate(priv, (GF_ODUpdate *) com); break; case GF_ODF_OD_REMOVE_TAG: e = ODS_RemoveOD(priv, (GF_ODRemove *) com); break; case GF_ODF_ESD_UPDATE_TAG: e = ODS_UpdateESD(priv, (GF_ESDUpdate *)com); break; case GF_ODF_ESD_REMOVE_TAG: e = ODS_RemoveESD(priv, (GF_ESDRemove *)com); break; case GF_ODF_IPMP_UPDATE_TAG: #if 0 { GF_IPMPUpdate *ipmpU = (GF_IPMPUpdate *)com; while (gf_list_count(ipmpU->IPMPDescList)) { GF_IPMP_Descriptor *ipmp = gf_list_get(ipmpU->IPMPDescList, 0); gf_list_rem(ipmpU->IPMPDescList, 0); IS_UpdateIPMP(priv->scene, ipmp); } e = GF_OK; } #else e = GF_OK; #endif break; case GF_ODF_IPMP_REMOVE_TAG: e = GF_NOT_SUPPORTED; break; /*should NEVER exist outside the file format*/ case GF_ODF_ESD_REMOVE_REF_TAG: e = GF_NON_COMPLIANT_BITSTREAM; break; default: if (com->tag >= GF_ODF_COM_ISO_BEGIN_TAG && com->tag <= GF_ODF_COM_ISO_END_TAG) { e = GF_ODF_FORBIDDEN_DESCRIPTOR; } else { /*we don't process user commands*/ e = GF_OK; } break; } gf_odf_com_del(&com); if (e) break; } err_exit: gf_odf_codec_del(oddec); return e; }