diff options
Diffstat (limited to 'dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp')
-rw-r--r-- | dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp | 1550 |
1 files changed, 0 insertions, 1550 deletions
diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp deleted file mode 100644 index 32a0c577b..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp +++ /dev/null @@ -1,1550 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include <climits> -#include "TrackMetadataBase.h" -#include "ISOMediaBoxes.h" -#include "ISOControl.h" -#include "ISOMediaWriter.h" -#include "EncodedFrameContainer.h" -#include "ISOTrackMetadata.h" -#include "MP4ESDS.h" -#include "AMRBox.h" -#include "AVCBox.h" -#include "EVRCBox.h" -#include "VideoUtils.h" - -namespace mozilla { - -// 14496-12 6.2.2 'Data Types and fields' -const uint32_t iso_matrix[] = { 0x00010000, 0, 0, - 0, 0x00010000, 0, - 0, 0, 0x40000000 }; - -uint32_t -set_sample_flags(bool aSync) -{ - std::bitset<32> flags; - flags.set(16, !aSync); - return flags.to_ulong(); -} - -Box::BoxSizeChecker::BoxSizeChecker(ISOControl* aControl, uint32_t aSize) -{ - mControl = aControl; - ori_size = mControl->GetBufPos(); - box_size = aSize; - MOZ_COUNT_CTOR(BoxSizeChecker); -} - -Box::BoxSizeChecker::~BoxSizeChecker() -{ - uint32_t cur_size = mControl->GetBufPos(); - if ((cur_size - ori_size) != box_size) { - MOZ_ASSERT(false); - } - - MOZ_COUNT_DTOR(BoxSizeChecker); -} - -nsresult -MediaDataBox::Generate(uint32_t* aBoxSize) -{ - mFirstSampleOffset = size; - mAllSampleSize = 0; - - if (mTrackType & Audio_Track) { - FragmentBuffer* frag = mControl->GetFragment(Audio_Track); - mAllSampleSize += frag->GetFirstFragmentSampleSize(); - } - if (mTrackType & Video_Track) { - FragmentBuffer* frag = mControl->GetFragment(Video_Track); - mAllSampleSize += frag->GetFirstFragmentSampleSize(); - } - - size += mAllSampleSize; - *aBoxSize = size; - return NS_OK; -} - -nsresult -MediaDataBox::Write() -{ - nsresult rv; - BoxSizeChecker checker(mControl, size); - Box::Write(); - nsTArray<uint32_t> types; - types.AppendElement(Audio_Track); - types.AppendElement(Video_Track); - - for (uint32_t l = 0; l < types.Length(); l++) { - if (mTrackType & types[l]) { - FragmentBuffer* frag = mControl->GetFragment(types[l]); - nsTArray<RefPtr<EncodedFrame>> frames; - - // Here is the last time we get fragment frames, flush it! - rv = frag->GetFirstFragment(frames, true); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t len = frames.Length(); - for (uint32_t i = 0; i < len; i++) { - nsTArray<uint8_t> frame_buffer; - frames.ElementAt(i)->SwapOutFrameData(frame_buffer); - mControl->WriteAVData(frame_buffer); - } - } - } - - return NS_OK; -} - -MediaDataBox::MediaDataBox(uint32_t aTrackType, ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("mdat"), aControl) - , mAllSampleSize(0) - , mFirstSampleOffset(0) - , mTrackType(aTrackType) -{ - MOZ_COUNT_CTOR(MediaDataBox); -} - -MediaDataBox::~MediaDataBox() -{ - MOZ_COUNT_DTOR(MediaDataBox); -} - -uint32_t -TrackRunBox::fillSampleTable() -{ - uint32_t table_size = 0; - nsresult rv; - nsTArray<RefPtr<EncodedFrame>> frames; - FragmentBuffer* frag = mControl->GetFragment(mTrackType); - - rv = frag->GetFirstFragment(frames); - if (NS_FAILED(rv)) { - return 0; - } - uint32_t len = frames.Length(); - sample_info_table = MakeUnique<tbl[]>(len); - // Create sample table according to 14496-12 8.8.8.2. - for (uint32_t i = 0; i < len; i++) { - // Sample size. - sample_info_table[i].sample_size = 0; - if (flags.to_ulong() & flags_sample_size_present) { - sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length(); - mAllSampleSize += sample_info_table[i].sample_size; - table_size += sizeof(uint32_t); - } - - // Sample flags. - sample_info_table[i].sample_flags = 0; - if (flags.to_ulong() & flags_sample_flags_present) { - sample_info_table[i].sample_flags = - set_sample_flags( - (frames.ElementAt(i)->GetFrameType() == EncodedFrame::AVC_I_FRAME)); - table_size += sizeof(uint32_t); - } - - // Sample duration. - sample_info_table[i].sample_duration = 0; - if (flags.to_ulong() & flags_sample_duration_present) { - // Calculate each frame's duration, it is decided by "current frame - // timestamp - last frame timestamp". - uint64_t frame_time = 0; - if (i == 0) { - frame_time = frames.ElementAt(i)->GetTimeStamp() - - frag->GetLastFragmentLastFrameTime(); - } else { - frame_time = frames.ElementAt(i)->GetTimeStamp() - - frames.ElementAt(i - 1)->GetTimeStamp(); - // Keep the last frame time of current fagment, it will be used to calculate - // the first frame duration of next fragment. - if ((len - 1) == i) { - frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp()); - } - } - - // In TrackRunBox, there should be exactly one type, either audio or video. - MOZ_ASSERT((mTrackType & Video_Track) ^ (mTrackType & Audio_Track)); - sample_info_table[i].sample_duration = (mTrackType & Video_Track ? - frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S : - frame_time * mAudioMeta->GetAudioSampleRate() / USECS_PER_S); - - table_size += sizeof(uint32_t); - } - - sample_info_table[i].sample_composition_time_offset = 0; - } - return table_size; -} - -nsresult -TrackRunBox::Generate(uint32_t* aBoxSize) -{ - FragmentBuffer* frag = mControl->GetFragment(mTrackType); - sample_count = frag->GetFirstFragmentSampleNumber(); - size += sizeof(sample_count); - - // data_offset needs to be updated if there is other - // TrackRunBox before this one. - if (flags.to_ulong() & flags_data_offset_present) { - data_offset = 0; - size += sizeof(data_offset); - } - size += fillSampleTable(); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackRunBox::SetDataOffset(uint32_t aOffset) -{ - data_offset = aOffset; - return NS_OK; -} - -nsresult -TrackRunBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sample_count); - if (flags.to_ulong() & flags_data_offset_present) { - mControl->Write(data_offset); - } - for (uint32_t i = 0; i < sample_count; i++) { - if (flags.to_ulong() & flags_sample_duration_present) { - mControl->Write(sample_info_table[i].sample_duration); - } - if (flags.to_ulong() & flags_sample_size_present) { - mControl->Write(sample_info_table[i].sample_size); - } - if (flags.to_ulong() & flags_sample_flags_present) { - mControl->Write(sample_info_table[i].sample_flags); - } - } - - return NS_OK; -} - -TrackRunBox::TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("trun"), 0, aFlags, aControl) - , sample_count(0) - , data_offset(0) - , first_sample_flags(0) - , mAllSampleSize(0) - , mTrackType(aType) -{ - MOZ_COUNT_CTOR(TrackRunBox); -} - -TrackRunBox::~TrackRunBox() -{ - MOZ_COUNT_DTOR(TrackRunBox); -} - -nsresult -TrackFragmentHeaderBox::UpdateBaseDataOffset(uint64_t aOffset) -{ - base_data_offset = aOffset; - return NS_OK; -} - -nsresult -TrackFragmentHeaderBox::Generate(uint32_t* aBoxSize) -{ - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - size += sizeof(track_ID); - - if (flags.to_ulong() & base_data_offset_present) { - // base_data_offset needs to add size of 'trun', 'tfhd' and - // header of 'mdat' later. - base_data_offset = 0; - size += sizeof(base_data_offset); - } - if (flags.to_ulong() & default_sample_duration_present) { - if (mTrackType == Video_Track) { - if (!mVideoMeta->GetVideoFrameRate()) { - // 0 means frame rate is variant, so it is wrong to write - // default_sample_duration. - MOZ_ASSERT(0); - default_sample_duration = 0; - } else { - default_sample_duration = mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate(); - } - } else if (mTrackType == Audio_Track) { - default_sample_duration = mAudioMeta->GetAudioFrameDuration(); - } else { - MOZ_ASSERT(0); - return NS_ERROR_FAILURE; - } - size += sizeof(default_sample_duration); - } - *aBoxSize = size; - return NS_OK; -} - -nsresult -TrackFragmentHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(track_ID); - if (flags.to_ulong() & base_data_offset_present) { - mControl->Write(base_data_offset); - } - if (flags.to_ulong() & default_sample_duration_present) { - mControl->Write(default_sample_duration); - } - return NS_OK; -} - -TrackFragmentHeaderBox::TrackFragmentHeaderBox(uint32_t aType, - uint32_t aFlags, - ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("tfhd"), 0, aFlags, aControl) - , track_ID(0) - , base_data_offset(0) - , default_sample_duration(0) -{ - mTrackType = aType; - MOZ_COUNT_CTOR(TrackFragmentHeaderBox); -} - -TrackFragmentHeaderBox::~TrackFragmentHeaderBox() -{ - MOZ_COUNT_DTOR(TrackFragmentHeaderBox); -} - -TrackFragmentBox::TrackFragmentBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("traf"), aControl) - , mTrackType(aType) -{ - // Flags in TrackFragmentHeaderBox. - uint32_t tf_flags = base_data_offset_present; - - // Ideally, audio encoder generates audio frame in const rate. However, some - // audio encoders don't do it so the audio frame duration needs to be checked - // here. - if ((mTrackType & Audio_Track) && mAudioMeta->GetAudioFrameDuration()) { - tf_flags |= default_sample_duration_present; - } - - boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl)); - - // Always adds flags_data_offset_present in each TrackRunBox, Android - // parser requires this flag to calculate the correct bitstream offset. - uint32_t tr_flags = flags_sample_size_present | flags_data_offset_present; - - // Flags in TrackRunBox. - // If there is no default sample duration exists, each frame duration needs to - // be recored in the TrackRunBox. - tr_flags |= (tf_flags & default_sample_duration_present ? 0 : flags_sample_duration_present); - - // For video, add sample_flags to record I frame. - tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0); - - boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl)); - MOZ_COUNT_CTOR(TrackFragmentBox); -} - -TrackFragmentBox::~TrackFragmentBox() -{ - MOZ_COUNT_DTOR(TrackFragmentBox); -} - -nsresult -MovieFragmentHeaderBox::Generate(uint32_t* aBoxSize) -{ - sequence_number = mControl->GetCurFragmentNumber(); - size += sizeof(sequence_number); - *aBoxSize = size; - return NS_OK; -} - -nsresult -MovieFragmentHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sequence_number); - return NS_OK; -} - -MovieFragmentHeaderBox::MovieFragmentHeaderBox(uint32_t aTrackType, - ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mfhd"), 0, 0, aControl) - , sequence_number(0) - , mTrackType(aTrackType) -{ - MOZ_COUNT_CTOR(MovieFragmentHeaderBox); -} - -MovieFragmentHeaderBox::~MovieFragmentHeaderBox() -{ - MOZ_COUNT_DTOR(MovieFragmentHeaderBox); -} - -MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("moof"), aControl) - , mTrackType(aType) -{ - boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl)); - - if (mTrackType & Audio_Track) { - boxes.AppendElement( - new TrackFragmentBox(Audio_Track, aControl)); - } - if (mTrackType & Video_Track) { - boxes.AppendElement( - new TrackFragmentBox(Video_Track, aControl)); - } - MOZ_COUNT_CTOR(MovieFragmentBox); -} - -MovieFragmentBox::~MovieFragmentBox() -{ - MOZ_COUNT_DTOR(MovieFragmentBox); -} - -nsresult -MovieFragmentBox::Generate(uint32_t* aBoxSize) -{ - nsresult rv = DefaultContainerImpl::Generate(aBoxSize); - NS_ENSURE_SUCCESS(rv, rv); - - // Correct data_offset if there are both audio and video track in - // this fragment. This offset means the offset in the MediaDataBox. - if (mTrackType & (Audio_Track | Video_Track)) { - nsTArray<RefPtr<MuxerOperation>> truns; - rv = Find(NS_LITERAL_CSTRING("trun"), truns); - NS_ENSURE_SUCCESS(rv, rv); - uint32_t len = truns.Length(); - uint32_t data_offset = 0; - for (uint32_t i = 0; i < len; i++) { - TrackRunBox* trun = (TrackRunBox*) truns.ElementAt(i).get(); - rv = trun->SetDataOffset(data_offset); - NS_ENSURE_SUCCESS(rv, rv); - data_offset += trun->GetAllSampleSize(); - } - } - - return NS_OK; -} - -nsresult -TrackExtendsBox::Generate(uint32_t* aBoxSize) -{ - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - - if (mTrackType == Audio_Track) { - default_sample_description_index = 1; - default_sample_duration = mAudioMeta->GetAudioFrameDuration(); - default_sample_size = mAudioMeta->GetAudioFrameSize(); - default_sample_flags = set_sample_flags(1); - } else if (mTrackType == Video_Track) { - default_sample_description_index = 1; - // Video meta data has assigned framerate, it implies that this video's - // frame rate should be fixed. - if (mVideoMeta->GetVideoFrameRate()) { - default_sample_duration = - mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate(); - } - default_sample_size = 0; - default_sample_flags = set_sample_flags(0); - } else { - MOZ_ASSERT(0); - return NS_ERROR_FAILURE; - } - - size += sizeof(track_ID) + - sizeof(default_sample_description_index) + - sizeof(default_sample_duration) + - sizeof(default_sample_size) + - sizeof(default_sample_flags); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackExtendsBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(track_ID); - mControl->Write(default_sample_description_index); - mControl->Write(default_sample_duration); - mControl->Write(default_sample_size); - mControl->Write(default_sample_flags); - - return NS_OK; -} - -TrackExtendsBox::TrackExtendsBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("trex"), 0, 0, aControl) - , track_ID(0) - , default_sample_description_index(0) - , default_sample_duration(0) - , default_sample_size(0) - , default_sample_flags(0) - , mTrackType(aType) -{ - MOZ_COUNT_CTOR(TrackExtendsBox); -} - -TrackExtendsBox::~TrackExtendsBox() -{ - MOZ_COUNT_DTOR(TrackExtendsBox); -} - -MovieExtendsBox::MovieExtendsBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("mvex"), aControl) -{ - if (mAudioMeta) { - boxes.AppendElement(new TrackExtendsBox(Audio_Track, aControl)); - } - if (mVideoMeta) { - boxes.AppendElement(new TrackExtendsBox(Video_Track, aControl)); - } - MOZ_COUNT_CTOR(MovieExtendsBox); -} - -MovieExtendsBox::~MovieExtendsBox() -{ - MOZ_COUNT_DTOR(MovieExtendsBox); -} - -nsresult -ChunkOffsetBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4. - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -ChunkOffsetBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -ChunkOffsetBox::ChunkOffsetBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stco"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(ChunkOffsetBox); -} - -ChunkOffsetBox::~ChunkOffsetBox() -{ - MOZ_COUNT_DTOR(ChunkOffsetBox); -} - -nsresult -SampleToChunkBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4 - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -SampleToChunkBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -SampleToChunkBox::SampleToChunkBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsc"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(SampleToChunkBox); -} - -SampleToChunkBox::~SampleToChunkBox() -{ - MOZ_COUNT_DTOR(SampleToChunkBox); -} - -nsresult -TimeToSampleBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4. - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -TimeToSampleBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -TimeToSampleBox::TimeToSampleBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stts"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(TimeToSampleBox); -} - -TimeToSampleBox::~TimeToSampleBox() -{ - MOZ_COUNT_DTOR(TimeToSampleBox); -} - -nsresult -SampleDescriptionBox::Generate(uint32_t* aBoxSize) -{ - entry_count = 1; - size += sizeof(entry_count); - - nsresult rv; - uint32_t box_size; - rv = sample_entry_box->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - *aBoxSize = size; - - return NS_OK; -} - -nsresult -SampleDescriptionBox::Write() -{ - WRITE_FULLBOX(mControl, size) - nsresult rv; - mControl->Write(entry_count); - rv = sample_entry_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -SampleDescriptionBox::SampleDescriptionBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsd"), 0, 0, aControl) - , entry_count(0) -{ - mTrackType = aType; - - switch (mTrackType) { - case Audio_Track: - { - CreateAudioSampleEntry(sample_entry_box); - } - break; - case Video_Track: - { - CreateVideoSampleEntry(sample_entry_box); - } - break; - } - MOZ_ASSERT(sample_entry_box); - MOZ_COUNT_CTOR(SampleDescriptionBox); -} - -nsresult -SampleDescriptionBox::CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry) -{ - if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AMR) { - aSampleEntry = new AMRSampleEntry(mControl); - } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AAC) { - aSampleEntry = new MP4AudioSampleEntry(mControl); - } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) { - aSampleEntry = new EVRCSampleEntry(mControl); - } else { - MOZ_ASSERT(0); - } - return NS_OK; -} - -nsresult -SampleDescriptionBox::CreateVideoSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry) -{ - if (mVideoMeta->GetKind() == TrackMetadataBase::METADATA_AVC) { - aSampleEntry = new AVCSampleEntry(mControl); - } else { - MOZ_ASSERT(0); - } - return NS_OK; -} - -SampleDescriptionBox::~SampleDescriptionBox() -{ - MOZ_COUNT_DTOR(SampleDescriptionBox); -} - -nsresult -SampleSizeBox::Generate(uint32_t* aBoxSize) -{ - size += sizeof(sample_size) + - sizeof(sample_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -SampleSizeBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sample_size); - mControl->Write(sample_count); - return NS_OK; -} - -SampleSizeBox::SampleSizeBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsz"), 0, 0, aControl) - , sample_size(0) - , sample_count(0) -{ - MOZ_COUNT_CTOR(SampleSizeBox); -} - -SampleSizeBox::~SampleSizeBox() -{ - MOZ_COUNT_DTOR(SampleSizeBox); -} - -SampleTableBox::SampleTableBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("stbl"), aControl) -{ - boxes.AppendElement(new SampleDescriptionBox(aType, aControl)); - boxes.AppendElement(new TimeToSampleBox(aType, aControl)); - boxes.AppendElement(new SampleToChunkBox(aType, aControl)); - boxes.AppendElement(new SampleSizeBox(aControl)); - boxes.AppendElement(new ChunkOffsetBox(aType, aControl)); - MOZ_COUNT_CTOR(SampleTableBox); -} - -SampleTableBox::~SampleTableBox() -{ - MOZ_COUNT_DTOR(SampleTableBox); -} - -nsresult -DataEntryUrlBox::Generate(uint32_t* aBoxSize) -{ - // location is null here, do nothing - size += location.Length(); - *aBoxSize = size; - - return NS_OK; -} - -nsresult -DataEntryUrlBox::Write() -{ - WRITE_FULLBOX(mControl, size) - return NS_OK; -} - -DataEntryUrlBox::DataEntryUrlBox() - : FullBox(NS_LITERAL_CSTRING("url "), 0, 0, (ISOControl*) nullptr) -{ - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::DataEntryUrlBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("url "), 0, flags_media_at_the_same_file, aControl) -{ - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::DataEntryUrlBox(const DataEntryUrlBox& aBox) - : FullBox(aBox.boxType, aBox.version, aBox.flags.to_ulong(), aBox.mControl) -{ - location = aBox.location; - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::~DataEntryUrlBox() -{ - MOZ_COUNT_DTOR(DataEntryUrlBox); -} - -nsresult DataReferenceBox::Generate(uint32_t* aBoxSize) -{ - entry_count = 1; // only allow on entry here - size += sizeof(uint32_t); - - for (uint32_t i = 0; i < entry_count; i++) { - uint32_t box_size = 0; - DataEntryUrlBox* url = new DataEntryUrlBox(mControl); - url->Generate(&box_size); - size += box_size; - urls.AppendElement(url); - } - - *aBoxSize = size; - - return NS_OK; -} - -nsresult DataReferenceBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - - for (uint32_t i = 0; i < entry_count; i++) { - urls[i]->Write(); - } - - return NS_OK; -} - -DataReferenceBox::DataReferenceBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("dref"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(DataReferenceBox); -} - -DataReferenceBox::~DataReferenceBox() -{ - MOZ_COUNT_DTOR(DataReferenceBox); -} - -DataInformationBox::DataInformationBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("dinf"), aControl) -{ - boxes.AppendElement(new DataReferenceBox(aControl)); - MOZ_COUNT_CTOR(DataInformationBox); -} - -DataInformationBox::~DataInformationBox() -{ - MOZ_COUNT_DTOR(DataInformationBox); -} - -nsresult -VideoMediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - size += sizeof(graphicsmode) + - sizeof(opcolor); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -VideoMediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(graphicsmode); - mControl->WriteArray(opcolor, 3); - return NS_OK; -} - -VideoMediaHeaderBox::VideoMediaHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("vmhd"), 0, 1, aControl) - , graphicsmode(0) -{ - memset(opcolor, 0 , sizeof(opcolor)); - MOZ_COUNT_CTOR(VideoMediaHeaderBox); -} - -VideoMediaHeaderBox::~VideoMediaHeaderBox() -{ - MOZ_COUNT_DTOR(VideoMediaHeaderBox); -} - -nsresult -SoundMediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - balance = 0; - reserved = 0; - size += sizeof(balance) + - sizeof(reserved); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -SoundMediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(balance); - mControl->Write(reserved); - - return NS_OK; -} - -SoundMediaHeaderBox::SoundMediaHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("smhd"), 0, 0, aControl) -{ - MOZ_COUNT_CTOR(SoundMediaHeaderBox); -} - -SoundMediaHeaderBox::~SoundMediaHeaderBox() -{ - MOZ_COUNT_DTOR(SoundMediaHeaderBox); -} - -MediaInformationBox::MediaInformationBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("minf"), aControl) -{ - mTrackType = aType; - - if (mTrackType == Audio_Track) { - boxes.AppendElement(new SoundMediaHeaderBox(aControl)); - } else if (mTrackType == Video_Track) { - boxes.AppendElement(new VideoMediaHeaderBox(aControl)); - } else { - MOZ_ASSERT(0); - } - - boxes.AppendElement(new DataInformationBox(aControl)); - boxes.AppendElement(new SampleTableBox(aType, aControl)); - MOZ_COUNT_CTOR(MediaInformationBox); -} - -MediaInformationBox::~MediaInformationBox() -{ - MOZ_COUNT_DTOR(MediaInformationBox); -} - -nsresult -HandlerBox::Generate(uint32_t* aBoxSize) -{ - pre_defined = 0; - if (mTrackType == Audio_Track) { - handler_type = FOURCC('s', 'o', 'u', 'n'); - } else if (mTrackType == Video_Track) { - handler_type = FOURCC('v', 'i', 'd', 'e'); - } - - size += sizeof(pre_defined) + - sizeof(handler_type) + - sizeof(reserved); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -HandlerBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(pre_defined); - mControl->Write(handler_type); - mControl->WriteArray(reserved, 3); - - return NS_OK; -} - -HandlerBox::HandlerBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("hdlr"), 0, 0, aControl) - , pre_defined(0) - , handler_type(0) -{ - mTrackType = aType; - memset(reserved, 0 , sizeof(reserved)); - MOZ_COUNT_CTOR(HandlerBox); -} - -HandlerBox::~HandlerBox() -{ - MOZ_COUNT_DTOR(HandlerBox); -} - -MediaHeaderBox::MediaHeaderBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mdhd"), 0, 0, aControl) - , creation_time(0) - , modification_time(0) - , timescale(0) - , duration(0) - , pad(0) - , lang1(0) - , lang2(0) - , lang3(0) - , pre_defined(0) -{ - mTrackType = aType; - MOZ_COUNT_CTOR(MediaHeaderBox); -} - -MediaHeaderBox::~MediaHeaderBox() -{ - MOZ_COUNT_DTOR(MediaHeaderBox); -} - -uint32_t -MediaHeaderBox::GetTimeScale() -{ - if (mTrackType == Audio_Track) { - return mAudioMeta->GetAudioSampleRate(); - } - - return mVideoMeta->GetVideoClockRate(); -} - -nsresult -MediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - timescale = GetTimeScale(); - duration = 0; // fragmented mp4 - - pad = 0; - lang1 = 'u' - 0x60; // "und" underdetermined language - lang2 = 'n' - 0x60; - lang3 = 'd' - 0x60; - size += (pad.size() + lang1.size() + lang2.size() + lang3.size()) / CHAR_BIT; - - pre_defined = 0; - size += sizeof(creation_time) + - sizeof(modification_time) + - sizeof(timescale) + - sizeof(duration) + - sizeof(pre_defined); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -MediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(timescale); - mControl->Write(duration); - mControl->WriteBits(pad.to_ulong(), pad.size()); - mControl->WriteBits(lang1.to_ulong(), lang1.size()); - mControl->WriteBits(lang2.to_ulong(), lang2.size()); - mControl->WriteBits(lang3.to_ulong(), lang3.size()); - mControl->Write(pre_defined); - - return NS_OK; -} - -MovieBox::MovieBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("moov"), aControl) -{ - boxes.AppendElement(new MovieHeaderBox(aControl)); - if (aControl->HasAudioTrack()) { - boxes.AppendElement(new TrackBox(Audio_Track, aControl)); - } - if (aControl->HasVideoTrack()) { - boxes.AppendElement(new TrackBox(Video_Track, aControl)); - } - boxes.AppendElement(new MovieExtendsBox(aControl)); - MOZ_COUNT_CTOR(MovieBox); -} - -MovieBox::~MovieBox() -{ - MOZ_COUNT_DTOR(MovieBox); -} - -nsresult -MovieHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - timescale = GetTimeScale(); - duration = 0; // The duration is always 0 in fragmented mp4. - next_track_ID = mControl->GetNextTrackID(); - - size += sizeof(next_track_ID) + - sizeof(creation_time) + - sizeof(modification_time) + - sizeof(timescale) + - sizeof(duration) + - sizeof(rate) + - sizeof(volume) + - sizeof(reserved16) + - sizeof(reserved32) + - sizeof(matrix) + - sizeof(pre_defined); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -MovieHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(timescale); - mControl->Write(duration); - mControl->Write(rate); - mControl->Write(volume); - mControl->Write(reserved16); - mControl->WriteArray(reserved32, 2); - mControl->WriteArray(matrix, 9); - mControl->WriteArray(pre_defined, 6); - mControl->Write(next_track_ID); - - return NS_OK; -} - -uint32_t -MovieHeaderBox::GetTimeScale() -{ - // Only audio track in container. - if (mAudioMeta && !mVideoMeta) { - return mAudioMeta->GetAudioSampleRate(); - } - - // return video rate - return mVideoMeta->GetVideoClockRate(); -} - -MovieHeaderBox::~MovieHeaderBox() -{ - MOZ_COUNT_DTOR(MovieHeaderBox); -} - -MovieHeaderBox::MovieHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mvhd"), 0, 0, aControl) - , creation_time(0) - , modification_time(0) - , timescale(90000) - , duration(0) - , rate(0x00010000) - , volume(0x0100) - , reserved16(0) - , next_track_ID(1) -{ - memcpy(matrix, iso_matrix, sizeof(matrix)); - memset(reserved32, 0, sizeof(reserved32)); - memset(pre_defined, 0, sizeof(pre_defined)); - MOZ_COUNT_CTOR(MovieHeaderBox); -} - -TrackHeaderBox::TrackHeaderBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("tkhd"), 0, - flags_track_enabled | flags_track_in_movie | flags_track_in_preview, - aControl) - , creation_time(0) - , modification_time(0) - , track_ID(0) - , reserved(0) - , duration(0) - , layer(0) - , alternate_group(0) - , volume(0) - , reserved3(0) - , width(0) - , height(0) -{ - mTrackType = aType; - memcpy(matrix, iso_matrix, sizeof(matrix)); - memset(reserved2, 0, sizeof(reserved2)); - MOZ_COUNT_CTOR(TrackHeaderBox); -} - -TrackHeaderBox::~TrackHeaderBox() -{ - MOZ_COUNT_DTOR(TrackHeaderBox); -} - -nsresult -TrackHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - // fragmented mp4 - duration = 0; - - // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2 - volume = (mTrackType == Audio_Track ? 0x0100 : 0); - - if (mTrackType == Video_Track) { - width = mVideoMeta->GetVideoDisplayWidth() << 16; - height = mVideoMeta->GetVideoDisplayHeight() << 16; - // Check display size, using the pixel size if any of them is invalid. - if (!width || !height) { - width = mVideoMeta->GetVideoWidth() << 16; - height = mVideoMeta->GetVideoHeight() << 16; - } - } - - size += sizeof(creation_time) + - sizeof(modification_time) + - sizeof(track_ID) + - sizeof(reserved) + - sizeof(duration) + - sizeof(reserved2) + - sizeof(layer) + - sizeof(alternate_group) + - sizeof(volume) + - sizeof(reserved3) + - sizeof(matrix) + - sizeof(width) + - sizeof(height); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(track_ID); - mControl->Write(reserved); - mControl->Write(duration); - mControl->WriteArray(reserved2, 2); - mControl->Write(layer); - mControl->Write(alternate_group); - mControl->Write(volume); - mControl->Write(reserved3); - mControl->WriteArray(matrix, 9); - mControl->Write(width); - mControl->Write(height); - - return NS_OK; -} - -nsresult -FileTypeBox::Generate(uint32_t* aBoxSize) -{ - minor_version = 0; - - if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_MP4) { - if (!mControl->HasVideoTrack() && mControl->HasAudioTrack()) { - major_brand = "M4A "; - } else { - major_brand = "MP42"; - } - compatible_brands.AppendElement("mp42"); - compatible_brands.AppendElement("isom"); - } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3GP) { - major_brand = "3gp9"; - // According to 3GPP TS 26.244 V12.2.0, section 5.3.4, it's recommended to - // list all compatible brands here. 3GP spec supports fragment from '3gp6'. - compatible_brands.AppendElement("3gp9"); - compatible_brands.AppendElement("3gp8"); - compatible_brands.AppendElement("3gp7"); - compatible_brands.AppendElement("3gp6"); - compatible_brands.AppendElement("isom"); - } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3G2) { - major_brand = "3g2a"; - // 3GPP2 Release 0 and A and 3GPP Release 6 allow movie fragmentation - compatible_brands.AppendElement("3gp9"); - compatible_brands.AppendElement("3gp8"); - compatible_brands.AppendElement("3gp7"); - compatible_brands.AppendElement("3gp6"); - compatible_brands.AppendElement("isom"); - compatible_brands.AppendElement("3g2c"); - compatible_brands.AppendElement("3g2b"); - compatible_brands.AppendElement("3g2a"); - } else { - MOZ_ASSERT(0); - } - - size += major_brand.Length() + - sizeof(minor_version) + - compatible_brands.Length() * 4; - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -FileTypeBox::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - mControl->WriteFourCC(major_brand.get()); - mControl->Write(minor_version); - uint32_t len = compatible_brands.Length(); - for (uint32_t i = 0; i < len; i++) { - mControl->WriteFourCC(compatible_brands[i].get()); - } - - return NS_OK; -} - -FileTypeBox::FileTypeBox(ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("ftyp"), aControl) - , minor_version(0) -{ - MOZ_COUNT_CTOR(FileTypeBox); -} - -FileTypeBox::~FileTypeBox() -{ - MOZ_COUNT_DTOR(FileTypeBox); -} - -MediaBox::MediaBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("mdia"), aControl) -{ - mTrackType = aType; - boxes.AppendElement(new MediaHeaderBox(aType, aControl)); - boxes.AppendElement(new HandlerBox(aType, aControl)); - boxes.AppendElement(new MediaInformationBox(aType, aControl)); - MOZ_COUNT_CTOR(MediaBox); -} - -MediaBox::~MediaBox() -{ - MOZ_COUNT_DTOR(MediaBox); -} - -nsresult -DefaultContainerImpl::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - uint32_t box_size; - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - } - *aBoxSize = size; - return NS_OK; -} - -nsresult -DefaultContainerImpl::Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) -{ - nsresult rv = Box::Find(aType, aOperations); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Find(aType, aOperations); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - -nsresult -DefaultContainerImpl::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - - nsresult rv; - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Write(); - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; -} - -DefaultContainerImpl::DefaultContainerImpl(const nsACString& aType, - ISOControl* aControl) - : Box(aType, aControl) -{ -} - -nsresult -Box::Write() -{ - mControl->Write(size); - mControl->WriteFourCC(boxType.get()); - return NS_OK; -} - -nsresult -Box::Find(const nsACString& aType, nsTArray<RefPtr<MuxerOperation>>& aOperations) -{ - if (boxType == aType) { - aOperations.AppendElement(this); - } - return NS_OK; -} - -Box::Box(const nsACString& aType, ISOControl* aControl) - : size(8), mControl(aControl) -{ - MOZ_ASSERT(aType.Length() == 4); - boxType = aType; - aControl->GetAudioMetadata(mAudioMeta); - aControl->GetVideoMetadata(mVideoMeta); -} - -FullBox::FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags, - ISOControl* aControl) - : Box(aType, aControl) -{ - std::bitset<24> tmp_flags(aFlags); - version = aVersion; - flags = tmp_flags; - size += sizeof(version) + flags.size() / CHAR_BIT; -} - -nsresult -FullBox::Write() -{ - Box::Write(); - mControl->Write(version); - mControl->WriteBits(flags.to_ulong(), flags.size()); - return NS_OK; -} - -TrackBox::TrackBox(uint32_t aTrackType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("trak"), aControl) -{ - boxes.AppendElement(new TrackHeaderBox(aTrackType, aControl)); - boxes.AppendElement(new MediaBox(aTrackType, aControl)); - MOZ_COUNT_CTOR(TrackBox); -} - -TrackBox::~TrackBox() -{ - MOZ_COUNT_DTOR(TrackBox); -} - -SampleEntryBox::SampleEntryBox(const nsACString& aFormat, ISOControl* aControl) - : Box(aFormat, aControl) - , data_reference_index(0) -{ - data_reference_index = 1; // There is only one data reference in each track. - size += sizeof(reserved) + - sizeof(data_reference_index); - memset(reserved, 0, sizeof(reserved)); -} - -nsresult -SampleEntryBox::Write() -{ - Box::Write(); - mControl->Write(reserved, sizeof(reserved)); - mControl->Write(data_reference_index); - return NS_OK; -} - -nsresult -AudioSampleEntry::Write() -{ - SampleEntryBox::Write(); - mControl->Write(sound_version); - mControl->Write(reserved2, sizeof(reserved2)); - mControl->Write(channels); - mControl->Write(sample_size); - mControl->Write(compressionId); - mControl->Write(packet_size); - mControl->Write(timeScale); - return NS_OK; -} - -AudioSampleEntry::AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl) - : SampleEntryBox(aFormat, aControl) - , sound_version(0) - , channels(2) - , sample_size(16) - , compressionId(0) - , packet_size(0) - , timeScale(0) -{ - memset(reserved2, 0 , sizeof(reserved2)); - channels = mAudioMeta->GetAudioChannels(); - timeScale = mAudioMeta->GetAudioSampleRate() << 16; - - size += sizeof(sound_version) + - sizeof(reserved2) + - sizeof(sample_size) + - sizeof(channels) + - sizeof(packet_size) + - sizeof(compressionId) + - sizeof(timeScale); - - MOZ_COUNT_CTOR(AudioSampleEntry); -} - -AudioSampleEntry::~AudioSampleEntry() -{ - MOZ_COUNT_DTOR(AudioSampleEntry); -} - -nsresult -VisualSampleEntry::Write() -{ - SampleEntryBox::Write(); - - mControl->Write(reserved, sizeof(reserved)); - mControl->Write(width); - mControl->Write(height); - mControl->Write(horizresolution); - mControl->Write(vertresolution); - mControl->Write(reserved2); - mControl->Write(frame_count); - mControl->Write(compressorName, sizeof(compressorName)); - mControl->Write(depth); - mControl->Write(pre_defined); - - return NS_OK; -} - -VisualSampleEntry::VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl) - : SampleEntryBox(aFormat, aControl) - , width(0) - , height(0) - , horizresolution(resolution_72_dpi) - , vertresolution(resolution_72_dpi) - , reserved2(0) - , frame_count(1) - , depth(video_depth) - , pre_defined(-1) -{ - memset(reserved, 0 , sizeof(reserved)); - memset(compressorName, 0 , sizeof(compressorName)); - - // both fields occupy 16 bits defined in 14496-2 6.2.3. - width = mVideoMeta->GetVideoWidth(); - height = mVideoMeta->GetVideoHeight(); - - size += sizeof(reserved) + - sizeof(width) + - sizeof(height) + - sizeof(horizresolution) + - sizeof(vertresolution) + - sizeof(reserved2) + - sizeof(frame_count) + - sizeof(compressorName) + - sizeof(depth) + - sizeof(pre_defined); - - MOZ_COUNT_CTOR(VisualSampleEntry); -} - -VisualSampleEntry::~VisualSampleEntry() -{ - MOZ_COUNT_DTOR(VisualSampleEntry); -} - -} |