content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp

branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
equal deleted inserted replaced
-1:000000000000 0:afd1dde6dd28
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include <climits>
7 #include "TrackMetadataBase.h"
8 #include "ISOMediaBoxes.h"
9 #include "ISOControl.h"
10 #include "ISOMediaWriter.h"
11 #include "EncodedFrameContainer.h"
12 #include "ISOTrackMetadata.h"
13 #include "MP4ESDS.h"
14 #include "AMRBox.h"
15 #include "AVCBox.h"
16 #include "VideoUtils.h"
17
18 namespace mozilla {
19
20 // 14496-12 6.2.2 'Data Types and fields'
21 const uint32_t iso_matrix[] = { 0x00010000, 0, 0,
22 0, 0x00010000, 0,
23 0, 0, 0x40000000 };
24
25 uint32_t
26 set_sample_flags(bool aSync)
27 {
28 std::bitset<32> flags;
29 flags.set(16, !aSync);
30 return flags.to_ulong();
31 }
32
33 Box::BoxSizeChecker::BoxSizeChecker(ISOControl* aControl, uint32_t aSize)
34 {
35 mControl = aControl;
36 ori_size = mControl->GetBufPos();
37 box_size = aSize;
38 MOZ_COUNT_CTOR(BoxSizeChecker);
39 }
40
41 Box::BoxSizeChecker::~BoxSizeChecker()
42 {
43 uint32_t cur_size = mControl->GetBufPos();
44 if ((cur_size - ori_size) != box_size) {
45 MOZ_ASSERT(false);
46 }
47
48 MOZ_COUNT_DTOR(BoxSizeChecker);
49 }
50
51 nsresult
52 MediaDataBox::Generate(uint32_t* aBoxSize)
53 {
54 mFirstSampleOffset = size;
55 mAllSampleSize = 0;
56
57 if (mTrackType & Audio_Track) {
58 FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
59 mAllSampleSize += frag->GetFirstFragmentSampleSize();
60 }
61 if (mTrackType & Video_Track) {
62 FragmentBuffer* frag = mControl->GetFragment(Video_Track);
63 mAllSampleSize += frag->GetFirstFragmentSampleSize();
64 }
65
66 size += mAllSampleSize;
67 *aBoxSize = size;
68 return NS_OK;
69 }
70
71 nsresult
72 MediaDataBox::Write()
73 {
74 nsresult rv;
75 BoxSizeChecker checker(mControl, size);
76 Box::Write();
77 nsTArray<uint32_t> types;
78 types.AppendElement(Audio_Track);
79 types.AppendElement(Video_Track);
80
81 for (uint32_t l = 0; l < types.Length(); l++) {
82 if (mTrackType & types[l]) {
83 FragmentBuffer* frag = mControl->GetFragment(types[l]);
84 nsTArray<nsRefPtr<EncodedFrame>> frames;
85
86 // Here is the last time we get fragment frames, flush it!
87 rv = frag->GetFirstFragment(frames, true);
88 NS_ENSURE_SUCCESS(rv, rv);
89
90 uint32_t len = frames.Length();
91 for (uint32_t i = 0; i < len; i++) {
92 nsTArray<uint8_t> frame_buffer;
93 frames.ElementAt(i)->SwapOutFrameData(frame_buffer);
94 mControl->WriteAVData(frame_buffer);
95 }
96 }
97 }
98
99 return NS_OK;
100 }
101
102 MediaDataBox::MediaDataBox(uint32_t aTrackType, ISOControl* aControl)
103 : Box(NS_LITERAL_CSTRING("mdat"), aControl)
104 , mAllSampleSize(0)
105 , mFirstSampleOffset(0)
106 , mTrackType(aTrackType)
107 {
108 MOZ_COUNT_CTOR(MediaDataBox);
109 }
110
111 MediaDataBox::~MediaDataBox()
112 {
113 MOZ_COUNT_DTOR(MediaDataBox);
114 }
115
116 uint32_t
117 TrackRunBox::fillSampleTable()
118 {
119 uint32_t table_size = 0;
120 nsresult rv;
121 nsTArray<nsRefPtr<EncodedFrame>> frames;
122 FragmentBuffer* frag = mControl->GetFragment(mTrackType);
123
124 rv = frag->GetFirstFragment(frames);
125 if (NS_FAILED(rv)) {
126 return 0;
127 }
128 uint32_t len = frames.Length();
129 sample_info_table = new tbl[len];
130 // Create sample table according to 14496-12 8.8.8.2.
131 for (uint32_t i = 0; i < len; i++) {
132 // Sample size.
133 sample_info_table[i].sample_size = 0;
134 if (flags.to_ulong() & flags_sample_size_present) {
135 sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length();
136 mAllSampleSize += sample_info_table[i].sample_size;
137 table_size += sizeof(uint32_t);
138 }
139
140 // Sample flags.
141 sample_info_table[i].sample_flags = 0;
142 if (flags.to_ulong() & flags_sample_flags_present) {
143 sample_info_table[i].sample_flags =
144 set_sample_flags(
145 (frames.ElementAt(i)->GetFrameType() == EncodedFrame::AVC_I_FRAME));
146 table_size += sizeof(uint32_t);
147 }
148
149 // Sample duration.
150 sample_info_table[i].sample_duration = 0;
151 if (flags.to_ulong() & flags_sample_duration_present) {
152 // Calculate each frame's duration, it is decided by "current frame
153 // timestamp - last frame timestamp".
154 uint64_t frame_time = 0;
155 if (i == 0) {
156 frame_time = frames.ElementAt(i)->GetTimeStamp() -
157 frag->GetLastFragmentLastFrameTime();
158 } else {
159 frame_time = frames.ElementAt(i)->GetTimeStamp() -
160 frames.ElementAt(i - 1)->GetTimeStamp();
161 // Keep the last frame time of current fagment, it will be used to calculate
162 // the first frame duration of next fragment.
163 if ((len - 1) == i) {
164 frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp());
165 }
166 }
167
168 // In TrackRunBox, there should be exactly one type, either audio or video.
169 MOZ_ASSERT((mTrackType & Video_Track) ^ (mTrackType & Audio_Track));
170 sample_info_table[i].sample_duration = (mTrackType & Video_Track ?
171 frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S :
172 frame_time * mAudioMeta->GetAudioSampleRate() / USECS_PER_S);
173
174 table_size += sizeof(uint32_t);
175 }
176
177 sample_info_table[i].sample_composition_time_offset = 0;
178 }
179 return table_size;
180 }
181
182 nsresult
183 TrackRunBox::Generate(uint32_t* aBoxSize)
184 {
185 FragmentBuffer* frag = mControl->GetFragment(mTrackType);
186 sample_count = frag->GetFirstFragmentSampleNumber();
187 size += sizeof(sample_count);
188
189 // data_offset needs to be updated if there is other
190 // TrackRunBox before this one.
191 if (flags.to_ulong() & flags_data_offset_present) {
192 data_offset = 0;
193 size += sizeof(data_offset);
194 }
195 size += fillSampleTable();
196
197 *aBoxSize = size;
198
199 return NS_OK;
200 }
201
202 nsresult
203 TrackRunBox::SetDataOffset(uint32_t aOffset)
204 {
205 data_offset = aOffset;
206 return NS_OK;
207 }
208
209 nsresult
210 TrackRunBox::Write()
211 {
212 WRITE_FULLBOX(mControl, size)
213 mControl->Write(sample_count);
214 if (flags.to_ulong() & flags_data_offset_present) {
215 mControl->Write(data_offset);
216 }
217 for (uint32_t i = 0; i < sample_count; i++) {
218 if (flags.to_ulong() & flags_sample_duration_present) {
219 mControl->Write(sample_info_table[i].sample_duration);
220 }
221 if (flags.to_ulong() & flags_sample_size_present) {
222 mControl->Write(sample_info_table[i].sample_size);
223 }
224 if (flags.to_ulong() & flags_sample_flags_present) {
225 mControl->Write(sample_info_table[i].sample_flags);
226 }
227 }
228
229 return NS_OK;
230 }
231
232 TrackRunBox::TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl)
233 : FullBox(NS_LITERAL_CSTRING("trun"), 0, aFlags, aControl)
234 , sample_count(0)
235 , data_offset(0)
236 , first_sample_flags(0)
237 , mAllSampleSize(0)
238 , mTrackType(aType)
239 {
240 MOZ_COUNT_CTOR(TrackRunBox);
241 }
242
243 TrackRunBox::~TrackRunBox()
244 {
245 MOZ_COUNT_DTOR(TrackRunBox);
246 }
247
248 nsresult
249 TrackFragmentHeaderBox::UpdateBaseDataOffset(uint64_t aOffset)
250 {
251 base_data_offset = aOffset;
252 return NS_OK;
253 }
254
255 nsresult
256 TrackFragmentHeaderBox::Generate(uint32_t* aBoxSize)
257 {
258 track_ID = (mTrackType == Audio_Track ?
259 mControl->GetTrackID(mAudioMeta->GetKind()) :
260 mControl->GetTrackID(mVideoMeta->GetKind()));
261 size += sizeof(track_ID);
262
263 if (flags.to_ulong() & base_data_offset_present) {
264 // base_data_offset needs to add size of 'trun', 'tfhd' and
265 // header of 'mdat' later.
266 base_data_offset = 0;
267 size += sizeof(base_data_offset);
268 }
269 if (flags.to_ulong() & default_sample_duration_present) {
270 if (mTrackType == Video_Track) {
271 if (!mVideoMeta->GetVideoFrameRate()) {
272 // 0 means frame rate is variant, so it is wrong to write
273 // default_sample_duration.
274 MOZ_ASSERT(0);
275 default_sample_duration = 0;
276 } else {
277 default_sample_duration = mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate();
278 }
279 } else if (mTrackType == Audio_Track) {
280 default_sample_duration = mAudioMeta->GetAudioFrameDuration();
281 } else {
282 MOZ_ASSERT(0);
283 return NS_ERROR_FAILURE;
284 }
285 size += sizeof(default_sample_duration);
286 }
287 *aBoxSize = size;
288 return NS_OK;
289 }
290
291 nsresult
292 TrackFragmentHeaderBox::Write()
293 {
294 WRITE_FULLBOX(mControl, size)
295 mControl->Write(track_ID);
296 if (flags.to_ulong() & base_data_offset_present) {
297 mControl->Write(base_data_offset);
298 }
299 if (flags.to_ulong() & default_sample_duration_present) {
300 mControl->Write(default_sample_duration);
301 }
302 return NS_OK;
303 }
304
305 TrackFragmentHeaderBox::TrackFragmentHeaderBox(uint32_t aType,
306 uint32_t aFlags,
307 ISOControl* aControl)
308 : FullBox(NS_LITERAL_CSTRING("tfhd"), 0, aFlags, aControl)
309 , track_ID(0)
310 , base_data_offset(0)
311 , default_sample_duration(0)
312 {
313 mTrackType = aType;
314 MOZ_COUNT_CTOR(TrackFragmentHeaderBox);
315 }
316
317 TrackFragmentHeaderBox::~TrackFragmentHeaderBox()
318 {
319 MOZ_COUNT_DTOR(TrackFragmentHeaderBox);
320 }
321
322 TrackFragmentBox::TrackFragmentBox(uint32_t aType, ISOControl* aControl)
323 : DefaultContainerImpl(NS_LITERAL_CSTRING("traf"), aControl)
324 , mTrackType(aType)
325 {
326 // Flags in TrackFragmentHeaderBox.
327 uint32_t tf_flags = base_data_offset_present;
328
329 // Ideally, audio encoder generates audio frame in const rate. However, some
330 // audio encoders don't do it so the audio frame duration needs to be checked
331 // here.
332 if ((mTrackType & Audio_Track) && mAudioMeta->GetAudioFrameDuration()) {
333 tf_flags |= default_sample_duration_present;
334 }
335
336 boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl));
337
338 // Always adds flags_data_offset_present in each TrackRunBox, Android
339 // parser requires this flag to calculate the correct bitstream offset.
340 uint32_t tr_flags = flags_sample_size_present | flags_data_offset_present;
341
342 // Flags in TrackRunBox.
343 // If there is no default sample duration exists, each frame duration needs to
344 // be recored in the TrackRunBox.
345 tr_flags |= (tf_flags & default_sample_duration_present ? 0 : flags_sample_duration_present);
346
347 // For video, add sample_flags to record I frame.
348 tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0);
349
350 boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl));
351 MOZ_COUNT_CTOR(TrackFragmentBox);
352 }
353
354 TrackFragmentBox::~TrackFragmentBox()
355 {
356 MOZ_COUNT_DTOR(TrackFragmentBox);
357 }
358
359 nsresult
360 MovieFragmentHeaderBox::Generate(uint32_t* aBoxSize)
361 {
362 sequence_number = mControl->GetCurFragmentNumber();
363 size += sizeof(sequence_number);
364 *aBoxSize = size;
365 return NS_OK;
366 }
367
368 nsresult
369 MovieFragmentHeaderBox::Write()
370 {
371 WRITE_FULLBOX(mControl, size)
372 mControl->Write(sequence_number);
373 return NS_OK;
374 }
375
376 MovieFragmentHeaderBox::MovieFragmentHeaderBox(uint32_t aTrackType,
377 ISOControl* aControl)
378 : FullBox(NS_LITERAL_CSTRING("mfhd"), 0, 0, aControl)
379 , sequence_number(0)
380 , mTrackType(aTrackType)
381 {
382 MOZ_COUNT_CTOR(MovieFragmentHeaderBox);
383 }
384
385 MovieFragmentHeaderBox::~MovieFragmentHeaderBox()
386 {
387 MOZ_COUNT_DTOR(MovieFragmentHeaderBox);
388 }
389
390 MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl)
391 : DefaultContainerImpl(NS_LITERAL_CSTRING("moof"), aControl)
392 , mTrackType(aType)
393 {
394 boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl));
395
396 if (mTrackType & Audio_Track) {
397 boxes.AppendElement(
398 new TrackFragmentBox(Audio_Track, aControl));
399 }
400 if (mTrackType & Video_Track) {
401 boxes.AppendElement(
402 new TrackFragmentBox(Video_Track, aControl));
403 }
404 MOZ_COUNT_CTOR(MovieFragmentBox);
405 }
406
407 MovieFragmentBox::~MovieFragmentBox()
408 {
409 MOZ_COUNT_DTOR(MovieFragmentBox);
410 }
411
412 nsresult
413 MovieFragmentBox::Generate(uint32_t* aBoxSize)
414 {
415 nsresult rv = DefaultContainerImpl::Generate(aBoxSize);
416 NS_ENSURE_SUCCESS(rv, rv);
417
418 // Correct data_offset if there are both audio and video track in
419 // this fragment. This offset means the offset in the MediaDataBox.
420 if (mTrackType & (Audio_Track | Video_Track)) {
421 nsTArray<nsRefPtr<MuxerOperation>> truns;
422 rv = Find(NS_LITERAL_CSTRING("trun"), truns);
423 NS_ENSURE_SUCCESS(rv, rv);
424 uint32_t len = truns.Length();
425 uint32_t data_offset = 0;
426 for (uint32_t i = 0; i < len; i++) {
427 TrackRunBox* trun = (TrackRunBox*) truns.ElementAt(i).get();
428 rv = trun->SetDataOffset(data_offset);
429 NS_ENSURE_SUCCESS(rv, rv);
430 data_offset += trun->GetAllSampleSize();
431 }
432 }
433
434 return NS_OK;
435 }
436
437 nsresult
438 TrackExtendsBox::Generate(uint32_t* aBoxSize)
439 {
440 track_ID = (mTrackType == Audio_Track ?
441 mControl->GetTrackID(mAudioMeta->GetKind()) :
442 mControl->GetTrackID(mVideoMeta->GetKind()));
443
444 if (mTrackType == Audio_Track) {
445 default_sample_description_index = 1;
446 default_sample_duration = mAudioMeta->GetAudioFrameDuration();
447 default_sample_size = mAudioMeta->GetAudioFrameSize();
448 default_sample_flags = set_sample_flags(1);
449 } else if (mTrackType == Video_Track) {
450 default_sample_description_index = 1;
451 // Video meta data has assigned framerate, it implies that this video's
452 // frame rate should be fixed.
453 if (mVideoMeta->GetVideoFrameRate()) {
454 default_sample_duration =
455 mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate();
456 }
457 default_sample_size = 0;
458 default_sample_flags = set_sample_flags(0);
459 } else {
460 MOZ_ASSERT(0);
461 return NS_ERROR_FAILURE;
462 }
463
464 size += sizeof(track_ID) +
465 sizeof(default_sample_description_index) +
466 sizeof(default_sample_duration) +
467 sizeof(default_sample_size) +
468 sizeof(default_sample_flags);
469
470 *aBoxSize = size;
471
472 return NS_OK;
473 }
474
475 nsresult
476 TrackExtendsBox::Write()
477 {
478 WRITE_FULLBOX(mControl, size)
479 mControl->Write(track_ID);
480 mControl->Write(default_sample_description_index);
481 mControl->Write(default_sample_duration);
482 mControl->Write(default_sample_size);
483 mControl->Write(default_sample_flags);
484
485 return NS_OK;
486 }
487
488 TrackExtendsBox::TrackExtendsBox(uint32_t aType, ISOControl* aControl)
489 : FullBox(NS_LITERAL_CSTRING("trex"), 0, 0, aControl)
490 , track_ID(0)
491 , default_sample_description_index(0)
492 , default_sample_duration(0)
493 , default_sample_size(0)
494 , default_sample_flags(0)
495 , mTrackType(aType)
496 {
497 MOZ_COUNT_CTOR(TrackExtendsBox);
498 }
499
500 TrackExtendsBox::~TrackExtendsBox()
501 {
502 MOZ_COUNT_DTOR(TrackExtendsBox);
503 }
504
505 MovieExtendsBox::MovieExtendsBox(ISOControl* aControl)
506 : DefaultContainerImpl(NS_LITERAL_CSTRING("mvex"), aControl)
507 {
508 if (mAudioMeta) {
509 boxes.AppendElement(new TrackExtendsBox(Audio_Track, aControl));
510 }
511 if (mVideoMeta) {
512 boxes.AppendElement(new TrackExtendsBox(Video_Track, aControl));
513 }
514 MOZ_COUNT_CTOR(MovieExtendsBox);
515 }
516
517 MovieExtendsBox::~MovieExtendsBox()
518 {
519 MOZ_COUNT_DTOR(MovieExtendsBox);
520 }
521
522 nsresult
523 ChunkOffsetBox::Generate(uint32_t* aBoxSize)
524 {
525 // We don't need time to sample table in fragmented mp4.
526 entry_count = 0;
527 size += sizeof(entry_count);
528 *aBoxSize = size;
529 return NS_OK;
530 }
531
532 nsresult
533 ChunkOffsetBox::Write()
534 {
535 WRITE_FULLBOX(mControl, size)
536 mControl->Write(entry_count);
537 return NS_OK;
538 }
539
540 ChunkOffsetBox::ChunkOffsetBox(uint32_t aType, ISOControl* aControl)
541 : FullBox(NS_LITERAL_CSTRING("stco"), 0, 0, aControl)
542 , entry_count(0)
543 {
544 MOZ_COUNT_CTOR(ChunkOffsetBox);
545 }
546
547 ChunkOffsetBox::~ChunkOffsetBox()
548 {
549 MOZ_COUNT_DTOR(ChunkOffsetBox);
550 }
551
552 nsresult
553 SampleToChunkBox::Generate(uint32_t* aBoxSize)
554 {
555 // We don't need time to sample table in fragmented mp4
556 entry_count = 0;
557 size += sizeof(entry_count);
558 *aBoxSize = size;
559 return NS_OK;
560 }
561
562 nsresult
563 SampleToChunkBox::Write()
564 {
565 WRITE_FULLBOX(mControl, size)
566 mControl->Write(entry_count);
567 return NS_OK;
568 }
569
570 SampleToChunkBox::SampleToChunkBox(uint32_t aType, ISOControl* aControl)
571 : FullBox(NS_LITERAL_CSTRING("stsc"), 0, 0, aControl)
572 , entry_count(0)
573 {
574 MOZ_COUNT_CTOR(SampleToChunkBox);
575 }
576
577 SampleToChunkBox::~SampleToChunkBox()
578 {
579 MOZ_COUNT_DTOR(SampleToChunkBox);
580 }
581
582 nsresult
583 TimeToSampleBox::Generate(uint32_t* aBoxSize)
584 {
585 // We don't need time to sample table in fragmented mp4.
586 entry_count = 0;
587 size += sizeof(entry_count);
588 *aBoxSize = size;
589 return NS_OK;
590 }
591
592 nsresult
593 TimeToSampleBox::Write()
594 {
595 WRITE_FULLBOX(mControl, size)
596 mControl->Write(entry_count);
597 return NS_OK;
598 }
599
600 TimeToSampleBox::TimeToSampleBox(uint32_t aType, ISOControl* aControl)
601 : FullBox(NS_LITERAL_CSTRING("stts"), 0, 0, aControl)
602 , entry_count(0)
603 {
604 MOZ_COUNT_CTOR(TimeToSampleBox);
605 }
606
607 TimeToSampleBox::~TimeToSampleBox()
608 {
609 MOZ_COUNT_DTOR(TimeToSampleBox);
610 }
611
612 nsresult
613 SampleDescriptionBox::Generate(uint32_t* aBoxSize)
614 {
615 entry_count = 1;
616 size += sizeof(entry_count);
617
618 nsresult rv;
619 uint32_t box_size;
620 rv = sample_entry_box->Generate(&box_size);
621 NS_ENSURE_SUCCESS(rv, rv);
622 size += box_size;
623 *aBoxSize = size;
624
625 return NS_OK;
626 }
627
628 nsresult
629 SampleDescriptionBox::Write()
630 {
631 WRITE_FULLBOX(mControl, size)
632 nsresult rv;
633 mControl->Write(entry_count);
634 rv = sample_entry_box->Write();
635 NS_ENSURE_SUCCESS(rv, rv);
636
637 return NS_OK;
638 }
639
640 SampleDescriptionBox::SampleDescriptionBox(uint32_t aType, ISOControl* aControl)
641 : FullBox(NS_LITERAL_CSTRING("stsd"), 0, 0, aControl)
642 , entry_count(0)
643 {
644 mTrackType = aType;
645
646 switch (mTrackType) {
647 case Audio_Track:
648 {
649 CreateAudioSampleEntry(sample_entry_box);
650 }
651 break;
652 case Video_Track:
653 {
654 CreateVideoSampleEntry(sample_entry_box);
655 }
656 break;
657 }
658 MOZ_ASSERT(sample_entry_box);
659 MOZ_COUNT_CTOR(SampleDescriptionBox);
660 }
661
662 nsresult
663 SampleDescriptionBox::CreateAudioSampleEntry(nsRefPtr<SampleEntryBox>& aSampleEntry)
664 {
665 if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AMR) {
666 aSampleEntry = new AMRSampleEntry(mControl);
667 } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AAC) {
668 aSampleEntry = new MP4AudioSampleEntry(mControl);
669 } else {
670 MOZ_ASSERT(0);
671 }
672 return NS_OK;
673 }
674
675 nsresult
676 SampleDescriptionBox::CreateVideoSampleEntry(nsRefPtr<SampleEntryBox>& aSampleEntry)
677 {
678 if (mVideoMeta->GetKind() == TrackMetadataBase::METADATA_AVC) {
679 aSampleEntry = new AVCSampleEntry(mControl);
680 } else {
681 MOZ_ASSERT(0);
682 }
683 return NS_OK;
684 }
685
686 SampleDescriptionBox::~SampleDescriptionBox()
687 {
688 MOZ_COUNT_DTOR(SampleDescriptionBox);
689 }
690
691 nsresult
692 SampleSizeBox::Generate(uint32_t* aBoxSize)
693 {
694 size += sizeof(sample_size) +
695 sizeof(sample_count);
696 *aBoxSize = size;
697 return NS_OK;
698 }
699
700 nsresult
701 SampleSizeBox::Write()
702 {
703 WRITE_FULLBOX(mControl, size)
704 mControl->Write(sample_size);
705 mControl->Write(sample_count);
706 return NS_OK;
707 }
708
709 SampleSizeBox::SampleSizeBox(ISOControl* aControl)
710 : FullBox(NS_LITERAL_CSTRING("stsz"), 0, 0, aControl)
711 , sample_size(0)
712 , sample_count(0)
713 {
714 MOZ_COUNT_CTOR(SampleSizeBox);
715 }
716
717 SampleSizeBox::~SampleSizeBox()
718 {
719 MOZ_COUNT_DTOR(SampleSizeBox);
720 }
721
722 SampleTableBox::SampleTableBox(uint32_t aType, ISOControl* aControl)
723 : DefaultContainerImpl(NS_LITERAL_CSTRING("stbl"), aControl)
724 {
725 boxes.AppendElement(new SampleDescriptionBox(aType, aControl));
726 boxes.AppendElement(new TimeToSampleBox(aType, aControl));
727 boxes.AppendElement(new SampleToChunkBox(aType, aControl));
728 boxes.AppendElement(new SampleSizeBox(aControl));
729 boxes.AppendElement(new ChunkOffsetBox(aType, aControl));
730 MOZ_COUNT_CTOR(SampleTableBox);
731 }
732
733 SampleTableBox::~SampleTableBox()
734 {
735 MOZ_COUNT_DTOR(SampleTableBox);
736 }
737
738 nsresult
739 DataEntryUrlBox::Generate(uint32_t* aBoxSize)
740 {
741 // location is null here, do nothing
742 size += location.Length();
743 *aBoxSize = size;
744
745 return NS_OK;
746 }
747
748 nsresult
749 DataEntryUrlBox::Write()
750 {
751 WRITE_FULLBOX(mControl, size)
752 return NS_OK;
753 }
754
755 DataEntryUrlBox::DataEntryUrlBox()
756 : FullBox(NS_LITERAL_CSTRING("url "), 0, 0, (ISOControl*) nullptr)
757 {
758 MOZ_COUNT_CTOR(DataEntryUrlBox);
759 }
760
761 DataEntryUrlBox::DataEntryUrlBox(ISOControl* aControl)
762 : FullBox(NS_LITERAL_CSTRING("url "), 0, flags_media_at_the_same_file, aControl)
763 {
764 MOZ_COUNT_CTOR(DataEntryUrlBox);
765 }
766
767 DataEntryUrlBox::DataEntryUrlBox(const DataEntryUrlBox& aBox)
768 : FullBox(aBox.boxType, aBox.version, aBox.flags.to_ulong(), aBox.mControl)
769 {
770 location = aBox.location;
771 MOZ_COUNT_CTOR(DataEntryUrlBox);
772 }
773
774 DataEntryUrlBox::~DataEntryUrlBox()
775 {
776 MOZ_COUNT_DTOR(DataEntryUrlBox);
777 }
778
779 nsresult DataReferenceBox::Generate(uint32_t* aBoxSize)
780 {
781 entry_count = 1; // only allow on entry here
782 size += sizeof(uint32_t);
783
784 for (uint32_t i = 0; i < entry_count; i++) {
785 uint32_t box_size = 0;
786 DataEntryUrlBox* url = new DataEntryUrlBox(mControl);
787 url->Generate(&box_size);
788 size += box_size;
789 urls.AppendElement(url);
790 }
791
792 *aBoxSize = size;
793
794 return NS_OK;
795 }
796
797 nsresult DataReferenceBox::Write()
798 {
799 WRITE_FULLBOX(mControl, size)
800 mControl->Write(entry_count);
801
802 for (uint32_t i = 0; i < entry_count; i++) {
803 urls[i]->Write();
804 }
805
806 return NS_OK;
807 }
808
809 DataReferenceBox::DataReferenceBox(ISOControl* aControl)
810 : FullBox(NS_LITERAL_CSTRING("dref"), 0, 0, aControl)
811 , entry_count(0)
812 {
813 MOZ_COUNT_CTOR(DataReferenceBox);
814 }
815
816 DataReferenceBox::~DataReferenceBox()
817 {
818 MOZ_COUNT_DTOR(DataReferenceBox);
819 }
820
821 DataInformationBox::DataInformationBox(ISOControl* aControl)
822 : DefaultContainerImpl(NS_LITERAL_CSTRING("dinf"), aControl)
823 {
824 boxes.AppendElement(new DataReferenceBox(aControl));
825 MOZ_COUNT_CTOR(DataInformationBox);
826 }
827
828 DataInformationBox::~DataInformationBox()
829 {
830 MOZ_COUNT_DTOR(DataInformationBox);
831 }
832
833 nsresult
834 VideoMediaHeaderBox::Generate(uint32_t* aBoxSize)
835 {
836 size += sizeof(graphicsmode) +
837 sizeof(opcolor);
838
839 *aBoxSize = size;
840
841 return NS_OK;
842 }
843
844 nsresult
845 VideoMediaHeaderBox::Write()
846 {
847 WRITE_FULLBOX(mControl, size)
848 mControl->Write(graphicsmode);
849 mControl->WriteArray(opcolor, 3);
850 return NS_OK;
851 }
852
853 VideoMediaHeaderBox::VideoMediaHeaderBox(ISOControl* aControl)
854 : FullBox(NS_LITERAL_CSTRING("vmhd"), 0, 1, aControl)
855 , graphicsmode(0)
856 {
857 memset(opcolor, 0 , sizeof(opcolor));
858 MOZ_COUNT_CTOR(VideoMediaHeaderBox);
859 }
860
861 VideoMediaHeaderBox::~VideoMediaHeaderBox()
862 {
863 MOZ_COUNT_DTOR(VideoMediaHeaderBox);
864 }
865
866 nsresult
867 SoundMediaHeaderBox::Generate(uint32_t* aBoxSize)
868 {
869 balance = 0;
870 reserved = 0;
871 size += sizeof(balance) +
872 sizeof(reserved);
873
874 *aBoxSize = size;
875
876 return NS_OK;
877 }
878
879 nsresult
880 SoundMediaHeaderBox::Write()
881 {
882 WRITE_FULLBOX(mControl, size)
883 mControl->Write(balance);
884 mControl->Write(reserved);
885
886 return NS_OK;
887 }
888
889 SoundMediaHeaderBox::SoundMediaHeaderBox(ISOControl* aControl)
890 : FullBox(NS_LITERAL_CSTRING("smhd"), 0, 0, aControl)
891 {
892 MOZ_COUNT_CTOR(SoundMediaHeaderBox);
893 }
894
895 SoundMediaHeaderBox::~SoundMediaHeaderBox()
896 {
897 MOZ_COUNT_DTOR(SoundMediaHeaderBox);
898 }
899
900 MediaInformationBox::MediaInformationBox(uint32_t aType, ISOControl* aControl)
901 : DefaultContainerImpl(NS_LITERAL_CSTRING("minf"), aControl)
902 {
903 mTrackType = aType;
904
905 if (mTrackType == Audio_Track) {
906 boxes.AppendElement(new SoundMediaHeaderBox(aControl));
907 } else if (mTrackType == Video_Track) {
908 boxes.AppendElement(new VideoMediaHeaderBox(aControl));
909 } else {
910 MOZ_ASSERT(0);
911 }
912
913 boxes.AppendElement(new DataInformationBox(aControl));
914 boxes.AppendElement(new SampleTableBox(aType, aControl));
915 MOZ_COUNT_CTOR(MediaInformationBox);
916 }
917
918 MediaInformationBox::~MediaInformationBox()
919 {
920 MOZ_COUNT_DTOR(MediaInformationBox);
921 }
922
923 nsresult
924 HandlerBox::Generate(uint32_t* aBoxSize)
925 {
926 pre_defined = 0;
927 if (mTrackType == Audio_Track) {
928 handler_type = FOURCC('s', 'o', 'u', 'n');
929 } else if (mTrackType == Video_Track) {
930 handler_type = FOURCC('v', 'i', 'd', 'e');
931 }
932
933 size += sizeof(pre_defined) +
934 sizeof(handler_type) +
935 sizeof(reserved);
936
937 *aBoxSize = size;
938
939 return NS_OK;
940 }
941
942 nsresult
943 HandlerBox::Write()
944 {
945 WRITE_FULLBOX(mControl, size)
946 mControl->Write(pre_defined);
947 mControl->Write(handler_type);
948 mControl->WriteArray(reserved, 3);
949
950 return NS_OK;
951 }
952
953 HandlerBox::HandlerBox(uint32_t aType, ISOControl* aControl)
954 : FullBox(NS_LITERAL_CSTRING("hdlr"), 0, 0, aControl)
955 , pre_defined(0)
956 , handler_type(0)
957 {
958 mTrackType = aType;
959 memset(reserved, 0 , sizeof(reserved));
960 MOZ_COUNT_CTOR(HandlerBox);
961 }
962
963 HandlerBox::~HandlerBox()
964 {
965 MOZ_COUNT_DTOR(HandlerBox);
966 }
967
968 MediaHeaderBox::MediaHeaderBox(uint32_t aType, ISOControl* aControl)
969 : FullBox(NS_LITERAL_CSTRING("mdhd"), 0, 0, aControl)
970 , creation_time(0)
971 , modification_time(0)
972 , timescale(0)
973 , duration(0)
974 , pad(0)
975 , lang1(0)
976 , lang2(0)
977 , lang3(0)
978 , pre_defined(0)
979 {
980 mTrackType = aType;
981 MOZ_COUNT_CTOR(MediaHeaderBox);
982 }
983
984 MediaHeaderBox::~MediaHeaderBox()
985 {
986 MOZ_COUNT_DTOR(MediaHeaderBox);
987 }
988
989 uint32_t
990 MediaHeaderBox::GetTimeScale()
991 {
992 if (mTrackType == Audio_Track) {
993 return mAudioMeta->GetAudioSampleRate();
994 }
995
996 return mVideoMeta->GetVideoClockRate();
997 }
998
999 nsresult
1000 MediaHeaderBox::Generate(uint32_t* aBoxSize)
1001 {
1002 creation_time = mControl->GetTime();
1003 modification_time = mControl->GetTime();
1004 timescale = GetTimeScale();
1005 duration = 0; // fragmented mp4
1006
1007 pad = 0;
1008 lang1 = 'u' - 0x60; // "und" underdetermined language
1009 lang2 = 'n' - 0x60;
1010 lang3 = 'd' - 0x60;
1011 size += (pad.size() + lang1.size() + lang2.size() + lang3.size()) / CHAR_BIT;
1012
1013 pre_defined = 0;
1014 size += sizeof(creation_time) +
1015 sizeof(modification_time) +
1016 sizeof(timescale) +
1017 sizeof(duration) +
1018 sizeof(pre_defined);
1019
1020 *aBoxSize = size;
1021
1022 return NS_OK;
1023 }
1024
1025 nsresult
1026 MediaHeaderBox::Write()
1027 {
1028 WRITE_FULLBOX(mControl, size)
1029 mControl->Write(creation_time);
1030 mControl->Write(modification_time);
1031 mControl->Write(timescale);
1032 mControl->Write(duration);
1033 mControl->WriteBits(pad.to_ulong(), pad.size());
1034 mControl->WriteBits(lang1.to_ulong(), lang1.size());
1035 mControl->WriteBits(lang2.to_ulong(), lang2.size());
1036 mControl->WriteBits(lang3.to_ulong(), lang3.size());
1037 mControl->Write(pre_defined);
1038
1039 return NS_OK;
1040 }
1041
1042 MovieBox::MovieBox(ISOControl* aControl)
1043 : DefaultContainerImpl(NS_LITERAL_CSTRING("moov"), aControl)
1044 {
1045 boxes.AppendElement(new MovieHeaderBox(aControl));
1046 if (aControl->HasAudioTrack()) {
1047 boxes.AppendElement(new TrackBox(Audio_Track, aControl));
1048 }
1049 if (aControl->HasVideoTrack()) {
1050 boxes.AppendElement(new TrackBox(Video_Track, aControl));
1051 }
1052 boxes.AppendElement(new MovieExtendsBox(aControl));
1053 MOZ_COUNT_CTOR(MovieBox);
1054 }
1055
1056 MovieBox::~MovieBox()
1057 {
1058 MOZ_COUNT_DTOR(MovieBox);
1059 }
1060
1061 nsresult
1062 MovieHeaderBox::Generate(uint32_t* aBoxSize)
1063 {
1064 creation_time = mControl->GetTime();
1065 modification_time = mControl->GetTime();
1066 timescale = GetTimeScale();
1067 duration = 0; // The duration is always 0 in fragmented mp4.
1068 next_track_ID = mControl->GetNextTrackID();
1069
1070 size += sizeof(next_track_ID) +
1071 sizeof(creation_time) +
1072 sizeof(modification_time) +
1073 sizeof(timescale) +
1074 sizeof(duration) +
1075 sizeof(rate) +
1076 sizeof(volume) +
1077 sizeof(reserved16) +
1078 sizeof(reserved32) +
1079 sizeof(matrix) +
1080 sizeof(pre_defined);
1081
1082 *aBoxSize = size;
1083
1084 return NS_OK;
1085 }
1086
1087 nsresult
1088 MovieHeaderBox::Write()
1089 {
1090 WRITE_FULLBOX(mControl, size)
1091 mControl->Write(creation_time);
1092 mControl->Write(modification_time);
1093 mControl->Write(timescale);
1094 mControl->Write(duration);
1095 mControl->Write(rate);
1096 mControl->Write(volume);
1097 mControl->Write(reserved16);
1098 mControl->WriteArray(reserved32, 2);
1099 mControl->WriteArray(matrix, 9);
1100 mControl->WriteArray(pre_defined, 6);
1101 mControl->Write(next_track_ID);
1102
1103 return NS_OK;
1104 }
1105
1106 uint32_t
1107 MovieHeaderBox::GetTimeScale()
1108 {
1109 // Only audio track in container.
1110 if (mAudioMeta && !mVideoMeta) {
1111 return mAudioMeta->GetAudioSampleRate();
1112 }
1113
1114 // return video rate
1115 return mVideoMeta->GetVideoClockRate();
1116 }
1117
1118 MovieHeaderBox::~MovieHeaderBox()
1119 {
1120 MOZ_COUNT_DTOR(MovieHeaderBox);
1121 }
1122
1123 MovieHeaderBox::MovieHeaderBox(ISOControl* aControl)
1124 : FullBox(NS_LITERAL_CSTRING("mvhd"), 0, 0, aControl)
1125 , creation_time(0)
1126 , modification_time(0)
1127 , timescale(90000)
1128 , duration(0)
1129 , rate(0x00010000)
1130 , volume(0x0100)
1131 , reserved16(0)
1132 , next_track_ID(1)
1133 {
1134 memcpy(matrix, iso_matrix, sizeof(matrix));
1135 memset(reserved32, 0, sizeof(reserved32));
1136 memset(pre_defined, 0, sizeof(pre_defined));
1137 MOZ_COUNT_CTOR(MovieHeaderBox);
1138 }
1139
1140 TrackHeaderBox::TrackHeaderBox(uint32_t aType, ISOControl* aControl)
1141 : FullBox(NS_LITERAL_CSTRING("tkhd"), 0,
1142 flags_track_enabled | flags_track_in_movie | flags_track_in_preview,
1143 aControl)
1144 , creation_time(0)
1145 , modification_time(0)
1146 , track_ID(0)
1147 , reserved(0)
1148 , duration(0)
1149 , layer(0)
1150 , alternate_group(0)
1151 , volume(0)
1152 , reserved3(0)
1153 , width(0)
1154 , height(0)
1155 {
1156 mTrackType = aType;
1157 memcpy(matrix, iso_matrix, sizeof(matrix));
1158 memset(reserved2, 0, sizeof(reserved2));
1159 MOZ_COUNT_CTOR(TrackHeaderBox);
1160 }
1161
1162 TrackHeaderBox::~TrackHeaderBox()
1163 {
1164 MOZ_COUNT_DTOR(TrackHeaderBox);
1165 }
1166
1167 nsresult
1168 TrackHeaderBox::Generate(uint32_t* aBoxSize)
1169 {
1170 creation_time = mControl->GetTime();
1171 modification_time = mControl->GetTime();
1172 track_ID = (mTrackType == Audio_Track ?
1173 mControl->GetTrackID(mAudioMeta->GetKind()) :
1174 mControl->GetTrackID(mVideoMeta->GetKind()));
1175 // fragmented mp4
1176 duration = 0;
1177
1178 // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2
1179 volume = (mTrackType == Audio_Track ? 0x0100 : 0);
1180
1181 if (mTrackType == Video_Track) {
1182 width = mVideoMeta->GetVideoDisplayWidth() << 16;
1183 height = mVideoMeta->GetVideoDisplayHeight() << 16;
1184 // Check display size, using the pixel size if any of them is invalid.
1185 if (!width || !height) {
1186 width = mVideoMeta->GetVideoWidth() << 16;
1187 height = mVideoMeta->GetVideoHeight() << 16;
1188 }
1189 }
1190
1191 size += sizeof(creation_time) +
1192 sizeof(modification_time) +
1193 sizeof(track_ID) +
1194 sizeof(reserved) +
1195 sizeof(duration) +
1196 sizeof(reserved2) +
1197 sizeof(layer) +
1198 sizeof(alternate_group) +
1199 sizeof(volume) +
1200 sizeof(reserved3) +
1201 sizeof(matrix) +
1202 sizeof(width) +
1203 sizeof(height);
1204
1205 *aBoxSize = size;
1206
1207 return NS_OK;
1208 }
1209
1210 nsresult
1211 TrackHeaderBox::Write()
1212 {
1213 WRITE_FULLBOX(mControl, size)
1214 mControl->Write(creation_time);
1215 mControl->Write(modification_time);
1216 mControl->Write(track_ID);
1217 mControl->Write(reserved);
1218 mControl->Write(duration);
1219 mControl->WriteArray(reserved2, 2);
1220 mControl->Write(layer);
1221 mControl->Write(alternate_group);
1222 mControl->Write(volume);
1223 mControl->Write(reserved3);
1224 mControl->WriteArray(matrix, 9);
1225 mControl->Write(width);
1226 mControl->Write(height);
1227
1228 return NS_OK;
1229 }
1230
1231 nsresult
1232 FileTypeBox::Generate(uint32_t* aBoxSize)
1233 {
1234 minor_version = 0;
1235
1236 if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_MP4) {
1237 if (!mControl->HasVideoTrack() && mControl->HasAudioTrack()) {
1238 major_brand = "M4A ";
1239 } else {
1240 major_brand = "MP42";
1241 }
1242 compatible_brands.AppendElement("mp42");
1243 compatible_brands.AppendElement("isom");
1244 } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3GP) {
1245 major_brand = "3gp9";
1246 // According to 3GPP TS 26.244 V12.2.0, section 5.3.4, it's recommended to
1247 // list all compatible brands here. 3GP spec supports fragment from '3gp6'.
1248 compatible_brands.AppendElement("3gp9");
1249 compatible_brands.AppendElement("3gp8");
1250 compatible_brands.AppendElement("3gp7");
1251 compatible_brands.AppendElement("3gp6");
1252 compatible_brands.AppendElement("isom");
1253 } else {
1254 MOZ_ASSERT(0);
1255 }
1256
1257 size += major_brand.Length() +
1258 sizeof(minor_version) +
1259 compatible_brands.Length() * 4;
1260
1261 *aBoxSize = size;
1262
1263 return NS_OK;
1264 }
1265
1266 nsresult
1267 FileTypeBox::Write()
1268 {
1269 BoxSizeChecker checker(mControl, size);
1270 Box::Write();
1271 mControl->WriteFourCC(major_brand.get());
1272 mControl->Write(minor_version);
1273 uint32_t len = compatible_brands.Length();
1274 for (uint32_t i = 0; i < len; i++) {
1275 mControl->WriteFourCC(compatible_brands[i].get());
1276 }
1277
1278 return NS_OK;
1279 }
1280
1281 FileTypeBox::FileTypeBox(ISOControl* aControl)
1282 : Box(NS_LITERAL_CSTRING("ftyp"), aControl)
1283 , minor_version(0)
1284 {
1285 MOZ_COUNT_CTOR(FileTypeBox);
1286 }
1287
1288 FileTypeBox::~FileTypeBox()
1289 {
1290 MOZ_COUNT_DTOR(FileTypeBox);
1291 }
1292
1293 MediaBox::MediaBox(uint32_t aType, ISOControl* aControl)
1294 : DefaultContainerImpl(NS_LITERAL_CSTRING("mdia"), aControl)
1295 {
1296 mTrackType = aType;
1297 boxes.AppendElement(new MediaHeaderBox(aType, aControl));
1298 boxes.AppendElement(new HandlerBox(aType, aControl));
1299 boxes.AppendElement(new MediaInformationBox(aType, aControl));
1300 MOZ_COUNT_CTOR(MediaBox);
1301 }
1302
1303 MediaBox::~MediaBox()
1304 {
1305 MOZ_COUNT_DTOR(MediaBox);
1306 }
1307
1308 nsresult
1309 DefaultContainerImpl::Generate(uint32_t* aBoxSize)
1310 {
1311 nsresult rv;
1312 uint32_t box_size;
1313 uint32_t len = boxes.Length();
1314 for (uint32_t i = 0; i < len; i++) {
1315 rv = boxes.ElementAt(i)->Generate(&box_size);
1316 NS_ENSURE_SUCCESS(rv, rv);
1317 size += box_size;
1318 }
1319 *aBoxSize = size;
1320 return NS_OK;
1321 }
1322
1323 nsresult
1324 DefaultContainerImpl::Find(const nsACString& aType,
1325 nsTArray<nsRefPtr<MuxerOperation>>& aOperations)
1326 {
1327 nsresult rv = Box::Find(aType, aOperations);
1328 NS_ENSURE_SUCCESS(rv, rv);
1329
1330 uint32_t len = boxes.Length();
1331 for (uint32_t i = 0; i < len; i++) {
1332 rv = boxes.ElementAt(i)->Find(aType, aOperations);
1333 NS_ENSURE_SUCCESS(rv, rv);
1334 }
1335 return NS_OK;
1336 }
1337
1338 nsresult
1339 DefaultContainerImpl::Write()
1340 {
1341 BoxSizeChecker checker(mControl, size);
1342 Box::Write();
1343
1344 nsresult rv;
1345 uint32_t len = boxes.Length();
1346 for (uint32_t i = 0; i < len; i++) {
1347 rv = boxes.ElementAt(i)->Write();
1348 NS_ENSURE_SUCCESS(rv, rv);
1349 }
1350
1351 return NS_OK;
1352 }
1353
1354 DefaultContainerImpl::DefaultContainerImpl(const nsACString& aType,
1355 ISOControl* aControl)
1356 : Box(aType, aControl)
1357 {
1358 }
1359
1360 nsresult
1361 Box::Write()
1362 {
1363 mControl->Write(size);
1364 mControl->WriteFourCC(boxType.get());
1365 return NS_OK;
1366 }
1367
1368 nsresult
1369 Box::Find(const nsACString& aType, nsTArray<nsRefPtr<MuxerOperation>>& aOperations)
1370 {
1371 if (boxType == aType) {
1372 aOperations.AppendElement(this);
1373 }
1374 return NS_OK;
1375 }
1376
1377 Box::Box(const nsACString& aType, ISOControl* aControl)
1378 : size(8), mControl(aControl)
1379 {
1380 MOZ_ASSERT(aType.Length() == 4);
1381 boxType = aType;
1382 aControl->GetAudioMetadata(mAudioMeta);
1383 aControl->GetVideoMetadata(mVideoMeta);
1384 }
1385
1386 FullBox::FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags,
1387 ISOControl* aControl)
1388 : Box(aType, aControl)
1389 {
1390 // Cast to uint64_t due to VC2010 bug.
1391 std::bitset<24> tmp_flags((uint64_t)aFlags);
1392 version = aVersion;
1393 flags = tmp_flags;
1394 size += sizeof(version) + flags.size() / CHAR_BIT;
1395 }
1396
1397 nsresult
1398 FullBox::Write()
1399 {
1400 Box::Write();
1401 mControl->Write(version);
1402 mControl->WriteBits(flags.to_ulong(), flags.size());
1403 return NS_OK;
1404 }
1405
1406 TrackBox::TrackBox(uint32_t aTrackType, ISOControl* aControl)
1407 : DefaultContainerImpl(NS_LITERAL_CSTRING("trak"), aControl)
1408 {
1409 boxes.AppendElement(new TrackHeaderBox(aTrackType, aControl));
1410 boxes.AppendElement(new MediaBox(aTrackType, aControl));
1411 MOZ_COUNT_CTOR(TrackBox);
1412 }
1413
1414 TrackBox::~TrackBox()
1415 {
1416 MOZ_COUNT_DTOR(TrackBox);
1417 }
1418
1419 SampleEntryBox::SampleEntryBox(const nsACString& aFormat, ISOControl* aControl)
1420 : Box(aFormat, aControl)
1421 , data_reference_index(0)
1422 {
1423 data_reference_index = 1; // There is only one data reference in each track.
1424 size += sizeof(reserved) +
1425 sizeof(data_reference_index);
1426 memset(reserved, 0, sizeof(reserved));
1427 }
1428
1429 nsresult
1430 SampleEntryBox::Write()
1431 {
1432 Box::Write();
1433 mControl->Write(reserved, sizeof(reserved));
1434 mControl->Write(data_reference_index);
1435 return NS_OK;
1436 }
1437
1438 nsresult
1439 AudioSampleEntry::Write()
1440 {
1441 SampleEntryBox::Write();
1442 mControl->Write(sound_version);
1443 mControl->Write(reserved2, sizeof(reserved2));
1444 mControl->Write(channels);
1445 mControl->Write(sample_size);
1446 mControl->Write(compressionId);
1447 mControl->Write(packet_size);
1448 mControl->Write(timeScale);
1449 return NS_OK;
1450 }
1451
1452 AudioSampleEntry::AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl)
1453 : SampleEntryBox(aFormat, aControl)
1454 , sound_version(0)
1455 , channels(2)
1456 , sample_size(16)
1457 , compressionId(0)
1458 , packet_size(0)
1459 , timeScale(0)
1460 {
1461 memset(reserved2, 0 , sizeof(reserved2));
1462 channels = mAudioMeta->GetAudioChannels();
1463 timeScale = mAudioMeta->GetAudioSampleRate() << 16;
1464
1465 size += sizeof(sound_version) +
1466 sizeof(reserved2) +
1467 sizeof(sample_size) +
1468 sizeof(channels) +
1469 sizeof(packet_size) +
1470 sizeof(compressionId) +
1471 sizeof(timeScale);
1472
1473 MOZ_COUNT_CTOR(AudioSampleEntry);
1474 }
1475
1476 AudioSampleEntry::~AudioSampleEntry()
1477 {
1478 MOZ_COUNT_DTOR(AudioSampleEntry);
1479 }
1480
1481 nsresult
1482 VisualSampleEntry::Write()
1483 {
1484 SampleEntryBox::Write();
1485
1486 mControl->Write(reserved, sizeof(reserved));
1487 mControl->Write(width);
1488 mControl->Write(height);
1489 mControl->Write(horizresolution);
1490 mControl->Write(vertresolution);
1491 mControl->Write(reserved2);
1492 mControl->Write(frame_count);
1493 mControl->Write(compressorName, sizeof(compressorName));
1494 mControl->Write(depth);
1495 mControl->Write(pre_defined);
1496
1497 return NS_OK;
1498 }
1499
1500 VisualSampleEntry::VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl)
1501 : SampleEntryBox(aFormat, aControl)
1502 , width(0)
1503 , height(0)
1504 , horizresolution(resolution_72_dpi)
1505 , vertresolution(resolution_72_dpi)
1506 , reserved2(0)
1507 , frame_count(1)
1508 , depth(video_depth)
1509 , pre_defined(-1)
1510 {
1511 memset(reserved, 0 , sizeof(reserved));
1512 memset(compressorName, 0 , sizeof(compressorName));
1513
1514 // both fields occupy 16 bits defined in 14496-2 6.2.3.
1515 width = mVideoMeta->GetVideoWidth();
1516 height = mVideoMeta->GetVideoHeight();
1517
1518 size += sizeof(reserved) +
1519 sizeof(width) +
1520 sizeof(height) +
1521 sizeof(horizresolution) +
1522 sizeof(vertresolution) +
1523 sizeof(reserved2) +
1524 sizeof(frame_count) +
1525 sizeof(compressorName) +
1526 sizeof(depth) +
1527 sizeof(pre_defined);
1528
1529 MOZ_COUNT_CTOR(VisualSampleEntry);
1530 }
1531
1532 VisualSampleEntry::~VisualSampleEntry()
1533 {
1534 MOZ_COUNT_DTOR(VisualSampleEntry);
1535 }
1536
1537 }

mercurial