Reland of Injectable Obj-C video codecs (patchset #1 id:1 of https://codereview.webrtc.org/2975963002/ )
Reason for revert: New CL for fixing the issues Original issue's description: > Revert of Injectable Obj-C video codecs (patchset #8 id:140001 of https://codereview.webrtc.org/2966023002/ ) > > Reason for revert: > Causes no video in certain scenarios. Please come up with a test plan or unit test to prevent such problems in the future. > > Original issue's description: > > Injectable Obj-C video codecs > > > > Initial CL for this effort, with a working RTCVideoEncoder/Decoder for H264 > > (wrapping the VideoToolbox codec). > > > > Some notes / things left to do: > > - There are some hard-coded references to codec types that are supported by > > webrtc::VideoCodec, cricket::VideoCodec, webrtc::CodecSpecificInfo etc > > since we need to convert to/from these types in ObjCVideoEncoder/Decoder. > > These types would need to be more codec agnostic to avoid this. > > - Most interfaces are borrowed from the design document for injectable > > codecs in Android. Some data in the corresponding C++ classes is discarded > > when converting to the Obj-C version, since it has fewer fields. I have not > > verified whether all data that we do keep is needed, or whether we might be > > losing anything useful in these conversions. > > - Implement the VideoToolbox codec code directly in the RTCVideoEncoderH264 > > classes, instead of wrapping webrtc::H264VideoToolboxEncoder / decoder. > > Eliminates converting between ObjC/C++ types outside the ObjCVideoEncoder/ > > Decoder wrapper classes. > > - List the injected codec factory's supported codecs in the list of codecs in > > AppRTCMobile. > > > > BUG=webrtc:7924 > > R=magjed@webrtc.org > > > > Review-Url: https://codereview.webrtc.org/2966023002 . > > Cr-Commit-Position: refs/heads/master@{#18928} > > Committed:a0349c138d> > TBR=magjed@webrtc.org,andersc@webrtc.org > # Not skipping CQ checks because original CL landed more than 1 days ago. > BUG=webrtc:7924 > NOTRY=true > > Review-Url: https://codereview.webrtc.org/2975963002 > Cr-Commit-Position: refs/heads/master@{#18979} > Committed:1095ada7adR=magjed@webrtc.org TBR=tkchin@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:7924 Review-Url: https://codereview.webrtc.org/2981583002 . Cr-Commit-Position: refs/heads/master@{#19002}
This commit is contained in:
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
|
||||
#import "RTCVideoCodec+Private.h"
|
||||
|
||||
@implementation RTCEncodedImage
|
||||
|
||||
@synthesize buffer = _buffer;
|
||||
@synthesize encodedWidth = _encodedWidth;
|
||||
@synthesize encodedHeight = _encodedHeight;
|
||||
@synthesize timeStamp = _timeStamp;
|
||||
@synthesize captureTimeMs = _captureTimeMs;
|
||||
@synthesize ntpTimeMs = _ntpTimeMs;
|
||||
@synthesize isTimingFrame = _isTimingFrame;
|
||||
@synthesize encodeStartMs = _encodeStartMs;
|
||||
@synthesize encodeFinishMs = _encodeFinishMs;
|
||||
@synthesize frameType = _frameType;
|
||||
@synthesize rotation = _rotation;
|
||||
@synthesize completeFrame = _completeFrame;
|
||||
@synthesize qp = _qp;
|
||||
|
||||
- (instancetype)initWithEncodedImage:(webrtc::EncodedImage)encodedImage {
|
||||
if (self = [super init]) {
|
||||
// Wrap the buffer in NSData without copying, do not take ownership.
|
||||
_buffer = [NSData dataWithBytesNoCopy:encodedImage._buffer
|
||||
length:encodedImage._length
|
||||
freeWhenDone:NO];
|
||||
_encodedWidth = encodedImage._encodedWidth;
|
||||
_encodedHeight = encodedImage._encodedHeight;
|
||||
_timeStamp = encodedImage._timeStamp;
|
||||
_captureTimeMs = encodedImage.capture_time_ms_;
|
||||
_ntpTimeMs = encodedImage.ntp_time_ms_;
|
||||
_isTimingFrame = encodedImage.timing_.is_timing_frame;
|
||||
_encodeStartMs = encodedImage.timing_.encode_start_ms;
|
||||
_encodeFinishMs = encodedImage.timing_.encode_finish_ms;
|
||||
_frameType = (RTCFrameType)encodedImage._frameType;
|
||||
_rotation = encodedImage.rotation_;
|
||||
_completeFrame = encodedImage._completeFrame;
|
||||
_qp = encodedImage.qp_ == -1 ? nil : @(encodedImage.qp_);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (webrtc::EncodedImage)toCpp {
|
||||
// Return the pointer without copying.
|
||||
webrtc::EncodedImage encodedImage(
|
||||
(uint8_t *)_buffer.bytes, (size_t)_buffer.length, (size_t)_buffer.length);
|
||||
encodedImage._encodedWidth = _encodedWidth;
|
||||
encodedImage._encodedHeight = _encodedHeight;
|
||||
encodedImage._timeStamp = _timeStamp;
|
||||
encodedImage.capture_time_ms_ = _captureTimeMs;
|
||||
encodedImage.ntp_time_ms_ = _ntpTimeMs;
|
||||
encodedImage.timing_.is_timing_frame = _isTimingFrame;
|
||||
encodedImage.timing_.encode_start_ms = _encodeStartMs;
|
||||
encodedImage.timing_.encode_finish_ms = _encodeFinishMs;
|
||||
encodedImage._frameType = webrtc::FrameType(_frameType);
|
||||
encodedImage.rotation_ = webrtc::VideoRotation(_rotation);
|
||||
encodedImage._completeFrame = _completeFrame;
|
||||
encodedImage.qp_ = _qp ? _qp.intValue : -1;
|
||||
|
||||
return encodedImage;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -11,6 +11,7 @@
|
||||
#import "RTCPeerConnectionFactory+Private.h"
|
||||
|
||||
#import "NSString+StdString.h"
|
||||
#import "RTCAVFoundationVideoSource+Private.h"
|
||||
#import "RTCAudioSource+Private.h"
|
||||
#import "RTCAudioTrack+Private.h"
|
||||
#import "RTCMediaConstraints+Private.h"
|
||||
@ -18,11 +19,15 @@
|
||||
#import "RTCPeerConnection+Private.h"
|
||||
#import "RTCVideoSource+Private.h"
|
||||
#import "RTCVideoTrack+Private.h"
|
||||
#import "RTCAVFoundationVideoSource+Private.h"
|
||||
#import "WebRTC/RTCLogging.h"
|
||||
#import "WebRTC/RTCVideoCodecFactory.h"
|
||||
#ifndef HAVE_NO_MEDIA
|
||||
#import "WebRTC/RTCVideoCodecH264.h"
|
||||
#endif
|
||||
|
||||
#include "PeerConnection/objc_video_decoder_factory.h"
|
||||
#include "PeerConnection/objc_video_encoder_factory.h"
|
||||
#include "Video/objcvideotracksource.h"
|
||||
#include "VideoToolbox/videocodecfactory.h"
|
||||
#include "webrtc/api/videosourceproxy.h"
|
||||
// Adding the nogncheck to disable the including header check.
|
||||
// The no-media version PeerConnectionFactory doesn't depend on media related
|
||||
@ -41,7 +46,17 @@
|
||||
@synthesize nativeFactory = _nativeFactory;
|
||||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
#ifdef HAVE_NO_MEDIA
|
||||
return [self initWithEncoderFactory:nil decoderFactory:nil];
|
||||
#else
|
||||
return [self initWithEncoderFactory:[[RTCVideoEncoderFactoryH264 alloc] init]
|
||||
decoderFactory:[[RTCVideoDecoderFactoryH264 alloc] init]];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (instancetype)initWithEncoderFactory:(nullable id<RTCVideoEncoderFactory>)encoderFactory
|
||||
decoderFactory:(nullable id<RTCVideoDecoderFactory>)decoderFactory {
|
||||
if (self = [super init]) {
|
||||
_networkThread = rtc::Thread::CreateWithSocketServer();
|
||||
BOOL result = _networkThread->Start();
|
||||
NSAssert(result, @"Failed to start network thread.");
|
||||
@ -68,8 +83,14 @@
|
||||
std::unique_ptr<webrtc::CallFactoryInterface>(),
|
||||
std::unique_ptr<webrtc::RtcEventLogFactoryInterface>());
|
||||
#else
|
||||
const auto encoder_factory = new webrtc::VideoToolboxVideoEncoderFactory();
|
||||
const auto decoder_factory = new webrtc::VideoToolboxVideoDecoderFactory();
|
||||
cricket::WebRtcVideoEncoderFactory *encoder_factory = nullptr;
|
||||
cricket::WebRtcVideoDecoderFactory *decoder_factory = nullptr;
|
||||
if (encoderFactory) {
|
||||
encoder_factory = new webrtc::ObjCVideoEncoderFactory(encoderFactory);
|
||||
}
|
||||
if (decoderFactory) {
|
||||
decoder_factory = new webrtc::ObjCVideoDecoderFactory(decoderFactory);
|
||||
}
|
||||
|
||||
// Ownership of encoder/decoder factories is passed on to the
|
||||
// peerconnectionfactory, that handles deleting them.
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
|
||||
@implementation RTCRtpFragmentationHeader
|
||||
|
||||
@synthesize fragmentationOffset = _fragmentationOffset;
|
||||
@synthesize fragmentationLength = _fragmentationLength;
|
||||
@synthesize fragmentationTimeDiff = _fragmentationTimeDiff;
|
||||
@synthesize fragmentationPlType = _fragmentationPlType;
|
||||
|
||||
- (instancetype)initWithFragmentationHeader:
|
||||
(const webrtc::RTPFragmentationHeader *__nullable)fragmentationHeader {
|
||||
if (self = [super init]) {
|
||||
if (fragmentationHeader) {
|
||||
int count = fragmentationHeader->fragmentationVectorSize;
|
||||
NSMutableArray *offsets = [NSMutableArray array];
|
||||
NSMutableArray *lengths = [NSMutableArray array];
|
||||
NSMutableArray *timeDiffs = [NSMutableArray array];
|
||||
NSMutableArray *plTypes = [NSMutableArray array];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
[offsets addObject:@(fragmentationHeader->fragmentationOffset[i])];
|
||||
[lengths addObject:@(fragmentationHeader->fragmentationLength[i])];
|
||||
[timeDiffs addObject:@(fragmentationHeader->fragmentationTimeDiff[i])];
|
||||
[plTypes addObject:@(fragmentationHeader->fragmentationPlType[i])];
|
||||
}
|
||||
_fragmentationOffset = [offsets copy];
|
||||
_fragmentationLength = [lengths copy];
|
||||
_fragmentationTimeDiff = [timeDiffs copy];
|
||||
_fragmentationPlType = [plTypes copy];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (webrtc::RTPFragmentationHeader *)toCpp {
|
||||
webrtc::RTPFragmentationHeader *fragmentationHeader = new webrtc::RTPFragmentationHeader;
|
||||
fragmentationHeader->VerifyAndAllocateFragmentationHeader(_fragmentationOffset.count);
|
||||
for (NSUInteger i = 0; i < _fragmentationOffset.count; ++i) {
|
||||
fragmentationHeader->fragmentationOffset[i] = (size_t)_fragmentationOffset[i].unsignedIntValue;
|
||||
fragmentationHeader->fragmentationLength[i] = (size_t)_fragmentationLength[i].unsignedIntValue;
|
||||
fragmentationHeader->fragmentationTimeDiff[i] =
|
||||
(uint16_t)_fragmentationOffset[i].unsignedIntValue;
|
||||
fragmentationHeader->fragmentationPlType[i] = (uint8_t)_fragmentationOffset[i].unsignedIntValue;
|
||||
}
|
||||
|
||||
return fragmentationHeader;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
|
||||
#import "WebRTC/RTCVideoCodecH264.h"
|
||||
|
||||
#include "webrtc/common_video/include/video_frame.h"
|
||||
#include "webrtc/media/base/codec.h"
|
||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/* Interfaces for converting to/from internal C++ formats. */
|
||||
@interface RTCEncodedImage ()
|
||||
|
||||
- (instancetype)initWithEncodedImage:(webrtc::EncodedImage)encodedImage;
|
||||
- (webrtc::EncodedImage)toCpp;
|
||||
|
||||
@end
|
||||
|
||||
@interface RTCVideoEncoderSettings ()
|
||||
|
||||
- (instancetype)initWithVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec;
|
||||
- (webrtc::VideoCodec *)toCpp;
|
||||
|
||||
@end
|
||||
|
||||
@interface RTCCodecSpecificInfoH264 ()
|
||||
|
||||
- (webrtc::CodecSpecificInfo)toCpp;
|
||||
|
||||
@end
|
||||
|
||||
@interface RTCRtpFragmentationHeader ()
|
||||
|
||||
- (instancetype)initWithFragmentationHeader:
|
||||
(const webrtc::RTPFragmentationHeader *__nullable)fragmentationHeader;
|
||||
- (webrtc::RTPFragmentationHeader *)toCpp;
|
||||
|
||||
@end
|
||||
|
||||
@interface RTCVideoCodecInfo ()
|
||||
|
||||
- (instancetype)initWithVideoCodec:(cricket::VideoCodec)videoCodec;
|
||||
- (cricket::VideoCodec)toCpp;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
|
||||
#import "RTCVideoCodec+Private.h"
|
||||
#import "WebRTC/RTCVideoCodecFactory.h"
|
||||
|
||||
#include "webrtc/sdk/objc/Framework/Classes/Common/helpers.h"
|
||||
|
||||
@implementation RTCVideoCodecInfo
|
||||
|
||||
@synthesize payload = _payload;
|
||||
@synthesize name = _name;
|
||||
@synthesize parameters = _parameters;
|
||||
|
||||
- (instancetype)initWithPayload:(int)payload
|
||||
name:(NSString *)name
|
||||
parameters:(NSDictionary<NSString *, NSString *> *)parameters {
|
||||
if (self = [super init]) {
|
||||
_payload = payload;
|
||||
_name = name;
|
||||
_parameters = parameters;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithVideoCodec:(cricket::VideoCodec)videoCodec {
|
||||
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
||||
for (auto it = videoCodec.params.begin(); it != videoCodec.params.end(); ++it) {
|
||||
[params setObject:webrtc::ios::NSStringFromStdString(it->second)
|
||||
forKey:webrtc::ios::NSStringFromStdString(it->first)];
|
||||
}
|
||||
return [self initWithPayload:videoCodec.id
|
||||
name:webrtc::ios::NSStringFromStdString(videoCodec.name)
|
||||
parameters:params];
|
||||
}
|
||||
|
||||
- (cricket::VideoCodec)toCpp {
|
||||
cricket::VideoCodec codec(webrtc::ios::StdStringFromNSString(_name));
|
||||
for (NSString *paramKey in [_parameters allKeys]) {
|
||||
codec.SetParam(webrtc::ios::StdStringFromNSString(paramKey),
|
||||
webrtc::ios::StdStringFromNSString(_parameters[paramKey]));
|
||||
}
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTCVideoEncoderSettings
|
||||
|
||||
@synthesize name = _name;
|
||||
@synthesize width = _width;
|
||||
@synthesize height = _height;
|
||||
@synthesize startBitrate = _startBitrate;
|
||||
@synthesize maxBitrate = _maxBitrate;
|
||||
@synthesize minBitrate = _minBitrate;
|
||||
@synthesize targetBitrate = _targetBitrate;
|
||||
@synthesize maxFramerate = _maxFramerate;
|
||||
@synthesize qpMax = _qpMax;
|
||||
|
||||
- (instancetype)initWithVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec {
|
||||
if (self = [super init]) {
|
||||
if (videoCodec) {
|
||||
rtc::Optional<const char *> codecName = CodecTypeToPayloadName(videoCodec->codecType);
|
||||
if (codecName) {
|
||||
_name = [NSString stringWithUTF8String:codecName.value()];
|
||||
}
|
||||
|
||||
_width = videoCodec->width;
|
||||
_height = videoCodec->height;
|
||||
_startBitrate = videoCodec->startBitrate;
|
||||
_maxBitrate = videoCodec->maxBitrate;
|
||||
_minBitrate = videoCodec->minBitrate;
|
||||
_targetBitrate = videoCodec->targetBitrate;
|
||||
_maxFramerate = videoCodec->maxFramerate;
|
||||
_qpMax = videoCodec->qpMax;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (webrtc::VideoCodec *)toCpp {
|
||||
webrtc::VideoCodec *codecSettings = new webrtc::VideoCodec;
|
||||
|
||||
rtc::Optional<webrtc::VideoCodecType> codecType =
|
||||
webrtc::PayloadNameToCodecType(webrtc::ios::StdStringFromNSString(_name));
|
||||
if (codecType) {
|
||||
codecSettings->codecType = codecType.value();
|
||||
}
|
||||
|
||||
codecSettings->width = _width;
|
||||
codecSettings->height = _height;
|
||||
codecSettings->startBitrate = _startBitrate;
|
||||
codecSettings->maxBitrate = _maxBitrate;
|
||||
codecSettings->minBitrate = _minBitrate;
|
||||
codecSettings->targetBitrate = _targetBitrate;
|
||||
codecSettings->maxFramerate = _maxFramerate;
|
||||
codecSettings->qpMax = _qpMax;
|
||||
|
||||
return codecSettings;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "WebRTC/RTCVideoCodecH264.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#import "RTCVideoCodec+Private.h"
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
#import "WebRTC/RTCVideoFrame.h"
|
||||
#import "WebRTC/RTCVideoFrameBuffer.h"
|
||||
|
||||
#include "webrtc/rtc_base/timeutils.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/encoder.h"
|
||||
#include "webrtc/system_wrappers/include/field_trial.h"
|
||||
|
||||
const size_t kDefaultPayloadSize = 1440;
|
||||
|
||||
const char kHighProfileExperiment[] = "WebRTC-H264HighProfile";
|
||||
|
||||
bool IsHighProfileEnabled() {
|
||||
return webrtc::field_trial::IsEnabled(kHighProfileExperiment);
|
||||
}
|
||||
|
||||
// H264 specific settings.
|
||||
@implementation RTCCodecSpecificInfoH264
|
||||
|
||||
@synthesize packetizationMode = _packetizationMode;
|
||||
|
||||
- (webrtc::CodecSpecificInfo)toCpp {
|
||||
webrtc::CodecSpecificInfo codecSpecificInfo;
|
||||
codecSpecificInfo.codecType = webrtc::kVideoCodecH264;
|
||||
codecSpecificInfo.codec_name = "H264";
|
||||
codecSpecificInfo.codecSpecific.H264.packetization_mode =
|
||||
(webrtc::H264PacketizationMode)_packetizationMode;
|
||||
|
||||
return codecSpecificInfo;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace {
|
||||
|
||||
class H264VideoToolboxEncodeCompleteCallback : public webrtc::EncodedImageCallback {
|
||||
public:
|
||||
Result OnEncodedImage(const webrtc::EncodedImage &encoded_image,
|
||||
const webrtc::CodecSpecificInfo *codec_specific_info,
|
||||
const webrtc::RTPFragmentationHeader *fragmentation) {
|
||||
RTCEncodedImage *image = [[RTCEncodedImage alloc] initWithEncodedImage:encoded_image];
|
||||
|
||||
RTCCodecSpecificInfoH264 *info = [[RTCCodecSpecificInfoH264 alloc] init];
|
||||
info.packetizationMode =
|
||||
(RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packetization_mode;
|
||||
|
||||
RTCRtpFragmentationHeader *header =
|
||||
[[RTCRtpFragmentationHeader alloc] initWithFragmentationHeader:fragmentation];
|
||||
|
||||
callback(image, info, header);
|
||||
return Result(Result::OK, 0);
|
||||
}
|
||||
|
||||
RTCVideoEncoderCallback callback;
|
||||
};
|
||||
|
||||
class H264VideoToolboxDecodeCompleteCallback : public webrtc::DecodedImageCallback {
|
||||
public:
|
||||
int32_t Decoded(webrtc::VideoFrame &decodedImage) {
|
||||
rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer =
|
||||
decodedImage.video_frame_buffer();
|
||||
id<RTCVideoFrameBuffer> rtcFrameBuffer;
|
||||
rtc::scoped_refptr<webrtc::ObjCFrameBuffer> objc_frame_buffer(
|
||||
static_cast<webrtc::ObjCFrameBuffer *>(video_frame_buffer.get()));
|
||||
rtcFrameBuffer = (id<RTCVideoFrameBuffer>)objc_frame_buffer->wrapped_frame_buffer();
|
||||
|
||||
RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc]
|
||||
initWithBuffer:rtcFrameBuffer
|
||||
rotation:static_cast<RTCVideoRotation>(decodedImage.rotation())
|
||||
timeStampNs:decodedImage.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
|
||||
videoFrame.timeStamp = decodedImage.timestamp();
|
||||
|
||||
callback(videoFrame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTCVideoDecoderCallback callback;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Encoder.
|
||||
@implementation RTCVideoEncoderH264 {
|
||||
webrtc::H264VideoToolboxEncoder *_videoToolboxEncoder;
|
||||
H264VideoToolboxEncodeCompleteCallback *_toolboxCallback;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCodecInfo:(RTCVideoCodecInfo *)codecInfo {
|
||||
if (self = [super init]) {
|
||||
cricket::VideoCodec codec = [codecInfo toCpp];
|
||||
_videoToolboxEncoder = new webrtc::H264VideoToolboxEncoder(codec);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setCallback:(RTCVideoEncoderCallback)callback {
|
||||
_toolboxCallback = new H264VideoToolboxEncodeCompleteCallback();
|
||||
_toolboxCallback->callback = callback;
|
||||
_videoToolboxEncoder->RegisterEncodeCompleteCallback(_toolboxCallback);
|
||||
}
|
||||
|
||||
- (int)initEncodeWithSettings:(RTCVideoEncoderSettings *)settings numberOfCores:(int)numberOfCores {
|
||||
webrtc::VideoCodec *codecSettings = [settings toCpp];
|
||||
return _videoToolboxEncoder->InitEncode(codecSettings, numberOfCores, kDefaultPayloadSize);
|
||||
}
|
||||
|
||||
- (int)releaseEncode {
|
||||
return _videoToolboxEncoder->Release();
|
||||
}
|
||||
|
||||
- (int)encode:(RTCVideoFrame *)frame
|
||||
codecSpecificInfo:(id<RTCCodecSpecificInfo>)info
|
||||
frameTypes:(NSArray<NSNumber *> *)frameTypes {
|
||||
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frameBuffer =
|
||||
new rtc::RefCountedObject<webrtc::ObjCFrameBuffer>(frame.buffer);
|
||||
webrtc::VideoFrame videoFrame(frameBuffer,
|
||||
(webrtc::VideoRotation)frame.rotation,
|
||||
frame.timeStampNs / rtc::kNumNanosecsPerMicrosec);
|
||||
videoFrame.set_timestamp(frame.timeStamp);
|
||||
|
||||
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
|
||||
webrtc::CodecSpecificInfo codecSpecificInfo;
|
||||
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
|
||||
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info toCpp];
|
||||
}
|
||||
|
||||
std::vector<webrtc::FrameType> nativeFrameTypes;
|
||||
for (NSNumber *frameType in frameTypes) {
|
||||
RTCFrameType rtcFrameType = (RTCFrameType)frameType.unsignedIntegerValue;
|
||||
nativeFrameTypes.push_back((webrtc::FrameType)rtcFrameType);
|
||||
}
|
||||
|
||||
return _videoToolboxEncoder->Encode(videoFrame, &codecSpecificInfo, &nativeFrameTypes);
|
||||
}
|
||||
|
||||
- (BOOL)setBitrate:(uint32_t)bitrateKbit framerate:(uint32_t)framerate {
|
||||
return _videoToolboxEncoder->SetRates(bitrateKbit, framerate) == WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Decoder.
|
||||
@implementation RTCVideoDecoderH264 {
|
||||
webrtc::H264VideoToolboxDecoder *_videoToolboxDecoder;
|
||||
H264VideoToolboxDecodeCompleteCallback *_toolboxCallback;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
cricket::VideoCodec codec(cricket::kH264CodecName);
|
||||
_videoToolboxDecoder = new webrtc::H264VideoToolboxDecoder();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)initDecodeWithSettings:(RTCVideoEncoderSettings *)settings numberOfCores:(int)numberOfCores {
|
||||
webrtc::VideoCodec *codecSettings = [settings toCpp];
|
||||
return _videoToolboxDecoder->InitDecode(codecSettings, numberOfCores);
|
||||
}
|
||||
|
||||
- (void)setCallback:(RTCVideoDecoderCallback)callback {
|
||||
_toolboxCallback = new H264VideoToolboxDecodeCompleteCallback();
|
||||
_toolboxCallback->callback = callback;
|
||||
_videoToolboxDecoder->RegisterDecodeCompleteCallback(_toolboxCallback);
|
||||
}
|
||||
|
||||
- (int32_t)releaseDecode {
|
||||
return _videoToolboxDecoder->Release();
|
||||
}
|
||||
|
||||
- (int)decode:(RTCEncodedImage *)encodedImage
|
||||
missingFrames:(BOOL)missingFrames
|
||||
fragmentationHeader:(RTCRtpFragmentationHeader *)fragmentationHeader
|
||||
codecSpecificInfo:(__nullable id<RTCCodecSpecificInfo>)info
|
||||
renderTimeMs:(int64_t)renderTimeMs {
|
||||
webrtc::EncodedImage image = [encodedImage toCpp];
|
||||
|
||||
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
|
||||
webrtc::CodecSpecificInfo codecSpecificInfo;
|
||||
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
|
||||
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info toCpp];
|
||||
}
|
||||
|
||||
webrtc::RTPFragmentationHeader *header = [fragmentationHeader toCpp];
|
||||
|
||||
return _videoToolboxDecoder->Decode(
|
||||
image, missingFrames, header, &codecSpecificInfo, renderTimeMs);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Encoder factory.
|
||||
@implementation RTCVideoEncoderFactoryH264
|
||||
|
||||
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
|
||||
NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];
|
||||
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
|
||||
|
||||
if (IsHighProfileEnabled()) {
|
||||
NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
|
||||
@"profile-level-id" : @"640c1f", // Level 3.1 Constrained High.
|
||||
@"level-asymmetry-allowed" : @"1",
|
||||
@"packetization-mode" : @"1",
|
||||
};
|
||||
RTCVideoCodecInfo *constrainedHighInfo =
|
||||
[[RTCVideoCodecInfo alloc] initWithPayload:0
|
||||
name:codecName
|
||||
parameters:constrainedHighParams];
|
||||
[codecs addObject:constrainedHighInfo];
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
|
||||
@"profile-level-id" : @"42e01f", // Level 3.1 Constrained Baseline.
|
||||
@"level-asymmetry-allowed" : @"1",
|
||||
@"packetization-mode" : @"1",
|
||||
};
|
||||
RTCVideoCodecInfo *constrainedBaselineInfo =
|
||||
[[RTCVideoCodecInfo alloc] initWithPayload:0
|
||||
name:codecName
|
||||
parameters:constrainedBaselineParams];
|
||||
[codecs addObject:constrainedBaselineInfo];
|
||||
|
||||
return [codecs copy];
|
||||
}
|
||||
|
||||
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
|
||||
return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Decoder factory.
|
||||
@implementation RTCVideoDecoderFactoryH264
|
||||
|
||||
- (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info {
|
||||
return [[RTCVideoDecoderH264 alloc] init];
|
||||
}
|
||||
|
||||
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
|
||||
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
|
||||
return @[ [[RTCVideoCodecInfo alloc] initWithPayload:0 name:codecName parameters:@{}] ];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -17,6 +17,7 @@
|
||||
}
|
||||
|
||||
@synthesize buffer = _buffer;
|
||||
@synthesize timeStamp;
|
||||
|
||||
- (int)width {
|
||||
return _buffer.width;
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_DECODER_FACTORY_H_
|
||||
#define WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_DECODER_FACTORY_H_
|
||||
|
||||
#include "webrtc/media/base/codec.h"
|
||||
#include "webrtc/media/engine/webrtcvideodecoderfactory.h"
|
||||
|
||||
@protocol RTCVideoDecoderFactory;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ObjCVideoDecoderFactory : public cricket::WebRtcVideoDecoderFactory {
|
||||
public:
|
||||
explicit ObjCVideoDecoderFactory(id<RTCVideoDecoderFactory>);
|
||||
~ObjCVideoDecoderFactory();
|
||||
|
||||
id<RTCVideoDecoderFactory> wrapped_decoder_factory() const;
|
||||
|
||||
webrtc::VideoDecoder* CreateVideoDecoder(
|
||||
webrtc::VideoCodecType type) override;
|
||||
void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override;
|
||||
|
||||
private:
|
||||
id<RTCVideoDecoderFactory> decoder_factory_;
|
||||
std::vector<cricket::VideoCodec> supported_codecs_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_DECODER_FACTORY_H_
|
||||
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/sdk/objc/Framework/Classes/PeerConnection/objc_video_decoder_factory.h"
|
||||
|
||||
#import "RTCVideoCodec+Private.h"
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
#import "WebRTC/RTCVideoCodecFactory.h"
|
||||
#import "WebRTC/RTCVideoCodecH264.h"
|
||||
#import "WebRTC/RTCVideoFrame.h"
|
||||
#import "WebRTC/RTCVideoFrameBuffer.h"
|
||||
|
||||
#include "webrtc/api/video_codecs/video_decoder.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||
#include "webrtc/modules/video_coding/include/video_error_codes.h"
|
||||
#include "webrtc/rtc_base/logging.h"
|
||||
#include "webrtc/rtc_base/timeutils.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
class ObjCVideoDecoder : public VideoDecoder {
|
||||
public:
|
||||
ObjCVideoDecoder(id<RTCVideoDecoder> decoder) : decoder_(decoder) {}
|
||||
~ObjCVideoDecoder() {}
|
||||
|
||||
int32_t InitDecode(const VideoCodec *codec_settings, int32_t number_of_cores) {
|
||||
RTCVideoEncoderSettings *settings =
|
||||
[[RTCVideoEncoderSettings alloc] initWithVideoCodec:codec_settings];
|
||||
return [decoder_ initDecodeWithSettings:settings numberOfCores:number_of_cores];
|
||||
}
|
||||
|
||||
int32_t Decode(const EncodedImage &input_image,
|
||||
bool missing_frames,
|
||||
const RTPFragmentationHeader *fragmentation,
|
||||
const CodecSpecificInfo *codec_specific_info = NULL,
|
||||
int64_t render_time_ms = -1) {
|
||||
RTCEncodedImage *encodedImage = [[RTCEncodedImage alloc] initWithEncodedImage:input_image];
|
||||
RTCRtpFragmentationHeader *header =
|
||||
[[RTCRtpFragmentationHeader alloc] initWithFragmentationHeader:fragmentation];
|
||||
|
||||
// webrtc::CodecSpecificInfo only handles a hard coded list of codecs
|
||||
id<RTCCodecSpecificInfo> rtcCodecSpecificInfo = nil;
|
||||
if (codec_specific_info) {
|
||||
if (codec_specific_info->codecType == kVideoCodecH264) {
|
||||
RTCCodecSpecificInfoH264 *h264Info = [[RTCCodecSpecificInfoH264 alloc] init];
|
||||
h264Info.packetizationMode =
|
||||
(RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packetization_mode;
|
||||
rtcCodecSpecificInfo = h264Info;
|
||||
}
|
||||
}
|
||||
|
||||
return [decoder_ decode:encodedImage
|
||||
missingFrames:missing_frames
|
||||
fragmentationHeader:header
|
||||
codecSpecificInfo:rtcCodecSpecificInfo
|
||||
renderTimeMs:render_time_ms];
|
||||
}
|
||||
|
||||
int32_t RegisterDecodeCompleteCallback(DecodedImageCallback *callback) {
|
||||
[decoder_ setCallback:^(RTCVideoFrame *frame) {
|
||||
const rtc::scoped_refptr<VideoFrameBuffer> buffer =
|
||||
new rtc::RefCountedObject<ObjCFrameBuffer>(frame.buffer);
|
||||
VideoFrame videoFrame(buffer,
|
||||
(uint32_t)(frame.timeStampNs / rtc::kNumNanosecsPerMicrosec),
|
||||
0,
|
||||
(VideoRotation)frame.rotation);
|
||||
videoFrame.set_timestamp(frame.timeStamp);
|
||||
|
||||
callback->Decoded(videoFrame);
|
||||
}];
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t Release() { return [decoder_ releaseDecode]; }
|
||||
|
||||
private:
|
||||
id<RTCVideoDecoder> decoder_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ObjCVideoDecoderFactory::ObjCVideoDecoderFactory(id<RTCVideoDecoderFactory> decoder_factory)
|
||||
: decoder_factory_(decoder_factory) {}
|
||||
|
||||
ObjCVideoDecoderFactory::~ObjCVideoDecoderFactory() {}
|
||||
|
||||
id<RTCVideoDecoderFactory> ObjCVideoDecoderFactory::wrapped_decoder_factory() const {
|
||||
return decoder_factory_;
|
||||
}
|
||||
|
||||
VideoDecoder *ObjCVideoDecoderFactory::CreateVideoDecoder(VideoCodecType type) {
|
||||
const rtc::Optional<const char *> codec_name = CodecTypeToPayloadName(type);
|
||||
if (!codec_name) {
|
||||
LOG(LS_ERROR) << "Invalid codec type: " << type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NSString *codecName = [NSString stringWithUTF8String:codec_name.value()];
|
||||
for (RTCVideoCodecInfo *codecInfo in decoder_factory_.supportedCodecs) {
|
||||
if ([codecName isEqualToString:codecInfo.name]) {
|
||||
id<RTCVideoDecoder> decoder = [decoder_factory_ createDecoder:codecInfo];
|
||||
return new ObjCVideoDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ObjCVideoDecoderFactory::DestroyVideoDecoder(VideoDecoder *decoder) {
|
||||
delete decoder;
|
||||
decoder = nullptr;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_ENCODER_FACTORY_H_
|
||||
#define WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_ENCODER_FACTORY_H_
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "webrtc/media/engine/webrtcvideoencoderfactory.h"
|
||||
|
||||
@protocol RTCVideoEncoderFactory;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ObjCVideoEncoderFactory : public cricket::WebRtcVideoEncoderFactory {
|
||||
public:
|
||||
explicit ObjCVideoEncoderFactory(id<RTCVideoEncoderFactory>);
|
||||
~ObjCVideoEncoderFactory();
|
||||
|
||||
id<RTCVideoEncoderFactory> wrapped_encoder_factory() const;
|
||||
|
||||
webrtc::VideoEncoder* CreateVideoEncoder(
|
||||
const cricket::VideoCodec& codec) override;
|
||||
const std::vector<cricket::VideoCodec>& supported_codecs() const override;
|
||||
void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override;
|
||||
|
||||
private:
|
||||
id<RTCVideoEncoderFactory> encoder_factory_;
|
||||
mutable std::vector<cricket::VideoCodec> supported_codecs_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_ENCODER_FACTORY_H_
|
||||
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/sdk/objc/Framework/Classes/PeerConnection/objc_video_encoder_factory.h"
|
||||
|
||||
#import "RTCVideoCodec+Private.h"
|
||||
#import "WebRTC/RTCVideoCodec.h"
|
||||
#import "WebRTC/RTCVideoCodecFactory.h"
|
||||
#import "WebRTC/RTCVideoCodecH264.h"
|
||||
#import "WebRTC/RTCVideoFrame.h"
|
||||
#import "WebRTC/RTCVideoFrameBuffer.h"
|
||||
|
||||
#include "webrtc/api/video/video_frame.h"
|
||||
#include "webrtc/api/video_codecs/video_encoder.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||
#include "webrtc/modules/video_coding/include/video_error_codes.h"
|
||||
#include "webrtc/rtc_base/logging.h"
|
||||
#include "webrtc/rtc_base/timeutils.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/Common/helpers.h"
|
||||
#include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
class ObjCVideoEncoder : public VideoEncoder {
|
||||
public:
|
||||
ObjCVideoEncoder(id<RTCVideoEncoder> encoder) : encoder_(encoder) {}
|
||||
~ObjCVideoEncoder() {}
|
||||
|
||||
int32_t InitEncode(const VideoCodec *codec_settings,
|
||||
int32_t number_of_cores,
|
||||
size_t max_payload_size) {
|
||||
RTCVideoEncoderSettings *settings =
|
||||
[[RTCVideoEncoderSettings alloc] initWithVideoCodec:codec_settings];
|
||||
return [encoder_ initEncodeWithSettings:settings numberOfCores:number_of_cores];
|
||||
}
|
||||
|
||||
int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) {
|
||||
[encoder_ setCallback:^(RTCEncodedImage *frame,
|
||||
id<RTCCodecSpecificInfo> info,
|
||||
RTCRtpFragmentationHeader *header) {
|
||||
EncodedImage encodedImage = [frame toCpp];
|
||||
|
||||
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded
|
||||
// cases.
|
||||
CodecSpecificInfo codecSpecificInfo;
|
||||
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
|
||||
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info toCpp];
|
||||
}
|
||||
|
||||
RTPFragmentationHeader *fragmentationHeader = [header toCpp];
|
||||
callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader);
|
||||
}];
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t Release() { return [encoder_ releaseEncode]; }
|
||||
|
||||
int32_t Encode(const VideoFrame &frame,
|
||||
const CodecSpecificInfo *codec_specific_info,
|
||||
const std::vector<FrameType> *frame_types) {
|
||||
RTC_CHECK(frame.video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative);
|
||||
|
||||
id<RTCVideoFrameBuffer> frame_buffer =
|
||||
static_cast<ObjCFrameBuffer *>(frame.video_frame_buffer().get())->wrapped_frame_buffer();
|
||||
RTCVideoFrame *rtcFrame =
|
||||
[[RTCVideoFrame alloc] initWithBuffer:frame_buffer
|
||||
rotation:RTCVideoRotation(frame.rotation())
|
||||
timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
|
||||
rtcFrame.timeStamp = frame.timestamp();
|
||||
|
||||
// webrtc::CodecSpecificInfo only handles a hard coded list of codecs
|
||||
id<RTCCodecSpecificInfo> rtcCodecSpecificInfo = nil;
|
||||
if (codec_specific_info) {
|
||||
if (strcmp(codec_specific_info->codec_name, "H264") == 0) {
|
||||
RTCCodecSpecificInfoH264 *h264Info = [[RTCCodecSpecificInfoH264 alloc] init];
|
||||
h264Info.packetizationMode =
|
||||
(RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packetization_mode;
|
||||
rtcCodecSpecificInfo = h264Info;
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableArray<NSNumber *> *rtcFrameTypes = [NSMutableArray array];
|
||||
for (size_t i = 0; i < frame_types->size(); ++i) {
|
||||
[rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
|
||||
}
|
||||
|
||||
return
|
||||
[encoder_ encode:rtcFrame codecSpecificInfo:rtcCodecSpecificInfo frameTypes:rtcFrameTypes];
|
||||
}
|
||||
|
||||
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) { return WEBRTC_VIDEO_CODEC_OK; }
|
||||
|
||||
int32_t SetRates(uint32_t bitrate, uint32_t framerate) {
|
||||
if ([encoder_ setBitrate:bitrate framerate:framerate]) {
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
} else {
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
bool SupportsNativeHandle() const { return true; }
|
||||
|
||||
private:
|
||||
id<RTCVideoEncoder> encoder_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ObjCVideoEncoderFactory::ObjCVideoEncoderFactory(id<RTCVideoEncoderFactory> encoder_factory)
|
||||
: encoder_factory_(encoder_factory) {}
|
||||
|
||||
ObjCVideoEncoderFactory::~ObjCVideoEncoderFactory() {}
|
||||
|
||||
id<RTCVideoEncoderFactory> ObjCVideoEncoderFactory::wrapped_encoder_factory() const {
|
||||
return encoder_factory_;
|
||||
}
|
||||
|
||||
webrtc::VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(
|
||||
const cricket::VideoCodec &codec) {
|
||||
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithVideoCodec:codec];
|
||||
id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
|
||||
return new ObjCVideoEncoder(encoder);
|
||||
}
|
||||
|
||||
const std::vector<cricket::VideoCodec> &ObjCVideoEncoderFactory::supported_codecs() const {
|
||||
supported_codecs_.clear();
|
||||
for (RTCVideoCodecInfo *supportedCodec in encoder_factory_.supportedCodecs) {
|
||||
cricket::VideoCodec codec = [supportedCodec toCpp];
|
||||
supported_codecs_.push_back(codec);
|
||||
}
|
||||
|
||||
return supported_codecs_;
|
||||
}
|
||||
|
||||
void ObjCVideoEncoderFactory::DestroyVideoEncoder(webrtc::VideoEncoder *encoder) {
|
||||
delete encoder;
|
||||
encoder = nullptr;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
Reference in New Issue
Block a user