void CompositionOffsetAtom::CheckAndParseEntry(uint32 i) { if (i >= _parsed_entry_cnt) { ParseEntryUnit(i); } else { uint32 entryLoc = i / _stbl_buff_size; if (_curr_buff_number != entryLoc) { _parsed_entry_cnt = entryLoc * _stbl_buff_size; while (_parsed_entry_cnt <= i) ParseEntryUnit(_parsed_entry_cnt); } } }
int32 ChunkOffsetAtom::getChunkClosestToOffset(uint32 offSet, int32& index) { index = -1; if (_pchunkOffsets == NULL) { return PV_ERROR; } uint32 prevIndex = 0; for (uint32 i = 0; i < _entryCount; i++) { if (_parsingMode == 1) { if (i >= _parsed_entry_cnt) { ParseEntryUnit(i); } else { uint32 entryLoc = i / _stbl_buff_size; if (_curr_buff_number != entryLoc) { _parsed_entry_cnt = entryLoc * _stbl_buff_size; while (_parsed_entry_cnt <= i) ParseEntryUnit(_parsed_entry_cnt); } } } if ((uint32)_pchunkOffsets[i%_stbl_buff_size] < offSet) { prevIndex = i; continue; } else { index = prevIndex; return (EVERYTHING_FINE); } } return (INSUFFICIENT_DATA); }
// Returns the chunk offset for the chunk at 'index' // In this case, 'index' is the actual chunk number MP4_ERROR_CODE ChunkOffsetAtom::getChunkOffsetAt(int32 index, uint32& aChunkOffset) { if (_pchunkOffsets == NULL) { return DEFAULT_ERROR; } if (index < (int32)_entryCount) { if (_parsingMode == 1) { if ((uint32)index >= _parsed_entry_cnt) { ParseEntryUnit(index); } else { uint32 entryLoc = index / _stbl_buff_size; if (_curr_buff_number != entryLoc) { _parsed_entry_cnt = entryLoc * _stbl_buff_size; while (_parsed_entry_cnt <= (uint32)index) ParseEntryUnit(_parsed_entry_cnt); } } aChunkOffset = _pchunkOffsets[index%_stbl_buff_size]; return EVERYTHING_FINE; } else { aChunkOffset = _pchunkOffsets[index]; return EVERYTHING_FINE; } } else { return DEFAULT_ERROR; } }
// Returns the chunk offset for the chunk at 'index' // In this case, 'index' is the actual chunk number int32 ChunkOffsetAtom::getChunkOffsetAt(int32 index) { if (_pchunkOffsets == NULL) { return PV_ERROR; } if (index < (int32)_entryCount) { if (_parsingMode == 1) { if ((uint32)index >= _parsed_entry_cnt) { ParseEntryUnit(index); } else { uint32 entryLoc = index / _stbl_buff_size; if (_curr_buff_number != entryLoc) { _parsed_entry_cnt = entryLoc * _stbl_buff_size; while (_parsed_entry_cnt <= (uint32)index) ParseEntryUnit(_parsed_entry_cnt); } } return (_pchunkOffsets[index%_stbl_buff_size]); } else { return (_pchunkOffsets[index]); } } else { return PV_ERROR; } }
MP4_ERROR_CODE CompositionOffsetAtom::ResetStateVariables(uint32 sampleNum) { MP4_ERROR_CODE retval = DEFAULT_ERROR; _currGetSampleCount = 0; _currGetIndex = -1; _currGetTimeOffset = 0; _currPeekSampleCount = 0; _currPeekIndex = -1; _currPeekTimeOffset = 0; // 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; } if (_parsing_mode) { if (_parsed_entry_cnt == 0) { ParseEntryUnit(sampleNum); } } for (uint32 i = 0; i < _entryCount; i++) { _currPeekIndex++; _currPeekSampleCount += _psampleCountVec[i%_stbl_buff_size]; _currPeekTimeOffset = _psampleOffsetVec[i%_stbl_buff_size]; _currGetIndex++; _currGetSampleCount += _psampleCountVec[i%_stbl_buff_size]; _currGetTimeOffset = _psampleOffsetVec[i%_stbl_buff_size]; if (sampleNum <= _currPeekSampleCount) { retval = EVERYTHING_FINE; break; } } // Went past end of list - not a valid sample number return retval; }
// 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)); } } }