blob: a20a2540aa8e8a7fde752668e8ece07cdde6bca8 [file] [log] [blame]
/*
* Copyright (C) 2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "api/video/encoded_image.h"
#include "modules/include/module_common_types.h"
using CVPixelBufferRef = struct __CVBuffer*;
namespace webrtc {
class EncodedImageCallback;
class VideoCodec;
class VideoFrame;
struct SdpVideoFormat;
class Settings;
class VideoEncoderFactoryWithSimulcast final : public VideoEncoderFactory {
public:
explicit VideoEncoderFactoryWithSimulcast(std::unique_ptr<VideoEncoderFactory>&& factory)
: m_internalEncoderFactory(std::move(factory))
{
}
VideoEncoderFactory::CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const final { return m_internalEncoderFactory->QueryVideoEncoder(format); }
std::unique_ptr<VideoEncoder> CreateVideoEncoder(const SdpVideoFormat& format) final;
std::vector<SdpVideoFormat> GetSupportedFormats() const final { return m_internalEncoderFactory->GetSupportedFormats(); }
private:
const std::unique_ptr<VideoEncoderFactory> m_internalEncoderFactory;
};
using WebKitVideoEncoder = void*;
using VideoEncoderCreateCallback = WebKitVideoEncoder(*)(const SdpVideoFormat& format);
using VideoEncoderReleaseCallback = int32_t(*)(WebKitVideoEncoder);
using VideoEncoderInitializeCallback = int32_t(*)(WebKitVideoEncoder, const VideoCodec&);
using VideoEncoderEncodeCallback = int32_t(*)(WebKitVideoEncoder, const VideoFrame&, bool shouldEncodeAsKeyFrame);
using VideoEncoderRegisterEncodeCompleteCallback = int32_t(*)(WebKitVideoEncoder, void* encodedImageCallback);
using VideoEncoderSetRatesCallback = void(*)(WebKitVideoEncoder, const VideoEncoder::RateControlParameters&);
void setVideoEncoderCallbacks(VideoEncoderCreateCallback, VideoEncoderReleaseCallback, VideoEncoderInitializeCallback, VideoEncoderEncodeCallback, VideoEncoderRegisterEncodeCompleteCallback, VideoEncoderSetRatesCallback);
using WebKitEncodedFrameTiming = EncodedImage::Timing;
struct WebKitEncodedFrameInfo {
uint32_t width { 0 };
uint32_t height { 0 };
int64_t timeStamp { 0 };
int64_t ntpTimeMS { 0 };
int64_t captureTimeMS { 0 };
VideoFrameType frameType { VideoFrameType::kVideoFrameDelta };
VideoRotation rotation { kVideoRotation_0 };
VideoContentType contentType { VideoContentType::UNSPECIFIED };
bool completeFrame = false;
int qp { -1 };
WebKitEncodedFrameTiming timing;
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static bool decode(Decoder&, WebKitEncodedFrameInfo&);
};
class WebKitRTPFragmentationHeader {
public:
explicit WebKitRTPFragmentationHeader(webrtc::RTPFragmentationHeader* = nullptr);
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static bool decode(Decoder&, WebKitRTPFragmentationHeader&);
webrtc::RTPFragmentationHeader* value() { return m_value; };
private:
webrtc::RTPFragmentationHeader* m_value { nullptr };
std::unique_ptr<webrtc::RTPFragmentationHeader> m_ownedHeader;
};
class RemoteVideoEncoder final : public webrtc::VideoEncoder {
public:
explicit RemoteVideoEncoder(WebKitVideoEncoder);
~RemoteVideoEncoder() = default;
static void encodeComplete(void* callback, uint8_t* buffer, size_t length, const WebKitEncodedFrameInfo&, const webrtc::RTPFragmentationHeader*);
private:
int32_t InitEncode(const VideoCodec*, const Settings&) final;
int32_t RegisterEncodeCompleteCallback(EncodedImageCallback*) final;
int32_t Release() final;
int32_t Encode(const VideoFrame&, const std::vector<VideoFrameType>*) final;
void SetRates(const RateControlParameters&) final;
EncoderInfo GetEncoderInfo() const final;
WebKitVideoEncoder m_internalEncoder;
};
using LocalEncoder = void*;
using LocalEncoderCallback = void (^)(const uint8_t* buffer, size_t size, const webrtc::WebKitEncodedFrameInfo&, webrtc::RTPFragmentationHeader*);
void* createLocalEncoder(const webrtc::SdpVideoFormat&, LocalEncoderCallback);
void releaseLocalEncoder(LocalEncoder);
void initializeLocalEncoder(LocalEncoder, uint16_t width, uint16_t height, unsigned int startBitrate, unsigned int maxBitrate, unsigned int minBitrate, uint32_t maxFramerate);
void encodeLocalEncoderFrame(LocalEncoder, CVPixelBufferRef, int64_t timeStamp, webrtc::VideoRotation, bool isKeyframeRequired);
void setLocalEncoderRates(LocalEncoder, uint32_t bitRate, uint32_t frameRate);
template<class Decoder>
bool WebKitEncodedFrameInfo::decode(Decoder& decoder, WebKitEncodedFrameInfo& info)
{
if (!decoder.decode(info.width))
return false;
if (!decoder.decode(info.height))
return false;
if (!decoder.decode(info.timeStamp))
return false;
if (!decoder.decode(info.ntpTimeMS))
return false;
if (!decoder.decode(info.captureTimeMS))
return false;
if (!decoder.decodeEnum(info.frameType))
return false;
if (!decoder.decodeEnum(info.rotation))
return false;
if (!decoder.decodeEnum(info.contentType))
return false;
if (!decoder.decode(info.completeFrame))
return false;
if (!decoder.decode(info.qp))
return false;
if (!decoder.decode(info.timing.flags))
return false;
if (!decoder.decode(info.timing.encode_start_ms))
return false;
if (!decoder.decode(info.timing.encode_finish_ms))
return false;
if (!decoder.decode(info.timing.packetization_finish_ms))
return false;
if (!decoder.decode(info.timing.pacer_exit_ms))
return false;
if (!decoder.decode(info.timing.network_timestamp_ms))
return false;
if (!decoder.decode(info.timing.network2_timestamp_ms))
return false;
if (!decoder.decode(info.timing.receive_start_ms))
return false;
return true;
}
template<class Encoder>
void WebKitEncodedFrameInfo::encode(Encoder& encoder) const
{
encoder << width;
encoder << height;
encoder << timeStamp;
encoder << ntpTimeMS;
encoder << captureTimeMS;
encoder.encodeEnum(frameType);
encoder.encodeEnum(rotation);
encoder.encodeEnum(contentType);
encoder << completeFrame;
encoder << qp;
encoder << timing.flags;
encoder << timing.encode_start_ms;
encoder << timing.encode_finish_ms;
encoder << timing.packetization_finish_ms;
encoder << timing.pacer_exit_ms;
encoder << timing.network_timestamp_ms;
encoder << timing.network2_timestamp_ms;
encoder << timing.receive_start_ms;
encoder << timing.receive_finish_ms;
}
inline WebKitRTPFragmentationHeader::WebKitRTPFragmentationHeader(webrtc::RTPFragmentationHeader* header)
: m_value(header)
{
}
template<class Encoder>
void WebKitRTPFragmentationHeader::encode(Encoder& encoder) const
{
encoder << !!m_value;
if (!m_value)
return;
encoder << static_cast<unsigned>(m_value->Size());
for (unsigned i = 0; i < m_value->Size(); ++i) {
encoder << static_cast<unsigned>(m_value->Offset(i));
encoder << static_cast<unsigned>(m_value->Length(i));
}
}
template<class Decoder>
bool WebKitRTPFragmentationHeader::decode(Decoder& decoder, WebKitRTPFragmentationHeader& header)
{
bool isNull;
if (!decoder.decode(isNull))
return false;
if (isNull) {
header.m_value = nullptr;
return true;
}
unsigned size;
if (!decoder.decode(size))
return false;
header.m_ownedHeader = std::make_unique<webrtc::RTPFragmentationHeader>();
header.m_value = header.m_ownedHeader.get();
header.m_value->VerifyAndAllocateFragmentationHeader(size);
for (size_t i = 0; i < header.m_value->Size(); ++i) {
unsigned offset, length;
if (!decoder.decode(offset))
return false;
if (!decoder.decode(length))
return false;
header.m_value->fragmentationOffset[i] = offset;
header.m_value->fragmentationLength[i] = length;
}
return true;
}
}