Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / media / VideoSegment.h
blob5421112c9f59252608fb123d8d16077583229ca1
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 MOZILLA_VIDEOSEGMENT_H_
7 #define MOZILLA_VIDEOSEGMENT_H_
9 #include "MediaSegment.h"
10 #include "nsCOMPtr.h"
11 #include "gfxPoint.h"
12 #include "ImageContainer.h"
14 namespace mozilla {
16 namespace layers {
17 class Image;
18 } // namespace layers
20 class VideoFrame {
21 public:
22 typedef mozilla::layers::Image Image;
24 VideoFrame(already_AddRefed<Image> aImage,
25 const gfx::IntSize& aIntrinsicSize);
26 VideoFrame();
27 ~VideoFrame();
29 bool operator==(const VideoFrame& aFrame) const {
30 return mIntrinsicSize == aFrame.mIntrinsicSize &&
31 mForceBlack == aFrame.mForceBlack &&
32 ((mForceBlack && aFrame.mForceBlack) || mImage == aFrame.mImage) &&
33 mPrincipalHandle == aFrame.mPrincipalHandle;
35 bool operator!=(const VideoFrame& aFrame) const {
36 return !operator==(aFrame);
39 Image* GetImage() const { return mImage; }
40 void SetForceBlack(bool aForceBlack) { mForceBlack = aForceBlack; }
41 bool GetForceBlack() const { return mForceBlack; }
42 void SetPrincipalHandle(PrincipalHandle aPrincipalHandle) {
43 mPrincipalHandle = std::forward<PrincipalHandle>(aPrincipalHandle);
45 const PrincipalHandle& GetPrincipalHandle() const { return mPrincipalHandle; }
46 const gfx::IntSize& GetIntrinsicSize() const { return mIntrinsicSize; }
47 void SetNull();
48 void TakeFrom(VideoFrame* aFrame);
50 // Create a planar YCbCr black image.
51 static already_AddRefed<Image> CreateBlackImage(const gfx::IntSize& aSize);
53 protected:
54 // mImage can be null to indicate "no video" (aka "empty frame"). It can
55 // still have an intrinsic size in this case.
56 RefPtr<Image> mImage;
57 // The desired size to render the video frame at.
58 gfx::IntSize mIntrinsicSize;
59 bool mForceBlack;
60 // principalHandle for the image in this frame.
61 // This can be compared to an nsIPrincipal when back on main thread.
62 PrincipalHandle mPrincipalHandle;
65 struct VideoChunk {
66 void SliceTo(TrackTime aStart, TrackTime aEnd) {
67 NS_ASSERTION(aStart >= 0 && aStart < aEnd && aEnd <= mDuration,
68 "Slice out of bounds");
69 mDuration = aEnd - aStart;
71 TrackTime GetDuration() const { return mDuration; }
72 bool CanCombineWithFollowing(const VideoChunk& aOther) const {
73 return aOther.mFrame == mFrame;
75 bool IsNull() const { return !mFrame.GetImage(); }
76 void SetNull(TrackTime aDuration) {
77 mDuration = aDuration;
78 mFrame.SetNull();
79 mTimeStamp = TimeStamp();
81 void SetForceBlack(bool aForceBlack) { mFrame.SetForceBlack(aForceBlack); }
83 size_t SizeOfExcludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const {
84 // Future:
85 // - mFrame
86 return 0;
89 const PrincipalHandle& GetPrincipalHandle() const {
90 return mFrame.GetPrincipalHandle();
93 TrackTime mDuration;
94 VideoFrame mFrame;
95 TimeStamp mTimeStamp;
98 class VideoSegment : public MediaSegmentBase<VideoSegment, VideoChunk> {
99 public:
100 typedef mozilla::layers::Image Image;
101 typedef mozilla::gfx::IntSize IntSize;
103 VideoSegment();
104 VideoSegment(VideoSegment&& aSegment);
106 VideoSegment(const VideoSegment&) = delete;
107 VideoSegment& operator=(const VideoSegment&) = delete;
109 ~VideoSegment();
111 void AppendFrame(already_AddRefed<Image>&& aImage,
112 const IntSize& aIntrinsicSize,
113 const PrincipalHandle& aPrincipalHandle,
114 bool aForceBlack = false,
115 TimeStamp aTimeStamp = TimeStamp::Now());
116 void ExtendLastFrameBy(TrackTime aDuration) {
117 if (aDuration <= 0) {
118 return;
120 if (mChunks.IsEmpty()) {
121 mChunks.AppendElement()->SetNull(aDuration);
122 } else {
123 mChunks[mChunks.Length() - 1].mDuration += aDuration;
125 mDuration += aDuration;
127 const VideoFrame* GetLastFrame(TrackTime* aStart = nullptr) {
128 VideoChunk* c = GetLastChunk();
129 if (!c) {
130 return nullptr;
132 if (aStart) {
133 *aStart = mDuration - c->mDuration;
135 return &c->mFrame;
137 VideoChunk* FindChunkContaining(const TimeStamp& aTime) {
138 VideoChunk* previousChunk = nullptr;
139 for (VideoChunk& c : mChunks) {
140 if (c.mTimeStamp.IsNull()) {
141 continue;
143 if (c.mTimeStamp > aTime) {
144 return previousChunk;
146 previousChunk = &c;
148 return previousChunk;
150 void ForgetUpToTime(const TimeStamp& aTime) {
151 VideoChunk* chunk = FindChunkContaining(aTime);
152 if (!chunk) {
153 return;
155 TrackTime duration = 0;
156 size_t chunksToRemove = 0;
157 for (const VideoChunk& c : mChunks) {
158 if (c.mTimeStamp >= chunk->mTimeStamp) {
159 break;
161 duration += c.GetDuration();
162 ++chunksToRemove;
164 mChunks.RemoveElementsAt(0, chunksToRemove);
165 mDuration -= duration;
166 MOZ_ASSERT(mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
167 "Capacity must be retained after removing chunks");
169 // Override default impl
170 void ReplaceWithDisabled() override {
171 for (ChunkIterator i(*this); !i.IsEnded(); i.Next()) {
172 VideoChunk& chunk = *i;
173 chunk.SetForceBlack(true);
177 // Segment-generic methods not in MediaSegmentBase
178 static Type StaticType() { return VIDEO; }
180 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override {
181 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
185 } // namespace mozilla
187 #endif /* MOZILLA_VIDEOSEGMENT_H_ */