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"
12 #include "ImageContainer.h"
22 typedef mozilla::layers::Image Image
;
24 VideoFrame(already_AddRefed
<Image
> aImage
,
25 const gfx::IntSize
& aIntrinsicSize
);
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
; }
48 void TakeFrom(VideoFrame
* aFrame
);
50 // Create a planar YCbCr black image.
51 static already_AddRefed
<Image
> CreateBlackImage(const gfx::IntSize
& aSize
);
54 // mImage can be null to indicate "no video" (aka "empty frame"). It can
55 // still have an intrinsic size in this case.
57 // The desired size to render the video frame at.
58 gfx::IntSize mIntrinsicSize
;
60 // principalHandle for the image in this frame.
61 // This can be compared to an nsIPrincipal when back on main thread.
62 PrincipalHandle mPrincipalHandle
;
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
;
79 mTimeStamp
= TimeStamp();
81 void SetForceBlack(bool aForceBlack
) { mFrame
.SetForceBlack(aForceBlack
); }
83 size_t SizeOfExcludingThisIfUnshared(MallocSizeOf aMallocSizeOf
) const {
89 const PrincipalHandle
& GetPrincipalHandle() const {
90 return mFrame
.GetPrincipalHandle();
98 class VideoSegment
: public MediaSegmentBase
<VideoSegment
, VideoChunk
> {
100 typedef mozilla::layers::Image Image
;
101 typedef mozilla::gfx::IntSize IntSize
;
104 VideoSegment(VideoSegment
&& aSegment
);
106 VideoSegment(const VideoSegment
&) = delete;
107 VideoSegment
& operator=(const VideoSegment
&) = delete;
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) {
120 if (mChunks
.IsEmpty()) {
121 mChunks
.AppendElement()->SetNull(aDuration
);
123 mChunks
[mChunks
.Length() - 1].mDuration
+= aDuration
;
125 mDuration
+= aDuration
;
127 const VideoFrame
* GetLastFrame(TrackTime
* aStart
= nullptr) {
128 VideoChunk
* c
= GetLastChunk();
133 *aStart
= mDuration
- c
->mDuration
;
137 VideoChunk
* FindChunkContaining(const TimeStamp
& aTime
) {
138 VideoChunk
* previousChunk
= nullptr;
139 for (VideoChunk
& c
: mChunks
) {
140 if (c
.mTimeStamp
.IsNull()) {
143 if (c
.mTimeStamp
> aTime
) {
144 return previousChunk
;
148 return previousChunk
;
150 void ForgetUpToTime(const TimeStamp
& aTime
) {
151 VideoChunk
* chunk
= FindChunkContaining(aTime
);
155 TrackTime duration
= 0;
156 size_t chunksToRemove
= 0;
157 for (const VideoChunk
& c
: mChunks
) {
158 if (c
.mTimeStamp
>= chunk
->mTimeStamp
) {
161 duration
+= c
.GetDuration();
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_ */