VideoSegment.cpp (6223B)
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 #include "VideoSegment.h" 7 8 #include "ImageContainer.h" 9 #include "VideoUtils.h" 10 #include "gfx2DGlue.h" 11 #include "mozilla/UniquePtr.h" 12 13 namespace mozilla { 14 15 using namespace layers; 16 17 VideoFrame::VideoFrame(already_AddRefed<Image> aImage, 18 const gfx::IntSize& aIntrinsicSize) 19 : mImage(aImage), 20 mIntrinsicSize(aIntrinsicSize), 21 mForceBlack(false), 22 mPrincipalHandle(PRINCIPAL_HANDLE_NONE) {} 23 24 VideoFrame::VideoFrame() 25 : mIntrinsicSize(0, 0), 26 mForceBlack(false), 27 mPrincipalHandle(PRINCIPAL_HANDLE_NONE) {} 28 29 VideoFrame::~VideoFrame() = default; 30 31 void VideoFrame::SetNull() { 32 mImage = nullptr; 33 mIntrinsicSize = gfx::IntSize(0, 0); 34 mPrincipalHandle = PRINCIPAL_HANDLE_NONE; 35 } 36 37 void VideoFrame::TakeFrom(VideoFrame* aFrame) { 38 mImage = std::move(aFrame->mImage); 39 mIntrinsicSize = aFrame->mIntrinsicSize; 40 mForceBlack = aFrame->GetForceBlack(); 41 mPrincipalHandle = aFrame->mPrincipalHandle; 42 } 43 44 /* static */ 45 already_AddRefed<Image> VideoFrame::CreateBlackImage( 46 const gfx::IntSize& aSize) { 47 RefPtr<ImageContainer> container = MakeAndAddRef<ImageContainer>( 48 ImageUsageType::BlackImage, ImageContainer::ASYNCHRONOUS); 49 RefPtr<PlanarYCbCrImage> image = container->CreatePlanarYCbCrImage(); 50 if (!image) { 51 return nullptr; 52 } 53 54 gfx::IntSize cbcrSize((aSize.width + 1) / 2, (aSize.height + 1) / 2); 55 int yLen = aSize.width * aSize.height; 56 int cbcrLen = cbcrSize.width * cbcrSize.height; 57 58 // Generate a black image. 59 auto frame = MakeUnique<uint8_t[]>(yLen + 2 * cbcrLen); 60 // Fill Y plane. 61 memset(frame.get(), 0x10, yLen); 62 // Fill Cb/Cr planes. 63 memset(frame.get() + yLen, 0x80, 2 * cbcrLen); 64 65 layers::PlanarYCbCrData data; 66 data.mYChannel = frame.get(); 67 data.mYStride = aSize.width; 68 data.mCbCrStride = cbcrSize.width; 69 data.mCbChannel = frame.get() + yLen; 70 data.mCrChannel = data.mCbChannel + cbcrLen; 71 data.mPictureRect = gfx::IntRect(0, 0, aSize.width, aSize.height); 72 data.mStereoMode = StereoMode::MONO; 73 data.mYUVColorSpace = gfx::YUVColorSpace::BT601; 74 // This could be made FULL once bug 1568745 is complete. A black pixel being 75 // 0x00, 0x80, 0x80 76 data.mColorRange = gfx::ColorRange::LIMITED; 77 data.mChromaSubsampling = gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT; 78 79 // Copies data, so we can free data. 80 if (NS_FAILED(image->CopyData(data))) { 81 return nullptr; 82 } 83 84 return image.forget(); 85 } 86 87 void VideoSegment::AppendFrame(const VideoChunk& aChunk, 88 const Maybe<bool>& aForceBlack, 89 const Maybe<TimeStamp>& aTimeStamp) { 90 VideoChunk* chunk = AppendChunk(0); 91 chunk->mTimeStamp = aTimeStamp ? *aTimeStamp : aChunk.mTimeStamp; 92 chunk->mProcessingDuration = aChunk.mProcessingDuration; 93 chunk->mMediaTime = aChunk.mMediaTime; 94 chunk->mWebrtcCaptureTime = aChunk.mWebrtcCaptureTime; 95 chunk->mWebrtcReceiveTime = aChunk.mWebrtcReceiveTime; 96 chunk->mRtpTimestamp = aChunk.mRtpTimestamp; 97 VideoFrame frame(do_AddRef(aChunk.mFrame.GetImage()), 98 aChunk.mFrame.GetIntrinsicSize()); 99 MOZ_ASSERT_IF(!IsNull(), !aChunk.mTimeStamp.IsNull()); 100 frame.SetForceBlack(aForceBlack ? *aForceBlack 101 : aChunk.mFrame.GetForceBlack()); 102 frame.SetPrincipalHandle(aChunk.mFrame.GetPrincipalHandle()); 103 chunk->mFrame.TakeFrom(&frame); 104 } 105 106 void VideoSegment::AppendFrame(already_AddRefed<Image>&& aImage, 107 const IntSize& aIntrinsicSize, 108 const PrincipalHandle& aPrincipalHandle, 109 bool aForceBlack, TimeStamp aTimeStamp, 110 media::TimeUnit aProcessingDuration, 111 media::TimeUnit aMediaTime) { 112 VideoChunk* chunk = AppendChunk(0); 113 chunk->mTimeStamp = aTimeStamp; 114 chunk->mProcessingDuration = aProcessingDuration; 115 chunk->mMediaTime = aMediaTime; 116 VideoFrame frame(std::move(aImage), aIntrinsicSize); 117 MOZ_ASSERT_IF(!IsNull(), !aTimeStamp.IsNull()); 118 frame.SetForceBlack(aForceBlack); 119 frame.SetPrincipalHandle(aPrincipalHandle); 120 chunk->mFrame.TakeFrom(&frame); 121 } 122 123 void VideoSegment::AppendWebrtcRemoteFrame( 124 already_AddRefed<Image>&& aImage, const IntSize& aIntrinsicSize, 125 const PrincipalHandle& aPrincipalHandle, bool aForceBlack, 126 TimeStamp aTimeStamp, media::TimeUnit aProcessingDuration, 127 uint32_t aRtpTimestamp, int64_t aWebrtcCaptureTimeNtp, 128 int64_t aWebrtcReceiveTimeUs) { 129 VideoChunk* chunk = AppendChunk(0); 130 chunk->mTimeStamp = aTimeStamp; 131 chunk->mProcessingDuration = aProcessingDuration; 132 if (aWebrtcCaptureTimeNtp > 0) { 133 chunk->mWebrtcCaptureTime = AsVariant(aWebrtcCaptureTimeNtp); 134 } 135 if (aWebrtcReceiveTimeUs > 0) { 136 chunk->mWebrtcReceiveTime = Some(aWebrtcReceiveTimeUs); 137 } 138 chunk->mRtpTimestamp = Some(aRtpTimestamp); 139 VideoFrame frame(std::move(aImage), aIntrinsicSize); 140 MOZ_ASSERT_IF(!IsNull(), !aTimeStamp.IsNull()); 141 frame.SetForceBlack(aForceBlack); 142 frame.SetPrincipalHandle(aPrincipalHandle); 143 chunk->mFrame.TakeFrom(&frame); 144 } 145 146 void VideoSegment::AppendWebrtcLocalFrame( 147 already_AddRefed<Image>&& aImage, const IntSize& aIntrinsicSize, 148 const PrincipalHandle& aPrincipalHandle, bool aForceBlack, 149 TimeStamp aTimeStamp, TimeStamp aWebrtcCaptureTime) { 150 VideoChunk* chunk = AppendChunk(0); 151 chunk->mTimeStamp = aTimeStamp; 152 chunk->mWebrtcCaptureTime = AsVariant(aWebrtcCaptureTime); 153 VideoFrame frame(std::move(aImage), aIntrinsicSize); 154 MOZ_ASSERT_IF(!IsNull(), !aTimeStamp.IsNull()); 155 frame.SetForceBlack(aForceBlack); 156 frame.SetPrincipalHandle(aPrincipalHandle); 157 chunk->mFrame.TakeFrom(&frame); 158 } 159 160 VideoSegment::VideoSegment() 161 : MediaSegmentBase<VideoSegment, VideoChunk>(VIDEO) {} 162 163 VideoSegment::VideoSegment(VideoSegment&& aSegment) 164 : MediaSegmentBase<VideoSegment, VideoChunk>(std::move(aSegment)) {} 165 166 VideoSegment::~VideoSegment() = default; 167 168 } // namespace mozilla