GF_Err gf_odf_codec_apply_com(GF_ODCodec *codec, GF_ODCom *command) { GF_ODCom *com; GF_ODUpdate *odU, *odU_o; u32 i, count; count = gf_list_count(codec->CommandList); switch (command->tag) { case GF_ODF_OD_REMOVE_TAG: for (i = 0; i<count; i++) { com = (GF_ODCom *)gf_list_get(codec->CommandList, i); /*process OD updates*/ if (com->tag == GF_ODF_OD_UPDATE_TAG) { u32 count, j, k; GF_ODRemove *odR = (GF_ODRemove *)command; odU = (GF_ODUpdate *)com; count = gf_list_count(odU->objectDescriptors); /*remove all descs*/ for (k = 0; k<count; k++) { GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k); for (j = 0; j<odR->NbODs; j++) { if (od->objectDescriptorID == odR->OD_ID[j]) { gf_list_rem(odU->objectDescriptors, k); k--; count--; gf_odf_desc_del((GF_Descriptor *)od); break; } } } if (!gf_list_count(odU->objectDescriptors)) { gf_list_rem(codec->CommandList, i); i--; count--; } } /*process ESD updates*/ else if (com->tag == GF_ODF_ESD_UPDATE_TAG) { u32 j; GF_ODRemove *odR = (GF_ODRemove *)command; GF_ESDUpdate *esdU = (GF_ESDUpdate*)com; for (j = 0; j<odR->NbODs; j++) { if (esdU->ODID == odR->OD_ID[j]) { gf_list_rem(codec->CommandList, i); i--; count--; gf_odf_com_del((GF_ODCom**)&esdU); break; } } } } return GF_OK; case GF_ODF_OD_UPDATE_TAG: odU_o = NULL; for (i = 0; i<count; i++) { odU_o = (GF_ODUpdate*)gf_list_get(codec->CommandList, i); /*process OD updates*/ if (odU_o->tag == GF_ODF_OD_UPDATE_TAG) break; odU_o = NULL; } if (!odU_o) { odU_o = (GF_ODUpdate *)gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); gf_list_add(codec->CommandList, odU_o); } odU = (GF_ODUpdate*)command; count = gf_list_count(odU->objectDescriptors); for (i = 0; i<count; i++) { Bool found = GF_FALSE; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, i); u32 j, count2 = gf_list_count(odU_o->objectDescriptors); for (j = 0; j<count2; j++) { GF_ObjectDescriptor *od2 = (GF_ObjectDescriptor *)gf_list_get(odU_o->objectDescriptors, j); if (od2->objectDescriptorID == od->objectDescriptorID) { found = GF_TRUE; break; } } if (!found) { GF_ObjectDescriptor *od_new; GF_Err e = gf_odf_desc_copy((GF_Descriptor*)od, (GF_Descriptor**)&od_new); if (e == GF_OK) gf_list_add(odU_o->objectDescriptors, od_new); } } return GF_OK; } return GF_NOT_SUPPORTED; }
// 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; }
/*import cubic QTVR to mp4*/ GF_Err gf_sm_load_init_qt(GF_SceneLoader *load) { u32 i, di, w, h, tk, nb_samp; Bool has_qtvr; GF_ISOSample *samp; GF_ISOFile *src; GF_StreamContext *st; GF_AUContext *au; GF_Command *com; M_Background *back; M_NavigationInfo *ni; M_Group *gr; GF_ODUpdate *odU; GF_SceneGraph *sg; GF_ObjectDescriptor *od; GF_ESD *esd; if (!load->ctx) return GF_NOT_SUPPORTED; src = gf_isom_open(load->fileName, GF_ISOM_OPEN_READ, NULL); if (!src) return gf_qt_report(load, GF_URL_ERROR, "Opening file %s failed", load->fileName); w = h = tk = 0; nb_samp = 0; has_qtvr = 0; for (i=0; i<gf_isom_get_track_count(src); i++) { switch (gf_isom_get_media_type(src, i+1)) { case GF_ISOM_MEDIA_VISUAL: if (gf_isom_get_media_subtype(src, i+1, 1) == GF_4CC('j', 'p', 'e', 'g')) { GF_GenericSampleDescription *udesc = gf_isom_get_generic_sample_description(src, i+1, 1); if ((udesc->width>w) || (udesc->height>h)) { w = udesc->width; h = udesc->height; tk = i+1; nb_samp = gf_isom_get_sample_count(src, i+1); } if (udesc->extension_buf) gf_free(udesc->extension_buf); gf_free(udesc); } break; case GF_4CC('q','t','v','r'): has_qtvr = 1; break; } } if (!has_qtvr) { gf_isom_delete(src); return gf_qt_report(load, GF_NOT_SUPPORTED, "QTVR not found - no conversion available for this QuickTime movie"); } if (!tk) { gf_isom_delete(src); return gf_qt_report(load, GF_NON_COMPLIANT_BITSTREAM, "No associated visual track with QTVR movie"); } if (nb_samp!=6) { gf_isom_delete(src); return gf_qt_report(load, GF_NOT_SUPPORTED, "Movie %s doesn't look a Cubic QTVR - sorry...", load->fileName); } GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("QT: Importing Cubic QTVR Movie")); /*create scene*/ sg = load->ctx->scene_graph; gr = (M_Group *) gf_node_new(sg, TAG_MPEG4_Group); gf_node_register((GF_Node *)gr, NULL); st = gf_sm_stream_new(load->ctx, 1, GF_STREAM_SCENE, 1); au = gf_sm_stream_au_new(st, 0, 0, 1); com = gf_sg_command_new(load->ctx->scene_graph, GF_SG_SCENE_REPLACE); gf_list_add(au->commands, com); com->node = (GF_Node *)gr; back = (M_Background *) gf_node_new(sg, TAG_MPEG4_Background); gf_node_list_add_child( &gr->children, (GF_Node*)back); gf_node_register((GF_Node *)back, (GF_Node *)gr); gf_sg_vrml_mf_alloc(&back->leftUrl, GF_SG_VRML_MFURL, 1); back->leftUrl.vals[0].OD_ID = 2; gf_sg_vrml_mf_alloc(&back->frontUrl, GF_SG_VRML_MFURL, 1); back->frontUrl.vals[0].OD_ID = 3; gf_sg_vrml_mf_alloc(&back->rightUrl, GF_SG_VRML_MFURL, 1); back->rightUrl.vals[0].OD_ID = 4; gf_sg_vrml_mf_alloc(&back->backUrl, GF_SG_VRML_MFURL, 1); back->backUrl.vals[0].OD_ID = 5; gf_sg_vrml_mf_alloc(&back->topUrl, GF_SG_VRML_MFURL, 1); back->topUrl.vals[0].OD_ID = 6; gf_sg_vrml_mf_alloc(&back->bottomUrl, GF_SG_VRML_MFURL, 1); back->bottomUrl.vals[0].OD_ID = 7; ni = (M_NavigationInfo *) gf_node_new(sg, TAG_MPEG4_NavigationInfo); gf_node_list_add_child(&gr->children, (GF_Node*)ni); gf_node_register((GF_Node *)ni, (GF_Node *)gr); gf_sg_vrml_mf_reset(&ni->type, GF_SG_VRML_MFSTRING); gf_sg_vrml_mf_alloc(&ni->type, GF_SG_VRML_MFSTRING, 1); ni->type.vals[0] = gf_strdup("QTVR"); /*create ODs*/ st = gf_sm_stream_new(load->ctx, 2, GF_STREAM_OD, 1); au = gf_sm_stream_au_new(st, 0, 0, 1); odU = (GF_ODUpdate*) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); gf_list_add(au->commands, odU); for (i=0; i<6; i++) { GF_MuxInfo *mi; FILE *img; char szName[1024]; od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->objectDescriptorID = 2+i; esd = gf_odf_desc_esd_new(2); esd->decoderConfig->streamType = GF_STREAM_VISUAL; esd->decoderConfig->objectTypeIndication = GPAC_OTI_IMAGE_JPEG; esd->ESID = 3+i; /*extract image and remember it*/ mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); mi->delete_file = 1; sprintf(szName, "%s_img%d.jpg", load->fileName, esd->ESID); mi->file_name = gf_strdup(szName); gf_list_add(od->ESDescriptors, esd); gf_list_add(odU->objectDescriptors, od); samp = gf_isom_get_sample(src, tk, i+1, &di); img = gf_f64_open(mi->file_name, "wb"); fwrite(samp->data, samp->dataLength, 1, img); fclose(img); gf_isom_sample_del(&samp); } gf_isom_delete(src); return GF_OK; }
// 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; }