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 "GMPVideoDecoderChild.h"
7 : #include "GMPVideoi420FrameImpl.h"
8 : #include "GMPContentChild.h"
9 : #include <stdio.h>
10 : #include "mozilla/Unused.h"
11 : #include "GMPVideoEncodedFrameImpl.h"
12 : #include "runnable_utils.h"
13 :
14 : namespace mozilla {
15 : namespace gmp {
16 :
17 0 : GMPVideoDecoderChild::GMPVideoDecoderChild(GMPContentChild* aPlugin)
18 : : GMPSharedMemManager(aPlugin)
19 : , mPlugin(aPlugin)
20 : , mVideoDecoder(nullptr)
21 : , mVideoHost(this)
22 : , mNeedShmemIntrCount(0)
23 0 : , mPendingDecodeComplete(false)
24 : {
25 0 : MOZ_ASSERT(mPlugin);
26 0 : }
27 :
28 0 : GMPVideoDecoderChild::~GMPVideoDecoderChild()
29 : {
30 0 : MOZ_ASSERT(!mNeedShmemIntrCount);
31 0 : }
32 :
33 : void
34 0 : GMPVideoDecoderChild::Init(GMPVideoDecoder* aDecoder)
35 : {
36 0 : MOZ_ASSERT(aDecoder, "Cannot initialize video decoder child without a video decoder!");
37 0 : mVideoDecoder = aDecoder;
38 0 : }
39 :
40 : GMPVideoHostImpl&
41 0 : GMPVideoDecoderChild::Host()
42 : {
43 0 : return mVideoHost;
44 : }
45 :
46 : void
47 0 : GMPVideoDecoderChild::Decoded(GMPVideoi420Frame* aDecodedFrame)
48 : {
49 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
50 :
51 0 : if (!aDecodedFrame) {
52 0 : MOZ_CRASH("Not given a decoded frame!");
53 : }
54 :
55 0 : auto df = static_cast<GMPVideoi420FrameImpl*>(aDecodedFrame);
56 :
57 0 : GMPVideoi420FrameData frameData;
58 0 : df->InitFrameData(frameData);
59 0 : SendDecoded(frameData);
60 :
61 0 : aDecodedFrame->Destroy();
62 0 : }
63 :
64 : void
65 0 : GMPVideoDecoderChild::ReceivedDecodedReferenceFrame(const uint64_t aPictureId)
66 : {
67 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
68 :
69 0 : SendReceivedDecodedReferenceFrame(aPictureId);
70 0 : }
71 :
72 : void
73 0 : GMPVideoDecoderChild::ReceivedDecodedFrame(const uint64_t aPictureId)
74 : {
75 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
76 :
77 0 : SendReceivedDecodedFrame(aPictureId);
78 0 : }
79 :
80 : void
81 0 : GMPVideoDecoderChild::InputDataExhausted()
82 : {
83 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
84 :
85 0 : SendInputDataExhausted();
86 0 : }
87 :
88 : void
89 0 : GMPVideoDecoderChild::DrainComplete()
90 : {
91 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
92 :
93 0 : SendDrainComplete();
94 0 : }
95 :
96 : void
97 0 : GMPVideoDecoderChild::ResetComplete()
98 : {
99 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
100 :
101 0 : SendResetComplete();
102 0 : }
103 :
104 : void
105 0 : GMPVideoDecoderChild::Error(GMPErr aError)
106 : {
107 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
108 :
109 0 : SendError(aError);
110 0 : }
111 :
112 : mozilla::ipc::IPCResult
113 0 : GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings,
114 : InfallibleTArray<uint8_t>&& aCodecSpecific,
115 : const int32_t& aCoreCount)
116 : {
117 0 : if (!mVideoDecoder) {
118 0 : return IPC_FAIL_NO_REASON(this);
119 : }
120 :
121 : // Ignore any return code. It is OK for this to fail without killing the process.
122 0 : mVideoDecoder->InitDecode(aCodecSettings,
123 0 : aCodecSpecific.Elements(),
124 0 : aCodecSpecific.Length(),
125 : this,
126 0 : aCoreCount);
127 0 : return IPC_OK();
128 : }
129 :
130 : mozilla::ipc::IPCResult
131 0 : GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
132 : const bool& aMissingFrames,
133 : InfallibleTArray<uint8_t>&& aCodecSpecificInfo,
134 : const int64_t& aRenderTimeMs)
135 : {
136 0 : if (!mVideoDecoder) {
137 0 : return IPC_FAIL_NO_REASON(this);
138 : }
139 :
140 0 : auto f = new GMPVideoEncodedFrameImpl(aInputFrame, &mVideoHost);
141 :
142 : // Ignore any return code. It is OK for this to fail without killing the process.
143 0 : mVideoDecoder->Decode(f,
144 0 : aMissingFrames,
145 0 : aCodecSpecificInfo.Elements(),
146 0 : aCodecSpecificInfo.Length(),
147 0 : aRenderTimeMs);
148 :
149 0 : return IPC_OK();
150 : }
151 :
152 : mozilla::ipc::IPCResult
153 0 : GMPVideoDecoderChild::RecvChildShmemForPool(Shmem&& aFrameBuffer)
154 : {
155 0 : if (aFrameBuffer.IsWritable()) {
156 0 : mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData,
157 0 : aFrameBuffer);
158 : }
159 0 : return IPC_OK();
160 : }
161 :
162 : mozilla::ipc::IPCResult
163 0 : GMPVideoDecoderChild::RecvReset()
164 : {
165 0 : if (!mVideoDecoder) {
166 0 : return IPC_FAIL_NO_REASON(this);
167 : }
168 :
169 : // Ignore any return code. It is OK for this to fail without killing the process.
170 0 : mVideoDecoder->Reset();
171 :
172 0 : return IPC_OK();
173 : }
174 :
175 : mozilla::ipc::IPCResult
176 0 : GMPVideoDecoderChild::RecvDrain()
177 : {
178 0 : if (!mVideoDecoder) {
179 0 : return IPC_FAIL_NO_REASON(this);
180 : }
181 :
182 : // Ignore any return code. It is OK for this to fail without killing the process.
183 0 : mVideoDecoder->Drain();
184 :
185 0 : return IPC_OK();
186 : }
187 :
188 : mozilla::ipc::IPCResult
189 0 : GMPVideoDecoderChild::RecvDecodingComplete()
190 : {
191 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
192 :
193 0 : if (mNeedShmemIntrCount) {
194 : // There's a GMP blocked in Alloc() waiting for the CallNeedShem() to
195 : // return a frame they can use. Don't call the GMP's DecodingComplete()
196 : // now and don't delete the GMPVideoDecoderChild, defer processing the
197 : // DecodingComplete() until once the Alloc() finishes.
198 0 : mPendingDecodeComplete = true;
199 0 : return IPC_OK();
200 : }
201 0 : if (mVideoDecoder) {
202 : // Ignore any return code. It is OK for this to fail without killing the process.
203 0 : mVideoDecoder->DecodingComplete();
204 0 : mVideoDecoder = nullptr;
205 : }
206 :
207 0 : mVideoHost.DoneWithAPI();
208 :
209 0 : mPlugin = nullptr;
210 :
211 0 : Unused << Send__delete__(this);
212 :
213 0 : return IPC_OK();
214 : }
215 :
216 : bool
217 0 : GMPVideoDecoderChild::Alloc(size_t aSize,
218 : Shmem::SharedMemory::SharedMemoryType aType,
219 : Shmem* aMem)
220 : {
221 0 : MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
222 :
223 : bool rv;
224 : #ifndef SHMEM_ALLOC_IN_CHILD
225 0 : ++mNeedShmemIntrCount;
226 0 : rv = CallNeedShmem(aSize, aMem);
227 0 : --mNeedShmemIntrCount;
228 0 : if (mPendingDecodeComplete && mNeedShmemIntrCount == 0) {
229 0 : mPendingDecodeComplete = false;
230 0 : mPlugin->GMPMessageLoop()->PostTask(
231 0 : NewRunnableMethod("gmp::GMPVideoDecoderChild::RecvDecodingComplete",
232 : this,
233 0 : &GMPVideoDecoderChild::RecvDecodingComplete));
234 : }
235 : #else
236 : #ifdef GMP_SAFE_SHMEM
237 : rv = AllocShmem(aSize, aType, aMem);
238 : #else
239 : rv = AllocUnsafeShmem(aSize, aType, aMem);
240 : #endif
241 : #endif
242 0 : return rv;
243 : }
244 :
245 : void
246 0 : GMPVideoDecoderChild::Dealloc(Shmem& aMem)
247 : {
248 : #ifndef SHMEM_ALLOC_IN_CHILD
249 0 : SendParentShmemForPool(aMem);
250 : #else
251 : DeallocShmem(aMem);
252 : #endif
253 0 : }
254 :
255 : } // namespace gmp
256 9 : } // namespace mozilla
|