• 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 /*********************************************************************************/
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