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 /*********************************************************************************/
19 /* ------------------------------------------------------------------- */
20 /* MPEG-4 CompositionOffsetAtom Class */
21 /* ------------------------------------------------------------------- */
22 /*********************************************************************************/
23
24 /*
25 This atom gives difference between decoding time and composition time on each
26 sample basis. This atom is optional and must be present only if Decoding time
27 and Composition Time differ for any samples. As understood that Decoding time
28 is always less than composition time, the offsets are termed as unsigned
29 numbers such.
30
31 */
32
33
34 #define IMPLEMENT_CompositionOffsetAtom
35
36 #include "compositionoffsetatom.h"
37 #include "atomutils.h"
38
39 #define CTTS_MIN_SAMPLE_TABLE_SIZE 4096
40 #define MT_SAMPLECOUNT_INCREMENT 100 //this has to be atleast 3
41 #define NUMBER_OF_SAMPLE_POPULATES_PER_RUNL 50
42 #define ENABLE_MT_LOGIC_ON_CTTS_ENTRY_COUNT_VALUE 512
43
44 // Stream-in ctor
CompositionOffsetAtom(MP4_FF_FILE * fp,uint32 mediaType,uint32 size,uint32 type,OSCL_wString & filename,uint32 parsingMode)45 CompositionOffsetAtom::CompositionOffsetAtom(MP4_FF_FILE *fp,
46 uint32 mediaType,
47 uint32 size,
48 uint32 type,
49 OSCL_wString& filename,
50 uint32 parsingMode):
51 FullAtom(fp, size, type),
52 OsclTimerObject(OsclActiveObject::EPriorityNominal, "CompositionOffsetAtom")
53 {
54 _psampleCountVec = NULL;
55 _psampleOffsetVec = NULL;
56 MT_SampleCount = NULL;
57 MT_EntryCount = NULL;
58 iMarkerTableCreation = false;
59 MT_Table_Size = 0;
60
61 _currGetSampleCount = 0;
62 _currGetIndex = -1;
63 _currGetTimeOffset = 0;
64 _currPeekSampleCount = 0;
65 _currPeekIndex = -1;
66 _currPeekTimeOffset = 0;
67
68 MT_Counter = 1;
69 addSampleCount = 0;
70 prevSampleCount = 0;
71 entrycountTraversed = 0;
72 refSample = MT_SAMPLECOUNT_INCREMENT;
73 MT_j = 1;
74
75 _mediaType = mediaType;
76 _parsed_entry_cnt = 0;
77 _fileptr = NULL;
78 _parsing_mode = 0;
79 _parsing_mode = parsingMode;
80
81
82 _stbl_buff_size = CTTS_MIN_SAMPLE_TABLE_SIZE;
83 _next_buff_number = 0;
84 _curr_buff_number = 0;
85 _curr_entry_point = 0;
86 _stbl_fptr_vec = NULL;
87
88 iLogger = PVLogger::GetLoggerObject("mp4ffparser");
89 iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
90 iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
91
92 iMarkerTableCreation = false;
93
94 /* Add this AO to the scheduler */
95 if (OsclExecScheduler::Current() != NULL)
96 {
97 if (!IsAdded())
98 {
99 AddToScheduler();
100 }
101 }
102
103 if (_success)
104 {
105 if (!AtomUtils::read32(fp, _entryCount))
106 {
107 _success = false;
108 }
109
110 PVMF_MP4FFPARSER_LOGPARSEDINFO((0, "CompositionOffsetAtom::CompositionOffsetAtom- _entryCount =%d", _entryCount));
111 uint32 dataSize = _size - (DEFAULT_FULL_ATOM_SIZE + 4);
112
113 uint32 entrySize = (4 + 4);
114
115 if ((_entryCount*entrySize) > dataSize)
116 {
117 _success = false;
118 }
119
120 if (_success)
121 {
122 if (_entryCount > 0)
123 {
124 if (parsingMode == 1)
125 {
126 // cache size is 4K so that optimization
127 // should work if entry_count is greater than 4K
128 if (_entryCount > _stbl_buff_size)
129 {
130
131 uint32 fptrBuffSize = (_entryCount / _stbl_buff_size) + 1;
132
133 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (fptrBuffSize), _stbl_fptr_vec);
134 if (_stbl_fptr_vec == NULL)
135 {
136 _success = false;
137 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
138 return;
139 }
140
141
142 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psampleCountVec);
143 if (_psampleCountVec == NULL)
144 {
145 _success = false;
146 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
147 return;
148 }
149
150
151 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_stbl_buff_size), _psampleOffsetVec);
152 if (_psampleOffsetVec == NULL)
153 {
154 PV_MP4_ARRAY_DELETE(NULL, _psampleOffsetVec);
155 _psampleOffsetVec = NULL;
156 _success = false;
157 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
158 return;
159 }
160
161 for (uint32 idx = 0; idx < _stbl_buff_size; idx++) //initialization
162 {
163 _psampleCountVec[idx] = 0;
164 _psampleOffsetVec[idx] = 0;
165 }
166
167 OsclAny* ptr = (MP4_FF_FILE *)(oscl_malloc(sizeof(MP4_FF_FILE)));
168 if (ptr == NULL)
169 {
170 _success = false;
171 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
172 return;
173 }
174
175 _fileptr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE());
176 _fileptr->_fileServSession = fp->_fileServSession;
177 _fileptr->_pvfile.SetCPM(fp->_pvfile.GetCPM());
178
179 if (AtomUtils::OpenMP4File(filename,
180 Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
181 _fileptr) != 0)
182 {
183 _success = false;
184 _mp4ErrorCode = FILE_OPEN_FAILED;
185 }
186
187 _fileptr->_fileSize = fp->_fileSize;
188
189 int32 _head_offset = AtomUtils::getCurrentFilePosition(fp);
190 AtomUtils::seekFromCurrPos(fp, dataSize);
191 AtomUtils::seekFromStart(_fileptr, _head_offset);
192
193 return;
194 }
195 else
196 {
197 _parsing_mode = 0;
198 _stbl_buff_size = _entryCount;
199 }
200 }
201 else
202 {
203 _stbl_buff_size = _entryCount;
204 }
205
206 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psampleCountVec);
207 if (_psampleCountVec == NULL)
208 {
209 _success = false;
210 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
211 return;
212 }
213
214 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psampleOffsetVec);
215 if (_psampleOffsetVec == NULL)
216 {
217 PV_MP4_ARRAY_DELETE(NULL, _psampleOffsetVec);
218 _psampleOffsetVec = NULL;
219 _success = false;
220 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
221 return;
222 }
223
224 for (uint32 idx = 0; idx < _entryCount; idx++) //initialization
225 {
226 _psampleCountVec[idx] = 0;
227 _psampleOffsetVec[idx] = 0;
228 }
229
230 uint32 number = 0;
231 uint32 offset = 0;
232 for (_parsed_entry_cnt = 0; _parsed_entry_cnt < _entryCount; _parsed_entry_cnt++)
233 {
234 if (!AtomUtils::read32(fp, number))
235 {
236 _success = false;
237 break;
238 }
239 if (!AtomUtils::read32(fp, offset))
240 {
241 _success = false;
242 break;
243 }
244 _psampleCountVec[_parsed_entry_cnt] = (number);
245 _psampleOffsetVec[_parsed_entry_cnt] = (offset);
246 }
247 }
248 }
249
250 if (!_success)
251 {
252 _mp4ErrorCode = READ_TIME_TO_SAMPLE_ATOM_FAILED;
253 }
254 }
255 else
256 {
257 if (_mp4ErrorCode != ATOM_VERSION_NOT_SUPPORTED)
258 _mp4ErrorCode = READ_TIME_TO_SAMPLE_ATOM_FAILED;
259 }
260 }
261
setSamplesCount(uint32 SamplesCount)262 void CompositionOffsetAtom::setSamplesCount(uint32 SamplesCount)
263 {
264 _iTotalNumSamplesInTrack = SamplesCount;
265
266 if (_entryCount > ENABLE_MT_LOGIC_ON_CTTS_ENTRY_COUNT_VALUE)
267 {
268 //Make this AO active so Run() will be called when scheduler is started
269 if (OsclExecScheduler::Current() != NULL)
270 {
271 RunIfNotReady();
272 }
273 }
274 }
275
ParseEntryUnit(uint32 entry_cnt)276 bool CompositionOffsetAtom::ParseEntryUnit(uint32 entry_cnt)
277 {
278 const uint32 threshold = 1024;
279 entry_cnt += threshold;
280
281 if (entry_cnt > _entryCount)
282 {
283 entry_cnt = _entryCount;
284 }
285
286 uint32 number = 0;
287 uint32 offset = 0;
288 while (_parsed_entry_cnt < entry_cnt)
289 {
290 _curr_entry_point = _parsed_entry_cnt % _stbl_buff_size;
291 _curr_buff_number = _parsed_entry_cnt / _stbl_buff_size;
292
293 if (_curr_buff_number == _next_buff_number)
294 {
295 uint32 currFilePointer = AtomUtils::getCurrentFilePosition(_fileptr);
296 _stbl_fptr_vec[_curr_buff_number] = currFilePointer;
297 _next_buff_number++;
298 }
299
300 if (!_curr_entry_point)
301 {
302 uint32 currFilePointer = _stbl_fptr_vec[_curr_buff_number];
303 AtomUtils::seekFromStart(_fileptr, currFilePointer);
304 }
305
306 if (!AtomUtils::read32(_fileptr, number))
307 {
308 return false;
309 }
310
311 if (!AtomUtils::read32(_fileptr, offset))
312 {
313 return false;
314 }
315 _psampleCountVec[_curr_entry_point] = (number);
316 _psampleOffsetVec[_curr_entry_point] = (offset);
317 _parsed_entry_cnt++;
318 }
319 return true;
320 }
321
322 // Destructor
~CompositionOffsetAtom()323 CompositionOffsetAtom::~CompositionOffsetAtom()
324 {
325 if (_psampleCountVec != NULL)
326 PV_MP4_ARRAY_DELETE(NULL, _psampleCountVec);
327
328 if (_psampleOffsetVec != NULL)
329 PV_MP4_ARRAY_DELETE(NULL, _psampleOffsetVec);
330
331 if (_stbl_fptr_vec != NULL)
332 PV_MP4_ARRAY_DELETE(NULL, _stbl_fptr_vec);
333
334 deleteMarkerTable();
335
336 if (_fileptr != NULL)
337 {
338 if (_fileptr->IsOpen())
339 {
340 AtomUtils::CloseMP4File(_fileptr);
341 }
342 oscl_free(_fileptr);
343 }
344
345 if (IsAdded())
346 {
347 RemoveFromScheduler();
348 }
349
350 }
351
352 // Return the number of samples at index
353 uint32
getSampleCountAt(int32 index)354 CompositionOffsetAtom::getSampleCountAt(int32 index)
355 {
356 if (_psampleCountVec == NULL)
357 {
358 return (uint32) PV_ERROR;
359 }
360
361 if (index < (int32)_entryCount)
362 {
363 if (_parsing_mode == 1)
364 CheckAndParseEntry(index);
365
366 return (int32)(_psampleCountVec[index%_stbl_buff_size]);
367 }
368 else
369 {
370 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getSampleCountAt index = %d", index));
371 return (uint32) PV_ERROR;
372 }
373 }
374
375 // Return sample offset at index
376 int32
getSampleOffsetAt(int32 index)377 CompositionOffsetAtom::getSampleOffsetAt(int32 index)
378 {
379 if (_psampleOffsetVec == NULL)
380 {
381 return PV_ERROR;
382 }
383
384 if (index < (int32)_entryCount)
385 {
386 if (_parsing_mode == 1)
387 CheckAndParseEntry(index);
388
389 return (int32)(_psampleOffsetVec[index%_stbl_buff_size]);
390 }
391 else
392 {
393 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getSampleOffsetAt index = %d", index));
394 return PV_ERROR;
395 }
396 }
397
398 int32
getTimeOffsetForSampleNumberPeek(uint32 sampleNum)399 CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek(uint32 sampleNum)
400 {
401 // It is assumed that sample 0 has a ts of 0 - i.e. the first
402 // entry in the table starts with the delta between sample 1 and sample 0
403 if ((_psampleOffsetVec == NULL) ||
404 (_psampleCountVec == NULL) ||
405 (_entryCount == 0))
406 {
407 return PV_ERROR;
408 }
409
410 // note that sampleNum is a zero based index while _currGetSampleCount is 1 based index
411 if (sampleNum < _currPeekSampleCount)
412 {
413 return (_currPeekTimeOffset);
414 }
415 else
416 {
417 do
418 {
419 _currPeekIndex++;
420 if (_parsing_mode)
421 CheckAndParseEntry(_currPeekIndex);
422
423 _currPeekSampleCount += _psampleCountVec[_currPeekIndex%_stbl_buff_size];
424 _currPeekTimeOffset = _psampleOffsetVec[_currPeekIndex%_stbl_buff_size];
425 }
426 while (_currPeekSampleCount == 0);
427
428 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekIndex =%d", _currPeekIndex));
429 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekSampleCount =%d", _currPeekSampleCount));
430 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek- _currPeekTimeOffset =%d", _currPeekTimeOffset));
431
432 if (sampleNum < _currPeekSampleCount)
433 {
434 return (_currPeekTimeOffset);
435 }
436 else
437 {
438 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>CompositionOffsetAtom::getTimeOffsetForSampleNumberPeek sampleNum = %d", sampleNum));
439 return (PV_ERROR);
440 }
441 }
442
443 }
444
445 // This is the most widely used API
446 // Returns the offset (ms) for the sample given by num. This is used when
447 // randomly accessing a frame and the timestamp has not been accumulated.
getTimeOffsetForSampleNumberGet(uint32 sampleNum)448 int32 CompositionOffsetAtom::getTimeOffsetForSampleNumberGet(uint32 sampleNum)
449 {
450 if ((_psampleOffsetVec == NULL) ||
451 (_psampleCountVec == NULL) ||
452 (_entryCount == 0))
453 {
454 return PV_ERROR;
455 }
456
457 // note that sampleNum is a zero based index while _currGetSampleCount is 1 based index
458 if (sampleNum < _currGetSampleCount)
459 {
460 return (_currGetTimeOffset);
461 }
462 else
463 {
464
465 do
466 {
467 _currGetIndex++;
468 if (_parsing_mode)
469 CheckAndParseEntry(_currGetIndex);
470 _currGetSampleCount += _psampleCountVec[_currGetIndex%_stbl_buff_size];
471 _currGetTimeOffset = _psampleOffsetVec[_currGetIndex%_stbl_buff_size];
472 }
473 while (_currGetSampleCount == 0);
474
475 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetIndex =%d", _currGetIndex));
476 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetSampleCount =%d", _currGetSampleCount));
477 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimeOffsetForSampleNumberGet- _currGetTimeOffset =%d", _currGetTimeOffset));
478
479 if (sampleNum < _currGetSampleCount)
480 {
481 return (_currGetTimeOffset);
482 }
483 else
484 {
485 PVMF_MP4FFPARSER_LOGERROR((0, "ERROR =>TimeToSampleAtom::getTimeDeltaForSampleNumberGet sampleNum = %d", sampleNum));
486 return (PV_ERROR);
487 }
488 }
489
490 }
491
492
493
494
495
getTimeOffsetFromMT(uint32 samplenum,uint32 currEC,uint32 currSampleCount)496 int32 CompositionOffsetAtom::getTimeOffsetFromMT(uint32 samplenum, uint32 currEC, uint32 currSampleCount)
497 {
498 if ((_psampleOffsetVec == NULL) ||
499 (_psampleCountVec == NULL) ||
500 (_entryCount == 0))
501 {
502 return PV_ERROR;
503 }
504
505 if (samplenum < currSampleCount)
506 { // Sample num within current entry
507 if (_parsing_mode == 1)
508 CheckAndParseEntry(currEC);
509
510 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForSampleNumber- Time StampOffset = %d", _psampleOffsetVec[currEC%_stbl_buff_size]));
511 return _psampleOffsetVec[currEC%_stbl_buff_size];
512 }
513 else
514 {
515
516 for (uint32 i = currEC + 1; i < _entryCount; i++)
517 {
518 if (_parsing_mode == 1)
519 CheckAndParseEntry(i);
520
521
522 if (samplenum < (currSampleCount + _psampleCountVec[i%_stbl_buff_size]))
523 {
524 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForSampleNumber- Time StampOffset = %d", _psampleOffsetVec[i%_stbl_buff_size]));
525 return _psampleOffsetVec[i%_stbl_buff_size];
526 }
527 else
528 {
529 currSampleCount += _psampleCountVec[i%_stbl_buff_size];
530 }
531 }
532 }
533
534 // Went past end of list - not a valid sample number
535 return PV_ERROR;
536 }
537
getTimeOffsetForSampleNumber(uint32 num)538 int32 CompositionOffsetAtom::getTimeOffsetForSampleNumber(uint32 num)
539 {
540 uint32 currSample = 0;
541 uint32 currEC = 0;
542
543 if (iMarkerTableCreation == true)
544 {
545 uint32 MT_EC = num / (MT_SAMPLECOUNT_INCREMENT - 1); //where MT_SAMPLECOUNT_INCREMENT is the granuality of sample separation in Marker Table
546
547 if (MT_EC > ((_iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT) - 1))
548 {
549 //boundary check, MT_EC valid value will always be between 0 to (_samples_count/MT_SAMPLECOUNT_INCREMENT)-1
550 MT_EC = (_iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT) - 1;
551 }
552 //assign the last marker entry count created till now to look for sample from this location onwards instead of from start
553 if (MT_EC > MT_Counter)
554 MT_EC = MT_Counter;
555
556 while ((num < MT_SampleCount[MT_EC]) && (MT_EC > 0))
557 {
558 //This check was put keeping in mind that it may happen (due to rounding off error),
559 //that we choose a MT_EC greater than desired. So to avoid such a scenario.
560 MT_EC = MT_EC - 1;
561 currSample = MT_SampleCount[MT_EC];
562 currEC = MT_EntryCount[MT_EC];
563 }
564
565 currSample = MT_SampleCount[MT_EC];
566 currEC = MT_EntryCount[MT_EC];
567
568
569
570 return getTimeOffsetFromMT(num, currEC, currSample);
571 }
572 else
573 {
574 if ((_psampleOffsetVec == NULL) ||
575 (_psampleCountVec == NULL) ||
576 (_entryCount == 0))
577 {
578 return PV_ERROR;
579 }
580
581 uint32 sampleCount = 0;
582
583 for (uint32 i = 0; i < _entryCount; i++)
584 {
585 if (_parsing_mode == 1)
586 CheckAndParseEntry(i);
587
588 if (num < (sampleCount + _psampleCountVec[i%_stbl_buff_size]))
589 { // Sample num within current entry
590
591 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "CompositionOffsetAtom::getTimestampForSampleNumber- Time StampOffset = %d", _psampleOffsetVec[i%_stbl_buff_size]));
592 return _psampleOffsetVec[i%_stbl_buff_size];
593 }
594 else
595 {
596 sampleCount += _psampleCountVec[i%_stbl_buff_size];
597 }
598 }
599
600 // Went past end of list - not a valid sample number
601 return PV_ERROR;
602 }
603 }
604
605 int32
resetStateVariables()606 CompositionOffsetAtom::resetStateVariables()
607 {
608 uint32 sampleNum = 0;
609 return (resetStateVariables(sampleNum));
610 }
611
612 int32
resetStateVariables(uint32 sampleNum)613 CompositionOffsetAtom::resetStateVariables(uint32 sampleNum)
614 {
615 _currGetSampleCount = 0;
616 _currGetIndex = -1;
617 _currGetTimeOffset = 0;
618 _currPeekSampleCount = 0;
619 _currPeekIndex = -1;
620 _currPeekTimeOffset = 0;
621
622 // It is assumed that sample 0 has a ts of 0 - i.e. the first
623 // entry in the table starts with the delta between sample 1 and sample 0
624 if ((_psampleOffsetVec == NULL) ||
625 (_psampleCountVec == NULL) ||
626 (_entryCount == 0))
627 {
628 return PV_ERROR;
629 }
630
631 if (_parsing_mode)
632 {
633 if (_parsed_entry_cnt == 0)
634 {
635 ParseEntryUnit(sampleNum);
636 }
637 }
638
639 for (uint32 i = 0; i < _entryCount; i++)
640 {
641 _currPeekIndex++;
642 _currPeekSampleCount += _psampleCountVec[i%_stbl_buff_size];
643 _currPeekTimeOffset = _psampleOffsetVec[i%_stbl_buff_size];
644
645 _currGetIndex++;
646 _currGetSampleCount += _psampleCountVec[i%_stbl_buff_size];
647 _currGetTimeOffset = _psampleOffsetVec[i%_stbl_buff_size];
648
649 if (sampleNum <= _currPeekSampleCount)
650 {
651 return (EVERYTHING_FINE);
652 }
653
654 }
655
656 // Went past end of list - not a valid sample number
657 return PV_ERROR;
658 }
659
resetPeekwithGet()660 int32 CompositionOffsetAtom::resetPeekwithGet()
661 {
662 _currPeekSampleCount = _currGetSampleCount;
663 _currPeekIndex = _currGetIndex;
664 _currPeekTimeOffset = _currGetTimeOffset;
665 return (EVERYTHING_FINE);
666 }
667
CheckAndParseEntry(uint32 i)668 void CompositionOffsetAtom::CheckAndParseEntry(uint32 i)
669 {
670 if (i >= _parsed_entry_cnt)
671 {
672 ParseEntryUnit(i);
673 }
674 else
675 {
676 uint32 entryLoc = i / _stbl_buff_size;
677 if (_curr_buff_number != entryLoc)
678 {
679 _parsed_entry_cnt = entryLoc * _stbl_buff_size;
680 while (_parsed_entry_cnt <= i)
681 ParseEntryUnit(_parsed_entry_cnt);
682 }
683 }
684 }
685
Run()686 void CompositionOffsetAtom::Run()
687 {
688 // Create it for the first time
689 if ((MT_SampleCount == NULL) && (MT_EntryCount == NULL))
690 {
691 int32 status = createMarkerTable();
692 if (status == PVMFFailure)
693 {
694 OSCL_LEAVE(OsclErrNoMemory);
695 }
696 iMarkerTableCreation = true;
697 }
698
699 populateMarkerTable();
700
701 // check for entry count being exhausted.. table iterated completely
702 if ((entrycountTraversed < _entryCount) && (refSample < _iTotalNumSamplesInTrack)
703 && (MT_Counter < _iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT))
704 {
705 RunIfNotReady();
706 }
707
708 return;
709
710 }
711 //Populate the Marker Table with SampleCount and EntryCount values
712 //for every nth sample starting from n-1, where n=MT_SAMPLECOUNT_INCREMENT.
713
populateMarkerTable()714 uint32 CompositionOffsetAtom::populateMarkerTable()
715 {
716 uint32 increment = MT_SAMPLECOUNT_INCREMENT;
717 uint32 numPopulated = 0;
718
719
720
721 for (uint32 i = entrycountTraversed; i < _entryCount; i++)
722 {
723
724 if (refSample < _iTotalNumSamplesInTrack)
725 {
726
727 if (i == 0)
728 {
729 if (_parsing_mode == 1)
730 CheckAndParseEntry(i);
731
732 MT_SampleCount[0] = _psampleCountVec[i%_stbl_buff_size];
733 prevSampleCount = MT_SampleCount[0];
734 addSampleCount = MT_SampleCount[0];
735 }
736 else if (addSampleCount < refSample)
737 {
738 if (_parsing_mode == 1)
739 CheckAndParseEntry(MT_j);
740
741 prevSampleCount = addSampleCount;
742 addSampleCount += _psampleCountVec[MT_j%_stbl_buff_size];
743 MT_j++;
744 }
745 else
746 {
747 entrycountTraversed = i - 1;
748 i = i - 1;
749 refSample += increment;
750 MT_SampleCount[MT_Counter] = prevSampleCount;
751 //Incase SampleCounts have same value for consecutive MT entries,
752 //even the same EntryCount should be mentioned in the Marker Table.
753 if (MT_SampleCount[MT_Counter] == MT_SampleCount[MT_Counter-1])
754 {
755 MT_EntryCount[MT_Counter] = MT_EntryCount[MT_Counter-1];
756 }
757 else
758 {
759 MT_EntryCount[MT_Counter] = MT_j - 2;
760 }
761
762
763 MT_Counter++;
764 numPopulated++;
765 if ((numPopulated == NUMBER_OF_SAMPLE_POPULATES_PER_RUNL) ||
766 (MT_Counter >= _iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT))
767 break;
768 }
769 }
770 else
771 {
772 break;
773 }
774
775 }
776
777 return numPopulated;
778
779 }
deleteMarkerTable()780 void CompositionOffsetAtom::deleteMarkerTable()
781 {
782 if (MT_SampleCount != NULL)
783 PV_MP4_ARRAY_DELETE(NULL, MT_SampleCount);
784
785 if (MT_EntryCount != NULL)
786 PV_MP4_ARRAY_DELETE(NULL, MT_EntryCount);
787 }
788 // responsible for creation of data sturcture inside the table.
createMarkerTable()789 PVMFStatus CompositionOffsetAtom::createMarkerTable()
790 {
791
792 MT_Table_Size = (_iTotalNumSamplesInTrack / MT_SAMPLECOUNT_INCREMENT);
793 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (MT_Table_Size), MT_SampleCount);
794
795 if (MT_SampleCount == NULL)
796 {
797 PV_MP4_ARRAY_DELETE(NULL, MT_SampleCount);
798 MT_SampleCount = NULL;
799 _success = false;
800 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
801 return PVMFFailure;
802 }
803
804 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (MT_Table_Size), MT_EntryCount);
805
806 if (MT_EntryCount == NULL)
807 {
808 PV_MP4_ARRAY_DELETE(NULL, MT_EntryCount);
809 MT_EntryCount = NULL;
810 PV_MP4_ARRAY_DELETE(NULL, MT_SampleCount);
811 MT_SampleCount = NULL;
812 _success = false;
813 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
814 return PVMFFailure;
815 }
816
817 for (uint32 idx = 0; idx < MT_Table_Size; idx++) //initialization
818 {
819
820 MT_EntryCount[idx] = 0;
821 MT_SampleCount[idx] = 0;
822 }
823
824 return PVMFSuccess;
825 }
826
827
828