Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /*********************************************************************************/
     19 /*     -------------------------------------------------------------------       */
     20 /*                         MPEG-4 SampleToChunkAtom Class                        */
     21 /*     -------------------------------------------------------------------       */
     22 /*********************************************************************************/
     23 /*
     24     This SampleSizeAtom Class contains the sample count and a table giving the
     25     size of each sample.
     26 */
     27 
     28 
     29 #define IMPLEMENT_SampleToChunkAtom_H__
     30 
     31 #include "sampletochunkatom.h"
     32 #include "atomutils.h"
     33 #include "atomdefs.h"
     34 
     35 #define DEFAULT_MAX_NUM_SAMPLES_PER_CHUNK                20
     36 #define DEFAULT_MAX_CHUNK_DATA_SIZE                   10240; // 10KB
     37 
     38 // Stream-in ctor
     39 // Create and return a new SampleToChunkAtom by reading in from an ifstream
     40 SampleToChunkAtom::SampleToChunkAtom(MP4_FF_FILE *fp, uint32 size, uint32 type, OSCL_wString& filename, uint32 parsingMode)
     41         : FullAtom(fp, size, type)
     42 {
     43     _pfirstChunkVec = NULL;
     44     _psamplesPerChunkVec = NULL;
     45     _psampleDescriptionIndexVec = NULL;
     46 
     47     _Index = 0;
     48     _numChunksInRun = 0;
     49     _majorGetIndex = 0;
     50     _currGetChunk = -1;
     51     _numGetChunksInRun = 0;
     52     _currGetSampleCount  = 0;
     53     _firstGetSampleInCurrChunk = 0;
     54     _numGetSamplesPerChunk = 0;
     55     _currGetSDI = 0;
     56 
     57     _majorPeekIndex = 0;
     58     _currPeekChunk = -1;
     59     _numPeekChunksInRun = 0;
     60     _currPeekSampleCount  = 0;
     61     _firstPeekSampleInCurrChunk = 0;
     62     _numPeekSamplesPerChunk = 0;
     63     _currPeekSDI = 0;
     64 
     65     _parsed_entry_cnt = 0;
     66     _fileptr = NULL;
     67 
     68     _stbl_buff_size = MAX_CACHED_TABLE_ENTRIES_FILE;
     69     _next_buff_number = 0;
     70     _curr_buff_number = 0;
     71     _curr_entry_point = 0;
     72     _stbl_fptr_vec = NULL;
     73     _parsing_mode = parsingMode;
     74 
     75     iLogger = PVLogger::GetLoggerObject("mp4ffparser");
     76     iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
     77     iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
     78 
     79     if (_success)
     80     {
     81         _currentChunkNumber = 0;
     82         _maxNumSamplesPerChunk = DEFAULT_MAX_NUM_SAMPLES_PER_CHUNK;
     83         _maxChunkDataSize = DEFAULT_MAX_CHUNK_DATA_SIZE;
     84 
     85         if (!AtomUtils::read32(fp, _entryCount))
     86         {
     87             _success = false;
     88         }
     89         PVMF_MP4FFPARSER_LOGPARSEDINFO((0, "SampleToChunkAtom::SampleToChunkAtom- _entryCount =%d", _entryCount));
     90         uint32 dataSize = _size - (DEFAULT_FULL_ATOM_SIZE + 4);
     91 
     92         uint32 entrySize = (4 + 4 + 4);
     93 
     94         if ((_entryCount*entrySize) > dataSize)
     95         {
     96             _success = false;
     97         }
     98 
     99         if (_success)
    100         {
    101             if (_entryCount > 0)
    102             {
    103                 if (_parsing_mode)
    104                 {
    105                     if ((_entryCount > _stbl_buff_size)) // cahce size is 4K so that optimization should work if entry_count is greater than 4K
    106                     {
    107 
    108                         uint32 fptrBuffSize = (_entryCount / _stbl_buff_size) + 1;
    109 
    110                         PV_MP4_FF_ARRAY_NEW(NULL, uint32, (fptrBuffSize), _stbl_fptr_vec);
    111                         if (_stbl_fptr_vec == NULL)
    112                         {
    113                             _success = false;
    114                             _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
    115                             return;
    116                         }
    117 
    118                         PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _pfirstChunkVec);
    119                         if (_pfirstChunkVec == NULL)
    120                         {
    121                             _success = false;
    122                             _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
    123                             return;
    124                         }
    125 
    126                         PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psamplesPerChunkVec);
    127                         if (_psamplesPerChunkVec == NULL)
    128                         {
    129                             _success = false;
    130                             _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
    131                             return;
    132                         }
    133                         PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psampleDescriptionIndexVec);
    134                         if (_psampleDescriptionIndexVec == NULL)
    135                         {
    136                             _success = false;
    137                             _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
    138                             return;
    139                         }
    140 
    141                         {
    142                             OsclAny* ptr = (MP4_FF_FILE *)(oscl_malloc(sizeof(MP4_FF_FILE)));
    143                             if (ptr == NULL)
    144                             {
    145                                 _success = false;
    146                                 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
    147                                 return;
    148                             }
    149                             _fileptr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE());
    150                             _fileptr->_fileServSession = fp->_fileServSession;
    151                             _fileptr->_pvfile.SetCPM(fp->_pvfile.GetCPM());
    152                             if (AtomUtils::OpenMP4File(filename,
    153                                                        Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
    154                                                        _fileptr) != 0)
    155                             {
    156                                 _success = false;
    157                                 _mp4ErrorCode = FILE_OPEN_FAILED;
    158                             }
    159 
    160                             _fileptr->_fileSize = fp->_fileSize;
    161                         }
    162                         int32 _head_offset = AtomUtils::getCurrentFilePosition(fp);
    163                         AtomUtils::seekFromCurrPos(fp, dataSize);
    164                         AtomUtils::seekFromStart(_fileptr, _head_offset);
    165 
    166                         return;
    167                     }
    168                     else
    169                     {
    170                         _parsing_mode = 0;
    171                         _stbl_buff_size = _entryCount;
    172                     }
    173                 }
    174                 else
    175                 {
    176                     _parsing_mode = 0;
    177                     _stbl_buff_size = _entryCount;
    178                 }
    179 
    180                 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _pfirstChunkVec);
    181                 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psamplesPerChunkVec);
    182                 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psampleDescriptionIndexVec);
    183 
    184                 uint32 firstChunk;
    185                 uint32 samplesPerChunk;
    186                 uint32 sampleDescrIndex;
    187 
    188                 uint32 offSet = 0;
    189 
    190                 uint32 prevFirstChunk = 0;
    191                 uint32 j = 0;
    192 
    193                 for (uint32 i = 0; i < _entryCount; i++)
    194                 {
    195                     if (!AtomUtils::read32(fp, firstChunk))
    196                     {
    197                         _success = false;
    198                         break;
    199                     }
    200 
    201                     if (i == 0)
    202                         offSet = firstChunk;
    203 
    204                     if (!AtomUtils::read32(fp, samplesPerChunk))
    205                     {
    206                         _success = false;
    207                         break;
    208                     }
    209                     if (!AtomUtils::read32(fp, sampleDescrIndex))
    210                     {
    211                         _success = false;
    212                         break;
    213                     }
    214 
    215                     if (firstChunk > prevFirstChunk)
    216                     {
    217                         _pfirstChunkVec[j] = (firstChunk - offSet);
    218                         _psamplesPerChunkVec[j] = (samplesPerChunk);
    219                         _psampleDescriptionIndexVec[j] = (sampleDescrIndex);
    220                         prevFirstChunk = firstChunk;
    221                         j++;
    222                     }
    223                 }
    224                 _entryCount = j;
    225                 uint32 firstsamplenum = 0;
    226                 resetStateVariables(firstsamplenum);
    227             }
    228             else
    229             {
    230                 _pfirstChunkVec = NULL;
    231                 _psamplesPerChunkVec = NULL;
    232                 _psampleDescriptionIndexVec = NULL;
    233             }
    234         }
    235 
    236         if (!_success)
    237         {
    238             _mp4ErrorCode = READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    239             PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::SampleToChunkAtom- Read SampleToChunk Atom failed %d", _mp4ErrorCode));
    240         }
    241     }
    242     else
    243     {
    244         if (_mp4ErrorCode != ATOM_VERSION_NOT_SUPPORTED)
    245         {
    246             _mp4ErrorCode = READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    247             PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::SampleToChunkAtom- Read SampleToChunk Atom failed %d", _mp4ErrorCode));
    248         }
    249     }
    250 }
    251 bool SampleToChunkAtom::ParseEntryUnit(uint32 sample_cnt)
    252 {
    253 
    254     uint32 prevFirstChunk = 0;
    255 
    256 
    257     const uint32 threshold = 512;
    258     sample_cnt += threshold;
    259 
    260     if (sample_cnt > _entryCount)
    261         sample_cnt = _entryCount;
    262 
    263     while (_parsed_entry_cnt < sample_cnt)
    264     {
    265         _curr_entry_point = _parsed_entry_cnt % _stbl_buff_size;
    266         _curr_buff_number = _parsed_entry_cnt / _stbl_buff_size;
    267         if (_curr_buff_number  == _next_buff_number)
    268         {
    269             uint32 currFilePointer = AtomUtils::getCurrentFilePosition(_fileptr);
    270             _stbl_fptr_vec[_curr_buff_number] = currFilePointer;
    271             _next_buff_number++;
    272         }
    273 
    274         if (!_curr_entry_point)
    275         {
    276             uint32 currFilePointer = _stbl_fptr_vec[_curr_buff_number];
    277             AtomUtils::seekFromStart(_fileptr, currFilePointer);
    278         }
    279         uint32 firstChunk;
    280         uint32 samplesPerChunk;
    281         uint32 sampleDescrIndex;
    282 
    283         if (!AtomUtils::read32(_fileptr, firstChunk))
    284         {
    285             _success = false;
    286             break;
    287         }
    288         uint32 offSet = 1;
    289         if (_parsed_entry_cnt == 0)
    290             offSet = firstChunk;
    291 
    292         if (!AtomUtils::read32(_fileptr, samplesPerChunk))
    293         {
    294             _success = false;
    295             break;
    296         }
    297         if (!AtomUtils::read32(_fileptr, sampleDescrIndex))
    298         {
    299             _success = false;
    300             break;
    301         }
    302         if (firstChunk > prevFirstChunk)
    303         {
    304             _pfirstChunkVec[_curr_entry_point] = (firstChunk - offSet);
    305             _psamplesPerChunkVec[_curr_entry_point] = (samplesPerChunk);
    306             _psampleDescriptionIndexVec[_curr_entry_point] = (sampleDescrIndex);
    307             _parsed_entry_cnt++;
    308             prevFirstChunk = firstChunk;
    309         }
    310     }
    311     return true;
    312 }
    313 
    314 SampleToChunkAtom::~SampleToChunkAtom()
    315 {
    316     if (_pfirstChunkVec != NULL)
    317     {
    318         PV_MP4_ARRAY_DELETE(NULL, _pfirstChunkVec);
    319     }
    320     if (_psamplesPerChunkVec != NULL)
    321     {
    322         PV_MP4_ARRAY_DELETE(NULL, _psamplesPerChunkVec);
    323     }
    324     if (_psampleDescriptionIndexVec != NULL)
    325     {
    326         PV_MP4_ARRAY_DELETE(NULL, _psampleDescriptionIndexVec);
    327     }
    328     if (_fileptr != NULL)
    329     {
    330         if (_fileptr->IsOpen())
    331         {
    332             AtomUtils::CloseMP4File(_fileptr);
    333         }
    334 
    335         oscl_free(_fileptr);
    336     }
    337     if (_stbl_fptr_vec != NULL)
    338         PV_MP4_ARRAY_DELETE(NULL, _stbl_fptr_vec);
    339 
    340 }
    341 
    342 // Returns the chunk number of the first chunk in run[index]
    343 int32
    344 SampleToChunkAtom::getFirstChunkAt(uint32 index)
    345 {
    346     if (_pfirstChunkVec == NULL)
    347     {
    348         return PV_ERROR;
    349     }
    350     if (index < _entryCount)
    351     {
    352         if (_parsing_mode == 1)
    353         {
    354             CheckAndParseEntry(index);
    355         }
    356         return (_pfirstChunkVec[index%_stbl_buff_size]);
    357     }
    358     else
    359     {
    360         PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::getFirstChunkAt index = %d", index));
    361         return PV_ERROR;
    362     }
    363 }
    364 
    365 // Returns the samples per chunk of all the chunks in run[index]
    366 int32
    367 SampleToChunkAtom::getSamplesPerChunkAt(uint32 index)
    368 {
    369     if (_psamplesPerChunkVec == NULL)
    370     {
    371         return PV_ERROR;
    372     }
    373     if (index < _entryCount)
    374     {
    375         if (_parsing_mode == 1)
    376         {
    377             CheckAndParseEntry(index);
    378         }
    379         return (_psamplesPerChunkVec[index%_stbl_buff_size]);
    380     }
    381     else
    382     {
    383         PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::getSamplesPerChunkAt index = %d", index));
    384         return PV_ERROR;
    385     }
    386 
    387 }
    388 
    389 // Returns the samples description index for the samples in all the chunks in run[index]
    390 uint32
    391 SampleToChunkAtom::getSDIndex() const
    392 {
    393     if (_psampleDescriptionIndexVec == NULL)
    394     {
    395         return (uint32)PV_ERROR;
    396     }
    397 
    398     if (_Index < _entryCount)
    399     {
    400         return (_psampleDescriptionIndexVec[_Index%_stbl_buff_size]);
    401     }
    402     else
    403     {
    404         PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndex"));
    405         return (uint32) PV_ERROR;
    406     }
    407 }
    408 
    409 // Returns the chunk number for the given sample number
    410 uint32
    411 SampleToChunkAtom::getChunkNumberForSampleGet(uint32 sampleNum)
    412 {
    413     if ((_pfirstChunkVec == NULL) ||
    414             (_psamplesPerChunkVec == NULL))
    415     {
    416         return (uint32)PV_ERROR;
    417     }
    418 
    419     if (_parsing_mode == 1)
    420     {
    421         CheckAndParseEntry(_majorGetIndex);
    422     }
    423 
    424     if (sampleNum < _currGetSampleCount)
    425     {
    426         return (_currGetChunk);
    427     }
    428     else if (_numGetChunksInRun > 1)
    429     {
    430         _firstGetSampleInCurrChunk = _currGetSampleCount;
    431         _currGetSampleCount += _numGetSamplesPerChunk;
    432         _currGetChunk++;
    433 
    434         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _firstGetSampleInCurrChunk =%d", _firstGetSampleInCurrChunk));
    435         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
    436         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));
    437 
    438         // to handle special case, every sample is a chunk
    439         if (_entryCount > 1)
    440         {
    441             _numGetChunksInRun--;
    442         }
    443 
    444         if (sampleNum < _currGetSampleCount)
    445         {
    446             return (_currGetChunk);
    447         }
    448         else
    449         {
    450             PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
    451             return (uint32)PV_ERROR;
    452         }
    453     }
    454     else if (_numGetChunksInRun <= 1)
    455     {
    456         if (_majorGetIndex < (int32)(_entryCount - 1))
    457         {
    458             uint32 prevFirstChunk = _pfirstChunkVec[_majorGetIndex%_stbl_buff_size];
    459             _numGetSamplesPerChunk = _psamplesPerChunkVec[_majorGetIndex%_stbl_buff_size];
    460             _currGetSDI = _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];
    461 
    462             if (_parsing_mode == 1)
    463             {
    464                 CheckAndParseEntry(_majorGetIndex + 1);
    465             }
    466 
    467             uint32 nextFirstChunk = _pfirstChunkVec[(_majorGetIndex+1)%_stbl_buff_size];
    468             _numGetChunksInRun = nextFirstChunk - prevFirstChunk;
    469             _numChunksInRun = _numGetChunksInRun;
    470 
    471 
    472             _majorGetIndex++;
    473             _firstGetSampleInCurrChunk = _currGetSampleCount;
    474             _currGetSampleCount    += _numGetSamplesPerChunk;
    475             _currGetChunk++;
    476 
    477             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetChunksInRun =%d", _numGetChunksInRun));
    478             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetSamplesPerChunk =%d", _numGetSamplesPerChunk));
    479             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
    480             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));
    481             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _majorGetIndex =%d", _majorGetIndex));
    482 
    483             if (sampleNum < _currGetSampleCount)
    484             {
    485                 return (_currGetChunk);
    486             }
    487             else
    488             {
    489                 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
    490                 return (uint32)PV_ERROR;
    491             }
    492         }
    493         else if (_majorGetIndex == (int32)(_entryCount - 1))
    494         {
    495             // Last run of chunks
    496             _numGetChunksInRun = 1;
    497 
    498             _numChunksInRun = _numGetChunksInRun;
    499 
    500             _currGetSDI = _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];
    501 
    502             _numGetSamplesPerChunk =
    503                 _psamplesPerChunkVec[_majorGetIndex%_stbl_buff_size];
    504 
    505             _firstGetSampleInCurrChunk = _currGetSampleCount;
    506 
    507             _currGetSampleCount += _numGetSamplesPerChunk;
    508             _currGetChunk++;
    509 
    510             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetSamplesPerChunk =%d", _firstGetSampleInCurrChunk));
    511             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _firstGetSampleInCurrChunk =%d", _firstGetSampleInCurrChunk));
    512             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
    513             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));
    514 
    515             if (sampleNum < _currGetSampleCount)
    516             {
    517                 return (_currGetChunk);
    518             }
    519             else
    520             {
    521                 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
    522                 return (uint32)PV_ERROR;
    523             }
    524         }
    525         else
    526         {
    527             PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet _majorGetIndex = %d _entryCount= %d", _majorGetIndex, _entryCount));
    528             return (uint32)PV_ERROR;
    529         }
    530     }
    531 
    532     return (uint32)PV_ERROR; // Should never get here
    533 }
    534 
    535 // Returns the chunk number for the given sample number
    536 uint32
    537 SampleToChunkAtom::getChunkNumberForSample(uint32 sampleNum)
    538 {
    539     if ((_pfirstChunkVec == NULL) ||
    540             (_psamplesPerChunkVec == NULL))
    541     {
    542         return (uint32)PV_ERROR;
    543     }
    544 
    545     uint32 sampleCount = 0;
    546 
    547     for (uint32 i = 0; i < _entryCount; i++)
    548     {
    549         uint32 chunkNum = 0;
    550         uint32 samplesPerChunkInRun = 0;
    551 
    552         if (_parsing_mode == 1)
    553         {
    554             CheckAndParseEntry(i);
    555         }
    556         chunkNum = _pfirstChunkVec[i%_stbl_buff_size];
    557         samplesPerChunkInRun = _psamplesPerChunkVec[i%_stbl_buff_size];
    558 
    559         if ((i + 1) < _entryCount)
    560         {
    561             if (_parsing_mode == 1)
    562             {
    563                 CheckAndParseEntry(i + 1);
    564             }
    565 
    566             uint32 nextChunkNum = _pfirstChunkVec[(int32)((i+1)%_stbl_buff_size)];
    567             uint32 numChunksInRun = nextChunkNum - chunkNum;
    568             uint32 count = sampleCount + samplesPerChunkInRun * numChunksInRun;
    569 
    570             if (count < sampleNum)
    571             { // Haven't found chunk yet - running count still less than sampleNum
    572                 sampleCount = count;
    573                 continue;
    574             }
    575             else
    576             { // Found run of chunks in which sample lies - now find actual chunk
    577                 for (int32 j = 0; j < (int32)numChunksInRun; j++)
    578                 {
    579                     sampleCount += samplesPerChunkInRun; //  samples for jth chunk
    580                     if (sampleNum < sampleCount)
    581                     { // Found specific chunk
    582                         _Index = i;
    583                         return chunkNum + j; // Return jth chunk in run
    584                     }
    585                 }
    586             }
    587         }
    588         else
    589         { // Last run of chunks - simply find specific chunk
    590             int k = 0;
    591             while (sampleNum >= sampleCount)
    592             {
    593                 // Continue until find chunk number - we do not know how many chunks are in
    594                 // this final run so keep going til we find a number
    595                 sampleCount += samplesPerChunkInRun;
    596                 if (sampleNum < sampleCount)
    597                 {
    598                     // Found specific chunk
    599                     _Index = i;
    600                     return chunkNum + k; // Return ith chunk in run
    601                     // Since we do not actually know how many chunk are in this last run,
    602                     // the chunkNum that is returned may not be a valid chunk!
    603                     // This is handled in the exception handling in the chunkOffset atom
    604                 }
    605                 k++;
    606             }
    607         }
    608     }
    609     return (uint32)PV_ERROR; // Should never get here
    610 }
    611 
    612 
    613 // Returns the sampleNum of the first sample in chunk with chunk number 'chunkNum'
    614 // Note that since the coding of this table does not indicate the total number of
    615 // chunks (i.e. don't know how many chunks in last run) this method may return a
    616 // sample number that is not valid.  This should be taken care of in the exception
    617 // handling in the chunkoffset and samplesize atoms
    618 uint32
    619 SampleToChunkAtom::getFirstSampleNumInChunk(uint32 chunkNum)
    620 {
    621     if ((_pfirstChunkVec == NULL) ||
    622             (_psamplesPerChunkVec == NULL))
    623     {
    624         return (uint32)PV_ERROR;
    625     }
    626 
    627     uint32 firstChunkCurrentRun = 0; // chunk number of first chunk in this run
    628     uint32 firstChunkNextRun = 0; // chunk number of first chunk in next run
    629     uint32 firstSample = 0; // number of first sample in the run of chunks in which chunk 'chunkNum' lies
    630     // once we find the correct run, this value holds the sample number of the first
    631     // sample in chunk 'chunkNum'
    632     uint32 samplesInRun = 0;    // Number of samples in the entire run of chunks (not just in each chunk)
    633 
    634     for (uint32 i = 0; i < _entryCount; i++)
    635     {
    636         // Go through vector of first chunks in runs
    637 
    638         if (_parsing_mode == 1)
    639         {
    640             CheckAndParseEntry(i);
    641         }
    642 
    643         firstChunkCurrentRun = _pfirstChunkVec[i%_stbl_buff_size]; // Get first chunk number for run i
    644 
    645         if (chunkNum < firstChunkCurrentRun)
    646         {
    647             // Chunk is in previous run of chunks
    648             firstSample -= samplesInRun; // Backtrack to first sample of last run
    649 
    650             // Now need to find specific chunk and sample in this run
    651             if (_parsing_mode == 1)
    652             {
    653                 CheckAndParseEntry(i - 1);
    654             }
    655 
    656             firstChunkCurrentRun = _pfirstChunkVec[(int32)((i-1)%_stbl_buff_size)];  // Backtrack to  last run
    657             uint32 samplesPerChunk = _psamplesPerChunkVec[(int32)((i-1)%_stbl_buff_size)];
    658 
    659             uint32 chunkOffset = chunkNum - firstChunkCurrentRun; // Offset from firstChunk
    660             uint32 sampleOffset = chunkOffset * samplesPerChunk;
    661             firstSample += sampleOffset;
    662 
    663             return firstSample;
    664         }
    665         else if (chunkNum == firstChunkCurrentRun)
    666         {
    667             // Requested chunk is first in this run
    668             return firstSample; // Return first sample in this run
    669         }
    670         else
    671         {
    672             // Haven't found chunk in run
    673 
    674             if ((i + 1) < _entryCount)
    675             {
    676                 if (_parsing_mode == 1)
    677                 {
    678                     CheckAndParseEntry(i + 1);
    679                 }
    680 
    681                 firstChunkNextRun = _pfirstChunkVec[(int32)(((i+1)%_stbl_buff_size))];  // If we are out of range of the vector
    682                 // This means we are in the last run of chunks
    683                 int32 numChunks = firstChunkNextRun - firstChunkCurrentRun;
    684                 samplesInRun = _psamplesPerChunkVec[i%_stbl_buff_size] * numChunks; // Once you advance, this value maintains the
    685                 // number of samples in the previous run
    686                 firstSample += samplesInRun;
    687             }
    688             else
    689             {
    690                 // In last run of chunks - we know the chunk is here
    691                 // Now need to find specific chunk and sample
    692 
    693                 firstChunkCurrentRun = _pfirstChunkVec[i%_stbl_buff_size]; // Get first chunk number for this run
    694                 uint32 samplesPerChunk = _psamplesPerChunkVec[i%_stbl_buff_size];
    695 
    696                 uint32 chunkOffset = chunkNum - firstChunkCurrentRun; // Offset from firstChunk
    697                 uint32 sampleOffset = chunkOffset * samplesPerChunk;
    698                 firstSample += sampleOffset;
    699 
    700                 return firstSample;
    701             }
    702         }
    703     }
    704 
    705     return 0; // Error condition
    706 }
    707 
    708 uint32
    709 SampleToChunkAtom::getNumChunksInRunofChunks(uint32 chunk)
    710 {
    711     if (_pfirstChunkVec == NULL)
    712     {
    713         return (uint32)PV_ERROR;
    714     }
    715 
    716     if ((chunk + 1) < _entryCount)
    717     {
    718         for (uint32 i = 0; i < _entryCount; i++)
    719         {
    720             if (_parsing_mode == 1)
    721             {
    722                 CheckAndParseEntry(i);
    723             }
    724 
    725             if (_pfirstChunkVec[i%_stbl_buff_size] < chunk)
    726             {
    727                 continue;
    728             }
    729             else if (_pfirstChunkVec[i%_stbl_buff_size] == chunk)
    730             {
    731                 uint32 chunkNum = _pfirstChunkVec[(int32)(i%_stbl_buff_size)];
    732                 if (_parsing_mode == 1)
    733                 {
    734                     CheckAndParseEntry(i + 1);
    735                 }
    736                 uint32 nextChunkNum = _pfirstChunkVec[(int32)((i+1)%_stbl_buff_size)];
    737                 return(nextChunkNum - chunkNum);
    738             }
    739             else if (_pfirstChunkVec[(i%_stbl_buff_size)] > chunk)
    740             {
    741                 return(_pfirstChunkVec[(i%_stbl_buff_size)] - chunk);
    742             }
    743         }
    744     }
    745     else
    746     {
    747         return (1);
    748     }
    749 
    750     return (uint32)PV_ERROR;
    751 }
    752 
    753 uint32
    754 SampleToChunkAtom::getSamplesPerChunkCorrespondingToSample(uint32 sampleNum)
    755 {
    756     uint32 sampleCount = 0;
    757 
    758     if ((_pfirstChunkVec == NULL) ||
    759             (_psamplesPerChunkVec == NULL))
    760     {
    761         return (uint32)PV_ERROR;
    762     }
    763 
    764     for (uint32 i = 0; i < _entryCount; i++)
    765     {
    766         if (_parsing_mode == 1)
    767         {
    768             CheckAndParseEntry(i);
    769         }
    770 
    771         uint32 chunkNum = 0;
    772         uint32 samplesPerChunkInRun = 0;
    773 
    774         chunkNum = _pfirstChunkVec[(i%_stbl_buff_size)];
    775         samplesPerChunkInRun = _psamplesPerChunkVec[(i%_stbl_buff_size)];
    776 
    777         if ((i + 1) < _entryCount)
    778         {
    779             if (_parsing_mode == 1)
    780             {
    781                 CheckAndParseEntry(i + 1);
    782             }
    783 
    784             uint32 nextChunkNum = _pfirstChunkVec[(int32)(((i+1)%_stbl_buff_size))];
    785             uint32 numChunksInRun = nextChunkNum - chunkNum;
    786             uint32 count = sampleCount + samplesPerChunkInRun * numChunksInRun;
    787 
    788             if (count < sampleNum)
    789             { // Haven't found chunk yet - running count still less than sampleNum
    790                 sampleCount = count;
    791                 continue;
    792             }
    793             else
    794             { // Found run of chunks in which sample lies - now find actual chunk
    795                 for (int32 j = 0; j < (int32)numChunksInRun; j++)
    796                 {
    797                     sampleCount += samplesPerChunkInRun; //  samples for jth chunk
    798                     if (sampleNum < sampleCount)
    799                     { // Found specific chunk
    800                         return (samplesPerChunkInRun);
    801                     }
    802                 }
    803             }
    804         }
    805         else
    806         {
    807             // Last run of chunks - simply find specific chunk
    808             int k = 0;
    809             int for_ever = 1;
    810             while (for_ever)
    811             {
    812                 // Continue until find chunk number - we do not know how many chunks are in
    813                 // this final run so keep going til we find a number
    814                 sampleCount += samplesPerChunkInRun;
    815                 if (sampleNum < sampleCount)
    816                 { // Found specific chunk
    817                     return (samplesPerChunkInRun);
    818                     // Since we do not actually know how many chunk are in this last run,
    819                     // the chunkNum that is returned may not be a valid chunk!
    820                     // This is handled in the exception handling in the chunkOffset atom
    821                 }
    822                 k++;
    823             }
    824         }
    825     }
    826     return 0; // Should never get here
    827 }
    828 
    829 
    830 // Returns the chunk number for the given sample number
    831 uint32
    832 SampleToChunkAtom::getSDIndexPeek() const
    833 {
    834     if (_psampleDescriptionIndexVec == NULL)
    835     {
    836         return (uint32)PV_ERROR;
    837     }
    838 
    839     if (_currPeekSDI != 0)
    840     {
    841         return (_currPeekSDI);
    842     }
    843     else
    844     {
    845         PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndexPeek _currPeekSDI = %d", _currPeekSDI));
    846         return (uint32) PV_ERROR;
    847     }
    848 }
    849 uint32
    850 SampleToChunkAtom::getSDIndexGet() const
    851 {
    852     if (_psampleDescriptionIndexVec == NULL)
    853     {
    854         return (uint32)PV_ERROR;
    855     }
    856 
    857     if (_currGetSDI != 0)
    858     {
    859         return (_currGetSDI);
    860     }
    861     else
    862     {
    863         PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndexGet _currGetSDI = %d", _currGetSDI));
    864         return (uint32) PV_ERROR;
    865     }
    866 }
    867 
    868 
    869 uint32
    870 SampleToChunkAtom::getFirstSampleNumInChunkGet() const
    871 {
    872     if ((_pfirstChunkVec == NULL) ||
    873             (_psamplesPerChunkVec == NULL))
    874     {
    875         return (uint32)PV_ERROR;
    876     }
    877 
    878     return (_firstGetSampleInCurrChunk);
    879 }
    880 
    881 
    882 uint32
    883 SampleToChunkAtom::getChunkNumberForSamplePeek(uint32 sampleNum)
    884 {
    885     if ((_pfirstChunkVec == NULL) ||
    886             (_psamplesPerChunkVec == NULL))
    887     {
    888         return (uint32)PV_ERROR;
    889     }
    890     if (_parsing_mode == 1)
    891     {
    892         CheckAndParseEntry(_majorPeekIndex);
    893     }
    894 
    895     if (sampleNum < _currPeekSampleCount)
    896     {
    897         return (_currPeekChunk);
    898     }
    899     else if (_numPeekChunksInRun > 1)
    900     {
    901         _firstPeekSampleInCurrChunk = _currPeekSampleCount;
    902         _currPeekSampleCount += _numPeekSamplesPerChunk;
    903         _currPeekChunk++;
    904 
    905         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
    906         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
    907         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
    908         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekChunk =%d", _currPeekChunk));
    909 
    910         // to handle special case, every sample is a chunk
    911         if (_entryCount > 1)
    912         {
    913             _numPeekChunksInRun--;
    914         }
    915 
    916         if (sampleNum < _currPeekSampleCount)
    917         {
    918             return (_currPeekChunk);
    919         }
    920         else
    921         {
    922             PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
    923             return (uint32)PV_ERROR;
    924         }
    925     }
    926     else if (_numPeekChunksInRun <= 1)
    927     {
    928         if (_majorPeekIndex < (int32)(_entryCount - 1))
    929         {
    930             uint32 prevNextChunk = _pfirstChunkVec[_majorPeekIndex%_stbl_buff_size];
    931             _numPeekSamplesPerChunk = _psamplesPerChunkVec[_majorPeekIndex%_stbl_buff_size];
    932             _currPeekSDI = _psampleDescriptionIndexVec[_majorPeekIndex%_stbl_buff_size];
    933 
    934             if (_parsing_mode == 1)
    935             {
    936                 CheckAndParseEntry(_majorPeekIndex + 1);
    937             }
    938 
    939             uint32 nextfirstChunk = _pfirstChunkVec[(_majorPeekIndex+1)%_stbl_buff_size];
    940 
    941             _numPeekChunksInRun = nextfirstChunk - prevNextChunk;
    942 
    943             _majorPeekIndex++;
    944 
    945             _firstPeekSampleInCurrChunk = _currPeekSampleCount;
    946             _currPeekSampleCount    += _numPeekSamplesPerChunk;
    947             _currPeekChunk++;
    948 
    949             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekChunksInRun =%d", _numPeekChunksInRun));
    950             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
    951             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _majorPeekIndex =%d", _majorPeekIndex));
    952             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
    953             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
    954             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
    955 
    956             if (sampleNum < _currPeekSampleCount)
    957             {
    958                 return (_currPeekChunk);
    959             }
    960             else
    961             {
    962                 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
    963                 return (uint32)PV_ERROR;
    964             }
    965         }
    966         else if (_majorPeekIndex == (int32)(_entryCount - 1))
    967         {
    968             _numPeekChunksInRun = 1;
    969 
    970             _currPeekSDI =
    971                 _psampleDescriptionIndexVec[_majorPeekIndex%_stbl_buff_size];
    972 
    973             _numPeekSamplesPerChunk =
    974                 _psamplesPerChunkVec[_majorPeekIndex%_stbl_buff_size];
    975 
    976             _firstPeekSampleInCurrChunk = _currPeekSampleCount;
    977 
    978             _currPeekSampleCount += _numPeekSamplesPerChunk;
    979             _currPeekChunk++;
    980 
    981             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
    982             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _majorPeekIndex =%d", _majorPeekIndex));
    983             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
    984             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
    985             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
    986 
    987             if (sampleNum < _currPeekSampleCount)
    988             {
    989                 return (_currPeekChunk);
    990             }
    991             else
    992             {
    993                 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
    994                 return (uint32)PV_ERROR;
    995             }
    996         }
    997         else
    998         {
    999             return (uint32)PV_ERROR;
   1000         }
   1001     }
   1002 
   1003     return (uint32)PV_ERROR; // Should never get here
   1004 }
   1005 uint32
   1006 SampleToChunkAtom::getNumChunksInRunofChunksGet() const
   1007 {
   1008     if (_pfirstChunkVec == NULL)
   1009     {
   1010         return (uint32)PV_ERROR;
   1011     }
   1012 
   1013     if (_numChunksInRun != 0)
   1014     {
   1015         return (_numChunksInRun);
   1016     }
   1017     return (uint32)PV_ERROR;
   1018 }
   1019 
   1020 uint32
   1021 SampleToChunkAtom::getSamplesPerChunkCorrespondingToSampleGet() const
   1022 {
   1023 
   1024     if ((_pfirstChunkVec == NULL) ||
   1025             (_psamplesPerChunkVec == NULL))
   1026     {
   1027         return (uint32)PV_ERROR;
   1028     }
   1029 
   1030     if (_numGetSamplesPerChunk != 0)
   1031     {
   1032         return (_numGetSamplesPerChunk);
   1033     }
   1034 
   1035     return 0; // Should never get here
   1036 }
   1037 uint32
   1038 SampleToChunkAtom::getFirstSampleNumInChunkPeek() const
   1039 {
   1040     if ((_pfirstChunkVec == NULL) ||
   1041             (_psamplesPerChunkVec == NULL))
   1042     {
   1043         return (uint32)PV_ERROR;
   1044     }
   1045 
   1046     return (_firstPeekSampleInCurrChunk);
   1047 }
   1048 
   1049 int32
   1050 SampleToChunkAtom::resetStateVariables()
   1051 {
   1052     _majorGetIndex = 0;
   1053     _currGetChunk = -1;
   1054     _numGetChunksInRun = 0;
   1055     _currGetSampleCount  = 0;
   1056     _firstGetSampleInCurrChunk = 0;
   1057     _numGetSamplesPerChunk = 0;
   1058     _currGetSDI = 0;
   1059 
   1060     _majorPeekIndex = 0;
   1061     _currPeekChunk = -1;
   1062     _numPeekChunksInRun = 0;
   1063     _currPeekSampleCount  = 0;
   1064     _firstPeekSampleInCurrChunk = 0;
   1065     _numPeekSamplesPerChunk = 0;
   1066     _currPeekSDI = 0;
   1067 
   1068     return (EVERYTHING_FINE);
   1069 }
   1070 
   1071 int32
   1072 SampleToChunkAtom::resetStateVariables(uint32 sampleNum)
   1073 {
   1074     _majorGetIndex = 0;
   1075     _currGetChunk = -1;
   1076     _numGetChunksInRun = 0;
   1077     _currGetSampleCount  = 0;
   1078     _firstGetSampleInCurrChunk = 0;
   1079     _numGetSamplesPerChunk = 0;
   1080     _currGetSDI = 0;
   1081 
   1082     _majorPeekIndex = 0;
   1083     _currPeekChunk = -1;
   1084     _numPeekChunksInRun = 0;
   1085     _currPeekSampleCount  = 0;
   1086     _firstPeekSampleInCurrChunk = 0;
   1087     _numPeekSamplesPerChunk = 0;
   1088     _currPeekSDI = 0;
   1089 
   1090     if ((_pfirstChunkVec == NULL) ||
   1091             (_psamplesPerChunkVec == NULL))
   1092     {
   1093         return PV_ERROR;
   1094     }
   1095 
   1096     uint32 sampleCount = 0;
   1097 
   1098     for (uint32 i = 0; i < _entryCount; i++)
   1099     {
   1100         uint32 chunkNum = 0;
   1101         uint32 samplesPerChunkInRun = 0;
   1102 
   1103         if (_parsing_mode == 1)
   1104         {
   1105             CheckAndParseEntry(i + 1);
   1106         }
   1107 
   1108         chunkNum = _pfirstChunkVec[i%_stbl_buff_size];
   1109         samplesPerChunkInRun = _psamplesPerChunkVec[i%_stbl_buff_size];
   1110 
   1111         if ((i + 1) < _entryCount)
   1112         {
   1113             uint32 nextChunkNum = _pfirstChunkVec[(int32)(i+1)%_stbl_buff_size];
   1114             uint32 numChunksInRun = nextChunkNum - chunkNum;
   1115             uint32 count = sampleCount + samplesPerChunkInRun * numChunksInRun;
   1116 
   1117             if (count < sampleNum)
   1118             {
   1119                 // Haven't found chunk yet - running count still less than sampleNum
   1120                 sampleCount = count;
   1121                 continue;
   1122             }
   1123             else
   1124             {
   1125                 _numGetChunksInRun = numChunksInRun;
   1126 
   1127                 // Found run of chunks in which sample lies - now find actual chunk
   1128                 for (int32 j = 0; j < (int32)numChunksInRun; j++)
   1129                 {
   1130                     //  samples for jth chunk
   1131                     _firstGetSampleInCurrChunk = sampleCount;
   1132                     _numGetSamplesPerChunk = samplesPerChunkInRun;
   1133                     sampleCount += samplesPerChunkInRun;
   1134 
   1135                     if (sampleNum < sampleCount)
   1136                     {
   1137                         _majorGetIndex = i;
   1138                         _numChunksInRun = numChunksInRun;
   1139                         _currGetSampleCount = sampleCount;
   1140                         _currGetChunk =  chunkNum + j;
   1141                         _currGetSDI =
   1142                             _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];
   1143 
   1144                         goto END_OF_RESET;
   1145                     }
   1146                     _numGetChunksInRun--;
   1147                 }
   1148             }
   1149         }
   1150         else
   1151         {
   1152             // Last run of chunks - simply find specific chunk
   1153             int k = 0;
   1154             while (sampleNum >= sampleCount)
   1155             {
   1156                 // Continue until find chunk number - we do not know how many chunks are in
   1157                 // this final run so keep going til we find a number
   1158                 _firstGetSampleInCurrChunk = sampleCount;
   1159                 _numGetSamplesPerChunk = samplesPerChunkInRun;
   1160 
   1161                 sampleCount += samplesPerChunkInRun;
   1162 
   1163                 if (sampleNum < sampleCount)
   1164                 {
   1165                     // Found specific chunk
   1166                     _majorGetIndex = i;
   1167                     _numGetChunksInRun = 1;
   1168                     _numChunksInRun = _numGetChunksInRun;
   1169                     _currGetSampleCount = sampleCount;
   1170                     _currGetChunk =  chunkNum + k;
   1171                     _currGetSDI =
   1172                         _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];
   1173 
   1174                     goto END_OF_RESET;
   1175                     // Return ith chunk in run
   1176                     // Since we do not actually know how many chunk are in this last run,
   1177                     // the chunkNum that is returned may not be a valid chunk!
   1178                     // This is handled in the exception handling in the chunkOffset atom
   1179                 }
   1180                 k++;
   1181             }
   1182         }
   1183     }
   1184 
   1185     return PV_ERROR; // Should never get here
   1186 
   1187 END_OF_RESET:
   1188     {
   1189         if (_majorGetIndex < (int32)(_entryCount - 1))
   1190         {
   1191             _majorGetIndex++;
   1192         }
   1193         _majorPeekIndex = _majorGetIndex;
   1194         _currPeekChunk = _currGetChunk;
   1195         _numPeekChunksInRun = _numGetChunksInRun;
   1196         _currPeekSampleCount  = _currGetSampleCount;
   1197         _firstPeekSampleInCurrChunk = _firstGetSampleInCurrChunk;
   1198         _numPeekSamplesPerChunk = _numGetSamplesPerChunk;
   1199         _currPeekSDI = _currGetSDI;
   1200 
   1201         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _majorPeekIndex = _majorGetIndex =%d", _majorPeekIndex));
   1202         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _currPeekChunk = _currGetChunk =%d", _currPeekChunk));
   1203         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekChunksInRun = _numGetChunksInRun = %d", _numPeekChunksInRun));
   1204         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _currPeekSampleCount = _currGetSampleCount = %d", _currPeekSampleCount));
   1205         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _firstPeekSampleInCurrChunk = _firstGetSampleInCurrChunk = %d", _firstPeekSampleInCurrChunk));
   1206         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekSamplesPerChunk = _numGetSamplesPerChunk = %d", _numPeekSamplesPerChunk));
   1207         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekSamplesPerChunk = _currGetSDI = %d", _currPeekSDI));
   1208 
   1209         return (EVERYTHING_FINE);
   1210     }
   1211 }
   1212 
   1213 int32 SampleToChunkAtom::resetPeekwithGet()
   1214 {
   1215     _majorPeekIndex = _majorGetIndex;
   1216     _currPeekChunk = _currGetChunk;
   1217     _numPeekChunksInRun = _numGetChunksInRun;
   1218     _currPeekSampleCount  = _currGetSampleCount;
   1219     _firstPeekSampleInCurrChunk = _firstGetSampleInCurrChunk;
   1220     _numPeekSamplesPerChunk = _numGetSamplesPerChunk;
   1221     _currPeekSDI = _currGetSDI;
   1222     return (EVERYTHING_FINE);
   1223 }
   1224 void SampleToChunkAtom::CheckAndParseEntry(uint32 i)
   1225 {
   1226     if (i >= _parsed_entry_cnt)
   1227     {
   1228         ParseEntryUnit(i);
   1229     }
   1230     else
   1231     {
   1232         uint32 entryLoc = i / _stbl_buff_size;
   1233         if (_curr_buff_number != entryLoc)
   1234         {
   1235             _parsed_entry_cnt = entryLoc * _stbl_buff_size;
   1236             while (_parsed_entry_cnt <= i)
   1237                 ParseEntryUnit(_parsed_entry_cnt);
   1238         }
   1239     }
   1240 }
   1241