2
* Copyright (C) 2020 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
* THE POSSIBILITY OF SUCH DAMAGE.
27
#include "LibWebRTCCodecs.h"
29
#if USE(LIBWEBRTC) && PLATFORM(COCOA) && ENABLE(GPU_PROCESS)
31
#include "DataReference.h"
32
#include "GPUProcessConnection.h"
33
#include "LibWebRTCCodecsProxyMessages.h"
34
#include "WebProcess.h"
35
#include <WebCore/LibWebRTCMacros.h>
36
#include <WebCore/RealtimeVideoUtilities.h>
37
#include <WebCore/RemoteVideoSample.h>
38
#include <pal/cf/CoreMediaSoftLink.h>
39
#include <webrtc/sdk/WebKit/WebKitEncoder.h>
40
#include <webrtc/sdk/WebKit/WebKitUtilities.h>
41
#include <wtf/MainThread.h>
44
using namespace WebCore;
46
static webrtc::WebKitVideoDecoder createVideoDecoder(const webrtc::SdpVideoFormat& format)
48
if (format.name != "H264")
51
return WebProcess::singleton().libWebRTCCodecs().createDecoder();
54
static int32_t releaseVideoDecoder(webrtc::WebKitVideoDecoder decoder)
56
return WebProcess::singleton().libWebRTCCodecs().releaseDecoder(*static_cast<LibWebRTCCodecs::Decoder*>(decoder));
59
static int32_t decodeVideoFrame(webrtc::WebKitVideoDecoder decoder, uint32_t timeStamp, const uint8_t* data, size_t size)
61
return WebProcess::singleton().libWebRTCCodecs().decodeFrame(*static_cast<LibWebRTCCodecs::Decoder*>(decoder), timeStamp, data, size);
64
static int32_t registerDecodeCompleteCallback(webrtc::WebKitVideoDecoder decoder, void* decodedImageCallback)
66
WebProcess::singleton().libWebRTCCodecs().registerDecodeFrameCallback(*static_cast<LibWebRTCCodecs::Decoder*>(decoder), decodedImageCallback);
70
static webrtc::WebKitVideoEncoder createVideoEncoder(const webrtc::SdpVideoFormat& format)
72
if (format.name != "H264")
75
return WebProcess::singleton().libWebRTCCodecs().createEncoder(format.parameters);
78
static int32_t releaseVideoEncoder(webrtc::WebKitVideoEncoder encoder)
80
return WebProcess::singleton().libWebRTCCodecs().releaseEncoder(*static_cast<LibWebRTCCodecs::Encoder*>(encoder));
83
static int32_t initializeVideoEncoder(webrtc::WebKitVideoEncoder encoder, const webrtc::VideoCodec& codec)
85
return WebProcess::singleton().libWebRTCCodecs().initializeEncoder(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), codec.width, codec.height, codec.startBitrate, codec.maxBitrate, codec.minBitrate, codec.maxFramerate);
88
static inline MediaSample::VideoRotation toMediaSampleVideoRotation(webrtc::VideoRotation rotation)
91
case webrtc::kVideoRotation_0:
92
return MediaSample::VideoRotation::None;
93
case webrtc::kVideoRotation_180:
94
return MediaSample::VideoRotation::UpsideDown;
95
case webrtc::kVideoRotation_90:
96
return MediaSample::VideoRotation::Right;
97
case webrtc::kVideoRotation_270:
98
return MediaSample::VideoRotation::Left;
100
ASSERT_NOT_REACHED();
101
return MediaSample::VideoRotation::None;
104
static int32_t encodeVideoFrame(webrtc::WebKitVideoEncoder encoder, const webrtc::VideoFrame& frame, bool shouldEncodeAsKeyFrame)
106
RetainPtr<CVPixelBufferRef> newPixelBuffer;
107
auto pixelBuffer = webrtc::pixelBufferFromFrame(frame, [&newPixelBuffer](size_t width, size_t height) -> CVPixelBufferRef {
108
auto pixelBufferPool = WebProcess::singleton().libWebRTCCodecs().pixelBufferPool(width, height);
109
if (!pixelBufferPool)
112
newPixelBuffer = WebCore::createPixelBufferFromPool(pixelBufferPool);
113
return newPixelBuffer.get();
117
return WEBRTC_VIDEO_CODEC_ERROR;
119
auto sample = RemoteVideoSample::create(pixelBuffer, MediaTime(frame.timestamp_us(), 1000000), toMediaSampleVideoRotation(frame.rotation()));
120
return WebProcess::singleton().libWebRTCCodecs().encodeFrame(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), *sample, shouldEncodeAsKeyFrame);
123
static int32_t registerEncodeCompleteCallback(webrtc::WebKitVideoEncoder encoder, void* encodedImageCallback)
125
WebProcess::singleton().libWebRTCCodecs().registerEncodeFrameCallback(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), encodedImageCallback);
129
static void setEncodeRatesCallback(webrtc::WebKitVideoEncoder encoder, const webrtc::VideoEncoder::RateControlParameters& parameters)
131
uint32_t bitRate = parameters.bitrate.get_sum_kbps();
132
uint32_t frameRate = static_cast<uint32_t>(parameters.framerate_fps + 0.5);
133
WebProcess::singleton().libWebRTCCodecs().setEncodeRates(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), bitRate, frameRate);
136
void LibWebRTCCodecs::setCallbacks(bool useGPUProcess)
138
ASSERT(isMainThread());
140
if (!useGPUProcess) {
141
webrtc::setVideoDecoderCallbacks(nullptr, nullptr, nullptr, nullptr);
142
webrtc::setVideoEncoderCallbacks(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
145
// Let's create WebProcess libWebRTCCodecs since it may be called from various threads.
146
WebProcess::singleton().libWebRTCCodecs();
147
webrtc::setVideoDecoderCallbacks(createVideoDecoder, releaseVideoDecoder, decodeVideoFrame, registerDecodeCompleteCallback);
148
webrtc::setVideoEncoderCallbacks(createVideoEncoder, releaseVideoEncoder, initializeVideoEncoder, encodeVideoFrame, registerEncodeCompleteCallback, setEncodeRatesCallback);
151
LibWebRTCCodecs::Decoder* LibWebRTCCodecs::createDecoder()
153
auto decoder = makeUnique<Decoder>();
154
auto* result = decoder.get();
155
decoder->identifier = RTCDecoderIdentifier::generateThreadSafe();
157
callOnMainRunLoop([this, decoder = WTFMove(decoder)]() mutable {
158
decoder->connection = &WebProcess::singleton().ensureGPUProcessConnection().connection();
160
auto decoderIdentifier = decoder->identifier;
161
decoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateDecoder { decoderIdentifier }, 0);
163
ASSERT(!m_decoders.contains(decoderIdentifier));
164
m_decoders.add(decoderIdentifier, WTFMove(decoder));
169
int32_t LibWebRTCCodecs::releaseDecoder(Decoder& decoder)
171
LockHolder holder(decoder.decodedImageCallbackLock);
172
decoder.decodedImageCallback = nullptr;
174
callOnMainRunLoop([this, decoderIdentifier = decoder.identifier] {
175
ASSERT(m_decoders.contains(decoderIdentifier));
177
m_decoders.remove(decoderIdentifier);
178
WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0);
183
int32_t LibWebRTCCodecs::decodeFrame(Decoder& decoder, uint32_t timeStamp, const uint8_t* data, size_t size)
185
if (!decoder.connection || decoder.hasError) {
186
decoder.hasError = false;
187
return WEBRTC_VIDEO_CODEC_ERROR;
190
decoder.connection->send(Messages::LibWebRTCCodecsProxy::DecodeFrame { decoder.identifier, timeStamp, IPC::DataReference { data, size } }, 0);
191
return WEBRTC_VIDEO_CODEC_OK;
194
void LibWebRTCCodecs::registerDecodeFrameCallback(Decoder& decoder, void* decodedImageCallback)
196
LockHolder holder(decoder.decodedImageCallbackLock);
197
decoder.decodedImageCallback = decodedImageCallback;
200
void LibWebRTCCodecs::failedDecoding(RTCDecoderIdentifier decoderIdentifier)
202
ASSERT(isMainThread());
204
if (auto* decoder = m_decoders.get(decoderIdentifier))
205
decoder->hasError = true;
208
void LibWebRTCCodecs::completedDecoding(RTCDecoderIdentifier decoderIdentifier, uint32_t timeStamp, WebCore::RemoteVideoSample&& remoteSample)
210
ASSERT(isMainThread());
212
// FIXME: Do error logging.
213
auto* decoder = m_decoders.get(decoderIdentifier);
217
auto locker = tryHoldLock(decoder->decodedImageCallbackLock);
221
if (!decoder->decodedImageCallback)
224
if (!m_imageTransferSession || m_imageTransferSession->pixelFormat() != remoteSample.videoFormat())
225
m_imageTransferSession = WebCore::ImageTransferSessionVT::create(remoteSample.videoFormat());
227
if (!m_imageTransferSession) {
228
ASSERT_NOT_REACHED();
232
auto pixelBuffer = m_imageTransferSession->createPixelBuffer(remoteSample.surface(), remoteSample.size());
234
ASSERT_NOT_REACHED();
238
webrtc::RemoteVideoDecoder::decodeComplete(decoder->decodedImageCallback, timeStamp, pixelBuffer.get(), remoteSample.time().toDouble());
241
LibWebRTCCodecs::Encoder* LibWebRTCCodecs::createEncoder(const std::map<std::string, std::string>& formatParameters)
243
auto encoder = makeUnique<Encoder>();
244
auto* result = encoder.get();
245
encoder->identifier = RTCEncoderIdentifier::generateThreadSafe();
247
Vector<std::pair<String, String>> parameters;
248
for (auto& keyValue : formatParameters)
249
parameters.append(std::make_pair(String::fromUTF8(keyValue.first.data(), keyValue.first.length()), String::fromUTF8(keyValue.second.data(), keyValue.second.length())));
251
callOnMainRunLoop([this, encoder = WTFMove(encoder), parameters = WTFMove(parameters)]() mutable {
252
auto encoderIdentifier = encoder->identifier;
253
ASSERT(!m_encoders.contains(encoderIdentifier));
255
WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoderIdentifier, parameters }, 0);
256
m_encoders.add(encoderIdentifier, WTFMove(encoder));
261
int32_t LibWebRTCCodecs::releaseEncoder(Encoder& encoder)
263
LockHolder holder(encoder.encodedImageCallbackLock);
264
encoder.encodedImageCallback = nullptr;
266
callOnMainRunLoop([this, encoderIdentifier = encoder.identifier] {
267
ASSERT(m_encoders.contains(encoderIdentifier));
269
m_encoders.remove(encoderIdentifier);
270
WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0);
275
int32_t LibWebRTCCodecs::initializeEncoder(Encoder& encoder, uint16_t width, uint16_t height, unsigned startBitRate, unsigned maxBitRate, unsigned minBitRate, uint32_t maxFrameRate)
277
callOnMainRunLoop([this, encoderIdentifier = encoder.identifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate] {
278
if (auto* encoder = m_encoders.get(encoderIdentifier)) {
279
auto& connection = WebProcess::singleton().ensureGPUProcessConnection().connection();
280
connection.send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoderIdentifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }, 0);
281
// We set encoder->connection here so that InitializeEncoder is sent before any EncodeFrame message.
282
encoder->connection = &connection;
288
int32_t LibWebRTCCodecs::encodeFrame(Encoder& encoder, const WebCore::RemoteVideoSample& frame, bool shouldEncodeAsKeyFrame)
290
if (!encoder.connection)
291
return WEBRTC_VIDEO_CODEC_ERROR;
293
encoder.connection->send(Messages::LibWebRTCCodecsProxy::EncodeFrame { encoder.identifier, frame, shouldEncodeAsKeyFrame }, 0);
294
return WEBRTC_VIDEO_CODEC_OK;
297
void LibWebRTCCodecs::registerEncodeFrameCallback(Encoder& encoder, void* encodedImageCallback)
299
LockHolder holder(encoder.encodedImageCallbackLock);
300
encoder.encodedImageCallback = encodedImageCallback;
303
void LibWebRTCCodecs::setEncodeRates(Encoder& encoder, uint32_t bitRate, uint32_t frameRate)
305
if (!encoder.connection) {
306
callOnMainRunLoop([this, encoderIdentifier = encoder.identifier, bitRate, frameRate] {
308
ASSERT(m_encoders.contains(encoderIdentifier));
309
ASSERT(m_encoders.get(encoderIdentifier)->connection);
310
WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoderIdentifier, bitRate, frameRate }, 0);
314
encoder.connection->send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoder.identifier, bitRate, frameRate }, 0);
317
void LibWebRTCCodecs::completedEncoding(RTCEncoderIdentifier identifier, IPC::DataReference&& data, const webrtc::WebKitEncodedFrameInfo& info, webrtc::WebKitRTPFragmentationHeader&& fragmentationHeader)
319
ASSERT(isMainThread());
321
// FIXME: Do error logging.
322
auto* encoder = m_encoders.get(identifier);
326
auto locker = tryHoldLock(encoder->encodedImageCallbackLock);
330
if (!encoder->encodedImageCallback)
333
webrtc::RemoteVideoEncoder::encodeComplete(encoder->encodedImageCallback, const_cast<uint8_t*>(data.data()), data.size(), info, fragmentationHeader.value());
336
CVPixelBufferPoolRef LibWebRTCCodecs::pixelBufferPool(size_t width, size_t height)
338
if (!m_pixelBufferPool || m_pixelBufferPoolWidth != width || m_pixelBufferPoolHeight != height) {
339
m_pixelBufferPool = createPixelBufferPool(width, height);
340
m_pixelBufferPoolWidth = width;
341
m_pixelBufferPoolHeight = height;
343
return m_pixelBufferPool.get();