tor-browser

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

VideoSegment.h (7016B)


      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/. */
      5 
      6 #ifndef MOZILLA_VIDEOSEGMENT_H_
      7 #define MOZILLA_VIDEOSEGMENT_H_
      8 
      9 #include "ImageContainer.h"
     10 #include "MediaSegment.h"
     11 #include "TimeUnits.h"
     12 #include "gfxPoint.h"
     13 #include "nsCOMPtr.h"
     14 
     15 namespace mozilla {
     16 
     17 namespace layers {
     18 class Image;
     19 }  // namespace layers
     20 
     21 class VideoFrame {
     22 public:
     23  typedef mozilla::layers::Image Image;
     24 
     25  VideoFrame(already_AddRefed<Image> aImage,
     26             const gfx::IntSize& aIntrinsicSize);
     27  VideoFrame();
     28  ~VideoFrame();
     29 
     30  bool operator==(const VideoFrame& aFrame) const {
     31    return mIntrinsicSize == aFrame.mIntrinsicSize &&
     32           mForceBlack == aFrame.mForceBlack &&
     33           ((mForceBlack && aFrame.mForceBlack) || mImage == aFrame.mImage) &&
     34           mPrincipalHandle == aFrame.mPrincipalHandle;
     35  }
     36  bool operator!=(const VideoFrame& aFrame) const {
     37    return !operator==(aFrame);
     38  }
     39 
     40  Image* GetImage() const { return mImage; }
     41  void SetForceBlack(bool aForceBlack) { mForceBlack = aForceBlack; }
     42  bool GetForceBlack() const { return mForceBlack; }
     43  void SetPrincipalHandle(PrincipalHandle aPrincipalHandle) {
     44    mPrincipalHandle = std::forward<PrincipalHandle>(aPrincipalHandle);
     45  }
     46  const PrincipalHandle& GetPrincipalHandle() const { return mPrincipalHandle; }
     47  const gfx::IntSize& GetIntrinsicSize() const { return mIntrinsicSize; }
     48  void SetNull();
     49  void TakeFrom(VideoFrame* aFrame);
     50 
     51  // Create a planar YCbCr black image.
     52  static already_AddRefed<Image> CreateBlackImage(const gfx::IntSize& aSize);
     53 
     54 protected:
     55  // mImage can be null to indicate "no video" (aka "empty frame"). It can
     56  // still have an intrinsic size in this case.
     57  RefPtr<Image> mImage;
     58  // The desired size to render the video frame at.
     59  gfx::IntSize mIntrinsicSize;
     60  bool mForceBlack;
     61  // principalHandle for the image in this frame.
     62  // This can be compared to an nsIPrincipal when back on main thread.
     63  PrincipalHandle mPrincipalHandle;
     64 };
     65 
     66 struct VideoChunk {
     67  void SliceTo(TrackTime aStart, TrackTime aEnd) {
     68    NS_ASSERTION(aStart >= 0 && aStart < aEnd && aEnd <= mDuration,
     69                 "Slice out of bounds");
     70    mDuration = aEnd - aStart;
     71  }
     72  TrackTime GetDuration() const { return mDuration; }
     73  bool CanCombineWithFollowing(const VideoChunk& aOther) const {
     74    return aOther.mFrame == mFrame;
     75  }
     76  bool IsNull() const { return !mFrame.GetImage(); }
     77  void SetNull(TrackTime aDuration) {
     78    mDuration = aDuration;
     79    mFrame.SetNull();
     80    mTimeStamp = TimeStamp();
     81  }
     82  void SetForceBlack(bool aForceBlack) { mFrame.SetForceBlack(aForceBlack); }
     83 
     84  size_t SizeOfExcludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const {
     85    // Future:
     86    // - mFrame
     87    return 0;
     88  }
     89 
     90  const PrincipalHandle& GetPrincipalHandle() const {
     91    return mFrame.GetPrincipalHandle();
     92  }
     93 
     94  TrackTime mDuration;
     95  VideoFrame mFrame;
     96  TimeStamp mTimeStamp;
     97  media::TimeUnit mProcessingDuration;
     98  media::TimeUnit mMediaTime;
     99  layers::ContainerCaptureTime mWebrtcCaptureTime = AsVariant(Nothing());
    100  layers::ContainerReceiveTime mWebrtcReceiveTime;
    101  layers::ContainerRtpTimestamp mRtpTimestamp;
    102 };
    103 
    104 class VideoSegment : public MediaSegmentBase<VideoSegment, VideoChunk> {
    105 public:
    106  typedef mozilla::layers::Image Image;
    107  typedef mozilla::gfx::IntSize IntSize;
    108 
    109  VideoSegment();
    110  VideoSegment(VideoSegment&& aSegment);
    111 
    112  VideoSegment(const VideoSegment&) = delete;
    113  VideoSegment& operator=(const VideoSegment&) = delete;
    114 
    115  ~VideoSegment();
    116 
    117  void AppendFrame(const VideoChunk& aChunk,
    118                   const Maybe<bool>& aForceBlack = Nothing(),
    119                   const Maybe<TimeStamp>& aTimeStamp = Nothing());
    120  void AppendFrame(
    121      already_AddRefed<Image>&& aImage, const IntSize& aIntrinsicSize,
    122      const PrincipalHandle& aPrincipalHandle, bool aForceBlack = false,
    123      TimeStamp aTimeStamp = TimeStamp::Now(),
    124      media::TimeUnit aProcessingDuration = media::TimeUnit::Invalid(),
    125      media::TimeUnit aMediaTime = media::TimeUnit::Invalid());
    126  void AppendWebrtcRemoteFrame(already_AddRefed<Image>&& aImage,
    127                               const IntSize& aIntrinsicSize,
    128                               const PrincipalHandle& aPrincipalHandle,
    129                               bool aForceBlack, TimeStamp aTimeStamp,
    130                               media::TimeUnit aProcessingDuration,
    131                               uint32_t aRtpTimestamp,
    132                               int64_t aWebrtcCaptureTimeNtp,
    133                               int64_t aWebrtcReceiveTimeUs);
    134  void AppendWebrtcLocalFrame(already_AddRefed<Image>&& aImage,
    135                              const IntSize& aIntrinsicSize,
    136                              const PrincipalHandle& aPrincipalHandle,
    137                              bool aForceBlack, TimeStamp aTimeStamp,
    138                              TimeStamp aWebrtcCaptureTime);
    139  void ExtendLastFrameBy(TrackTime aDuration) {
    140    if (aDuration <= 0) {
    141      return;
    142    }
    143    if (mChunks.IsEmpty()) {
    144      mChunks.AppendElement()->SetNull(aDuration);
    145    } else {
    146      mChunks[mChunks.Length() - 1].mDuration += aDuration;
    147    }
    148    mDuration += aDuration;
    149  }
    150  const VideoFrame* GetLastFrame(TrackTime* aStart = nullptr) {
    151    VideoChunk* c = GetLastChunk();
    152    if (!c) {
    153      return nullptr;
    154    }
    155    if (aStart) {
    156      *aStart = mDuration - c->mDuration;
    157    }
    158    return &c->mFrame;
    159  }
    160  VideoChunk* FindChunkContaining(const TimeStamp& aTime) {
    161    VideoChunk* previousChunk = nullptr;
    162    for (VideoChunk& c : mChunks) {
    163      if (c.mTimeStamp.IsNull()) {
    164        continue;
    165      }
    166      if (c.mTimeStamp > aTime) {
    167        return previousChunk;
    168      }
    169      previousChunk = &c;
    170    }
    171    return previousChunk;
    172  }
    173  void ForgetUpToTime(const TimeStamp& aTime) {
    174    VideoChunk* chunk = FindChunkContaining(aTime);
    175    if (!chunk) {
    176      return;
    177    }
    178    TrackTime duration = 0;
    179    size_t chunksToRemove = 0;
    180    for (const VideoChunk& c : mChunks) {
    181      if (c.mTimeStamp >= chunk->mTimeStamp) {
    182        break;
    183      }
    184      duration += c.GetDuration();
    185      ++chunksToRemove;
    186    }
    187    mChunks.RemoveElementsAt(0, chunksToRemove);
    188    mDuration -= duration;
    189    MOZ_ASSERT(mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
    190               "Capacity must be retained after removing chunks");
    191  }
    192  // Override default impl
    193  void ReplaceWithDisabled() override {
    194    for (ChunkIterator i(*this); !i.IsEnded(); i.Next()) {
    195      VideoChunk& chunk = *i;
    196      chunk.SetForceBlack(true);
    197    }
    198  }
    199 
    200  // Segment-generic methods not in MediaSegmentBase
    201  static Type StaticType() { return VIDEO; }
    202 
    203  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override {
    204    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
    205  }
    206 };
    207 
    208 }  // namespace mozilla
    209 
    210 #endif /* MOZILLA_VIDEOSEGMENT_H_ */