Coverage Report

Created: 2018-09-25 14:53

/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