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 ¤tTrunOffset, 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 {