MP4_ERROR_CODE CompositionOffsetAtom::GetTimeOffsetFromMT(uint32 aSampleNum, uint32 aCurrEC, uint32 aCurrSampleCount, uint32& aTimeOffset)
{
    MP4_ERROR_CODE retval = DEFAULT_ERROR;
    if ((_psampleOffsetVec == NULL) ||
            (_psampleCountVec == NULL) ||
            (_entryCount == 0))
    {
        return retval;
    }

    if (aSampleNum < aCurrSampleCount)
    { // Sample num within current entry
        if (_parsing_mode == 1)
            CheckAndParseEntry(aCurrEC);

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForaSampleNumber- Time StampOffset = %d", _psampleOffsetVec[aCurrEC%_stbl_buff_size]));
        aTimeOffset = _psampleOffsetVec[aCurrEC%_stbl_buff_size];
        retval = EVERYTHING_FINE;
    }
    else
    {

        for (uint32 i = aCurrEC + 1; i < _entryCount; i++)
        {
            if (_parsing_mode == 1)
                CheckAndParseEntry(i);


            if (aSampleNum < (aCurrSampleCount + _psampleCountVec[i%_stbl_buff_size]))
            {
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForaSampleNumber- Time StampOffset = %d", _psampleOffsetVec[i%_stbl_buff_size]));
                aTimeOffset = _psampleOffsetVec[i%_stbl_buff_size];
                retval = EVERYTHING_FINE;
            }
            else
            {
                aCurrSampleCount += _psampleCountVec[i%_stbl_buff_size];
            }
        }
    }

    // Went past end of list - not a valid sample number
    return retval;
}
// This is the most widely used API
// Returns the offset (ms) for the  sample given by num.  This is used when
// randomly accessing a frame and the timestamp has not been accumulated.
int32 CompositionOffsetAtom::getTimeOffsetForSampleNumberGet(uint32 sampleNum)
{
    if ((_psampleOffsetVec == NULL) ||
            (_psampleCountVec == NULL) ||
            (_entryCount == 0))
    {
        return PV_ERROR;
    }

    // note that sampleNum is a zero based index while _currGetSampleCount is 1 based index
    if (sampleNum < _currGetSampleCount)
    {
        return (_currGetTimeOffset);
    }
    else
    {

        do
        {
            _currGetIndex++;
            if (_parsing_mode)
                CheckAndParseEntry(_currGetIndex);
            _currGetSampleCount += _psampleCountVec[_currGetIndex%_stbl_buff_size];
            _currGetTimeOffset    = _psampleOffsetVec[_currGetIndex%_stbl_buff_size];
        }
        while (_currGetSampleCount == 0);

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetIndex =%d", _currGetIndex));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetSampleCount =%d", _currGetSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetTimeOffset =%d", _currGetTimeOffset));

        if (sampleNum < _currGetSampleCount)
        {
            return (_currGetTimeOffset);
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>TimeToSampleAtom::getTimeDeltaForSampleNumberGet sampleNum = %d", sampleNum));
            return (PV_ERROR);
        }
    }
}
// Returns the timestamp (ms) for the current sample given by num.  This is used when
// randomly accessing a frame and the timestamp has not been accumulated. It is implicit
// that sample[0] occurs at timestamp ts=0.
MP4_ERROR_CODE TimeToSampleAtom::GetTimestampForSampleNumber(uint32 aSampleNumber, uint64& aTimestamp)
{
    MP4_ERROR_CODE retval = READ_FAILED;
    if ((_psampleDeltaVec == NULL) ||
            (_psampleCountVec == NULL) ||
            (_entryCount == 0))
    {
        return retval;
    }
    // It is assumed that sample 0 has a ts of 0 - i.e. the first
    // entry in the table starts with the delta between sample 1 and sample 0
    if (0 == aSampleNumber)
    {
        aTimestamp = 0;
        return EVERYTHING_FINE;
    }

    uint32 sampleCount = 0;
    uint64 ts = 0; // Timestamp value to return
    for (uint32 i = 0; i < _entryCount; i++)
    {
        if (_parsing_mode == 1)
            CheckAndParseEntry(i);

        if (aSampleNumber <= (sampleCount + _psampleCountVec[i%_stbl_buff_size]))
        { // Sample num within current entry
            int32 count = aSampleNumber - sampleCount;
            ts += _psampleDeltaVec[i%_stbl_buff_size] * count;
            aTimestamp = ts;
            retval = EVERYTHING_FINE;
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TimeToSampleAtom::getTimestampForSampleNumber- Time Stamp =%d", ts));
            break;
        }
        else
        {
            sampleCount += _psampleCountVec[i%_stbl_buff_size];
            ts += (_psampleDeltaVec[i%_stbl_buff_size] * _psampleCountVec[i%_stbl_buff_size]);
        }
    }

    // Went past end of list - not a valid sample number
    return retval;
}
MP4_ERROR_CODE CompositionOffsetAtom::GetTimeOffsetForSampleNumber(uint32 aSampleNum, uint32& aTimeOffset)
{
    uint32 currSample = 0;
    uint32 currEC = 0;
    MP4_ERROR_CODE retval = DEFAULT_ERROR;
    if (iMarkerTableCreation == true)
    {
        uint32 MT_EC = aSampleNum / (MT_SAMPLECOUNT_INCREMENT - 1); //where MT_SAMPLECOUNT_INCREMENT is the granuality of sample separation in Marker Table

        if (MT_EC > ((_iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT) - 1))
        {
            //boundary check, MT_EC valid value will always be between 0 to (_samples_count/MT_SAMPLECOUNT_INCREMENT)-1
            MT_EC = (_iTotalNumSamplesInTrack  / MT_SAMPLECOUNT_INCREMENT) - 1;
        }
        //assign the last marker entry count created till now to look for sample from this location onwards instead of from start
        if (MT_EC > MT_Counter)
            MT_EC = MT_Counter;

        while ((aSampleNum < MT_SampleCount[MT_EC]) && (MT_EC > 0))
        {
            //This check was put keeping in mind that it may happen (due to rounding off error),
            //that we choose a MT_EC greater than desired. So to avoid such a scenario.
            MT_EC = MT_EC - 1;
            currSample = MT_SampleCount[MT_EC];
            currEC = MT_EntryCount[MT_EC];
        }

        currSample = MT_SampleCount[MT_EC];
        currEC = MT_EntryCount[MT_EC];

        GetTimeOffsetFromMT(aSampleNum, currEC, currSample, aTimeOffset);
        retval = EVERYTHING_FINE;
    }
    else
    {
        if ((_psampleOffsetVec == NULL) ||
                (_psampleCountVec == NULL) ||
                (_entryCount == 0))
        {
            return retval;
        }

        uint32 sampleCount = 0;

        for (uint32 i = 0; i < _entryCount; i++)
        {
            if (_parsing_mode == 1)
                CheckAndParseEntry(i);

            if (aSampleNum < (sampleCount + _psampleCountVec[i%_stbl_buff_size]))
            { // Sample aSampleNum within current entry

                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForSampleaSampleNumber- Time StampOffset = %d", _psampleOffsetVec[i%_stbl_buff_size]));
                aTimeOffset = _psampleOffsetVec[i%_stbl_buff_size];
                retval = EVERYTHING_FINE;
                break;
            }
            else
            {
                sampleCount += _psampleCountVec[i%_stbl_buff_size];
            }
        }
    }
    return retval;
}
MP4_ERROR_CODE
SampleToChunkAtom::getChunkNumberForSamplePeek(uint32 sampleNum, uint32& ChunkNumber)
{
    if ((_pfirstChunkVec == NULL) ||
            (_psamplesPerChunkVec == NULL))
    {
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }
    if (_parsing_mode == 1)
    {
        CheckAndParseEntry(_majorPeekIndex);
    }

    if (sampleNum < _currPeekSampleCount)
    {
        ChunkNumber = _currPeekChunk;
        return EVERYTHING_FINE;
    }
    else if (_numPeekChunksInRun > 1)
    {
        _firstPeekSampleInCurrChunk = _currPeekSampleCount;
        _currPeekSampleCount += _numPeekSamplesPerChunk;
        _currPeekChunk++;

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekChunk =%d", _currPeekChunk));

        // to handle special case, every sample is a chunk
        if (_entryCount > 1)
        {
            _numPeekChunksInRun--;
        }

        if (sampleNum < _currPeekSampleCount)
        {
            ChunkNumber = _currPeekChunk;
            return EVERYTHING_FINE;
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
            return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
        }
    }
    else if (_numPeekChunksInRun <= 1)
    {
        if (_majorPeekIndex < (int32)(_entryCount - 1))
        {
            uint32 prevNextChunk = _pfirstChunkVec[_majorPeekIndex%_stbl_buff_size];
            _numPeekSamplesPerChunk = _psamplesPerChunkVec[_majorPeekIndex%_stbl_buff_size];
            _currPeekSDI = _psampleDescriptionIndexVec[_majorPeekIndex%_stbl_buff_size];

            if (_parsing_mode == 1)
            {
                CheckAndParseEntry(_majorPeekIndex + 1);
            }

            uint32 nextfirstChunk = _pfirstChunkVec[(_majorPeekIndex+1)%_stbl_buff_size];

            _numPeekChunksInRun = nextfirstChunk - prevNextChunk;

            _majorPeekIndex++;

            _firstPeekSampleInCurrChunk = _currPeekSampleCount;
            _currPeekSampleCount    += _numPeekSamplesPerChunk;
            _currPeekChunk++;

            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekChunksInRun =%d", _numPeekChunksInRun));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _majorPeekIndex =%d", _majorPeekIndex));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));

            if (sampleNum < _currPeekSampleCount)
            {
                ChunkNumber = _currPeekChunk;
                return EVERYTHING_FINE;
            }
            else
            {
                PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
                return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
            }
        }
        else if (_majorPeekIndex == (int32)(_entryCount - 1))
        {
            _numPeekChunksInRun = 1;

            _currPeekSDI =
                _psampleDescriptionIndexVec[_majorPeekIndex%_stbl_buff_size];

            _numPeekSamplesPerChunk =
                _psamplesPerChunkVec[_majorPeekIndex%_stbl_buff_size];

            _firstPeekSampleInCurrChunk = _currPeekSampleCount;

            _currPeekSampleCount += _numPeekSamplesPerChunk;
            _currPeekChunk++;

            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _majorPeekIndex =%d", _majorPeekIndex));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _firstPeekSampleInCurrChunk =%d", _firstPeekSampleInCurrChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _currPeekSampleCount =%d", _currPeekSampleCount));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSamplePeek- _numPeekSamplesPerChunk =%d", _numPeekSamplesPerChunk));

            if (sampleNum < _currPeekSampleCount)
            {
                ChunkNumber = _currPeekChunk;
                return EVERYTHING_FINE;
            }
            else
            {
                PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSamplePeek sampleNum = %d", sampleNum));
                return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
            }
        }
        else
        {
            return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
        }
    }

    return READ_SAMPLE_TO_CHUNK_ATOM_FAILED; // Should never get here
}
int32
SampleToChunkAtom::resetStateVariables(uint32 sampleNum)
{
    _majorGetIndex = 0;
    _currGetChunk = -1;
    _numGetChunksInRun = 0;
    _currGetSampleCount  = 0;
    _firstGetSampleInCurrChunk = 0;
    _numGetSamplesPerChunk = 0;
    _currGetSDI = 0;

    _majorPeekIndex = 0;
    _currPeekChunk = -1;
    _numPeekChunksInRun = 0;
    _currPeekSampleCount  = 0;
    _firstPeekSampleInCurrChunk = 0;
    _numPeekSamplesPerChunk = 0;
    _currPeekSDI = 0;

    if ((_pfirstChunkVec == NULL) ||
            (_psamplesPerChunkVec == NULL))
    {
        return DEFAULT_ERROR;
    }

    uint32 sampleCount = 0;

    for (uint32 i = 0; i < _entryCount; i++)
    {
        uint32 chunkNum = 0;
        uint32 samplesPerChunkInRun = 0;

        if (_parsing_mode == 1)
        {
            CheckAndParseEntry(i + 1);
        }

        chunkNum = _pfirstChunkVec[i%_stbl_buff_size];
        samplesPerChunkInRun = _psamplesPerChunkVec[i%_stbl_buff_size];

        if ((i + 1) < _entryCount)
        {
            uint32 nextChunkNum = _pfirstChunkVec[(int32)(i+1)%_stbl_buff_size];
            uint32 numChunksInRun = nextChunkNum - chunkNum;
            uint32 count = sampleCount + samplesPerChunkInRun * numChunksInRun;

            if (count < sampleNum)
            {
                // Haven't found chunk yet - running count still less than sampleNum
                sampleCount = count;
                continue;
            }
            else
            {
                _numGetChunksInRun = numChunksInRun;

                // Found run of chunks in which sample lies - now find actual chunk
                for (int32 j = 0; j < (int32)numChunksInRun; j++)
                {
                    //  samples for jth chunk
                    _firstGetSampleInCurrChunk = sampleCount;
                    _numGetSamplesPerChunk = samplesPerChunkInRun;
                    sampleCount += samplesPerChunkInRun;

                    if (sampleNum < sampleCount)
                    {
                        _majorGetIndex = i;
                        _numChunksInRun = numChunksInRun;
                        _currGetSampleCount = sampleCount;
                        _currGetChunk =  chunkNum + j;
                        _currGetSDI =
                            _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];

                        goto END_OF_RESET;
                    }
                    _numGetChunksInRun--;
                }
            }
        }
        else
        {
            // Last run of chunks - simply find specific chunk
            int k = 0;
            while (sampleNum >= sampleCount)
            {
                // Continue until find chunk number - we do not know how many chunks are in
                // this final run so keep going til we find a number
                _firstGetSampleInCurrChunk = sampleCount;
                _numGetSamplesPerChunk = samplesPerChunkInRun;

                sampleCount += samplesPerChunkInRun;

                if (sampleNum < sampleCount)
                {
                    // Found specific chunk
                    _majorGetIndex = i;
                    _numGetChunksInRun = 1;
                    _numChunksInRun = _numGetChunksInRun;
                    _currGetSampleCount = sampleCount;
                    _currGetChunk =  chunkNum + k;
                    _currGetSDI =
                        _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];

                    goto END_OF_RESET;
                    // Return ith chunk in run
                    // Since we do not actually know how many chunk are in this last run,
                    // the chunkNum that is returned may not be a valid chunk!
                    // This is handled in the exception handling in the chunkOffset atom
                }
                k++;
            }
        }
    }

    return DEFAULT_ERROR; // Should never get here

END_OF_RESET:
    {
        if (_majorGetIndex < (int32)(_entryCount - 1))
        {
            _majorGetIndex++;
        }
        _majorPeekIndex = _majorGetIndex;
        _currPeekChunk = _currGetChunk;
        _numPeekChunksInRun = _numGetChunksInRun;
        _currPeekSampleCount  = _currGetSampleCount;
        _firstPeekSampleInCurrChunk = _firstGetSampleInCurrChunk;
        _numPeekSamplesPerChunk = _numGetSamplesPerChunk;
        _currPeekSDI = _currGetSDI;

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _majorPeekIndex = _majorGetIndex =%d", _majorPeekIndex));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _currPeekChunk = _currGetChunk =%d", _currPeekChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekChunksInRun = _numGetChunksInRun = %d", _numPeekChunksInRun));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _currPeekSampleCount = _currGetSampleCount = %d", _currPeekSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _firstPeekSampleInCurrChunk = _firstGetSampleInCurrChunk = %d", _firstPeekSampleInCurrChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekSamplesPerChunk = _numGetSamplesPerChunk = %d", _numPeekSamplesPerChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::resetStateVariables- _numPeekSamplesPerChunk = _currGetSDI = %d", _currPeekSDI));

        return (EVERYTHING_FINE);
    }
}
// Returns the chunk number for the given sample number
uint32
SampleToChunkAtom::getChunkNumberForSampleGet(uint32 sampleNum)
{
    if ((_pfirstChunkVec == NULL) ||
            (_psamplesPerChunkVec == NULL))
    {
        return (uint32)PV_ERROR;
    }

    if (_parsing_mode == 1)
    {
        CheckAndParseEntry(_majorGetIndex);
    }

    if (sampleNum < _currGetSampleCount)
    {
        return (_currGetChunk);
    }
    else if (_numGetChunksInRun > 1)
    {
        _firstGetSampleInCurrChunk = _currGetSampleCount;
        _currGetSampleCount += _numGetSamplesPerChunk;
        _currGetChunk++;

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _firstGetSampleInCurrChunk =%d", _firstGetSampleInCurrChunk));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));

        // to handle special case, every sample is a chunk
        if (_entryCount > 1)
        {
            _numGetChunksInRun--;
        }

        if (sampleNum < _currGetSampleCount)
        {
            return (_currGetChunk);
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
            return (uint32)PV_ERROR;
        }
    }
    else if (_numGetChunksInRun <= 1)
    {
        if (_majorGetIndex < (int32)(_entryCount - 1))
        {
            uint32 prevFirstChunk = _pfirstChunkVec[_majorGetIndex%_stbl_buff_size];
            _numGetSamplesPerChunk = _psamplesPerChunkVec[_majorGetIndex%_stbl_buff_size];
            _currGetSDI = _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];

            if (_parsing_mode == 1)
            {
                CheckAndParseEntry(_majorGetIndex + 1);
            }

            uint32 nextFirstChunk = _pfirstChunkVec[(_majorGetIndex+1)%_stbl_buff_size];
            _numGetChunksInRun = nextFirstChunk - prevFirstChunk;
            _numChunksInRun = _numGetChunksInRun;


            _majorGetIndex++;
            _firstGetSampleInCurrChunk = _currGetSampleCount;
            _currGetSampleCount    += _numGetSamplesPerChunk;
            _currGetChunk++;

            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetChunksInRun =%d", _numGetChunksInRun));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetSamplesPerChunk =%d", _numGetSamplesPerChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _majorGetIndex =%d", _majorGetIndex));

            if (sampleNum < _currGetSampleCount)
            {
                return (_currGetChunk);
            }
            else
            {
                PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
                return (uint32)PV_ERROR;
            }
        }
        else if (_majorGetIndex == (int32)(_entryCount - 1))
        {
            // Last run of chunks
            _numGetChunksInRun = 1;

            _numChunksInRun = _numGetChunksInRun;

            _currGetSDI = _psampleDescriptionIndexVec[_majorGetIndex%_stbl_buff_size];

            _numGetSamplesPerChunk =
                _psamplesPerChunkVec[_majorGetIndex%_stbl_buff_size];

            _firstGetSampleInCurrChunk = _currGetSampleCount;

            _currGetSampleCount += _numGetSamplesPerChunk;
            _currGetChunk++;

            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _numGetSamplesPerChunk =%d", _firstGetSampleInCurrChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _firstGetSampleInCurrChunk =%d", _firstGetSampleInCurrChunk));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetSampleCount =%d", _currGetSampleCount));
            PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "SampleToChunkAtom::getChunkNumberForSampleGet- _currGetChunk =%d", _currGetChunk));

            if (sampleNum < _currGetSampleCount)
            {
                return (_currGetChunk);
            }
            else
            {
                PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet sampleNum= %d", sampleNum));
                return (uint32)PV_ERROR;
            }
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getChunkNumberForSampleGet _majorGetIndex = %d _entryCount= %d", _majorGetIndex, _entryCount));
            return (uint32)PV_ERROR;
        }
    }

    return (uint32)PV_ERROR; // Should never get here
}
TrackFragmentRunAtom ::TrackFragmentRunAtom(MP4_FF_FILE *fp, uint32 size, uint32 type,
        uint32 baseDataOffset,
        uint32 &currentTrunOffset,
        uint32 &offset,
        uint64 trackDuration,
        bool bdo_present,
        bool &trunParsingCompleted,
        uint32 &countOfTrunsParsed)
        : FullAtom(fp, size, type)
{
    OSCL_UNUSED_ARG(type);
    _data_offset = 0;
    _sample_count = 0;
    _first_sample_flags = 0;
    _sampleTimeStamp = trackDuration;
    uint32 tr_flag = getFlags();
    _trun_start_offset  = currentTrunOffset;
    _samplesToBeParsed = 0;
    _partialTrunOffset = 0;

    iLogger = PVLogger::GetLoggerObject("mp4ffparser");
    iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
    iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRunAtom ::TrackFragmentRunAtom In"));
    if (_success)
    {
        if (!AtomUtils::read32(fp, _sample_count))
        {
            _success = false;
            _mp4ErrorCode = READ_TRACK_FRAGMENT_RUN_ATOM_FAILED;
            return;
        }

        if (tr_flag & 0x000001)
        {
            if (!AtomUtils::read32(fp, _data_offset))
            {
                _success = false;
                _mp4ErrorCode = READ_TRACK_FRAGMENT_RUN_ATOM_FAILED;
                return;
            }
            _trun_start_offset = baseDataOffset;
            _trun_start_offset += _data_offset;
        }
        else if (bdo_present)
        {
        }
        else
        {
            _trun_start_offset += offset;
        }

        if (tr_flag & 0x000004)
        {
            if (!AtomUtils::read32(fp, _first_sample_flags))
            {
                _success = false;
                _mp4ErrorCode = READ_TRACK_FRAGMENT_RUN_ATOM_FAILED;
                return;
            }
        }

        if (_sample_count > 0)
        {
            PV_MP4_FF_NEW(fp->auditCB, _pTFrunSampleTableVecType, (), _pTFrunSampleTable);
            _pTFrunSampleTable->reserve(_sample_count);
            _samplesToBeParsed = _sample_count;
        }

        if ((countOfTrunsParsed > COUNT_OF_TRUNS_PARSED_THRESHOLD) && (_sample_count > 25))
        {
            if (trunParsingCompleted)
            {
                trunParsingCompleted = false;
                _samplesToBeParsed = _sample_count / 2;
                if (_sample_count % 2 != 0)
                {
                    _samplesToBeParsed += 1;
                }
            }
            else
            {
                trunParsingCompleted = true;
                _samplesToBeParsed = _sample_count - _samplesToBeParsed;
            }
        }

        uint32 sigmaSampleSize = 0;
        uint32 sample_offset = _trun_start_offset;
        for (uint32 idx = 0; idx < _samplesToBeParsed ; idx++)
        {
            TFrunSampleTable *pTFrunSampleTable = NULL;
            PV_MP4_FF_NEW(fp->auditCB, TFrunSampleTable, (fp, tr_flag, sample_offset, _sampleTimeStamp), pTFrunSampleTable);
            _pTFrunSampleTable->push_back(pTFrunSampleTable);
            if (pTFrunSampleTable != NULL)
            {
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Track Fragment Run=>Sample Number\t\t\t=%d", idx));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Track Fragment Run=>Sample Offset\t\t\t=%d", sample_offset));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Track Fragment Run=>Sample Sample Size\t\t=%d", pTFrunSampleTable->_sample_size));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Track Fragment Run=>Sample Ts\t\t\t=%u", _sampleTimeStamp));
                sample_offset += pTFrunSampleTable->_sample_size;
                sigmaSampleSize += pTFrunSampleTable->_sample_size;
                _sampleTimeStamp += pTFrunSampleTable->_sample_duration;

            }
        }
        offset = sigmaSampleSize;
        currentTrunOffset = _trun_start_offset;
        _partialTrunOffset = sample_offset;

        if (trunParsingCompleted)
        {
            countOfTrunsParsed++;
        }

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "###################################"));

    }
TrackFragmentRandomAccessAtom ::TrackFragmentRandomAccessAtom(MP4_FF_FILE *fp, uint32 size, uint32 type)
        : FullAtom(fp, size, type)
{
    OSCL_UNUSED_ARG(type);
    _entry_count = 0;
    _trackId = 0;
    _length_size_of_traf_num = 0;
    _length_size_of_trun_num = 0;
    _length_size_of_sample_num = 0;
    _pTFRAEntriesVec = NULL;
    const uint32 version = getVersion();

    iLogger = PVLogger::GetLoggerObject("mp4ffparser");
    iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
    iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");

    if (_success)
    {
        PV_MP4_FF_NEW(fp->auditCB, TFRAEntriesVecType, (), _pTFRAEntriesVec);

        if (!AtomUtils::read32(fp, _trackId))
        {
            _success = false;
            _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
            return;
        }

        if (!AtomUtils::read32(fp, _reserved))
        {
            _success = false;
            _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
            return;
        }
        _length_size_of_traf_num = OSCL_STATIC_CAST(uint8, (_reserved & 0x00000003));
        _length_size_of_trun_num = OSCL_STATIC_CAST(uint8, ((_reserved >> 2) & 0x00000003));
        _length_size_of_sample_num = OSCL_STATIC_CAST(uint8, (((_reserved >> 4) & 0x00000003)));

        if (!AtomUtils::read32(fp, _entry_count))
        {
            _success = false;
            _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
            return;
        }

        for (uint32 idx = 0; idx < _entry_count ; idx++)
        {
            TFRAEntries *pTFRAEntries = NULL;
            PV_MP4_FF_NEW(fp->auditCB, TFRAEntries, (fp, version, _length_size_of_traf_num,
                          _length_size_of_trun_num,
                          _length_size_of_sample_num),
                          pTFRAEntries);
            if (pTFRAEntries)
            {
                _pTFRAEntriesVec->push_back(pTFRAEntries);
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRandom Access Point _sample_number[%u] =%u", idx, pTFRAEntries->GetSampleNumber()));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRandom Access Point TimeStamp    [%u] =%u", idx, pTFRAEntries->getTimeStamp()));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRandom Access Point MoofOffset    [%u] =%u", idx, pTFRAEntries->getTimeMoofOffset()));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRandom Access Point _traf_number    [%u] =%u", idx, pTFRAEntries->GetTrafNumber()));
                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TrackFragmentRandom Access Point _trun_number  [%u] =%u", idx, pTFRAEntries->GetTrunNumber()));
            }
            else
            {
                _success = false;
                _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
                return;
            }
        }
    }
}
// Constructor
TrackFragmentAtom::TrackFragmentAtom(MP4_FF_FILE *fp,
                                     uint32 &size,
                                     uint32 type,
                                     uint32 movieFragmentCurrentOffset,
                                     uint32 movieFragmentBaseOffset,
                                     uint32 moofSize,
                                     TrackDurationContainer *trackDurationContainer,
                                     Oscl_Vector<TrackExtendsAtom*, OsclMemAllocator> *trackExtendAtomVec,
                                     bool &parseTrafCompletely,
                                     bool &trafParsingCompleted,
                                     uint32 &countOfTrunsParsed)
        : Atom(fp, size, type)
{
    OSCL_UNUSED_ARG(movieFragmentCurrentOffset);

    _pTrackFragmentHeaderAtom       = NULL;
    _pTrackFragmentRunAtom          = NULL;
    _pinput = NULL;
    _commonFilePtr = NULL;
    _fileSize = 0;
    _currentTrackFragmentRunSampleNumber = 0;
    _currentPlaybackSampleTimestamp = 0;
    _movieFragmentOffset = 0;
    _prevSampleOffset = 0;
    _trackEndDuration = 0;
    _startTrackFragmentTSOffset = 0;
    _pFragmentptrOffsetVec = NULL;
    _peekPlaybackSampleNumber = 0;
    _default_duration = 0;
    _use_default_duratoin = false;
    _pTrackDurationContainer = trackDurationContainer;

    tf_flags = 0;
    trun_offset = 0;

    trunParsingCompleted = true;

    iLogger = PVLogger::GetLoggerObject("mp4ffparser_traf");
    iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats_traf");
    iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata_traf");
    OsclAny*ptr = oscl_malloc(sizeof(MP4_FF_FILE));
    if (ptr == NULL)
    {
        _success = false;
        _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
        return;
    }
    _pinput = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE(*fp));

    _pinput->_fileServSession = fp->_fileServSession;
    _pinput->_pvfile.SetCPM(fp->_pvfile.GetCPM());
    _pinput->_fileSize = fp->_fileSize;
    _pinput->_pvfile.Copy(fp->_pvfile);

    uint32 trun_start = 0;
    uint32 count = size - DEFAULT_ATOM_SIZE;

    uint32 _movieFragmentBaseOffset = movieFragmentBaseOffset - DEFAULT_ATOM_SIZE;
    bool bdo_present = false;
    uint32 base_data_offset = _movieFragmentBaseOffset;
    trackId = 0;
    trun_offset = moofSize + DEFAULT_ATOM_SIZE;

    if (_success)
    {
        PV_MP4_FF_NEW(fp->auditCB, trackFragmentRunAtomVecType, (), _pTrackFragmentRunAtomVec);
        while (count > 0)
        {
            uint32 atomType = UNKNOWN_ATOM;
            uint32 atomSize = 0;
            AtomUtils::getNextAtomType(fp, atomSize, atomType);

            if (atomType == TRACK_FRAGMENT_HEADER_ATOM)
            {
                if (_pTrackFragmentHeaderAtom == NULL)
                {
                    PV_MP4_FF_NEW(fp->auditCB, TrackFragmentHeaderAtom, (fp, atomSize, atomType), _pTrackFragmentHeaderAtom);
                    if (!_pTrackFragmentHeaderAtom->MP4Success())
                    {
                        _success = false;
                        _mp4ErrorCode = READ_MOVIE_EXTENDS_HEADER_FAILED;
                        return;
                    }
                    count -= _pTrackFragmentHeaderAtom->getSize();
                    trackId = _pTrackFragmentHeaderAtom->getTrackId();
                    tf_flags = _pTrackFragmentHeaderAtom->getFlags();
                    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "@@@@@@@@@@@@@@@****** Track ID= %d ********@@@@@@@@@@@@@@@@", trackId));
                    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "#### tf_flag =0x%x######", tf_flags));

                    if (tf_flags & 0x000001)
                    {
                        uint64 bdo = _pTrackFragmentHeaderAtom->getBaseDataOffset();
                        base_data_offset = Oscl_Int64_Utils::get_uint64_lower32(bdo);
                        bdo_present = true;
                    }
                    else
                        base_data_offset = _movieFragmentBaseOffset;

                    trun_start = base_data_offset;
                    if (trackDurationContainer != NULL)
                    {
                        for (int32 i = 0; i < trackDurationContainer->getNumTrackInfoVec(); i++)
                        {
                            TrackDurationInfo* trackInfo = trackDurationContainer->getTrackdurationInfoAt(i);
                            if (trackInfo->trackId == trackId)
                            {
                                _trackEndDuration = trackInfo->trackDuration;
                                _startTrackFragmentTSOffset = _trackEndDuration;
                            }
                        }
                    }
                }
                else
                {
                    //duplicate atom
                    count -= atomSize;
                    atomSize -= DEFAULT_ATOM_SIZE;
                    AtomUtils::seekFromCurrPos(fp, atomSize);
                }
            }
            else if (atomType == TRACK_FRAGMENT_RUN_ATOM)
            {
                uint32 trunsParsed = countOfTrunsParsed;
                if (countOfTrunsParsed > COUNT_OF_TRUNS_PARSED_THRESHOLD)
                {
                    countOfTrunsParsed = COUNT_OF_TRUNS_PARSED_THRESHOLD;
                }
                // here we want parser to parse complete TRUN atom.

                PV_MP4_FF_NEW(fp->auditCB, TrackFragmentRunAtom, (fp, atomSize, atomType,
                              base_data_offset,
                              trun_start,
                              trun_offset,
                              _trackEndDuration,
                              bdo_present,
                              trunParsingCompleted,
                              countOfTrunsParsed),
                              _pTrackFragmentRunAtom);

                countOfTrunsParsed = trunsParsed + 1;

                if (!_pTrackFragmentRunAtom->MP4Success())
                {
                    _success = false;
                    _mp4ErrorCode = READ_TRACK_EXTENDS_ATOM_FAILED;
                    return;
                }
                bdo_present = false;
                count -= _pTrackFragmentRunAtom->getSize();

                size = count;
                uint32 trunFlags = _pTrackFragmentRunAtom->getFlags();
                if (!(trunFlags & 0x000100))
                {
                    _use_default_duratoin = true;
                    if (tf_flags & 0x000008)
                    {
                        _default_duration = _pTrackFragmentHeaderAtom->getDefaultSampleDuration();
                        _pTrackFragmentRunAtom->setDefaultDuration(_default_duration);
                    }
                    else
                    {
                        for (uint32 idx = 0; idx < trackExtendAtomVec->size(); idx++)
                        {
                            TrackExtendsAtom* pTrackExtendAtom = (*trackExtendAtomVec)[idx];
                            uint32 id = pTrackExtendAtom->getTrackId();
                            if (id == trackId)
                            {
                                uint32 trexDefaultDuration = pTrackExtendAtom->getDefaultSampleDuration();
                                _default_duration = trexDefaultDuration;
                                _pTrackFragmentRunAtom->setDefaultDuration(trexDefaultDuration);
                            }
                        }
                    }
                }
                if (!(trunFlags & 0x000200))
                {
                    if (tf_flags & 0x000010)
                        _pTrackFragmentRunAtom->setDefaultSampleSize(_pTrackFragmentHeaderAtom->getDefaultSampleSize(), trun_offset);
                    else
                    {
                        for (uint32 idx = 0; idx < trackExtendAtomVec->size(); idx++)
                        {
                            TrackExtendsAtom* pTrackExtendAtom = (*trackExtendAtomVec)[idx];
                            uint32 id = pTrackExtendAtom->getTrackId();
                            if (id == trackId)
                            {
                                uint32 trexDefaultSampleSize = pTrackExtendAtom->getDefaultSampleSize();
                                _pTrackFragmentRunAtom->setDefaultSampleSize(trexDefaultSampleSize, trun_offset);
                            }
                        }
                    }
                }
                _pTrackFragmentRunAtomVec->push_back(_pTrackFragmentRunAtom);
                _trackEndDuration = _pTrackFragmentRunAtom->GetSampleTimeStamp();

                PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "****** tr_flag =0x%x ********", trunFlags));
                if (!parseTrafCompletely)
                {
                    trafParsingCompleted = false;
                    uint64 duration = _trackEndDuration;
                    trackDurationContainer->updateTrackDurationForTrackId(trackId, duration);
                    break;
                }
            }
            else
            {
                count -= atomSize;
                atomSize -= DEFAULT_ATOM_SIZE;
                AtomUtils::seekFromCurrPos(fp, atomSize);
            }
            uint64 track_duration = _trackEndDuration;
            trackDurationContainer->updateTrackDurationForTrackId(trackId, track_duration);
            trafParsingCompleted = true;
        }
    }
    else
    {