LCOV - code coverage report
Current view: top level - isomedia - stbl_read.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 192 258 74.4 %
Date: 2021-04-29 23:48:07 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISO Media File Format sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/isomedia_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_ISOM
      29             : 
      30             : //Get the sample number
      31         441 : GF_Err stbl_findEntryForTime(GF_SampleTableBox *stbl, u64 DTS, u8 useCTS, u32 *sampleNumber, u32 *prevSampleNumber)
      32             : {
      33             :         u32 i, j, curSampNum, count;
      34             :         s32 CTSOffset;
      35             :         u64 curDTS;
      36             :         GF_SttsEntry *ent;
      37         441 :         (*sampleNumber) = 0;
      38         441 :         (*prevSampleNumber) = 0;
      39             : 
      40         441 :         if (!stbl->TimeToSample) return GF_ISOM_INVALID_FILE;
      41             : 
      42             :         /*CTS is ALWAYS disabled for now to make sure samples are fetched in decoding order. useCTS is therefore disabled*/
      43             : #if 0
      44             :         if (!stbl->CompositionOffset) useCTS = 0;
      45             : #endif
      46             : 
      47             :         //our cache
      48         737 :         if (stbl->TimeToSample->r_FirstSampleInEntry &&
      49         296 :                 (DTS >= stbl->TimeToSample->r_CurrentDTS) ) {
      50             :                 //if we're using CTS, we don't really know whether we're in the good entry or not
      51             :                 //(eg, the real DTS of the sample could be in a previous entry
      52         286 :                 i = stbl->TimeToSample->r_currentEntryIndex;
      53             :                 curDTS = stbl->TimeToSample->r_CurrentDTS;
      54         286 :                 curSampNum = stbl->TimeToSample->r_FirstSampleInEntry;
      55             :         } else {
      56             :                 i = 0;
      57         155 :                 curDTS = stbl->TimeToSample->r_CurrentDTS = 0;
      58         155 :                 curSampNum = stbl->TimeToSample->r_FirstSampleInEntry = 1;
      59         155 :                 stbl->TimeToSample->r_currentEntryIndex = 0;
      60             :         }
      61             : 
      62             : #if 0
      63             :         //we need to validate our cache if we are using CTS because of B-frames and co...
      64             :         if (i && useCTS) {
      65             :                 while (1) {
      66             :                         stbl_GetSampleCTS(stbl->CompositionOffset, curSampNum, &CTSOffset);
      67             :                         //we're too far, rewind
      68             :                         if ( i && (curDTS + CTSOffset > DTS) ) {
      69             :                                 ent = &stbl->TimeToSample->entries[i];
      70             :                                 curSampNum -= ent->sampleCount;
      71             :                                 curDTS -= (u64)ent->sampleDelta * ent->sampleCount;
      72             :                                 i --;
      73             :                         } else if (!i) {
      74             :                                 //beginning of the table, no choice
      75             :                                 curDTS = stbl->TimeToSample->r_CurrentDTS = 0;
      76             :                                 curSampNum = stbl->TimeToSample->r_FirstSampleInEntry = 1;
      77             :                                 stbl->TimeToSample->r_currentEntryIndex = 0;
      78             :                                 break;
      79             :                         } else {
      80             :                                 //OK now we're good
      81             :                                 break;
      82             :                         }
      83             :                 }
      84             :         }
      85             : #endif
      86             : 
      87             :         //look for the DTS from this entry
      88         441 :         count = stbl->TimeToSample->nb_entries;
      89         471 :         for (; i<count; i++) {
      90         392 :                 ent = &stbl->TimeToSample->entries[i];
      91             : #if 0
      92             :                 if (useCTS) {
      93             :                         stbl_GetSampleCTS(stbl->CompositionOffset, curSampNum, &CTSOffset);
      94             :                 } else
      95             : #endif
      96             :                 {
      97             :                         CTSOffset = 0;
      98             :                 }
      99        8329 :                 for (j=0; j<ent->sampleCount; j++) {
     100        8299 :                         if (curDTS + CTSOffset >= DTS) goto entry_found;
     101        7937 :                         curSampNum += 1;
     102        7937 :                         curDTS += ent->sampleDelta;
     103             :                 }
     104             :                 //we're switching to the next entry, update the cache!
     105          30 :                 stbl->TimeToSample->r_CurrentDTS += (u64)ent->sampleCount * ent->sampleDelta;
     106          30 :                 stbl->TimeToSample->r_currentEntryIndex += 1;
     107          30 :                 stbl->TimeToSample->r_FirstSampleInEntry += ent->sampleCount;
     108             :         }
     109             :         //return as is
     110             :         return GF_OK;
     111             : 
     112         362 : entry_found:
     113             :         //do we have the exact time ?
     114         362 :         if (curDTS + CTSOffset == DTS) {
     115         278 :                 (*sampleNumber) = curSampNum;
     116             :         }
     117             :         //if we match the exact DTS also select this sample
     118             :         else if (curDTS == DTS) {
     119             :                 (*sampleNumber) = curSampNum;
     120             :         } else {
     121             :                 //exception for the first sample (we need to "load" the playback)
     122          84 :                 if (curSampNum != 1) {
     123          84 :                         (*prevSampleNumber) = curSampNum - 1;
     124             :                 } else {
     125           0 :                         (*prevSampleNumber) = 1;
     126             :                 }
     127             :         }
     128             :         return GF_OK;
     129             : }
     130             : 
     131             : //Get the Size of a given sample
     132     3886024 : GF_Err stbl_GetSampleSize(GF_SampleSizeBox *stsz, u32 SampleNumber, u32 *Size)
     133             : {
     134     3886024 :         if (!stsz || !SampleNumber || (SampleNumber > stsz->sampleCount))
     135             :                 return GF_BAD_PARAM;
     136             : 
     137     3886024 :         if (stsz->sampleSize && (stsz->type != GF_ISOM_BOX_TYPE_STZ2)) {
     138     1121139 :                 (*Size) = stsz->sampleSize;
     139     2764885 :         } else if (stsz->sizes) {
     140     2764885 :                 (*Size) = stsz->sizes[SampleNumber - 1];
     141             :         } else {
     142           0 :                 (*Size) = 0;
     143             :         }
     144             :         return GF_OK;
     145             : }
     146             : 
     147             : 
     148             : 
     149             : //Get the CTS offset of a given sample
     150      436672 : GF_Err stbl_GetSampleCTS(GF_CompositionOffsetBox *ctts, u32 SampleNumber, s32 *CTSoffset)
     151             : {
     152             :         u32 i;
     153             : 
     154      436672 :         (*CTSoffset) = 0;
     155             :         //test on SampleNumber is done before
     156      436672 :         if (!ctts || !SampleNumber) return GF_BAD_PARAM;
     157             : 
     158      436672 :         if (ctts->r_FirstSampleInEntry && (ctts->r_FirstSampleInEntry < SampleNumber) ) {
     159      431400 :                 i = ctts->r_currentEntryIndex;
     160             :         } else {
     161        5272 :                 ctts->r_FirstSampleInEntry = 1;
     162        5272 :                 ctts->r_currentEntryIndex = 0;
     163             :                 i = 0;
     164             :         }
     165      393963 :         for (; i< ctts->nb_entries; i++) {
     166      826783 :                 if (SampleNumber < ctts->r_FirstSampleInEntry + ctts->entries[i].sampleCount) break;
     167             :                 //update our cache
     168      393963 :                 ctts->r_currentEntryIndex += 1;
     169      393963 :                 ctts->r_FirstSampleInEntry += ctts->entries[i].sampleCount;
     170             :         }
     171             :         //no ent, set everything to 0...
     172      436672 :         if (i==ctts->nb_entries) return GF_OK;
     173             :         /*asked for a sample not in table - this means CTTS is 0 (that's due to out internal packing construction of CTTS)*/
     174      432820 :         if (SampleNumber >= ctts->r_FirstSampleInEntry + ctts->entries[i].sampleCount) return GF_OK;
     175      432820 :         (*CTSoffset) = ctts->entries[i].decodingOffset;
     176      432820 :         return GF_OK;
     177             : }
     178             : 
     179             : //Get the DTS of a sample
     180     4376569 : GF_Err stbl_GetSampleDTS_and_Duration(GF_TimeToSampleBox *stts, u32 SampleNumber, u64 *DTS, u32 *duration)
     181             : {
     182             :         u32 i, j, count;
     183             :         GF_SttsEntry *ent;
     184             : 
     185     4376569 :         (*DTS) = 0;
     186     4376569 :         if (duration) {
     187     2674138 :                 *duration = 0;
     188             :         }
     189     4376569 :         if (!stts || !SampleNumber) return GF_BAD_PARAM;
     190             : 
     191             :         ent = NULL;
     192             :         //use our cache
     193     4362484 :         count = stts->nb_entries;
     194     4362484 :         if (stts->r_FirstSampleInEntry
     195     3800454 :                 && (stts->r_FirstSampleInEntry <= SampleNumber)
     196             :                 //this is for read/write access
     197     3799710 :                 && (stts->r_currentEntryIndex < count) ) {
     198             : 
     199             :                 i = stts->r_currentEntryIndex;
     200             :         } else {
     201      562841 :                 i = stts->r_currentEntryIndex = 0;
     202      562841 :                 stts->r_FirstSampleInEntry = 1;
     203      562841 :                 stts->r_CurrentDTS = 0;
     204             :         }
     205             : 
     206     5523627 :         for (; i < count; i++) {
     207     9885977 :                 ent = &stts->entries[i];
     208             : 
     209             :                 //in our entry
     210     9885977 :                 if (ent->sampleCount + stts->r_FirstSampleInEntry >= 1 + SampleNumber) {
     211     4362350 :                         j = SampleNumber - stts->r_FirstSampleInEntry;
     212             :                         goto found;
     213             :                 }
     214             : 
     215             :                 //update our cache
     216     5523627 :                 stts->r_CurrentDTS += (u64)ent->sampleCount * ent->sampleDelta;
     217     5523627 :                 stts->r_currentEntryIndex += 1;
     218     5523627 :                 stts->r_FirstSampleInEntry += ent->sampleCount;
     219             :         }
     220             : //      if (SampleNumber >= stts->r_FirstSampleInEntry + ent->sampleCount) return GF_BAD_PARAM;
     221             : 
     222             :         //no ent, this is really weird. Let's assume the DTS is then what is written in the table
     223         134 :         if (!ent || (i == count)) {
     224         134 :                 (*DTS) = stts->r_CurrentDTS;
     225         134 :                 if (duration) *duration = ent ? ent->sampleDelta : 0;
     226             :         }
     227             :         return GF_OK;
     228             : 
     229             : found:
     230     4362350 :         (*DTS) = stts->r_CurrentDTS + j * (u64) ent->sampleDelta;
     231     7022269 :         if (duration) *duration = ent->sampleDelta;
     232             :         return GF_OK;
     233             : }
     234             : 
     235     1702431 : GF_Err stbl_GetSampleDTS(GF_TimeToSampleBox *stts, u32 SampleNumber, u64 *DTS)
     236             : {
     237     1702431 :         return stbl_GetSampleDTS_and_Duration(stts, SampleNumber, DTS, NULL);
     238             : }
     239             : //Retrieve closes RAP for a given sample - if sample is RAP, sets the RAP flag
     240      743736 : GF_Err stbl_GetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, GF_ISOSAPType *IsRAP, u32 *prevRAP, u32 *nextRAP)
     241             : {
     242             :         u32 i;
     243      743736 :         if (prevRAP) *prevRAP = 0;
     244      743736 :         if (nextRAP) *nextRAP = 0;
     245             : 
     246      743736 :         (*IsRAP) = RAP_NO;
     247      743736 :         if (!stss || !SampleNumber) return GF_BAD_PARAM;
     248             : 
     249      743736 :         if (stss->r_LastSyncSample && (stss->r_LastSyncSample < SampleNumber) ) {
     250      732485 :                 i = stss->r_LastSampleIndex;
     251             :         } else {
     252             :                 i = 0;
     253             :         }
     254      765133 :         for (; i < stss->nb_entries; i++) {
     255             :                 //get the entry
     256     1377655 :                 if (stss->sampleNumbers[i] == SampleNumber) {
     257             :                         //update the cache
     258       28213 :                         stss->r_LastSyncSample = SampleNumber;
     259       28213 :                         stss->r_LastSampleIndex = i;
     260       28213 :                         (*IsRAP) = RAP;
     261             :                 }
     262     1349442 :                 else if (stss->sampleNumbers[i] > SampleNumber) {
     263      612522 :                         if (nextRAP) *nextRAP = stss->sampleNumbers[i];
     264             :                         return GF_OK;
     265             :                 }
     266      765133 :                 if (prevRAP) *prevRAP = stss->sampleNumbers[i];
     267             :         }
     268             :         return GF_OK;
     269             : }
     270             : 
     271          57 : GF_Err stbl_SearchSAPs(GF_SampleTableBox *stbl, u32 SampleNumber, GF_ISOSAPType *IsRAP, u32 *prevRAP, u32 *nextRAP)
     272             : {
     273             :         u32 i, j, count, count2;
     274             :         assert(prevRAP);
     275             :         assert(nextRAP);
     276          57 :         (*prevRAP) = 0;
     277          57 :         (*nextRAP) = 0;
     278          57 :         (*IsRAP) = RAP_NO;
     279             : 
     280          57 :         if (!stbl->sampleGroups || !stbl->sampleGroupsDescription) return GF_OK;
     281             : 
     282           1 :         count = gf_list_count(stbl->sampleGroups);
     283           1 :         count2 = gf_list_count(stbl->sampleGroupsDescription);
     284           2 :         for (i=0; i<count; i++) {
     285             :                 GF_SampleGroupDescriptionBox *sgdp = NULL;
     286             :                 Bool is_rap_group = 0;
     287             :                 s32 roll_distance = 0;
     288             :                 u32 first_sample_in_entry, last_sample_in_entry;
     289           1 :                 GF_SampleGroupBox *sg = gf_list_get(stbl->sampleGroups, i);
     290           1 :                 switch (sg->grouping_type) {
     291           0 :                 case GF_ISOM_SAMPLE_GROUP_RAP:
     292             :                 case GF_ISOM_SAMPLE_GROUP_SYNC:
     293             :                         is_rap_group = 1;
     294           0 :                         break;
     295             :                 case GF_ISOM_SAMPLE_GROUP_ROLL:
     296             :                         break;
     297           1 :                 default:
     298           1 :                         continue;
     299             :                 }
     300           0 :                 for (j=0; j<count2; j++) {
     301           0 :                         sgdp = gf_list_get(stbl->sampleGroupsDescription, j);
     302           0 :                         if (sgdp->grouping_type==sg->grouping_type) break;
     303             :                         sgdp = NULL;
     304             :                 }
     305           0 :                 if (! sgdp) continue;
     306             : 
     307             :                 first_sample_in_entry=1;
     308           0 :                 for (j=0; j<sg->entry_count; j++) {
     309             :                         u32 first_rap_in_entry, last_rap_in_entry;
     310           0 :                         last_sample_in_entry = first_sample_in_entry + sg->sample_entries[j].sample_count - 1;
     311             : 
     312             :                         /*samples in this entry are not RAPs, continue*/
     313           0 :                         if (! sg->sample_entries[j].group_description_index) {
     314             :                                 first_sample_in_entry += sg->sample_entries[j].sample_count;
     315           0 :                                 continue;
     316             :                         }
     317           0 :                         if (!is_rap_group) {
     318           0 :                                 GF_RollRecoveryEntry *entry = gf_list_get(sgdp->group_descriptions, sg->sample_entries[j].group_description_index - 1);
     319           0 :                                 roll_distance = entry ? entry->roll_distance : 0;
     320             :                         }
     321             : 
     322             :                         /*we consider the first sample in a roll or rap group entry to be the RAP (eg, we have to decode from this sample anyway)
     323             :                         except if roll_distance is strictly negative in which case we have to rewind our sample numbers from roll_distance*/
     324           0 :                         if (roll_distance < 0) {
     325           0 :                                 if ((s32) first_sample_in_entry + roll_distance>=0) first_rap_in_entry = first_sample_in_entry + roll_distance;
     326             :                                 else first_rap_in_entry = 0;
     327             : 
     328           0 :                                 if ((s32) last_sample_in_entry + roll_distance>=0) last_rap_in_entry = last_sample_in_entry + roll_distance;
     329             :                                 else last_rap_in_entry = 0;
     330             :                         } else {
     331             :                                 first_rap_in_entry = first_sample_in_entry;
     332             :                                 last_rap_in_entry = last_sample_in_entry;
     333             :                         }
     334             : 
     335             :                         /*store previous & next sample RAP - note that we do not store the closest previous RAP, only the first of the previous RAP group
     336             :                         as RAPs are usually isolated this should not be an issue*/
     337           0 :                         if (first_rap_in_entry <= SampleNumber) {
     338           0 :                                 *prevRAP = first_rap_in_entry;
     339             :                         }
     340           0 :                         *nextRAP = last_rap_in_entry;
     341             :                         
     342             :                         /*sample lies in this (rap) group, it is rap*/
     343           0 :                         if (is_rap_group) {
     344           0 :                                 if ((first_rap_in_entry <= SampleNumber) && (SampleNumber <= last_rap_in_entry)) {
     345           0 :                                         (*IsRAP) = RAP;
     346           0 :                                         return GF_OK;
     347             :                                 }
     348             :                         } else {
     349             :                                 /*prevRAP or nextRAP matches SampleNumber, sample is RAP*/
     350           0 :                                 if ((*prevRAP == SampleNumber) || (*nextRAP == SampleNumber)) {
     351           0 :                                         (*IsRAP) = RAP;
     352           0 :                                         return GF_OK;
     353             :                                 }
     354             :                         }
     355             : 
     356             :                         /*first sample in entry is after our target sample, abort*/
     357           0 :                         if (first_rap_in_entry > SampleNumber) {
     358             :                                 break;
     359             :                         }
     360           0 :                         first_sample_in_entry += sg->sample_entries[j].sample_count;
     361             :                 }
     362             :         }
     363             :         return GF_OK;
     364             : }
     365             : 
     366             : //get the number of "ghost chunk" (implicit chunks described by an entry)
     367     1933354 : void GetGhostNum(GF_StscEntry *ent, u32 EntryIndex, u32 count, GF_SampleTableBox *stbl)
     368             : {
     369             :         GF_StscEntry *nextEnt;
     370             :         u32 ghostNum = 1;
     371             : 
     372     1933354 :         if (!ent) {
     373           0 :                 stbl->SampleToChunk->ghostNumber = 0;
     374           0 :                 return;
     375             :         }
     376             : 
     377     1933354 :         if (!ent->nextChunk) {
     378      129254 :                 if (EntryIndex+1 == count) {
     379             :                         //not specified in the spec, what if the last sample to chunk is no written?
     380      129254 :                         if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
     381             :                                 GF_ChunkOffsetBox *stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
     382      129254 :                                 ghostNum = (stco->nb_entries > ent->firstChunk) ? (1 + stco->nb_entries - ent->firstChunk) : 1;
     383             :                         } else {
     384             :                                 GF_ChunkLargeOffsetBox *co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
     385           0 :                                 ghostNum = (co64->nb_entries > ent->firstChunk) ? (1 + co64->nb_entries - ent->firstChunk) : 1;
     386             :                         }
     387             :                 } else {
     388             :                         //this is an unknown case due to edit mode...
     389           0 :                         nextEnt = &stbl->SampleToChunk->entries[EntryIndex+1];
     390           0 :                         ghostNum = nextEnt->firstChunk - ent->firstChunk;
     391             :                 }
     392             :         } else {
     393     1804100 :                 ghostNum = (ent->nextChunk > ent->firstChunk) ? (ent->nextChunk - ent->firstChunk) : 1;
     394             :         }
     395     1933354 :         stbl->SampleToChunk->ghostNumber = ghostNum;
     396             : }
     397             : 
     398             : //Get the offset, descIndex and chunkNumber of a sample...
     399     3324005 : GF_Err stbl_GetSampleInfos(GF_SampleTableBox *stbl, u32 sampleNumber, u64 *offset, u32 *chunkNumber, u32 *descIndex, GF_StscEntry **out_ent)
     400             : {
     401             :         GF_Err e;
     402             :         u32 i, k, offsetInChunk, size, chunk_num;
     403             :         GF_ChunkOffsetBox *stco;
     404             :         GF_ChunkLargeOffsetBox *co64;
     405             :         GF_StscEntry *ent;
     406             : 
     407     3324005 :         (*offset) = 0;
     408     3324005 :         (*chunkNumber) = (*descIndex) = 0;
     409     3324005 :         if (out_ent) (*out_ent) = NULL;
     410     3324005 :         if (!stbl || !sampleNumber) return GF_BAD_PARAM;
     411     3324004 :         if (!stbl->ChunkOffset || !stbl->SampleToChunk || !stbl->SampleSize) return GF_ISOM_INVALID_FILE;
     412             : 
     413     3324004 :         if (stbl->SampleSize && stbl->SampleToChunk->nb_entries == stbl->SampleSize->sampleCount) {
     414     1477230 :                 ent = &stbl->SampleToChunk->entries[sampleNumber-1];
     415     1477230 :                 if (!ent) return GF_BAD_PARAM;
     416     1477230 :                 (*descIndex) = ent->sampleDescriptionIndex;
     417     1477230 :                 (*chunkNumber) = sampleNumber;
     418     1477230 :                 if (out_ent) *out_ent = ent;
     419     1477230 :                 if ( stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
     420             :                         stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
     421     1477230 :                         if (!stco->offsets) return GF_ISOM_INVALID_FILE;
     422     1477230 :                         if (stco->nb_entries < sampleNumber) return GF_ISOM_INVALID_FILE;
     423             : 
     424     1477230 :                         (*offset) = (u64) stco->offsets[sampleNumber - 1];
     425             :                 } else {
     426             :                         co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
     427           0 :                         if (!co64->offsets) return GF_ISOM_INVALID_FILE;
     428           0 :                         if (co64->nb_entries < sampleNumber) return GF_ISOM_INVALID_FILE;
     429             : 
     430           0 :                         (*offset) = co64->offsets[sampleNumber - 1];
     431             :                 }
     432             :                 return GF_OK;
     433             :         }
     434             : 
     435             :         //check our cache: if desired sample is at or above current cache entry, start from here
     436     1846774 :         if (stbl->SampleToChunk->firstSampleInCurrentChunk &&
     437             :                 (stbl->SampleToChunk->firstSampleInCurrentChunk <= sampleNumber)) {
     438             : 
     439     1841954 :                 i = stbl->SampleToChunk->currentIndex;
     440     1841954 :                 ent = &stbl->SampleToChunk->entries[stbl->SampleToChunk->currentIndex];
     441     1841954 :                 GetGhostNum(ent, i, stbl->SampleToChunk->nb_entries, stbl);
     442     1841954 :                 k = stbl->SampleToChunk->currentChunk;
     443             :         }
     444             :         //otherwise start from first entry
     445             :         else {
     446             :                 i = 0;
     447        4820 :                 stbl->SampleToChunk->currentIndex = 0;
     448        4820 :                 stbl->SampleToChunk->currentChunk = 1;
     449        4820 :                 stbl->SampleToChunk->ghostNumber = 1;
     450        4820 :                 stbl->SampleToChunk->firstSampleInCurrentChunk = 1;
     451        4820 :                 ent = &stbl->SampleToChunk->entries[0];
     452        4820 :                 GetGhostNum(ent, 0, stbl->SampleToChunk->nb_entries, stbl);
     453        4820 :                 k = stbl->SampleToChunk->currentChunk;
     454             :         }
     455             : 
     456             :         //first get the chunk
     457     1933358 :         for (; i < stbl->SampleToChunk->nb_entries; i++) {
     458             :                 assert(stbl->SampleToChunk->firstSampleInCurrentChunk <= sampleNumber);
     459             :                 //corrupted file (less sample2chunk info than sample count
     460     1933354 :                 if (k > stbl->SampleToChunk->ghostNumber) {
     461             :                         return GF_ISOM_INVALID_FILE;
     462             :                 }
     463             : 
     464             : 
     465             :                 //check if sample is in current chunk
     466     1933354 :                 u32 max_chunks_in_entry = stbl->SampleToChunk->ghostNumber - k;
     467     1933354 :                 u32 nb_chunks_for_sample = sampleNumber - stbl->SampleToChunk->firstSampleInCurrentChunk;
     468     1933354 :                 if (ent->samplesPerChunk) 
     469     1933354 :                         nb_chunks_for_sample /= ent->samplesPerChunk;
     470             : 
     471     1933354 :                 if (
     472             :                         (nb_chunks_for_sample <= max_chunks_in_entry)
     473     1846770 :                         && (stbl->SampleToChunk->firstSampleInCurrentChunk + (nb_chunks_for_sample+1) * ent->samplesPerChunk > sampleNumber)
     474             :                 ) {
     475             : 
     476     1846770 :                         stbl->SampleToChunk->firstSampleInCurrentChunk += nb_chunks_for_sample * ent->samplesPerChunk;
     477     1846770 :                         stbl->SampleToChunk->currentChunk += nb_chunks_for_sample;
     478             :                         goto sample_found;
     479             :                 }
     480       86584 :                 max_chunks_in_entry += 1;
     481       86584 :                 stbl->SampleToChunk->firstSampleInCurrentChunk += max_chunks_in_entry * ent->samplesPerChunk;
     482       86584 :                 stbl->SampleToChunk->currentChunk += max_chunks_in_entry;
     483             : 
     484             :                 //not in this entry, get the next entry if not the last one
     485       86584 :                 if (i+1 != stbl->SampleToChunk->nb_entries) {
     486       86580 :                         ent = &stbl->SampleToChunk->entries[i+1];
     487             :                         //update the GhostNumber
     488       86580 :                         GetGhostNum(ent, i+1, stbl->SampleToChunk->nb_entries, stbl);
     489             :                         //update the entry in our cache
     490       86580 :                         stbl->SampleToChunk->currentIndex = i+1;
     491       86580 :                         stbl->SampleToChunk->currentChunk = 1;
     492             :                         k = 1;
     493             :                 }
     494             :         }
     495             :         //if we get here, gasp, the sample was not found
     496             :         return GF_ISOM_INVALID_FILE;
     497             : 
     498             : sample_found:
     499             : 
     500     1846770 :         (*descIndex) = ent->sampleDescriptionIndex;
     501     1846770 :         (*chunkNumber) = chunk_num = ent->firstChunk + stbl->SampleToChunk->currentChunk - 1;
     502     3548681 :         if (out_ent) *out_ent = ent;
     503     1846770 :         if (! *chunkNumber)
     504             :                 return GF_ISOM_INVALID_FILE;
     505             :         
     506             :         //ok, get the size of all the previous samples in the chunk
     507             :         offsetInChunk = 0;
     508             :         //constant size
     509     2799613 :         if (stbl->SampleSize && stbl->SampleSize->sampleSize) {
     510      952843 :                 u32 diff = sampleNumber - stbl->SampleToChunk->firstSampleInCurrentChunk;
     511      952843 :                 offsetInChunk += diff * stbl->SampleSize->sampleSize;
     512      893927 :         } else if ((stbl->r_last_chunk_num == chunk_num) && (stbl->r_last_sample_num == sampleNumber)) {
     513       40429 :                 offsetInChunk = stbl->r_last_offset_in_chunk;
     514      853498 :         } else if ((stbl->r_last_chunk_num == chunk_num) && (stbl->r_last_sample_num + 1 == sampleNumber)) {
     515      710288 :                 e = stbl_GetSampleSize(stbl->SampleSize, stbl->r_last_sample_num, &size);
     516      710288 :                 if (e) return e;
     517      710288 :                 stbl->r_last_offset_in_chunk += size;
     518      710288 :                 stbl->r_last_sample_num = sampleNumber;
     519      710288 :                 offsetInChunk = stbl->r_last_offset_in_chunk;
     520             :         } else {
     521             :                 //warning, firstSampleInChunk is at least 1 - not 0
     522      143652 :                 for (i = stbl->SampleToChunk->firstSampleInCurrentChunk; i < sampleNumber; i++) {
     523         442 :                         e = stbl_GetSampleSize(stbl->SampleSize, i, &size);
     524         442 :                         if (e) return e;
     525         442 :                         offsetInChunk += size;
     526             :                 }
     527      143210 :                 stbl->r_last_chunk_num = chunk_num;
     528      143210 :                 stbl->r_last_sample_num = sampleNumber;
     529      143210 :                 stbl->r_last_offset_in_chunk = offsetInChunk;
     530             :         }
     531             :         //OK, that's the size of our offset in the chunk
     532             :         //now get the chunk
     533     1846770 :         if ( stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {
     534             :                 stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;
     535     1846770 :                 if (stco->nb_entries < (*chunkNumber) ) return GF_ISOM_INVALID_FILE;
     536     1846770 :                 (*offset) = (u64) stco->offsets[(*chunkNumber) - 1] + (u64) offsetInChunk;
     537             :         } else {
     538             :                 co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;
     539           0 :                 if (co64->nb_entries < (*chunkNumber) ) return GF_ISOM_INVALID_FILE;
     540           0 :                 (*offset) = co64->offsets[(*chunkNumber) - 1] + (u64) offsetInChunk;
     541             :         }
     542             :         return GF_OK;
     543             : }
     544             : 
     545             : 
     546           0 : GF_Err stbl_GetSampleShadow(GF_ShadowSyncBox *stsh, u32 *sampleNumber, u32 *syncNum)
     547             : {
     548             :         u32 i, count;
     549             :         GF_StshEntry *ent;
     550             : 
     551           0 :         if (stsh->r_LastFoundSample && (stsh->r_LastFoundSample <= *sampleNumber)) {
     552           0 :                 i = stsh->r_LastEntryIndex;
     553             :         } else {
     554             :                 i = 0;
     555           0 :                 stsh->r_LastFoundSample = 1;
     556             :         }
     557             : 
     558             :         ent = NULL;
     559           0 :         (*syncNum) = 0;
     560             : 
     561           0 :         count = gf_list_count(stsh->entries);
     562           0 :         for (; i<count; i++) {
     563           0 :                 ent = (GF_StshEntry*)gf_list_get(stsh->entries, i);
     564             :                 //we get the exact desired sample !
     565           0 :                 if (ent->shadowedSampleNumber == *sampleNumber) {
     566           0 :                         (*syncNum) = ent->syncSampleNumber;
     567           0 :                         stsh->r_LastFoundSample = *sampleNumber;
     568           0 :                         stsh->r_LastEntryIndex = i;
     569           0 :                         return GF_OK;
     570           0 :                 } else if (ent->shadowedSampleNumber > *sampleNumber) {
     571             :                         //do we have an entry before ? If not, there is no shadowing available
     572             :                         //for this sample
     573           0 :                         if (!i) return GF_OK;
     574             :                         //ok, indicate the previous ShadowedSample
     575           0 :                         ent = (GF_StshEntry*)gf_list_get(stsh->entries, i-1);
     576           0 :                         (*syncNum) = ent->syncSampleNumber;
     577             :                         //change the sample number
     578           0 :                         (*sampleNumber) = ent->shadowedSampleNumber;
     579             :                         //reset the cache to the last ShadowedSample
     580           0 :                         stsh->r_LastEntryIndex = i-1;
     581           0 :                         stsh->r_LastFoundSample = ent->shadowedSampleNumber;
     582             :                 }
     583             :         }
     584           0 :         stsh->r_LastEntryIndex = i-1;
     585           0 :         stsh->r_LastFoundSample = ent ? ent->shadowedSampleNumber : 0;
     586           0 :         return GF_OK;
     587             : }
     588             : 
     589             : 
     590             : 
     591           1 : GF_Err stbl_GetPaddingBits(GF_PaddingBitsBox *padb, u32 SampleNumber, u8 *PadBits)
     592             : {
     593           1 :         if (!PadBits) return GF_BAD_PARAM;
     594           1 :         *PadBits = 0;
     595           1 :         if (!padb || !padb->padbits) return GF_OK;
     596             :         //the spec says "should" not shall. return 0 padding
     597           0 :         if (padb->SampleCount < SampleNumber) return GF_OK;
     598           0 :         *PadBits = padb->padbits[SampleNumber-1];
     599           0 :         return GF_OK;
     600             : }
     601             : 
     602             : //Set the RAP flag of a sample
     603      231983 : GF_Err stbl_GetSampleDepType(GF_SampleDependencyTypeBox *sdep, u32 SampleNumber, u32 *isLeading, u32 *dependsOn, u32 *dependedOn, u32 *redundant)
     604             : {
     605             :         u8 flag;
     606             : 
     607             :         assert(dependsOn && dependedOn && redundant);
     608      231983 :         *dependsOn = *dependedOn = *redundant = 0;
     609             : 
     610      231983 :         if (SampleNumber > sdep->sampleCount) {
     611             :                 return GF_OK;
     612             :         }
     613      224279 :         flag = sdep->sample_info[SampleNumber-1];
     614      224279 :         *isLeading = (flag >> 6) & 3;
     615      224279 :         *dependsOn = (flag >> 4) & 3;
     616      224279 :         *dependedOn = (flag >> 2) & 3;
     617      224279 :         *redundant = (flag) & 3;
     618      224279 :         return GF_OK;
     619             : }
     620             : 
     621             : 
     622             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13