summaryrefslogtreecommitdiffstats
path: root/dom/media/encoder/fmp4_muxer/ISOControl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/encoder/fmp4_muxer/ISOControl.cpp')
-rw-r--r--dom/media/encoder/fmp4_muxer/ISOControl.cpp415
1 files changed, 0 insertions, 415 deletions
diff --git a/dom/media/encoder/fmp4_muxer/ISOControl.cpp b/dom/media/encoder/fmp4_muxer/ISOControl.cpp
deleted file mode 100644
index 6addaeb30..000000000
--- a/dom/media/encoder/fmp4_muxer/ISOControl.cpp
+++ /dev/null
@@ -1,415 +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 <time.h>
-#include "nsAutoPtr.h"
-#include "ISOControl.h"
-#include "ISOMediaBoxes.h"
-#include "EncodedFrameContainer.h"
-
-namespace mozilla {
-
-// For MP4 creation_time and modification_time offset from January 1, 1904 to
-// January 1, 1970.
-#define iso_time_offset 2082844800
-
-FragmentBuffer::FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration)
- : mTrackType(aTrackType)
- , mFragDuration(aFragDuration)
- , mMediaStartTime(0)
- , mFragmentNumber(0)
- , mLastFrameTimeOfLastFragment(0)
- , mEOS(false)
-{
- mFragArray.AppendElement();
- MOZ_COUNT_CTOR(FragmentBuffer);
-}
-
-FragmentBuffer::~FragmentBuffer()
-{
- MOZ_COUNT_DTOR(FragmentBuffer);
-}
-
-bool
-FragmentBuffer::HasEnoughData()
-{
- // Audio or video frame is enough to form a moof.
- return (mFragArray.Length() > 1);
-}
-
-nsresult
-FragmentBuffer::GetCSD(nsTArray<uint8_t>& aCSD)
-{
- if (!mCSDFrame) {
- return NS_ERROR_FAILURE;
- }
- aCSD.AppendElements(mCSDFrame->GetFrameData().Elements(),
- mCSDFrame->GetFrameData().Length());
-
- return NS_OK;
-}
-
-nsresult
-FragmentBuffer::AddFrame(EncodedFrame* aFrame)
-{
- // already EOS, it rejects all new data.
- if (mEOS) {
- MOZ_ASSERT(0);
- return NS_OK;
- }
-
- EncodedFrame::FrameType type = aFrame->GetFrameType();
- if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD ||
- type == EncodedFrame::AMR_AUDIO_CSD || type == EncodedFrame::EVRC_AUDIO_CSD) {
- mCSDFrame = aFrame;
- // Use CSD's timestamp as the start time. Encoder should send CSD frame first
- // and then data frames.
- mMediaStartTime = aFrame->GetTimeStamp();
- mFragmentNumber = 1;
- return NS_OK;
- }
-
- // if the timestamp is incorrect, abort it.
- if (aFrame->GetTimeStamp() < mMediaStartTime) {
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
-
- mFragArray.LastElement().AppendElement(aFrame);
-
- // check if current fragment is reach the fragment duration.
- if ((aFrame->GetTimeStamp() - mMediaStartTime) >= (mFragDuration * mFragmentNumber)) {
- mFragArray.AppendElement();
- mFragmentNumber++;
- }
-
- return NS_OK;
-}
-
-nsresult
-FragmentBuffer::GetFirstFragment(nsTArray<RefPtr<EncodedFrame>>& aFragment,
- bool aFlush)
-{
- // It should be called only if there is a complete fragment in mFragArray.
- if (mFragArray.Length() <= 1 && !mEOS) {
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
-
- if (aFlush) {
- aFragment.SwapElements(mFragArray.ElementAt(0));
- mFragArray.RemoveElementAt(0);
- } else {
- aFragment.AppendElements(mFragArray.ElementAt(0));
- }
- return NS_OK;
-}
-
-uint32_t
-FragmentBuffer::GetFirstFragmentSampleNumber()
-{
- return mFragArray.ElementAt(0).Length();
-}
-
-uint32_t
-FragmentBuffer::GetFirstFragmentSampleSize()
-{
- uint32_t size = 0;
- uint32_t len = mFragArray.ElementAt(0).Length();
- for (uint32_t i = 0; i < len; i++) {
- size += mFragArray.ElementAt(0).ElementAt(i)->GetFrameData().Length();
- }
- return size;
-}
-
-ISOControl::ISOControl(uint32_t aMuxingType)
- : mMuxingType(aMuxingType)
- , mAudioFragmentBuffer(nullptr)
- , mVideoFragmentBuffer(nullptr)
- , mFragNum(0)
- , mOutputSize(0)
- , mBitCount(0)
- , mBit(0)
-{
- // Create a data array for first mp4 Box, ftyp.
- mOutBuffers.SetLength(1);
- MOZ_COUNT_CTOR(ISOControl);
-}
-
-ISOControl::~ISOControl()
-{
- MOZ_COUNT_DTOR(ISOControl);
-}
-
-uint32_t
-ISOControl::GetNextTrackID()
-{
- return (mMetaArray.Length() + 1);
-}
-
-uint32_t
-ISOControl::GetTrackID(TrackMetadataBase::MetadataKind aKind)
-{
- for (uint32_t i = 0; i < mMetaArray.Length(); i++) {
- if (mMetaArray[i]->GetKind() == aKind) {
- return (i + 1);
- }
- }
-
- // Track ID shouldn't be 0. It must be something wrong here.
- MOZ_ASSERT(0);
- return 0;
-}
-
-nsresult
-ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta)
-{
- if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC ||
- aTrackMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- mMetaArray.AppendElement(aTrackMeta);
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-ISOControl::GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta)
-{
- for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
- if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC ||
- mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR ||
- mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_EVRC) {
- aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get());
- return NS_OK;
- }
- }
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-ISOControl::GetVideoMetadata(RefPtr<VideoTrackMetadata>& aVidMeta)
-{
- for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
- if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AVC) {
- aVidMeta = static_cast<VideoTrackMetadata*>(mMetaArray[i].get());
- return NS_OK;
- }
- }
- return NS_ERROR_FAILURE;
-}
-
-bool
-ISOControl::HasAudioTrack()
-{
- RefPtr<AudioTrackMetadata> audMeta;
- GetAudioMetadata(audMeta);
- return audMeta;
-}
-
-bool
-ISOControl::HasVideoTrack()
-{
- RefPtr<VideoTrackMetadata> vidMeta;
- GetVideoMetadata(vidMeta);
- return vidMeta;
-}
-
-nsresult
-ISOControl::SetFragment(FragmentBuffer* aFragment)
-{
- if (aFragment->GetType() == Audio_Track) {
- mAudioFragmentBuffer = aFragment;
- } else {
- mVideoFragmentBuffer = aFragment;
- }
- return NS_OK;
-}
-
-FragmentBuffer*
-ISOControl::GetFragment(uint32_t aType)
-{
- if (aType == Audio_Track) {
- return mAudioFragmentBuffer;
- } else if (aType == Video_Track){
- return mVideoFragmentBuffer;
- }
- MOZ_ASSERT(0);
- return nullptr;
-}
-
-nsresult
-ISOControl::GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs)
-{
- uint32_t len = mOutBuffers.Length();
- for (uint32_t i = 0; i < len; i++) {
- mOutBuffers[i].SwapElements(*aOutputBufs->AppendElement());
- }
- return FlushBuf();
-}
-
-nsresult
-ISOControl::FlushBuf()
-{
- mOutBuffers.SetLength(1);
- return NS_OK;
-}
-
-uint32_t
-ISOControl::WriteAVData(nsTArray<uint8_t>& aArray)
-{
- MOZ_ASSERT(!mBitCount);
-
- uint32_t len = aArray.Length();
- if (!len) {
- return 0;
- }
-
- mOutputSize += len;
-
- // The last element already has data, allocated a new element for pointer
- // swapping.
- if (mOutBuffers.LastElement().Length()) {
- mOutBuffers.AppendElement();
- }
- // Swap the video/audio data pointer.
- mOutBuffers.LastElement().SwapElements(aArray);
- // Following data could be boxes, so appending a new uint8_t array here.
- mOutBuffers.AppendElement();
-
- return len;
-}
-
-uint32_t
-ISOControl::WriteBits(uint64_t aBits, size_t aNumBits)
-{
- uint8_t output_byte = 0;
-
- MOZ_ASSERT(aNumBits <= 64);
- // TODO: rewritten following with bitset?
- for (size_t i = aNumBits; i > 0; i--) {
- mBit |= (((aBits >> (i - 1)) & 1) << (8 - ++mBitCount));
- if (mBitCount == 8) {
- Write(&mBit, sizeof(uint8_t));
- mBit = 0;
- mBitCount = 0;
- output_byte++;
- }
- }
- return output_byte;
-}
-
-uint32_t
-ISOControl::Write(uint8_t* aBuf, uint32_t aSize)
-{
- mOutBuffers.LastElement().AppendElements(aBuf, aSize);
- mOutputSize += aSize;
- return aSize;
-}
-
-uint32_t
-ISOControl::Write(uint8_t aData)
-{
- MOZ_ASSERT(!mBitCount);
- Write((uint8_t*)&aData, sizeof(uint8_t));
- return sizeof(uint8_t);
-}
-
-uint32_t
-ISOControl::GetBufPos()
-{
- uint32_t len = mOutBuffers.Length();
- uint32_t pos = 0;
- for (uint32_t i = 0; i < len; i++) {
- pos += mOutBuffers.ElementAt(i).Length();
- }
- return pos;
-}
-
-uint32_t
-ISOControl::WriteFourCC(const char* aType)
-{
- // Bit operation should be aligned to byte before writing any byte data.
- MOZ_ASSERT(!mBitCount);
-
- uint32_t size = strlen(aType);
- if (size == 4) {
- return Write((uint8_t*)aType, size);
- }
-
- return 0;
-}
-
-nsresult
-ISOControl::GenerateFtyp()
-{
- nsresult rv;
- uint32_t size;
- nsAutoPtr<FileTypeBox> type_box(new FileTypeBox(this));
- rv = type_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = type_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-ISOControl::GenerateMoov()
-{
- nsresult rv;
- uint32_t size;
- nsAutoPtr<MovieBox> moov_box(new MovieBox(this));
- rv = moov_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = moov_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-ISOControl::GenerateMoof(uint32_t aTrackType)
-{
- mFragNum++;
-
- nsresult rv;
- uint32_t size;
- uint64_t first_sample_offset = mOutputSize;
- nsAutoPtr<MovieFragmentBox> moof_box(new MovieFragmentBox(aTrackType, this));
- nsAutoPtr<MediaDataBox> mdat_box(new MediaDataBox(aTrackType, this));
-
- rv = moof_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- first_sample_offset += size;
- rv = mdat_box->Generate(&size);
- NS_ENSURE_SUCCESS(rv, rv);
- first_sample_offset += mdat_box->FirstSampleOffsetInMediaDataBox();
-
- // correct offset info
- nsTArray<RefPtr<MuxerOperation>> tfhds;
- rv = moof_box->Find(NS_LITERAL_CSTRING("tfhd"), tfhds);
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t len = tfhds.Length();
- for (uint32_t i = 0; i < len; i++) {
- TrackFragmentHeaderBox* tfhd = (TrackFragmentHeaderBox*) tfhds.ElementAt(i).get();
- rv = tfhd->UpdateBaseDataOffset(first_sample_offset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = moof_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mdat_box->Write();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-uint32_t
-ISOControl::GetTime()
-{
- return (uint64_t)time(nullptr) + iso_time_offset;
-}
-
-}