MP4_ERROR_CODE TimeToSampleAtom::GetSampleCountAt(uint32 aIndex, uint32& aCount)
{
    MP4_ERROR_CODE retval = READ_FAILED;
    if ((aIndex < _entryCount) && _psampleCountVec)
    {
        if (_parsing_mode == 1)
            CheckAndParseEntry(aIndex);
        aCount = _psampleCountVec[aIndex%_stbl_buff_size];
        retval = EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>TimeToSampleAtom::getSampleCountAt aIndex = %d", aIndex));
    }
    return retval;
}
// Return sample offset at index
MP4_ERROR_CODE CompositionOffsetAtom::GetTimeOffsetForSampleNumberPeek(uint32 aSampleNumber, uint32& aTimeOffset)
{
    MP4_ERROR_CODE retval = DEFAULT_ERROR;
    // 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 ((_psampleOffsetVec == NULL) ||
            (_psampleCountVec == NULL) ||
            (_entryCount == 0))
    {
        return retval;
    }

    // note that aSampleNumber is a zero based index while _currGetSampleCount is 1 based index
    if (aSampleNumber < _currPeekSampleCount)
    {
        aTimeOffset = _currPeekTimeOffset;
        retval = EVERYTHING_FINE;
    }
    else
    {
        do
        {
            _currPeekIndex++;
            if (_parsing_mode)
                CheckAndParseEntry(_currPeekIndex);

            _currPeekSampleCount += _psampleCountVec[_currPeekIndex%_stbl_buff_size];
            _currPeekTimeOffset    = _psampleOffsetVec[_currPeekIndex%_stbl_buff_size];
        }
        while (_currPeekSampleCount == 0);

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekIndex =%d", _currPeekIndex));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekSampleCount =%d", _currPeekSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekTimeOffset =%d", _currPeekTimeOffset));

        if (aSampleNumber < _currPeekSampleCount)
        {
            aTimeOffset = _currPeekTimeOffset;
            retval = EVERYTHING_FINE;
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getTimeOffsetForaSampleNumberberPeek aSampleNumber = %d", aSampleNumber));
        }
    }
    return retval;
}
// Return the number of samples  at index
MP4_ERROR_CODE CompositionOffsetAtom::GetSampleCountAt(uint32 aIndex, uint32& aSampleCount)
{
    MP4_ERROR_CODE retval = DEFAULT_ERROR;
    if ((aIndex < _entryCount) && _psampleCountVec)
    {
        if (_parsing_mode == 1)
            CheckAndParseEntry(aIndex);

        aSampleCount = _psampleCountVec[aIndex%_stbl_buff_size];
        retval = EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getSampleCountAt aIndex = %d", aIndex));
    }
    return retval;
}
// Returns the timestamp delta (ms) for the current sample given by num.  This value
// is the difference in timestamps between the sample (num) and the previous sample
// in the track.  It is implicit that sample[0] occurs at timestamp ts=0.
MP4_ERROR_CODE TimeToSampleAtom::GetTimeDeltaForSampleNumberGet(uint32 aSampleNumber, uint32& aTimeDelta)
{
    MP4_ERROR_CODE retval = READ_FAILED;
    // 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 ((NULL == _psampleDeltaVec) ||
            (NULL == _psampleCountVec) ||
            (0 == _entryCount))
    {
        return retval;
    }

    // note that sampleNum is a zero based index while _currGetSampleCount is 1 based index
    if (aSampleNumber < _currGetSampleCount)
    {
        aTimeDelta = _currGetTimeDelta;
        return EVERYTHING_FINE;
    }

    do
    {
        ++_currGetIndex;
        if (_parsing_mode)
            CheckAndParseEntry(_currGetIndex);

        _currGetSampleCount += _psampleCountVec[_currGetIndex%_stbl_buff_size];
        _currGetTimeDelta    = _psampleDeltaVec[_currGetIndex%_stbl_buff_size];
    }
    while (0 == _currGetSampleCount);

    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TimeToSampleAtom::getTimeDeltaForSampleNumberGet- _currGetIndex =%d", _currGetIndex));
    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TimeToSampleAtom::getTimeDeltaForSampleNumberGet- _currGetSampleCount =%d", _currGetSampleCount));
    PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "TimeToSampleAtom::getTimeDeltaForSampleNumberGet- _currGetTimeDelta =%d", _currGetTimeDelta));

    if (aSampleNumber < _currGetSampleCount)
    {
        aTimeDelta = _currGetTimeDelta;
        retval = EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>TimeToSampleAtom::getTimeDeltaForSampleNumberGet sampleNum = %d", aSampleNumber));
    }
    return retval;
}
int32
CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek(uint32 sampleNum)
{
    // 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 ((_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 < _currPeekSampleCount)
    {
        return (_currPeekTimeOffset);
    }
    else
    {
        do
        {
            _currPeekIndex++;
            if (_parsing_mode)
                CheckAndParseEntry(_currPeekIndex);

            _currPeekSampleCount += _psampleCountVec[_currPeekIndex%_stbl_buff_size];
            _currPeekTimeOffset    = _psampleOffsetVec[_currPeekIndex%_stbl_buff_size];
        }
        while (_currPeekSampleCount == 0);

        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekIndex =%d", _currPeekIndex));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekSampleCount =%d", _currPeekSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekTimeOffset =%d", _currPeekTimeOffset));

        if (sampleNum < _currPeekSampleCount)
        {
            return (_currPeekTimeOffset);
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek sampleNum = %d", sampleNum));
            return (PV_ERROR);
        }
    }
}
// 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.
MP4_ERROR_CODE CompositionOffsetAtom::GetTimeOffsetForSampleNumberGet(uint32 aSampleNum, uint32& aTimeOffset)
{
    MP4_ERROR_CODE retval = DEFAULT_ERROR;
    if ((_psampleOffsetVec == NULL) ||
            (_psampleCountVec == NULL) ||
            (_entryCount == 0))
    {
        return retval;
    }

    // note that aSampleNum is a zero based index while _currGetSampleCount is 1 based index
    if (aSampleNum < _currGetSampleCount)
    {
        aTimeOffset = _currGetTimeOffset;
        retval = EVERYTHING_FINE;
    }
    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::getTimeOffsetForaSampleNumberGet- _currGetIndex =%d", _currGetIndex));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForaSampleNumberGet- _currGetSampleCount =%d", _currGetSampleCount));
        PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForaSampleNumberGet- _currGetTimeOffset =%d", _currGetTimeOffset));

        if (aSampleNum < _currGetSampleCount)
        {
            aTimeOffset = _currGetTimeOffset;
            retval = EVERYTHING_FINE;
        }
        else
        {
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>TimeToSampleAtom::getTimeDeltaForaSampleNumberGet aSampleNum = %d", aSampleNum));
        }
    }
    return retval;
}
uint32
SampleToChunkAtom::getSDIndexGet() const
{
    if (_psampleDescriptionIndexVec == NULL)
    {
        return (uint32)PV_ERROR;
    }

    if (_currGetSDI != 0)
    {
        return (_currGetSDI);
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndexGet _currGetSDI = %d", _currGetSDI));
        return (uint32) PV_ERROR;
    }
}
// Returns the samples description index for the samples in all the chunks in run[index]
uint32
SampleToChunkAtom::getSDIndex() const
{
    if (_psampleDescriptionIndexVec == NULL)
    {
        return (uint32)PV_ERROR;
    }

    if (_Index < _entryCount)
    {
        return (_psampleDescriptionIndexVec[_Index%_stbl_buff_size]);
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndex"));
        return (uint32) PV_ERROR;
    }
}
MP4_ERROR_CODE
SampleToChunkAtom::getSDIndexGet(uint32 &SDIndex) const
{
    if (_psampleDescriptionIndexVec == NULL)
    {
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }

    if (_currGetSDI != 0)
    {
        SDIndex = (_currGetSDI);
        return EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndexGet _currGetSDI = %d", _currGetSDI));
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }
}
// Returns the samples description index for the samples in all the chunks in run[index]
MP4_ERROR_CODE
SampleToChunkAtom::getSDIndex(uint32& SDIndex) const
{
    if (_psampleDescriptionIndexVec == NULL)
    {
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }

    if (_Index < _entryCount)
    {
        SDIndex = (_psampleDescriptionIndexVec[_Index%_stbl_buff_size]);
        return EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR=>SampleToChunkAtom::getSDIndex"));
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }
}
// 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);
        }
    }
}
// Return sample offset at index
int32
CompositionOffsetAtom::getSampleOffsetAt(int32 index)
{
    if (_psampleOffsetVec == NULL)
    {
        return PV_ERROR;
    }

    if (index < (int32)_entryCount)
    {
        if (_parsing_mode == 1)
            CheckAndParseEntry(index);

        return (int32)(_psampleOffsetVec[index%_stbl_buff_size]);
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getSampleOffsetAt index = %d", index));
        return PV_ERROR;
    }
}
// Returns the chunk number of the first chunk in run[index]
int32
SampleToChunkAtom::getFirstChunkAt(uint32 index)
{
    if (_pfirstChunkVec == NULL)
    {
        return PV_ERROR;
    }
    if (index < _entryCount)
    {
        if (_parsing_mode == 1)
        {
            CheckAndParseEntry(index);
        }
        return (_pfirstChunkVec[index%_stbl_buff_size]);
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::getFirstChunkAt index = %d", index));
        return PV_ERROR;
    }
}
// Returns the chunk number of the first chunk in run[index]
MP4_ERROR_CODE
SampleToChunkAtom::getFirstChunkAt(uint32 index, int32& pos)
{
    if (_pfirstChunkVec == NULL)
    {
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }
    if (index < _entryCount)
    {
        if (_parsing_mode == 1)
        {
            CheckAndParseEntry(index);
        }
        pos = (_pfirstChunkVec[index%_stbl_buff_size]);
        return EVERYTHING_FINE;
    }
    else
    {
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::getFirstChunkAt index = %d", index));
        return READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
    }
}
Exemple #15
0
MetaDataAtom::MetaDataAtom(MP4_FF_FILE *fp, uint32 size, uint32 type): Atom(fp, size, type)
{
    _success = true;

    // User ilst Data
    _pITunesILSTAtom = NULL;
    _pHdlrAtom = NULL;
    int32 _count = _size - getDefaultSize();

    uint32 data_32_hdlr = 0;
    iLogger = PVLogger::GetLoggerObject("mp4ffparser");

    // Skip first 4 bytes.
    if (!AtomUtils::read32(fp, data_32_hdlr))
    {
        _success = false;
        _mp4ErrorCode = READ_META_DATA_FAILED;
        PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>MetaDataAtom::MetaDataAtom READ_META_DATA_FAILED   if(!AtomUtils::read32(fp,data_32_hdlr)))"));
        return;
    }
    _count -= 4;

    while (_count > 0)
    {
        uint32 atomType = UNKNOWN_ATOM;
        uint32 atomSize = 0;

        uint32 currPtr = AtomUtils::getCurrentFilePosition(fp);
        AtomUtils::getNextAtomType(fp, atomSize, atomType);

        // Validate atomSize
        if (atomSize < DEFAULT_ATOM_SIZE)
        {
            _success = false;
            _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
            break;
        }

        if ((atomType == FREE_SPACE_ATOM) || (atomType == UNKNOWN_ATOM))
        {
            //skip the atom
            if (_count < atomSize)
            {
                AtomUtils::seekFromStart(fp, currPtr);
                AtomUtils::seekFromCurrPos(fp, _count);
                _count = 0;
                return;
            }

            _count -= atomSize;
            atomSize -= DEFAULT_ATOM_SIZE;
            AtomUtils::seekFromCurrPos(fp, atomSize);
        }
        else if (atomType == HANDLER_ATOM)
        {
            PV_MP4_FF_NEW(fp->auditCB, HandlerAtom, (fp, atomSize, atomType), _pHdlrAtom);

            if (!_pHdlrAtom->MP4Success())
            {
                AtomUtils::seekFromStart(fp, currPtr);
                AtomUtils::seekFromCurrPos(fp, atomSize);
                PV_MP4_FF_DELETE(NULL, HandlerAtom, _pHdlrAtom);
                _pHdlrAtom = NULL;
                _count -= atomSize;
            }

            if (_pHdlrAtom != NULL)
            {
                if (_pHdlrAtom->getHandlerType() != ITUNES_MDIRAPPL_HDLR_PART1)
                {
                    // Skip the parsing...
                    fp->_pvfile.Seek(atomSize, Oscl_File::SEEKCUR);
                    return;
                }
                _count -= _pHdlrAtom->getSize();
            }
        }
        // Read the ilst Atom
        else if (atomType == ITUNES_ILST_ATOM)
        {
            PV_MP4_FF_NEW(fp->auditCB, ITunesILSTAtom, (fp, atomSize, atomType), _pITunesILSTAtom);

            if (!_pITunesILSTAtom->MP4Success())
            {
                AtomUtils::seekFromStart(fp, currPtr);
                AtomUtils::seekFromCurrPos(fp, atomSize);
                PV_MP4_FF_DELETE(NULL, ITunesILSTAtom, _pITunesILSTAtom);
                _pITunesILSTAtom = NULL;
                _count -= atomSize;
            }
            else
                _count -= _pITunesILSTAtom->getSize();
        }
        else
        {
            //Unexpected atomType. Flag an error.
            _success = false;
            _mp4ErrorCode = READ_META_DATA_FAILED;
            break;
        }
    }
}
// Stream-in ctor
// Create and return a new SampleToChunkAtom by reading in from an ifstream
SampleToChunkAtom::SampleToChunkAtom(MP4_FF_FILE *fp, uint32 size, uint32 type, OSCL_wString& filename, uint32 parsingMode)
        : FullAtom(fp, size, type)
{
    _pfirstChunkVec = NULL;
    _psamplesPerChunkVec = NULL;
    _psampleDescriptionIndexVec = NULL;

    _Index = 0;
    _numChunksInRun = 0;
    _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;

    _parsed_entry_cnt = 0;
    _fileptr = NULL;

    _stbl_buff_size = MAX_CACHED_TABLE_ENTRIES_FILE;
    _next_buff_number = 0;
    _curr_buff_number = 0;
    _curr_entry_point = 0;
    _stbl_fptr_vec = NULL;
    _parsing_mode = parsingMode;

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

    if (_success)
    {
        _currentChunkNumber = 0;
        _maxNumSamplesPerChunk = DEFAULT_MAX_NUM_SAMPLES_PER_CHUNK;
        _maxChunkDataSize = DEFAULT_MAX_CHUNK_DATA_SIZE;

        if (!AtomUtils::read32(fp, _entryCount))
        {
            _success = false;
        }
        PVMF_MP4FFPARSER_LOGPARSEDINFO((0, "SampleToChunkAtom::SampleToChunkAtom- _entryCount =%d", _entryCount));
        TOsclFileOffset dataSize = _size - (DEFAULT_FULL_ATOM_SIZE + 4);

        uint32 entrySize = (4 + 4 + 4);

        if ((TOsclFileOffset)(_entryCount*entrySize) > dataSize)
        {
            _success = false;
        }

        if (_success)
        {
            if (_entryCount > 0)
            {
                if (_parsing_mode)
                {
                    if ((_entryCount > _stbl_buff_size)) // cahce size is 4K so that optimization should work if entry_count is greater than 4K
                    {

                        uint32 fptrBuffSize = (_entryCount / _stbl_buff_size) + 1;

                        PV_MP4_FF_ARRAY_NEW(NULL, TOsclFileOffset, (fptrBuffSize), _stbl_fptr_vec);
                        if (_stbl_fptr_vec == NULL)
                        {
                            _success = false;
                            _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
                            return;
                        }

                        PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _pfirstChunkVec);
                        if (_pfirstChunkVec == NULL)
                        {
                            _success = false;
                            _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
                            return;
                        }

                        PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psamplesPerChunkVec);
                        if (_psamplesPerChunkVec == NULL)
                        {
                            _success = false;
                            _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
                            return;
                        }
                        PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psampleDescriptionIndexVec);
                        if (_psampleDescriptionIndexVec == NULL)
                        {
                            _success = false;
                            _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
                            return;
                        }

                        {
                            OsclAny* ptr = (MP4_FF_FILE *)(oscl_malloc(sizeof(MP4_FF_FILE)));
                            if (ptr == NULL)
                            {
                                _success = false;
                                _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
                                return;
                            }
                            _fileptr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE());
                            _fileptr->_fileServSession = fp->_fileServSession;
                            _fileptr->_pvfile.SetCPM(fp->_pvfile.GetCPM());
                            _fileptr->_pvfile.SetFileHandle(fp->_pvfile.iFileHandle);
                            if (AtomUtils::OpenMP4File(filename,
                                                       Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
                                                       _fileptr) != 0)
                            {
                                _success = false;
                                _mp4ErrorCode = FILE_OPEN_FAILED;
                            }

                            _fileptr->_fileSize = fp->_fileSize;
                        }
                        TOsclFileOffset _head_offset = AtomUtils::getCurrentFilePosition(fp);
                        AtomUtils::seekFromCurrPos(fp, dataSize);
                        AtomUtils::seekFromStart(_fileptr, _head_offset);

                        ParseEntryUnit(0);
                        uint32 firstsamplenum = 0;
                        resetStateVariables(firstsamplenum);

                        return;
                    }
                    else
                    {
                        _parsing_mode = 0;
                        _stbl_buff_size = _entryCount;
                    }
                }
                else
                {
                    _parsing_mode = 0;
                    _stbl_buff_size = _entryCount;
                }

                PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _pfirstChunkVec);
                PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psamplesPerChunkVec);
                PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psampleDescriptionIndexVec);

                uint32 firstChunk;
                uint32 samplesPerChunk;
                uint32 sampleDescrIndex;

                uint32 offSet = 0;

                uint32 prevFirstChunk = 0;
                uint32 j = 0;

                for (uint32 i = 0; i < _entryCount; i++)
                {
                    if (!AtomUtils::read32(fp, firstChunk))
                    {
                        _success = false;
                        break;
                    }

                    if (i == 0)
                        offSet = firstChunk;

                    if (!AtomUtils::read32(fp, samplesPerChunk))
                    {
                        _success = false;
                        break;
                    }
                    if (!AtomUtils::read32(fp, sampleDescrIndex))
                    {
                        _success = false;
                        break;
                    }

                    if (firstChunk > prevFirstChunk)
                    {
                        _pfirstChunkVec[j] = (firstChunk - offSet);
                        _psamplesPerChunkVec[j] = (samplesPerChunk);
                        _psampleDescriptionIndexVec[j] = (sampleDescrIndex);
                        prevFirstChunk = firstChunk;
                        j++;
                    }
                }
                _entryCount = j;
                uint32 firstsamplenum = 0;
                resetStateVariables(firstsamplenum);
            }
            else
            {
                _pfirstChunkVec = NULL;
                _psamplesPerChunkVec = NULL;
                _psampleDescriptionIndexVec = NULL;
            }
        }

        if (!_success)
        {
            _mp4ErrorCode = READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::SampleToChunkAtom- Read SampleToChunk Atom failed %d", _mp4ErrorCode));
        }
    }
    else
    {
        if (_mp4ErrorCode != ATOM_VERSION_NOT_SUPPORTED)
        {
            _mp4ErrorCode = READ_SAMPLE_TO_CHUNK_ATOM_FAILED;
            PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>SampleToChunkAtom::SampleToChunkAtom- Read SampleToChunk Atom failed %d", _mp4ErrorCode));
        }
    }
}
// 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
}
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
}