tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebMDemuxer.h (9942B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #ifndef WebMDemuxer_h_
      7 #define WebMDemuxer_h_
      8 
      9 #include <stdint.h>
     10 
     11 #include <deque>
     12 #include <utility>
     13 
     14 #include "MediaDataDemuxer.h"
     15 #include "MediaResource.h"
     16 #include "NesteggPacketHolder.h"
     17 #include "nsTArray.h"
     18 
     19 typedef struct nestegg nestegg;
     20 
     21 namespace mozilla {
     22 
     23 class WebMBufferedState;
     24 
     25 // Queue for holding MediaRawData samples
     26 class MediaRawDataQueue {
     27  typedef std::deque<RefPtr<MediaRawData>> ContainerType;
     28 
     29 public:
     30  uint32_t GetSize() { return mQueue.size(); }
     31 
     32  void Push(MediaRawData* aItem) { mQueue.push_back(aItem); }
     33 
     34  void Push(already_AddRefed<MediaRawData>&& aItem) {
     35    mQueue.push_back(std::move(aItem));
     36  }
     37 
     38  void PushFront(MediaRawData* aItem) { mQueue.push_front(aItem); }
     39 
     40  void PushFront(already_AddRefed<MediaRawData>&& aItem) {
     41    mQueue.push_front(std::move(aItem));
     42  }
     43 
     44  void PushFront(MediaRawDataQueue&& aOther) {
     45    while (!aOther.mQueue.empty()) {
     46      PushFront(aOther.Pop());
     47    }
     48  }
     49 
     50  already_AddRefed<MediaRawData> PopFront() {
     51    RefPtr<MediaRawData> result = std::move(mQueue.front());
     52    mQueue.pop_front();
     53    return result.forget();
     54  }
     55 
     56  already_AddRefed<MediaRawData> Pop() {
     57    RefPtr<MediaRawData> result = std::move(mQueue.back());
     58    mQueue.pop_back();
     59    return result.forget();
     60  }
     61 
     62  void Reset() {
     63    while (!mQueue.empty()) {
     64      mQueue.pop_front();
     65    }
     66  }
     67 
     68  MediaRawDataQueue& operator=(const MediaRawDataQueue& aOther) = delete;
     69 
     70  const RefPtr<MediaRawData>& First() const { return mQueue.front(); }
     71 
     72  const RefPtr<MediaRawData>& Last() const { return mQueue.back(); }
     73 
     74  // Methods for range-based for loops.
     75  ContainerType::iterator begin() { return mQueue.begin(); }
     76 
     77  ContainerType::const_iterator begin() const { return mQueue.begin(); }
     78 
     79  ContainerType::iterator end() { return mQueue.end(); }
     80 
     81  ContainerType::const_iterator end() const { return mQueue.end(); }
     82 
     83 private:
     84  ContainerType mQueue;
     85 };
     86 
     87 class WebMTrackDemuxer;
     88 
     89 DDLoggedTypeDeclNameAndBase(WebMDemuxer, MediaDataDemuxer);
     90 DDLoggedTypeNameAndBase(WebMTrackDemuxer, MediaTrackDemuxer);
     91 
     92 class WebMDemuxer : public MediaDataDemuxer,
     93                    public DecoderDoctorLifeLogger<WebMDemuxer> {
     94 public:
     95  explicit WebMDemuxer(MediaResource* aResource);
     96  // Indicate if the WebMDemuxer is to be used with MediaSource. In which
     97  // case the demuxer will stop reads to the last known complete block.
     98  WebMDemuxer(
     99      MediaResource* aResource, bool aIsMediaSource,
    100      Maybe<media::TimeUnit> aFrameEndTimeBeforeRecreateDemuxer = Nothing());
    101 
    102  RefPtr<InitPromise> Init() override;
    103 
    104  uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
    105 
    106  UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType,
    107                                    size_t aTrackNumber) const;
    108 
    109  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
    110      TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
    111 
    112  bool IsSeekable() const override;
    113 
    114  bool IsSeekableOnlyInBufferedRanges() const override;
    115 
    116  UniquePtr<EncryptionInfo> GetCrypto() override;
    117 
    118  bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
    119 
    120  // Demux next WebM packet and append samples to MediaRawDataQueue
    121  nsresult GetNextPacket(TrackInfo::TrackType aType,
    122                         MediaRawDataQueue* aSamples);
    123 
    124  void Reset(TrackInfo::TrackType aType);
    125 
    126  // Pushes a packet to the front of the audio packet queue.
    127  void PushAudioPacket(NesteggPacketHolder* aItem);
    128 
    129  // Pushes a packet to the front of the video packet queue.
    130  void PushVideoPacket(NesteggPacketHolder* aItem);
    131 
    132  // Public accessor for nestegg callbacks
    133  bool IsMediaSource() const { return mIsMediaSource; }
    134 
    135  struct NestEggContext {
    136    NestEggContext(WebMDemuxer* aParent, MediaResource* aResource)
    137        : mParent(aParent), mResource(aResource), mContext(nullptr) {}
    138 
    139    ~NestEggContext();
    140 
    141    int Init();
    142 
    143    // Public accessor for nestegg callbacks
    144 
    145    bool IsMediaSource() const { return mParent->IsMediaSource(); }
    146    MediaResourceIndex* GetResource() { return &mResource; }
    147 
    148    WebMDemuxer* mParent;
    149    MediaResourceIndex mResource;
    150    nestegg* mContext;
    151    nsresult mLastIORV = NS_OK;
    152  };
    153 
    154 protected:
    155  virtual nsresult SetVideoCodecInfo(nestegg* aContext, int aTrackId);
    156  virtual nsresult SetAudioCodecInfo(nestegg* aContext, int aTrackId,
    157                                     const nestegg_audio_params& aParams);
    158  virtual nsresult GetCodecPrivateData(nestegg* aContext, int aTrackId,
    159                                       nsTArray<const unsigned char*>* aHeaders,
    160                                       nsTArray<size_t>* aHeaderLens);
    161 
    162  virtual bool CheckKeyFrameByExamineByteStream(const MediaRawData* aSample);
    163 
    164  virtual ~WebMDemuxer();
    165 
    166  friend class WebMTrackDemuxer;
    167 
    168  void InitBufferedState();
    169  int64_t FloorDefaultDurationToTimecodeScale(nestegg* aContext,
    170                                              unsigned aTrackNumber);
    171  nsresult ReadMetadata();
    172  void NotifyDataArrived() override;
    173  void NotifyDataRemoved() override;
    174  void EnsureUpToDateIndex();
    175 
    176  // A helper to catch bad intervals during `GetBuffered`.
    177  // Verifies if the interval given by start and end is valid, returning true if
    178  // it is, or false if not. Logs failure reason if the interval is invalid.
    179  bool IsBufferedIntervalValid(uint64_t start, uint64_t end);
    180 
    181  media::TimeIntervals GetBuffered();
    182  nsresult SeekInternal(TrackInfo::TrackType aType,
    183                        const media::TimeUnit& aTarget);
    184  CryptoTrack GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber);
    185 
    186  // Read a packet from the nestegg file.
    187  // Returns NS_ERROR_DOM_MEDIA_END_OF_STREAM if all packets for the
    188  // particular track have been read. Pass TrackInfo::kVideoTrack or
    189  // TrackInfo::kVideoTrack to indicate the type of the packet to read.
    190  Result<RefPtr<NesteggPacketHolder>, nsresult> NextPacket(
    191      TrackInfo::TrackType aType);
    192 
    193  // Internal method that demuxes the next packet from the stream. The caller
    194  // is responsible for making sure it doesn't get lost.
    195  Result<RefPtr<NesteggPacketHolder>, nsresult> DemuxPacket(
    196      TrackInfo::TrackType aType);
    197 
    198  // libnestegg audio and video context for webm container.
    199  // Access on reader's thread only.
    200  NestEggContext mVideoContext;
    201  NestEggContext mAudioContext;
    202  MediaResourceIndex& Resource(TrackInfo::TrackType aType) {
    203    return aType == TrackInfo::kVideoTrack ? mVideoContext.mResource
    204                                           : mAudioContext.mResource;
    205  }
    206  const NestEggContext& CallbackContext(TrackInfo::TrackType aType) const {
    207    return aType == TrackInfo::kVideoTrack ? mVideoContext : mAudioContext;
    208  }
    209  nestegg* Context(TrackInfo::TrackType aType) const {
    210    return CallbackContext(aType).mContext;
    211  }
    212 
    213  MediaInfo mInfo;
    214  nsTArray<RefPtr<WebMTrackDemuxer>> mDemuxers;
    215 
    216  // Parser state and computed offset-time mappings.  Shared by multiple
    217  // readers when decoder has been cloned.  Main thread only.
    218  RefPtr<WebMBufferedState> mBufferedState;
    219  RefPtr<MediaByteBuffer> mInitData;
    220 
    221  // Queue of video and audio packets that have been read but not decoded.
    222  WebMPacketQueue mVideoPackets;
    223  WebMPacketQueue mAudioPackets;
    224 
    225  // Index of video and audio track to play
    226  uint32_t mVideoTrack;
    227  uint32_t mAudioTrack;
    228 
    229  // Nanoseconds to discard after seeking.
    230  uint64_t mSeekPreroll;
    231 
    232  // Calculate the frame duration from the last decodeable frame using the
    233  // previous frame's timestamp.  In microseconds.
    234  Maybe<int64_t> mLastAudioFrameTime;
    235  Maybe<int64_t> mLastVideoFrameTime;
    236 
    237  Maybe<media::TimeUnit> mVideoFrameEndTimeBeforeReset;
    238 
    239  // Codec ID of audio track
    240  int mAudioCodec;
    241  // Codec ID of video track
    242  int mVideoCodec;
    243  // Default durations of blocks for each track, in microseconds
    244  int64_t mAudioDefaultDuration;
    245  int64_t mVideoDefaultDuration;
    246 
    247  // Booleans to indicate if we have audio and/or video data
    248  bool mHasVideo;
    249  bool mHasAudio;
    250  bool mNeedReIndex;
    251 
    252  const bool mIsMediaSource;
    253  // Discard padding in WebM cannot occur more than once. This is set to true if
    254  // a discard padding element has been found and processed, and the decoding is
    255  // expected to error out if another discard padding element is found
    256  // subsequently in the byte stream.
    257  bool mProcessedDiscardPadding = false;
    258 
    259  EncryptionInfo mCrypto;
    260 };
    261 
    262 class WebMTrackDemuxer : public MediaTrackDemuxer,
    263                         public DecoderDoctorLifeLogger<WebMTrackDemuxer> {
    264 public:
    265  WebMTrackDemuxer(WebMDemuxer* aParent, TrackInfo::TrackType aType,
    266                   uint32_t aTrackNumber);
    267 
    268  UniquePtr<TrackInfo> GetInfo() const override;
    269 
    270  RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
    271 
    272  RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
    273 
    274  void Reset() override;
    275 
    276  nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
    277 
    278  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
    279      const media::TimeUnit& aTimeThreshold) override;
    280 
    281  media::TimeIntervals GetBuffered() override;
    282 
    283  int64_t GetEvictionOffset(const media::TimeUnit& aTime) override;
    284 
    285  void BreakCycles() override;
    286 
    287 private:
    288  friend class WebMDemuxer;
    289  ~WebMTrackDemuxer();
    290  void UpdateSamples(const nsTArray<RefPtr<MediaRawData>>& aSamples);
    291  void SetNextKeyFrameTime();
    292  nsresult NextSample(RefPtr<MediaRawData>& aData);
    293  RefPtr<WebMDemuxer> mParent;
    294  TrackInfo::TrackType mType;
    295  UniquePtr<TrackInfo> mInfo;
    296  Maybe<media::TimeUnit> mNextKeyframeTime;
    297  bool mNeedKeyframe;
    298 
    299  // Queued samples extracted by the demuxer, but not yet returned.
    300  MediaRawDataQueue mSamples;
    301 };
    302 
    303 }  // namespace mozilla
    304 
    305 #endif