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