content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     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"
    18 namespace mozilla {
    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 };
    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 }
    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 }
    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   }
    48   MOZ_COUNT_DTOR(BoxSizeChecker);
    49 }
    51 nsresult
    52 MediaDataBox::Generate(uint32_t* aBoxSize)
    53 {
    54   mFirstSampleOffset = size;
    55   mAllSampleSize = 0;
    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   }
    66   size += mAllSampleSize;
    67   *aBoxSize = size;
    68   return NS_OK;
    69 }
    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);
    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;
    86       // Here is the last time we get fragment frames, flush it!
    87       rv = frag->GetFirstFragment(frames, true);
    88       NS_ENSURE_SUCCESS(rv, rv);
    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   }
    99   return NS_OK;
   100 }
   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 }
   111 MediaDataBox::~MediaDataBox()
   112 {
   113   MOZ_COUNT_DTOR(MediaDataBox);
   114 }
   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);
   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     }
   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     }
   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       }
   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);
   174       table_size += sizeof(uint32_t);
   175     }
   177     sample_info_table[i].sample_composition_time_offset = 0;
   178   }
   179   return table_size;
   180 }
   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);
   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();
   197   *aBoxSize = size;
   199   return NS_OK;
   200 }
   202 nsresult
   203 TrackRunBox::SetDataOffset(uint32_t aOffset)
   204 {
   205   data_offset = aOffset;
   206   return NS_OK;
   207 }
   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   }
   229   return NS_OK;
   230 }
   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 }
   243 TrackRunBox::~TrackRunBox()
   244 {
   245   MOZ_COUNT_DTOR(TrackRunBox);
   246 }
   248 nsresult
   249 TrackFragmentHeaderBox::UpdateBaseDataOffset(uint64_t aOffset)
   250 {
   251   base_data_offset = aOffset;
   252   return NS_OK;
   253 }
   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);
   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 }
   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 }
   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 }
   317 TrackFragmentHeaderBox::~TrackFragmentHeaderBox()
   318 {
   319   MOZ_COUNT_DTOR(TrackFragmentHeaderBox);
   320 }
   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;
   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   }
   336   boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl));
   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;
   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);
   347   // For video, add sample_flags to record I frame.
   348   tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0);
   350   boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl));
   351   MOZ_COUNT_CTOR(TrackFragmentBox);
   352 }
   354 TrackFragmentBox::~TrackFragmentBox()
   355 {
   356   MOZ_COUNT_DTOR(TrackFragmentBox);
   357 }
   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 }
   368 nsresult
   369 MovieFragmentHeaderBox::Write()
   370 {
   371   WRITE_FULLBOX(mControl, size)
   372   mControl->Write(sequence_number);
   373   return NS_OK;
   374 }
   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 }
   385 MovieFragmentHeaderBox::~MovieFragmentHeaderBox()
   386 {
   387   MOZ_COUNT_DTOR(MovieFragmentHeaderBox);
   388 }
   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));
   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 }
   407 MovieFragmentBox::~MovieFragmentBox()
   408 {
   409   MOZ_COUNT_DTOR(MovieFragmentBox);
   410 }
   412 nsresult
   413 MovieFragmentBox::Generate(uint32_t* aBoxSize)
   414 {
   415   nsresult rv = DefaultContainerImpl::Generate(aBoxSize);
   416   NS_ENSURE_SUCCESS(rv, rv);
   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   }
   434   return NS_OK;
   435 }
   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()));
   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   }
   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);
   470   *aBoxSize = size;
   472   return NS_OK;
   473 }
   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);
   485   return NS_OK;
   486 }
   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 }
   500 TrackExtendsBox::~TrackExtendsBox()
   501 {
   502   MOZ_COUNT_DTOR(TrackExtendsBox);
   503 }
   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 }
   517 MovieExtendsBox::~MovieExtendsBox()
   518 {
   519   MOZ_COUNT_DTOR(MovieExtendsBox);
   520 }
   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 }
   532 nsresult
   533 ChunkOffsetBox::Write()
   534 {
   535   WRITE_FULLBOX(mControl, size)
   536   mControl->Write(entry_count);
   537   return NS_OK;
   538 }
   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 }
   547 ChunkOffsetBox::~ChunkOffsetBox()
   548 {
   549   MOZ_COUNT_DTOR(ChunkOffsetBox);
   550 }
   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 }
   562 nsresult
   563 SampleToChunkBox::Write()
   564 {
   565   WRITE_FULLBOX(mControl, size)
   566   mControl->Write(entry_count);
   567   return NS_OK;
   568 }
   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 }
   577 SampleToChunkBox::~SampleToChunkBox()
   578 {
   579   MOZ_COUNT_DTOR(SampleToChunkBox);
   580 }
   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 }
   592 nsresult
   593 TimeToSampleBox::Write()
   594 {
   595   WRITE_FULLBOX(mControl, size)
   596   mControl->Write(entry_count);
   597   return NS_OK;
   598 }
   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 }
   607 TimeToSampleBox::~TimeToSampleBox()
   608 {
   609   MOZ_COUNT_DTOR(TimeToSampleBox);
   610 }
   612 nsresult
   613 SampleDescriptionBox::Generate(uint32_t* aBoxSize)
   614 {
   615   entry_count = 1;
   616   size += sizeof(entry_count);
   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;
   625   return NS_OK;
   626 }
   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);
   637   return NS_OK;
   638 }
   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;
   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 }
   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 }
   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 }
   686 SampleDescriptionBox::~SampleDescriptionBox()
   687 {
   688   MOZ_COUNT_DTOR(SampleDescriptionBox);
   689 }
   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 }
   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 }
   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 }
   717 SampleSizeBox::~SampleSizeBox()
   718 {
   719   MOZ_COUNT_DTOR(SampleSizeBox);
   720 }
   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 }
   733 SampleTableBox::~SampleTableBox()
   734 {
   735   MOZ_COUNT_DTOR(SampleTableBox);
   736 }
   738 nsresult
   739 DataEntryUrlBox::Generate(uint32_t* aBoxSize)
   740 {
   741   // location is null here, do nothing
   742   size += location.Length();
   743   *aBoxSize = size;
   745   return NS_OK;
   746 }
   748 nsresult
   749 DataEntryUrlBox::Write()
   750 {
   751   WRITE_FULLBOX(mControl, size)
   752   return NS_OK;
   753 }
   755 DataEntryUrlBox::DataEntryUrlBox()
   756   : FullBox(NS_LITERAL_CSTRING("url "), 0, 0, (ISOControl*) nullptr)
   757 {
   758   MOZ_COUNT_CTOR(DataEntryUrlBox);
   759 }
   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 }
   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 }
   774 DataEntryUrlBox::~DataEntryUrlBox()
   775 {
   776   MOZ_COUNT_DTOR(DataEntryUrlBox);
   777 }
   779 nsresult DataReferenceBox::Generate(uint32_t* aBoxSize)
   780 {
   781   entry_count = 1;  // only allow on entry here
   782   size += sizeof(uint32_t);
   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   }
   792   *aBoxSize = size;
   794   return NS_OK;
   795 }
   797 nsresult DataReferenceBox::Write()
   798 {
   799   WRITE_FULLBOX(mControl, size)
   800   mControl->Write(entry_count);
   802   for (uint32_t i = 0; i < entry_count; i++) {
   803     urls[i]->Write();
   804   }
   806   return NS_OK;
   807 }
   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 }
   816 DataReferenceBox::~DataReferenceBox()
   817 {
   818   MOZ_COUNT_DTOR(DataReferenceBox);
   819 }
   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 }
   828 DataInformationBox::~DataInformationBox()
   829 {
   830   MOZ_COUNT_DTOR(DataInformationBox);
   831 }
   833 nsresult
   834 VideoMediaHeaderBox::Generate(uint32_t* aBoxSize)
   835 {
   836   size += sizeof(graphicsmode) +
   837           sizeof(opcolor);
   839   *aBoxSize = size;
   841   return NS_OK;
   842 }
   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 }
   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 }
   861 VideoMediaHeaderBox::~VideoMediaHeaderBox()
   862 {
   863   MOZ_COUNT_DTOR(VideoMediaHeaderBox);
   864 }
   866 nsresult
   867 SoundMediaHeaderBox::Generate(uint32_t* aBoxSize)
   868 {
   869   balance = 0;
   870   reserved = 0;
   871   size += sizeof(balance) +
   872           sizeof(reserved);
   874   *aBoxSize = size;
   876   return NS_OK;
   877 }
   879 nsresult
   880 SoundMediaHeaderBox::Write()
   881 {
   882   WRITE_FULLBOX(mControl, size)
   883   mControl->Write(balance);
   884   mControl->Write(reserved);
   886   return NS_OK;
   887 }
   889 SoundMediaHeaderBox::SoundMediaHeaderBox(ISOControl* aControl)
   890   : FullBox(NS_LITERAL_CSTRING("smhd"), 0, 0, aControl)
   891 {
   892   MOZ_COUNT_CTOR(SoundMediaHeaderBox);
   893 }
   895 SoundMediaHeaderBox::~SoundMediaHeaderBox()
   896 {
   897   MOZ_COUNT_DTOR(SoundMediaHeaderBox);
   898 }
   900 MediaInformationBox::MediaInformationBox(uint32_t aType, ISOControl* aControl)
   901   : DefaultContainerImpl(NS_LITERAL_CSTRING("minf"), aControl)
   902 {
   903   mTrackType = aType;
   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   }
   913   boxes.AppendElement(new DataInformationBox(aControl));
   914   boxes.AppendElement(new SampleTableBox(aType, aControl));
   915   MOZ_COUNT_CTOR(MediaInformationBox);
   916 }
   918 MediaInformationBox::~MediaInformationBox()
   919 {
   920   MOZ_COUNT_DTOR(MediaInformationBox);
   921 }
   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   }
   933   size += sizeof(pre_defined) +
   934           sizeof(handler_type) +
   935           sizeof(reserved);
   937   *aBoxSize = size;
   939   return NS_OK;
   940 }
   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);
   950   return NS_OK;
   951 }
   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 }
   963 HandlerBox::~HandlerBox()
   964 {
   965   MOZ_COUNT_DTOR(HandlerBox);
   966 }
   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 }
   984 MediaHeaderBox::~MediaHeaderBox()
   985 {
   986   MOZ_COUNT_DTOR(MediaHeaderBox);
   987 }
   989 uint32_t
   990 MediaHeaderBox::GetTimeScale()
   991 {
   992   if (mTrackType == Audio_Track) {
   993     return mAudioMeta->GetAudioSampleRate();
   994   }
   996   return mVideoMeta->GetVideoClockRate();
   997 }
   999 nsresult
  1000 MediaHeaderBox::Generate(uint32_t* aBoxSize)
  1002   creation_time = mControl->GetTime();
  1003   modification_time = mControl->GetTime();
  1004   timescale = GetTimeScale();
  1005   duration = 0; // fragmented mp4
  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;
  1013   pre_defined = 0;
  1014   size += sizeof(creation_time) +
  1015           sizeof(modification_time) +
  1016           sizeof(timescale) +
  1017           sizeof(duration) +
  1018           sizeof(pre_defined);
  1020   *aBoxSize = size;
  1022   return NS_OK;
  1025 nsresult
  1026 MediaHeaderBox::Write()
  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);
  1039   return NS_OK;
  1042 MovieBox::MovieBox(ISOControl* aControl)
  1043   : DefaultContainerImpl(NS_LITERAL_CSTRING("moov"), aControl)
  1045   boxes.AppendElement(new MovieHeaderBox(aControl));
  1046   if (aControl->HasAudioTrack()) {
  1047     boxes.AppendElement(new TrackBox(Audio_Track, aControl));
  1049   if (aControl->HasVideoTrack()) {
  1050     boxes.AppendElement(new TrackBox(Video_Track, aControl));
  1052   boxes.AppendElement(new MovieExtendsBox(aControl));
  1053   MOZ_COUNT_CTOR(MovieBox);
  1056 MovieBox::~MovieBox()
  1058   MOZ_COUNT_DTOR(MovieBox);
  1061 nsresult
  1062 MovieHeaderBox::Generate(uint32_t* aBoxSize)
  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();
  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);
  1082   *aBoxSize = size;
  1084   return NS_OK;
  1087 nsresult
  1088 MovieHeaderBox::Write()
  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);
  1103   return NS_OK;
  1106 uint32_t
  1107 MovieHeaderBox::GetTimeScale()
  1109   // Only audio track in container.
  1110   if (mAudioMeta && !mVideoMeta) {
  1111     return mAudioMeta->GetAudioSampleRate();
  1114   // return video rate
  1115   return mVideoMeta->GetVideoClockRate();
  1118 MovieHeaderBox::~MovieHeaderBox()
  1120   MOZ_COUNT_DTOR(MovieHeaderBox);
  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)
  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);
  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)
  1156   mTrackType = aType;
  1157   memcpy(matrix, iso_matrix, sizeof(matrix));
  1158   memset(reserved2, 0, sizeof(reserved2));
  1159   MOZ_COUNT_CTOR(TrackHeaderBox);
  1162 TrackHeaderBox::~TrackHeaderBox()
  1164   MOZ_COUNT_DTOR(TrackHeaderBox);
  1167 nsresult
  1168 TrackHeaderBox::Generate(uint32_t* aBoxSize)
  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;
  1178   // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2
  1179   volume = (mTrackType == Audio_Track ? 0x0100 : 0);
  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;
  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);
  1205   *aBoxSize = size;
  1207   return NS_OK;
  1210 nsresult
  1211 TrackHeaderBox::Write()
  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);
  1228   return NS_OK;
  1231 nsresult
  1232 FileTypeBox::Generate(uint32_t* aBoxSize)
  1234   minor_version = 0;
  1236   if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_MP4) {
  1237     if (!mControl->HasVideoTrack() && mControl->HasAudioTrack()) {
  1238       major_brand = "M4A ";
  1239     } else {
  1240       major_brand = "MP42";
  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);
  1257   size += major_brand.Length() +
  1258           sizeof(minor_version) +
  1259           compatible_brands.Length() * 4;
  1261   *aBoxSize = size;
  1263   return NS_OK;
  1266 nsresult
  1267 FileTypeBox::Write()
  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());
  1278   return NS_OK;
  1281 FileTypeBox::FileTypeBox(ISOControl* aControl)
  1282   : Box(NS_LITERAL_CSTRING("ftyp"), aControl)
  1283   , minor_version(0)
  1285   MOZ_COUNT_CTOR(FileTypeBox);
  1288 FileTypeBox::~FileTypeBox()
  1290   MOZ_COUNT_DTOR(FileTypeBox);
  1293 MediaBox::MediaBox(uint32_t aType, ISOControl* aControl)
  1294   : DefaultContainerImpl(NS_LITERAL_CSTRING("mdia"), aControl)
  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);
  1303 MediaBox::~MediaBox()
  1305   MOZ_COUNT_DTOR(MediaBox);
  1308 nsresult
  1309 DefaultContainerImpl::Generate(uint32_t* aBoxSize)
  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;
  1319   *aBoxSize = size;
  1320   return NS_OK;
  1323 nsresult
  1324 DefaultContainerImpl::Find(const nsACString& aType,
  1325                            nsTArray<nsRefPtr<MuxerOperation>>& aOperations)
  1327   nsresult rv = Box::Find(aType, aOperations);
  1328   NS_ENSURE_SUCCESS(rv, rv);
  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);
  1335   return NS_OK;
  1338 nsresult
  1339 DefaultContainerImpl::Write()
  1341   BoxSizeChecker checker(mControl, size);
  1342   Box::Write();
  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);
  1351   return NS_OK;
  1354 DefaultContainerImpl::DefaultContainerImpl(const nsACString& aType,
  1355                                            ISOControl* aControl)
  1356   : Box(aType, aControl)
  1360 nsresult
  1361 Box::Write()
  1363   mControl->Write(size);
  1364   mControl->WriteFourCC(boxType.get());
  1365   return NS_OK;
  1368 nsresult
  1369 Box::Find(const nsACString& aType, nsTArray<nsRefPtr<MuxerOperation>>& aOperations)
  1371   if (boxType == aType) {
  1372     aOperations.AppendElement(this);
  1374   return NS_OK;
  1377 Box::Box(const nsACString& aType, ISOControl* aControl)
  1378   : size(8), mControl(aControl)
  1380   MOZ_ASSERT(aType.Length() == 4);
  1381   boxType = aType;
  1382   aControl->GetAudioMetadata(mAudioMeta);
  1383   aControl->GetVideoMetadata(mVideoMeta);
  1386 FullBox::FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags,
  1387                  ISOControl* aControl)
  1388   : Box(aType, aControl)
  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;
  1397 nsresult
  1398 FullBox::Write()
  1400   Box::Write();
  1401   mControl->Write(version);
  1402   mControl->WriteBits(flags.to_ulong(), flags.size());
  1403   return NS_OK;
  1406 TrackBox::TrackBox(uint32_t aTrackType, ISOControl* aControl)
  1407   : DefaultContainerImpl(NS_LITERAL_CSTRING("trak"), aControl)
  1409   boxes.AppendElement(new TrackHeaderBox(aTrackType, aControl));
  1410   boxes.AppendElement(new MediaBox(aTrackType, aControl));
  1411   MOZ_COUNT_CTOR(TrackBox);
  1414 TrackBox::~TrackBox()
  1416   MOZ_COUNT_DTOR(TrackBox);
  1419 SampleEntryBox::SampleEntryBox(const nsACString& aFormat, ISOControl* aControl)
  1420   : Box(aFormat, aControl)
  1421   , data_reference_index(0)
  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));
  1429 nsresult
  1430 SampleEntryBox::Write()
  1432   Box::Write();
  1433   mControl->Write(reserved, sizeof(reserved));
  1434   mControl->Write(data_reference_index);
  1435   return NS_OK;
  1438 nsresult
  1439 AudioSampleEntry::Write()
  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;
  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)
  1461   memset(reserved2, 0 , sizeof(reserved2));
  1462   channels = mAudioMeta->GetAudioChannels();
  1463   timeScale = mAudioMeta->GetAudioSampleRate() << 16;
  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);
  1473   MOZ_COUNT_CTOR(AudioSampleEntry);
  1476 AudioSampleEntry::~AudioSampleEntry()
  1478   MOZ_COUNT_DTOR(AudioSampleEntry);
  1481 nsresult
  1482 VisualSampleEntry::Write()
  1484   SampleEntryBox::Write();
  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);
  1497   return NS_OK;
  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)
  1511   memset(reserved, 0 , sizeof(reserved));
  1512   memset(compressorName, 0 , sizeof(compressorName));
  1514   // both fields occupy 16 bits defined in 14496-2 6.2.3.
  1515   width = mVideoMeta->GetVideoWidth();
  1516   height = mVideoMeta->GetVideoHeight();
  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);
  1529   MOZ_COUNT_CTOR(VisualSampleEntry);
  1532 VisualSampleEntry::~VisualSampleEntry()
  1534   MOZ_COUNT_DTOR(VisualSampleEntry);

mercurial