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 "gfx2DGlue.h"
9 #include "ImageContainer.h"
10 #include "Layers.h"
11 #include "VideoUtils.h"
12 #include "mozilla/UniquePtr.h"
13 
14 namespace mozilla {
15 
16 using namespace layers;
17 
VideoFrame(already_AddRefed<Image> aImage,const gfx::IntSize & aIntrinsicSize)18 VideoFrame::VideoFrame(already_AddRefed<Image> aImage,
19                        const gfx::IntSize& aIntrinsicSize)
20     : mImage(aImage),
21       mIntrinsicSize(aIntrinsicSize),
22       mForceBlack(false),
23       mPrincipalHandle(PRINCIPAL_HANDLE_NONE) {}
24 
VideoFrame()25 VideoFrame::VideoFrame()
26     : mIntrinsicSize(0, 0),
27       mForceBlack(false),
28       mPrincipalHandle(PRINCIPAL_HANDLE_NONE) {}
29 
30 VideoFrame::~VideoFrame() = default;
31 
SetNull()32 void VideoFrame::SetNull() {
33   mImage = nullptr;
34   mIntrinsicSize = gfx::IntSize(0, 0);
35   mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
36 }
37 
TakeFrom(VideoFrame * aFrame)38 void VideoFrame::TakeFrom(VideoFrame* aFrame) {
39   mImage = std::move(aFrame->mImage);
40   mIntrinsicSize = aFrame->mIntrinsicSize;
41   mForceBlack = aFrame->GetForceBlack();
42   mPrincipalHandle = aFrame->mPrincipalHandle;
43 }
44 
45 /* static */
CreateBlackImage(const gfx::IntSize & aSize)46 already_AddRefed<Image> VideoFrame::CreateBlackImage(
47     const gfx::IntSize& aSize) {
48   RefPtr<ImageContainer> container =
49       LayerManager::CreateImageContainer(ImageContainer::ASYNCHRONOUS);
50   RefPtr<PlanarYCbCrImage> image = container->CreatePlanarYCbCrImage();
51   if (!image) {
52     return nullptr;
53   }
54 
55   int len = ((aSize.width * aSize.height) * 3 / 2);
56 
57   // Generate a black image.
58   auto frame = MakeUnique<uint8_t[]>(len);
59   int y = aSize.width * aSize.height;
60   // Fill Y plane.
61   memset(frame.get(), 0x10, y);
62   // Fill Cb/Cr planes.
63   memset(frame.get() + y, 0x80, (len - y));
64 
65   const uint8_t lumaBpp = 8;
66   const uint8_t chromaBpp = 4;
67 
68   layers::PlanarYCbCrData data;
69   data.mYChannel = frame.get();
70   data.mYSize = gfx::IntSize(aSize.width, aSize.height);
71   data.mYStride = (int32_t)(aSize.width * lumaBpp / 8.0);
72   data.mCbCrStride = (int32_t)(aSize.width * chromaBpp / 8.0);
73   data.mCbChannel = frame.get() + aSize.height * data.mYStride;
74   data.mCrChannel = data.mCbChannel + aSize.height * data.mCbCrStride / 2;
75   data.mCbCrSize = gfx::IntSize(aSize.width / 2, aSize.height / 2);
76   data.mPicX = 0;
77   data.mPicY = 0;
78   data.mPicSize = gfx::IntSize(aSize.width, aSize.height);
79   data.mStereoMode = StereoMode::MONO;
80   data.mYUVColorSpace = gfx::YUVColorSpace::BT601;
81   // This could be made FULL once bug 1568745 is complete. A black pixel being
82   // 0x00, 0x80, 0x80
83   data.mColorRange = gfx::ColorRange::LIMITED;
84 
85   // Copies data, so we can free data.
86   if (!image->CopyData(data)) {
87     return nullptr;
88   }
89 
90   return image.forget();
91 }
92 
AppendFrame(already_AddRefed<Image> && aImage,const IntSize & aIntrinsicSize,const PrincipalHandle & aPrincipalHandle,bool aForceBlack,TimeStamp aTimeStamp)93 void VideoSegment::AppendFrame(already_AddRefed<Image>&& aImage,
94                                const IntSize& aIntrinsicSize,
95                                const PrincipalHandle& aPrincipalHandle,
96                                bool aForceBlack, TimeStamp aTimeStamp) {
97   VideoChunk* chunk = AppendChunk(0);
98   chunk->mTimeStamp = aTimeStamp;
99   VideoFrame frame(std::move(aImage), aIntrinsicSize);
100   MOZ_ASSERT_IF(!IsNull(), !aTimeStamp.IsNull());
101   frame.SetForceBlack(aForceBlack);
102   frame.SetPrincipalHandle(aPrincipalHandle);
103   chunk->mFrame.TakeFrom(&frame);
104 }
105 
VideoSegment()106 VideoSegment::VideoSegment()
107     : MediaSegmentBase<VideoSegment, VideoChunk>(VIDEO) {}
108 
VideoSegment(VideoSegment && aSegment)109 VideoSegment::VideoSegment(VideoSegment&& aSegment)
110     : MediaSegmentBase<VideoSegment, VideoChunk>(std::move(aSegment)) {}
111 
112 VideoSegment::~VideoSegment() = default;
113 
114 }  // namespace mozilla
115