LCOV - code coverage report
Current view: top level - isomedia - media_odf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 233 274 85.0 %
Date: 2021-04-29 23:48:07 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISO Media File Format sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/isomedia_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_ISOM
      29             : 
      30             : // Rewrite the good dependencies when an OD AU is extracted from the file
      31          97 : GF_Err Media_RewriteODFrame(GF_MediaBox *mdia, GF_ISOSample *sample)
      32             : {
      33             :         GF_Err e;
      34             :         GF_ODCodec *ODdecode;
      35             :         GF_ODCodec *ODencode;
      36             :         GF_ODCom *com;
      37             : 
      38             :         //the commands we proceed
      39             :         GF_ESDUpdate *esdU, *esdU2;
      40             :         GF_ESDRemove *esdR, *esdR2;
      41             :         GF_ODUpdate *odU, *odU2;
      42             : 
      43             :         //the desc they contain
      44             :         GF_ObjectDescriptor *od;
      45             :         GF_IsomObjectDescriptor *isom_od;
      46             :         GF_ESD *esd;
      47             :         GF_ES_ID_Ref *ref;
      48             :         GF_Descriptor *desc;
      49             :         GF_TrackReferenceTypeBox *mpod;
      50             :         u32 i, j, skipped;
      51             : 
      52          97 :         if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
      53             : 
      54          97 :         mpod = NULL;
      55          97 :         e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
      56          97 :         if (e) return e;
      57             :         //no references, nothing to do...
      58          97 :         if (!mpod || !mpod->trackIDs) return GF_OK;
      59             : 
      60          94 :         ODdecode = gf_odf_codec_new();
      61          94 :         if (!ODdecode) return GF_OUT_OF_MEM;
      62          94 :         ODencode = gf_odf_codec_new();
      63          94 :         if (!ODencode) {
      64           0 :                 gf_odf_codec_del(ODdecode);
      65           0 :                 return GF_OUT_OF_MEM;
      66             :         }
      67          94 :         e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
      68          94 :         if (e) goto err_exit;
      69          94 :         e = gf_odf_codec_decode(ODdecode);
      70          94 :         if (e) goto err_exit;
      71             : 
      72             :         while (1) {
      73         188 :                 com = gf_odf_codec_get_com(ODdecode);
      74         188 :                 if (!com) break;
      75             : 
      76             :                 //we only need to rewrite commands with ESDs inside: ESDUpdate and ODUpdate
      77          94 :                 switch (com->tag) {
      78          52 :                 case GF_ODF_OD_UPDATE_TAG:
      79          52 :                         odU = (GF_ODUpdate *) com;
      80          52 :                         odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
      81             : 
      82          52 :                         i=0;
      83         200 :                         while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
      84          96 :                                 switch (desc->tag) {
      85             :                                 case GF_ODF_OD_TAG:
      86             :                                 case GF_ODF_ISOM_OD_TAG:
      87             :                                 //IOD can be used in OD streams
      88             :                                 case GF_ODF_ISOM_IOD_TAG:
      89             :                                         break;
      90             :                                 default:
      91             :                                         return GF_ISOM_INVALID_FILE;
      92             :                                 }
      93          96 :                                 e = gf_odf_desc_copy(desc, (GF_Descriptor **)&isom_od);
      94          96 :                                 if (e) goto err_exit;
      95             : 
      96             :                                 //create our OD...
      97          96 :                                 if (desc->tag == GF_ODF_ISOM_IOD_TAG) {
      98           0 :                                         od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_InitialObjectDescriptor));
      99             :                                 } else {
     100          96 :                                         od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_ObjectDescriptor));
     101             :                                 }
     102          96 :                                 if (!od) {
     103             :                                         e = GF_OUT_OF_MEM;
     104             :                                         goto err_exit;
     105             :                                 }
     106          96 :                                 od->ESDescriptors = gf_list_new();
     107             :                                 //and duplicate...
     108          96 :                                 od->objectDescriptorID = isom_od->objectDescriptorID;
     109          96 :                                 od->tag = GF_ODF_OD_TAG;
     110          96 :                                 od->URLString = isom_od->URLString;
     111          96 :                                 isom_od->URLString = NULL;
     112          96 :                                 od->extensionDescriptors = isom_od->extensionDescriptors;
     113          96 :                                 isom_od->extensionDescriptors = NULL;
     114          96 :                                 od->IPMP_Descriptors = isom_od->IPMP_Descriptors;
     115          96 :                                 isom_od->IPMP_Descriptors = NULL;
     116          96 :                                 od->OCIDescriptors = isom_od->OCIDescriptors;
     117          96 :                                 isom_od->OCIDescriptors = NULL;
     118             : 
     119             :                                 //init as IOD
     120          96 :                                 if (isom_od->tag == GF_ODF_ISOM_IOD_TAG) {
     121           0 :                                         ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel;
     122           0 :                                         ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag = ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag;
     123           0 :                                         ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel;
     124           0 :                                         ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel;
     125           0 :                                         ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel;
     126           0 :                                         ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel;
     127           0 :                                         ((GF_InitialObjectDescriptor *)od)->IPMPToolList = ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList;
     128           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = NULL;
     129             :                                 }
     130             : 
     131             :                                 //then rewrite the ESDesc
     132          96 :                                 j=0;
     133         288 :                                 while ((ref = (GF_ES_ID_Ref*)gf_list_enum(isom_od->ES_ID_RefDescriptors, &j))) {
     134             :                                         //if the ref index is not valid, skip this desc...
     135          96 :                                         if (!mpod->trackIDs || gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
     136             :                                         //OK, get the esd
     137          96 :                                         e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
     138          96 :                                         if (!e) e = gf_odf_desc_add_desc((GF_Descriptor *) od, (GF_Descriptor *) esd);
     139          96 :                                         if (e) {
     140           0 :                                                 gf_odf_desc_del((GF_Descriptor *)od);
     141           0 :                                                 gf_odf_com_del((GF_ODCom **)&odU2);
     142           0 :                                                 gf_odf_desc_del((GF_Descriptor *)isom_od);
     143           0 :                                                 gf_odf_com_del((GF_ODCom **)&odU);
     144           0 :                                                 goto err_exit;
     145             :                                         }
     146             : 
     147             :                                 }
     148             :                                 //delete our desc
     149          96 :                                 gf_odf_desc_del((GF_Descriptor *)isom_od);
     150          96 :                                 gf_list_add(odU2->objectDescriptors, od);
     151             :                         }
     152             :                         //clean a bit
     153          52 :                         gf_odf_com_del((GF_ODCom **)&odU);
     154          52 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
     155          52 :                         break;
     156             : 
     157           6 :                 case GF_ODF_ESD_UPDATE_TAG:
     158           6 :                         esdU = (GF_ESDUpdate *) com;
     159           6 :                         esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
     160           6 :                         esdU2->ODID = esdU->ODID;
     161           6 :                         i=0;
     162          18 :                         while ((ref = (GF_ES_ID_Ref*)gf_list_enum(esdU->ESDescriptors, &i))) {
     163             :                                 //if the ref index is not valid, skip this desc...
     164           6 :                                 if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
     165             :                                 //OK, get the esd
     166           6 :                                 e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
     167           6 :                                 if (e) goto err_exit;
     168           6 :                                 gf_list_add(esdU2->ESDescriptors, esd);
     169             :                         }
     170           6 :                         gf_odf_com_del((GF_ODCom **)&esdU);
     171           6 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
     172           6 :                         break;
     173             : 
     174             :                 //brand new case: the ESRemove follows the same principle according to the spec...
     175          18 :                 case GF_ODF_ESD_REMOVE_REF_TAG:
     176             :                         //both commands have the same structure, only the tags change
     177          18 :                         esdR = (GF_ESDRemove *) com;
     178          18 :                         esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
     179          18 :                         esdR2->ODID = esdR->ODID;
     180          18 :                         esdR2->NbESDs = esdR->NbESDs;
     181             :                         //alloc our stuff
     182          18 :                         esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
     183          18 :                         if (!esdR2->ES_ID) {
     184             :                                 e = GF_OUT_OF_MEM;
     185             :                                 goto err_exit;
     186             :                         }
     187             :                         skipped = 0;
     188             :                         //get the ES_ID in the mpod indicated in the ES_ID[]
     189          36 :                         for (i = 0; i < esdR->NbESDs; i++) {
     190             :                                 //if the ref index is not valid, remove this desc...
     191          18 :                                 if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[esdR->ES_ID[i] - 1]) == NULL) {
     192           0 :                                         skipped ++;
     193             :                                 } else {
     194             :                                         //the command in the file has the ref index of the trackID in the mpod
     195          18 :                                         esdR2->ES_ID[i - skipped] = mpod->trackIDs[esdR->ES_ID[i] - 1];
     196             :                                 }
     197             :                         }
     198             :                         //gf_realloc...
     199          18 :                         if (skipped && (skipped != esdR2->NbESDs) ) {
     200           0 :                                 esdR2->NbESDs -= skipped;
     201           0 :                                 esdR2->ES_ID = (unsigned short*)gf_realloc(esdR2->ES_ID, sizeof(u32) * esdR2->NbESDs);
     202             :                         }
     203          18 :                         gf_odf_com_del((GF_ODCom **)&esdR);
     204          18 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
     205          18 :                         break;
     206             : 
     207          18 :                 default:
     208          18 :                         e = gf_odf_codec_add_com(ODencode, com);
     209          18 :                         if (e) goto err_exit;
     210             :                 }
     211             :         }
     212             :         //encode our new AU
     213          94 :         e = gf_odf_codec_encode(ODencode, 1);
     214          94 :         if (e) goto err_exit;
     215             : 
     216             :         //and set the buffer in the sample
     217          94 :         gf_free(sample->data);
     218          94 :         sample->data = NULL;
     219          94 :         sample->dataLength = 0;
     220          94 :         e = gf_odf_codec_get_au(ODencode, &sample->data, &sample->dataLength);
     221             : 
     222          94 : err_exit:
     223          94 :         gf_odf_codec_del(ODdecode);
     224          94 :         gf_odf_codec_del(ODencode);
     225          94 :         return e;
     226             : }
     227             : 
     228             : 
     229             : // Update the dependencies when an OD AU is inserted in the file
     230          78 : GF_Err Media_ParseODFrame(GF_MediaBox *mdia, const GF_ISOSample *sample, GF_ISOSample **od_samp)
     231             : {
     232             :         GF_TrackReferenceBox *tref;
     233             :         GF_TrackReferenceTypeBox *mpod;
     234             :         GF_Err e;
     235             :         GF_ODCom *com;
     236             :         GF_ODCodec *ODencode;
     237             :         GF_ODCodec *ODdecode;
     238             :         u32 i, j;
     239             :         //the commands we proceed
     240             :         GF_ESDUpdate *esdU, *esdU2;
     241             :         GF_ESDRemove *esdR, *esdR2;
     242             :         GF_ODUpdate *odU, *odU2;
     243             : 
     244             :         //the desc they contain
     245             :         GF_ObjectDescriptor *od;
     246             :         GF_IsomObjectDescriptor *isom_od;
     247             :         GF_ESD *esd;
     248             :         GF_ES_ID_Ref *ref;
     249             :         GF_Descriptor *desc;
     250             : 
     251          78 :         *od_samp = NULL;
     252          78 :         if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
     253             : 
     254             :         //First find the references, and create them if none
     255          78 :         tref = mdia->mediaTrack->References;
     256          78 :         if (!tref) {
     257          23 :                 tref = (GF_TrackReferenceBox *) gf_isom_box_new_parent(&mdia->mediaTrack->child_boxes, GF_ISOM_BOX_TYPE_TREF);
     258          23 :                 if (!tref) return GF_OUT_OF_MEM;
     259          23 :                 e = trak_on_child_box((GF_Box*)mdia->mediaTrack, (GF_Box *) tref, GF_FALSE);
     260          23 :                 if (e) return e;
     261             :         }
     262             :         //then find the OD reference, and create it if none
     263          78 :         e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
     264          78 :         if (e) return e;
     265          78 :         if (!mpod) {
     266          30 :                 mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new_parent(&tref->child_boxes, GF_ISOM_BOX_TYPE_REFT);
     267          30 :                 if (!mpod) return GF_OUT_OF_MEM;
     268          30 :                 mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD;
     269             :         }
     270             : 
     271             :         //OK, create our codecs
     272          78 :         ODencode = gf_odf_codec_new();
     273          78 :         if (!ODencode) return GF_OUT_OF_MEM;
     274          78 :         ODdecode = gf_odf_codec_new();
     275          78 :         if (!ODdecode) return GF_OUT_OF_MEM;
     276             : 
     277          78 :         e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
     278          78 :         if (e) goto err_exit;
     279          78 :         e = gf_odf_codec_decode(ODdecode);
     280          78 :         if (e) goto err_exit;
     281             : 
     282             :         while (1) {
     283         156 :                 com = gf_odf_codec_get_com(ODdecode);
     284         156 :                 if (!com) break;
     285             : 
     286             :                 //check our commands
     287          78 :                 switch (com->tag) {
     288             :                 //Rewrite OD Update
     289          57 :                 case GF_ODF_OD_UPDATE_TAG:
     290             :                         //duplicate our command
     291          57 :                         odU = (GF_ODUpdate *) com;
     292          57 :                         odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
     293             : 
     294          57 :                         i=0;
     295         231 :                         while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
     296             :                                 //both OD and IODs are accepted
     297         117 :                                 switch (desc->tag) {
     298             :                                 case GF_ODF_OD_TAG:
     299             :                                 case GF_ODF_IOD_TAG:
     300             :                                         break;
     301             :                                 default:
     302             :                                         e = GF_ODF_INVALID_DESCRIPTOR;
     303             :                                         goto err_exit;
     304             :                                 }
     305             :                                 //get the esd
     306         117 :                                 e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od);
     307         117 :                                 if (e) goto err_exit;
     308         117 :                                 if (desc->tag == GF_ODF_OD_TAG) {
     309         117 :                                         isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor));
     310         117 :                                         if (!isom_od) return GF_OUT_OF_MEM;
     311         117 :                                         isom_od->tag = GF_ODF_ISOM_OD_TAG;
     312             :                                 } else {
     313           0 :                                         isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor));
     314           0 :                                         if (!isom_od) return GF_OUT_OF_MEM;
     315           0 :                                         isom_od->tag = GF_ODF_ISOM_IOD_TAG;
     316             :                                         //copy PL
     317           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag;
     318           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel;
     319           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel;
     320           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel;
     321           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel;
     322           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel;
     323           0 :                                         ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList;
     324           0 :                                         ((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL;
     325             :                                 }
     326             :                                 //in OD stream only ref desc are accepted
     327         117 :                                 isom_od->ES_ID_RefDescriptors = gf_list_new();
     328         117 :                                 isom_od->ES_ID_IncDescriptors = NULL;
     329             : 
     330             :                                 //TO DO: check that a given sampleDescription exists
     331         117 :                                 isom_od->extensionDescriptors = od->extensionDescriptors;
     332         117 :                                 od->extensionDescriptors = NULL;
     333         117 :                                 isom_od->IPMP_Descriptors = od->IPMP_Descriptors;
     334         117 :                                 od->IPMP_Descriptors = NULL;
     335         117 :                                 isom_od->OCIDescriptors = od->OCIDescriptors;
     336         117 :                                 od->OCIDescriptors = NULL;
     337         117 :                                 isom_od->URLString = od->URLString;
     338         117 :                                 od->URLString = NULL;
     339         117 :                                 isom_od->objectDescriptorID = od->objectDescriptorID;
     340             : 
     341         117 :                                 j=0;
     342         346 :                                 while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) {
     343         112 :                                         ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
     344         112 :                                         if (!esd->ESID) {
     345           0 :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISOM] Missing ESID on ESD, cannot add track reference in OD frame"));
     346             :                                                 e = GF_BAD_PARAM;
     347             :                                                 goto err_exit;
     348             :                                         }
     349             :                                         //1 to 1 mapping trackID and ESID. Add this track to MPOD
     350             :                                         //if track does not exist, this will be remove while reading the OD stream
     351         112 :                                         e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
     352         112 :                                         if (e) goto err_exit;
     353         112 :                                         e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref);
     354         112 :                                         if (e) goto err_exit;
     355             :                                 }
     356             :                                 //delete our desc
     357         117 :                                 gf_odf_desc_del((GF_Descriptor *)od);
     358             :                                 //and add the new one to our command
     359         117 :                                 gf_list_add(odU2->objectDescriptors, isom_od);
     360             :                         }
     361             :                         //delete the command
     362          57 :                         gf_odf_com_del((GF_ODCom **)&odU);
     363             :                         //and add the new one to the codec
     364          57 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
     365          57 :                         break;
     366             : 
     367             :                 //Rewrite ESD Update
     368           3 :                 case GF_ODF_ESD_UPDATE_TAG:
     369           3 :                         esdU = (GF_ESDUpdate *) com;
     370           3 :                         esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
     371           3 :                         esdU2->ODID = esdU->ODID;
     372           3 :                         i=0;
     373           9 :                         while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) {
     374           3 :                                 ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
     375             :                                 //1 to 1 mapping trackID and ESID
     376           3 :                                 e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
     377           3 :                                 if (e) goto err_exit;
     378           3 :                                 e = gf_list_add(esdU2->ESDescriptors, ref);
     379           3 :                                 if (e) goto err_exit;
     380             :                         }
     381           3 :                         gf_odf_com_del((GF_ODCom **)&esdU);
     382           3 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
     383           3 :                         break;
     384             : 
     385             :                 //Brand new case: the ESRemove has to be rewritten too according to the specs...
     386           9 :                 case GF_ODF_ESD_REMOVE_TAG:
     387             :                         esdR = (GF_ESDRemove *) com;
     388           9 :                         esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
     389             :                         //change the tag for the file format
     390           9 :                         esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG;
     391           9 :                         esdR2->ODID = esdR->ODID;
     392           9 :                         esdR2->NbESDs = esdR->NbESDs;
     393           9 :                         if (esdR->NbESDs) {
     394             :                                 //alloc our stuff
     395           9 :                                 esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
     396           9 :                                 if (!esdR2->ES_ID) {
     397             :                                         e = GF_OUT_OF_MEM;
     398             :                                         goto err_exit;
     399             :                                 }
     400          18 :                                 for (i = 0; i < esdR->NbESDs; i++) {
     401             :                                         //1 to 1 mapping trackID and ESID
     402           9 :                                         e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
     403           9 :                                         if (e) goto err_exit;
     404             :                                 }
     405             :                         }
     406           9 :                         gf_odf_com_del(&com);
     407           9 :                         gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
     408           9 :                         break;
     409             : 
     410             :                 //Add the command as is
     411           9 :                 default:
     412           9 :                         e = gf_odf_codec_add_com(ODencode, com);
     413           9 :                         if (e) goto err_exit;
     414             :                 }
     415             :         }
     416             : 
     417             :         //encode our new AU
     418          78 :         e = gf_odf_codec_encode(ODencode, 1);
     419          78 :         if (e) goto err_exit;
     420             : 
     421             :         //and set the buffer in the sample
     422          78 :         *od_samp = gf_isom_sample_new();
     423          78 :         (*od_samp)->CTS_Offset = sample->CTS_Offset;
     424          78 :         (*od_samp)->DTS = sample->DTS;
     425          78 :         (*od_samp)->IsRAP = sample->IsRAP;
     426          78 :         e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength);
     427          78 :         if (e) {
     428           0 :                 gf_isom_sample_del(od_samp);
     429           0 :                 *od_samp = NULL;
     430             :         }
     431             : 
     432         156 : err_exit:
     433             : 
     434          78 :         gf_odf_codec_del(ODencode);
     435          78 :         gf_odf_codec_del(ODdecode);
     436          78 :         return e;
     437             : }
     438             : 
     439             : 
     440             : 
     441             : // Rewrite the good dependencies when an OD AU is extracted from the file
     442           1 : static u32 Media_FindOD_ID(GF_MediaBox *mdia, GF_ISOSample *sample, u32 track_id)
     443             : {
     444             :         GF_Err e;
     445             :         GF_ODCodec *ODdecode;
     446             :         GF_ODCom *com;
     447             :         u32 the_od_id;
     448             :         GF_ODUpdate *odU;
     449             :         GF_ESD *esd;
     450             :         GF_Descriptor *desc;
     451             :         GF_TrackReferenceTypeBox *mpod;
     452             :         u32 i, j;
     453             : 
     454           1 :         if (!mdia || !sample || !sample->data || !sample->dataLength) return 0;
     455             : 
     456           1 :         mpod = NULL;
     457           1 :         e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
     458           1 :         if (e) return 0;
     459             :         //no references, nothing to do...
     460           1 :         if (!mpod) return 0;
     461             : 
     462             :         the_od_id = 0;
     463             : 
     464           1 :         ODdecode = gf_odf_codec_new();
     465           1 :         if (!ODdecode) return 0;
     466           1 :         e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
     467           1 :         if (e) goto err_exit;
     468           1 :         e = gf_odf_codec_decode(ODdecode);
     469           1 :         if (e) goto err_exit;
     470             : 
     471             :         while (1) {
     472             :                 GF_List *esd_list = NULL;
     473           2 :                 com = gf_odf_codec_get_com(ODdecode);
     474           2 :                 if (!com) break;
     475           1 :                 if (com->tag != GF_ODF_OD_UPDATE_TAG) continue;
     476           1 :                 odU = (GF_ODUpdate *) com;
     477             : 
     478           1 :                 i=0;
     479           3 :                 while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
     480           1 :                         switch (desc->tag) {
     481           0 :                         case GF_ODF_OD_TAG:
     482             :                         case GF_ODF_IOD_TAG:
     483           0 :                                 esd_list = ((GF_ObjectDescriptor *)desc)->ESDescriptors;
     484             :                                 break;
     485           1 :                         default:
     486           1 :                                 continue;
     487             :                         }
     488           0 :                         j=0;
     489           0 :                         while ((esd = (GF_ESD*)gf_list_enum( esd_list, &j))) {
     490           0 :                                 if (esd->ESID==track_id) {
     491           0 :                                         the_od_id = ((GF_IsomObjectDescriptor*)desc)->objectDescriptorID;
     492           0 :                                         break;
     493             :                                 }
     494             :                         }
     495           0 :                         if (the_od_id) break;
     496             :                 }
     497           1 :                 gf_odf_com_del((GF_ODCom **)&odU);
     498           1 :                 if (the_od_id) break;
     499             :         }
     500             : 
     501           1 : err_exit:
     502           1 :         gf_odf_codec_del(ODdecode);
     503           1 :         return the_od_id; //still 0 if error, no need to check for e
     504             : }
     505             : 
     506             : 
     507             : GF_EXPORT
     508           1 : u32 gf_isom_find_od_id_for_track(GF_ISOFile *file, u32 track)
     509             : {
     510             :         u32 i, j, di, the_od_id;
     511             :         GF_TrackBox *od_tk;
     512           1 :         GF_TrackBox *tk = gf_isom_get_track_from_file(file, track);
     513           1 :         if (!tk) return 0;
     514             : 
     515           1 :         i=0;
     516           4 :         while ( (od_tk = (GF_TrackBox*)gf_list_enum(file->moov->trackList, &i))) {
     517           2 :                 if (od_tk->Media->handler->handlerType != GF_ISOM_MEDIA_OD) continue;
     518             : 
     519           2 :                 for (j=0; j<od_tk->Media->information->sampleTable->SampleSize->sampleCount; j++) {
     520           1 :                         GF_ISOSample *samp = gf_isom_get_sample(file, i, j+1, &di);
     521           1 :                         the_od_id = Media_FindOD_ID(od_tk->Media, samp, tk->Header->trackID);
     522           1 :                         gf_isom_sample_del(&samp);
     523           1 :                         if (the_od_id) return the_od_id;
     524             :                 }
     525             :         }
     526             :         return 0;
     527             : }
     528             : 
     529             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13