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"
13 #include "TimeUnits.h"
23 typedef mozilla::layers::Image Image
;
25 VideoFrame(already_AddRefed
<Image
> aImage
,
26 const gfx::IntSize
& aIntrinsicSize
);
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
;
36 bool operator!=(const VideoFrame
& aFrame
) const {
37 return !operator==(aFrame
);
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
);
46 const PrincipalHandle
& GetPrincipalHandle() const { return mPrincipalHandle
; }
47 const gfx::IntSize
& GetIntrinsicSize() const { return mIntrinsicSize
; }
49 void TakeFrom(VideoFrame
* aFrame
);
51 // Create a planar YCbCr black image.
52 static already_AddRefed
<Image
> CreateBlackImage(const gfx::IntSize
& aSize
);
55 // mImage can be null to indicate "no video" (aka "empty frame"). It can
56 // still have an intrinsic size in this case.
58 // The desired size to render the video frame at.
59 gfx::IntSize mIntrinsicSize
;
61 // principalHandle for the image in this frame.
62 // This can be compared to an nsIPrincipal when back on main thread.
63 PrincipalHandle mPrincipalHandle
;
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
;
72 TrackTime
GetDuration() const { return mDuration
; }
73 bool CanCombineWithFollowing(const VideoChunk
& aOther
) const {
74 return aOther
.mFrame
== mFrame
;
76 bool IsNull() const { return !mFrame
.GetImage(); }
77 void SetNull(TrackTime aDuration
) {
78 mDuration
= aDuration
;
80 mTimeStamp
= TimeStamp();
82 void SetForceBlack(bool aForceBlack
) { mFrame
.SetForceBlack(aForceBlack
); }
84 size_t SizeOfExcludingThisIfUnshared(MallocSizeOf aMallocSizeOf
) const {
90 const PrincipalHandle
& GetPrincipalHandle() const {
91 return mFrame
.GetPrincipalHandle();
97 media::TimeUnit mProcessingDuration
;
98 media::TimeUnit mMediaTime
;
99 layers::ContainerCaptureTime mWebrtcCaptureTime
= AsVariant(Nothing());
100 layers::ContainerReceiveTime mWebrtcReceiveTime
;
101 layers::ContainerRtpTimestamp mRtpTimestamp
;
104 class VideoSegment
: public MediaSegmentBase
<VideoSegment
, VideoChunk
> {
106 typedef mozilla::layers::Image Image
;
107 typedef mozilla::gfx::IntSize IntSize
;
110 VideoSegment(VideoSegment
&& aSegment
);
112 VideoSegment(const VideoSegment
&) = delete;
113 VideoSegment
& operator=(const VideoSegment
&) = delete;
117 void AppendFrame(const VideoChunk
& aChunk
,
118 const Maybe
<bool>& aForceBlack
= Nothing(),
119 const Maybe
<TimeStamp
>& aTimeStamp
= Nothing());
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 media::TimeUnit aProcessingDuration
,
139 TimeStamp aWebrtcCaptureTime
);
140 void ExtendLastFrameBy(TrackTime aDuration
) {
141 if (aDuration
<= 0) {
144 if (mChunks
.IsEmpty()) {
145 mChunks
.AppendElement()->SetNull(aDuration
);
147 mChunks
[mChunks
.Length() - 1].mDuration
+= aDuration
;
149 mDuration
+= aDuration
;
151 const VideoFrame
* GetLastFrame(TrackTime
* aStart
= nullptr) {
152 VideoChunk
* c
= GetLastChunk();
157 *aStart
= mDuration
- c
->mDuration
;
161 VideoChunk
* FindChunkContaining(const TimeStamp
& aTime
) {
162 VideoChunk
* previousChunk
= nullptr;
163 for (VideoChunk
& c
: mChunks
) {
164 if (c
.mTimeStamp
.IsNull()) {
167 if (c
.mTimeStamp
> aTime
) {
168 return previousChunk
;
172 return previousChunk
;
174 void ForgetUpToTime(const TimeStamp
& aTime
) {
175 VideoChunk
* chunk
= FindChunkContaining(aTime
);
179 TrackTime duration
= 0;
180 size_t chunksToRemove
= 0;
181 for (const VideoChunk
& c
: mChunks
) {
182 if (c
.mTimeStamp
>= chunk
->mTimeStamp
) {
185 duration
+= c
.GetDuration();
188 mChunks
.RemoveElementsAt(0, chunksToRemove
);
189 mDuration
-= duration
;
190 MOZ_ASSERT(mChunks
.Capacity() >= DEFAULT_SEGMENT_CAPACITY
,
191 "Capacity must be retained after removing chunks");
193 // Override default impl
194 void ReplaceWithDisabled() override
{
195 for (ChunkIterator
i(*this); !i
.IsEnded(); i
.Next()) {
196 VideoChunk
& chunk
= *i
;
197 chunk
.SetForceBlack(true);
201 // Segment-generic methods not in MediaSegmentBase
202 static Type
StaticType() { return VIDEO
; }
204 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) const override
{
205 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf
);
209 } // namespace mozilla
211 #endif /* MOZILLA_VIDEOSEGMENT_H_ */