blob: abb8fa5c7f6ed2023cac7e7c1b0c2ceae630ccdc [file] [log] [blame]
/* ------------------------------------------------------------------
* 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));
}