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