| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "pv_avifile_parser.h" |
| |
| |
| PVAviFileParser::PVAviFileParser(OSCL_wHeapString<OsclMemAllocator> aFileName, int32& aError, Oscl_FileServer* aFileServer, |
| PVMFCPMPluginAccessInterfaceFactory* aCPM, OsclFileHandle* aFileHandle) |
| { |
| ipFileHeader = NULL; |
| ipIdxChunk = NULL; |
| iIdxChunkPresent = false; |
| iFileSize = 0; |
| iHeaderChunkSize = 0; |
| iMovieChunkSize = 0; |
| iMovieChunkStartOffset = 0; |
| iIndxChunkSize = 0; |
| iSampleOffset = 0; |
| iTimeStampVideo = 0; |
| iTimeStampAudio = 0; |
| |
| OSCL_TRY(aError, ipFilePtr = OSCL_NEW(PVFile, ());); |
| |
| if (0 == aError) |
| { |
| ipFilePtr->SetCPM(aCPM); |
| ipFilePtr->SetFileHandle(aFileHandle); |
| |
| aError = PV_AVI_FILE_PARSER_SUCCESS; |
| |
| if (ipFilePtr->Open(aFileName.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileServer) != 0) |
| { |
| aError = PV_AVI_FILE_PARSER_FILE_OPEN_ERROR; |
| } |
| } |
| } |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::ParseFile() |
| { |
| iError = PV_AVI_FILE_PARSER_SUCCESS; |
| ipFilePtr->Seek(0, Oscl_File::SEEKSET); |
| |
| // Seek to the end to find the file size |
| uint32 filesize = 0; |
| if (ipFilePtr->Seek(0, Oscl_File::SEEKEND)) |
| { |
| iError = PV_AVI_FILE_PARSER_SEEK_ERROR; |
| return iError; |
| } |
| filesize = ipFilePtr->Tell(); |
| |
| // Seek back to the beginning |
| ipFilePtr->Seek(0, Oscl_File::SEEKSET); |
| uint32 chunkType = 0; |
| |
| if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file")); |
| return iError; |
| } |
| |
| //first chunk must be RIFF |
| if (chunkType != RIFF) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: First Chunk Must be RIFF")); |
| iError = PV_AVI_FILE_PARSER_WRONG_FILE; |
| return iError; |
| } |
| |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iFileSize, true)) |
| { |
| iError = PV_AVI_FILE_PARSER_READ_ERROR; |
| return iError; |
| } |
| |
| if ((iFileSize <= 0) || (iFileSize > filesize)) |
| { |
| iError = PV_AVI_FILE_PARSER_WRONG_SIZE; |
| return iError; |
| } |
| |
| if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file")); |
| return iError; |
| } |
| |
| //second chunk must be AVI |
| if (chunkType != AVI) |
| { |
| PVAVIFILE_LOGERROR((0, "Second Chunk Must be AVI")); |
| iError = PV_AVI_FILE_PARSER_WRONG_FILE; |
| return iError; |
| } |
| |
| uint32 bytesRead = CHUNK_SIZE; |
| uint32 listSize = 0; |
| uint32 oldChkType = chunkType; |
| |
| while (bytesRead < iFileSize) |
| { |
| oldChkType = chunkType; |
| if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| if ((PV_AVI_FILE_PARSER_UNSUPPORTED_CHUNK == iError)) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk")); |
| |
| uint32 chksz = 0; |
| if (oldChkType != LIST) |
| { |
| //get the size of unsupported chunk and skip it. |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, chksz, true)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: File Read Error")); |
| iError = PV_AVI_FILE_PARSER_READ_ERROR; |
| break; |
| } |
| |
| ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR); |
| bytesRead += chksz + CHUNK_SIZE + CHUNK_SIZE; //chunk data + chunk size + chunk type; |
| |
| } |
| else |
| { |
| //skip the entire list if not supported |
| chksz = listSize - CHUNK_SIZE ; //subtract list name already read |
| ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR); |
| bytesRead += listSize; |
| } |
| |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk skipped")); |
| iError = PV_AVI_FILE_PARSER_SUCCESS; |
| continue; |
| } |
| else |
| { |
| break; |
| } |
| } |
| bytesRead += CHUNK_SIZE; |
| |
| if (LIST == chunkType) |
| { |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, listSize, true)) |
| { |
| iError = PV_AVI_FILE_PARSER_READ_ERROR; |
| break; |
| } |
| |
| bytesRead += CHUNK_SIZE; |
| if (bytesRead > iFileSize) |
| { |
| iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| break; |
| } |
| |
| if ((listSize <= 0) || (listSize > iFileSize)) |
| { |
| iError = PV_AVI_FILE_PARSER_WRONG_SIZE; |
| break; |
| } |
| } |
| else if (HDRL == chunkType) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found File Header")); |
| |
| iHeaderChunkSize = listSize - CHUNK_SIZE; //subtract 4 bytes of chunk type |
| ipFileHeader = OSCL_NEW(PVAviFileHeader, (ipFilePtr, iHeaderChunkSize)); |
| if (ipFileHeader != NULL) |
| { |
| iError = ipFileHeader->GetStatus(); |
| if (iError != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| OSCL_DELETE(ipFileHeader); |
| ipFileHeader = NULL; |
| break; |
| } |
| } |
| bytesRead += iHeaderChunkSize; |
| if (bytesRead > iFileSize) |
| { |
| iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| break; |
| } |
| } |
| else if (MOVI == chunkType) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found MOVI Chunk")); |
| |
| iMovieChunkSize = listSize - CHUNK_SIZE; |
| iMovieChunkStartOffset = ipFilePtr->Tell(); //get movi chunk start offset. |
| iSampleOffset = iMovieChunkStartOffset; |
| ipFilePtr->Seek(iMovieChunkSize, Oscl_File::SEEKCUR); |
| |
| uint32 numStr = GetNumStreams(); |
| for (uint32 ii = 0; ii < numStr; ii++) |
| { |
| iStreamCount.push_back(ii); |
| iStreamSampleCount.push_back(0); |
| } |
| |
| bytesRead += iMovieChunkSize; |
| |
| } |
| else if (IDX1 == chunkType) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found Index Table")); |
| |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iIndxChunkSize, true)) |
| { |
| iError = PV_AVI_FILE_PARSER_READ_ERROR; |
| break; |
| } |
| |
| bytesRead += CHUNK_SIZE; |
| if (bytesRead > iFileSize) |
| { |
| iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| break; |
| } |
| |
| if ((iIndxChunkSize <= 0) || (iIndxChunkSize > iFileSize)) |
| { |
| iError = PV_AVI_FILE_PARSER_WRONG_SIZE; |
| break; |
| } |
| uint32 numStreams = GetNumStreams(); |
| ipIdxChunk = OSCL_NEW(PVAviFileIdxChunk, (ipFilePtr, iIndxChunkSize, numStreams)); |
| if (ipIdxChunk != NULL) |
| { |
| iError = ipIdxChunk->GetStatus(); |
| if (iError != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| OSCL_DELETE(ipIdxChunk); |
| ipIdxChunk = NULL; |
| break; |
| } |
| iIdxChunkPresent = true; |
| } |
| bytesRead += iIndxChunkSize; |
| } |
| else if (JUNK == chunkType) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Skip Junk data")); |
| |
| uint32 junkSize = 0; |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, junkSize, true)) |
| { |
| iError = PV_AVI_FILE_PARSER_READ_ERROR; |
| break; |
| } |
| |
| bytesRead += CHUNK_SIZE; |
| if (bytesRead > iFileSize) |
| { |
| iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| break; |
| } |
| |
| if ((junkSize <= 0) || (junkSize > iFileSize)) |
| { |
| iError = PV_AVI_FILE_PARSER_WRONG_SIZE; |
| break; |
| } |
| |
| ipFilePtr->Seek(junkSize, Oscl_File::SEEKCUR); |
| bytesRead += junkSize; |
| if (bytesRead > iFileSize) |
| { |
| iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| break; |
| } |
| } |
| else |
| { |
| iError = PV_AVI_FILE_PARSER_WRONG_CHUNK; |
| break; |
| } |
| |
| } //while (bytesRead <= iFileSize) |
| |
| return iError; |
| } |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::GetNextMediaSample(uint32& arStreamNo, uint8* aBuffer, |
| uint32& arSize, uint32& arTimeStamp) |
| { |
| if (iSampleOffset >= iFileSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset")); |
| return PV_AVI_FILE_PARSER_WRONG_OFFSET; |
| } |
| |
| if (iSampleOffset == iMovieChunkStartOffset) |
| { |
| //first Sample reset sample count. |
| for (uint32 ii = 0; ii < GetNumStreams(); ii++) |
| { |
| iStreamSampleCount[ii] = 0; |
| } |
| |
| ipFilePtr->Seek(0, Oscl_File::SEEKSET); |
| } |
| |
| uint32 CurrOff = ipFilePtr->Tell(); |
| if (CurrOff > iSampleOffset) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset")); |
| return PV_AVI_FILE_PARSER_WRONG_OFFSET; |
| } |
| |
| ipFilePtr->Seek((iSampleOffset - CurrOff), Oscl_File::SEEKCUR); |
| |
| uint32 bytesRead = 0; |
| uint32 data = 0; |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| int32 strNo = PVAviFileParserUtils::GetStreamNumber(data); |
| if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No")); |
| return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM; |
| } |
| |
| arStreamNo = strNo; |
| |
| bytesRead += CHUNK_SIZE; |
| |
| uint32 size = 0; |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| bytesRead += CHUNK_SIZE; |
| |
| if (size > arSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); |
| return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; |
| } |
| |
| arSize = size; |
| |
| if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| iSampleOffset = iSampleOffset + arSize + bytesRead; |
| |
| uint32 offsetFrmMoviChk = iSampleOffset - iMovieChunkStartOffset; |
| |
| if (offsetFrmMoviChk >= iMovieChunkSize) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached")); |
| return PV_AVI_FILE_PARSER_EOF_REACHED; |
| } |
| |
| //calculate time stamp |
| if (oscl_strstr(GetStreamMimeType(arStreamNo).get_str(), "audio")) |
| { |
| arTimeStamp = iTimeStampAudio; |
| uint32 sampleSize = GetBitsPerSample(arStreamNo); |
| sampleSize = sampleSize / BIT_COUNT8; //in bytes |
| OsclFloat samplingRate = GetFrameRate(arStreamNo); |
| if (sampleSize > 0) |
| { |
| OsclFloat sampleCount = (OsclFloat)arSize / sampleSize; |
| if (samplingRate > 0) |
| { |
| iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate); |
| } |
| } |
| } |
| else |
| { |
| if (iStreamSampleCount[arStreamNo] > 0) |
| { |
| uint32 frameDurationInms = GetFrameDuration() / 1000; |
| arTimeStamp = (iStreamSampleCount[arStreamNo] * (frameDurationInms)); |
| } |
| else |
| { |
| arTimeStamp = 0; |
| } |
| } |
| |
| iStreamSampleCount[arStreamNo] = iStreamSampleCount[arStreamNo] + 1; |
| return PV_AVI_FILE_PARSER_SUCCESS; |
| } |
| |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::GetNextStreamSampleInfo(uint32 aStreamNo, uint32& arSize, uint32& arOffset) |
| { |
| if (false == iIdxChunkPresent) |
| { |
| return PV_AVI_FILE_PARSER_NO_INDEX_CHUNK; |
| } |
| else |
| { |
| return GetStreamOffsetFromIndexTable(aStreamNo, arSize, arOffset); |
| } |
| } |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::GetNextStreamMediaSample(uint32 aStreamNo, uint8* aBuffer, |
| uint32& arSize, uint32& arTimeStamp) |
| { |
| uint32 sampleOffset = 0; |
| PV_AVI_FILE_PARSER_ERROR_TYPE error = PV_AVI_FILE_PARSER_SUCCESS; |
| |
| if (false == iIdxChunkPresent) |
| { |
| error = GetStreamOffset(aStreamNo, arSize, sampleOffset); |
| |
| if ((error != PV_AVI_FILE_PARSER_SUCCESS)) |
| { |
| if (PV_AVI_FILE_PARSER_NO_OFFSET_FOUND == error) |
| { |
| arSize = 0; |
| arTimeStamp = 0; |
| //probably EOS has been reached. |
| return PV_AVI_FILE_PARSER_EOS_REACHED; |
| } |
| else |
| { |
| return error; |
| } |
| } |
| |
| uint32 offsetFrmMoviChk = sampleOffset - iMovieChunkStartOffset; |
| if (offsetFrmMoviChk >= iMovieChunkSize) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextStreamMediaSample: EOF Reached")); |
| return PV_AVI_FILE_PARSER_EOF_REACHED; |
| } |
| } |
| else |
| { |
| error = GetStreamOffsetFromIndexTable(aStreamNo, arSize, sampleOffset); |
| if (error != PV_AVI_FILE_PARSER_SUCCESS) |
| { |
| return error; |
| } |
| } |
| |
| if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| //calculate time stamp |
| if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio")) |
| { |
| arTimeStamp = iTimeStampAudio; |
| uint32 sampleSize = GetBitsPerSample(aStreamNo); |
| sampleSize = sampleSize / BIT_COUNT8; //in bytes |
| OsclFloat samplingRate = GetFrameRate(aStreamNo); |
| if (sampleSize > 0) |
| { |
| OsclFloat sampleCount = (OsclFloat)arSize / sampleSize; |
| if (samplingRate > 0) |
| { |
| iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate); |
| } |
| } |
| } |
| else |
| { |
| if (iStreamSampleCount[aStreamNo] > 0) |
| { |
| uint32 frameDurationInms = GetFrameDuration() / 1000; |
| arTimeStamp = (iStreamSampleCount[aStreamNo] * (frameDurationInms)); |
| } |
| else |
| { |
| arTimeStamp = 0; |
| } |
| } |
| |
| iStreamSampleCount[aStreamNo] = iStreamSampleCount[aStreamNo] + 1; |
| |
| return PV_AVI_FILE_PARSER_SUCCESS; |
| } |
| |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::GetStreamOffsetFromIndexTable(uint32 aStreamNo, uint32& arSize, uint32& arOffset) |
| { |
| uint32 sampleOffset = 0; |
| |
| if (iStreamSampleCount[aStreamNo] >= ipIdxChunk->GetNumberOfSamplesInStream(aStreamNo)) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached")); |
| return PV_AVI_FILE_PARSER_EOS_REACHED; |
| } |
| |
| sampleOffset = ipIdxChunk->GetOffset(aStreamNo, iStreamSampleCount[aStreamNo]); |
| uint32 size = ipIdxChunk->GetSampleSize(aStreamNo, iStreamSampleCount[aStreamNo]); |
| |
| if (size > arSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); |
| return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; |
| } |
| |
| arSize = size; |
| |
| if (ipIdxChunk->IsOffsetFromMoviList()) |
| { |
| arOffset = iMovieChunkStartOffset + sampleOffset - CHUNK_SIZE; |
| } |
| else |
| { |
| arOffset = sampleOffset; |
| } |
| |
| arOffset += (CHUNK_SIZE + CHUNK_SIZE); //add 4 bytes each for sample type and data size param. |
| |
| if ((arOffset > iFileSize)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Size & Byte Count mismatch")); |
| return PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR; |
| } |
| |
| ipFilePtr->Seek(0, Oscl_File::SEEKSET); |
| ipFilePtr->Seek(arOffset, Oscl_File::SEEKCUR); |
| |
| return PV_AVI_FILE_PARSER_SUCCESS; |
| } |
| |
| |
| PV_AVI_FILE_PARSER_ERROR_TYPE |
| PVAviFileParser::GetStreamOffset(uint32 aStreamNo, uint32& arSampleSize, uint32& arOffset) |
| { |
| uint32 startOffset = 0; |
| arOffset = 0; |
| bool foundOffset = false; |
| |
| if (iStreamSampleOffset.size() == 0) |
| { |
| uint32 numstreams = GetNumStreams(); |
| startOffset = iMovieChunkStartOffset; |
| |
| for (uint32 ii = 0; ii < numstreams; ii++) |
| { |
| iStreamSampleOffset.push_back(startOffset); |
| } |
| } |
| else |
| { |
| startOffset = iStreamSampleOffset[aStreamNo]; |
| } |
| |
| ipFilePtr->Seek(startOffset, Oscl_File::SEEKSET); |
| uint32 currentFileOffset = startOffset; |
| |
| uint32 endOfdataPosition = iMovieChunkStartOffset + iMovieChunkSize; |
| |
| while (currentFileOffset < endOfdataPosition) |
| { |
| uint32 data = 0; |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| int32 strNo = PVAviFileParserUtils::GetStreamNumber(data); |
| if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No")); |
| return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM; |
| } |
| |
| uint32 size = 0; |
| if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true)) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error")); |
| return PV_AVI_FILE_PARSER_READ_ERROR; |
| } |
| |
| if ((uint32)strNo == aStreamNo) |
| { |
| arOffset = ipFilePtr->Tell(); |
| iStreamSampleOffset[aStreamNo] = arOffset + size; |
| if (size > arSampleSize) |
| { |
| PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size")); |
| return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY; |
| } |
| |
| arSampleSize = size; |
| foundOffset = true; |
| break; |
| } |
| else |
| { |
| ipFilePtr->Seek(size, Oscl_File::SEEKCUR); |
| foundOffset = false; |
| } |
| |
| currentFileOffset = ipFilePtr->Tell(); |
| } |
| |
| if (foundOffset) |
| { |
| return PV_AVI_FILE_PARSER_SUCCESS; |
| } |
| else |
| { |
| return PV_AVI_FILE_PARSER_NO_OFFSET_FOUND; |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVAviFileParser::Reset() |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset")); |
| |
| uint32 ii = 0; |
| for (ii = 0; ii < GetNumStreams(); ii++) |
| { |
| iStreamSampleCount[ii] = 0; |
| } |
| |
| if (iStreamSampleOffset.size() > 0) |
| { |
| for (ii = 0; ii < iStreamSampleOffset.size(); ii++) |
| { |
| iStreamSampleOffset.pop_back(); |
| } |
| } |
| |
| iSampleOffset = iMovieChunkStartOffset; |
| iTimeStampAudio = 0; |
| } |
| |
| OSCL_EXPORT_REF void PVAviFileParser::Reset(uint32 aStreamNo) |
| { |
| PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset stream")); |
| |
| iStreamSampleCount[aStreamNo] = 0; |
| |
| if (iStreamSampleOffset.size() > aStreamNo) |
| { |
| iStreamSampleOffset[aStreamNo] = iMovieChunkStartOffset; |
| } |
| |
| if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio")) |
| { |
| iTimeStampAudio = 0; |
| } |
| } |
| |
| OSCL_EXPORT_REF bool PVAviFileParser::GetFormatSpecificInfo(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag) |
| { |
| uint8* buff = NULL; |
| uint32 len = 0; |
| |
| ipFileHeader->GetFormatSpecificInfo(aStreamNum, buff, len); |
| |
| if ((buff == NULL) || (len == 0)) |
| { |
| return false; |
| } |
| |
| OsclMemAllocDestructDealloc<uint8> my_alloc; |
| OsclRefCounter* my_refcnt; |
| |
| uint aligned_refcnt_size = |
| oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); |
| |
| uint8* my_ptr = NULL; |
| int32 errcode = 0; |
| OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len)); |
| |
| if (errcode != OsclErrNone) |
| { |
| return false; |
| } |
| |
| my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); |
| my_ptr += aligned_refcnt_size; |
| |
| oscl_memcpy(my_ptr, buff, len); |
| |
| OsclMemoryFragment memfrag; |
| memfrag.len = len; |
| memfrag.ptr = my_ptr; |
| |
| OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len); |
| arFormatSpecificDataFrag = refcntMemFrag; |
| return true; |
| |
| } |
| |
| //method to get codec specific info |
| OSCL_EXPORT_REF bool PVAviFileParser::GetCodecSpecificData(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag) |
| { |
| uint8* buff = NULL; |
| uint32 len = 0; |
| ipFileHeader->GetCodecSpecificData(aStreamNum, buff, len); |
| |
| if ((buff == NULL) || (len == 0)) |
| { |
| return false; |
| } |
| |
| OsclMemAllocDestructDealloc<uint8> my_alloc; |
| OsclRefCounter* my_refcnt; |
| |
| uint aligned_refcnt_size = |
| oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); |
| |
| uint8* my_ptr = NULL; |
| int32 errcode = 0; |
| OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len)); |
| |
| if (errcode != OsclErrNone) |
| { |
| return false; |
| } |
| |
| my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); |
| my_ptr += aligned_refcnt_size; |
| |
| oscl_memcpy(my_ptr, buff, len); |
| |
| OsclMemoryFragment memfrag; |
| memfrag.len = len; |
| memfrag.ptr = my_ptr; |
| |
| OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len); |
| arFormatSpecificDataFrag = refcntMemFrag; |
| return true; |
| } |
| |
| PVAviFileParser::~PVAviFileParser() |
| { |
| if (NULL != ipFileHeader) |
| { |
| OSCL_DELETE(ipFileHeader); |
| ipFileHeader = NULL; |
| } |
| |
| if (NULL != ipIdxChunk) |
| { |
| OSCL_DELETE(ipIdxChunk); |
| ipIdxChunk = NULL; |
| } |
| |
| if (ipFilePtr->IsOpen()) |
| { |
| ipFilePtr->Close(); |
| } |
| |
| OSCL_DELETE(ipFilePtr); |
| } |
| |
| uint32 PVAviFileParser::GetFileSuggestedBufferSize() |
| { |
| uint32 buffSz = ipFileHeader->GetFileSuggestedBufferSize(); |
| if (0 == buffSz) |
| { |
| uint32 numStr = ipFileHeader->GetNumStreams(); |
| for (uint32 ii = 0; ii < numStr; ii++) |
| { |
| uint32 strSz = ipFileHeader->GetStreamSuggestedBufferSize(ii); |
| if (buffSz < strSz) |
| { |
| buffSz = strSz; |
| } |
| } |
| } |
| return buffSz; |
| } |
| |
| bool PVAviFileParser::GetVideoFormatType(uint8* aHdlr, uint32& arSize, uint32 aStreamNo) |
| { |
| uint32 numstr = GetNumStreams(); |
| uint32 ii = 0; |
| bool retTyp = false; |
| for (ii = 0; ii < numstr; ii++) |
| { |
| if ((oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video")) && (aStreamNo == ii)) |
| { |
| ipFileHeader->GetHandlerType(ii, aHdlr, arSize); |
| retTyp = true; |
| } |
| } |
| return retTyp; |
| } |
| |
| OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetAudioStreamCountList() |
| { |
| uint32 ii = 0; |
| Oscl_Vector<uint32, OsclMemAllocator> audioStrNum; |
| for (ii = 0; ii < GetNumStreams(); ii++) |
| { |
| if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "audio")) |
| { |
| audioStrNum.push_back(ii); |
| } |
| } |
| |
| return audioStrNum; |
| } |
| |
| OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetVideoStreamCountList() |
| { |
| uint32 ii = 0; |
| Oscl_Vector<uint32, OsclMemAllocator> vidStrNum; |
| for (ii = 0; ii < GetNumStreams(); ii++) |
| { |
| if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video")) |
| { |
| vidStrNum.push_back(ii); |
| } |
| } |
| |
| return vidStrNum; |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetFileDuration() |
| { |
| uint32 frameDuration = ipFileHeader->GetFrameDuration(); |
| uint32 totalFrames = ipFileHeader->GetTotalFrames(); |
| uint32 fileDuration = (uint32)((OsclFloat)(frameDuration * totalFrames) / 1000000.0); //in seconds |
| return fileDuration; |
| } |
| |
| OSCL_EXPORT_REF PVAviFileStreamHeaderStruct |
| PVAviFileParser::GetStreamHeaderStruct(uint32 aStreamNum) |
| { |
| return (ipFileHeader->GetStreamHeaderStruct(aStreamNum)); |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetNumStreams() |
| { |
| return (ipFileHeader->GetNumStreams()); |
| } |
| |
| OSCL_EXPORT_REF OSCL_HeapString<OsclMemAllocator> |
| PVAviFileParser::GetStreamMimeType(uint32 aStreamNum) |
| { |
| return (ipFileHeader->GetStreamMimeType(aStreamNum)); |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetWidth(int32 aStreamNo) |
| { |
| return (ipFileHeader->GetWidth(aStreamNo)); |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetHeight(bool& rBottomUp, int32 aStreamNo) |
| { |
| return (ipFileHeader->GetHeight(rBottomUp, aStreamNo)); |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetFrameDuration() |
| { |
| return (ipFileHeader->GetFrameDuration()); |
| } |
| |
| OSCL_EXPORT_REF OsclFloat PVAviFileParser::GetFrameRate(uint32 aStreamNum) |
| { |
| return (ipFileHeader->GetSamplingRate(aStreamNum)); |
| } |
| |
| OSCL_EXPORT_REF uint32 PVAviFileParser::GetStreamDuration(uint32 aStreamNum) |
| { |
| return (ipFileHeader->GetStreamDuration(aStreamNum)); |
| } |