• 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 Track Fragment Atom Class                             */
21 /*     -------------------------------------------------------------------       */
22 /*********************************************************************************/
23 /*
24 */
25 
26 #define IMPLEMENT_MovieFragmentRandomAccessAtom
27 
28 #include "atomdefs.h"
29 #include "atomutils.h"
30 #include "moviefragmentrandomaccess.h"
31 
32 typedef Oscl_Vector<TrackFragmentRandomAccessAtom*, OsclMemAllocator> trackFragmentRandomAccessAtomVecType;
33 
34 // Constructor
MovieFragmentRandomAccessAtom(MP4_FF_FILE * fp,uint32 size,uint32 type)35 MovieFragmentRandomAccessAtom::MovieFragmentRandomAccessAtom(MP4_FF_FILE *fp,
36         uint32 size,
37         uint32 type)
38         : Atom(fp, size, type)
39 {
40     _pTrackFragmentRandomAccessAtomVec      = NULL;
41     _pMfraOffsetAtom = NULL;
42 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT)
43     // This will store the entry count of TFRA for Video for Vonly,AVT,AV,VT clips and Audio TFRA entry count for Aonly,AT clips
44     // and Text TFRA entry count for Tonly clips.
45     oVideoAudioTextTrackTfraCount = 0;
46 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
47 
48     iLogger = PVLogger::GetLoggerObject("mp4ffparser");
49     iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
50     iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
51 
52     uint32 count = size - DEFAULT_ATOM_SIZE;
53     if (_success)
54     {
55         PV_MP4_FF_NEW(fp->auditCB, trackFragmentRandomAccessAtomVecType, (), _pTrackFragmentRandomAccessAtomVec);
56         while (count > 0)
57         {
58             uint32 atomType = UNKNOWN_ATOM;
59             uint32 atomSize = 0;
60             AtomUtils::getNextAtomType(fp, atomSize, atomType);
61 
62             if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_ATOM)
63             {
64                 if (_pMfraOffsetAtom == NULL)
65                 {
66                     PV_MP4_FF_NEW(fp->auditCB, MfraOffsetAtom, (fp, atomSize, atomType), _pMfraOffsetAtom);
67                     if (!_pMfraOffsetAtom->MP4Success())
68                     {
69                         _success = false;
70                         _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_FAILED;
71                         return;
72                     }
73                     count -= _pMfraOffsetAtom->getSize();
74                 }
75                 else
76                 {
77                     //duplicate atom
78                     count -= atomSize;
79                     atomSize -= DEFAULT_ATOM_SIZE;
80                     AtomUtils::seekFromCurrPos(fp, atomSize);
81                 }
82             }
83             else if (atomType == TRACK_FRAGMENT_RANDOM_ACCESS_ATOM)
84             {
85                 TrackFragmentRandomAccessAtom *pTrackFragmentRandomAccessAtom = NULL;
86                 PV_MP4_FF_NEW(fp->auditCB, TrackFragmentRandomAccessAtom, (fp, atomSize, atomType),
87                               pTrackFragmentRandomAccessAtom);
88                 if (!pTrackFragmentRandomAccessAtom->MP4Success())
89                 {
90                     PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, pTrackFragmentRandomAccessAtom);
91                     _success = false;
92                     _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
93                     return;
94                 }
95                 count -= pTrackFragmentRandomAccessAtom->getSize();
96                 _pTrackFragmentRandomAccessAtomVec->push_back(pTrackFragmentRandomAccessAtom);
97             }
98 
99         }
100     }
101     else
102     {
103         _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
104     }
105 }
106 
~MovieFragmentRandomAccessAtom()107 MovieFragmentRandomAccessAtom::~MovieFragmentRandomAccessAtom()
108 {
109     if (_pMfraOffsetAtom != NULL)
110     {
111         PV_MP4_FF_DELETE(NULL, MfraOffsetAtom, _pMfraOffsetAtom);
112     }
113 
114     for (uint32 i = 0; i < _pTrackFragmentRandomAccessAtomVec->size(); i++)
115     {
116         PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, (*_pTrackFragmentRandomAccessAtomVec)[i]);
117     }
118     PV_MP4_FF_TEMPLATED_DELETE(NULL, trackFragmentRandomAccessAtomVecType, Oscl_Vector, _pTrackFragmentRandomAccessAtomVec);
119 
120 }
121 
IsTFRAPresentForTrack(uint32 trackID,bool oVideoAudioTextTrack)122 bool MovieFragmentRandomAccessAtom::IsTFRAPresentForTrack(uint32 trackID, bool oVideoAudioTextTrack)
123 {
124 
125     uint32 num_tfra = 0;
126     if (_pTrackFragmentRandomAccessAtomVec != NULL)
127     {
128         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
129         for (uint32 idx = 0; idx < num_tfra; idx++)
130         {
131             TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
132             if (tfraAtom->getTrackID() == trackID)
133             {
134                 if (tfraAtom->_entry_count > 0)
135                 {
136 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT)
137                     if (oVideoAudioTextTrack)
138                     {
139                         oVideoAudioTextTrackTfraCount = tfraAtom->_entry_count;
140                         // If oVideoAudioTextTrack flag is set we just store the entry count to be checked
141                         // for other tracks.
142                         return true;
143                     }
144                     else if (oVideoAudioTextTrackTfraCount == tfraAtom->_entry_count)
145 #else
146                     OSCL_UNUSED_ARG(oVideoAudioTextTrack);
147 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
148                     {
149                         return true;
150                     }
151                 }
152             }
153         }
154     }
155     return false;
156 
157 }
getSyncSampleInfoClosestToTime(uint32 trackID,uint32 & time,uint32 & moof_offset,uint32 & traf_number,uint32 & trun_number,uint32 & sample_num)158 int32 MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime(uint32 trackID, uint32 &time, uint32 &moof_offset,
159         uint32 &traf_number, uint32 &trun_number,
160         uint32 &sample_num)
161 {
162     uint32 num_tfra = 0;
163     PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time));
164     if (_pTrackFragmentRandomAccessAtomVec == NULL)
165     {
166         return -1;
167     };
168     num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
169     for (uint32 idx = 0; idx < num_tfra; idx++)
170     {
171         TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
172         if (! tfraAtom)     // (unlikely)
173             return -1;
174         if (tfraAtom->getTrackID() == trackID)
175         {
176             uint32 entries = tfraAtom->_entry_count;
177             if (entries == 0)
178                 return -1;
179 
180             Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
181             if (!tfraEntries)       // unlikely/error
182                 return -1;
183             int32 prevTime = 0;
184             for (uint32 idy = 0; idy < entries; idy++)
185             {
186                 if (time < (*tfraEntries)[idy]->getTimeStamp())
187                 {
188                     uint32 tmp = (*tfraEntries)[idy]->getTimeStamp();
189                     uint32 diffwithbeforeTS = time - prevTime;
190                     uint32 diffwithafterTS = tmp - time;
191                     if (diffwithbeforeTS > diffwithafterTS)
192                     {
193                         time = tmp;
194                         moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset();
195                         traf_number = (*tfraEntries)[idy]->_traf_number;
196                         trun_number = (*tfraEntries)[idy]->_trun_number;
197                         sample_num = (*tfraEntries)[idy]->_sample_number;
198                         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
199                         return 0;
200                     }
201                     else
202                     {
203                         time = prevTime;
204                         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
205                         return 0;
206                     }
207                 }
208                 moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset();
209                 traf_number = (*tfraEntries)[idy]->_traf_number;
210                 trun_number = (*tfraEntries)[idy]->_trun_number;
211                 sample_num = (*tfraEntries)[idy]->_sample_number;
212 
213                 prevTime = (*tfraEntries)[idy]->getTimeStamp();
214             }
215             time = prevTime;
216             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
217             return 0;
218         }
219     }
220 
221     // error return if we get here.
222     return -1;
223 }
224 
queryRepositionTime(uint32 trackID,int32 time,bool oDependsOn,bool bBeforeRequestedTime)225 int32 MovieFragmentRandomAccessAtom::queryRepositionTime(uint32 trackID, int32 time, bool oDependsOn, bool bBeforeRequestedTime)
226 {
227     OSCL_UNUSED_ARG(oDependsOn);
228 
229     uint32 num_tfra = 0;
230     int32 closestTime = 0;
231     PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time));
232     if (_pTrackFragmentRandomAccessAtomVec != NULL)
233     {
234         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
235         for (uint32 idx = 0; idx < num_tfra; idx++)
236         {
237             TrackFragmentRandomAccessAtom* tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
238             if (tfraAtom->getTrackID() == trackID)
239             {
240                 uint32 entries = tfraAtom->_entry_count;
241                 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
242                 if (!tfraEntries)   // unlikely/error
243                     return closestTime;
244                 int32 prevTime = 0;
245                 for (uint32 idy = 0; idy < entries; idy++)
246                 {
247                     if (bBeforeRequestedTime)
248                     {
249                         if (time < (int32)(*tfraEntries)[idy]->getTimeStamp())
250                         {
251                             time = prevTime;
252                             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
253                             break;
254                         }
255                         else if ((time == (int32)(*tfraEntries)[idy]->getTimeStamp()) ||
256                                  ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp())))
257                         {
258                             time = (*tfraEntries)[idy]->getTimeStamp();
259                             break;
260 
261                         }
262                         prevTime = (*tfraEntries)[idy]->getTimeStamp();
263                     }
264                     else
265                     {
266                         if (time <= (int32)(*tfraEntries)[idy]->getTimeStamp())
267                         {
268                             time = (*tfraEntries)[idy]->getTimeStamp();
269                             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
270                             break;
271                         }
272                         else if ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp()))
273                         {
274                             time = (*tfraEntries)[idy]->getTimeStamp();
275                             break;
276 
277                         }
278 
279                         prevTime = (*tfraEntries)[idy]->getTimeStamp();
280 
281                     }
282                 }
283                 closestTime = time;
284                 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
285                 return closestTime;
286             }
287         }
288     }
289     return closestTime;
290 }
291 
getTimestampForRandomAccessPoints(uint32 id,uint32 * num,uint32 * tsBuf,uint32 * numBuf,uint32 * offsetBuff,uint32 samplesFromMovie)292 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPoints(uint32 id, uint32 *num, uint32 *tsBuf, uint32* numBuf, uint32* offsetBuff, uint32 samplesFromMovie)
293 {
294     uint32 num_tfra = 0;
295     uint32 samplesfromMoov = samplesFromMovie;
296     TrackFragmentRandomAccessAtom *tfraAtom = NULL;
297 
298     if (_pTrackFragmentRandomAccessAtomVec != NULL)
299     {
300         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
301 
302         for (uint32 idx = 0; idx < num_tfra; idx++)
303         {
304             tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
305             if (tfraAtom->getTrackID() == id)
306             {
307                 break;
308             }
309         }
310     }
311     if (tfraAtom != NULL)
312     {
313         uint32 entries = tfraAtom->_entry_count;
314         Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
315         if (!tfraEntries)       // unlikely/error
316             return 0;
317 
318 
319         uint32 tmp = entries;
320 
321         if (*num == 0)
322         {
323             *num = tmp;
324             return 1;   //success. This is only the query mode.
325         }
326 
327         uint32 sampleToBeRead = *num;
328         if (tmp < sampleToBeRead)
329             sampleToBeRead = tmp;
330 
331         for (uint32 idx = samplesfromMoov; idx < sampleToBeRead + samplesfromMoov; idx++)
332         {
333             //it may crash if this buffer is not big enough
334             if (tsBuf != NULL)
335                 tsBuf[idx] = (*tfraEntries)[idx]->getTimeStamp();
336             if (numBuf)
337                 numBuf[idx] = (*tfraEntries)[idx]->_sample_number;
338             if (offsetBuff)
339                 offsetBuff[idx] = (*tfraEntries)[idx]->getTimeMoofOffset();
340         }
341         *num = sampleToBeRead + samplesfromMoov;
342 
343         return  1;  //success
344     }
345     return 0;
346 }
347 
348 
getTimestampForRandomAccessPointsBeforeAfter(uint32 id,uint32 ts,uint32 * tsBuf,uint32 * numBuf,uint32 & numsamplestoget,uint32 howManyKeySamples)349 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPointsBeforeAfter(uint32 id, uint32 ts, uint32 *tsBuf, uint32* numBuf,
350         uint32& numsamplestoget,
351         uint32 howManyKeySamples)
352 {
353     uint32 num_tfra = 0, prevSampleNum = 0, sample_num = 0;
354     uint32 time = ts;
355     uint32 startIdx = 0, endIdx = 0;
356 
357     TrackFragmentRandomAccessAtom *tfraAtom = NULL;
358     if (_pTrackFragmentRandomAccessAtomVec != NULL)
359     {
360         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
361 
362         for (uint32 idx = 0; idx < num_tfra; idx++)
363         {
364             tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
365             if (tfraAtom != NULL)
366             {
367                 if (tfraAtom->getTrackID() == id)
368                 {
369                     break;
370                 }
371             }
372         }
373     }
374     if (tfraAtom != NULL)
375     {
376         uint32 entries = tfraAtom->_entry_count;
377         startIdx = entries;
378         endIdx = entries;
379         Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
380         if (!tfraEntries)       // unlikely/error
381             return 0;
382         int32 prevTime = 0;
383         for (uint32 idy = 0; idy < entries; idy++)
384         {
385             if (time <= (*tfraEntries)[idy]->getTimeStamp())
386             {
387                 uint32 tmp = (*tfraEntries)[idy]->getTimeStamp();
388                 uint32 diffwithbeforeTS = time - prevTime;
389                 uint32 diffwithafterTS = tmp - time;
390                 if (diffwithbeforeTS > diffwithafterTS)
391                 {
392                     sample_num = (*tfraEntries)[idy]->_sample_number;
393                 }
394                 else
395                 {
396                     sample_num = prevSampleNum;
397                 }
398                 startIdx = idy;
399                 endIdx = entries;
400                 break;
401             }
402             prevSampleNum = (*tfraEntries)[idy]->_sample_number;
403             prevTime = (*tfraEntries)[idy]->getTimeStamp();
404         }
405         if ((startIdx + howManyKeySamples) <= entries)
406             endIdx = startIdx + howManyKeySamples;
407 
408         if (startIdx > howManyKeySamples)
409             startIdx -= howManyKeySamples;
410         else
411         {
412             startIdx = 0;
413         }
414 
415         uint32 idx = 0;
416         uint32 k = 0;
417         for (idx = startIdx; idx < endIdx; idx++)
418         {
419             int32 keySampleNum = (*tfraEntries)[idx]->_sample_number;
420             int32 keySampleTS = (*tfraEntries)[idx]->getTimeStamp();
421             numBuf[k] = keySampleNum;
422             tsBuf[k] = keySampleTS;
423             k++;
424         }
425         numsamplestoget = k;
426     }
427     else
428         return 0;
429 
430     return  1;  //success
431 
432 }
433