Coverage Report

Created: 2018-09-25 14:53

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