content/media/encoder/fmp4_muxer/ISOControl.h

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 #ifndef ISOCOMPOSITOR_H_
     7 #define ISOCOMPOSITOR_H_
     9 #include "mozilla/Endian.h"
    10 #include "nsTArray.h"
    11 #include "ISOTrackMetadata.h"
    12 #include "EncodedFrameContainer.h"
    14 namespace mozilla {
    16 class Box;
    17 class ISOControl;
    19 /**
    20  * This class collects elementary stream data to form a fragment.
    21  * ISOMediaWriter will check if the data is enough; if yes, the corresponding
    22  * moof will be created and write to ISOControl.
    23  * Each audio and video has its own fragment and only one during the whole
    24  * life cycle, when a fragment is formed in ISOControl, Flush() needs to
    25  * be called to reset it.
    26  */
    27 class FragmentBuffer {
    28 public:
    29   // aTrackType: it could be Audio_Track or Video_Track.
    30   // aFragDuration: it is the fragment duration. (microsecond per unit)
    31   //                Audio and video have the same fragment duration.
    32   FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration);
    33   ~FragmentBuffer();
    35   // Get samples of first fragment, that will swap all the elements in the
    36   // mFragArray[0] when aFlush = true, and caller is responsible for drop
    37   // EncodedFrame reference count.
    38   nsresult GetFirstFragment(nsTArray<nsRefPtr<EncodedFrame>>& aFragment,
    39                             bool aFlush = false);
    41   // Add sample frame to the last element fragment of mFragArray. If sample
    42   // number is enough, it will append a new fragment element. And the new
    43   // sample will be added to the new fragment element of mFragArray.
    44   nsresult AddFrame(EncodedFrame* aFrame);
    46   // Get total sample size of first complete fragment size.
    47   uint32_t GetFirstFragmentSampleSize();
    49   // Get sample number of first complete fragment.
    50   uint32_t GetFirstFragmentSampleNumber();
    52   // Check if it accumulates enough frame data.
    53   // It returns true when data is enough to form a fragment.
    54   bool HasEnoughData();
    56   // Called by ISOMediaWriter when TrackEncoder has sent the last frame. The
    57   // remains frame data will form the last moof and move the state machine to
    58   // in ISOMediaWriter to last phrase.
    59   nsresult SetEndOfStream() {
    60     mEOS = true;
    61     return  NS_OK;
    62   }
    63   bool EOS() { return mEOS; }
    65   // CSD (codec specific data), it is generated by encoder and the data depends
    66   // on codec type. This data will be sent as a special frame from encoder to
    67   // ISOMediaWriter and pass to this class via AddFrame().
    68   nsresult GetCSD(nsTArray<uint8_t>& aCSD);
    70   bool HasCSD() { return mCSDFrame; }
    72   uint32_t GetType() { return mTrackType; }
    74   void SetLastFragmentLastFrameTime(uint32_t aTime) {
    75     mLastFrameTimeOfLastFragment = aTime;
    76   }
    78   uint32_t GetLastFragmentLastFrameTime() {
    79     return mLastFrameTimeOfLastFragment;
    80   }
    82 private:
    83   uint32_t mTrackType;
    85   // Fragment duration, microsecond per unit.
    86   uint32_t mFragDuration;
    88   // Media start time, microsecond per unit.
    89   // Together with mFragDuration, mFragmentNumber and EncodedFrame->GetTimeStamp(),
    90   // when the difference between current frame time and mMediaStartTime is
    91   // exceeded current fragment ceiling timeframe, that means current fragment has
    92   // enough data and a new element in mFragArray will be added.
    93   uint64_t mMediaStartTime;
    95   // Current fragment number. It will be increase when a new element of
    96   // mFragArray is created.
    97   // Note:
    98   //   It only means the fragment number of current accumulated frames, not
    99   //   the current 'creating' fragment mFragNum in ISOControl.
   100   uint32_t mFragmentNumber;
   102   // The last frame time stamp of last fragment. It is for calculating the
   103   // play duration of first frame in current fragment. The frame duration is
   104   // defined as "current frame timestamp - last frame timestamp" here. So it
   105   // needs to keep the last timestamp of last fragment.
   106   uint32_t mLastFrameTimeOfLastFragment;
   108   // Array of fragments, each element has enough samples to form a
   109   // complete fragment.
   110   nsTArray<nsTArray<nsRefPtr<EncodedFrame>>> mFragArray;
   112   // Codec specific data frame, it will be generated by encoder and send to
   113   // ISOMediaWriter through WriteEncodedTrack(). The data will be vary depends
   114   // on codec type.
   115   nsRefPtr<EncodedFrame> mCSDFrame;
   117   // END_OF_STREAM from ContainerWriter
   118   bool mEOS;
   119 };
   121 /**
   122  * ISOControl will be carried to each box when box is created. It is the main
   123  * bridge for box to output stream to ContainerWriter and retrieve information.
   124  * ISOControl acts 3 different roles:
   125  * 1. Holds the pointer of audio metadata, video metadata, fragment and
   126  *    pass them to boxes.
   127  * 2. Provide the functions to generate the base structure of MP4; they are
   128  *    GenerateFtyp, GenerateMoov, GenerateMoof, and GenerateMfra.
   129  * 3. The actually writer used by MuxOperation::Write() in each box. It provides
   130  *    writing methods for different kind of data; they are Write, WriteArray,
   131  *    WriteBits...etc.
   132  */
   133 class ISOControl {
   135 friend class Box;
   137 public:
   138   ISOControl(uint32_t aMuxingType);
   139   ~ISOControl();
   141   nsresult GenerateFtyp();
   142   nsresult GenerateMoov();
   143   nsresult GenerateMoof(uint32_t aTrackType);
   145   // Swap elementary stream pointer to output buffers.
   146   uint32_t WriteAVData(nsTArray<uint8_t>& aArray);
   148   uint32_t Write(uint8_t* aBuf, uint32_t aSize);
   150   uint32_t Write(uint8_t aData);
   152   template <typename T>
   153   uint32_t Write(T aData) {
   154     MOZ_ASSERT(!mBitCount);
   156     aData = NativeEndian::swapToNetworkOrder(aData);
   157     Write((uint8_t*)&aData, sizeof(T));
   158     return sizeof(T);
   159   }
   161   template <typename T>
   162   uint32_t WriteArray(const T &aArray, uint32_t aSize) {
   163     MOZ_ASSERT(!mBitCount);
   165     uint32_t size = 0;
   166     for (uint32_t i = 0; i < aSize; i++) {
   167       size += Write(aArray[i]);
   168     }
   169     return size;
   170   }
   172   uint32_t WriteFourCC(const char* aType);
   174   // Bit writing. Note: it needs to be byte-boundary before using
   175   // others non-bit writing function.
   176   uint32_t WriteBits(uint64_t aBits, size_t aNumBits);
   178   // This is called by GetContainerData and swap all the buffers to aOutputBuffers.
   179   nsresult GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs);
   181   // Presentation time in seconds since midnight, Jan. 1, 1904, in UTC time.
   182   uint32_t GetTime();
   184   // current fragment number
   185   uint32_t GetCurFragmentNumber() { return mFragNum; }
   187   nsresult SetFragment(FragmentBuffer* aFragment);
   188   FragmentBuffer* GetFragment(uint32_t aType);
   190   uint32_t GetMuxingType() { return mMuxingType; }
   192   nsresult SetMetadata(TrackMetadataBase* aTrackMeta);
   193   nsresult GetAudioMetadata(nsRefPtr<AudioTrackMetadata>& aAudMeta);
   194   nsresult GetVideoMetadata(nsRefPtr<VideoTrackMetadata>& aVidMeta);
   196   // Track ID is the Metadata index in mMetaArray. It allows only 1 audio
   197   // track and 1 video track in this muxer. In this muxer, it is prohibt to have
   198   // mutiple audio track or video track in the same file.
   199   uint32_t GetTrackID(TrackMetadataBase::MetadataKind aKind);
   200   uint32_t GetNextTrackID();
   202   bool HasAudioTrack();
   203   bool HasVideoTrack();
   205 private:
   206   uint32_t GetBufPos();
   207   nsresult FlushBuf();
   209   // One of value in TYPE_XXX, defined in ISOMediaWriter.
   210   uint32_t mMuxingType;
   212   // Audio and video fragments are owned by ISOMediaWriter.
   213   // They don't need to worry about pointer going stale because ISOMediaWriter's
   214   // lifetime is longer than ISOControl.
   215   FragmentBuffer* mAudioFragmentBuffer;
   216   FragmentBuffer* mVideoFragmentBuffer;
   218   // Generated fragment number
   219   uint32_t mFragNum;
   221   // The (index + 1) will be the track ID.
   222   nsTArray<nsRefPtr<TrackMetadataBase>> mMetaArray;
   224   // Array of output buffers.
   225   // To save memory usage, audio/video sample will be swapped into a new element
   226   // of this array.
   227   //
   228   // For example,
   229   //   mOutBuffers[0] --> boxes (allocated by muxer)
   230   //   mOutBuffers[1] --> video raw data (allocated by encoder)
   231   //   mOutBuffers[2] --> video raw data (allocated by encoder)
   232   //   mOutBuffers[3] --> video raw data (allocated by encoder)
   233   //   mOutBuffers[4] --> boxes (allocated by muxer)
   234   //   mOutBuffers[5] --> audio raw data (allocated by encoder)
   235   //   ...etc.
   236   //
   237   nsTArray<nsTArray<uint8_t>> mOutBuffers;
   239   // Accumulate output size from Write().
   240   uint64_t mOutputSize;
   242   // Bit writing operation. Note: the mBitCount should be 0 before any
   243   // byte-boundary writing method be called (Write(uint32_t), Write(uint16_t)...etc);
   244   // otherwise, there will be assertion on these functions.
   245   uint8_t mBitCount;
   246   uint8_t mBit;
   247 };
   249 }
   250 #endif

mercurial