• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pv_avifile_parser.h"
19 
20 
PVAviFileParser(OSCL_wHeapString<OsclMemAllocator> aFileName,int32 & aError,Oscl_FileServer * aFileServer,PVMFCPMPluginAccessInterfaceFactory * aCPM,OsclFileHandle * aFileHandle)21 PVAviFileParser::PVAviFileParser(OSCL_wHeapString<OsclMemAllocator> aFileName, int32& aError, Oscl_FileServer* aFileServer,
22                                  PVMFCPMPluginAccessInterfaceFactory*  aCPM, OsclFileHandle*  aFileHandle)
23 {
24     ipFileHeader = NULL;
25     ipIdxChunk = NULL;
26     iIdxChunkPresent = false;
27     iFileSize = 0;
28     iHeaderChunkSize = 0;
29     iMovieChunkSize = 0;
30     iMovieChunkStartOffset = 0;
31     iIndxChunkSize = 0;
32     iSampleOffset = 0;
33     iTimeStampVideo = 0;
34     iTimeStampAudio = 0;
35 
36     OSCL_TRY(aError, ipFilePtr = OSCL_NEW(PVFile, ()););
37 
38     if (0 == aError)
39     {
40         ipFilePtr->SetCPM(aCPM);
41         ipFilePtr->SetFileHandle(aFileHandle);
42 
43         aError = PV_AVI_FILE_PARSER_SUCCESS;
44 
45         if (ipFilePtr->Open(aFileName.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileServer) != 0)
46         {
47             aError = PV_AVI_FILE_PARSER_FILE_OPEN_ERROR;
48         }
49     }
50 }
51 
52 PV_AVI_FILE_PARSER_ERROR_TYPE
ParseFile()53 PVAviFileParser::ParseFile()
54 {
55     iError = PV_AVI_FILE_PARSER_SUCCESS;
56     ipFilePtr->Seek(0, Oscl_File::SEEKSET);
57 
58     // Seek to the end to find the file size
59     uint32 filesize = 0;
60     if (ipFilePtr->Seek(0, Oscl_File::SEEKEND))
61     {
62         iError = PV_AVI_FILE_PARSER_SEEK_ERROR;
63         return iError;
64     }
65     filesize = ipFilePtr->Tell();
66 
67     // Seek back to the beginning
68     ipFilePtr->Seek(0, Oscl_File::SEEKSET);
69     uint32 chunkType = 0;
70 
71     if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS)
72     {
73         PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file"));
74         return iError;
75     }
76 
77     //first chunk must be RIFF
78     if (chunkType != RIFF)
79     {
80         PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: First Chunk Must be RIFF"));
81         iError = PV_AVI_FILE_PARSER_WRONG_FILE;
82         return iError;
83     }
84 
85     if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iFileSize, true))
86     {
87         iError = PV_AVI_FILE_PARSER_READ_ERROR;
88         return iError;
89     }
90 
91     if ((iFileSize <= 0) || (iFileSize > filesize))
92     {
93         iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
94         return iError;
95     }
96 
97     if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS)
98     {
99         PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: UnSupported Chunk at begining of the file"));
100         return iError;
101     }
102 
103     //second chunk must be AVI
104     if (chunkType != AVI)
105     {
106         PVAVIFILE_LOGERROR((0, "Second Chunk Must be AVI"));
107         iError = PV_AVI_FILE_PARSER_WRONG_FILE;
108         return iError;
109     }
110 
111     uint32 bytesRead = CHUNK_SIZE;
112     uint32 listSize = 0;
113     uint32 oldChkType = chunkType;
114 
115     while (bytesRead < iFileSize)
116     {
117         oldChkType = chunkType;
118         if ((iError = PVAviFileParserUtils::ReadNextChunkType(ipFilePtr, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS)
119         {
120             if ((PV_AVI_FILE_PARSER_UNSUPPORTED_CHUNK == iError))
121             {
122                 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk"));
123 
124                 uint32 chksz = 0;
125                 if (oldChkType != LIST)
126                 {
127                     //get the size of unsupported chunk and skip it.
128                     if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, chksz, true))
129                     {
130                         PVAVIFILE_LOGERROR((0, "PVAviFileParser::ParseFile: File Read Error"));
131                         iError = PV_AVI_FILE_PARSER_READ_ERROR;
132                         break;
133                     }
134 
135                     ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR);
136                     bytesRead += chksz + CHUNK_SIZE + CHUNK_SIZE; //chunk data + chunk size + chunk type;
137 
138                 }
139                 else
140                 {
141                     //skip the entire list if not supported
142                     chksz = listSize - CHUNK_SIZE ;  //subtract list name already read
143                     ipFilePtr->Seek(chksz, Oscl_File::SEEKCUR);
144                     bytesRead += listSize;
145                 }
146 
147                 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Unsupported chunk skipped"));
148                 iError = PV_AVI_FILE_PARSER_SUCCESS;
149                 continue;
150             }
151             else
152             {
153                 break;
154             }
155         }
156         bytesRead += CHUNK_SIZE;
157 
158         if (LIST == chunkType)
159         {
160             if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, listSize, true))
161             {
162                 iError = PV_AVI_FILE_PARSER_READ_ERROR;
163                 break;
164             }
165 
166             bytesRead += CHUNK_SIZE;
167             if (bytesRead > iFileSize)
168             {
169                 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
170                 break;
171             }
172 
173             if ((listSize <= 0) || (listSize > iFileSize))
174             {
175                 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
176                 break;
177             }
178         }
179         else if (HDRL == chunkType)
180         {
181             PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found File Header"));
182 
183             iHeaderChunkSize = listSize - CHUNK_SIZE; //subtract 4 bytes of chunk type
184             ipFileHeader = OSCL_NEW(PVAviFileHeader, (ipFilePtr, iHeaderChunkSize));
185             if (ipFileHeader != NULL)
186             {
187                 iError = ipFileHeader->GetStatus();
188                 if (iError != PV_AVI_FILE_PARSER_SUCCESS)
189                 {
190                     OSCL_DELETE(ipFileHeader);
191                     ipFileHeader = NULL;
192                     break;
193                 }
194             }
195             bytesRead += iHeaderChunkSize;
196             if (bytesRead > iFileSize)
197             {
198                 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
199                 break;
200             }
201         }
202         else if (MOVI == chunkType)
203         {
204             PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found MOVI Chunk"));
205 
206             iMovieChunkSize = listSize - CHUNK_SIZE;
207             iMovieChunkStartOffset = ipFilePtr->Tell();     //get movi chunk start offset.
208             iSampleOffset = iMovieChunkStartOffset;
209             ipFilePtr->Seek(iMovieChunkSize, Oscl_File::SEEKCUR);
210 
211             uint32 numStr = GetNumStreams();
212             for (uint32 ii = 0; ii < numStr; ii++)
213             {
214                 iStreamCount.push_back(ii);
215                 iStreamSampleCount.push_back(0);
216             }
217 
218             bytesRead += iMovieChunkSize;
219 
220         }
221         else if (IDX1 == chunkType)
222         {
223             PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Found Index Table"));
224 
225             if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, iIndxChunkSize, true))
226             {
227                 iError = PV_AVI_FILE_PARSER_READ_ERROR;
228                 break;
229             }
230 
231             bytesRead += CHUNK_SIZE;
232             if (bytesRead > iFileSize)
233             {
234                 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
235                 break;
236             }
237 
238             if ((iIndxChunkSize <= 0) || (iIndxChunkSize > iFileSize))
239             {
240                 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
241                 break;
242             }
243             uint32 numStreams = GetNumStreams();
244             ipIdxChunk = OSCL_NEW(PVAviFileIdxChunk, (ipFilePtr, iIndxChunkSize, numStreams));
245             if (ipIdxChunk != NULL)
246             {
247                 iError = ipIdxChunk->GetStatus();
248                 if (iError != PV_AVI_FILE_PARSER_SUCCESS)
249                 {
250                     OSCL_DELETE(ipIdxChunk);
251                     ipIdxChunk = NULL;
252                     break;
253                 }
254                 iIdxChunkPresent = true;
255             }
256             bytesRead += iIndxChunkSize;
257         }
258         else if (JUNK == chunkType)
259         {
260             PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Skip Junk data"));
261 
262             uint32 junkSize = 0;
263             if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, junkSize, true))
264             {
265                 iError = PV_AVI_FILE_PARSER_READ_ERROR;
266                 break;
267             }
268 
269             bytesRead += CHUNK_SIZE;
270             if (bytesRead > iFileSize)
271             {
272                 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
273                 break;
274             }
275 
276             if ((junkSize <= 0) || (junkSize > iFileSize))
277             {
278                 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
279                 break;
280             }
281 
282             ipFilePtr->Seek(junkSize, Oscl_File::SEEKCUR);
283             bytesRead += junkSize;
284             if (bytesRead > iFileSize)
285             {
286                 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
287                 break;
288             }
289         }
290         else
291         {
292             iError = PV_AVI_FILE_PARSER_WRONG_CHUNK;
293             break;
294         }
295 
296     }   //while (bytesRead <= iFileSize)
297 
298     return iError;
299 }
300 
301 PV_AVI_FILE_PARSER_ERROR_TYPE
GetNextMediaSample(uint32 & arStreamNo,uint8 * aBuffer,uint32 & arSize,uint32 & arTimeStamp)302 PVAviFileParser::GetNextMediaSample(uint32& arStreamNo, uint8* aBuffer,
303                                     uint32& arSize, uint32& arTimeStamp)
304 {
305     if (iSampleOffset >= iFileSize)
306     {
307         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset"));
308         return PV_AVI_FILE_PARSER_WRONG_OFFSET;
309     }
310 
311     if (iSampleOffset == iMovieChunkStartOffset)
312     {
313         //first Sample reset sample count.
314         for (uint32 ii = 0; ii < GetNumStreams(); ii++)
315         {
316             iStreamSampleCount[ii] = 0;
317         }
318 
319         ipFilePtr->Seek(0, Oscl_File::SEEKSET);
320     }
321 
322     uint32 CurrOff = ipFilePtr->Tell();
323     if (CurrOff > iSampleOffset)
324     {
325         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong offset"));
326         return PV_AVI_FILE_PARSER_WRONG_OFFSET;
327     }
328 
329     ipFilePtr->Seek((iSampleOffset - CurrOff), Oscl_File::SEEKCUR);
330 
331     uint32 bytesRead = 0;
332     uint32 data = 0;
333     if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data))
334     {
335         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error"));
336         return PV_AVI_FILE_PARSER_READ_ERROR;
337     }
338 
339     int32 strNo = PVAviFileParserUtils::GetStreamNumber(data);
340     if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo)
341     {
342         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No"));
343         return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM;
344     }
345 
346     arStreamNo = strNo;
347 
348     bytesRead += CHUNK_SIZE;
349 
350     uint32 size = 0;
351     if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true))
352     {
353         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error"));
354         return PV_AVI_FILE_PARSER_READ_ERROR;
355     }
356 
357     bytesRead += CHUNK_SIZE;
358 
359     if (size > arSize)
360     {
361         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size"));
362         return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY;
363     }
364 
365     arSize = size;
366 
367     if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize)
368     {
369         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error"));
370         return PV_AVI_FILE_PARSER_READ_ERROR;
371     }
372 
373     iSampleOffset = iSampleOffset + arSize + bytesRead;
374 
375     uint32 offsetFrmMoviChk = iSampleOffset - iMovieChunkStartOffset;
376 
377     if (offsetFrmMoviChk >= iMovieChunkSize)
378     {
379         PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached"));
380         return PV_AVI_FILE_PARSER_EOF_REACHED;
381     }
382 
383     //calculate time stamp
384     if (oscl_strstr(GetStreamMimeType(arStreamNo).get_str(), "audio"))
385     {
386         arTimeStamp = iTimeStampAudio;
387         uint32 sampleSize = GetBitsPerSample(arStreamNo);
388         sampleSize = sampleSize / BIT_COUNT8; //in bytes
389         OsclFloat  samplingRate = GetFrameRate(arStreamNo);
390         if (sampleSize > 0)
391         {
392             OsclFloat  sampleCount = (OsclFloat)arSize / sampleSize;
393             if (samplingRate > 0)
394             {
395                 iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate);
396             }
397         }
398     }
399     else
400     {
401         if (iStreamSampleCount[arStreamNo] > 0)
402         {
403             uint32 frameDurationInms = GetFrameDuration() / 1000;
404             arTimeStamp = (iStreamSampleCount[arStreamNo] * (frameDurationInms));
405         }
406         else
407         {
408             arTimeStamp = 0;
409         }
410     }
411 
412     iStreamSampleCount[arStreamNo] = iStreamSampleCount[arStreamNo] + 1;
413     return PV_AVI_FILE_PARSER_SUCCESS;
414 }
415 
416 
417 PV_AVI_FILE_PARSER_ERROR_TYPE
GetNextStreamSampleInfo(uint32 aStreamNo,uint32 & arSize,uint32 & arOffset)418 PVAviFileParser::GetNextStreamSampleInfo(uint32 aStreamNo, uint32& arSize, uint32& arOffset)
419 {
420     if (false == iIdxChunkPresent)
421     {
422         return PV_AVI_FILE_PARSER_NO_INDEX_CHUNK;
423     }
424     else
425     {
426         return GetStreamOffsetFromIndexTable(aStreamNo, arSize, arOffset);
427     }
428 }
429 
430 PV_AVI_FILE_PARSER_ERROR_TYPE
GetNextStreamMediaSample(uint32 aStreamNo,uint8 * aBuffer,uint32 & arSize,uint32 & arTimeStamp)431 PVAviFileParser::GetNextStreamMediaSample(uint32 aStreamNo, uint8* aBuffer,
432         uint32& arSize, uint32& arTimeStamp)
433 {
434     uint32 sampleOffset = 0;
435     PV_AVI_FILE_PARSER_ERROR_TYPE error = PV_AVI_FILE_PARSER_SUCCESS;
436 
437     if (false == iIdxChunkPresent)
438     {
439         error = GetStreamOffset(aStreamNo, arSize, sampleOffset);
440 
441         if ((error != PV_AVI_FILE_PARSER_SUCCESS))
442         {
443             if (PV_AVI_FILE_PARSER_NO_OFFSET_FOUND == error)
444             {
445                 arSize = 0;
446                 arTimeStamp = 0;
447                 //probably EOS has been reached.
448                 return PV_AVI_FILE_PARSER_EOS_REACHED;
449             }
450             else
451             {
452                 return error;
453             }
454         }
455 
456         uint32 offsetFrmMoviChk = sampleOffset - iMovieChunkStartOffset;
457         if (offsetFrmMoviChk >= iMovieChunkSize)
458         {
459             PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextStreamMediaSample: EOF Reached"));
460             return PV_AVI_FILE_PARSER_EOF_REACHED;
461         }
462     }
463     else
464     {
465         error = GetStreamOffsetFromIndexTable(aStreamNo, arSize, sampleOffset);
466         if (error != PV_AVI_FILE_PARSER_SUCCESS)
467         {
468             return error;
469         }
470     }
471 
472     if (PVAviFileParserUtils::read8(ipFilePtr, aBuffer, arSize) != arSize)
473     {
474         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error"));
475         return PV_AVI_FILE_PARSER_READ_ERROR;
476     }
477 
478     //calculate time stamp
479     if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio"))
480     {
481         arTimeStamp = iTimeStampAudio;
482         uint32 sampleSize = GetBitsPerSample(aStreamNo);
483         sampleSize = sampleSize / BIT_COUNT8; //in bytes
484         OsclFloat samplingRate = GetFrameRate(aStreamNo);
485         if (sampleSize > 0)
486         {
487             OsclFloat sampleCount = (OsclFloat)arSize / sampleSize;
488             if (samplingRate > 0)
489             {
490                 iTimeStampAudio += (uint32)((sampleCount * 1000) / samplingRate);
491             }
492         }
493     }
494     else
495     {
496         if (iStreamSampleCount[aStreamNo] > 0)
497         {
498             uint32 frameDurationInms = GetFrameDuration() / 1000;
499             arTimeStamp = (iStreamSampleCount[aStreamNo] * (frameDurationInms));
500         }
501         else
502         {
503             arTimeStamp = 0;
504         }
505     }
506 
507     iStreamSampleCount[aStreamNo] = iStreamSampleCount[aStreamNo] + 1;
508 
509     return PV_AVI_FILE_PARSER_SUCCESS;
510 }
511 
512 
513 PV_AVI_FILE_PARSER_ERROR_TYPE
GetStreamOffsetFromIndexTable(uint32 aStreamNo,uint32 & arSize,uint32 & arOffset)514 PVAviFileParser::GetStreamOffsetFromIndexTable(uint32 aStreamNo, uint32& arSize, uint32& arOffset)
515 {
516     uint32 sampleOffset = 0;
517 
518     if (iStreamSampleCount[aStreamNo] >= ipIdxChunk->GetNumberOfSamplesInStream(aStreamNo))
519     {
520         PVAVIFILE_LOGINFO((0, "PVAviFileParser::GetNextMediaSample: EOF Reached"));
521         return PV_AVI_FILE_PARSER_EOS_REACHED;
522     }
523 
524     sampleOffset = ipIdxChunk->GetOffset(aStreamNo, iStreamSampleCount[aStreamNo]);
525     uint32 size = ipIdxChunk->GetSampleSize(aStreamNo, iStreamSampleCount[aStreamNo]);
526 
527     if (size > arSize)
528     {
529         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size"));
530         return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY;
531     }
532 
533     arSize = size;
534 
535     if (ipIdxChunk->IsOffsetFromMoviList())
536     {
537         arOffset = iMovieChunkStartOffset + sampleOffset - CHUNK_SIZE;
538     }
539     else
540     {
541         arOffset = sampleOffset;
542     }
543 
544     arOffset += (CHUNK_SIZE + CHUNK_SIZE); //add 4 bytes each for sample type and data size param.
545 
546     if ((arOffset > iFileSize))
547     {
548         PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Size & Byte Count mismatch"));
549         return PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
550     }
551 
552     ipFilePtr->Seek(0, Oscl_File::SEEKSET);
553     ipFilePtr->Seek(arOffset, Oscl_File::SEEKCUR);
554 
555     return PV_AVI_FILE_PARSER_SUCCESS;
556 }
557 
558 
559 PV_AVI_FILE_PARSER_ERROR_TYPE
GetStreamOffset(uint32 aStreamNo,uint32 & arSampleSize,uint32 & arOffset)560 PVAviFileParser::GetStreamOffset(uint32 aStreamNo, uint32& arSampleSize, uint32& arOffset)
561 {
562     uint32 startOffset = 0;
563     arOffset = 0;
564     bool foundOffset = false;
565 
566     if (iStreamSampleOffset.size() == 0)
567     {
568         uint32 numstreams = GetNumStreams();
569         startOffset = iMovieChunkStartOffset;
570 
571         for (uint32 ii = 0; ii < numstreams; ii++)
572         {
573             iStreamSampleOffset.push_back(startOffset);
574         }
575     }
576     else
577     {
578         startOffset = iStreamSampleOffset[aStreamNo];
579     }
580 
581     ipFilePtr->Seek(startOffset, Oscl_File::SEEKSET);
582     uint32 currentFileOffset = startOffset;
583 
584     uint32 endOfdataPosition = iMovieChunkStartOffset + iMovieChunkSize;
585 
586     while (currentFileOffset < endOfdataPosition)
587     {
588         uint32 data = 0;
589         if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, data))
590         {
591             PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Read Error"));
592             return PV_AVI_FILE_PARSER_READ_ERROR;
593         }
594 
595         int32 strNo = PVAviFileParserUtils::GetStreamNumber(data);
596         if (PV_AVI_FILE_PARSER_ERROR_UNKNOWN == strNo)
597         {
598             PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Wrong Stream No"));
599             return PV_AVI_FILE_PARSER_ERROR_WRONG_STREAM_NUM;
600         }
601 
602         uint32 size = 0;
603         if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(ipFilePtr, size, true))
604         {
605             PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: File Read Error"));
606             return PV_AVI_FILE_PARSER_READ_ERROR;
607         }
608 
609         if ((uint32)strNo == aStreamNo)
610         {
611             arOffset = ipFilePtr->Tell();
612             iStreamSampleOffset[aStreamNo] = arOffset + size;
613             if (size > arSampleSize)
614             {
615                 PVAVIFILE_LOGERROR((0, "PVAviFileParser::GetNextMediaSample: Insufficient Buffer Size"));
616                 return PV_AVI_FILE_PARSER_INSUFFICIENT_MEMORY;
617             }
618 
619             arSampleSize = size;
620             foundOffset = true;
621             break;
622         }
623         else
624         {
625             ipFilePtr->Seek(size, Oscl_File::SEEKCUR);
626             foundOffset = false;
627         }
628 
629         currentFileOffset = ipFilePtr->Tell();
630     }
631 
632     if (foundOffset)
633     {
634         return PV_AVI_FILE_PARSER_SUCCESS;
635     }
636     else
637     {
638         return PV_AVI_FILE_PARSER_NO_OFFSET_FOUND;
639     }
640 }
641 
Reset()642 OSCL_EXPORT_REF void PVAviFileParser::Reset()
643 {
644     PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset"));
645 
646     uint32 ii = 0;
647     for (ii = 0; ii < GetNumStreams(); ii++)
648     {
649         iStreamSampleCount[ii] = 0;
650     }
651 
652     if (iStreamSampleOffset.size() > 0)
653     {
654         for (ii = 0; ii < iStreamSampleOffset.size(); ii++)
655         {
656             iStreamSampleOffset.pop_back();
657         }
658     }
659 
660     iSampleOffset = iMovieChunkStartOffset;
661     iTimeStampAudio = 0;
662 }
663 
Reset(uint32 aStreamNo)664 OSCL_EXPORT_REF void PVAviFileParser::Reset(uint32 aStreamNo)
665 {
666     PVAVIFILE_LOGINFO((0, "PVAviFileParser::Reset stream"));
667 
668     iStreamSampleCount[aStreamNo] = 0;
669 
670     if (iStreamSampleOffset.size() > aStreamNo)
671     {
672         iStreamSampleOffset[aStreamNo] = iMovieChunkStartOffset;
673     }
674 
675     if (oscl_strstr(GetStreamMimeType(aStreamNo).get_str(), "audio"))
676     {
677         iTimeStampAudio = 0;
678     }
679 }
680 
GetFormatSpecificInfo(uint32 aStreamNum,OsclRefCounterMemFrag & arFormatSpecificDataFrag)681 OSCL_EXPORT_REF bool PVAviFileParser::GetFormatSpecificInfo(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag)
682 {
683     uint8* buff = NULL;
684     uint32 len = 0;
685 
686     ipFileHeader->GetFormatSpecificInfo(aStreamNum, buff, len);
687 
688     if ((buff == NULL) || (len == 0))
689     {
690         return false;
691     }
692 
693     OsclMemAllocDestructDealloc<uint8> my_alloc;
694     OsclRefCounter* my_refcnt;
695 
696     uint aligned_refcnt_size =
697         oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
698 
699     uint8* my_ptr = NULL;
700     int32 errcode = 0;
701     OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len));
702 
703     if (errcode != OsclErrNone)
704     {
705         return false;
706     }
707 
708     my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
709     my_ptr += aligned_refcnt_size;
710 
711     oscl_memcpy(my_ptr, buff, len);
712 
713     OsclMemoryFragment memfrag;
714     memfrag.len = len;
715     memfrag.ptr = my_ptr;
716 
717     OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len);
718     arFormatSpecificDataFrag = refcntMemFrag;
719     return true;
720 
721 }
722 
723 //method to get codec specific info
GetCodecSpecificData(uint32 aStreamNum,OsclRefCounterMemFrag & arFormatSpecificDataFrag)724 OSCL_EXPORT_REF bool PVAviFileParser::GetCodecSpecificData(uint32 aStreamNum, OsclRefCounterMemFrag& arFormatSpecificDataFrag)
725 {
726     uint8* buff = NULL;
727     uint32 len = 0;
728     ipFileHeader->GetCodecSpecificData(aStreamNum, buff, len);
729 
730     if ((buff == NULL) || (len == 0))
731     {
732         return false;
733     }
734 
735     OsclMemAllocDestructDealloc<uint8> my_alloc;
736     OsclRefCounter* my_refcnt;
737 
738     uint aligned_refcnt_size =
739         oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
740 
741     uint8* my_ptr = NULL;
742     int32 errcode = 0;
743     OSCL_TRY(errcode, my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + len));
744 
745     if (errcode != OsclErrNone)
746     {
747         return false;
748     }
749 
750     my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
751     my_ptr += aligned_refcnt_size;
752 
753     oscl_memcpy(my_ptr, buff, len);
754 
755     OsclMemoryFragment memfrag;
756     memfrag.len = len;
757     memfrag.ptr = my_ptr;
758 
759     OsclRefCounterMemFrag refcntMemFrag(memfrag, my_refcnt, memfrag.len);
760     arFormatSpecificDataFrag = refcntMemFrag;
761     return true;
762 }
763 
~PVAviFileParser()764 PVAviFileParser::~PVAviFileParser()
765 {
766     if (NULL != ipFileHeader)
767     {
768         OSCL_DELETE(ipFileHeader);
769         ipFileHeader = NULL;
770     }
771 
772     if (NULL != ipIdxChunk)
773     {
774         OSCL_DELETE(ipIdxChunk);
775         ipIdxChunk = NULL;
776     }
777 
778     if (ipFilePtr->IsOpen())
779     {
780         ipFilePtr->Close();
781     }
782 
783     OSCL_DELETE(ipFilePtr);
784 }
785 
GetFileSuggestedBufferSize()786 uint32 PVAviFileParser::GetFileSuggestedBufferSize()
787 {
788     uint32 buffSz = ipFileHeader->GetFileSuggestedBufferSize();
789     if (0 == buffSz)
790     {
791         uint32 numStr = ipFileHeader->GetNumStreams();
792         for (uint32 ii = 0; ii < numStr; ii++)
793         {
794             uint32 strSz = ipFileHeader->GetStreamSuggestedBufferSize(ii);
795             if (buffSz < strSz)
796             {
797                 buffSz = strSz;
798             }
799         }
800     }
801     return buffSz;
802 }
803 
GetVideoFormatType(uint8 * aHdlr,uint32 & arSize,uint32 aStreamNo)804 bool PVAviFileParser::GetVideoFormatType(uint8* aHdlr, uint32& arSize, uint32 aStreamNo)
805 {
806     uint32 numstr = GetNumStreams();
807     uint32 ii = 0;
808     bool retTyp = false;
809     for (ii = 0; ii < numstr; ii++)
810     {
811         if ((oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video")) && (aStreamNo == ii))
812         {
813             ipFileHeader->GetHandlerType(ii, aHdlr, arSize);
814             retTyp = true;
815         }
816     }
817     return retTyp;
818 }
819 
GetAudioStreamCountList()820 OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetAudioStreamCountList()
821 {
822     uint32 ii = 0;
823     Oscl_Vector<uint32, OsclMemAllocator> audioStrNum;
824     for (ii = 0; ii < GetNumStreams(); ii++)
825     {
826         if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "audio"))
827         {
828             audioStrNum.push_back(ii);
829         }
830     }
831 
832     return audioStrNum;
833 }
834 
GetVideoStreamCountList()835 OSCL_EXPORT_REF Oscl_Vector<uint32, OsclMemAllocator> PVAviFileParser::GetVideoStreamCountList()
836 {
837     uint32 ii = 0;
838     Oscl_Vector<uint32, OsclMemAllocator> vidStrNum;
839     for (ii = 0; ii < GetNumStreams(); ii++)
840     {
841         if (oscl_strstr((GetStreamMimeType(ii)).get_cstr(), "video"))
842         {
843             vidStrNum.push_back(ii);
844         }
845     }
846 
847     return vidStrNum;
848 }
849 
GetFileDuration()850 OSCL_EXPORT_REF uint32 PVAviFileParser::GetFileDuration()
851 {
852     uint32 frameDuration = ipFileHeader->GetFrameDuration();
853     uint32 totalFrames = ipFileHeader->GetTotalFrames();
854     uint32 fileDuration = (uint32)((OsclFloat)(frameDuration * totalFrames) / 1000000.0); //in seconds
855     return fileDuration;
856 }
857 
858 OSCL_EXPORT_REF PVAviFileStreamHeaderStruct
GetStreamHeaderStruct(uint32 aStreamNum)859 PVAviFileParser::GetStreamHeaderStruct(uint32 aStreamNum)
860 {
861     return (ipFileHeader->GetStreamHeaderStruct(aStreamNum));
862 }
863 
GetNumStreams()864 OSCL_EXPORT_REF uint32 PVAviFileParser::GetNumStreams()
865 {
866     return (ipFileHeader->GetNumStreams());
867 }
868 
869 OSCL_EXPORT_REF OSCL_HeapString<OsclMemAllocator>
GetStreamMimeType(uint32 aStreamNum)870 PVAviFileParser::GetStreamMimeType(uint32 aStreamNum)
871 {
872     return (ipFileHeader->GetStreamMimeType(aStreamNum));
873 }
874 
GetWidth(int32 aStreamNo)875 OSCL_EXPORT_REF uint32 PVAviFileParser::GetWidth(int32 aStreamNo)
876 {
877     return (ipFileHeader->GetWidth(aStreamNo));
878 }
879 
GetHeight(bool & rBottomUp,int32 aStreamNo)880 OSCL_EXPORT_REF uint32 PVAviFileParser::GetHeight(bool& rBottomUp, int32 aStreamNo)
881 {
882     return (ipFileHeader->GetHeight(rBottomUp, aStreamNo));
883 }
884 
GetFrameDuration()885 OSCL_EXPORT_REF uint32 PVAviFileParser::GetFrameDuration()
886 {
887     return (ipFileHeader->GetFrameDuration());
888 }
889 
GetFrameRate(uint32 aStreamNum)890 OSCL_EXPORT_REF OsclFloat PVAviFileParser::GetFrameRate(uint32 aStreamNum)
891 {
892     return (ipFileHeader->GetSamplingRate(aStreamNum));
893 }
894 
GetStreamDuration(uint32 aStreamNum)895 OSCL_EXPORT_REF uint32 PVAviFileParser::GetStreamDuration(uint32 aStreamNum)
896 {
897     return (ipFileHeader->GetStreamDuration(aStreamNum));
898 }
899