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 This PVA_FF_TrackAtom Class fp the container for a single track in the MPEG-4
20 presentation.
21 */
22
23 #define IMPLEMENT_TrackAtom
24
25 #include "trackatom.h"
26 #include "a_atomdefs.h"
27 #include "atomutils.h"
28
29 typedef Oscl_Vector<uint32, OsclMemAllocator> uint32VecType;
30 typedef Oscl_Vector<int32, OsclMemAllocator> int32VecType;
31 typedef Oscl_Vector<uint8, OsclMemAllocator> uint8VecType;
32
33 // Constructor
PVA_FF_TrackAtom(int32 type,uint32 id,uint32 fileAuthoringFlags,int32 codecType,uint32 protocol,uint8 profile,uint8 profileComp,uint8 level)34 PVA_FF_TrackAtom::PVA_FF_TrackAtom(int32 type,
35 uint32 id,
36 uint32 fileAuthoringFlags,
37 int32 codecType,
38 uint32 protocol,
39 uint8 profile,
40 uint8 profileComp,
41 uint8 level)
42 : PVA_FF_Atom(TRACK_ATOM)
43 {
44 _success = true;
45 FIRST_SAMPLE = true;
46 _intialTrackTimeOffsetInMilliSeconds = 0;
47
48 _eList = NULL;
49 _mediaType = type;
50
51 _codecType = codecType;
52
53 _oInterLeaveMode = false;
54 if (fileAuthoringFlags & PVMP4FF_SET_MEDIA_INTERLEAVE_MODE)
55 {
56 _oInterLeaveMode = true;
57 }
58
59
60 _pUserDataAtom = NULL;
61
62 if ((codecType == CODEC_TYPE_MPEG4_VIDEO) ||
63 (codecType == CODEC_TYPE_AAC_AUDIO))
64 {
65 _setDecoderSpecificInfoDone = false;
66 }
67 else
68 {
69 _setDecoderSpecificInfoDone = true;
70 }
71
72 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_TrackHeaderAtom, (type, id, (uint8)0, (uint32)0x000001, fileAuthoringFlags), _ptrackHeader);
73
74 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaAtom, (type,
75 codecType,
76 fileAuthoringFlags,
77 protocol, profile,
78 profileComp, level),
79 _pmediaAtom);
80
81 _ptrackReference = NULL;
82 recomputeSize();
83
84 _ptrackHeader->setParent(this);
85 _pmediaAtom->setParent(this);
86 }
87
88 // Destructor
~PVA_FF_TrackAtom()89 PVA_FF_TrackAtom::~PVA_FF_TrackAtom()
90 {
91 PV_MP4_FF_DELETE(NULL, PVA_FF_TrackHeaderAtom, _ptrackHeader);
92
93 PV_MP4_FF_DELETE(NULL, PVA_FF_MediaAtom, _pmediaAtom);
94
95 if (_ptrackReference != NULL)
96 {
97 PV_MP4_FF_DELETE(NULL, PVA_FF_TrackReferenceAtom, _ptrackReference);
98 }
99
100 if (_eList != NULL)
101 {
102 PV_MP4_FF_DELETE(NULL, PVA_FF_EditAtom, _eList);
103 }
104
105 if (_pUserDataAtom != NULL)
106 {
107 PV_MP4_FF_DELETE(NULL, PVA_FF_UserDataAtom, _pUserDataAtom);
108 }
109 }
110
111 void
nextSample(int32 mediaType,void * psample,uint32 size,uint32 ts,uint8 flags,uint32 baseOffset,bool oChunkStart)112 PVA_FF_TrackAtom::nextSample(int32 mediaType,
113 void *psample,
114 uint32 size,
115 uint32 ts,
116 uint8 flags,
117 uint32 baseOffset,
118 bool oChunkStart)
119 {
120 uint32 ts_in_milliseconds = 0;
121 uint32 mediaTimeScale = getMediaTimeScale();
122
123 if (mediaTimeScale != 0)
124 {
125 ts_in_milliseconds = (uint32)((ts * 1000.0f) / mediaTimeScale);
126
127 // Add sample to track header so can update its _duration
128 // which is supposed to be in movie time scale
129 _ptrackHeader->addSample(ts_in_milliseconds);
130 }
131
132 if (FIRST_SAMPLE)
133 {
134 FIRST_SAMPLE = false;
135 if (ts != 0)
136 {
137 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_EditAtom, (), _eList);
138
139 _eList->setParent(this);
140
141 //Edit durations are sposed to be movie time scale
142 _eList->addEmptyEdit(ts_in_milliseconds);
143
144 _intialTrackTimeOffsetInMilliSeconds = ts_in_milliseconds;
145 }
146 else
147 {
148 _eList = NULL;
149 }
150 }
151
152 _pmediaAtom->nextSample(mediaType, psample, size, ts,
153 flags, baseOffset, oChunkStart);
154 }
155
156 void
nextTextSample(int32 mediaType,void * psample,uint32 size,uint32 ts,uint8 flags,int32 index,uint32 baseOffset,bool oChunkStart)157 PVA_FF_TrackAtom::nextTextSample(int32 mediaType,
158 void *psample,
159 uint32 size,
160 uint32 ts,
161 uint8 flags,
162 int32 index,
163 uint32 baseOffset,
164 bool oChunkStart)
165 {
166 uint32 ts_in_milliseconds = 0;
167 uint32 mediaTimeScale = getMediaTimeScale();
168
169 if (mediaTimeScale != 0)
170 {
171 ts_in_milliseconds = (uint32)((ts * 1000.0f) / mediaTimeScale);
172
173 // Add sample to track header so can update its _duration
174 // which is supposed to be in movie time scale
175 _ptrackHeader->addSample(ts_in_milliseconds);
176 }
177
178 if (FIRST_SAMPLE)
179 {
180 FIRST_SAMPLE = false;
181 if (ts != 0)
182 {
183 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_EditAtom, (), _eList);
184
185 _eList->setParent(this);
186
187 //Edit durations are sposed to be movie time scale
188 _eList->addEmptyEdit(ts_in_milliseconds);
189
190 _intialTrackTimeOffsetInMilliSeconds = ts_in_milliseconds;
191 }
192 else
193 {
194 _eList = NULL;
195 }
196 }
197
198 _pmediaAtom->nextTextSample(mediaType, psample, size, ts,
199 flags, index, baseOffset, oChunkStart);
200 }
201
202 void
nextSample(int32 mediaType,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 size,uint32 ts,uint8 flags,uint32 baseOffset,bool oChunkStart)203 PVA_FF_TrackAtom::nextSample(int32 mediaType,
204 Oscl_Vector <OsclMemoryFragment, OsclMemAllocator>& fragmentList,
205 uint32 size,
206 uint32 ts,
207 uint8 flags,
208 uint32 baseOffset,
209 bool oChunkStart)
210 {
211 uint32 ts_in_milliseconds = 0;
212 uint32 mediaTimeScale = getMediaTimeScale();
213
214 if (mediaTimeScale != 0)
215 {
216 ts_in_milliseconds = (uint32)((ts * 1000.0f) / mediaTimeScale);
217
218 // Add sample to track header so can update its _duration
219 // which is supposed to be in movie time scale
220 _ptrackHeader->addSample(ts_in_milliseconds);
221 }
222
223 if (FIRST_SAMPLE)
224 {
225 FIRST_SAMPLE = false;
226 if (ts != 0)
227 {
228 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_EditAtom, (), _eList);
229
230 _eList->setParent(this);
231
232 //Edit durations are sposed to be movie time scale
233 _eList->addEmptyEdit(ts_in_milliseconds);
234
235 _intialTrackTimeOffsetInMilliSeconds = ts_in_milliseconds;
236 }
237 else
238 {
239 _eList = NULL;
240 }
241 }
242
243 _pmediaAtom->nextSample(mediaType, fragmentList, size, ts,
244 flags, baseOffset, oChunkStart);
245
246 }
247
248 void
nextTextSample(int32 mediaType,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 size,uint32 ts,uint8 flags,int32 index,uint32 baseOffset,bool oChunkStart)249 PVA_FF_TrackAtom::nextTextSample(int32 mediaType,
250 Oscl_Vector <OsclMemoryFragment, OsclMemAllocator>& fragmentList,
251 uint32 size,
252 uint32 ts,
253 uint8 flags,
254 int32 index,
255 uint32 baseOffset,
256 bool oChunkStart)
257 {
258 uint32 ts_in_milliseconds = 0;
259 uint32 mediaTimeScale = getMediaTimeScale();
260
261 if (mediaTimeScale != 0)
262 {
263 ts_in_milliseconds = (uint32)((ts * 1000.0f) / mediaTimeScale);
264
265 // Add sample to track header so can update its _duration
266 // which is supposed to be in movie time scale
267 _ptrackHeader->addSample(ts_in_milliseconds);
268 }
269
270 if (FIRST_SAMPLE)
271 {
272 FIRST_SAMPLE = false;
273 if (ts != 0)
274 {
275 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_EditAtom, (), _eList);
276
277 _eList->setParent(this);
278
279 //Edit durations are sposed to be movie time scale
280 _eList->addEmptyEdit(ts_in_milliseconds);
281
282 _intialTrackTimeOffsetInMilliSeconds = ts_in_milliseconds;
283 }
284 else
285 {
286 _eList = NULL;
287 }
288 }
289
290 _pmediaAtom->nextTextSample(mediaType, fragmentList, size, ts,
291 flags, index, baseOffset, oChunkStart);
292
293 }
294
295 bool
reAuthorFirstSample(uint32 size,uint32 baseOffset)296 PVA_FF_TrackAtom::reAuthorFirstSample(uint32 size,
297 uint32 baseOffset)
298 {
299 return(
300 _pmediaAtom->reAuthorFirstSample(size,
301 baseOffset));
302 }
303
304 int32
addTrackReference(uint32 ref)305 PVA_FF_TrackAtom::addTrackReference(uint32 ref)
306 {
307 if (_ptrackReference == NULL)
308 {
309 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_TrackReferenceAtom, (TREF_TYPE_DEPEND), _ptrackReference);
310 _ptrackReference->setParent(this);
311 }
312
313 if (_ptrackReference != NULL)
314 {
315 return _ptrackReference->addTrackReference(ref);
316 }
317 return 0;
318 }
319
320 // Create methods for the optional member atoms
321 void
createTrackReferenceAtom()322 PVA_FF_TrackAtom::createTrackReferenceAtom()
323 {
324 // Empty
325 }
326
327 void
createEditAtom()328 PVA_FF_TrackAtom::createEditAtom()
329 {
330 // Empty
331 }
332
333 // Recomputes the size of the current atom by checking all contained atoms
334 void
recomputeSize()335 PVA_FF_TrackAtom::recomputeSize()
336 {
337 int32 size = getDefaultSize(); // From base class
338
339 if (_pUserDataAtom != NULL)
340 {
341 size += _pUserDataAtom->getSize();
342 }
343
344 if (_eList != NULL)
345 {
346 size += _eList->getSize();
347 }
348 size += _ptrackHeader->getSize();
349 size += _pmediaAtom->getSize();
350 if (_ptrackReference != NULL)
351 {
352 size += _ptrackReference->getSize();
353 }
354 _size = size;
355
356 // Update the size of the parent atom since this child atom may have changed
357 if (_pparent != NULL)
358 {
359 _pparent->recomputeSize();
360 }
361 }
362
363 // Rendering the PVA_FF_Atom in proper format (bitlengths, etc.) to an ostream
364 bool
renderToFileStream(MP4_AUTHOR_FF_FILE_IO_WRAP * fp)365 PVA_FF_TrackAtom::renderToFileStream(MP4_AUTHOR_FF_FILE_IO_WRAP *fp)
366 {
367 int32 rendered = 0; // Keep track of number of bytes rendered
368
369 uint32 creationTime = _ptrackHeader->getCreationTime();
370 uint32 modTime = _ptrackHeader->getModificationTime();
371
372 PVA_FF_MediaHeaderAtom *mdhdPtr = _pmediaAtom->getMediaHeaderAtomPtr();
373
374 mdhdPtr->setCreationTime(creationTime);
375 mdhdPtr->setModificationTime(modTime);
376
377 recomputeSize();
378
379 // Render PVA_FF_Atom type and size
380 renderAtomBaseMembers(fp);
381 rendered += getDefaultSize();
382
383 // Set ESID
384 _pmediaAtom->setESID((uint16)(_ptrackHeader->getTrackID()));
385 {
386 if (_pUserDataAtom != NULL)
387 {
388 if (!_pUserDataAtom->renderToFileStream(fp))
389 {
390 return false;
391 }
392 }
393 }
394 // Render the track header atom
395 if (!_ptrackHeader->renderToFileStream(fp))
396 {
397 return false;
398 }
399 rendered += getTrackHeaderAtom().getSize();
400
401 //Render Edit atom
402 if (_eList != NULL)
403 {
404 if (!_eList->renderToFileStream(fp))
405 {
406 return false;
407 }
408 }
409
410 // Render trackReference atom if present
411 if (_ptrackReference != NULL)
412 {
413 if (!_ptrackReference->renderToFileStream(fp))
414 {
415 return false;
416 }
417 }
418
419 // Render the media atom
420 if (!_pmediaAtom->renderToFileStream(fp))
421 {
422 return false;
423 }
424 rendered += getMediaAtom().getSize();
425
426 return true;
427 }
428
429 void
prepareToRender()430 PVA_FF_TrackAtom::prepareToRender()
431 {
432 if (_eList != NULL)
433 {
434 //subtract any intial time offset
435 uint32 segDuration = getDuration();
436
437 segDuration -= _intialTrackTimeOffsetInMilliSeconds;
438
439 _eList->addEditEntry(segDuration, 0, 1);
440 }
441 recomputeSize();
442 }
443
444 uint32
convertTrackDurationToMediaTimeScale(uint32 duration)445 PVA_FF_TrackAtom::convertTrackDurationToMediaTimeScale(uint32 duration)
446 {
447 uint32 mediaHeaderDuration = 0;
448
449 float timescaleconversionFactor = 0;
450 uint32 mediaTimeScale = getMediaTimeScale();
451
452 if (mediaTimeScale >= 1000)
453 {
454 timescaleconversionFactor = mediaTimeScale / 1000.0f;
455 }
456 if (timescaleconversionFactor > 0)
457 {
458 mediaHeaderDuration = (uint32)(duration * timescaleconversionFactor);
459 }
460 else
461 {
462 float temp = (float)(duration * mediaTimeScale);
463 mediaHeaderDuration = (uint32)(temp / 1000.00f);
464 }
465 return (mediaHeaderDuration);
466 }
467
468 // in movie fragment mode set the actual duration of
469 // last sample
470 void
updateLastTSEntry(uint32 ts)471 PVA_FF_TrackAtom::updateLastTSEntry(uint32 ts)
472 {
473 uint32 ts_in_milliseconds = 0;
474 uint32 mediaTimeScale = getMediaTimeScale();
475 if (mediaTimeScale != 0)
476 {
477 ts_in_milliseconds = (uint32)((ts * 1000.0f) / mediaTimeScale);
478 _ptrackHeader->updateLastTSEntry(ts_in_milliseconds);
479 }
480
481 _pmediaAtom->updateLastTSEntry(ts);
482
483 }
484
485 void
SetMaxSampleSize(uint32 aSize)486 PVA_FF_TrackAtom::SetMaxSampleSize(uint32 aSize)
487 {
488 _pmediaAtom->SetMaxSampleSize(aSize);
489 }
490
491 void
writeMaxSampleSize(MP4_AUTHOR_FF_FILE_IO_WRAP * _afp)492 PVA_FF_TrackAtom::writeMaxSampleSize(MP4_AUTHOR_FF_FILE_IO_WRAP *_afp)
493 {
494 _pmediaAtom->writeMaxSampleSize(_afp);
495 }
496
497 void
setVideoParams(uint32 frame_width,uint32 frame_height)498 PVA_FF_TrackAtom::setVideoParams(uint32 frame_width, uint32 frame_height)
499 {
500 if (_ptrackHeader != NULL)
501 _ptrackHeader->setVideoWidthHeight((int16)frame_width, (int16)frame_height);
502
503 if (_pmediaAtom != NULL)
504 _pmediaAtom->setVideoParams(frame_width, frame_height);
505 }
506
507 void
setAudioEncodeParams(PVMP4FFComposerAudioEncodeParams & audioParams)508 PVA_FF_TrackAtom::setAudioEncodeParams(PVMP4FFComposerAudioEncodeParams &audioParams)
509 {
510 if (_pmediaAtom != NULL)
511 _pmediaAtom->setAudioEncodeParams(audioParams);
512 }
513