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