LCOV - code coverage report
Current view: top level - isomedia - track.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 635 813 78.1 %
Date: 2021-04-29 23:48:07 Functions: 13 13 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-2020
       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             : #include <gpac/constants.h>
      28             : 
      29             : #ifndef GPAC_DISABLE_ISOM
      30             : 
      31          56 : GF_TrackBox *GetTrackbyID(GF_MovieBox *moov, GF_ISOTrackID TrackID)
      32             : {
      33             :         GF_TrackBox *trak;
      34             :         u32 i;
      35          56 :         if (!moov) return NULL;
      36          56 :         i=0;
      37         139 :         while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) {
      38          81 :                 if (trak->Header->trackID == TrackID) return trak;
      39             :         }
      40             :         return NULL;
      41             : }
      42             : 
      43     6158961 : GF_TrackBox *gf_isom_get_track(GF_MovieBox *moov, u32 trackNumber)
      44             : {
      45             :         GF_TrackBox *trak;
      46     6158961 :         if (!moov || !trackNumber || (trackNumber > gf_list_count(moov->trackList))) return NULL;
      47     6157736 :         trak = (GF_TrackBox*)gf_list_get(moov->trackList, trackNumber - 1);
      48     6157736 :         return trak;
      49             : 
      50             : }
      51             : 
      52             : //get the number of a track given its ID
      53             : //return 0 if not found error
      54      101153 : u32 gf_isom_get_tracknum_from_id(GF_MovieBox *moov, GF_ISOTrackID trackID)
      55             : {
      56             :         u32 i;
      57             :         GF_TrackBox *trak;
      58      101153 :         i=0;
      59      346954 :         while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) {
      60      245801 :                 if (trak->Header->trackID == trackID) return i;
      61             :         }
      62             :         return 0;
      63             : }
      64             : 
      65             : //extraction of the ESD from the track
      66        1902 : GF_Err GetESD(GF_MovieBox *moov, GF_ISOTrackID trackID, u32 StreamDescIndex, GF_ESD **outESD)
      67             : {
      68             :         GF_Err e;
      69             :         GF_ESD *esd;
      70             :         u32 track_num = 0;
      71             :         u32 k;
      72             :         GF_SampleTableBox *stbl;
      73             :         GF_TrackBox *trak, *OCRTrack;
      74             :         GF_TrackReferenceTypeBox *dpnd;
      75             :         GF_SLConfig *slc;
      76             :         GF_MPEGSampleEntryBox *entry;
      77             : 
      78        1902 :         if (!moov) return GF_ISOM_INVALID_FILE;
      79             : 
      80        1902 :         track_num = gf_isom_get_tracknum_from_id(moov, trackID);
      81        1902 :         dpnd = NULL;
      82        1902 :         *outESD = NULL;
      83             : 
      84        1902 :         trak = gf_isom_get_track(moov, track_num);
      85        1902 :         if (!trak) return GF_ISOM_INVALID_FILE;
      86             : 
      87        1902 :         e = Media_GetESD(trak->Media, StreamDescIndex, &esd, 0);
      88        1902 :         if (e) return e;
      89        1781 :         if (!esd) return GF_NON_COMPLIANT_BITSTREAM;
      90             : 
      91        1781 :         e = Media_GetSampleDesc(trak->Media, StreamDescIndex, (GF_SampleEntryBox **) &entry, NULL);
      92        1781 :         if (e) return e;
      93             :         //set the ID
      94        1781 :         esd->ESID = trackID;
      95             : 
      96             :         //find stream dependencies: dpnd, sbas and scal
      97        7085 :         for (k=0; k<3; k++) {
      98             :                 u32 ref = GF_ISOM_BOX_TYPE_DPND;
      99        5325 :                 if (k==1) ref = GF_ISOM_REF_BASE;
     100        3544 :                 else if (k==2) ref = GF_ISOM_REF_SCAL;
     101             : 
     102        5325 :                 e = Track_FindRef(trak, ref , &dpnd);
     103        5325 :                 if (e) return e;
     104        5325 :                 if (dpnd) {
     105             :                         //ONLY ONE STREAM DEPENDENCY IS ALLOWED
     106          21 :                         if (!k && (dpnd->trackIDCount != 1)) return GF_ISOM_INVALID_MEDIA;
     107             :                         //fix the spec: where is the index located ??
     108          21 :                         esd->dependsOnESID = dpnd->trackIDs[0];
     109          21 :                         break;
     110             :                 } else {
     111        5304 :                         esd->dependsOnESID = 0;
     112             :                 }
     113             :         }
     114             : 
     115        1781 :         if (trak->udta) {
     116             :                 GF_UserDataMap *map;
     117           9 :                 u32 i = 0;
     118          25 :                 while ((map = (GF_UserDataMap*)gf_list_enum(trak->udta->recordList, &i))) {
     119           9 :                         if (map->boxType == GF_ISOM_BOX_TYPE_AUXV) {
     120           2 :                                 GF_Descriptor *d = gf_odf_desc_new(GF_ODF_AUX_VIDEO_DATA);
     121           2 :                                 gf_list_add(esd->extensionDescriptors, d);
     122           2 :                                 break;
     123             :                         }
     124             :                 }
     125             :         }
     126             : 
     127             :         //OK, get the OCR (in a REAL MP4File, OCR is 0 in ESD and is specified through track reference
     128        1781 :         dpnd = NULL;
     129             :         OCRTrack = NULL;
     130             :         //find OCR dependencies
     131        1781 :         e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_SYNC, &dpnd);
     132        1781 :         if (e) return e;
     133        1781 :         if (dpnd) {
     134          58 :                 if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
     135          58 :                 esd->OCRESID = dpnd->trackIDs[0];
     136          58 :                 OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);
     137             : 
     138         116 :                 while (OCRTrack) {
     139             :                         /*if we have a dependency on a track that doesn't have OCR dep, remove that dependency*/
     140          58 :                         e = Track_FindRef(OCRTrack, GF_ISOM_BOX_TYPE_SYNC, &dpnd);
     141          58 :                         if (e || !dpnd || !dpnd->trackIDCount) {
     142             :                                 OCRTrack = NULL;
     143             :                                 goto default_sync;
     144             :                         }
     145             :                         /*this is explicit desync*/
     146          46 :                         if ((dpnd->trackIDs[0]==0) || (dpnd->trackIDs[0]==OCRTrack->Header->trackID))
     147             :                                 break;
     148             :                         /*loop in OCRs, break it*/
     149           0 :                         if (esd->ESID == (u16) OCRTrack->Header->trackID) {
     150             :                                 OCRTrack = NULL;
     151             :                                 goto default_sync;
     152             :                         }
     153             :                         /*check next*/
     154           0 :                         OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);
     155             :                 }
     156          46 :                 if (!OCRTrack) goto default_sync;
     157             :         } else {
     158        1723 : default_sync:
     159             :                 /*all tracks are sync'ed by default*/
     160        1735 :                 if (trak->moov->mov->es_id_default_sync<0) {
     161        1118 :                         if (esd->OCRESID)
     162           0 :                                 trak->moov->mov->es_id_default_sync = esd->OCRESID;
     163             :                         else
     164        1118 :                                 trak->moov->mov->es_id_default_sync = esd->ESID;
     165             :                 }
     166        1735 :                 if (trak->moov->mov->es_id_default_sync) esd->OCRESID = (u16) trak->moov->mov->es_id_default_sync;
     167             :                 /*cf ESD writer*/
     168        1735 :                 if (esd->OCRESID == esd->ESID) esd->OCRESID = 0;
     169             :         }
     170             : 
     171             : 
     172             : 
     173             :         //update the IPI stuff if needed
     174        1781 :         if (esd->ipiPtr != NULL) {
     175           0 :                 dpnd = NULL;
     176           0 :                 e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_IPIR, &dpnd);
     177           0 :                 if (e) return e;
     178           0 :                 if (dpnd) {
     179           0 :                         if (esd->ipiPtr->tag != GF_ODF_ISOM_IPI_PTR_TAG) return GF_ISOM_INVALID_FILE;
     180             :                         //OK, retrieve the ID: the IPI_ES_Id is currently the ref track
     181           0 :                         esd->ipiPtr->IPI_ES_Id = dpnd->trackIDs[esd->ipiPtr->IPI_ES_Id - 1];
     182             :                         //and change the tag
     183           0 :                         esd->ipiPtr->tag = GF_ODF_IPI_PTR_TAG;
     184             :                 } else {
     185             :                         return GF_ISOM_INVALID_FILE;
     186             :                 }
     187             :         }
     188             : 
     189        3562 :         if ((trak->Media->mediaHeader->packedLanguage[0] != 'u')
     190        1781 :                 || (trak->Media->mediaHeader->packedLanguage[1] != 'n')
     191        1757 :                 || (trak->Media->mediaHeader->packedLanguage[2] != 'd') ) {
     192          24 :                 if (!esd->langDesc) esd->langDesc = (GF_Language *) gf_odf_desc_new(GF_ODF_LANG_TAG);
     193             : 
     194          24 :                 esd->langDesc->langCode = trak->Media->mediaHeader->packedLanguage[0];
     195          24 :                 esd->langDesc->langCode <<= 8;
     196          24 :                 esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[1];
     197          24 :                 esd->langDesc->langCode <<= 8;
     198          24 :                 esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[2];
     199             :         }
     200             : 
     201             : 
     202             :         {
     203             :                 u16 rvc_predefined;
     204             :                 u8 *rvc_cfg_data;
     205             :                 const char *mime_type;
     206             :                 u32 rvc_cfg_size;
     207        1781 :                 e = gf_isom_get_rvc_config(moov->mov, track_num, 1, &rvc_predefined, &rvc_cfg_data, &rvc_cfg_size, &mime_type);
     208        1781 :                 if (e==GF_OK) {
     209           0 :                         if (rvc_predefined) {
     210           0 :                                 esd->decoderConfig->predefined_rvc_config = rvc_predefined;
     211             :                         } else {
     212           0 :                                 esd->decoderConfig->rvc_config = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
     213           0 :                                 if (mime_type && !strcmp(mime_type, "application/rvc-config+xml+gz") ) {
     214             : #if !defined(GPAC_DISABLE_CORE_TOOLS) && !defined(GPAC_DISABLE_ZLIB)
     215           0 :                                         gf_gz_decompress_payload(rvc_cfg_data, rvc_cfg_size, &esd->decoderConfig->rvc_config->data, &esd->decoderConfig->rvc_config->dataLength);
     216           0 :                                         gf_free(rvc_cfg_data);
     217             : #endif
     218             :                                 } else {
     219           0 :                                         esd->decoderConfig->rvc_config->data = rvc_cfg_data;
     220           0 :                                         esd->decoderConfig->rvc_config->dataLength = rvc_cfg_size;
     221             :                                 }
     222             :                         }
     223             :                 }
     224             :         }
     225             : 
     226             : 
     227             :         /*normally all files shall be stored with predefined=SLPredef_MP4, but of course some are broken (philips)
     228             :         so we just check the ESD_URL. If set, use the given cfg, otherwise always rewrite it*/
     229        1781 :         if (esd->URLString != NULL) {
     230           0 :                 *outESD = esd;
     231           0 :                 return GF_OK;
     232             :         }
     233             : 
     234             :         //if we are in publishing mode and we have an SLConfig specified, use it as is
     235        1781 :         switch (entry->type) {
     236         218 :         case GF_ISOM_BOX_TYPE_MP4V:
     237         218 :                 slc = ((GF_MPEGVisualSampleEntryBox *)entry)->slc;
     238         218 :                 break;
     239         322 :         case GF_ISOM_BOX_TYPE_MP4A:
     240         322 :                 slc = ((GF_MPEGAudioSampleEntryBox *)entry)->slc;
     241         322 :                 break;
     242         273 :         case GF_ISOM_BOX_TYPE_MP4S:
     243         273 :                 slc = entry->slc;
     244         273 :                 break;
     245             :         default:
     246             :                 slc = NULL;
     247             :                 break;
     248             :         }
     249         813 :         if (slc) {
     250         103 :                 gf_odf_desc_del((GF_Descriptor *)esd->slConfig);
     251         103 :                 gf_odf_desc_copy((GF_Descriptor *)slc, (GF_Descriptor **)&esd->slConfig);
     252         103 :                 *outESD = esd;
     253         103 :                 return GF_OK;
     254             :         }
     255             :         //otherwise use the regular mapping
     256             : 
     257        1678 :         if (!esd->slConfig)
     258           0 :                 esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
     259             : 
     260             :         //this is a desc for a media in the file, let's rewrite some param
     261        1678 :         esd->slConfig->timestampLength = 32;
     262        1678 :         esd->slConfig->timestampResolution = trak->Media->mediaHeader->timeScale;
     263             :         //NO OCR from MP4File streams (eg, constant OC Res one)
     264        1678 :         esd->slConfig->OCRLength = 0;
     265        1678 :         esd->slConfig->OCRResolution = 0;
     266             : //      if (OCRTrack) esd->slConfig->OCRResolution = OCRTrack->Media->mediaHeader->timeScale;
     267             : 
     268        1678 :         stbl = trak->Media->information->sampleTable;
     269             :         // a little optimization here: if all our samples are sync,
     270             :         //set the RAPOnly to true... for external users...
     271        1678 :         if (! stbl->SyncSample) {
     272         781 :                 if (
     273             : #ifndef GPAC_DISABLE_ISOM_FRAGMENTS
     274        1003 :                     moov->mvex &&
     275             : #endif
     276         444 :                     esd->decoderConfig && esd->decoderConfig->streamType &&
     277             :                     (esd->decoderConfig->streamType==GF_STREAM_VISUAL)
     278             :                 ) {
     279         160 :                         esd->slConfig->hasRandomAccessUnitsOnlyFlag = 0;
     280         160 :                         esd->slConfig->useRandomAccessPointFlag = 1;
     281         160 :                         if (trak->moov->mov->openMode!=GF_ISOM_OPEN_READ) {
     282           0 :                                 stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSS);
     283           0 :                                 if (!stbl->SyncSample) return GF_OUT_OF_MEM;
     284             :                         }
     285             :                 } else {
     286         621 :                         esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;
     287         621 :                         esd->slConfig->useRandomAccessPointFlag = 0;
     288             :                 }
     289             :         } else {
     290         897 :                 esd->slConfig->hasRandomAccessUnitsOnlyFlag = 0;
     291             :                 //signal we are NOT using sync points if no info is present in the table
     292         897 :                 esd->slConfig->useRandomAccessPointFlag = stbl->SyncSample->nb_entries ? 1 : 0;
     293             :         }
     294             :         //change to support reflecting OD streams
     295        1678 :         esd->slConfig->useAccessUnitEndFlag = 1;
     296        1678 :         esd->slConfig->useAccessUnitStartFlag = 1;
     297             : 
     298             :         //signal we do have padding flag (since we only use logical SL packet
     299             :         //the user can decide whether to use the info or not
     300        1678 :         esd->slConfig->usePaddingFlag = stbl->PaddingBits ? 1 : 0;
     301             : 
     302             :         //same with degradation priority
     303        1678 :         esd->slConfig->degradationPriorityLength = stbl->DegradationPriority ? 32 : 0;
     304             : 
     305             :         //this new SL will be OUT OF THE FILE. Let's set its predefined to 0
     306        1678 :         esd->slConfig->predefined = 0;
     307             : 
     308             : 
     309        1678 :         *outESD = esd;
     310        1678 :         return GF_OK;
     311             : }
     312             : 
     313             : 
     314             : //extraction of the ESD from the track for the given time
     315         187 : GF_Err GetESDForTime(GF_MovieBox *moov, GF_ISOTrackID trackID, u64 CTS, GF_ESD **outESD)
     316             : {
     317             :         GF_Err e;
     318             :         u32 sampleDescIndex;
     319             :         GF_TrackBox *trak;
     320             : 
     321         187 :         trak = gf_isom_get_track(moov, gf_isom_get_tracknum_from_id(moov, trackID));
     322         187 :         if (!trak) return GF_ISOM_INVALID_FILE;
     323             : 
     324         187 :         e = Media_GetSampleDescIndex(trak->Media, CTS, &sampleDescIndex );
     325         187 :         if (e) return e;
     326         187 :         return GetESD(moov, trackID, sampleDescIndex, outESD);
     327             : }
     328             : 
     329             : 
     330      619935 : GF_Err Track_FindRef(GF_TrackBox *trak, u32 ReferenceType, GF_TrackReferenceTypeBox **dpnd)
     331             : {
     332             :         GF_TrackReferenceBox *ref;
     333             :         GF_TrackReferenceTypeBox *a;
     334             :         u32 i;
     335      619935 :         if (! trak) return GF_BAD_PARAM;
     336      619935 :         if (! trak->References) {
     337      223779 :                 *dpnd = NULL;
     338      223779 :                 return GF_OK;
     339             :         }
     340             :         ref = trak->References;
     341      396156 :         i=0;
     342      924034 :         while ((a = (GF_TrackReferenceTypeBox *)gf_list_enum(ref->child_boxes, &i))) {
     343      407498 :                 if (a->reference_type == ReferenceType) {
     344      275776 :                         *dpnd = a;
     345      275776 :                         return GF_OK;
     346             :                 }
     347             :         }
     348      120380 :         *dpnd = NULL;
     349      120380 :         return GF_OK;
     350             : }
     351             : 
     352        3792 : Bool Track_IsMPEG4Stream(u32 HandlerType)
     353             : {
     354        3792 :         switch (HandlerType) {
     355             :         case GF_ISOM_MEDIA_VISUAL:
     356             :     case GF_ISOM_MEDIA_AUXV:
     357             :     case GF_ISOM_MEDIA_PICT:
     358             :         case GF_ISOM_MEDIA_AUDIO:
     359             :         case GF_ISOM_MEDIA_SUBPIC:
     360             :         case GF_ISOM_MEDIA_OD:
     361             :         case GF_ISOM_MEDIA_OCR:
     362             :         case GF_ISOM_MEDIA_SCENE:
     363             :         case GF_ISOM_MEDIA_MPEG7:
     364             :         case GF_ISOM_MEDIA_OCI:
     365             :         case GF_ISOM_MEDIA_IPMP:
     366             :         case GF_ISOM_MEDIA_MPEGJ:
     367             :         case GF_ISOM_MEDIA_ESM:
     368             :                 return 1;
     369             :         /*Timedtext is NOT an MPEG-4 stream*/
     370          40 :         default:
     371             :                 /*consider xxsm as MPEG-4 handlers*/
     372          40 :                 if ( (((HandlerType>>8) & 0xFF)== 's') && ((HandlerType& 0xFF)== 'm'))
     373             :                         return 1;
     374          40 :                 return 0;
     375             :         }
     376             : }
     377             : 
     378             : 
     379      586785 : GF_Err SetTrackDuration(GF_TrackBox *trak)
     380             : {
     381             :         u64 trackDuration;
     382             :         u32 i;
     383             :         GF_Err e;
     384             : 
     385             :         //the total duration is the media duration: adjust it in case...
     386      586785 :         e = Media_SetDuration(trak);
     387      586785 :         if (e) return e;
     388             : 
     389             :         //assert the timeScales are non-NULL
     390      586785 :         if (!trak->moov->mvhd || !trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE;
     391      586785 :         trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale;
     392             : 
     393             :         //if we have an edit list, the duration is the sum of all the editList
     394             :         //entries' duration (always expressed in MovieTimeScale)
     395      586785 :         if (trak->editBox && trak->editBox->editList) {
     396             :                 GF_EdtsEntry *ent;
     397             :                 GF_EditListBox *elst = trak->editBox->editList;
     398             :                 trackDuration = 0;
     399       30863 :                 i=0;
     400      104135 :                 while ((ent = (GF_EdtsEntry*)gf_list_enum(elst->entryList, &i))) {
     401       42409 :                         trackDuration += ent->segmentDuration;
     402             :                 }
     403             :         }
     404      586785 :         if (!trackDuration) {
     405       12889 :                 trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale;
     406             :         }
     407      586785 :         if (!trak->Header) {
     408             :                 return GF_OK;
     409             :         }
     410      586785 :         trak->Header->duration = trackDuration;
     411      586785 :         if (!trak->moov->mov->keep_utc && !gf_sys_is_test_mode() )
     412         746 :                 trak->Header->modificationTime = gf_isom_get_mp4time();
     413             :         return GF_OK;
     414             : }
     415             : 
     416             : 
     417             : #ifndef GPAC_DISABLE_ISOM_FRAGMENTS
     418             : 
     419             : #ifdef GF_ENABLE_CTRN
     420             : GF_TrunEntry *traf_get_sample_entry(GF_TrackFragmentBox *traf, u32 sample_index)
     421             : {
     422             :         u32 i, idx;
     423             :         GF_TrackFragmentRunBox *trun;
     424             :         idx=0;
     425             :         i=0;
     426             :         while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {
     427             :                 u32 j;
     428             :                 for (j=0; j<trun->sample_count; j++) {
     429             :                         GF_TrunEntry *ent = gf_list_get(trun->entries, j);
     430             :                         if (idx==sample_index) return ent;
     431             :                         if (ent->nb_pack>1) {
     432             :                                 if (idx < sample_index + ent->nb_pack)
     433             :                                         return ent;
     434             :                                 idx += ent->nb_pack;
     435             :                         } else {
     436             :                                 idx++;
     437             :                         }
     438             :                 }
     439             :         }
     440             :         return NULL;
     441             : }
     442             : #endif
     443             : 
     444             : 
     445        4079 : GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, GF_MovieFragmentBox *moof_box, u64 moof_offset, s32 compressed_diff, u64 *cumulated_offset, Bool is_first_merge)
     446             : {
     447             :         u32 i, j, chunk_size, track_num;
     448             :         u64 base_offset, data_offset, traf_duration;
     449             :         u32 def_duration, DescIndex, def_size, def_flags;
     450             :         u32 duration, size, flags, prev_trun_data_offset, sample_index;
     451             :         u8 pad, sync;
     452             :         u16 degr;
     453             :         Bool first_samp_in_traf=GF_TRUE;
     454             :         Bool store_traf_map=GF_FALSE;
     455        4079 :         u8 *moof_template=NULL;
     456        4079 :         u32 moof_template_size=0;
     457             :         Bool is_seg_start = GF_FALSE;
     458             :         u64 seg_start=0, sidx_start=0, sidx_end=0, frag_start=0, last_dts=0;
     459             :         GF_TrackFragmentRunBox *trun;
     460             :         GF_TrunEntry *ent;
     461             : #ifdef GF_ENABLE_CTRN
     462             :         GF_TrackFragmentBox *traf_ref = NULL;
     463             : #endif
     464             : 
     465             :         GF_Err stbl_AppendTime(GF_SampleTableBox *stbl, u32 duration, u32 nb_pack);
     466             :         GF_Err stbl_AppendSize(GF_SampleTableBox *stbl, u32 size, u32 nb_pack);
     467             :         GF_Err stbl_AppendChunk(GF_SampleTableBox *stbl, u64 offset);
     468             :         GF_Err stbl_AppendSampleToChunk(GF_SampleTableBox *stbl, u32 DescIndex, u32 samplesInChunk);
     469             :         GF_Err stbl_AppendCTSOffset(GF_SampleTableBox *stbl, s32 CTSOffset);
     470             :         GF_Err stbl_AppendRAP(GF_SampleTableBox *stbl, u8 isRap);
     471             :         GF_Err stbl_AppendPadding(GF_SampleTableBox *stbl, u8 padding);
     472             :         GF_Err stbl_AppendDegradation(GF_SampleTableBox *stbl, u16 DegradationPriority);
     473             : 
     474        4079 :         if (trak->Header->trackID != traf->tfhd->trackID) return GF_OK;
     475        4079 :         if (!trak->Media->information->sampleTable
     476        4079 :                 || !trak->Media->information->sampleTable->SampleSize
     477        4079 :                 || !trak->Media->information->sampleTable->TimeToSample
     478        4079 :                 || !trak->Media->information->sampleTable->SampleToChunk
     479        4079 :                 || !trak->Media->information->sampleTable->ChunkOffset
     480             :         ) {
     481             :                 return GF_ISOM_INVALID_FILE;
     482             :         }
     483             : 
     484        4079 :         if (!traf->trex->track)
     485         316 :                 traf->trex->track = trak;
     486             : 
     487             :         //setup all our defaults
     488        4079 :         DescIndex = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_DESC) ? traf->tfhd->sample_desc_index : traf->trex->def_sample_desc_index;
     489        4079 :         if (!DescIndex) {
     490           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] default sample description set to 0, likely broken ! Fixing to 1\n" ));
     491             :                 DescIndex = 1;
     492        4079 :         } else if (DescIndex > gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes)) {
     493           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] default sample description set to %d but only %d sample description(s), likely broken ! Fixing to 1\n", DescIndex, gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes)));
     494             :                 DescIndex = 1;
     495             :         }
     496             : #ifdef GF_ENABLE_CTRN
     497             :         if (traf->trex->inherit_from_traf_id) {
     498             :                 u32 traf_count = gf_list_count(moof_box->TrackList);
     499             :                 for (i=0; i<traf_count; i++) {
     500             :                         GF_TrackFragmentBox *atraf = gf_list_get(moof_box->TrackList, i);
     501             :                         if (atraf->tfhd && atraf->tfhd->trackID==traf->trex->inherit_from_traf_id) {
     502             :                                 traf_ref = atraf;
     503             :                                 break;
     504             :                         }
     505             :                 }
     506             :         }
     507             : #endif
     508             : 
     509        4079 :         def_duration = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_DUR) ? traf->tfhd->def_sample_duration : traf->trex->def_sample_duration;
     510        4079 :         def_size = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_SIZE) ? traf->tfhd->def_sample_size : traf->trex->def_sample_size;
     511        4079 :         def_flags = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_FLAGS) ? traf->tfhd->def_sample_flags : traf->trex->def_sample_flags;
     512             : 
     513             :         //locate base offset, by default use moof (dash-like)
     514             :         base_offset = moof_offset;
     515             :         //explicit base offset, use it
     516        4079 :         if (traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET)
     517          51 :                 base_offset = traf->tfhd->base_data_offset;
     518             :         //no moof offset and no explicit offset, the offset is the end of the last written chunk of
     519             :         //the previous traf. For the first traf, *cumulated_offset is actually moof offset
     520        4028 :         else if (!(traf->tfhd->flags & GF_ISOM_MOOF_BASE_OFFSET))
     521          32 :                 base_offset = *cumulated_offset;
     522             : 
     523             :         chunk_size = 0;
     524             :         prev_trun_data_offset = 0;
     525             :         data_offset = 0;
     526             :         traf_duration = 0;
     527             : 
     528             :         /*in playback mode*/
     529        4079 :         if (traf->tfdt && is_first_merge) {
     530             : #ifndef GPAC_DISABLE_LOG
     531        3071 :                 if (trak->moov->mov->NextMoofNumber && trak->present_in_scalable_segment && trak->sample_count_at_seg_start && (trak->dts_at_seg_start != traf->tfdt->baseMediaDecodeTime)) {
     532           0 :                         s32 drift = (s32) ((s64) traf->tfdt->baseMediaDecodeTime - (s64)trak->dts_at_seg_start);
     533           0 :                         if (drift<0)  {
     534           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Warning: TFDT timing "LLD" less than cumulated timing "LLD" - using tfdt\n", traf->tfdt->baseMediaDecodeTime, trak->dts_at_seg_start ));
     535             :                         } else {
     536           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[iso file] TFDT timing "LLD" higher than cumulated timing "LLD" (last sample got extended in duration)\n", traf->tfdt->baseMediaDecodeTime, trak->dts_at_seg_start ));
     537             :                         }
     538             :                 }
     539             : #endif
     540        3071 :                 trak->dts_at_seg_start = traf->tfdt->baseMediaDecodeTime;
     541             :         }
     542        1008 :         else if (traf->tfxd) {
     543           3 :                 trak->dts_at_seg_start = traf->tfxd->absolute_time_in_track_timescale;
     544             :         }
     545             : 
     546        4079 :         if (traf->tfxd) {
     547           3 :                 trak->last_tfxd_value = traf->tfxd->absolute_time_in_track_timescale;
     548           3 :                 trak->last_tfxd_value += traf->tfxd->fragment_duration_in_track_timescale;
     549             :         }
     550        4079 :         if (traf->tfrf) {
     551           0 :                 if (trak->tfrf) gf_isom_box_del_parent(&trak->child_boxes, (GF_Box *)trak->tfrf);
     552           0 :                 trak->tfrf = traf->tfrf;
     553           0 :                 gf_list_del_item(traf->child_boxes, traf->tfrf);
     554           0 :                 gf_list_add(trak->child_boxes, trak->tfrf);
     555             :         }
     556             : 
     557        4079 :         if (trak->moov->mov->signal_frag_bounds) {
     558             :                 store_traf_map = GF_TRUE;
     559         195 :                 if (is_first_merge) {
     560          87 :                         GF_MovieFragmentBox *moof_clone = NULL;
     561          87 :                         gf_isom_box_freeze_order((GF_Box *)moof_box);
     562          87 :                         gf_isom_clone_box((GF_Box *)moof_box, (GF_Box **)&moof_clone);
     563             : 
     564          87 :                         if (moof_clone) {
     565             :                                 GF_BitStream *bs;
     566         174 :                                 for (i=0; i<gf_list_count(moof_clone->TrackList); i++) {
     567          87 :                                         GF_TrackFragmentBox *traf_clone = gf_list_get(moof_clone->TrackList, i);
     568          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->TrackRuns);
     569          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->sampleGroups);
     570          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->sampleGroupsDescription);
     571          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->sub_samples);
     572          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->sai_offsets);
     573          87 :                                         gf_isom_box_array_reset_parent(&traf_clone->child_boxes, traf_clone->sai_sizes);
     574          87 :                                         if (traf_clone->sample_encryption) {
     575           0 :                                                 gf_isom_box_del_parent(&traf_clone->child_boxes, (GF_Box *) traf_clone->sample_encryption);
     576           0 :                                                 traf_clone->sample_encryption = NULL;
     577             :                                         }
     578          87 :                                         if (traf_clone->sdtp) {
     579           0 :                                                 gf_isom_box_del_parent(&traf_clone->child_boxes, (GF_Box *) traf_clone->sdtp);
     580           0 :                                                 traf_clone->sdtp = NULL;
     581             :                                         }
     582             :                                 }
     583          87 :                                 gf_isom_box_size((GF_Box *)moof_clone);
     584          87 :                                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     585             : 
     586          87 :                                 if (trak->moov->mov->seg_styp) {
     587          84 :                                         gf_isom_box_size(trak->moov->mov->seg_styp);
     588          84 :                                         gf_isom_box_write(trak->moov->mov->seg_styp, bs);
     589             :                                 }
     590          87 :                                 if (trak->moov->mov->root_sidx) {
     591          87 :                                         gf_isom_box_size((GF_Box *)trak->moov->mov->root_sidx);
     592          87 :                                         gf_isom_box_write((GF_Box *)trak->moov->mov->root_sidx, bs);
     593             :                                 }
     594          87 :                                 if (trak->moov->mov->seg_ssix) {
     595           0 :                                         gf_isom_box_size(trak->moov->mov->seg_ssix);
     596           0 :                                         gf_isom_box_write(trak->moov->mov->seg_ssix, bs);
     597             :                                 }
     598          87 :                                 gf_isom_box_write((GF_Box *)moof_clone, bs);
     599          87 :                                 gf_isom_box_del((GF_Box*)moof_clone);
     600             : 
     601          87 :                                 gf_bs_get_content(bs, &moof_template, &moof_template_size);
     602          87 :                                 gf_bs_del(bs);
     603             :                         }
     604             :                 }
     605         195 :                 if (trak->moov->mov->seg_styp) {
     606             :                         is_seg_start = GF_TRUE;
     607          84 :                         seg_start = trak->moov->mov->styp_start_offset;
     608             :                 }
     609         195 :                 if (trak->moov->mov->root_sidx) {
     610             :                         is_seg_start = GF_TRUE;
     611          87 :                         sidx_start = trak->moov->mov->sidx_start_offset;
     612          87 :                         sidx_end = trak->moov->mov->sidx_end_offset;
     613          87 :                         if (! seg_start || (sidx_start<seg_start))
     614             :                                 seg_start = sidx_start;
     615             :                 }
     616         195 :                 frag_start = trak->moov->mov->current_top_box_start;
     617             :         }
     618        3884 :         else if (trak->moov->mov->store_traf_map) {
     619             :                 store_traf_map = GF_TRUE;
     620             :         }
     621             : 
     622             : 
     623             :         sample_index = 0;
     624        4079 :         i=0;
     625       12282 :         while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {
     626             :                 //merge the run
     627      109375 :                 for (j=0; j<trun->sample_count; j++) {
     628             :                         GF_Err e;
     629             :                         s32 cts_offset=0;
     630      109375 :                         if (j<trun->nb_samples) {
     631      109375 :                                 ent = &trun->samples[j];
     632             :                         } else {
     633           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Track %d doesn't have enough trun entries (%d) compared to sample count (%d) in run\n", traf->trex->trackID, trun->nb_samples, trun->sample_count ));
     634             :                                 break;
     635             :                         }
     636             :                         size = def_size;
     637             :                         duration = def_duration;
     638             :                         flags = def_flags;
     639             : 
     640             :                         //CTS - if flag not set (trun or ctrn) defaults to 0 which is the base value after alloc
     641             :                         //we just need to overrite its value if inherited
     642      109375 :                         cts_offset = ent->CTS_Offset;
     643             : 
     644             : #ifdef GF_ENABLE_CTRN
     645             :                         if (trun->use_ctrn) {
     646             :                                 if (!j && (trun->ctrn_flags & GF_ISOM_CTRN_FIRST_SAMPLE) ) {
     647             :                                         if (trun->ctrn_first_dur) duration = ent->Duration;
     648             :                                         if (trun->ctrn_first_size) size = ent->size;
     649             :                                         if (trun->ctrn_first_ctts) flags = ent->flags;
     650             :                                 } else {
     651             :                                         if (trun->ctrn_dur) duration = ent->Duration;
     652             :                                         if (trun->ctrn_size) size = ent->size;
     653             :                                         if (trun->ctrn_sample_flags) flags = ent->flags;
     654             :                                 }
     655             :                                 /*re-override*/
     656             :                                 if (trun->ctrn_flags & 0xF0) {
     657             :                                         GF_TrunEntry *ref_entry;
     658             :                                         if (!traf_ref) {
     659             :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Track %d use traf inheritance to track ID %d but reference traf not found\n", traf->trex->trackID, traf->trex->inherit_from_traf_id ));
     660             :                                                 break;
     661             :                                         }
     662             :                                         ref_entry = traf_get_sample_entry(traf_ref, sample_index);
     663             :                                         if (!ref_entry) {
     664             :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Track %d use traf inheritance but sample %d not found in reference traf\n", traf->trex->trackID, sample_index+1 ));
     665             :                                                 break;
     666             :                                         }
     667             :                                         if (trun->ctrn_flags & GF_ISOM_CTRN_INHERIT_DUR)
     668             :                                                 duration = ref_entry->Duration;
     669             :                                         if (trun->ctrn_flags & GF_ISOM_CTRN_INHERIT_SIZE)
     670             :                                                 size = ref_entry->size;
     671             :                                         if (trun->ctrn_flags & GF_ISOM_CTRN_INHERIT_FLAGS)
     672             :                                                 flags = ref_entry->flags;
     673             :                                         if (trun->ctrn_flags & GF_ISOM_CTRN_INHERIT_CTSO)
     674             :                                                 cts_offset = ref_entry->CTS_Offset;
     675             :                                 }
     676             : 
     677             :                         } else
     678             : #endif
     679             :                         {
     680      114634 :                                 if (trun->flags & GF_ISOM_TRUN_DURATION) duration = ent->Duration;
     681      109375 :                                 if (trun->flags & GF_ISOM_TRUN_SIZE) size = ent->size;
     682      109375 :                                 if (trun->flags & GF_ISOM_TRUN_FLAGS) {
     683        6868 :                                         flags = ent->flags;
     684      102507 :                                 } else if (!j && (trun->flags & GF_ISOM_TRUN_FIRST_FLAG)) {
     685        3147 :                                         flags = trun->first_sample_flags;
     686             :                                 }
     687             :                         }
     688             :                         sample_index++;
     689             :                         /*store the resolved value in case we have inheritance*/
     690      109375 :                         ent->size = size;
     691      109375 :                         ent->Duration = duration;
     692      109375 :                         ent->flags = flags;
     693             :                         ent->CTS_Offset = cts_offset;
     694             : 
     695      109375 :                         last_dts += duration;
     696             : 
     697             :                         //add size first
     698      109375 :                         if (!trak->Media->information->sampleTable->SampleSize) {
     699           0 :                                 trak->Media->information->sampleTable->SampleSize = (GF_SampleSizeBox *) gf_isom_box_new_parent(&trak->Media->information->sampleTable->child_boxes, GF_ISOM_BOX_TYPE_STSZ);
     700           0 :                                 if (!trak->Media->information->sampleTable->SampleSize)
     701             :                                         return GF_OUT_OF_MEM;
     702             :                         }
     703      109375 :                         e = stbl_AppendSize(trak->Media->information->sampleTable, size, ent->nb_pack);
     704      109375 :                         if (e) return e;
     705             : 
     706             :                         //then TS
     707      109375 :                         if (!trak->Media->information->sampleTable->TimeToSample) {
     708           0 :                                 trak->Media->information->sampleTable->TimeToSample = (GF_TimeToSampleBox *) gf_isom_box_new_parent(&trak->Media->information->sampleTable->child_boxes, GF_ISOM_BOX_TYPE_STTS);
     709           0 :                                 if (!trak->Media->information->sampleTable->TimeToSample)
     710             :                                         return GF_OUT_OF_MEM;
     711             :                         }
     712      109375 :                         e = stbl_AppendTime(trak->Media->information->sampleTable, duration, ent->nb_pack);
     713      109375 :                         if (e) return e;
     714             : 
     715             :                         //add chunk on first sample
     716      109375 :                         if (!j) {
     717             :                                 u64 final_offset;
     718             :                                 data_offset = base_offset;
     719             :                                 //we have an explicit data offset for this trun
     720        4124 :                                 if (trun->flags & GF_ISOM_TRUN_DATA_OFFSET) {
     721        4083 :                                         data_offset += trun->data_offset;
     722             :                                         /*reset chunk size since data is now relative to this trun*/
     723             :                                         chunk_size = 0;
     724             :                                         /*remember this data offset for following trun*/
     725        4083 :                                         prev_trun_data_offset = trun->data_offset;
     726             :                                         /*if mdat is located after the moof, and the moof was compressed, adjust offset
     727             :                                         otherwise the offset does not need adjustment*/
     728        4083 :                                         if (trun->data_offset>=0) {
     729        4083 :                                                 data_offset -= compressed_diff;
     730        4083 :                                                 prev_trun_data_offset -= compressed_diff;
     731             :                                         }
     732             :                                 }
     733             :                                 //we had an explicit data offset for the previous trun, use it + chunk size
     734          41 :                                 else if (prev_trun_data_offset) {
     735             :                                         /*data offset is previous chunk size plus previous offset of the trun*/
     736           0 :                                         data_offset += prev_trun_data_offset + chunk_size;
     737             :                                 }
     738             :                                 //no explicit data offset, continuous data after last data in previous chunk
     739             :                                 else {
     740          41 :                                         data_offset += chunk_size;
     741             :                                         //data offset of first trun in first traf, adjust if compressed moof
     742          41 :                                         if ((i==1) && (trun->data_offset>=0)) {
     743          41 :                                                 data_offset -= compressed_diff;
     744             :                                         }
     745             :                                 }
     746             : 
     747             :                                 final_offset = data_offset;
     748             :                                 //adjust offset if moov was also compressed and we are still in the same file
     749             :                                 //so that later call to gf_isom_get_sample properly adjust back the offset
     750        4124 :                                 if (trak->moov->compressed_diff) {
     751          10 :                                         final_offset += trak->moov->compressed_diff;
     752             :                                 }
     753             : 
     754        4124 :                                 if (!trak->Media->information->sampleTable->ChunkOffset) {
     755           0 :                                         trak->Media->information->sampleTable->ChunkOffset = gf_isom_box_new_parent(&trak->Media->information->sampleTable->child_boxes, GF_ISOM_BOX_TYPE_STCO);
     756           0 :                                         if (!trak->Media->information->sampleTable->ChunkOffset)
     757             :                                                 return GF_OUT_OF_MEM;
     758             :                                 }
     759        4124 :                                 e = stbl_AppendChunk(trak->Media->information->sampleTable, final_offset);
     760        4124 :                                 if (e) return e;
     761             :                                 //then sampleToChunk
     762        4124 :                                 if (!trak->Media->information->sampleTable->SampleToChunk) {
     763           0 :                                         trak->Media->information->sampleTable->SampleToChunk = (GF_SampleToChunkBox *) gf_isom_box_new_parent(&trak->Media->information->sampleTable->child_boxes, GF_ISOM_BOX_TYPE_STSC);
     764           0 :                                         if (!trak->Media->information->sampleTable->SampleToChunk)
     765             :                                                 return GF_OUT_OF_MEM;
     766             :                                 }
     767        4124 :                                 e = stbl_AppendSampleToChunk(trak->Media->information->sampleTable,
     768             :                                                          DescIndex, trun->sample_count);
     769        4124 :                                 if (e) return e;
     770             :                         }
     771      109375 :                         chunk_size += size;
     772             : 
     773      109375 :                         if (store_traf_map && first_samp_in_traf) {
     774             :                                 first_samp_in_traf = GF_FALSE;
     775         195 :                                 e = stbl_AppendTrafMap(trak->Media->information->sampleTable, is_seg_start, seg_start, frag_start, moof_template, moof_template_size, sidx_start, sidx_end);
     776         195 :                                 if (e) return e;
     777             :                                 //do not deallocate, the memory is now owned by traf map
     778         195 :                                 moof_template = NULL;
     779         195 :                                 moof_template_size = 0;
     780             :                         }
     781      109375 :                         if (ent->nb_pack>1) {
     782         185 :                                 j+= ent->nb_pack-1;
     783         185 :                                 traf_duration += ent->nb_pack*duration;
     784         185 :                                 continue;
     785             :                         }
     786             : 
     787      109190 :                         traf_duration += duration;
     788             : 
     789      109190 :                         e = stbl_AppendCTSOffset(trak->Media->information->sampleTable, cts_offset);
     790      109190 :                         if (e) return e;
     791             :                         //flags
     792      109190 :                         sync = GF_ISOM_GET_FRAG_SYNC(flags);
     793      109190 :                         if (trak->Media->information->sampleTable->no_sync_found && sync) {
     794         291 :                                 trak->Media->information->sampleTable->no_sync_found = 0;
     795             :                         }
     796      109190 :                         e = stbl_AppendRAP(trak->Media->information->sampleTable, sync);
     797      109190 :                         if (e) return e;
     798      109190 :                         pad = GF_ISOM_GET_FRAG_PAD(flags);
     799      109190 :                         if (pad) {
     800           0 :                                 e = stbl_AppendPadding(trak->Media->information->sampleTable, pad);
     801           0 :                                 if (e) return e;
     802             :                         }
     803      109190 :                         degr = GF_ISOM_GET_FRAG_DEG(flags);
     804      109190 :                         if (degr) {
     805           3 :                                 e = stbl_AppendDegradation(trak->Media->information->sampleTable, degr);
     806           3 :                                 if (e) return e;
     807             :                         }
     808      109190 :                         e = stbl_AppendDependencyType(trak->Media->information->sampleTable, GF_ISOM_GET_FRAG_LEAD(flags), GF_ISOM_GET_FRAG_DEPENDS(flags), GF_ISOM_GET_FRAG_DEPENDED(flags), GF_ISOM_GET_FRAG_REDUNDANT(flags));
     809      109190 :                         if (e) return e;
     810             :                 }
     811             :         }
     812             : 
     813        4079 :         if (trak->moov->mov->is_smooth && !traf->tfdt && !traf->tfxd) {
     814          25 :                 if (is_first_merge)
     815          25 :                         trak->dts_at_seg_start = trak->dts_at_next_seg_start;
     816          25 :                 trak->dts_at_next_seg_start += last_dts;
     817             :         }
     818        4079 :         if (traf_duration && trak->editBox && trak->editBox->editList) {
     819         264 :                 for (i=0; i<gf_list_count(trak->editBox->editList->entryList); i++) {
     820         132 :                         GF_EdtsEntry *edts_e = gf_list_get(trak->editBox->editList->entryList, i);
     821         132 :                         if (edts_e->was_empty_dur) {
     822             :                                 u64 extend_dur = traf_duration;
     823         105 :                                 extend_dur *= trak->moov->mvhd->timeScale;
     824         105 :                                 extend_dur /= trak->Media->mediaHeader->timeScale;
     825         105 :                                 edts_e->segmentDuration += extend_dur;
     826             :                         }
     827          27 :                         else if (!edts_e->segmentDuration) {
     828          27 :                                 edts_e->was_empty_dur = GF_TRUE;
     829          27 :                                 if ((s64) traf_duration > edts_e->mediaTime)
     830          27 :                                         traf_duration -= edts_e->mediaTime;
     831             :                                 else
     832             :                                         traf_duration = 0;
     833             : 
     834          27 :                                 edts_e->segmentDuration = traf_duration;
     835          27 :                                 edts_e->segmentDuration *= trak->moov->mvhd->timeScale;
     836          27 :                                 edts_e->segmentDuration /= trak->Media->mediaHeader->timeScale;
     837             :                         }
     838             : 
     839             :                 }
     840             :         }
     841             : 
     842             :         //in any case, update the cumulated offset
     843             :         //this will handle hypothetical files mixing MOOF offset and implicit non-moof offset
     844        4079 :         *cumulated_offset = data_offset + chunk_size;
     845             : 
     846             :         /*merge sample groups*/
     847        4079 :         if (traf->sampleGroups) {
     848             :                 GF_List *groups;
     849             :                 GF_List *groupDescs;
     850             :                 Bool is_identical_sgpd = GF_TRUE;
     851             :                 u32 *new_idx = NULL, new_idx_count=0;
     852             : 
     853          98 :                 if (!trak->Media->information->sampleTable->sampleGroups)
     854          98 :                         trak->Media->information->sampleTable->sampleGroups = gf_list_new();
     855             : 
     856          98 :                 if (!trak->Media->information->sampleTable->sampleGroupsDescription)
     857          10 :                         trak->Media->information->sampleTable->sampleGroupsDescription = gf_list_new();
     858             : 
     859          98 :                 groupDescs = trak->Media->information->sampleTable->sampleGroupsDescription;
     860         126 :                 for (i=0; i<gf_list_count(traf->sampleGroupsDescription); i++) {
     861             :                         GF_SampleGroupDescriptionBox *new_sgdesc = NULL;
     862          28 :                         GF_SampleGroupDescriptionBox *sgdesc = gf_list_get(traf->sampleGroupsDescription, i);
     863          28 :                         for (j=0; j<gf_list_count(groupDescs); j++) {
     864           0 :                                 new_sgdesc = gf_list_get(groupDescs, j);
     865           0 :                                 if (new_sgdesc->grouping_type==sgdesc->grouping_type) break;
     866             :                                 new_sgdesc = NULL;
     867             :                         }
     868             :                         /*new description, move it to our sample table*/
     869          28 :                         if (!new_sgdesc) {
     870          28 :                                 gf_list_add(groupDescs, sgdesc);
     871          28 :                                 gf_list_add(trak->Media->information->sampleTable->child_boxes, sgdesc);
     872          28 :                                 gf_list_rem(traf->sampleGroupsDescription, i);
     873          28 :                                 gf_list_del_item(traf->child_boxes, sgdesc);
     874          28 :                                 i--;
     875             :                         }
     876             :                         /*merge descriptions*/
     877             :                         else {
     878             :                                 u32 count;
     879             : 
     880           0 :                                 is_identical_sgpd = gf_isom_is_identical_sgpd(new_sgdesc, sgdesc, 0);
     881           0 :                                 if (is_identical_sgpd)
     882           0 :                                         continue;
     883             : 
     884           0 :                                 new_idx_count = gf_list_count(sgdesc->group_descriptions);
     885           0 :                                 new_idx = (u32 *)gf_malloc(new_idx_count * sizeof(u32));
     886           0 :                                 if (!new_idx) return GF_OUT_OF_MEM;
     887             : 
     888             :                                 count = 0;
     889           0 :                                 while (gf_list_count(sgdesc->group_descriptions)) {
     890           0 :                                         void *sgpd_entry = gf_list_get(sgdesc->group_descriptions, 0);
     891             :                                         Bool new_entry = GF_TRUE;
     892             : 
     893           0 :                                         for (j = 0; j < gf_list_count(new_sgdesc->group_descriptions); j++) {
     894           0 :                                                 void *ptr = gf_list_get(new_sgdesc->group_descriptions, j);
     895           0 :                                                 if (gf_isom_is_identical_sgpd(sgpd_entry, ptr, new_sgdesc->grouping_type)) {
     896           0 :                                                         new_idx[count] = j + 1;
     897           0 :                                                         count ++;
     898             :                                                         new_entry = GF_FALSE;
     899           0 :                                                         gf_free(sgpd_entry);
     900             :                                                         break;
     901             :                                                 }
     902             :                                         }
     903             : 
     904             :                                         if (new_entry) {
     905           0 :                                                 gf_list_add(new_sgdesc->group_descriptions, sgpd_entry);
     906           0 :                                                 new_idx[count] = gf_list_count(new_sgdesc->group_descriptions);
     907           0 :                                                 count ++;
     908             :                                         }
     909             : 
     910           0 :                                         gf_list_rem(sgdesc->group_descriptions, 0);
     911             :                                 }
     912             :                         }
     913             :                 }
     914             : 
     915          98 :                 groups = trak->Media->information->sampleTable->sampleGroups;
     916         196 :                 for (i=0; i<gf_list_count(traf->sampleGroups); i++) {
     917             :                         GF_SampleGroupBox *stbl_group = NULL;
     918          98 :                         GF_SampleGroupBox *frag_group = gf_list_get(traf->sampleGroups, i);
     919             : 
     920             : 
     921          98 :                         for (j=0; j<gf_list_count(groups); j++) {
     922           0 :                                 stbl_group = gf_list_get(groups, j);
     923           0 :                                 if ((frag_group->grouping_type==stbl_group->grouping_type) && (frag_group->grouping_type_parameter==stbl_group->grouping_type_parameter))
     924             :                                         break;
     925             :                                 stbl_group = NULL;
     926             :                         }
     927          98 :                         if (!stbl_group) {
     928          98 :                                 stbl_group = (GF_SampleGroupBox *) gf_isom_box_new_parent(&trak->Media->information->sampleTable->child_boxes, GF_ISOM_BOX_TYPE_SBGP);
     929          98 :                                 if (!stbl_group) return GF_OUT_OF_MEM;
     930          98 :                                 stbl_group->grouping_type = frag_group->grouping_type;
     931          98 :                                 stbl_group->grouping_type_parameter = frag_group->grouping_type_parameter;
     932          98 :                                 stbl_group->version = frag_group->version;
     933          98 :                                 gf_list_add(groups, stbl_group);
     934             :                         }
     935             : 
     936          98 :                         if (is_identical_sgpd) {
     937             :                                 //adjust sgpd index: in traf index start at 0x1001
     938         181 :                                 for (j = 0; j < frag_group->entry_count; j++)
     939         181 :                                         frag_group->sample_entries[j].group_description_index &= 0x0FFFF;
     940          98 :                                 if (frag_group->entry_count && stbl_group->entry_count &&
     941           0 :                                         (frag_group->sample_entries[0].group_description_index==stbl_group->sample_entries[stbl_group->entry_count-1].group_description_index)
     942             :                                    ) {
     943           0 :                                         stbl_group->sample_entries[stbl_group->entry_count - 1].sample_count += frag_group->sample_entries[0].sample_count;
     944           0 :                                         if (frag_group->entry_count>1) {
     945           0 :                                                 stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count - 1));
     946           0 :                                                 memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[1], sizeof(GF_SampleGroupEntry) * (frag_group->entry_count - 1));
     947           0 :                                                 stbl_group->entry_count += frag_group->entry_count - 1;
     948             :                                         }
     949             :                                 } else {
     950          98 :                                         stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count));
     951          98 :                                         memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[0], sizeof(GF_SampleGroupEntry) * frag_group->entry_count);
     952          98 :                                         stbl_group->entry_count += frag_group->entry_count;
     953             :                                 }
     954             :                         } else {
     955           0 :                                 stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count));
     956             :                                 //adjust sgpd index
     957           0 :                                 for (j = 0; j < frag_group->entry_count; j++) {
     958           0 :                                         u32 sgidx = frag_group->sample_entries[j].group_description_index;
     959           0 :                                         if (sgidx > 0x10000) {
     960           0 :                                                 sgidx -= 0x10001;
     961           0 :                                                 if (sgidx>=new_idx_count) {
     962           0 :                                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[isobmf] corrupted sample group index in fragment %d but only %d group descriptions in fragment\n", sgidx, new_idx_count));
     963             :                                                 } else {
     964           0 :                                                         frag_group->sample_entries[j].group_description_index = new_idx[sgidx];
     965             :                                                 }
     966             :                                         }
     967             :                                 }
     968           0 :                                 memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[0], sizeof(GF_SampleGroupEntry) * frag_group->entry_count);
     969           0 :                                 stbl_group->entry_count += frag_group->entry_count;
     970             :                         }
     971             :                 }
     972             : 
     973          98 :                 if (new_idx) gf_free(new_idx);
     974             :         }
     975             : 
     976             :         /*content is encrypted*/
     977        4079 :         track_num = gf_isom_get_tracknum_from_id(trak->moov, trak->Header->trackID);
     978        4079 :         if (gf_isom_is_cenc_media(trak->moov->mov, track_num, DescIndex)
     979        3942 :                 || traf->sample_encryption) {
     980             :                 /*Merge sample auxiliary encryption information*/
     981             :                 GF_SampleEncryptionBox *senc = NULL;
     982             :                 u32 scheme_type;
     983         141 :                 gf_isom_get_cenc_info(trak->moov->mov, track_num, DescIndex, NULL, &scheme_type, NULL);
     984             : 
     985         141 :                 if (traf->sample_encryption) {
     986        1431 :                         for (i = 0; i < gf_list_count(trak->Media->information->sampleTable->child_boxes); i++) {
     987        1290 :                                 GF_Box *a = (GF_Box *)gf_list_get(trak->Media->information->sampleTable->child_boxes, i);
     988        1290 :                                 if (a->type != traf->sample_encryption->type) continue;
     989             : 
     990           0 :                                 if ((a->type ==GF_ISOM_BOX_TYPE_UUID) && (((GF_UUIDBox *)a)->internal_4cc == GF_ISOM_BOX_UUID_PSEC)) {
     991             :                                         senc = (GF_SampleEncryptionBox *)a;
     992             :                                         break;
     993             :                                 }
     994           0 :                                 else if (a->type ==GF_ISOM_BOX_TYPE_SENC) {
     995             :                                         senc = (GF_SampleEncryptionBox *)a;
     996             :                                         break;
     997             :                                 }
     998             :                         }
     999         141 :                         if (!senc && trak->sample_encryption)
    1000             :                                 senc = trak->sample_encryption;
    1001             : 
    1002         141 :                         if (!senc) {
    1003          72 :                                 if (traf->sample_encryption->piff_type==1) {
    1004           2 :                                         senc = (GF_SampleEncryptionBox *)gf_isom_create_piff_psec_box(1, 0x2, 0, 0, NULL);
    1005             :                                 } else {
    1006          70 :                                         senc = gf_isom_create_samp_enc_box(1, 0x2);
    1007             :                                 }
    1008             : 
    1009          72 :                                 if (!trak->Media->information->sampleTable->child_boxes) trak->Media->information->sampleTable->child_boxes = gf_list_new();
    1010             : 
    1011          72 :                                 trak->sample_encryption = senc;
    1012          72 :                                 if (!trak->child_boxes) trak->child_boxes = gf_list_new();
    1013          72 :                                 gf_list_add(trak->child_boxes, senc);
    1014             :                         }
    1015             :                 }
    1016             : 
    1017             :                 /*get sample auxiliary information by saiz/saio rather than by parsing senc box*/
    1018         141 :                 if (gf_isom_cenc_has_saiz_saio_traf(traf, scheme_type)) {
    1019             :                         u32 nb_saio;
    1020             :                         u32 aux_info_type;
    1021             :                         u64 offset;
    1022             :                         GF_Err e;
    1023             :                         Bool is_encrypted;
    1024             :                         GF_SampleAuxiliaryInfoOffsetBox *saio = NULL;
    1025             :                         GF_SampleAuxiliaryInfoSizeBox *saiz = NULL;
    1026             : 
    1027             :                         offset = nb_saio = 0;
    1028             : 
    1029         139 :                         for (i = 0; i < gf_list_count(traf->sai_offsets); i++) {
    1030         139 :                                 saio = (GF_SampleAuxiliaryInfoOffsetBox *)gf_list_get(traf->sai_offsets, i);
    1031         139 :                                 aux_info_type = saio->aux_info_type;
    1032         139 :                                 if (!aux_info_type) aux_info_type = scheme_type;
    1033             : 
    1034             :                                 /*if we have only 1 sai_offsets, assume that its type is cenc*/
    1035         139 :                                 if ((aux_info_type == GF_ISOM_CENC_SCHEME) || (aux_info_type == GF_ISOM_CBC_SCHEME) ||
    1036          30 :                                         (aux_info_type == GF_ISOM_CENS_SCHEME) || (aux_info_type == GF_ISOM_CBCS_SCHEME) ||
    1037           0 :                                         (gf_list_count(traf->sai_offsets) == 1)) {
    1038         139 :                                         if (saio->offsets && saio->entry_count) {
    1039         139 :                                                 offset = saio->offsets[0] + moof_offset;
    1040             :                                                 nb_saio = saio->entry_count;
    1041         139 :                                                 break;
    1042             :                                         }
    1043             :                                 }
    1044             :                                 saio = NULL;
    1045             :                         }
    1046         139 :                         for (i = 0; i < gf_list_count(traf->sai_sizes); i++) {
    1047         139 :                                 saiz = (GF_SampleAuxiliaryInfoSizeBox *)gf_list_get(traf->sai_sizes, i);
    1048         139 :                                 aux_info_type = saiz->aux_info_type;
    1049         139 :                                 if (!aux_info_type) aux_info_type = scheme_type;
    1050             :                                 /*if we have only 1 sai_sizes, assume that its type is cenc*/
    1051         139 :                                 if ((aux_info_type == GF_ISOM_CENC_SCHEME) || (aux_info_type == GF_ISOM_CBC_SCHEME) ||
    1052          30 :                                         (aux_info_type == GF_ISOM_CENS_SCHEME) || (aux_info_type == GF_ISOM_CBCS_SCHEME) ||
    1053           0 :                                         (gf_list_count(traf->sai_sizes) == 1)) {
    1054             :                                         break;
    1055             :                                 }
    1056             :                                 saiz = NULL;
    1057             :                         }
    1058         139 :                         if (saiz && saio && senc) {
    1059        8616 :                                 for (i = 0; i < saiz->sample_count; i++) {
    1060             :                                         GF_CENCSampleAuxInfo *sai;
    1061        4169 :                                         const u8 *key_info=NULL;
    1062             :                                         u32 key_info_size;
    1063             :                                         u64 cur_position;
    1064        4169 :                                         if (nb_saio != 1)
    1065           0 :                                                 offset = saio->offsets[i] + moof_offset;
    1066        4169 :                                         size = saiz->default_sample_info_size ? saiz->default_sample_info_size : saiz->sample_info_size[i];
    1067             : 
    1068        4169 :                                         cur_position = gf_bs_get_position(trak->moov->mov->movieFileMap->bs);
    1069        4169 :                                         gf_bs_seek(trak->moov->mov->movieFileMap->bs, offset);
    1070             : 
    1071        4169 :                                         GF_SAFEALLOC(sai, GF_CENCSampleAuxInfo);
    1072        4169 :                                         if (!sai) return GF_OUT_OF_MEM;
    1073             : 
    1074        4169 :                                         e = gf_isom_get_sample_cenc_info_internal(trak, traf, senc, i+1, &is_encrypted, NULL, NULL, &key_info, &key_info_size);
    1075        4169 :                                         if (e) {
    1076           0 :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isobmf] could not get cenc info for sample %d: %s\n", i+1, gf_error_to_string(e) ));
    1077             :                                                 return e;
    1078             :                                         }
    1079             : 
    1080        4169 :                                         if (is_encrypted) {
    1081        4144 :                                                 sai->cenc_data_size = size;
    1082        4144 :                                                 sai->cenc_data = gf_malloc(sizeof(u8)*size);
    1083        4144 :                                                 if (!sai->cenc_data) return GF_OUT_OF_MEM;
    1084        4144 :                                                 gf_bs_read_data(trak->moov->mov->movieFileMap->bs, sai->cenc_data, sai->cenc_data_size);
    1085             :                                         } else {
    1086          25 :                                                 sai->isNotProtected=1;
    1087             :                                         }
    1088             : 
    1089        4169 :                                         if (key_info) {
    1090             :                                                 //not multikey
    1091        4072 :                                                 if (!key_info[0]) {
    1092             :                                                         //size greater than IV
    1093        4072 :                                                         if (size > key_info[3])
    1094        1805 :                                                                 senc->flags = 0x00000002;
    1095             :                                                 }
    1096             :                                                 //multikey, always use subsamples
    1097             :                                                 else {
    1098           0 :                                                         senc->flags = 0x00000002;
    1099             :                                                 }
    1100             :                                         }
    1101             : 
    1102             : 
    1103        4169 :                                         gf_bs_seek(trak->moov->mov->movieFileMap->bs, cur_position);
    1104             : 
    1105        4169 :                                         gf_list_add(senc->samp_aux_info, sai);
    1106             : 
    1107        4169 :                                         e = gf_isom_cenc_merge_saiz_saio(senc, trak->Media->information->sampleTable, offset, size);
    1108        4169 :                                         if (e) return e;
    1109        4169 :                                         if (nb_saio == 1)
    1110        4169 :                                                 offset += size;
    1111             :                                 }
    1112             :                         }
    1113           2 :                 } else if (traf->sample_encryption) {
    1114           2 :                         senc_Parse(trak->moov->mov->movieFileMap->bs, trak, traf, traf->sample_encryption);
    1115           2 :                         trak->sample_encryption->AlgorithmID = traf->sample_encryption->AlgorithmID;
    1116           2 :                         if (!trak->sample_encryption->IV_size)
    1117           2 :                                 trak->sample_encryption->IV_size = traf->sample_encryption->IV_size;
    1118           2 :                         if (!trak->sample_encryption->samp_aux_info) trak->sample_encryption->samp_aux_info = gf_list_new();
    1119           2 :                         gf_list_transfer(trak->sample_encryption->samp_aux_info, traf->sample_encryption->samp_aux_info);
    1120           2 :                         if (traf->sample_encryption->flags & 0x00000002)
    1121           2 :                                 trak->sample_encryption->flags |= 0x00000002;
    1122             :                 }
    1123             :         }
    1124             :         return GF_OK;
    1125             : }
    1126             : 
    1127             : #endif
    1128             : 
    1129             : 
    1130             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1131             : 
    1132             : //used to check if a TrackID is available
    1133        1857 : u8 RequestTrack(GF_MovieBox *moov, GF_ISOTrackID TrackID)
    1134             : {
    1135             :         u32 i;
    1136             :         GF_TrackBox *trak;
    1137             : 
    1138        1857 :         i=0;
    1139        5351 :         while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) {
    1140        1831 :                 if (trak->Header->trackID == TrackID) {
    1141         194 :                         gf_isom_set_last_error(moov->mov, GF_BAD_PARAM);
    1142         194 :                         return 0;
    1143             :                 }
    1144             :         }
    1145             :         return 1;
    1146             : }
    1147             : 
    1148           1 : GF_Err Track_RemoveRef(GF_TrackBox *trak, u32 ReferenceType)
    1149             : {
    1150             :         GF_TrackReferenceBox *ref;
    1151             :         GF_Box *a;
    1152             :         u32 i;
    1153           1 :         if (! trak) return GF_BAD_PARAM;
    1154           1 :         if (! trak->References) return GF_OK;
    1155             :         ref = trak->References;
    1156           1 :         i=0;
    1157           4 :         while ((a = (GF_Box *)gf_list_enum(ref->child_boxes, &i))) {
    1158           2 :                 if (a->type == ReferenceType) {
    1159           0 :                         gf_isom_box_del_parent(&ref->child_boxes, a);
    1160           0 :                         return GF_OK;
    1161             :                 }
    1162             :         }
    1163             :         return GF_OK;
    1164             : }
    1165             : 
    1166        1626 : GF_Err NewMedia(GF_MediaBox **mdia, u32 MediaType, u32 TimeScale)
    1167             : {
    1168             :         GF_MediaHeaderBox *mdhd;
    1169             :         GF_Box *mediaInfo;
    1170             :         GF_HandlerBox *hdlr;
    1171             :         GF_MediaInformationBox *minf;
    1172             :         GF_DataInformationBox *dinf;
    1173             :         GF_SampleTableBox *stbl;
    1174             :         GF_DataReferenceBox *dref;
    1175             :         char *str="";
    1176             : 
    1177             :         GF_Err e;
    1178             : 
    1179        1626 :         if (!mdia) return GF_BAD_PARAM;
    1180             : 
    1181        1626 :         minf = *mdia ? (*mdia)->information : NULL;
    1182        1626 :         mdhd = *mdia ? (*mdia)->mediaHeader : NULL;
    1183        1626 :         hdlr = *mdia ? (*mdia)->handler : NULL;
    1184        1626 :         dinf =  minf ? minf->dataInformation : NULL;
    1185        1626 :         stbl = minf ? minf->sampleTable : NULL;
    1186        1626 :         dref = dinf ? dinf->dref : NULL;
    1187        1626 :         mediaInfo = minf ? minf->InfoHeader : NULL;
    1188             : 
    1189             :         //first create the media
    1190        1626 :         if (!*mdia) {
    1191        1011 :                 *mdia = (GF_MediaBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDIA);
    1192        1011 :                 if (! *mdia) { e = GF_OUT_OF_MEM; goto err_exit; }
    1193             :         }
    1194        1626 :         if (!mdhd) {
    1195        1011 :                 mdhd = (GF_MediaHeaderBox *) gf_isom_box_new_parent( & ((*mdia)->child_boxes), GF_ISOM_BOX_TYPE_MDHD);
    1196        1011 :                 if (! mdhd) { e = GF_OUT_OF_MEM; goto err_exit; }
    1197        1011 :                 e = mdia_on_child_box((GF_Box*)*mdia, (GF_Box *) mdhd, GF_FALSE);
    1198        1011 :                 if (e) goto err_exit;
    1199             :         }
    1200        1626 :         if (!hdlr) {
    1201        1011 :                 hdlr = (GF_HandlerBox *) gf_isom_box_new_parent(& ((*mdia)->child_boxes), GF_ISOM_BOX_TYPE_HDLR);
    1202        1011 :                 if (! hdlr) { e = GF_OUT_OF_MEM; goto err_exit; }
    1203        1011 :                 e = mdia_on_child_box((GF_Box*)*mdia, (GF_Box *) hdlr, GF_FALSE);
    1204        1011 :                 if (e) goto err_exit;
    1205             :         }
    1206        1626 :         if (!minf) {
    1207        1011 :                 minf = (GF_MediaInformationBox *) gf_isom_box_new_parent(& ((*mdia)->child_boxes), GF_ISOM_BOX_TYPE_MINF);
    1208        1011 :                 if (! minf) { e = GF_OUT_OF_MEM; goto err_exit; }
    1209        1011 :                 e = mdia_on_child_box((GF_Box*)*mdia, (GF_Box *) minf, GF_FALSE);
    1210        1011 :                 if (e) goto err_exit;
    1211             :         }
    1212        1626 :         if (!dinf) {
    1213        1011 :                 dinf = (GF_DataInformationBox *) gf_isom_box_new_parent(&minf->child_boxes, GF_ISOM_BOX_TYPE_DINF);
    1214        1011 :                 if (! dinf) { e = GF_OUT_OF_MEM; goto err_exit; }
    1215        1011 :                 e = minf_on_child_box((GF_Box*)minf, (GF_Box *) dinf, GF_FALSE);
    1216        1011 :                 if (e) goto err_exit;
    1217             :         }
    1218             : 
    1219        1626 :         if (!mediaInfo) {
    1220             :                 //"handler name" is for debugging purposes. Let's stick our name here ;)
    1221        1011 :                 switch (MediaType) {
    1222         537 :                 case GF_ISOM_MEDIA_VISUAL:
    1223         537 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_VMHD);
    1224             :                         str = "GPAC ISO Video Handler";
    1225         537 :                         break;
    1226           0 :                 case GF_ISOM_MEDIA_AUXV:
    1227           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_VMHD);
    1228             :                         str = "GPAC ISO Auxiliary Video Handler";
    1229           0 :                         break;
    1230           0 :                 case GF_ISOM_MEDIA_PICT:
    1231           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_VMHD);
    1232             :                         str = "GPAC ISO Picture Sequence Handler";
    1233           0 :                         break;
    1234         179 :                 case GF_ISOM_MEDIA_AUDIO:
    1235         179 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_SMHD);
    1236             :                         str = "GPAC ISO Audio Handler";
    1237         179 :                         break;
    1238          73 :                 case GF_ISOM_MEDIA_HINT:
    1239          73 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_HMHD);
    1240             :                         str = "GPAC ISO Hint Handler";
    1241          73 :                         break;
    1242          11 :                 case GF_ISOM_MEDIA_META:
    1243          11 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1244             :                         str = "GPAC Timed MetaData Handler";
    1245          11 :                         break;
    1246          30 :                 case GF_ISOM_MEDIA_OD:
    1247          30 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1248             :                         str = "GPAC MPEG-4 OD Handler";
    1249          30 :                         break;
    1250           0 :                 case GF_ISOM_MEDIA_OCR:
    1251           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1252             :                         str = "GPAC MPEG-4 OCR Handler";
    1253           0 :                         break;
    1254          69 :                 case GF_ISOM_MEDIA_SCENE:
    1255          69 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1256             :                         str = "GPAC MPEG-4 Scene Description Handler";
    1257          69 :                         break;
    1258           0 :                 case GF_ISOM_MEDIA_MPEG7:
    1259           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1260             :                         str = "GPAC MPEG-4 MPEG-7 Handler";
    1261           0 :                         break;
    1262           0 :                 case GF_ISOM_MEDIA_OCI:
    1263           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1264             :                         str = "GPAC MPEG-4 OCI Handler";
    1265           0 :                         break;
    1266           0 :                 case GF_ISOM_MEDIA_IPMP:
    1267           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1268             :                         str = "GPAC MPEG-4 IPMP Handler";
    1269           0 :                         break;
    1270           0 :                 case GF_ISOM_MEDIA_MPEGJ:
    1271           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1272             :                         str = "GPAC MPEG-4 MPEG-J Handler";
    1273           0 :                         break;
    1274          83 :                 case GF_ISOM_MEDIA_TEXT:
    1275             :                 case GF_ISOM_MEDIA_SUBT:
    1276          83 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1277             :                         str = "GPAC Streaming Text Handler";
    1278          83 :                         break;
    1279          25 :                 case GF_ISOM_MEDIA_MPEG_SUBT:
    1280          25 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_STHD);
    1281             :                         str = "GPAC MPEG Subtitle Handler";
    1282          25 :                         break;
    1283           0 :                 case GF_ISOM_MEDIA_DIMS:
    1284           0 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_VMHD);
    1285             :                         MediaType = GF_ISOM_MEDIA_SCENE;
    1286             :                         str = "GPAC DIMS Handler";
    1287           0 :                         break;
    1288           3 :                 case GF_ISOM_MEDIA_TIMECODE:
    1289           3 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_GMHD);
    1290             :                         str = "GPAC TMCD Handler";
    1291           3 :                         break;
    1292           1 :                 default:
    1293           1 :                         mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD);
    1294             :                         str = "GPAC IsoMedia Handler";
    1295           1 :                         break;
    1296             :                 }
    1297        1011 :                 if (! mediaInfo) { e = GF_OUT_OF_MEM; goto err_exit; }
    1298        1011 :                 if (!minf->child_boxes) minf->child_boxes = gf_list_new();
    1299        1011 :                 gf_list_add(minf->child_boxes, mediaInfo);
    1300             : 
    1301        1011 :                 e = minf_on_child_box((GF_Box*)minf, (GF_Box *) mediaInfo, GF_FALSE);
    1302        1011 :                 if (e) goto err_exit;
    1303             :         }
    1304             : 
    1305        1626 :         mdhd->timeScale = TimeScale;
    1306        1626 :         hdlr->handlerType = MediaType;
    1307        1626 :         if (!hdlr->nameUTF8)
    1308        1011 :                 hdlr->nameUTF8 = gf_strdup(str);
    1309             : 
    1310        1626 :         if (!dref) {
    1311             :                 //Create a data reference WITHOUT DATA ENTRY (we don't know anything yet about the media Data)
    1312        1011 :                 dref = (GF_DataReferenceBox *) gf_isom_box_new_parent(&dinf->child_boxes, GF_ISOM_BOX_TYPE_DREF);
    1313        1011 :                 if (! dref) { e = GF_OUT_OF_MEM; goto err_exit; }
    1314        1011 :                 e = dinf_on_child_box((GF_Box*)dinf, (GF_Box *)dref, GF_FALSE);
    1315        1011 :                 if (e) goto err_exit;
    1316             :         }
    1317             : 
    1318        1626 :         if (!stbl) {
    1319             :                 //first set-up the sample table...
    1320        1011 :                 stbl = (GF_SampleTableBox *) gf_isom_box_new_parent(&minf->child_boxes, GF_ISOM_BOX_TYPE_STBL);
    1321        1011 :                 if (! stbl) { e = GF_OUT_OF_MEM; goto err_exit; }
    1322             : 
    1323        1011 :                 e = minf_on_child_box((GF_Box*)minf, (GF_Box *) stbl, GF_FALSE);
    1324        1011 :                 if (e) goto err_exit;
    1325             :         }
    1326        1626 :         if (!stbl->SampleDescription) {
    1327        1011 :                 stbl->SampleDescription = (GF_SampleDescriptionBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSD);
    1328        1011 :                 if (! stbl->SampleDescription) { e = GF_OUT_OF_MEM; goto err_exit; }
    1329             :         }
    1330             : 
    1331             :         //by default create a regular table, 32 but offset and normal sample size
    1332        1626 :         if (!stbl->ChunkOffset) {
    1333        1626 :                 stbl->ChunkOffset = gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STCO);
    1334        1626 :                 if (! stbl->ChunkOffset) { e = GF_OUT_OF_MEM; goto err_exit; }
    1335             :         }
    1336        1626 :         if (!stbl->SampleSize) {
    1337        1626 :                 stbl->SampleSize = (GF_SampleSizeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSZ);
    1338        1626 :                 if (! stbl->SampleSize) { e = GF_OUT_OF_MEM; goto err_exit; }
    1339             :         }
    1340        1626 :         if (!stbl->SampleToChunk) {
    1341        1626 :                 stbl->SampleToChunk = (GF_SampleToChunkBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSC);
    1342        1626 :                 if (! stbl->SampleToChunk) { e = GF_OUT_OF_MEM; goto err_exit; }
    1343             :         }
    1344        1626 :         if (!stbl->TimeToSample) {
    1345        1626 :                 stbl->TimeToSample = (GF_TimeToSampleBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STTS);
    1346        1626 :                 if (! stbl->TimeToSample) { e = GF_OUT_OF_MEM; goto err_exit; }
    1347             :         }
    1348        1626 :         if (!stbl->SampleDescription) {
    1349           0 :                 stbl->SampleDescription = (GF_SampleDescriptionBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSD);
    1350           0 :                 if (! stbl->SampleDescription) { e = GF_OUT_OF_MEM; goto err_exit; }
    1351             :         }
    1352             :         return GF_OK;
    1353             : 
    1354           0 : err_exit:
    1355           0 :         if (mdhd) gf_isom_box_del_parent(& ((*mdia)->child_boxes), (GF_Box *)mdhd);
    1356           0 :         if (minf) gf_isom_box_del_parent(& ((*mdia)->child_boxes), (GF_Box *)minf);
    1357           0 :         if (hdlr) {
    1358           0 :                 gf_isom_box_del_parent(& ((*mdia)->child_boxes) , (GF_Box *)hdlr);
    1359             :         }
    1360             :         return e;
    1361             : 
    1362             : }
    1363             : 
    1364         612 : GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, u32 DataReferenceIndex, GF_ESD *esd, u32 *outStreamIndex)
    1365             : {
    1366             :         GF_Err e;
    1367             :         GF_MPEGSampleEntryBox *entry;
    1368             :         GF_MPEGVisualSampleEntryBox *entry_v;
    1369             :         GF_MPEGAudioSampleEntryBox *entry_a;
    1370             :         GF_TrackReferenceBox *tref;
    1371             :         GF_TrackReferenceTypeBox *dpnd;
    1372             :         u16 tmpRef;
    1373             : 
    1374             :         entry = NULL;
    1375             :         tref = NULL;
    1376             : 
    1377         612 :         if (!trak || !esd || (!outStreamIndex && !DataReferenceIndex) ) return GF_BAD_PARAM;
    1378         612 :         if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) return GF_ISOM_INVALID_MEDIA;
    1379             : 
    1380             : 
    1381         611 :         esd->ESID = 0;
    1382             :         //set SL to predefined if no url
    1383         611 :         if (esd->URLString == NULL) {
    1384         611 :                 if (!esd->slConfig) esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG);
    1385         611 :                 esd->slConfig->predefined = SLPredef_MP4;
    1386         611 :                 esd->slConfig->durationFlag = 0;
    1387         611 :                 esd->slConfig->useTimestampsFlag = 1;
    1388             :         }
    1389             : 
    1390             :         //get the REF box if needed
    1391         611 :         if (esd->dependsOnESID || (esd->OCRESID  && (esd->OCRESID != trak->moov->mov->es_id_default_sync)) ) {
    1392          53 :                 if (!trak->References) {
    1393          27 :                         tref = (GF_TrackReferenceBox *) gf_isom_box_new_parent(&trak->child_boxes, GF_ISOM_BOX_TYPE_TREF);
    1394          27 :                         if (!tref) return GF_OUT_OF_MEM;
    1395          27 :                         e = trak_on_child_box((GF_Box*)trak, (GF_Box *)tref, GF_FALSE);
    1396          27 :                         if (e) return e;
    1397             :                 }
    1398          53 :                 tref = trak->References;
    1399             :         }
    1400             : 
    1401             :         //Update Stream dependencies
    1402         611 :         e = Track_FindRef(trak, GF_ISOM_REF_DECODE, &dpnd);
    1403         611 :         if (e) return e;
    1404             : 
    1405         611 :         if (!dpnd && esd->dependsOnESID) {
    1406          17 :                 e = Track_FindRef(trak, GF_ISOM_REF_BASE, &dpnd);
    1407          17 :                 if (e) return e;
    1408             :         }
    1409             : 
    1410         611 :         if (!dpnd && esd->dependsOnESID) {
    1411          14 :                 dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new_parent(&tref->child_boxes, GF_ISOM_BOX_TYPE_REFT);
    1412          14 :                 dpnd->reference_type = GF_ISOM_BOX_TYPE_DPND;
    1413          14 :                 e = reftype_AddRefTrack(dpnd, esd->dependsOnESID, NULL);
    1414          14 :                 if (e) return e;
    1415         597 :         } else if (dpnd && !esd->dependsOnESID) {
    1416           0 :                 Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_DPND);
    1417             :         }
    1418         611 :         esd->dependsOnESID = 0;
    1419             : 
    1420             :         //Update GF_Clock dependencies
    1421         611 :         e = Track_FindRef(trak, GF_ISOM_REF_OCR, &dpnd);
    1422         611 :         if (e) return e;
    1423         611 :         if (!dpnd && esd->OCRESID && (esd->OCRESID != trak->moov->mov->es_id_default_sync)) {
    1424          29 :                 dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new_parent(&tref->child_boxes, GF_ISOM_BOX_TYPE_REFT);
    1425          29 :                 if (!dpnd) return GF_OUT_OF_MEM;
    1426          29 :                 dpnd->reference_type = GF_ISOM_BOX_TYPE_SYNC;
    1427          29 :                 e = reftype_AddRefTrack(dpnd, esd->OCRESID, NULL);
    1428          29 :                 if (e) return e;
    1429         582 :         } else if (dpnd && !esd->OCRESID) {
    1430           1 :                 Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_SYNC);
    1431         581 :         } else if (dpnd && esd->OCRESID) {
    1432          21 :                 if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
    1433          21 :                 dpnd->trackIDs[0] = esd->OCRESID;
    1434             :         }
    1435         611 :         esd->OCRESID = 0;
    1436             : 
    1437             :         //brand new case: we have to change the IPI desc
    1438         611 :         if (esd->ipiPtr) {
    1439           0 :                 e = Track_FindRef(trak, GF_ISOM_REF_IPI, &dpnd);
    1440           0 :                 if (e) return e;
    1441           0 :                 if (!dpnd) {
    1442           0 :                         tmpRef = 0;
    1443           0 :                         dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new_parent(&tref->child_boxes, GF_ISOM_BOX_TYPE_REFT);
    1444           0 :                         if (!dpnd) return GF_OUT_OF_MEM;
    1445           0 :                         dpnd->reference_type = GF_ISOM_BOX_TYPE_IPIR;
    1446           0 :                         e = reftype_AddRefTrack(dpnd, esd->ipiPtr->IPI_ES_Id, &tmpRef);
    1447           0 :                         if (e) return e;
    1448             :                         //and replace the tag and value...
    1449           0 :                         esd->ipiPtr->IPI_ES_Id = tmpRef;
    1450           0 :                         esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
    1451             :                 } else {
    1452             :                         //Watch out! ONLY ONE IPI dependency is allowed per stream
    1453           0 :                         if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
    1454             :                         //if an existing one is there, what shall we do ???
    1455             :                         //donno, erase it
    1456           0 :                         dpnd->trackIDs[0] = esd->ipiPtr->IPI_ES_Id;
    1457             :                         //and replace the tag and value...
    1458           0 :                         esd->ipiPtr->IPI_ES_Id = 1;
    1459           0 :                         esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
    1460             :                 }
    1461             :         }
    1462             : 
    1463             :         /*don't store the lang desc in ESD, use the media header language info*/
    1464         611 :         if (esd->langDesc) {
    1465           2 :                 trak->Media->mediaHeader->packedLanguage[0] = (esd->langDesc->langCode>>16)&0xFF;
    1466           2 :                 trak->Media->mediaHeader->packedLanguage[1] = (esd->langDesc->langCode>>8)&0xFF;
    1467           2 :                 trak->Media->mediaHeader->packedLanguage[2] = (esd->langDesc->langCode)&0xFF;
    1468           2 :                 gf_odf_desc_del((GF_Descriptor *)esd->langDesc);
    1469           2 :                 esd->langDesc = NULL;
    1470             :         }
    1471             : 
    1472             :         //we have a streamDescriptionIndex, use it
    1473         611 :         if (StreamDescriptionIndex) {
    1474             :                 u32 entry_type;
    1475         116 :                 entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex - 1);
    1476         116 :                 if (!entry) return GF_ISOM_INVALID_FILE;
    1477             : 
    1478         116 :                 entry_type = entry->type;
    1479         116 :                 GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    1480         116 :                 if (sinf && sinf->original_format) entry_type = sinf->original_format->data_format;
    1481             :                 
    1482         116 :                 switch (entry_type) {
    1483          73 :                 case GF_ISOM_BOX_TYPE_MP4S:
    1484             :                         //OK, delete the previous ESD
    1485          73 :                         gf_odf_desc_del((GF_Descriptor *) entry->esd->desc);
    1486          73 :                         entry->esd->desc = esd;
    1487          73 :                         break;
    1488           5 :                 case GF_ISOM_BOX_TYPE_MP4V:
    1489             :                         entry_v = (GF_MPEGVisualSampleEntryBox*) entry;
    1490             :                         //OK, delete the previous ESD
    1491           5 :                         gf_odf_desc_del((GF_Descriptor *) entry_v->esd->desc);
    1492           5 :                         entry_v->esd->desc = esd;
    1493           5 :                         break;
    1494          10 :                 case GF_ISOM_BOX_TYPE_MP4A:
    1495             :                         entry_a = (GF_MPEGAudioSampleEntryBox*) entry;
    1496          10 :             if (entry_a->esd) { // some non-conformant files may not have an ESD ...
    1497             :                 //OK, delete the previous ESD
    1498          10 :                 gf_odf_desc_del((GF_Descriptor *) entry_a->esd->desc);
    1499          10 :                 entry_a->esd->desc = esd;
    1500             :             } else {
    1501             :                                 // can't return OK here otherwise we can't know if esd hasn't been used
    1502             :                                 // and need to be freed
    1503             :                                 return GF_ISOM_INVALID_MEDIA;
    1504             :                         }
    1505          10 :                         break;
    1506          26 :                 case GF_ISOM_BOX_TYPE_AVC1:
    1507             :                 case GF_ISOM_BOX_TYPE_AVC2:
    1508             :                 case GF_ISOM_BOX_TYPE_AVC3:
    1509             :                 case GF_ISOM_BOX_TYPE_AVC4:
    1510             :                 case GF_ISOM_BOX_TYPE_SVC1:
    1511             :                 case GF_ISOM_BOX_TYPE_MVC1:
    1512             :                 case GF_ISOM_BOX_TYPE_HVC1:
    1513             :                 case GF_ISOM_BOX_TYPE_HEV1:
    1514             :                 case GF_ISOM_BOX_TYPE_HVC2:
    1515             :                 case GF_ISOM_BOX_TYPE_HEV2:
    1516             :                 case GF_ISOM_BOX_TYPE_LHE1:
    1517             :                 case GF_ISOM_BOX_TYPE_LHV1:
    1518             :                 case GF_ISOM_BOX_TYPE_HVT1:
    1519             :                 case GF_ISOM_BOX_TYPE_VVC1:
    1520             :                 case GF_ISOM_BOX_TYPE_VVI1:
    1521          26 :                         e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry, esd);
    1522          26 :                         if (e) return e;
    1523             :                         break;
    1524           2 :                 case GF_ISOM_BOX_TYPE_LSR1:
    1525           2 :                         e = LSR_UpdateESD((GF_LASeRSampleEntryBox*)entry, esd);
    1526           2 :                         if (e) return e;
    1527             :                         break;
    1528             :                 case GF_ISOM_BOX_TYPE_AV01:
    1529             :                 case GF_ISOM_BOX_TYPE_AV1C:
    1530             :                 case GF_ISOM_BOX_TYPE_OPUS:
    1531             :                 case GF_ISOM_BOX_TYPE_DOPS:
    1532             :                 case GF_ISOM_BOX_TYPE_STXT:
    1533             :                 case GF_ISOM_BOX_TYPE_WVTT:
    1534             :                 case GF_ISOM_BOX_TYPE_STPP:
    1535           0 :                         if (esd) gf_odf_desc_del((GF_Descriptor *) esd);
    1536             :                         break;
    1537             : 
    1538           0 :                 default:
    1539             :                         //silently fail, not an MPEG-4 esd
    1540           0 :                         gf_odf_desc_del((GF_Descriptor *) esd);
    1541           0 :                         return GF_OK;
    1542             :                 }
    1543             :         } else {
    1544             :                 //need to check we're not in URL mode where only ONE description is allowed...
    1545         495 :                 StreamDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1546         495 :                 if (StreamDescriptionIndex) {
    1547           0 :                         GF_ESD *old_esd=NULL;
    1548           0 :                         entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex - 1);
    1549           0 :                         if (!entry) return GF_ISOM_INVALID_FILE;
    1550             :                         //get ESD (only if present, do not emulate)
    1551           0 :                         Media_GetESD(trak->Media, StreamDescriptionIndex, &old_esd, GF_TRUE);
    1552           0 :                         if (old_esd && old_esd->URLString) return GF_BAD_PARAM;
    1553             :                 }
    1554             : 
    1555             :                 //OK, check the handler and create the entry
    1556         495 :                 switch (trak->Media->handler->handlerType) {
    1557         154 :         case GF_ISOM_MEDIA_AUXV:
    1558             :         case GF_ISOM_MEDIA_PICT:
    1559             :                 case GF_ISOM_MEDIA_VISUAL:
    1560         154 :                         if ((esd->decoderConfig->objectTypeIndication==GF_CODECID_AVC) || (esd->decoderConfig->objectTypeIndication==GF_CODECID_SVC) || (esd->decoderConfig->objectTypeIndication==GF_CODECID_MVC)) {
    1561           4 :                                 entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_AVC1);
    1562           4 :                                 if (!entry_v) return GF_OUT_OF_MEM;
    1563           4 :                                 e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
    1564           4 :                                 if (e) return  e;
    1565         150 :                         } else if (esd->decoderConfig->objectTypeIndication==GF_CODECID_HEVC) {
    1566           0 :                                 entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HVC1);
    1567           0 :                                 if (!entry_v) return GF_OUT_OF_MEM;
    1568           0 :                                 e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
    1569           0 :                                 if (e) return  e;
    1570         150 :                         } else if (esd->decoderConfig->objectTypeIndication==GF_CODECID_VVC) {
    1571           0 :                                 entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_VVC1);
    1572           0 :                                 if (!entry_v) return GF_OUT_OF_MEM;
    1573           0 :                                 e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
    1574           0 :                                 if (e) return  e;
    1575             :                         } else {
    1576         150 :                                 entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4V);
    1577         150 :                                 if (!entry_v) return GF_OUT_OF_MEM;
    1578         150 :                                 entry_v->esd = (GF_ESDBox *) gf_isom_box_new_parent(&entry_v->child_boxes, GF_ISOM_BOX_TYPE_ESDS);
    1579         150 :                                 if (!entry_v->esd) return GF_OUT_OF_MEM;
    1580         150 :                                 entry_v->esd->desc = esd;
    1581             :                         }
    1582             : 
    1583             :                         //type cast possible now
    1584             :                         entry = (GF_MPEGSampleEntryBox*) entry_v;
    1585             :                         break;
    1586         218 :                 case GF_ISOM_MEDIA_AUDIO:
    1587         218 :                         if (esd->decoderConfig->objectTypeIndication == GF_CODECID_OPUS) {
    1588           0 :                                 GF_MPEGAudioSampleEntryBox *opus = (GF_MPEGAudioSampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_OPUS);
    1589           0 :                                 if (!opus) return GF_OUT_OF_MEM;
    1590           0 :                                 opus->cfg_opus = (GF_OpusSpecificBox *)gf_isom_box_new_parent(&opus->child_boxes, GF_ISOM_BOX_TYPE_DOPS);
    1591           0 :                                 if (!opus->cfg_opus) return GF_OUT_OF_MEM;
    1592             :                                 entry = (GF_MPEGSampleEntryBox*)opus;
    1593           0 :                                 gf_odf_desc_del((GF_Descriptor *) esd);
    1594         218 :                         } else if (esd->decoderConfig->objectTypeIndication == GF_CODECID_AC3) {
    1595           0 :                                 GF_MPEGAudioSampleEntryBox *ac3 = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_AC3);
    1596           0 :                                 if (!ac3) return GF_OUT_OF_MEM;
    1597           0 :                                 ac3->cfg_ac3 = (GF_AC3ConfigBox *) gf_isom_box_new_parent(&ac3->child_boxes, GF_ISOM_BOX_TYPE_DAC3);
    1598           0 :                                 if (!ac3->cfg_ac3) return GF_OUT_OF_MEM;
    1599             :                                 entry = (GF_MPEGSampleEntryBox*) ac3;
    1600           0 :                                 gf_odf_desc_del((GF_Descriptor *) esd);
    1601         218 :                         } else if (esd->decoderConfig->objectTypeIndication==GF_CODECID_EAC3) {
    1602           0 :                                 GF_MPEGAudioSampleEntryBox *eac3 = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_EC3);
    1603           0 :                                 if (!eac3) return GF_OUT_OF_MEM;
    1604           0 :                                 eac3->cfg_ac3 = (GF_AC3ConfigBox *) gf_isom_box_new_parent(&eac3->child_boxes, GF_ISOM_BOX_TYPE_DEC3);
    1605           0 :                                 if (!eac3->cfg_ac3) return GF_OUT_OF_MEM;
    1606             :                                 entry = (GF_MPEGSampleEntryBox*) eac3;
    1607           0 :                                 gf_odf_desc_del((GF_Descriptor *) esd);
    1608             :                         } else {
    1609         218 :                                 entry_a = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4A);
    1610         218 :                                 if (!entry_a) return GF_OUT_OF_MEM;
    1611         218 :                                 entry_a->samplerate_hi = trak->Media->mediaHeader->timeScale;
    1612         218 :                                 entry_a->esd = (GF_ESDBox *) gf_isom_box_new_parent(&entry_a->child_boxes, GF_ISOM_BOX_TYPE_ESDS);
    1613         218 :                                 if (!entry_a->esd) return GF_OUT_OF_MEM;
    1614         218 :                                 entry_a->esd->desc = esd;
    1615             :                                 //type cast possible now
    1616             :                                 entry = (GF_MPEGSampleEntryBox*) entry_a;
    1617             :                         }
    1618             :                         break;
    1619         123 :                 default:
    1620         123 :                         if ((esd->decoderConfig->streamType==0x03) && (esd->decoderConfig->objectTypeIndication==0x09)) {
    1621           3 :                                 entry = (GF_MPEGSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_LSR1);
    1622           3 :                                 if (!entry) return GF_OUT_OF_MEM;
    1623           3 :                                 e = LSR_UpdateESD((GF_LASeRSampleEntryBox*)entry, esd);
    1624           3 :                                 if (e) return  e;
    1625             :                         } else {
    1626         120 :                                 entry = (GF_MPEGSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4S);
    1627         120 :                                 entry->esd = (GF_ESDBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_ESDS);
    1628         120 :                                 if (!entry->esd) return GF_OUT_OF_MEM;
    1629         120 :                                 entry->esd->desc = esd;
    1630             :                         }
    1631             :                         break;
    1632             :                 }
    1633         495 :                 entry->dataReferenceIndex = DataReferenceIndex;
    1634             : 
    1635         495 :                 if (!trak->Media->information->sampleTable->SampleDescription->child_boxes)
    1636           0 :                         trak->Media->information->sampleTable->SampleDescription->child_boxes = gf_list_new();
    1637         495 :                 gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, entry);
    1638             :                 
    1639         495 :                 e = stsd_on_child_box((GF_Box*)trak->Media->information->sampleTable->SampleDescription, (GF_Box *) entry, GF_FALSE);
    1640         495 :                 if (e) return e;
    1641         495 :                 if(outStreamIndex) *outStreamIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1642             :         }
    1643             :         return GF_OK;
    1644             : }
    1645             : 
    1646             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
    1647             : 
    1648             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13