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