Line data Source code
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
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "GMPVideoEncoderChild.h"
7 : #include "GMPContentChild.h"
8 : #include <stdio.h>
9 : #include "mozilla/Unused.h"
10 : #include "GMPVideoEncodedFrameImpl.h"
11 : #include "GMPVideoi420FrameImpl.h"
12 : #include "runnable_utils.h"
13 :
14 : namespace mozilla {
15 : namespace gmp {
16 :
17 0 : GMPVideoEncoderChild::GMPVideoEncoderChild(GMPContentChild* aPlugin)
18 : : GMPSharedMemManager(aPlugin)
19 : , mPlugin(aPlugin)
20 : , mVideoEncoder(nullptr)
21 : , mVideoHost(this)
22 : , mNeedShmemIntrCount(0)
23 0 : , mPendingEncodeComplete(false)
24 : {
25 0 : MOZ_ASSERT(mPlugin);
26 0 : }
27 :
28 0 : GMPVideoEncoderChild::~GMPVideoEncoderChild()
29 : {
30 0 : MOZ_ASSERT(!mNeedShmemIntrCount);
31 0 : }
32 :
33 : void
34 0 : GMPVideoEncoderChild::Init(GMPVideoEncoder* aEncoder)
35 : {
36 0 : MOZ_ASSERT(aEncoder, "Cannot initialize video encoder child without a video encoder!");
37 0 : mVideoEncoder = aEncoder;
38 0 : }
39 :
40 : GMPVideoHostImpl&
41 0 : GMPVideoEncoderChild::Host()
42 : {
43 0 : return mVideoHost;
44 : }
45 :
46 : void
47 0 : GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
48 : const uint8_t* aCodecSpecificInfo,
49 : uint32_t aCodecSpecificInfoLength)
50 : {
51 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
52 :
53 0 : auto ef = static_cast<GMPVideoEncodedFrameImpl*>(aEncodedFrame);
54 :
55 0 : GMPVideoEncodedFrameData frameData;
56 0 : ef->RelinquishFrameData(frameData);
57 :
58 0 : nsTArray<uint8_t> codecSpecific;
59 0 : codecSpecific.AppendElements(aCodecSpecificInfo, aCodecSpecificInfoLength);
60 0 : SendEncoded(frameData, codecSpecific);
61 :
62 0 : aEncodedFrame->Destroy();
63 0 : }
64 :
65 : void
66 0 : GMPVideoEncoderChild::Error(GMPErr aError)
67 : {
68 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
69 :
70 0 : SendError(aError);
71 0 : }
72 :
73 : mozilla::ipc::IPCResult
74 0 : GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings,
75 : InfallibleTArray<uint8_t>&& aCodecSpecific,
76 : const int32_t& aNumberOfCores,
77 : const uint32_t& aMaxPayloadSize)
78 : {
79 0 : if (!mVideoEncoder) {
80 0 : return IPC_FAIL_NO_REASON(this);
81 : }
82 :
83 : // Ignore any return code. It is OK for this to fail without killing the process.
84 0 : mVideoEncoder->InitEncode(aCodecSettings,
85 0 : aCodecSpecific.Elements(),
86 0 : aCodecSpecific.Length(),
87 : this,
88 : aNumberOfCores,
89 0 : aMaxPayloadSize);
90 :
91 0 : return IPC_OK();
92 : }
93 :
94 : mozilla::ipc::IPCResult
95 0 : GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame,
96 : InfallibleTArray<uint8_t>&& aCodecSpecificInfo,
97 : InfallibleTArray<GMPVideoFrameType>&& aFrameTypes)
98 : {
99 0 : if (!mVideoEncoder) {
100 0 : return IPC_FAIL_NO_REASON(this);
101 : }
102 :
103 0 : auto f = new GMPVideoi420FrameImpl(aInputFrame, &mVideoHost);
104 :
105 : // Ignore any return code. It is OK for this to fail without killing the process.
106 0 : mVideoEncoder->Encode(f,
107 0 : aCodecSpecificInfo.Elements(),
108 0 : aCodecSpecificInfo.Length(),
109 0 : aFrameTypes.Elements(),
110 0 : aFrameTypes.Length());
111 :
112 0 : return IPC_OK();
113 : }
114 :
115 : mozilla::ipc::IPCResult
116 0 : GMPVideoEncoderChild::RecvChildShmemForPool(Shmem&& aEncodedBuffer)
117 : {
118 0 : if (aEncodedBuffer.IsWritable()) {
119 0 : mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData,
120 0 : aEncodedBuffer);
121 : }
122 0 : return IPC_OK();
123 : }
124 :
125 : mozilla::ipc::IPCResult
126 0 : GMPVideoEncoderChild::RecvSetChannelParameters(const uint32_t& aPacketLoss,
127 : const uint32_t& aRTT)
128 : {
129 0 : if (!mVideoEncoder) {
130 0 : return IPC_FAIL_NO_REASON(this);
131 : }
132 :
133 : // Ignore any return code. It is OK for this to fail without killing the process.
134 0 : mVideoEncoder->SetChannelParameters(aPacketLoss, aRTT);
135 :
136 0 : return IPC_OK();
137 : }
138 :
139 : mozilla::ipc::IPCResult
140 0 : GMPVideoEncoderChild::RecvSetRates(const uint32_t& aNewBitRate,
141 : const uint32_t& aFrameRate)
142 : {
143 0 : if (!mVideoEncoder) {
144 0 : return IPC_FAIL_NO_REASON(this);
145 : }
146 :
147 : // Ignore any return code. It is OK for this to fail without killing the process.
148 0 : mVideoEncoder->SetRates(aNewBitRate, aFrameRate);
149 :
150 0 : return IPC_OK();
151 : }
152 :
153 : mozilla::ipc::IPCResult
154 0 : GMPVideoEncoderChild::RecvSetPeriodicKeyFrames(const bool& aEnable)
155 : {
156 0 : if (!mVideoEncoder) {
157 0 : return IPC_FAIL_NO_REASON(this);
158 : }
159 :
160 : // Ignore any return code. It is OK for this to fail without killing the process.
161 0 : mVideoEncoder->SetPeriodicKeyFrames(aEnable);
162 :
163 0 : return IPC_OK();
164 : }
165 :
166 : mozilla::ipc::IPCResult
167 0 : GMPVideoEncoderChild::RecvEncodingComplete()
168 : {
169 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
170 :
171 0 : if (mNeedShmemIntrCount) {
172 : // There's a GMP blocked in Alloc() waiting for the CallNeedShem() to
173 : // return a frame they can use. Don't call the GMP's EncodingComplete()
174 : // now and don't delete the GMPVideoEncoderChild, defer processing the
175 : // EncodingComplete() until once the Alloc() finishes.
176 0 : mPendingEncodeComplete = true;
177 0 : return IPC_OK();
178 : }
179 :
180 0 : if (!mVideoEncoder) {
181 0 : Unused << Send__delete__(this);
182 0 : return IPC_FAIL_NO_REASON(this);
183 : }
184 :
185 : // Ignore any return code. It is OK for this to fail without killing the process.
186 0 : mVideoEncoder->EncodingComplete();
187 :
188 0 : mVideoHost.DoneWithAPI();
189 :
190 0 : mPlugin = nullptr;
191 :
192 0 : Unused << Send__delete__(this);
193 :
194 0 : return IPC_OK();
195 : }
196 :
197 : bool
198 0 : GMPVideoEncoderChild::Alloc(size_t aSize,
199 : Shmem::SharedMemory::SharedMemoryType aType,
200 : Shmem* aMem)
201 : {
202 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
203 :
204 : bool rv;
205 : #ifndef SHMEM_ALLOC_IN_CHILD
206 0 : ++mNeedShmemIntrCount;
207 0 : rv = CallNeedShmem(aSize, aMem);
208 0 : --mNeedShmemIntrCount;
209 0 : if (mPendingEncodeComplete && mNeedShmemIntrCount == 0) {
210 0 : mPendingEncodeComplete = false;
211 0 : mPlugin->GMPMessageLoop()->PostTask(
212 0 : NewRunnableMethod("gmp::GMPVideoEncoderChild::RecvEncodingComplete",
213 : this,
214 0 : &GMPVideoEncoderChild::RecvEncodingComplete));
215 : }
216 : #else
217 : #ifdef GMP_SAFE_SHMEM
218 : rv = AllocShmem(aSize, aType, aMem);
219 : #else
220 : rv = AllocUnsafeShmem(aSize, aType, aMem);
221 : #endif
222 : #endif
223 0 : return rv;
224 : }
225 :
226 : void
227 0 : GMPVideoEncoderChild::Dealloc(Shmem& aMem)
228 : {
229 : #ifndef SHMEM_ALLOC_IN_CHILD
230 0 : SendParentShmemForPool(aMem);
231 : #else
232 : DeallocShmem(aMem);
233 : #endif
234 0 : }
235 :
236 : } // namespace gmp
237 : } // namespace mozilla
|