LCOV - code coverage report
Current view: top level - isomedia - stbl_write.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 754 1150 65.6 %
Date: 2021-04-29 23:48:07 Functions: 35 43 81.4 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISO Media File Format sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/isomedia_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_ISOM
      29             : 
      30             : /*macro used for table gf_realloc - we allocate much more than needed in order to keep the number of
      31             : gf_realloc low, which greatly impacts performances for large files*/
      32             : #define ALLOC_INC(a) {\
      33             :                 u32 new_a = ((a<10) ? 100 : (a*3)/2);\
      34             :                 if (new_a < a) return GF_OUT_OF_MEM;\
      35             :                 a = new_a;\
      36             :         }
      37             : 
      38             : #ifndef GPAC_DISABLE_ISOM_WRITE
      39             : 
      40             : //adds a DTS in the table and get the sample number of this new sample
      41             : //we could return an error if a sample with the same DTS already exists
      42             : //but this is not true for QT or MJ2K, only for MP4...
      43             : //we assume the authoring tool tries to create a compliant MP4 file.
      44      556713 : GF_Err stbl_AddDTS(GF_SampleTableBox *stbl, u64 DTS, u32 *sampleNumber, u32 LastAUDefDuration, u32 nb_packed_samples)
      45             : {
      46             :         u32 i, j, sampNum;
      47             :         u64 *DTSs, curDTS;
      48             :         Bool inserted;
      49             :         GF_SttsEntry *ent;
      50             : 
      51      556713 :         GF_TimeToSampleBox *stts = stbl->TimeToSample;
      52             : 
      53             :         //reset the reading cache when adding a sample
      54      556713 :         stts->r_FirstSampleInEntry = 0;
      55             : 
      56      556713 :         *sampleNumber = 0;
      57      556713 :         if (!nb_packed_samples)
      58             :                 nb_packed_samples=1;
      59             : 
      60             :         //if we don't have an entry, that's the first one...
      61      556713 :         if (!stts->nb_entries) {
      62             :                 //assert the first DTS is 0. If not, that will break the whole file
      63        1316 :                 if (DTS) return GF_BAD_PARAM;
      64        1316 :                 stts->alloc_size = 1;
      65        1316 :                 stts->nb_entries = 1;
      66        1316 :                 stts->entries = gf_malloc(sizeof(GF_SttsEntry));
      67        1316 :                 if (!stts->entries) return GF_OUT_OF_MEM;
      68        1316 :                 stts->entries[0].sampleCount = nb_packed_samples;
      69        1316 :                 stts->entries[0].sampleDelta = (nb_packed_samples>1) ? 0 : LastAUDefDuration;
      70        1316 :                 (*sampleNumber) = 1;
      71        1316 :                 stts->w_currentSampleNum = nb_packed_samples;
      72        1316 :                 return GF_OK;
      73             :         }
      74             :         //check the last DTS - we allow 0-duration samples (same DTS)
      75      555397 :         if (DTS >= stts->w_LastDTS) {
      76             :                 u32 nb_extra = 0;
      77      555391 :                 ent = &stts->entries[stts->nb_entries-1];
      78      555391 :                 if (!ent->sampleDelta && (ent->sampleCount>1)) {
      79          22 :                         ent->sampleDelta = (u32) ( DTS / ent->sampleCount);
      80          22 :                         stts->w_LastDTS = DTS - ent->sampleDelta;
      81             :                 }
      82             :                 //OK, we're adding at the end
      83      555391 :                 if ((DTS == stts->w_LastDTS + ent->sampleDelta)
      84             :                         //for raw audio, consider (dts==last_dts) and (dts==last_dts+2*delta) as sample append to cope with
      85             :                         //timescale vs samplerate precision
      86       18681 :                         || ((nb_packed_samples>1) && ((DTS == stts->w_LastDTS) || (DTS == stts->w_LastDTS + 2*ent->sampleDelta) ))
      87             :                 ) {
      88      536710 :                         (*sampleNumber) = stts->w_currentSampleNum + 1;
      89      536710 :                         ent->sampleCount += nb_packed_samples;
      90      536710 :                         stts->w_currentSampleNum += nb_packed_samples;
      91      536710 :                         stts->w_LastDTS = DTS + ent->sampleDelta * (nb_packed_samples-1);
      92      536710 :                         return GF_OK;
      93             :                 }
      94             :                 //we need to split the entry
      95       18681 :                 if (ent->sampleCount == 1) {
      96             :                         //FIXME - we need more tests with timed text
      97             : #if 0
      98             :                         if (stts->w_LastDTS)
      99             :                                 ent->sampleDelta += (u32) (DTS - stts->w_LastDTS);
     100             :                         else
     101             :                                 ent->sampleDelta = (u32) DTS;
     102             : #else
     103             :                         //use this one and adjust...
     104       13890 :                         ent->sampleDelta = (u32) (DTS - stts->w_LastDTS);
     105             : #endif
     106             : 
     107       13890 :                         ent->sampleCount ++;
     108             :                         //little opt, merge last entry with previous one if same delta
     109       13890 :                         if ((stts->nb_entries>=2) && (ent->sampleDelta== stts->entries[stts->nb_entries-2].sampleDelta)) {
     110       13527 :                                 stts->entries[stts->nb_entries-2].sampleCount += ent->sampleCount;
     111       13527 :                                 stts->nb_entries--;
     112             :                         }
     113       13890 :                         stts->w_currentSampleNum ++;
     114       13890 :                         stts->w_LastDTS = DTS;
     115       13890 :                         (*sampleNumber) = stts->w_currentSampleNum;
     116       13890 :                         return GF_OK;
     117             :                 }
     118             :                 //we definitely need to split the entry ;)
     119        4791 :                 ent->sampleCount --;
     120             : 
     121        4791 :                 if (nb_packed_samples>1)
     122             :                         nb_extra = 1;
     123             : 
     124        4791 :                 if (stts->alloc_size <= stts->nb_entries + nb_extra) {
     125          93 :                         ALLOC_INC(stts->alloc_size);
     126          93 :                         stts->entries = gf_realloc(stts->entries, sizeof(GF_SttsEntry)*stts->alloc_size);
     127          93 :                         if (!stts->entries) return GF_OUT_OF_MEM;
     128          93 :                         memset(&stts->entries[stts->nb_entries], 0, sizeof(GF_SttsEntry)*(stts->alloc_size-stts->nb_entries) );
     129             :                 }
     130             : 
     131        4791 :                 if (nb_extra)
     132           0 :                         nb_extra = stts->entries[stts->nb_entries-1].sampleDelta;
     133             : 
     134        4791 :                 ent = &stts->entries[stts->nb_entries];
     135        4791 :                 stts->nb_entries++;
     136             : 
     137        4791 :                 if (nb_packed_samples==1) {
     138        4791 :                         ent->sampleCount = 2;
     139        4791 :                         ent->sampleDelta = (u32) (DTS - stts->w_LastDTS);
     140        4791 :                         stts->w_LastDTS = DTS;
     141        4791 :                         (*sampleNumber) = stts->w_currentSampleNum+1;
     142        4791 :                         stts->w_currentSampleNum += 1;
     143        4791 :                         return GF_OK;
     144             :                 }
     145             : 
     146           0 :                 ent->sampleCount = 1;
     147           0 :                 ent->sampleDelta = (u32) (DTS - stts->w_LastDTS);
     148             : 
     149           0 :                 ent = &stts->entries[stts->nb_entries];
     150           0 :                 stts->nb_entries++;
     151             : 
     152           0 :                 ent->sampleCount = nb_packed_samples;
     153           0 :                 ent->sampleDelta = nb_extra;
     154           0 :                 stts->w_LastDTS = DTS;
     155           0 :                 (*sampleNumber) = stts->w_currentSampleNum + 1;
     156           0 :                 stts->w_currentSampleNum += nb_packed_samples;
     157           0 :                 return GF_OK;
     158             :         }
     159             : 
     160             : 
     161             :         //unpack the DTSs and locate new sample...
     162           6 :         DTSs = (u64*)gf_malloc(sizeof(u64) * (stbl->SampleSize->sampleCount+2) );
     163           6 :         if (!DTSs) return GF_OUT_OF_MEM;
     164             :         curDTS = 0;
     165             :         sampNum = 0;
     166             :         ent = NULL;
     167             :         inserted = 0;
     168          15 :         for (i=0; i<stts->nb_entries; i++) {
     169          15 :                 ent = & stts->entries[i];
     170         108 :                 for (j = 0; j<ent->sampleCount; j++) {
     171          93 :                         if (!inserted && (curDTS > DTS)) {
     172           6 :                                 DTSs[sampNum] = DTS;
     173           6 :                                 sampNum++;
     174           6 :                                 *sampleNumber = sampNum;
     175             :                                 inserted = 1;
     176             :                         }
     177          93 :                         DTSs[sampNum] = curDTS;
     178          93 :                         curDTS += ent->sampleDelta;
     179          93 :                         sampNum ++;
     180             :                 }
     181             :         }
     182           6 :         if (!inserted) {
     183           0 :                 gf_free(DTSs);
     184           0 :                 return GF_BAD_PARAM;
     185             :         }
     186             : 
     187             :         /*we will at most insert 3 new entries*/
     188           6 :         if (stts->nb_entries+3 >= stts->alloc_size) {
     189           6 :                 stts->alloc_size += 3;
     190           6 :                 stts->entries = gf_realloc(stts->entries, sizeof(GF_SttsEntry)*stts->alloc_size);
     191           6 :                 if (!stts->entries) return GF_OUT_OF_MEM;
     192           6 :                 memset(&stts->entries[stts->nb_entries], 0, sizeof(GF_SttsEntry)*(stts->alloc_size - stts->nb_entries) );
     193             :         }
     194             : 
     195             :         /*repack the DTSs*/
     196             :         j=0;
     197           6 :         stts->nb_entries = 1;
     198           6 :         stts->entries[0].sampleCount = 1;
     199           6 :         stts->entries[0].sampleDelta = (u32) DTSs[1] /* - (DTS[0] which is 0)*/;
     200          99 :         for (i=1; i<stbl->SampleSize->sampleCount+1; i++) {
     201          93 :                 if (i == stbl->SampleSize->sampleCount) {
     202             :                         //and by default, our last sample has the same delta as the prev
     203           6 :                         stts->entries[j].sampleCount++;
     204          87 :                 } else if (stts->entries[j].sampleDelta == (u32) ( DTSs[i+1] - DTSs[i]) ) {
     205          60 :                         stts->entries[j].sampleCount ++;
     206             :                 } else {
     207          27 :                         stts->nb_entries ++;
     208          27 :                         j++;
     209          27 :                         stts->entries[j].sampleCount = 1;
     210          27 :                         stts->entries[j].sampleDelta = (u32) (DTSs[i+1] - DTSs[i]);
     211             :                 }
     212             :         }
     213           6 :         gf_free(DTSs);
     214             : 
     215             :         //reset the cache to the end
     216           6 :         stts->w_currentSampleNum = stbl->SampleSize->sampleCount + 1;
     217           6 :         return GF_OK;
     218             : }
     219             : 
     220      152909 : GF_Err AddCompositionOffset(GF_CompositionOffsetBox *ctts, s32 offset)
     221             : {
     222      152909 :         if (!ctts) return GF_BAD_PARAM;
     223             : 
     224      152909 :         if (ctts->nb_entries && (ctts->entries[ctts->nb_entries-1].decodingOffset==offset)) {
     225       24579 :                 ctts->entries[ctts->nb_entries-1].sampleCount++;
     226             :         } else {
     227      128330 :                 if (ctts->alloc_size==ctts->nb_entries) {
     228         622 :                         ALLOC_INC(ctts->alloc_size);
     229         622 :                         ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
     230         622 :                         if (!ctts->entries) return GF_OUT_OF_MEM;
     231         622 :                         memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size-ctts->nb_entries) );
     232             :                 }
     233      128330 :                 if (!ctts->entries) return GF_OUT_OF_MEM;
     234             : 
     235      128330 :                 ctts->entries[ctts->nb_entries].decodingOffset = offset;
     236      128330 :                 ctts->entries[ctts->nb_entries].sampleCount = 1;
     237      128330 :                 ctts->nb_entries++;
     238             :         }
     239      152909 :         if (offset<0) ctts->version=1;
     240      152909 :         ctts->w_LastSampleNumber++;
     241      152909 :         return GF_OK;
     242             : }
     243             : 
     244             : //adds a CTS offset for a new sample
     245      152002 : GF_Err stbl_AddCTS(GF_SampleTableBox *stbl, u32 sampleNumber, s32 offset)
     246             : {
     247             :         u32 i, j, sampNum, *CTSs;
     248             : 
     249      152002 :         GF_CompositionOffsetBox *ctts = stbl->CompositionOffset;
     250             : 
     251             :         /*in unpack mode we're sure to have 1 ctts entry per sample*/
     252      152002 :         if (ctts->unpack_mode) {
     253         692 :                 if (ctts->nb_entries==ctts->alloc_size) {
     254           7 :                         ALLOC_INC(ctts->alloc_size);
     255           7 :                         ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
     256           7 :                         if (!ctts->entries) return GF_OUT_OF_MEM;
     257           7 :                         memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size - ctts->nb_entries) );
     258             :                 }
     259         692 :                 ctts->entries[ctts->nb_entries].decodingOffset = offset;
     260         692 :                 ctts->entries[ctts->nb_entries].sampleCount = 1;
     261         692 :                 ctts->nb_entries++;
     262         692 :                 ctts->w_LastSampleNumber++;
     263         692 :                 if (offset<0) ctts->version=1;
     264             :                 return GF_OK;
     265             :         }
     266             :         //check if we're working in order...
     267      151310 :         if (ctts->w_LastSampleNumber < sampleNumber) {
     268             :                 //add some 0 till we get to the sample
     269      152909 :                 while (ctts->w_LastSampleNumber + 1 != sampleNumber) {
     270        1599 :                         GF_Err e = AddCompositionOffset(ctts, 0);
     271        1599 :                         if (e) return e;
     272             :                 }
     273      151310 :                 return AddCompositionOffset(ctts, offset);
     274             :         }
     275             : 
     276             :         //NOPE we are inserting a sample...
     277           0 :         CTSs = (u32*)gf_malloc(sizeof(u32) * (stbl->SampleSize->sampleCount+1) );
     278           0 :         if (!CTSs) return GF_OUT_OF_MEM;
     279             :         sampNum = 0;
     280           0 :         for (i=0; i<ctts->nb_entries; i++) {
     281           0 :                 for (j = 0; j<ctts->entries[i].sampleCount; j++) {
     282           0 :                         if (sampNum > stbl->SampleSize->sampleCount) {
     283           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Too many CTS Offset entries for %d samples\n", stbl->SampleSize->sampleCount ));
     284           0 :                                 gf_free(CTSs);
     285           0 :                                 return GF_ISOM_INVALID_FILE;
     286             :                         }
     287           0 :                         if (sampNum+1==sampleNumber) {
     288           0 :                                 CTSs[sampNum] = offset;
     289             :                                 sampNum ++;
     290             :                         }
     291           0 :                         CTSs[sampNum] = ctts->entries[i].decodingOffset;
     292           0 :                         sampNum ++;
     293             :                 }
     294             :         }
     295             : 
     296             :         /*we will at most add 2 new entries (splitting of an existing one)*/
     297           0 :         if (ctts->nb_entries+2>=ctts->alloc_size) {
     298           0 :                 ctts->alloc_size += 2;
     299           0 :                 ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
     300           0 :                 if (!ctts->entries) return GF_OUT_OF_MEM;
     301           0 :                 memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size-ctts->nb_entries) );
     302             :         }
     303             : 
     304           0 :         ctts->entries[0].sampleCount = 1;
     305           0 :         ctts->entries[0].decodingOffset = CTSs[0];
     306           0 :         ctts->nb_entries = 1;
     307             :         j=0;
     308           0 :         for (i=1; i<stbl->SampleSize->sampleCount + 1; i++) {
     309           0 :                 if (CTSs[i]==ctts->entries[j].decodingOffset) {
     310           0 :                         ctts->entries[j].sampleCount++;
     311             :                 } else {
     312           0 :                         j++;
     313           0 :                         ctts->nb_entries++;
     314           0 :                         ctts->entries[j].sampleCount = 1;
     315           0 :                         ctts->entries[j].decodingOffset = CTSs[i];
     316             :                 }
     317             :         }
     318           0 :         gf_free(CTSs);
     319             : 
     320           0 :         if (offset<0) ctts->version=1;
     321             : 
     322             :         /*we've inserted a sample, therefore the last sample (n) has now number n+1
     323             :         we cannot use SampleCount because we have probably skipped some samples
     324             :         (we're calling AddCTS only if the sample has a offset !!!)*/
     325           0 :         ctts->w_LastSampleNumber += 1;
     326           0 :         return GF_OK;
     327             : }
     328             : 
     329         182 : GF_Err stbl_repackCTS(GF_CompositionOffsetBox *ctts)
     330             : {
     331             :         u32 i, j;
     332             : 
     333         182 :         if (!ctts->unpack_mode) return GF_OK;
     334         182 :         ctts->unpack_mode = 0;
     335             : 
     336             :         j=0;
     337      133715 :         for (i=1; i<ctts->nb_entries; i++) {
     338      133533 :                 if (ctts->entries[i].decodingOffset==ctts->entries[j].decodingOffset) {
     339       18051 :                         ctts->entries[j].sampleCount++;
     340             :                 } else {
     341      115482 :                         j++;
     342      115482 :                         ctts->entries[j].sampleCount = 1;
     343      115482 :                         ctts->entries[j].decodingOffset = ctts->entries[i].decodingOffset;
     344             :                 }
     345             :         }
     346         182 :         ctts->nb_entries=j+1;
     347             :         /*note we don't realloc*/
     348         182 :         return GF_OK;
     349             : }
     350             : 
     351        1577 : GF_Err stbl_unpackCTS(GF_SampleTableBox *stbl)
     352             : {
     353             :         GF_DttsEntry *packed;
     354             :         u32 i, j, count;
     355             :         GF_CompositionOffsetBox *ctts;
     356        1577 :         ctts = stbl->CompositionOffset;
     357        1577 :         if (!ctts || ctts->unpack_mode) return GF_OK;
     358         186 :         ctts->unpack_mode = 1;
     359             : 
     360         186 :         packed = ctts->entries;
     361         186 :         count = ctts->nb_entries;
     362         186 :         ctts->entries = NULL;
     363         186 :         ctts->nb_entries = 0;
     364         186 :         ctts->alloc_size = 0;
     365      116561 :         for (i=0; i<count; i++) {
     366      134144 :                 for (j=0; j<packed[i].sampleCount; j++) {
     367      134144 :                         if (ctts->nb_entries == ctts->alloc_size) {
     368         640 :                                 ALLOC_INC(ctts->alloc_size);
     369         640 :                                 ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
     370         640 :                                 if (!ctts->entries) return GF_OUT_OF_MEM;
     371             : 
     372         640 :                                 memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size-ctts->nb_entries) );
     373             :                         }
     374      134144 :                         ctts->entries[ctts->nb_entries].decodingOffset = packed[i].decodingOffset;
     375      134144 :                         ctts->entries[ctts->nb_entries].sampleCount = 1;
     376      134144 :                         ctts->nb_entries++;
     377             :                 }
     378             :         }
     379         186 :         gf_free(packed);
     380             : 
     381        1122 :         while (stbl->SampleSize->sampleCount > ctts->nb_entries) {
     382         750 :                 if (ctts->nb_entries == ctts->alloc_size) {
     383           6 :                         ALLOC_INC(ctts->alloc_size);
     384           6 :                         ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
     385           6 :                         if (!ctts->entries) return GF_OUT_OF_MEM;
     386           6 :                         memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size-ctts->nb_entries) );
     387             :                 }
     388         750 :                 ctts->entries[ctts->nb_entries].decodingOffset = 0;
     389         750 :                 ctts->entries[ctts->nb_entries].sampleCount = 1;
     390         750 :                 ctts->nb_entries++;
     391             :         }
     392             :         return GF_OK;
     393             : }
     394             : 
     395             : //add size
     396      556713 : GF_Err stbl_AddSize(GF_SampleSizeBox *stsz, u32 sampleNumber, u32 size, u32 nb_pack_samples)
     397             : {
     398             :         u32 i, k;
     399             :         u32 *newSizes;
     400      556713 :         if (!stsz /*|| !size */ || !sampleNumber) return GF_BAD_PARAM;
     401             : 
     402      556713 :         if (sampleNumber > stsz->sampleCount + 1) return GF_BAD_PARAM;
     403             : 
     404      556713 :         if (!nb_pack_samples) nb_pack_samples = 1;
     405         490 :         else if (nb_pack_samples>1)
     406         490 :                 size /= nb_pack_samples;
     407             : 
     408             :         //all samples have the same size
     409      556713 :         if (stsz->sizes == NULL) {
     410             :                 //1 first sample added in NON COMPACT MODE
     411       80934 :                 if (! stsz->sampleCount && (stsz->type != GF_ISOM_BOX_TYPE_STZ2) ) {
     412        1316 :                         stsz->sampleCount = nb_pack_samples;
     413        1316 :                         stsz->sampleSize = size;
     414        1316 :                         return GF_OK;
     415             :                 }
     416             :                 //2- sample has the same size
     417       79618 :                 if (stsz->sampleSize == size) {
     418       78611 :                         stsz->sampleCount += nb_pack_samples;
     419       78611 :                         return GF_OK;
     420             :                 }
     421        1007 :                 if (nb_pack_samples>1) {
     422           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Inserting packed samples with different sizes is not yet supported\n" ));
     423             :                         return GF_NOT_SUPPORTED;
     424             :                 }
     425             :                 //3- no, need to alloc a size table
     426        1007 :                 stsz->sizes = (u32*)gf_malloc(sizeof(u32) * (stsz->sampleCount + 1));
     427        1007 :                 if (!stsz->sizes) return GF_OUT_OF_MEM;
     428        1007 :                 stsz->alloc_size = stsz->sampleCount + 1;
     429             : 
     430             :                 k = 0;
     431        3145 :                 for (i = 0 ; i < stsz->sampleCount; i++) {
     432        1131 :                         if (i + 1 == sampleNumber) {
     433           0 :                                 stsz->sizes[i + k] = size;
     434             :                                 k = 1;
     435             :                         }
     436        1131 :                         stsz->sizes[i+k] = stsz->sampleSize;
     437             :                 }
     438             :                 //this if we append a new sample
     439        1007 :                 if (stsz->sampleCount + 1 == sampleNumber) {
     440        1007 :                         stsz->sizes[stsz->sampleCount] = size;
     441             :                 }
     442        1007 :                 stsz->sampleSize = 0;
     443        1007 :                 stsz->sampleCount++;
     444        1007 :                 return GF_OK;
     445             :         }
     446             : 
     447             : 
     448             :         /*append*/
     449      475779 :         if (stsz->sampleCount + 1 == sampleNumber) {
     450      475773 :                 if (!stsz->alloc_size) stsz->alloc_size = stsz->sampleCount;
     451      475773 :                 if (stsz->sampleCount == stsz->alloc_size) {
     452        3451 :                         ALLOC_INC(stsz->alloc_size);
     453        3451 :                         stsz->sizes = gf_realloc(stsz->sizes, sizeof(u32)*(stsz->alloc_size) );
     454        3451 :                         if (!stsz->sizes) return GF_OUT_OF_MEM;
     455        3451 :                         memset(&stsz->sizes[stsz->sampleCount], 0, sizeof(u32)*(stsz->alloc_size - stsz->sampleCount) );
     456             :                 }
     457      475773 :                 stsz->sizes[stsz->sampleCount] = size;
     458             :         } else {
     459           6 :                 newSizes = (u32*)gf_malloc(sizeof(u32)*(1 + stsz->sampleCount) );
     460           6 :                 if (!newSizes) return GF_OUT_OF_MEM;
     461             :                 k = 0;
     462          99 :                 for (i = 0; i < stsz->sampleCount; i++) {
     463          93 :                         if (i + 1 == sampleNumber) {
     464           6 :                                 newSizes[i + k] = size;
     465             :                                 k = 1;
     466             :                         }
     467          93 :                         newSizes[i + k] = stsz->sizes[i];
     468             :                 }
     469           6 :                 gf_free(stsz->sizes);
     470           6 :                 stsz->sizes = newSizes;
     471           6 :                 stsz->alloc_size = 1 + stsz->sampleCount;
     472             :         }
     473      475779 :         stsz->sampleCount++;
     474      475779 :         return GF_OK;
     475             : }
     476             : 
     477             : 
     478       12101 : GF_Err stbl_AddRAP(GF_SyncSampleBox *stss, u32 sampleNumber)
     479             : {
     480             :         u32 i, k;
     481             :         u32 *newNumbers;
     482             : 
     483       12101 :         if (!stss || !sampleNumber) return GF_BAD_PARAM;
     484             : 
     485       12101 :         if (stss->sampleNumbers == NULL) {
     486         703 :                 ALLOC_INC(stss->alloc_size);
     487         703 :                 stss->sampleNumbers = (u32*)gf_malloc(sizeof(u32)*stss->alloc_size);
     488         703 :                 if (!stss->sampleNumbers) return GF_OUT_OF_MEM;
     489         703 :                 stss->sampleNumbers[0] = sampleNumber;
     490         703 :                 stss->nb_entries = 1;
     491         703 :                 return GF_OK;
     492             :         }
     493             : 
     494       11398 :         if (stss->sampleNumbers[stss->nb_entries-1] == sampleNumber) return GF_OK;
     495             : 
     496       11398 :         if (stss->sampleNumbers[stss->nb_entries-1] < sampleNumber) {
     497       11396 :                 if (stss->nb_entries==stss->alloc_size) {
     498          41 :                         ALLOC_INC(stss->alloc_size);
     499          41 :                         stss->sampleNumbers = gf_realloc(stss->sampleNumbers, sizeof(u32) * stss->alloc_size);
     500          41 :                         if (!stss->sampleNumbers) return GF_OUT_OF_MEM;
     501          41 :                         memset(&stss->sampleNumbers[stss->nb_entries], 0, sizeof(u32) * (stss->alloc_size-stss->nb_entries) );
     502             :                 }
     503       11396 :                 stss->sampleNumbers[stss->nb_entries] = sampleNumber;
     504             :         } else {
     505           2 :                 newNumbers = (u32*)gf_malloc(sizeof(u32) * (stss->nb_entries + 1));
     506           2 :                 if (!newNumbers) return GF_OUT_OF_MEM;
     507             :                 //the table is in increasing order of sampleNumber
     508             :                 k = 0;
     509           9 :                 for (i = 0; i < stss->nb_entries; i++) {
     510           9 :                         if (stss->sampleNumbers[i] >= sampleNumber) {
     511           5 :                                 newNumbers[i + k] = sampleNumber;
     512             :                                 k = 1;
     513             :                         }
     514           9 :                         newNumbers[i + k] = stss->sampleNumbers[i] + k;
     515             :                 }
     516           2 :                 gf_free(stss->sampleNumbers);
     517           2 :                 stss->sampleNumbers = newNumbers;
     518           2 :                 stss->alloc_size = stss->nb_entries+1;
     519             :         }
     520             :         //update our list
     521       11398 :         stss->nb_entries ++;
     522       11398 :         return GF_OK;
     523             : }
     524             : 
     525           0 : GF_Err stbl_AddRedundant(GF_SampleTableBox *stbl, u32 sampleNumber)
     526             : {
     527             :         GF_SampleDependencyTypeBox *sdtp;
     528             : 
     529           0 :         if (stbl->SampleDep == NULL) {
     530           0 :                 stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_SDTP);
     531           0 :                 if (!stbl->SampleDep) return GF_OUT_OF_MEM;
     532             :         }
     533           0 :         sdtp = stbl->SampleDep;
     534           0 :         if (sdtp->sampleCount + 1 < sampleNumber) {
     535           0 :                 u32 missed = sampleNumber-1 - sdtp->sampleCount;
     536           0 :                 sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount+missed) );
     537           0 :                 if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     538           0 :                 sdtp->sample_alloc = sdtp->sampleCount+missed;
     539           0 :                 memset(&sdtp->sample_info[sdtp->sampleCount], 0, sizeof(u8) * missed );
     540           0 :                 while (missed) {
     541             :                         GF_ISOSAPType isRAP;
     542           0 :                         if (stbl->SyncSample) stbl_GetSampleRAP(stbl->SyncSample, sdtp->sampleCount+1, &isRAP, NULL, NULL);
     543           0 :                         else isRAP = 1;
     544           0 :                         sdtp->sample_info[sdtp->sampleCount] = isRAP ? 0x20 : 0;
     545           0 :                         sdtp->sampleCount++;
     546           0 :                         missed--;
     547             :                 }
     548             :         }
     549             : 
     550           0 :         sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1));
     551           0 :         if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     552           0 :         sdtp->sample_alloc = sdtp->sampleCount+1;
     553           0 :         if (sdtp->sampleCount < sampleNumber) {
     554           0 :                 sdtp->sample_info[sdtp->sampleCount] = 0x29;
     555             :         } else {
     556           0 :                 u32 snum = sampleNumber-1;
     557           0 :                 memmove(sdtp->sample_info+snum+1, sdtp->sample_info+snum, sizeof(u8) * (sdtp->sampleCount - snum) );
     558           0 :                 sdtp->sample_info[snum] = 0x29;
     559             :         }
     560             :         //update our list
     561           0 :         sdtp->sampleCount ++;
     562           0 :         return GF_OK;
     563             : }
     564             : 
     565        3346 : GF_Err stbl_SetDependencyType(GF_SampleTableBox *stbl, u32 sampleNumber, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant)
     566             : {
     567             :         GF_SampleDependencyTypeBox *sdtp;
     568             :         u32 flags;
     569        3346 :         if (stbl->SampleDep == NULL) {
     570           6 :                 stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_SDTP);
     571           6 :                 if (!stbl->SampleDep) return GF_OUT_OF_MEM;
     572             :         }
     573        3346 :         sdtp = stbl->SampleDep;
     574             : 
     575             :         flags = 0;
     576        3346 :         flags |= isLeading << 6;
     577        3346 :         flags |= dependsOn << 4;
     578        3346 :         flags |= dependedOn << 2;
     579        3346 :         flags |= redundant;
     580             : 
     581        3346 :         if (sdtp->sampleCount < sampleNumber) {
     582             :                 u32 i;
     583        3346 :                 sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * sampleNumber);
     584        3346 :                 if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     585        3346 :                 sdtp->sample_alloc = sampleNumber;
     586             : 
     587        6692 :                 for (i=sdtp->sampleCount; i<sampleNumber; i++) {
     588        3346 :                         sdtp->sample_info[i] = 0;
     589             :                 }
     590        3346 :                 sdtp->sampleCount = sampleNumber;
     591             :         }
     592        3346 :         sdtp->sample_info[sampleNumber-1] = flags;
     593        3346 :         return GF_OK;
     594             : }
     595             : 
     596             : #if 0 //unused
     597             : GF_Err stbl_AddDependencyType(GF_SampleTableBox *stbl, u32 sampleNumber, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant)
     598             : {
     599             :         u32 flags;
     600             :         GF_SampleDependencyTypeBox *sdtp;
     601             : 
     602             :         if (stbl->SampleDep == NULL) {
     603             :                 stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_SDTP);
     604             :                 if (!stbl->SampleDep) return GF_OUT_OF_MEM;
     605             :         }
     606             :         sdtp = stbl->SampleDep;
     607             :         if (sdtp->sampleCount + 1 < sampleNumber) {
     608             :                 u32 missed = sampleNumber-1 - sdtp->sampleCount;
     609             :                 sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount+missed) );
     610             :                 if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     611             :                 sdtp->sample_alloc = sdtp->sampleCount+missed;
     612             :                 memset(&sdtp->sample_info[sdtp->sampleCount], 0, sizeof(u8) * missed );
     613             :                 while (missed) {
     614             :                         GF_ISOSAPType isRAP;
     615             :                         if (stbl->SyncSample) stbl_GetSampleRAP(stbl->SyncSample, sdtp->sampleCount+1, &isRAP, NULL, NULL);
     616             :                         else isRAP = 1;
     617             :                         sdtp->sample_info[sdtp->sampleCount] = isRAP ? (2<<4) : 0;
     618             :                         if (isRAP) {
     619             :                                 sdtp->sample_info[sdtp->sampleCount] = 0;
     620             : 
     621             :                         }
     622             :                         sdtp->sampleCount++;
     623             :                         missed--;
     624             :                 }
     625             :         }
     626             : 
     627             :         flags = 0;
     628             :         flags |= isLeading << 6;
     629             :         flags |= dependsOn << 4;
     630             :         flags |= dependedOn << 2;
     631             :         flags |= redundant;
     632             : 
     633             :         sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1));
     634             :         if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     635             :         sdtp->sample_alloc = sdtp->sampleCount + 1;
     636             :         if (sdtp->sampleCount < sampleNumber) {
     637             :                 sdtp->sample_info[sdtp->sampleCount] = flags;
     638             :         } else {
     639             :                 u32 snum = sampleNumber-1;
     640             :                 memmove(sdtp->sample_info+snum+1, sdtp->sample_info+snum, sizeof(u8) * (sdtp->sampleCount - snum) );
     641             :                 sdtp->sample_info[snum] = flags;
     642             :         }
     643             :         //update our list
     644             :         sdtp->sampleCount ++;
     645             :         return GF_OK;
     646             : }
     647             : #endif
     648             : 
     649      109695 : GF_Err stbl_AppendDependencyType(GF_SampleTableBox *stbl, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant)
     650             : {
     651             :         GF_SampleDependencyTypeBox *sdtp;
     652             :         u32 flags;
     653      109695 :         if (stbl->SampleDep == NULL) {
     654         318 :                 stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_SDTP);
     655         318 :                 if (!stbl->SampleDep) return GF_OUT_OF_MEM;
     656             :         }
     657      109695 :         sdtp = stbl->SampleDep;
     658             : 
     659             :         flags = 0;
     660      109695 :         flags |= isLeading << 6;
     661      109695 :         flags |= dependsOn << 4;
     662      109695 :         flags |= dependedOn << 2;
     663      109695 :         flags |= redundant;
     664             : 
     665      109695 :         if (sdtp->sampleCount >= sdtp->sample_alloc) {
     666        3019 :                 ALLOC_INC(sdtp->sample_alloc);
     667        3019 :                 if (sdtp->sampleCount >= sdtp->sample_alloc) sdtp->sample_alloc = sdtp->sampleCount+1;
     668        3019 :                 sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * sdtp->sample_alloc);
     669        3019 :                 if (!sdtp->sample_info) return GF_OUT_OF_MEM;
     670             :         }
     671      109695 :         sdtp->sample_info[sdtp->sampleCount] = flags;
     672      109695 :         sdtp->sampleCount ++;
     673      109695 :         return GF_OK;
     674             : }
     675             : 
     676             : //this function is always called in INCREASING order of shadow sample numbers
     677          12 : GF_Err stbl_AddShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber, u32 shadowNumber)
     678             : {
     679             :         GF_StshEntry *ent;
     680             :         u32 i, count;
     681          12 :         count = gf_list_count(stsh->entries);
     682          21 :         for (i=0; i<count; i++) {
     683           9 :                 ent = (GF_StshEntry*)gf_list_get(stsh->entries, i);
     684           9 :                 if (ent->shadowedSampleNumber == shadowNumber) {
     685           0 :                         ent->syncSampleNumber = sampleNumber;
     686           0 :                         return GF_OK;
     687           9 :                 } else if (ent->shadowedSampleNumber > shadowNumber) break;
     688             :         }
     689          12 :         ent = (GF_StshEntry*)gf_malloc(sizeof(GF_StshEntry));
     690          12 :         if (!ent) return GF_OUT_OF_MEM;
     691          12 :         ent->shadowedSampleNumber = shadowNumber;
     692          12 :         ent->syncSampleNumber = sampleNumber;
     693          12 :         if (i == gf_list_count(stsh->entries)) {
     694          12 :                 return gf_list_add(stsh->entries, ent);
     695             :         } else {
     696           0 :                 return gf_list_insert(stsh->entries, ent, i ? i-1 : 0);
     697             :         }
     698             : }
     699             : 
     700             : //used in edit/write, where sampleNumber == chunkNumber
     701      555750 : GF_Err stbl_AddChunkOffset(GF_MediaBox *mdia, u32 sampleNumber, u32 StreamDescIndex, u64 offset, u32 nb_pack_samples)
     702             : {
     703             :         GF_SampleTableBox *stbl;
     704             :         GF_ChunkOffsetBox *stco;
     705             :         GF_SampleToChunkBox *stsc;
     706             :         GF_ChunkLargeOffsetBox *co64;
     707             :         GF_StscEntry *ent;
     708             :         u32 i, k, *newOff, new_chunk_idx=0;
     709             :         u64 *newLarge;
     710             :         s32 insert_idx = -1;
     711             : 
     712      555750 :         stbl = mdia->information->sampleTable;
     713      555750 :         stsc = stbl->SampleToChunk;
     714             : 
     715             : //      if (stsc->w_lastSampleNumber + 1 < sampleNumber ) return GF_BAD_PARAM;
     716      555750 :         if (!nb_pack_samples)
     717             :                 nb_pack_samples = 1;
     718             : 
     719      555750 :         if (!stsc->nb_entries || (stsc->nb_entries + 2 >= stsc->alloc_size)) {
     720        3963 :                 if (!stsc->alloc_size) stsc->alloc_size = 1;
     721        3963 :                 ALLOC_INC(stsc->alloc_size);
     722        3963 :                 stsc->entries = gf_realloc(stsc->entries, sizeof(GF_StscEntry)*stsc->alloc_size);
     723        3963 :                 if (!stsc->entries) return GF_OUT_OF_MEM;
     724        3963 :                 memset(&stsc->entries[stsc->nb_entries], 0, sizeof(GF_StscEntry)*(stsc->alloc_size-stsc->nb_entries) );
     725             :         }
     726      555750 :         if (sampleNumber == stsc->w_lastSampleNumber + 1) {
     727      555741 :                 ent = &stsc->entries[stsc->nb_entries];
     728      555741 :                 stsc->w_lastChunkNumber ++;
     729      555741 :                 ent->firstChunk = stsc->w_lastChunkNumber;
     730      555741 :                 if (stsc->nb_entries) stsc->entries[stsc->nb_entries-1].nextChunk = stsc->w_lastChunkNumber;
     731             : 
     732      555741 :                 new_chunk_idx = stsc->w_lastChunkNumber;
     733      555741 :                 stsc->w_lastSampleNumber = sampleNumber + nb_pack_samples-1;
     734      555741 :                 stsc->nb_entries += 1;
     735             :         } else {
     736             :                 u32 cur_samp = 1;
     737             :                 u32 samples_in_next_entry = 0;
     738             :                 u32 next_entry_first_chunk = 1;
     739         114 :                 for (i=0; i<stsc->nb_entries; i++) {
     740             :                         u32 nb_chunks = 1;
     741         111 :                         ent = &stsc->entries[i];
     742         111 :                         if (i+1<stsc->nb_entries) nb_chunks = stsc->entries[i+1].firstChunk - ent->firstChunk;
     743         216 :                         for (k=0; k<nb_chunks; k++) {
     744         111 :                                 if ((cur_samp <= sampleNumber) && (ent->samplesPerChunk + cur_samp > sampleNumber)) {
     745           6 :                                         insert_idx = i;
     746             :                                         //stsc entry has samples before inserted sample, split
     747           6 :                                         if (sampleNumber>cur_samp) {
     748           0 :                                                 samples_in_next_entry = ent->samplesPerChunk - (sampleNumber-cur_samp);
     749           0 :                                                 ent->samplesPerChunk = sampleNumber-cur_samp;
     750             :                                         }
     751             :                                         break;
     752             :                                 }
     753         105 :                                 cur_samp += ent->samplesPerChunk;
     754         105 :                                 next_entry_first_chunk++;
     755             :                         }
     756         111 :                         if (insert_idx>=0) break;
     757             :                 }
     758             :                 //we need to split the entry
     759           9 :                 if (samples_in_next_entry) {
     760           0 :                         memmove(&stsc->entries[insert_idx+3], &stsc->entries[insert_idx+1], sizeof(GF_StscEntry)*(stsc->nb_entries - insert_idx - 1));
     761             :                         //copy over original entry
     762           0 :                         ent = &stsc->entries[insert_idx];
     763           0 :                         stsc->entries[insert_idx+2] = *ent;
     764           0 :                         stsc->entries[insert_idx+2].samplesPerChunk = samples_in_next_entry;
     765           0 :                         stsc->entries[insert_idx+2].firstChunk = next_entry_first_chunk + 1;
     766             : 
     767             :                         //setup new entry
     768           0 :                         ent = &stsc->entries[insert_idx+1];
     769           0 :                         ent->firstChunk = next_entry_first_chunk;
     770             : 
     771           0 :                         stsc->nb_entries += 2;
     772             :                 } else {
     773           9 :                         if (insert_idx<0) {
     774           3 :                                 ent = &stsc->entries[stsc->nb_entries];
     775           3 :                                 insert_idx = stsc->nb_entries;
     776             :                         } else {
     777           6 :                                 memmove(&stsc->entries[insert_idx+1], &stsc->entries[insert_idx], sizeof(GF_StscEntry)*(stsc->nb_entries+1-insert_idx));
     778           6 :                                 ent = &stsc->entries[insert_idx+1];
     779             :                         }
     780             : 
     781           9 :                         ent->firstChunk = next_entry_first_chunk;
     782           9 :                         stsc->nb_entries += 1;
     783             :                 }
     784             :                 new_chunk_idx = next_entry_first_chunk;
     785             :         }
     786      555750 :         ent->isEdited = (Media_IsSelfContained(mdia, StreamDescIndex)) ? 1 : 0;
     787      555750 :         ent->sampleDescriptionIndex = StreamDescIndex;
     788      555750 :         ent->samplesPerChunk = nb_pack_samples;
     789      555750 :         ent->nextChunk = ent->firstChunk+1;
     790             : 
     791             :         //OK, now if we've inserted a chunk, update the sample to chunk info...
     792      555750 :         if (sampleNumber + nb_pack_samples - 1 == stsc->w_lastSampleNumber) {
     793      555741 :                 if (stsc->nb_entries)
     794      555741 :                         stsc->entries[stsc->nb_entries-1].nextChunk = ent->firstChunk;
     795             : 
     796      555741 :                 stbl->SampleToChunk->currentIndex = stsc->nb_entries-1;
     797      555741 :                 stbl->SampleToChunk->firstSampleInCurrentChunk = sampleNumber;
     798             :                 //write - edit mode: sample number = chunk number
     799      555741 :                 stbl->SampleToChunk->currentChunk = stsc->w_lastChunkNumber;
     800      555741 :                 stbl->SampleToChunk->ghostNumber = 1;
     801             :         } else {
     802             :                 /*offset remaining entries*/
     803          66 :                 for (i = insert_idx+1; i<stsc->nb_entries+1; i++) {
     804          48 :                         stsc->entries[i].firstChunk++;
     805          48 :                         if (i+1<stsc->nb_entries)
     806          33 :                                 stsc->entries[i-1].nextChunk = stsc->entries[i].firstChunk;
     807             :                 }
     808             :         }
     809             : 
     810             :         //add the offset to the chunk...
     811             :         //and we change our offset
     812      555750 :         if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
     813             :                 stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
     814             :                 //if the new offset is a large one, we have to rewrite our table entry by entry (32->64 bit conv)...
     815      555750 :                 if (offset > 0xFFFFFFFF) {
     816           0 :                         co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CO64);
     817           0 :                         if (!co64) return GF_OUT_OF_MEM;
     818           0 :                         co64->nb_entries = stco->nb_entries + 1;
     819           0 :                         co64->alloc_size = co64->nb_entries;
     820           0 :                         co64->offsets = (u64*)gf_malloc(sizeof(u64) * co64->nb_entries);
     821           0 :                         if (!co64->offsets) return GF_OUT_OF_MEM;
     822             :                         k = 0;
     823           0 :                         for (i=0; i<stco->nb_entries; i++) {
     824           0 :                                 if (i + 1 == new_chunk_idx) {
     825           0 :                                         co64->offsets[i] = offset;
     826             :                                         k = 1;
     827             :                                 }
     828           0 :                                 co64->offsets[i+k] = (u64) stco->offsets[i];
     829             :                         }
     830           0 :                         if (!k) co64->offsets[co64->nb_entries - 1] = offset;
     831           0 :                         gf_isom_box_del_parent(&stbl->child_boxes, stbl->ChunkOffset);
     832           0 :                         stbl->ChunkOffset = (GF_Box *) co64;
     833             :                 } else {
     834             :                         //no, we can use this one.
     835      555750 :                         if (new_chunk_idx > stco->nb_entries) {
     836      555744 :                                 if (!stco->alloc_size) stco->alloc_size = stco->nb_entries;
     837      555744 :                                 if (stco->nb_entries == stco->alloc_size) {
     838        3956 :                                         ALLOC_INC(stco->alloc_size);
     839        3956 :                                         stco->offsets = (u32*)gf_realloc(stco->offsets, sizeof(u32) * stco->alloc_size);
     840        3956 :                                         if (!stco->offsets) return GF_OUT_OF_MEM;
     841        3956 :                                         memset(&stco->offsets[stco->nb_entries], 0, sizeof(u32) * (stco->alloc_size-stco->nb_entries) );
     842             :                                 }
     843      555744 :                                 stco->offsets[stco->nb_entries] = (u32) offset;
     844      555744 :                                 stco->nb_entries += 1;
     845             :                         } else {
     846             :                                 //nope. we're inserting
     847           6 :                                 newOff = (u32*)gf_malloc(sizeof(u32) * (stco->nb_entries + 1));
     848           6 :                                 if (!newOff) return GF_OUT_OF_MEM;
     849             :                                 k=0;
     850          99 :                                 for (i=0; i<stco->nb_entries; i++) {
     851          93 :                                         if (i+1 == new_chunk_idx) {
     852           6 :                                                 newOff[i] = (u32) offset;
     853             :                                                 k=1;
     854             :                                         }
     855          93 :                                         newOff[i+k] = stco->offsets[i];
     856             :                                 }
     857           6 :                                 gf_free(stco->offsets);
     858           6 :                                 stco->offsets = newOff;
     859           6 :                                 stco->nb_entries ++;
     860           6 :                                 stco->alloc_size = stco->nb_entries;
     861             :                         }
     862             :                 }
     863             :         } else {
     864             :                 //use large offset...
     865             :                 co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
     866           0 :                 if (sampleNumber > co64->nb_entries) {
     867           0 :                         if (!co64->alloc_size) co64->alloc_size = co64->nb_entries;
     868           0 :                         if (co64->nb_entries == co64->alloc_size) {
     869           0 :                                 ALLOC_INC(co64->alloc_size);
     870           0 :                                 co64->offsets = (u64*)gf_realloc(co64->offsets, sizeof(u64) * co64->alloc_size);
     871           0 :                                 if (!co64->offsets) return GF_OUT_OF_MEM;
     872           0 :                                 memset(&co64->offsets[co64->nb_entries], 0, sizeof(u64) * (co64->alloc_size - co64->nb_entries) );
     873             :                         }
     874           0 :                         co64->offsets[co64->nb_entries] = offset;
     875           0 :                         co64->nb_entries += 1;
     876             :                 } else {
     877             :                         //nope. we're inserting
     878           0 :                         newLarge = (u64*)gf_malloc(sizeof(u64) * (co64->nb_entries + 1));
     879           0 :                         if (!newLarge) return GF_OUT_OF_MEM;
     880             :                         k=0;
     881           0 :                         for (i=0; i<co64->nb_entries; i++) {
     882           0 :                                 if (i+1 == new_chunk_idx) {
     883           0 :                                         newLarge[i] = offset;
     884             :                                         k=1;
     885             :                                 }
     886           0 :                                 newLarge[i+k] = co64->offsets[i];
     887             :                         }
     888           0 :                         gf_free(co64->offsets);
     889           0 :                         co64->offsets = newLarge;
     890           0 :                         co64->nb_entries++;
     891           0 :                         co64->alloc_size++;
     892             :                 }
     893             :         }
     894             : 
     895             :         return GF_OK;
     896             : }
     897             : 
     898             : 
     899             : 
     900             : 
     901        4677 : GF_Err stbl_SetChunkOffset(GF_MediaBox *mdia, u32 sampleNumber, u64 offset)
     902             : {
     903             :         GF_StscEntry *ent;
     904             :         u32 i;
     905             :         GF_ChunkLargeOffsetBox *co64;
     906        4677 :         GF_SampleTableBox *stbl = mdia->information->sampleTable;
     907             : 
     908        4677 :         if (!sampleNumber || !stbl) return GF_BAD_PARAM;
     909             : 
     910        4677 :         ent = &stbl->SampleToChunk->entries[sampleNumber - 1];
     911             : 
     912             :         //we edit our entry if self contained
     913        4677 :         if (Media_IsSelfContained(mdia, ent->sampleDescriptionIndex))
     914        4677 :                 ent->isEdited = 1;
     915             : 
     916             :         //and we change our offset
     917        4677 :         if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
     918             :                 //if the new offset is a large one, we have to rewrite our table...
     919        4677 :                 if (offset > 0xFFFFFFFF) {
     920           0 :                         co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CO64);
     921           0 :                         if (!co64) return GF_OUT_OF_MEM;
     922           0 :                         co64->nb_entries = ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->nb_entries;
     923           0 :                         co64->alloc_size = co64->nb_entries;
     924           0 :                         co64->offsets = (u64*)gf_malloc(sizeof(u64)*co64->nb_entries);
     925           0 :                         if (!co64->offsets) return GF_OUT_OF_MEM;
     926           0 :                         for (i=0; i<co64->nb_entries; i++) {
     927           0 :                                 co64->offsets[i] = (u64) ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets[i];
     928             :                         }
     929           0 :                         co64->offsets[ent->firstChunk - 1] = offset;
     930           0 :                         gf_isom_box_del_parent(&stbl->child_boxes, stbl->ChunkOffset);
     931           0 :                         stbl->ChunkOffset = (GF_Box *) co64;
     932           0 :                         return GF_OK;
     933             :                 }
     934        4677 :                 ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets[ent->firstChunk - 1] = (u32) offset;
     935             :         } else {
     936           0 :                 ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets[ent->firstChunk - 1] = offset;
     937             :         }
     938             :         return GF_OK;
     939             : }
     940             : 
     941             : 
     942           0 : GF_Err stbl_SetSampleCTS(GF_SampleTableBox *stbl, u32 sampleNumber, s32 offset)
     943             : {
     944           0 :         GF_CompositionOffsetBox *ctts = stbl->CompositionOffset;
     945             : 
     946             :         assert(ctts->unpack_mode);
     947             : 
     948             :         //if we're setting the CTS of a sample we've skipped...
     949           0 :         if (ctts->w_LastSampleNumber < sampleNumber) {
     950             :                 //add some 0 till we get to the sample
     951           0 :                 while (ctts->w_LastSampleNumber + 1 != sampleNumber) {
     952           0 :                         GF_Err e = AddCompositionOffset(ctts, 0);
     953           0 :                         if (e) return e;
     954             :                 }
     955           0 :                 return AddCompositionOffset(ctts, offset);
     956             :         }
     957           0 :         if (offset<0) ctts->version=1;
     958           0 :         ctts->entries[sampleNumber-1].decodingOffset = offset;
     959           0 :         return GF_OK;
     960             : }
     961             : 
     962        4677 : GF_Err stbl_SetSampleSize(GF_SampleSizeBox *stsz, u32 SampleNumber, u32 size)
     963             : {
     964             :         u32 i;
     965        4677 :         if (!SampleNumber || (stsz->sampleCount < SampleNumber)) return GF_BAD_PARAM;
     966             : 
     967        4677 :         if (stsz->sampleSize) {
     968           0 :                 if (stsz->sampleSize == size) return GF_OK;
     969           0 :                 if (stsz->sampleCount == 1) {
     970           0 :                         stsz->sampleSize = size;
     971           0 :                         return GF_OK;
     972             :                 }
     973             :                 //nope, we have to rewrite a table
     974           0 :                 stsz->sizes = (u32*)gf_malloc(sizeof(u32)*stsz->sampleCount);
     975           0 :                 if (!stsz->sizes) return GF_OUT_OF_MEM;
     976           0 :                 for (i=0; i<stsz->sampleCount; i++) stsz->sizes[i] = stsz->sampleSize;
     977           0 :                 stsz->sampleSize = 0;
     978             :         }
     979        4677 :         stsz->sizes[SampleNumber - 1] = size;
     980        4677 :         return GF_OK;
     981             : }
     982             : 
     983             : 
     984           0 : GF_Err stbl_SetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 isRAP)
     985             : {
     986             :         u32 i;
     987             : 
     988             :         //check if we have already a sync sample
     989           0 :         for (i = 0; i < stss->nb_entries; i++) {
     990             : 
     991           0 :                 if (stss->sampleNumbers[i] < SampleNumber) continue;
     992           0 :                 else if (stss->sampleNumbers[i] > SampleNumber) break;
     993             : 
     994             :                 /*found our sample number*/
     995           0 :                 if (isRAP) return GF_OK;
     996             :                 /*remove it...*/
     997           0 :                 if (i+1 < stss->nb_entries)
     998           0 :                         memmove(stss->sampleNumbers + i, stss->sampleNumbers + i + 1, sizeof(u32) * (stss->nb_entries - i - 1));
     999           0 :                 stss->nb_entries--;
    1000           0 :                 return GF_OK;
    1001             :         }
    1002             :         //we need to insert a RAP somewhere if RAP ...
    1003           0 :         if (!isRAP) return GF_OK;
    1004           0 :         if (stss->nb_entries==stss->alloc_size) {
    1005           0 :                 ALLOC_INC(stss->alloc_size);
    1006           0 :                 stss->sampleNumbers = gf_realloc(stss->sampleNumbers, sizeof(u32)*stss->alloc_size);
    1007           0 :                 if (!stss->sampleNumbers) return GF_OUT_OF_MEM;
    1008           0 :                 memset(&stss->sampleNumbers[stss->nb_entries], 0, sizeof(u32)*(stss->alloc_size - stss->nb_entries) );
    1009             :         }
    1010             : 
    1011           0 :         if (i+1 < stss->nb_entries)
    1012           0 :                 memmove(stss->sampleNumbers + i + 1, stss->sampleNumbers + i, sizeof(u32) * (stss->nb_entries - i - 1));
    1013           0 :         stss->sampleNumbers[i] = SampleNumber;
    1014           0 :         stss->nb_entries ++;
    1015           0 :         return GF_OK;
    1016             : }
    1017             : 
    1018           0 : GF_Err stbl_SetRedundant(GF_SampleTableBox *stbl, u32 sampleNumber)
    1019             : {
    1020           0 :         if (stbl->SampleDep->sampleCount < sampleNumber) {
    1021           0 :                 return stbl_AddRedundant(stbl, sampleNumber);
    1022             :         } else {
    1023           0 :                 stbl->SampleDep->sample_info[sampleNumber-1] = 0x29;
    1024           0 :                 return GF_OK;
    1025             :         }
    1026             : }
    1027             : 
    1028           0 : GF_Err stbl_SetSyncShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber, u32 syncSample)
    1029             : {
    1030             :         u32 i, count;
    1031             :         GF_StshEntry *ent;
    1032             : 
    1033           0 :         count = gf_list_count(stsh->entries);
    1034           0 :         for (i=0; i<count; i++) {
    1035           0 :                 ent = (GF_StshEntry*)gf_list_get(stsh->entries, i);
    1036           0 :                 if (ent->shadowedSampleNumber == sampleNumber) {
    1037           0 :                         ent->syncSampleNumber = syncSample;
    1038           0 :                         return GF_OK;
    1039             :                 }
    1040           0 :                 if (ent->shadowedSampleNumber > sampleNumber) break;
    1041             :         }
    1042             :         //we need a new one...
    1043           0 :         ent = (GF_StshEntry*)gf_malloc(sizeof(GF_StshEntry));
    1044           0 :         if (!ent) return GF_OUT_OF_MEM;
    1045           0 :         ent->shadowedSampleNumber = sampleNumber;
    1046           0 :         ent->syncSampleNumber = syncSample;
    1047             :         //insert or append ?
    1048           0 :         if (i == gf_list_count(stsh->entries)) {
    1049             :                 //don't update the cache ...
    1050           0 :                 return gf_list_add(stsh->entries, ent);
    1051             :         } else {
    1052             :                 //update the cache
    1053           0 :                 stsh->r_LastEntryIndex = i;
    1054           0 :                 stsh->r_LastFoundSample = sampleNumber;
    1055           0 :                 return gf_list_insert(stsh->entries, ent, i);
    1056             :         }
    1057             : }
    1058             : 
    1059             : 
    1060             : //always called before removing the sample from SampleSize
    1061         562 : GF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples, u32 LastAUDefDuration)
    1062             : {
    1063             :         GF_SttsEntry *ent;
    1064             :         GF_TimeToSampleBox *stts;
    1065             : 
    1066         562 :         if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM;
    1067             : 
    1068         562 :         stts = stbl->TimeToSample;
    1069             : 
    1070             :         //we're removing the only sample: empty the sample table
    1071         562 :         if (stbl->SampleSize->sampleCount == 1) {
    1072           0 :                 stts->nb_entries = 0;
    1073           0 :                 stts->r_FirstSampleInEntry = stts->r_currentEntryIndex = 0;
    1074           0 :                 stts->r_CurrentDTS = 0;
    1075           0 :                 return GF_OK;
    1076             :         }
    1077             :         //we're removing the last sample
    1078         562 :         if ((nb_samples==1) && (sampleNumber == stbl->SampleSize->sampleCount)) {
    1079           4 :                 ent = &stts->entries[stts->nb_entries-1];
    1080           4 :                 ent->sampleCount--;
    1081           4 :                 if (!ent->sampleCount) stts->nb_entries--;
    1082             :         } else {
    1083             :                 u64 *DTSs, curDTS;
    1084             :                 u32 i, j, k, sampNum;
    1085             :                 u32 tot_samples, nb_written=0;
    1086             :                 //unpack the DTSs...
    1087         558 :                 DTSs = (u64*)gf_malloc(sizeof(u64) * (stbl->SampleSize->sampleCount - 1));
    1088         558 :                 if (!DTSs) return GF_OUT_OF_MEM;
    1089         558 :                 memset(DTSs, 0, sizeof(u64) * (stbl->SampleSize->sampleCount - 1) );
    1090             : 
    1091             :                 curDTS = 0;
    1092             :                 sampNum = 0;
    1093             :                 ent = NULL;
    1094             :                 k=0;
    1095             : 
    1096       58928 :                 for (i=0; i<stts->nb_entries; i++) {
    1097       58370 :                         ent = & stts->entries[i];
    1098      400471 :                         for (j=0; j<ent->sampleCount; j++) {
    1099      342101 :                                 if (nb_samples==1) {
    1100      175955 :                                         if (sampNum == sampleNumber - 1) {
    1101             :                                                 k=1;
    1102             :                                         } else {
    1103      175472 :                                                 DTSs[sampNum-k] = curDTS;
    1104             :                                         }
    1105      166146 :                                 } else if (sampNum >= nb_samples) {
    1106      151204 :                                         DTSs[sampNum - nb_samples] = curDTS;
    1107             :                                         nb_written++;
    1108             :                                 }
    1109      342101 :                                 curDTS += ent->sampleDelta;
    1110      342101 :                                 sampNum ++;
    1111             :                         }
    1112             :                 }
    1113             : 
    1114             :                 if (nb_samples>1) {
    1115             :                         assert(sampNum == stbl->SampleSize->sampleCount);
    1116             :                         assert(nb_written + nb_samples == stbl->SampleSize->sampleCount);
    1117             :                 }
    1118             :                 j=0;
    1119             : 
    1120         558 :                 if (nb_samples==1) {
    1121         483 :                         tot_samples = stbl->SampleSize->sampleCount - 1;
    1122             :                 } else {
    1123          75 :                         tot_samples = stbl->SampleSize->sampleCount - nb_samples;
    1124             :                 }
    1125         558 :                 if (tot_samples) {
    1126             :                         sampNum = 1;
    1127         558 :                         stts->nb_entries = 1;
    1128         558 :                         stts->entries[0].sampleCount = 1;
    1129         558 :                         if (stbl->SampleSize->sampleCount == 2) {
    1130           0 :                                 stts->entries[0].sampleDelta = LastAUDefDuration;
    1131             :                         } else {
    1132         558 :                                 stts->entries[0].sampleDelta = (u32) DTSs[1] /*- DTSs[0]*/;
    1133             :                         }
    1134             :                 } else {
    1135             :                         sampNum = 0;
    1136           0 :                         stts->nb_entries = 0;
    1137             :                 }
    1138             : 
    1139      326676 :                 for (i=1; i<tot_samples; i++) {
    1140      326118 :                         if (i+1 == tot_samples) {
    1141             :                                 //and by default, our last sample has the same delta as the prev
    1142         558 :                                 stts->entries[j].sampleCount++;
    1143             :                                 sampNum ++;
    1144      325560 :                         } else if (DTSs[i+1] - DTSs[i] == stts->entries[j].sampleDelta) {
    1145      267254 :                                 stts->entries[j].sampleCount += 1;
    1146             :                                 sampNum ++;
    1147             :                         } else {
    1148       58306 :                                 stts->nb_entries++;
    1149       58306 :                                 if (j+1==stts->alloc_size) {
    1150         495 :                                         stts->alloc_size++;
    1151         495 :                                         stts->entries = gf_realloc(stts->entries, sizeof(GF_SttsEntry) * stts->alloc_size);
    1152         495 :                                         if (!stts->entries) return GF_OUT_OF_MEM;
    1153             :                                 }
    1154             :                                 j++;
    1155       58306 :                                 stts->entries[j].sampleCount = 1;
    1156       58306 :                                 stts->entries[j].sampleDelta = (u32) (DTSs[i+1] - DTSs[i]);
    1157             :                                 assert(stts->entries[j].sampleDelta);
    1158             :                                 sampNum ++;
    1159             :                         }
    1160             :                 }
    1161         558 :                 stts->w_LastDTS = tot_samples ? DTSs[tot_samples - 1] : 0;
    1162         558 :                 gf_free(DTSs);
    1163             :                 assert(sampNum == tot_samples);
    1164             :                 assert(sampNum + nb_samples == stbl->SampleSize->sampleCount);
    1165             :         }
    1166             : 
    1167             :         //reset write the cache to the end
    1168         562 :         stts->w_currentSampleNum = stbl->SampleSize->sampleCount - nb_samples;
    1169             :         //reset read the cache to the beginning
    1170         562 :         stts->r_FirstSampleInEntry = stts->r_currentEntryIndex = 0;
    1171         562 :         stts->r_CurrentDTS = 0;
    1172         562 :         return GF_OK;
    1173             : }
    1174             : 
    1175             : 
    1176             : //always called before removing the sample from SampleSize
    1177         561 : GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples)
    1178             : {
    1179         561 :         GF_CompositionOffsetBox *ctts = stbl->CompositionOffset;
    1180         561 :         if (!ctts) return GF_OK;
    1181             : 
    1182             :         assert(ctts->unpack_mode);
    1183         561 :         if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM;
    1184             : 
    1185             :         //last one...
    1186         561 :         if (stbl->SampleSize->sampleCount == 1) {
    1187           0 :                 gf_isom_box_del_parent(&stbl->child_boxes, (GF_Box *) ctts);
    1188           0 :                 stbl->CompositionOffset = NULL;
    1189           0 :                 return GF_OK;
    1190             :         }
    1191             : 
    1192             :         //the number of entries is NOT ALWAYS the number of samples !
    1193             :         //instead, use the cache
    1194             :         //first case, we're removing a sample that was not added yet
    1195         561 :         if (sampleNumber > ctts->w_LastSampleNumber) return GF_OK;
    1196             : 
    1197         561 :         if (nb_samples==1) {
    1198             :                 assert(ctts->nb_entries);
    1199         486 :                 memmove(&ctts->entries[sampleNumber-1], &ctts->entries[sampleNumber], sizeof(GF_DttsEntry)* (ctts->nb_entries-sampleNumber) );
    1200         486 :                 ctts->nb_entries--;
    1201             :         } else {
    1202          75 :                 memmove(&ctts->entries[0], &ctts->entries[nb_samples], sizeof(GF_DttsEntry)* (ctts->nb_entries-nb_samples) );
    1203          75 :                 ctts->nb_entries -= nb_samples;
    1204             :         }
    1205         561 :         ctts->w_LastSampleNumber -= nb_samples;
    1206             :         assert(ctts->w_LastSampleNumber >= ctts->nb_entries);
    1207             : 
    1208         561 :         return GF_OK;
    1209             : }
    1210             : 
    1211         562 : GF_Err stbl_RemoveSize(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples)
    1212             : {
    1213         562 :         GF_SampleSizeBox *stsz = stbl->SampleSize;
    1214             : 
    1215         562 :         if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM;
    1216             :         //last sample
    1217         562 :         if (stsz->sampleCount == 1) {
    1218           0 :                 if (stsz->sizes) gf_free(stsz->sizes);
    1219           0 :                 stsz->sizes = NULL;
    1220           0 :                 stsz->sampleCount = 0;
    1221           0 :                 return GF_OK;
    1222             :         }
    1223             :         //one single size
    1224         562 :         if (stsz->sampleSize) {
    1225           0 :                 stsz->sampleCount -= nb_samples;
    1226           0 :                 return GF_OK;
    1227             :         }
    1228         562 :         if (nb_samples==1) {
    1229         487 :                 if (sampleNumber < stsz->sampleCount)
    1230         483 :                         memmove(stsz->sizes + sampleNumber - 1, stsz->sizes + sampleNumber, sizeof(u32) * (stsz->sampleCount - sampleNumber));
    1231             :         } else {
    1232          75 :                 if (nb_samples < stsz->sampleCount)
    1233          75 :                         memmove(stsz->sizes, stsz->sizes + nb_samples, sizeof(u32) * (stsz->sampleCount - nb_samples));
    1234             :         }
    1235         562 :         stsz->sampleCount -= nb_samples;
    1236         562 :         return GF_OK;
    1237             : }
    1238             : 
    1239             : //always called after removing the sample from SampleSize
    1240         562 : GF_Err stbl_RemoveChunk(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples)
    1241             : {
    1242             :         u32 i;
    1243         562 :         GF_SampleToChunkBox *stsc = stbl->SampleToChunk;
    1244             : 
    1245         562 :         if ((nb_samples>1) && (sampleNumber>1))
    1246             :                 return GF_BAD_PARAM;
    1247             :         
    1248             :         //raw audio or constant sample size and dur
    1249         562 :         if (stsc->nb_entries < stbl->SampleSize->sampleCount) {
    1250           0 :                 if (sampleNumber==stbl->SampleSize->sampleCount+1) {
    1251           0 :                         GF_StscEntry *ent = &stsc->entries[stsc->nb_entries-1];
    1252           0 :                         if (ent->samplesPerChunk)
    1253           0 :                                 ent->samplesPerChunk--;
    1254           0 :                         if (!ent->samplesPerChunk) {
    1255           0 :                                 stsc->nb_entries--;
    1256             : 
    1257           0 :                                 if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
    1258           0 :                                         ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->nb_entries --;
    1259             :                                 } else {
    1260           0 :                                         ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->nb_entries --;
    1261             :                                 }
    1262           0 :                                 if (stsc->nb_entries) {
    1263           0 :                                         ent = &stsc->entries[stsc->nb_entries-1];
    1264           0 :                                         ent->nextChunk --;
    1265             :                                 }
    1266             :                         }
    1267             :                         return GF_OK;
    1268             :                 }
    1269           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] removing sample in middle of track not supported for constant size and duration samples\n"));
    1270             :                 return GF_NOT_SUPPORTED;
    1271             :         }
    1272             : 
    1273             :         //remove the entry in SampleToChunk (1 <-> 1 in edit mode)
    1274         562 :         if (nb_samples==1) {
    1275         487 :                 memmove(&stsc->entries[sampleNumber-1], &stsc->entries[sampleNumber], sizeof(GF_StscEntry)*(stsc->nb_entries-sampleNumber));
    1276         487 :                 stsc->nb_entries--;
    1277             : 
    1278             :                 //update the firstchunk info
    1279      111428 :                 for (i=sampleNumber-1; i < stsc->nb_entries; i++) {
    1280             :                         assert(stsc->entries[i].firstChunk >= 1);
    1281      110941 :                         stsc->entries[i].firstChunk -= 1;
    1282      110941 :                         if (stsc->entries[i].nextChunk) {
    1283             :                                 assert(stsc->entries[i].nextChunk >= 1);
    1284      110771 :                                 stsc->entries[i].nextChunk -= 1;
    1285             :                         }
    1286             :                 }
    1287             :         } else {
    1288          75 :                 memmove(&stsc->entries[0], &stsc->entries[nb_samples], sizeof(GF_StscEntry)*(stsc->nb_entries-nb_samples));
    1289          75 :                 stsc->nb_entries -= nb_samples;
    1290             : 
    1291             :                 //update the firstchunk info
    1292      151354 :                 for (i=0; i < stsc->nb_entries; i++) {
    1293      151204 :                         stsc->entries[i].firstChunk = i+1;
    1294      151204 :                         stsc->entries[i].nextChunk = (stsc->nb_entries==i+1) ? 0 : i+2;
    1295             :                 }
    1296             :         }
    1297         562 :         memset(&stsc->entries[stsc->nb_entries], 0, sizeof(GF_StscEntry)*(stsc->alloc_size - stsc->nb_entries) );
    1298             : 
    1299             :         //update the cache
    1300         562 :         stsc->firstSampleInCurrentChunk = 1;
    1301         562 :         stsc->currentIndex = 0;
    1302         562 :         stsc->currentChunk = 1;
    1303         562 :         stsc->ghostNumber = 1;
    1304             : 
    1305             :         //realloc the chunk offset
    1306         562 :         if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
    1307             :                 GF_ChunkOffsetBox *stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
    1308         562 :                 if (!stbl->SampleSize->sampleCount) {
    1309           0 :                         gf_free(stco->offsets);
    1310           0 :                         stco->offsets = NULL;
    1311           0 :                         stco->nb_entries = 0;
    1312           0 :                         stco->alloc_size = 0;
    1313           0 :                         return GF_OK;
    1314             :                 }
    1315             :                 assert(stco->nb_entries - nb_samples == stbl->SampleSize->sampleCount);
    1316         562 :                 if (nb_samples==1) {
    1317         487 :                         memmove(&stco->offsets[sampleNumber-1], &stco->offsets[sampleNumber], sizeof(u32) * (stco->nb_entries - sampleNumber) );
    1318             :                 } else {
    1319          75 :                         memmove(&stco->offsets[0], &stco->offsets[nb_samples], sizeof(u32) * (stco->nb_entries - nb_samples) );
    1320             :                 }
    1321         562 :                 stco->nb_entries -= nb_samples;
    1322             :         } else {
    1323             :                 GF_ChunkLargeOffsetBox *co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
    1324           0 :                 if (!stbl->SampleSize->sampleCount) {
    1325           0 :                         gf_free(co64->offsets);
    1326           0 :                         co64->offsets = NULL;
    1327           0 :                         co64->nb_entries = 0;
    1328           0 :                         co64->alloc_size = 0;
    1329           0 :                         return GF_OK;
    1330             :                 }
    1331             : 
    1332             :                 assert(co64->nb_entries - nb_samples == stbl->SampleSize->sampleCount);
    1333           0 :                 if (nb_samples==1) {
    1334           0 :                         memmove(&co64->offsets[sampleNumber-1], &co64->offsets[sampleNumber], sizeof(u64) * (co64->nb_entries - sampleNumber) );
    1335             :                 } else {
    1336           0 :                         memmove(&co64->offsets[0], &co64->offsets[nb_samples], sizeof(u64) * (co64->nb_entries - nb_samples) );
    1337             :                 }
    1338           0 :                 co64->nb_entries -= nb_samples;
    1339             :         }
    1340             :         return GF_OK;
    1341             : }
    1342             : 
    1343             : 
    1344       15428 : GF_Err stbl_RemoveRAP(GF_SampleTableBox *stbl, u32 sampleNumber)
    1345             : {
    1346             :         u32 i;
    1347             : 
    1348       15428 :         GF_SyncSampleBox *stss = stbl->SyncSample;
    1349       15428 :         if (!stss) return GF_OK;
    1350             : 
    1351             :         //we remove the only one around...
    1352       15428 :         if (stss->nb_entries == 1) {
    1353         259 :                 if (stss->sampleNumbers[0] != sampleNumber) return GF_OK;
    1354             :                 //free our numbers but don't delete (all samples are NON-sync
    1355           0 :                 gf_free(stss->sampleNumbers);
    1356           0 :                 stss->sampleNumbers = NULL;
    1357           0 :                 stss->r_LastSampleIndex = stss->r_LastSyncSample = 0;
    1358           0 :                 stss->alloc_size = stss->nb_entries = 0;
    1359           0 :                 return GF_OK;
    1360             :         }
    1361             : 
    1362     1287362 :         for (i=0; i<stss->nb_entries; i++) {
    1363             :                 //found the sample
    1364     1287362 :                 if (sampleNumber == stss->sampleNumbers[i]) {
    1365         598 :                         memmove(&stss->sampleNumbers[i], &stss->sampleNumbers[i+1], sizeof(u32)* (stss->nb_entries-i-1) );
    1366         598 :                         stss->nb_entries--;
    1367             :                 }
    1368             : 
    1369     1287362 :                 if (sampleNumber < stss->sampleNumbers[i]) {
    1370             :                         assert(stss->sampleNumbers[i]);
    1371     1287105 :                         stss->sampleNumbers[i]--;
    1372             :                 }
    1373             :         }
    1374             :         return GF_OK;
    1375             : }
    1376             : 
    1377         390 : GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber, u32 nb_samples)
    1378             : {
    1379             :         u32 i;
    1380             : 
    1381         390 :         if (!stbl->SampleDep) return GF_OK;
    1382         390 :         if (stbl->SampleDep->sampleCount < SampleNumber) return GF_BAD_PARAM;
    1383         390 :         if ((nb_samples>1) && (SampleNumber>1)) return GF_BAD_PARAM;
    1384             : 
    1385         390 :         if (nb_samples==1) {
    1386         315 :                 i = stbl->SampleDep->sampleCount - SampleNumber;
    1387         315 :                 if (i) memmove(&stbl->SampleDep->sample_info[SampleNumber-1], & stbl->SampleDep->sample_info[SampleNumber], sizeof(u8)*i);
    1388         315 :                 stbl->SampleDep->sample_info = (u8*)gf_realloc(stbl->SampleDep->sample_info, sizeof(u8) * (stbl->SampleDep->sampleCount-1));
    1389         315 :                 if (!stbl->SampleDep->sample_info) return GF_OUT_OF_MEM;
    1390         315 :                 stbl->SampleDep->sample_alloc = stbl->SampleDep->sampleCount-1;
    1391         315 :                 stbl->SampleDep->sampleCount-=1;
    1392             :         } else {
    1393          75 :                 memmove(&stbl->SampleDep->sample_info[0], &stbl->SampleDep->sample_info[nb_samples], sizeof(u8) * (stbl->SampleDep->sampleCount - nb_samples) );
    1394          75 :                 stbl->SampleDep->sampleCount -= nb_samples;
    1395             :         }
    1396             :         return GF_OK;
    1397             : }
    1398             : 
    1399       15429 : GF_Err stbl_RemoveShadow(GF_SampleTableBox *stbl, u32 sampleNumber)
    1400             : {
    1401             :         u32 i;
    1402             :         GF_ShadowSyncBox *stsh;
    1403             :         GF_StshEntry *ent;
    1404       15429 :         if (!stbl->ShadowSync) return GF_OK;
    1405             :         stsh = stbl->ShadowSync;
    1406             : 
    1407             :         //we loop for the whole chain cause the spec doesn't say if we can have several
    1408             :         //shadows for 1 sample...
    1409           0 :         i=0;
    1410           0 :         while ((ent = (GF_StshEntry *)gf_list_enum(stsh->entries, &i))) {
    1411           0 :                 if (ent->shadowedSampleNumber == sampleNumber) {
    1412           0 :                         i--;
    1413           0 :                         gf_list_rem(stsh->entries, i);
    1414             :                 }
    1415             :         }
    1416             :         //reset the cache
    1417           0 :         stsh->r_LastEntryIndex = 0;
    1418           0 :         stsh->r_LastFoundSample = 0;
    1419           0 :         return GF_OK;
    1420             : }
    1421             : 
    1422             : 
    1423           0 : GF_Err stbl_SetPaddingBits(GF_SampleTableBox *stbl, u32 SampleNumber, u8 bits)
    1424             : {
    1425             :         u8 *p;
    1426             :         //make sure the sample is a good one
    1427           0 :         if (SampleNumber > stbl->SampleSize->sampleCount) return GF_BAD_PARAM;
    1428             : 
    1429             :         //create the table
    1430           0 :         if (!stbl->PaddingBits) {
    1431           0 :                 stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_PADB);
    1432           0 :                 if (!stbl->PaddingBits) return GF_OUT_OF_MEM;
    1433             :         }
    1434             : 
    1435             :         //alloc
    1436           0 :         if (!stbl->PaddingBits->padbits || !stbl->PaddingBits->SampleCount) {
    1437           0 :                 stbl->PaddingBits->SampleCount = stbl->SampleSize->sampleCount;
    1438           0 :                 stbl->PaddingBits->padbits = (u8*)gf_malloc(sizeof(u8)*stbl->PaddingBits->SampleCount);
    1439           0 :                 if (!stbl->PaddingBits->padbits) return GF_OUT_OF_MEM;
    1440           0 :                 memset(stbl->PaddingBits->padbits, 0, sizeof(u8)*stbl->PaddingBits->SampleCount);
    1441             :         }
    1442             :         //realloc (this is needed in case n out of k samples get padding added)
    1443           0 :         if (stbl->PaddingBits->SampleCount < stbl->SampleSize->sampleCount) {
    1444           0 :                 p = (u8*)gf_malloc(sizeof(u8) * stbl->SampleSize->sampleCount);
    1445           0 :                 if (!p) return GF_OUT_OF_MEM;
    1446             :                 //set everything to 0
    1447           0 :                 memset(p, 0, stbl->SampleSize->sampleCount);
    1448             :                 //copy our previous table
    1449           0 :                 memcpy(p, stbl->PaddingBits->padbits, stbl->PaddingBits->SampleCount);
    1450           0 :                 gf_free(stbl->PaddingBits->padbits);
    1451           0 :                 stbl->PaddingBits->padbits = p;
    1452           0 :                 stbl->PaddingBits->SampleCount = stbl->SampleSize->sampleCount;
    1453             :         }
    1454           0 :         stbl->PaddingBits->padbits[SampleNumber-1] = bits;
    1455           0 :         return GF_OK;
    1456             : }
    1457             : 
    1458       15429 : GF_Err stbl_RemovePaddingBits(GF_SampleTableBox *stbl, u32 SampleNumber)
    1459             : {
    1460             :         u8 *p;
    1461             :         u32 i, k;
    1462             : 
    1463       15429 :         if (!stbl->PaddingBits) return GF_OK;
    1464           0 :         if (stbl->PaddingBits->SampleCount < SampleNumber) return GF_BAD_PARAM;
    1465             : 
    1466             :         //last sample - remove the table
    1467           0 :         if (stbl->PaddingBits->SampleCount == 1) {
    1468           0 :                 gf_isom_box_del_parent(&stbl->child_boxes, (GF_Box *) stbl->PaddingBits);
    1469           0 :                 stbl->PaddingBits = NULL;
    1470           0 :                 return GF_OK;
    1471             :         }
    1472             : 
    1473             :         //reallocate and check size by the way...
    1474           0 :         p = (u8 *)gf_malloc(sizeof(u8) * (stbl->PaddingBits->SampleCount - 1));
    1475           0 :         if (!p) return GF_OUT_OF_MEM;
    1476             : 
    1477             :         k=0;
    1478           0 :         for (i=0; i<stbl->PaddingBits->SampleCount; i++) {
    1479           0 :                 if (i+1 != SampleNumber) {
    1480           0 :                         p[k] = stbl->PaddingBits->padbits[i];
    1481           0 :                         k++;
    1482             :                 }
    1483             :         }
    1484             : 
    1485           0 :         stbl->PaddingBits->SampleCount -= 1;
    1486           0 :         gf_free(stbl->PaddingBits->padbits);
    1487           0 :         stbl->PaddingBits->padbits = p;
    1488           0 :         return GF_OK;
    1489             : }
    1490             : 
    1491       15429 : GF_Err stbl_RemoveSubSample(GF_SampleTableBox *stbl, u32 SampleNumber)
    1492             : {
    1493             :         u32 i, count, j, subs_count, prev_sample, delta=0;
    1494             : 
    1495       15429 :         if (! stbl->sub_samples) return GF_OK;
    1496           0 :         subs_count = gf_list_count(stbl->sub_samples);
    1497           0 :         for (j=0; j<subs_count; j++) {
    1498           0 :                 GF_SubSampleInformationBox *subs = gf_list_get(stbl->sub_samples, j);
    1499           0 :                 if (! subs->Samples) continue;
    1500             : 
    1501             :                 prev_sample = 0;
    1502           0 :                 count = gf_list_count(subs->Samples);
    1503           0 :                 for (i=0; i<count; i++) {
    1504           0 :                         GF_SubSampleInfoEntry *e = gf_list_get(subs->Samples, i);
    1505           0 :                         prev_sample += e->sample_delta;
    1506           0 :                         if (prev_sample==SampleNumber) {
    1507           0 :                                 gf_list_rem(subs->Samples, i);
    1508           0 :                                 while (gf_list_count(e->SubSamples)) {
    1509           0 :                                         GF_SubSampleEntry *pSubSamp = (GF_SubSampleEntry*) gf_list_get(e->SubSamples, 0);
    1510           0 :                                         gf_free(pSubSamp);
    1511           0 :                                         gf_list_rem(e->SubSamples, 0);
    1512             :                                 }
    1513           0 :                                 gf_list_del(e->SubSamples);
    1514           0 :                                 gf_free(e);
    1515           0 :                                 i--;
    1516           0 :                                 count--;
    1517             :                                 delta=1;
    1518           0 :                                 continue;
    1519             :                         }
    1520           0 :                         e->sample_delta+=delta;
    1521             :                 }
    1522             :         }
    1523             :         return GF_OK;
    1524             : }
    1525             : 
    1526             : 
    1527       15429 : GF_Err stbl_RemoveSampleGroup(GF_SampleTableBox *stbl, u32 SampleNumber)
    1528             : {
    1529             :         u32 i, k, count, prev_sample;
    1530             : 
    1531       15429 :         if (!stbl->sampleGroups) return GF_OK;
    1532             : 
    1533         240 :         count = gf_list_count(stbl->sampleGroups);
    1534             :         prev_sample = 0;
    1535         480 :         for (i=0; i<count; i++) {
    1536         240 :                 GF_SampleGroupBox *e = gf_list_get(stbl->sampleGroups, i);
    1537       13584 :                 for (k=0; k<e->entry_count; k++) {
    1538       13354 :                         if ((SampleNumber>prev_sample) && (SampleNumber <= prev_sample + e->sample_entries[k].sample_count) ) {
    1539          10 :                                 e->sample_entries[k].sample_count--;
    1540          10 :                                 if (!e->sample_entries[k].sample_count) {
    1541           0 :                                         memmove(&e->sample_entries[k], &e->sample_entries[k+1], sizeof(GF_SampleGroupEntry) * (e->entry_count-k-1));
    1542           0 :                                         e->entry_count--;
    1543             :                                 }
    1544             :                                 break;
    1545             :                         }
    1546             :                 }
    1547         240 :                 if (!e->entry_count) {
    1548           0 :                         gf_list_rem(stbl->sampleGroups, i);
    1549           0 :                         i--;
    1550           0 :                         count--;
    1551           0 :                         gf_isom_box_del_parent(&stbl->child_boxes, (GF_Box *) e);
    1552             :                 }
    1553             :         }
    1554             :         return GF_OK;
    1555             : }
    1556             : 
    1557         701 : GF_Err stbl_SampleSizeAppend(GF_SampleSizeBox *stsz, u32 data_size)
    1558             : {
    1559             :         u32 i;
    1560         701 :         if (!stsz || !stsz->sampleCount) return GF_BAD_PARAM;
    1561             : 
    1562             :         //we must realloc our table
    1563         701 :         if (stsz->sampleSize) {
    1564          17 :                 stsz->sizes = (u32*)gf_malloc(sizeof(u32)*stsz->sampleCount);
    1565          17 :                 if (!stsz->sizes) return GF_OUT_OF_MEM;
    1566          17 :                 for (i=0; i<stsz->sampleCount; i++) stsz->sizes[i] = stsz->sampleSize;
    1567          17 :                 stsz->sampleSize = 0;
    1568             :         }
    1569         701 :         if (!stsz->sizes) {
    1570           0 :                 stsz->sampleSize = data_size;
    1571             :         } else {
    1572             :                 u32 single_size;
    1573         701 :                 stsz->sizes[stsz->sampleCount-1] += data_size;
    1574             : 
    1575         701 :                 single_size = stsz->sizes[0];
    1576         701 :                 for (i=1; i<stsz->sampleCount; i++) {
    1577         684 :                         if (stsz->sizes[i] != single_size) {
    1578             :                                 single_size = 0;
    1579             :                                 break;
    1580             :                         }
    1581             :                 }
    1582         701 :                 if (single_size) {
    1583          17 :                         stsz->sampleSize = single_size;
    1584          17 :                         gf_free(stsz->sizes);
    1585          17 :                         stsz->sizes = NULL;
    1586             :                 }
    1587             :         }
    1588             :         return GF_OK;
    1589             : }
    1590             : 
    1591             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
    1592             : 
    1593             : 
    1594             : 
    1595      109375 : GF_Err stbl_AppendTime(GF_SampleTableBox *stbl, u32 duration, u32 nb_pack)
    1596             : {
    1597      109375 :         GF_TimeToSampleBox *stts = stbl->TimeToSample;
    1598             : 
    1599      109375 :         if (!nb_pack) nb_pack = 1;
    1600      109375 :         if (stts->nb_entries) {
    1601      106269 :                 if (stts->entries[stts->nb_entries-1].sampleDelta == duration) {
    1602      104349 :                         stts->entries[stts->nb_entries-1].sampleCount += nb_pack;
    1603      104349 :                         return GF_OK;
    1604             :                 }
    1605             :         }
    1606        5026 :         if (stts->nb_entries==stts->alloc_size) {
    1607        3106 :                 ALLOC_INC(stts->alloc_size);
    1608        3106 :                 stts->entries = gf_realloc(stts->entries, sizeof(GF_SttsEntry)*stts->alloc_size);
    1609        3106 :                 if (!stts->entries) return GF_OUT_OF_MEM;
    1610        3106 :                 memset(&stts->entries[stts->nb_entries], 0, sizeof(GF_SttsEntry)*(stts->alloc_size-stts->nb_entries) );
    1611             :         }
    1612        5026 :         stts->entries[stts->nb_entries].sampleCount = nb_pack;
    1613        5026 :         stts->entries[stts->nb_entries].sampleDelta = duration;
    1614        5026 :         stts->nb_entries++;
    1615        5026 :         if (stts->max_ts_delta < duration ) stts->max_ts_delta = duration;
    1616             :         return GF_OK;
    1617             : }
    1618             : 
    1619      109375 : GF_Err stbl_AppendSize(GF_SampleTableBox *stbl, u32 size, u32 nb_pack)
    1620             : {
    1621             :         u32 i;
    1622      109375 :         if (!nb_pack) nb_pack = 1;
    1623             : 
    1624      109375 :         if (!stbl->SampleSize->sampleCount) {
    1625        3106 :                 stbl->SampleSize->sampleSize = size;
    1626        3106 :                 stbl->SampleSize->sampleCount += nb_pack;
    1627        3106 :                 return GF_OK;
    1628             :         }
    1629      106269 :         if (stbl->SampleSize->sampleSize && (stbl->SampleSize->sampleSize==size)) {
    1630          30 :                 stbl->SampleSize->sampleCount += nb_pack;
    1631          30 :                 return GF_OK;
    1632             :         }
    1633      106239 :         if (!stbl->SampleSize->sizes || (stbl->SampleSize->sampleCount+nb_pack > stbl->SampleSize->alloc_size)) {
    1634             :                 Bool init_table = (stbl->SampleSize->sizes==NULL) ? 1 : 0;
    1635        3008 :                 ALLOC_INC(stbl->SampleSize->alloc_size);
    1636        3008 :                 if (stbl->SampleSize->sampleCount+nb_pack > stbl->SampleSize->alloc_size)
    1637           0 :                         stbl->SampleSize->alloc_size = stbl->SampleSize->sampleCount+nb_pack;
    1638             : 
    1639        3008 :                 stbl->SampleSize->sizes = (u32 *)gf_realloc(stbl->SampleSize->sizes, sizeof(u32)*stbl->SampleSize->alloc_size);
    1640        3008 :                 if (!stbl->SampleSize->sizes) return GF_OUT_OF_MEM;
    1641        3008 :                 memset(&stbl->SampleSize->sizes[stbl->SampleSize->sampleCount], 0, sizeof(u32) * (stbl->SampleSize->alloc_size - stbl->SampleSize->sampleCount) );
    1642             : 
    1643        3008 :                 if (init_table) {
    1644        2948 :                         for (i=0; i<stbl->SampleSize->sampleCount; i++)
    1645        2948 :                                 stbl->SampleSize->sizes[i] = stbl->SampleSize->sampleSize;
    1646             :                 }
    1647             :         }
    1648      106239 :         stbl->SampleSize->sampleSize = 0;
    1649      212478 :         for (i=0; i<nb_pack; i++) {
    1650      106239 :                 stbl->SampleSize->sizes[stbl->SampleSize->sampleCount+i] = size;
    1651             :         }
    1652      106239 :         stbl->SampleSize->sampleCount += nb_pack;
    1653      106239 :         if (size > stbl->SampleSize->max_size)
    1654       11225 :                 stbl->SampleSize->max_size = size;
    1655      106239 :         stbl->SampleSize->total_size += size;
    1656      106239 :         stbl->SampleSize->total_samples += nb_pack;
    1657      106239 :         return GF_OK;
    1658             : }
    1659             : 
    1660             : 
    1661             : 
    1662        4124 : GF_Err stbl_AppendChunk(GF_SampleTableBox *stbl, u64 offset)
    1663             : {
    1664             :         GF_ChunkOffsetBox *stco;
    1665             :         GF_ChunkLargeOffsetBox *co64;
    1666             :         u32 i;
    1667             :         
    1668             :         //we may have to convert the table...
    1669        4124 :         if (stbl->ChunkOffset->type==GF_ISOM_BOX_TYPE_STCO) {
    1670             :                 stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
    1671             : 
    1672        4124 :                 if (offset>0xFFFFFFFF) {
    1673           0 :                         co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CO64);
    1674           0 :                         if (!co64) return GF_OUT_OF_MEM;
    1675           0 :                         co64->nb_entries = stco->nb_entries + 1;
    1676           0 :                         if (co64->nb_entries<=stco->nb_entries) return GF_OUT_OF_MEM;
    1677           0 :                         co64->alloc_size = co64->nb_entries;
    1678           0 :                         co64->offsets = (u64*)gf_malloc(sizeof(u64) * co64->nb_entries);
    1679           0 :                         if (!co64->offsets) return GF_OUT_OF_MEM;
    1680           0 :                         for (i=0; i<stco->nb_entries; i++) co64->offsets[i] = stco->offsets[i];
    1681           0 :                         co64->offsets[i] = offset;
    1682           0 :                         gf_isom_box_del_parent(&stbl->child_boxes, stbl->ChunkOffset);
    1683           0 :                         stbl->ChunkOffset = (GF_Box *) co64;
    1684           0 :                         return GF_OK;
    1685             :                 }
    1686             :                 //we're fine
    1687        4124 :                 stco->alloc_size = stco->nb_entries + 1;
    1688             :                 if (stco->alloc_size < stco->nb_entries + 1) return GF_OUT_OF_MEM;
    1689        4124 :                 stco->offsets = gf_realloc(stco->offsets, sizeof(u32)*stco->alloc_size);
    1690        4124 :                 if (!stco->offsets) return GF_OUT_OF_MEM;
    1691        4124 :                 stco->offsets[stco->nb_entries] = (u32) offset;
    1692        4124 :                 stco->nb_entries += 1;
    1693        4124 :                 return GF_OK;
    1694             :         }
    1695             : 
    1696             :         co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
    1697           0 :         co64->alloc_size = co64->nb_entries+1;
    1698             :         if (co64->alloc_size < co64->nb_entries + 1) return GF_OUT_OF_MEM;
    1699             : 
    1700           0 :         co64->offsets = gf_realloc(co64->offsets, sizeof(u64)*co64->alloc_size);
    1701           0 :         if (!co64->offsets) return GF_OUT_OF_MEM;
    1702           0 :         co64->offsets[co64->nb_entries] = offset;
    1703           0 :         co64->alloc_size = co64->nb_entries;
    1704           0 :         return GF_OK;
    1705             : }
    1706             : 
    1707        4124 : GF_Err stbl_AppendSampleToChunk(GF_SampleTableBox *stbl, u32 DescIndex, u32 samplesInChunk)
    1708             : {
    1709             :         u32 nextChunk;
    1710        4124 :         GF_SampleToChunkBox *stsc= stbl->SampleToChunk;
    1711             :         GF_StscEntry *ent;
    1712             : 
    1713        4124 :         nextChunk = ((GF_ChunkOffsetBox *) stbl->ChunkOffset)->nb_entries;
    1714             : 
    1715        4124 :         if (stsc->nb_entries) {
    1716        1018 :                 ent = &stsc->entries[stsc->nb_entries-1];
    1717             :                 //good we can use this one
    1718        1018 :                 if ( (ent->sampleDescriptionIndex == DescIndex) && (ent->samplesPerChunk==samplesInChunk))
    1719             :                         return GF_OK;
    1720             : 
    1721             :                 //set the next chunk btw ...
    1722         109 :                 ent->nextChunk = nextChunk;
    1723             :         }
    1724        3215 :         if (stsc->nb_entries==stsc->alloc_size) {
    1725        3106 :                 ALLOC_INC(stsc->alloc_size);
    1726        3106 :                 stsc->entries = gf_realloc(stsc->entries, sizeof(GF_StscEntry)*stsc->alloc_size);
    1727        3106 :                 if (!stsc->entries) return GF_OUT_OF_MEM;
    1728        3106 :                 memset(&stsc->entries[stsc->nb_entries], 0, sizeof(GF_StscEntry)*(stsc->alloc_size - stsc->nb_entries) );
    1729             :         }
    1730             :         //ok we need a new entry - this assumes this function is called AFTER AppendChunk
    1731        3215 :         ent = &stsc->entries[stsc->nb_entries];
    1732        3215 :         ent->firstChunk = nextChunk;
    1733        3215 :         ent->sampleDescriptionIndex = DescIndex;
    1734        3215 :         ent->samplesPerChunk = samplesInChunk;
    1735        3215 :         ent->isEdited = 0;
    1736        3215 :         stsc->nb_entries++;
    1737        3215 :         return GF_OK;
    1738             : }
    1739             : 
    1740             : //called AFTER AddSize
    1741      109190 : GF_Err stbl_AppendRAP(GF_SampleTableBox *stbl, u8 isRap)
    1742             : {
    1743             :         u32 i;
    1744             : 
    1745             :         //no sync table
    1746      109190 :         if (!stbl->SyncSample) {
    1747             :                 //all samples RAP - no table
    1748       26638 :                 if (isRap) return GF_OK;
    1749             : 
    1750             :                 //nope, create one
    1751         225 :                 stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSS);
    1752         225 :                 if (!stbl->SyncSample) return GF_OUT_OF_MEM;
    1753             : 
    1754         225 :                 if (stbl->SampleSize->sampleCount > 1) {
    1755         225 :                         stbl->SyncSample->sampleNumbers = (u32*)gf_malloc(sizeof(u32) * (stbl->SampleSize->sampleCount-1));
    1756         225 :                         if (!stbl->SyncSample->sampleNumbers) return GF_OUT_OF_MEM;
    1757         450 :                         for (i=0; i<stbl->SampleSize->sampleCount-1; i++)
    1758         225 :                                 stbl->SyncSample->sampleNumbers[i] = i+1;
    1759             : 
    1760             :                 }
    1761         225 :                 stbl->SyncSample->nb_entries = stbl->SampleSize->sampleCount-1;
    1762         225 :                 stbl->SyncSample->alloc_size = stbl->SyncSample->nb_entries;
    1763         225 :                 return GF_OK;
    1764             :         }
    1765       82552 :         if (!isRap) return GF_OK;
    1766             : 
    1767        4764 :         if (stbl->SyncSample->alloc_size == stbl->SyncSample->nb_entries) {
    1768        2166 :                 ALLOC_INC(stbl->SyncSample->alloc_size);
    1769        2166 :                 stbl->SyncSample->sampleNumbers = (u32*) gf_realloc(stbl->SyncSample->sampleNumbers, sizeof(u32) * stbl->SyncSample->alloc_size);
    1770        2166 :                 if (!stbl->SyncSample->sampleNumbers) return GF_OUT_OF_MEM;
    1771        2166 :                 memset(&stbl->SyncSample->sampleNumbers[stbl->SyncSample->nb_entries], 0, sizeof(u32) * (stbl->SyncSample->alloc_size-stbl->SyncSample->nb_entries) );
    1772             :         }
    1773        4764 :         stbl->SyncSample->sampleNumbers[stbl->SyncSample->nb_entries] = stbl->SampleSize->sampleCount;
    1774        4764 :         stbl->SyncSample->nb_entries += 1;
    1775        4764 :         return GF_OK;
    1776             : }
    1777             : 
    1778         195 : GF_Err stbl_AppendTrafMap(GF_SampleTableBox *stbl, Bool is_seg_start, u64 seg_start_offset, u64 frag_start_offset, u8 *moof_template, u32 moof_template_size, u64 sidx_start, u64 sidx_end)
    1779             : {
    1780             :         GF_TrafToSampleMap *tmap;
    1781             :         GF_TrafMapEntry *tmap_ent;
    1782         195 :         if (!stbl->traf_map) {
    1783             :                 //nope, create one
    1784          36 :                 GF_SAFEALLOC(stbl->traf_map, GF_TrafToSampleMap);
    1785          36 :                 if (!stbl->traf_map) return GF_OUT_OF_MEM;
    1786             :         }
    1787         195 :         tmap = stbl->traf_map;
    1788         195 :         if (tmap->nb_entries >= stbl->SampleSize->sampleCount) {
    1789             :                 u32 i;
    1790           0 :                 for (i=0; i<tmap->nb_entries; i++) {
    1791           0 :                         if (tmap->frag_starts[i].moof_template)
    1792           0 :                                 gf_free(tmap->frag_starts[i].moof_template);
    1793             :                 }
    1794           0 :                 memset(tmap->frag_starts, 0, sizeof(GF_TrafMapEntry)*tmap->nb_alloc);
    1795           0 :                 tmap->nb_entries = 0;
    1796             :         }
    1797             : 
    1798         195 :         if (tmap->nb_entries + 1 > tmap->nb_alloc) {
    1799         117 :                 tmap->nb_alloc++;
    1800         117 :                 tmap->frag_starts = gf_realloc(tmap->frag_starts, sizeof(GF_TrafMapEntry) * tmap->nb_alloc);
    1801         117 :                 if (!tmap->frag_starts) return GF_OUT_OF_MEM;
    1802             :         }
    1803         195 :         tmap_ent = &tmap->frag_starts[tmap->nb_entries];
    1804         195 :         tmap->nb_entries += 1;
    1805             : 
    1806             :         memset(tmap_ent, 0, sizeof(GF_TrafMapEntry));
    1807         195 :         tmap_ent->sample_num = stbl->SampleSize->sampleCount;
    1808         195 :         tmap_ent->moof_template = moof_template;
    1809         195 :         tmap_ent->moof_template_size = moof_template_size;
    1810         195 :         tmap_ent->moof_start = frag_start_offset;
    1811         195 :         tmap_ent->sidx_start = sidx_start;
    1812         195 :         tmap_ent->sidx_end = sidx_end;
    1813         195 :         if (is_seg_start)
    1814          87 :                 tmap_ent->seg_start_plus_one = 1 + seg_start_offset;
    1815             : 
    1816             :         return GF_OK;
    1817             : }
    1818             : 
    1819           0 : GF_Err stbl_AppendPadding(GF_SampleTableBox *stbl, u8 padding)
    1820             : {
    1821           0 :         if (!stbl->PaddingBits) {
    1822           0 :                 stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_PADB);
    1823           0 :                 if (!stbl->PaddingBits) return GF_OUT_OF_MEM;
    1824             :         }
    1825           0 :         stbl->PaddingBits->padbits = (u8*)gf_realloc(stbl->PaddingBits->padbits, sizeof(u8) * stbl->SampleSize->sampleCount);
    1826           0 :         if (!stbl->PaddingBits->padbits) return GF_OUT_OF_MEM;
    1827           0 :         stbl->PaddingBits->padbits[stbl->SampleSize->sampleCount-1] = padding;
    1828           0 :         stbl->PaddingBits->SampleCount = stbl->SampleSize->sampleCount;
    1829           0 :         return GF_OK;
    1830             : }
    1831             : 
    1832      109190 : GF_Err stbl_AppendCTSOffset(GF_SampleTableBox *stbl, s32 offset)
    1833             : {
    1834             :         GF_CompositionOffsetBox *ctts;
    1835             : 
    1836      109190 :         if (!stbl->CompositionOffset) {
    1837         314 :                 stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CTTS);
    1838         314 :                 if (!stbl->CompositionOffset) return GF_OUT_OF_MEM;
    1839             :         }
    1840      109190 :         ctts = stbl->CompositionOffset;
    1841      109190 :         ctts->w_LastSampleNumber ++;
    1842             : 
    1843      109190 :         if (!ctts->unpack_mode && ctts->nb_entries && (ctts->entries[ctts->nb_entries-1].decodingOffset == offset) ) {
    1844       87589 :                 ctts->entries[ctts->nb_entries-1].sampleCount++;
    1845       87589 :                 return GF_OK;
    1846             :         }
    1847       21601 :         if (ctts->nb_entries==ctts->alloc_size) {
    1848        2955 :                 ALLOC_INC(ctts->alloc_size);
    1849        2955 :                 ctts->entries = gf_realloc(ctts->entries, sizeof(GF_DttsEntry)*ctts->alloc_size);
    1850        2955 :                 if (!ctts->entries) return GF_OUT_OF_MEM;
    1851        2955 :                 memset(&ctts->entries[ctts->nb_entries], 0, sizeof(GF_DttsEntry)*(ctts->alloc_size-ctts->nb_entries) );
    1852             :         }
    1853       21601 :         ctts->entries[ctts->nb_entries].decodingOffset = offset;
    1854       21601 :         ctts->entries[ctts->nb_entries].sampleCount = 1;
    1855       21601 :         ctts->nb_entries++;
    1856       21601 :         if (offset<0) ctts->version=1;
    1857             : 
    1858       21601 :         if (ABS(offset) > ctts->max_ts_delta) ctts->max_ts_delta = ABS(offset);
    1859             : 
    1860             :         return GF_OK;
    1861             : }
    1862             : 
    1863           3 : GF_Err stbl_AppendDegradation(GF_SampleTableBox *stbl, u16 DegradationPriority)
    1864             : {
    1865           3 :         if (!stbl->DegradationPriority) {
    1866           3 :                 stbl->DegradationPriority = (GF_DegradationPriorityBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STDP);
    1867           3 :                 if (!stbl->DegradationPriority) return GF_OUT_OF_MEM;
    1868             :         }
    1869             : 
    1870           3 :         stbl->DegradationPriority->priorities = (u16 *)gf_realloc(stbl->DegradationPriority->priorities, sizeof(u16) * stbl->SampleSize->sampleCount);
    1871           3 :         if (!stbl->DegradationPriority->priorities) return GF_OUT_OF_MEM;
    1872           3 :         stbl->DegradationPriority->priorities[stbl->SampleSize->sampleCount-1] = DegradationPriority;
    1873           3 :         stbl->DegradationPriority->nb_entries = stbl->SampleSize->sampleCount;
    1874           3 :         return GF_OK;
    1875             : }
    1876             : 
    1877             : #if 0
    1878             : GF_Err stbl_AppendDepType(GF_SampleTableBox *stbl, u32 DepType)
    1879             : {
    1880             :         if (!stbl->SampleDep) {
    1881             :                 stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_SDTP);
    1882             :                 if (!stbl->SampleDep) return GF_OUT_OF_MEM;
    1883             :         }
    1884             :         stbl->SampleDep->sample_info = (u8*)gf_realloc(stbl->SampleDep->sample_info, sizeof(u8)*stbl->SampleSize->sampleCount );
    1885             :         if (!stbl->SampleDep->sample_info) return GF_OUT_OF_MEM;
    1886             :         stbl->SampleDep->sample_alloc = stbl->SampleSize->sampleCount;
    1887             :         stbl->SampleDep->sample_info[stbl->SampleDep->sampleCount] = DepType;
    1888             :         stbl->SampleDep->sampleCount = stbl->SampleSize->sampleCount;
    1889             :         return GF_OK;
    1890             : }
    1891             : #endif
    1892             : 
    1893             : 
    1894             : 
    1895             : 
    1896             : //This functions unpack the offset for easy editing, eg each sample
    1897             : //is contained in one chunk...
    1898        1395 : GF_Err stbl_UnpackOffsets(GF_SampleTableBox *stbl)
    1899             : {
    1900             :         GF_Err e;
    1901             :         u32 i, chunkNumber, sampleDescIndex;
    1902             :         u64 dataOffset;
    1903             :         GF_StscEntry *ent;
    1904             :         GF_ChunkOffsetBox *stco_tmp;
    1905             :         GF_ChunkLargeOffsetBox *co64_tmp;
    1906             :         GF_SampleToChunkBox *stsc_tmp;
    1907             : 
    1908        1395 :         if (!stbl) return GF_ISOM_INVALID_FILE;
    1909             : 
    1910             :         //we should have none of the mandatory boxes (allowed in the spec)
    1911        1395 :         if (!stbl->ChunkOffset && !stbl->SampleDescription && !stbl->SampleSize && !stbl->SampleToChunk && !stbl->TimeToSample)
    1912             :                 return GF_OK;
    1913             :         /*empty track (just created)*/
    1914        1395 :         if (!stbl->SampleToChunk && !stbl->TimeToSample) return GF_OK;
    1915             : 
    1916             :         //or all the mandatory ones ...
    1917        1395 :         if (!stbl->ChunkOffset || !stbl->SampleDescription || !stbl->SampleSize || !stbl->SampleToChunk || !stbl->TimeToSample)
    1918             :                 return GF_ISOM_INVALID_FILE;
    1919             : 
    1920             :         //do we need to unpack? Not if we have only one sample per chunk.
    1921        1395 :         if (stbl->SampleSize->sampleCount == stbl->SampleToChunk->nb_entries) return GF_OK;
    1922             : 
    1923             :         //check the offset type and create a new table...
    1924          51 :         if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
    1925             :                 co64_tmp = NULL;
    1926          51 :                 stco_tmp = (GF_ChunkOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STCO);
    1927          51 :                 if (!stco_tmp) return GF_OUT_OF_MEM;
    1928          51 :                 stco_tmp->nb_entries = stbl->SampleSize->sampleCount;
    1929          51 :                 stco_tmp->offsets = (u32*)gf_malloc(stco_tmp->nb_entries * sizeof(u32));
    1930          51 :                 if (!stco_tmp->offsets) {
    1931           0 :                         gf_isom_box_del((GF_Box*)stco_tmp);
    1932           0 :                         return GF_OUT_OF_MEM;
    1933             :                 }
    1934          51 :                 stco_tmp->alloc_size = stco_tmp->nb_entries;
    1935           0 :         } else if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_CO64) {
    1936             :                 stco_tmp = NULL;
    1937           0 :                 co64_tmp = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);
    1938           0 :                 if (!co64_tmp) return GF_OUT_OF_MEM;
    1939           0 :                 co64_tmp->nb_entries = stbl->SampleSize->sampleCount;
    1940           0 :                 co64_tmp->offsets = (u64*)gf_malloc(co64_tmp->nb_entries * sizeof(u64));
    1941           0 :                 if (!co64_tmp->offsets) {
    1942           0 :                         gf_isom_box_del((GF_Box*)co64_tmp);
    1943           0 :                         return GF_OUT_OF_MEM;
    1944             :                 }
    1945           0 :                 co64_tmp->alloc_size = co64_tmp->nb_entries;
    1946             :         } else {
    1947             :                 return GF_ISOM_INVALID_FILE;
    1948             :         }
    1949             : 
    1950             :         //create a new SampleToChunk table
    1951          51 :         stsc_tmp = (GF_SampleToChunkBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSC);
    1952          51 :         if (!stsc_tmp) return GF_OUT_OF_MEM;
    1953             : 
    1954          51 :         stsc_tmp->nb_entries = stsc_tmp->alloc_size = stbl->SampleSize->sampleCount;
    1955          51 :         stsc_tmp->entries = gf_malloc(sizeof(GF_StscEntry)*stsc_tmp->nb_entries);
    1956          51 :         if (!stsc_tmp->entries) return GF_OUT_OF_MEM;
    1957             :         //set write cache to last sample before unpack
    1958          51 :         stsc_tmp->w_lastSampleNumber = stbl->SampleSize->sampleCount;
    1959          51 :         stsc_tmp->w_lastChunkNumber = stbl->SampleSize->sampleCount;
    1960             : 
    1961             :         //OK write our two tables...
    1962             :         ent = NULL;
    1963       89156 :         for (i = 0; i < stbl->SampleSize->sampleCount; i++) {
    1964             :                 //get the data info for the sample
    1965       89054 :                 e = stbl_GetSampleInfos(stbl, i+1, &dataOffset, &chunkNumber, &sampleDescIndex, NULL);
    1966       89054 :                 if (e) goto err_exit;
    1967       89054 :                 ent = &stsc_tmp->entries[i];
    1968       89054 :                 ent->isEdited = 0;
    1969       89054 :                 ent->sampleDescriptionIndex = sampleDescIndex;
    1970             :                 //here's the trick: each sample is in ONE chunk
    1971       89054 :                 ent->firstChunk = i+1;
    1972       89054 :                 ent->nextChunk = i+2;
    1973       89054 :                 ent->samplesPerChunk = 1;
    1974       89054 :                 if (stco_tmp) {
    1975       89054 :                         stco_tmp->offsets[i] = (u32) dataOffset;
    1976             :                 } else {
    1977           0 :                         co64_tmp->offsets[i] = dataOffset;
    1978             :                 }
    1979             :         }
    1980             :         //close the list
    1981          51 :         if (ent) ent->nextChunk = 0;
    1982             : 
    1983             : 
    1984             :         //done, remove our previous tables
    1985          51 :         gf_list_del_item(stbl->child_boxes, stbl->ChunkOffset);
    1986          51 :         gf_list_del_item(stbl->child_boxes, stbl->SampleToChunk);
    1987          51 :         gf_isom_box_del(stbl->ChunkOffset);
    1988          51 :         gf_isom_box_del((GF_Box *)stbl->SampleToChunk);
    1989             :         //and set these ones...
    1990          51 :         if (stco_tmp) {
    1991          51 :                 stbl->ChunkOffset = (GF_Box *)stco_tmp;
    1992             :         } else {
    1993           0 :                 stbl->ChunkOffset = (GF_Box *)co64_tmp;
    1994             :         }
    1995          51 :         stbl->SampleToChunk = stsc_tmp;
    1996          51 :         gf_list_add(stbl->child_boxes, stbl->ChunkOffset);
    1997          51 :         gf_list_add(stbl->child_boxes, stbl->SampleToChunk);
    1998             : 
    1999          51 :         stbl->SampleToChunk->currentIndex = 0;
    2000          51 :         stbl->SampleToChunk->currentChunk = 0;
    2001          51 :         stbl->SampleToChunk->firstSampleInCurrentChunk = 0;
    2002          51 :         return GF_OK;
    2003             : 
    2004           0 : err_exit:
    2005           0 :         if (stco_tmp) gf_isom_box_del((GF_Box *) stco_tmp);
    2006           0 :         if (co64_tmp) gf_isom_box_del((GF_Box *) co64_tmp);
    2007           0 :         if (stsc_tmp) gf_isom_box_del((GF_Box *) stsc_tmp);
    2008           0 :         return e;
    2009             : }
    2010             : 
    2011             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2012             : 
    2013       63897 : static GFINLINE GF_Err stbl_AddOffset(GF_SampleTableBox *stbl, GF_Box **old_stco, u64 offset)
    2014             : {
    2015             :         GF_ChunkOffsetBox *stco;
    2016             :         GF_ChunkLargeOffsetBox *co64;
    2017             :         u32 i;
    2018             : 
    2019       63897 :         if ((*old_stco)->type == GF_ISOM_BOX_TYPE_STCO) {
    2020             :                 stco = (GF_ChunkOffsetBox *) *old_stco;
    2021             :                 //if dataOffset is bigger than 0xFFFFFFFF, move to LARGE offset
    2022       63897 :                 if (offset > 0xFFFFFFFF) {
    2023           0 :                         s32 prev_pos = gf_list_find(stbl->child_boxes, *old_stco);
    2024           0 :                         co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);
    2025           0 :                         if (!co64) return GF_OUT_OF_MEM;
    2026           0 :                         co64->nb_entries = stco->nb_entries + 1;
    2027           0 :                         co64->alloc_size = co64->nb_entries;
    2028           0 :                         co64->offsets = (u64*)gf_malloc(co64->nb_entries * sizeof(u64));
    2029           0 :                         if (!co64->offsets) {
    2030           0 :                                 gf_isom_box_del((GF_Box *)co64);
    2031           0 :                                 return GF_OUT_OF_MEM;
    2032             :                         }
    2033           0 :                         for (i = 0; i< co64->nb_entries - 1; i++) {
    2034           0 :                                 co64->offsets[i] = (u64) stco->offsets[i];
    2035             :                         }
    2036           0 :                         co64->offsets[i] = offset;
    2037             :                         //delete the box...
    2038           0 :                         gf_isom_box_del_parent(&stbl->child_boxes, *old_stco);
    2039           0 :                         *old_stco = (GF_Box *)co64;
    2040             : 
    2041             :                         assert (stbl->child_boxes);
    2042             :                         //register new box only if old one was registered
    2043           0 :                         if (prev_pos>=0)
    2044           0 :                                 gf_list_insert(stbl->child_boxes, *old_stco, prev_pos);
    2045             :                         return GF_OK;
    2046             :                 }
    2047             :                 //OK, stick with regular...
    2048       63897 :                 if (stco->nb_entries==stco->alloc_size) {
    2049        1634 :                         ALLOC_INC(stco->alloc_size);
    2050        1634 :                         stco->offsets = (u32*)gf_realloc(stco->offsets, stco->alloc_size * sizeof(u32));
    2051        1634 :                         if (!stco->offsets) return GF_OUT_OF_MEM;
    2052        1634 :                         memset(&stco->offsets[stco->nb_entries], 0, (stco->alloc_size - stco->nb_entries) * sizeof(u32));
    2053             :                 }
    2054             : 
    2055       63897 :                 stco->offsets[stco->nb_entries] = (u32) offset;
    2056       63897 :                 stco->nb_entries += 1;
    2057             :         } else {
    2058             :                 //this is a large offset
    2059             :                 co64 = (GF_ChunkLargeOffsetBox *) *old_stco;
    2060           0 :                 if (co64->nb_entries==co64->alloc_size) {
    2061           0 :                         ALLOC_INC(co64->alloc_size);
    2062           0 :                         co64->offsets = (u64*)gf_realloc(co64->offsets, co64->alloc_size * sizeof(u64));
    2063           0 :                         if (!co64->offsets) return GF_OUT_OF_MEM;
    2064           0 :                         memset(&co64->offsets[co64->nb_entries], 0, (co64->alloc_size - co64->nb_entries) * sizeof(u64) );
    2065             :                 }
    2066           0 :                 co64->offsets[co64->nb_entries] = offset;
    2067           0 :                 co64->nb_entries += 1;
    2068             :         }
    2069             :         return GF_OK;
    2070             : }
    2071             : 
    2072             : //This function packs the offset after easy editing, eg samples
    2073             : //are re-arranged in chunks according to the chunkOffsets
    2074             : //NOTE: this has to be called once interleaving or whatever is done and
    2075             : //the final MDAT is written!!!
    2076     1038476 : GF_Err stbl_SetChunkAndOffset(GF_SampleTableBox *stbl, u32 sampleNumber, u32 StreamDescIndex, GF_SampleToChunkBox *the_stsc, GF_Box **the_stco, u64 data_offset, Bool forceNewChunk, u32 nb_samp)
    2077             : {
    2078             :         GF_Err e;
    2079             :         u8 newChunk;
    2080             :         GF_StscEntry *newEnt, *cur_ent;
    2081             : 
    2082     1038476 :         if (!stbl) return GF_ISOM_INVALID_FILE;
    2083             : 
    2084             :         newChunk = 0;
    2085             :         //do we need a new chunk ??? For that, we need
    2086             :         //1 - make sure this sample data is contiguous to the prev one
    2087             : 
    2088             :         //force new chunk is set during writing (flat / interleaved)
    2089             :         //it is set to 1 when data is not contiguous in the media (eg, interleaving)
    2090             :         //when writing flat files, it is never used
    2091     1038476 :         if (forceNewChunk) newChunk = 1;
    2092             : 
    2093             :         cur_ent = NULL;
    2094             :         //2 - make sure we have the table inited (i=0)
    2095     1038476 :         if (! the_stsc->entries) {
    2096             :                 newChunk = 1;
    2097             :         } else {
    2098     1037071 :                 cur_ent = &the_stsc->entries[the_stsc->nb_entries - 1];
    2099             :                 //3 - make sure we do not exceed the MaxSamplesPerChunk and we have the same descIndex
    2100     1037071 :                 if (StreamDescIndex != cur_ent->sampleDescriptionIndex)
    2101             :                         newChunk = 1;
    2102     1037071 :                 if (stbl->MaxSamplePerChunk && cur_ent->samplesPerChunk >= stbl->MaxSamplePerChunk)
    2103             :                         newChunk = 1;
    2104             :         }
    2105             : 
    2106             :         //no need for a new chunk
    2107     1036822 :         if (!newChunk) {
    2108      974579 :                 cur_ent->samplesPerChunk += nb_samp;
    2109      974579 :                 return GF_OK;
    2110             :         }
    2111             : 
    2112             :         //OK, we have to create a new chunk...
    2113             :         //check if we can remove the current sampleToChunk entry (same properties)
    2114       63897 :         if (the_stsc->nb_entries > 1) {
    2115       61395 :                 GF_StscEntry *ent = &the_stsc->entries[the_stsc->nb_entries - 2];
    2116       61395 :                 if (!ent) return GF_OUT_OF_MEM;
    2117       61395 :                 if ( (ent->sampleDescriptionIndex == cur_ent->sampleDescriptionIndex)
    2118       61385 :                         && (ent->samplesPerChunk == cur_ent->samplesPerChunk)
    2119             :                    ) {
    2120             :                         //OK, it's the same SampleToChunk, so delete it
    2121       58903 :                         ent->nextChunk = cur_ent->firstChunk;
    2122       58903 :                         the_stsc->nb_entries--;
    2123             :                 }
    2124             :         }
    2125             : 
    2126             :         //add our offset
    2127       63897 :         e = stbl_AddOffset(stbl, the_stco, data_offset);
    2128       63897 :         if (e) return e;
    2129             : 
    2130       63897 :         if (the_stsc->nb_entries==the_stsc->alloc_size) {
    2131        1409 :                 ALLOC_INC(the_stsc->alloc_size);
    2132        1409 :                 the_stsc->entries = gf_realloc(the_stsc->entries, sizeof(GF_StscEntry)*the_stsc->alloc_size);
    2133        1409 :                 if (!the_stsc->entries) return GF_OUT_OF_MEM;
    2134        1409 :                 memset(&the_stsc->entries[the_stsc->nb_entries], 0, sizeof(GF_StscEntry)*(the_stsc->alloc_size-the_stsc->nb_entries));
    2135             :         }
    2136             :         //create a new entry (could be the first one, BTW)
    2137       63897 :         newEnt = &the_stsc->entries[the_stsc->nb_entries];
    2138       63897 :         if (!newEnt) return GF_OUT_OF_MEM;
    2139             : 
    2140             :         //get the first chunk value
    2141       63897 :         if ((*the_stco)->type == GF_ISOM_BOX_TYPE_STCO) {
    2142       63897 :                 newEnt->firstChunk = ((GF_ChunkOffsetBox *) (*the_stco) )->nb_entries;
    2143             :         } else {
    2144           0 :                 newEnt->firstChunk = ((GF_ChunkLargeOffsetBox *) (*the_stco) )->nb_entries;
    2145             :         }
    2146       63897 :         newEnt->sampleDescriptionIndex = StreamDescIndex;
    2147       63897 :         newEnt->samplesPerChunk = nb_samp;
    2148       63897 :         newEnt->nextChunk = 0;
    2149             :         //if we already have an entry, adjust its next chunk to point to our new chunk
    2150       63897 :         if (the_stsc->nb_entries)
    2151       62492 :                 the_stsc->entries[the_stsc->nb_entries-1].nextChunk = newEnt->firstChunk;
    2152       63897 :         the_stsc->nb_entries++;
    2153       63897 :         return GF_OK;
    2154             : }
    2155             : 
    2156             : GF_EXPORT
    2157           0 : GF_Err gf_isom_refresh_size_info(GF_ISOFile *file, u32 trackNumber)
    2158             : {
    2159             :         u32 i, size;
    2160             :         GF_TrackBox *trak;
    2161             :         GF_SampleSizeBox *stsz;
    2162           0 :         trak = gf_isom_get_track_from_file(file, trackNumber);
    2163           0 :         if (!trak) return GF_BAD_PARAM;
    2164             : 
    2165           0 :         stsz = trak->Media->information->sampleTable->SampleSize;
    2166           0 :         if (stsz->sampleSize || !stsz->sampleCount) return GF_OK;
    2167             : 
    2168           0 :         size = stsz->sizes[0];
    2169           0 :         for (i=1; i<stsz->sampleCount; i++) {
    2170           0 :                 if (stsz->sizes[i] != size) {
    2171             :                         size = 0;
    2172             :                         break;
    2173             :                 }
    2174             :         }
    2175           0 :         if (size) {
    2176           0 :                 gf_free(stsz->sizes);
    2177           0 :                 stsz->sizes = NULL;
    2178           0 :                 stsz->sampleSize = size;
    2179             :         }
    2180             :         return GF_OK;
    2181             : }
    2182             : 
    2183             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    2184             : 
    2185             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13