Injectable software video codecs in Obj-C.

When injecting video codec factories in the Obj-C SDK, use the new
peer connection API that uses webrtc::Video{De,En}CoderFactory classes
and does not automatically add internal software codecs. Instead the
injected factory can support internal VP8 and VP9 codecs through the
included Obj-C classes RTCVideo{De,En}coderVP{8,9}.

When not explicitly injecting any video codec factory, the old code
path is still used and injects only H264 as an external codec and
the internal codec factory is used.

Bug: webrtc:7925
Change-Id: I657d30dfde71da9c0be341e213ab9f97a04caa58
Reviewed-on: https://webrtc-review.googlesource.com/3620
Commit-Queue: Anders Carlsson <andersc@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20175}
This commit is contained in:
Anders Carlsson
2017-10-05 16:55:38 +02:00
committed by Commit Bot
parent c522298e03
commit 7e04281870
35 changed files with 856 additions and 133 deletions

View File

@ -233,6 +233,10 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
"objc/AppRTCMobile/ARDTURNClient+Internal.h",
"objc/AppRTCMobile/ARDTURNClient.h",
"objc/AppRTCMobile/ARDTURNClient.m",
"objc/AppRTCMobile/ARDVideoDecoderFactory.h",
"objc/AppRTCMobile/ARDVideoDecoderFactory.m",
"objc/AppRTCMobile/ARDVideoEncoderFactory.h",
"objc/AppRTCMobile/ARDVideoEncoderFactory.m",
"objc/AppRTCMobile/ARDWebSocketChannel.h",
"objc/AppRTCMobile/ARDWebSocketChannel.m",
"objc/AppRTCMobile/RTCIceCandidate+JSON.h",

View File

@ -32,6 +32,8 @@
#import "ARDSignalingMessage.h"
#import "ARDTURNClient+Internal.h"
#import "ARDUtilities.h"
#import "ARDVideoDecoderFactory.h"
#import "ARDVideoEncoderFactory.h"
#import "ARDWebSocketChannel.h"
#import "RTCIceCandidate+JSON.h"
#import "RTCSessionDescription+JSON.h"
@ -163,7 +165,10 @@ static int const kKbpsMultiplier = 1000;
}
- (void)configure {
_factory = [[RTCPeerConnectionFactory alloc] init];
ARDVideoDecoderFactory *decoderFactory = [[ARDVideoDecoderFactory alloc] init];
ARDVideoEncoderFactory *encoderFactory = [[ARDVideoEncoderFactory alloc] init];
_factory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
decoderFactory:decoderFactory];
_messageQueue = [NSMutableArray array];
_iceServers = [NSMutableArray array];
_fileLogger = [[RTCFileLogger alloc] init];

View File

@ -0,0 +1,16 @@
/*
* 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 <Foundation/Foundation.h>
#import "WebRTC/RTCVideoCodecFactory.h"
@interface ARDVideoDecoderFactory : NSObject<RTCVideoDecoderFactory>
@end

View File

@ -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.
*/
#import "ARDVideoDecoderFactory.h"
#import "WebRTC/RTCVideoCodecH264.h"
#import "WebRTC/RTCVideoDecoderVP8.h"
#import "WebRTC/RTCVideoDecoderVP9.h"
@implementation ARDVideoDecoderFactory
- (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info {
if ([info.name isEqualToString:@"H264"]) {
return [[RTCVideoDecoderH264 alloc] init];
} else if ([info.name isEqualToString:@"VP8"]) {
return [RTCVideoDecoderVP8 vp8Decoder];
} else if ([info.name isEqualToString:@"VP9"]) {
return [RTCVideoDecoderVP9 vp9Decoder];
}
return nil;
}
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
return @[
[[RTCVideoCodecInfo alloc] initWithName:@"H264" parameters:nil],
[[RTCVideoCodecInfo alloc] initWithName:@"VP8" parameters:nil],
[[RTCVideoCodecInfo alloc] initWithName:@"VP9" parameters:nil]
];
}
@end

View File

@ -0,0 +1,16 @@
/*
* 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 <Foundation/Foundation.h>
#import "WebRTC/RTCVideoCodecFactory.h"
@interface ARDVideoEncoderFactory : NSObject<RTCVideoEncoderFactory>
@end

View File

@ -0,0 +1,64 @@
/*
* 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 "ARDVideoEncoderFactory.h"
#import "WebRTC/RTCVideoCodecH264.h"
#import "WebRTC/RTCVideoEncoderVP8.h"
#import "WebRTC/RTCVideoEncoderVP9.h"
static NSString *kLevel31ConstrainedHigh = @"640c1f";
static NSString *kLevel31ConstrainedBaseline = @"42e01f";
@implementation ARDVideoEncoderFactory
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
if ([info.name isEqualToString:@"H264"]) {
return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
} else if ([info.name isEqualToString:@"VP8"]) {
return [RTCVideoEncoderVP8 vp8Encoder];
} else if ([info.name isEqualToString:@"VP9"]) {
return [RTCVideoEncoderVP9 vp9Encoder];
}
return nil;
}
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];
NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
@"profile-level-id" : kLevel31ConstrainedHigh,
@"level-asymmetry-allowed" : @"1",
@"packetization-mode" : @"1",
};
RTCVideoCodecInfo *constrainedHighInfo =
[[RTCVideoCodecInfo alloc] initWithName:@"H264" parameters:constrainedHighParams];
[codecs addObject:constrainedHighInfo];
NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
@"profile-level-id" : kLevel31ConstrainedBaseline,
@"level-asymmetry-allowed" : @"1",
@"packetization-mode" : @"1",
};
RTCVideoCodecInfo *constrainedBaselineInfo =
[[RTCVideoCodecInfo alloc] initWithName:@"H264" parameters:constrainedBaselineParams];
[codecs addObject:constrainedBaselineInfo];
RTCVideoCodecInfo *vp8Info = [[RTCVideoCodecInfo alloc] initWithName:@"VP8" parameters:nil];
[codecs addObject:vp8Info];
RTCVideoCodecInfo *vp9Info = [[RTCVideoCodecInfo alloc] initWithName:@"VP9" parameters:nil];
[codecs addObject:vp9Info];
return [codecs copy];
}
@end

View File

@ -434,7 +434,10 @@ if (is_ios || is_mac) {
"objc/Framework/Classes/PeerConnection/RTCVideoCapturer.m",
"objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h",
"objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoCodecVP8.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoFrame+Private.h",
"objc/Framework/Classes/PeerConnection/RTCVideoFrame.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter+Private.h",
"objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.h",
@ -443,6 +446,10 @@ if (is_ios || is_mac) {
"objc/Framework/Classes/PeerConnection/RTCVideoSource.mm",
"objc/Framework/Classes/PeerConnection/RTCVideoTrack+Private.h",
"objc/Framework/Classes/PeerConnection/RTCVideoTrack.mm",
"objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h",
"objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm",
"objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h",
"objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm",
"objc/Framework/Headers/WebRTC/RTCAVFoundationVideoSource.h",
"objc/Framework/Headers/WebRTC/RTCAudioSource.h",
"objc/Framework/Headers/WebRTC/RTCAudioTrack.h",
@ -493,9 +500,12 @@ if (is_ios || is_mac) {
":corevideoframebuffer_objc",
":videotracksource_objc",
"../api:video_frame_api",
"../api/video_codecs:video_codecs_api",
"../common_video",
"../media:rtc_media_base",
"../modules:module_api",
"../modules/video_coding:webrtc_vp8",
"../modules/video_coding:webrtc_vp9",
"../pc:peerconnection",
"../rtc_base:rtc_base",
]
@ -621,6 +631,11 @@ if (is_ios || is_mac) {
"objc/Framework/Headers/WebRTC/RTCSessionDescription.h",
"objc/Framework/Headers/WebRTC/RTCTracing.h",
"objc/Framework/Headers/WebRTC/RTCVideoCapturer.h",
"objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h",
"objc/Framework/Headers/WebRTC/RTCVideoDecoderVP8.h",
"objc/Framework/Headers/WebRTC/RTCVideoDecoderVP9.h",
"objc/Framework/Headers/WebRTC/RTCVideoEncoderVP8.h",
"objc/Framework/Headers/WebRTC/RTCVideoEncoderVP9.h",
"objc/Framework/Headers/WebRTC/RTCVideoFrame.h",
"objc/Framework/Headers/WebRTC/RTCVideoFrameBuffer.h",
"objc/Framework/Headers/WebRTC/RTCVideoRenderer.h",
@ -628,7 +643,6 @@ if (is_ios || is_mac) {
"objc/Framework/Headers/WebRTC/RTCVideoTrack.h",
"objc/Framework/Headers/WebRTC/RTCVideoViewShading.h",
"objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h",
"objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h",
"objc/Framework/Headers/WebRTC/WebRTC.h",
]
if (rtc_use_metal_rendering) {

View File

@ -15,4 +15,6 @@ include_rules = [
"+modules/video_coding",
"+pc",
"+system_wrappers",
]
"+modules/audio_device",
"+modules/audio_processing",
]

View File

@ -16,6 +16,8 @@ namespace webrtc {
class AudioEncoderFactory;
class AudioDecoderFactory;
class VideoEncoderFactory;
class VideoDecoderFactory;
} // namespace webrtc
@ -33,16 +35,31 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface RTCPeerConnectionFactory ()
- (instancetype)initNative NS_DESIGNATED_INITIALIZER;
/* Initializer used when WebRTC is compiled with no media support */
- (instancetype)initWithNoMedia;
/* Initialize object with injectable native audio/video encoder/decoder factories */
- (instancetype)initWithNativeAudioEncoderFactory:
(rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory
nativeAudioDecoderFactory:
(rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory
nativeVideoEncoderFactory:
(nullable cricket::WebRtcVideoEncoderFactory *)videoEncoderFactory
(std::unique_ptr<webrtc::VideoEncoderFactory>)videoEncoderFactory
nativeVideoDecoderFactory:
(nullable cricket::WebRtcVideoDecoderFactory *)videoDecoderFactory
NS_DESIGNATED_INITIALIZER;
(std::unique_ptr<webrtc::VideoDecoderFactory>)videoDecoderFactory;
/* Initialize object with legacy injectable native audio/video encoder/decoder factories
TODO(andersc): Remove this when backwards compatiblity is no longer needed.
*/
- (instancetype)
initWithNativeAudioEncoderFactory:
(rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory
nativeAudioDecoderFactory:
(rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory
legacyNativeVideoEncoderFactory:(cricket::WebRtcVideoEncoderFactory*)videoEncoderFactory
legacyNativeVideoDecoderFactory:(cricket::WebRtcVideoDecoderFactory*)videoDecoderFactory;
@end

View File

@ -28,8 +28,10 @@
#import "WebRTC/RTCVideoCodecH264.h"
// The no-media version PeerConnectionFactory doesn't depend on these files, but the gn check tool
// is not smart enough to take the #ifdef into account.
#include "api/audio_codecs/builtin_audio_decoder_factory.h" // nogncheck
#include "api/audio_codecs/builtin_audio_encoder_factory.h" // nogncheck
#include "api/audio_codecs/builtin_audio_decoder_factory.h" // nogncheck
#include "api/audio_codecs/builtin_audio_encoder_factory.h" // nogncheck
#include "modules/audio_device/include/audio_device.h" // nogncheck
#include "modules/audio_processing/include/audio_processing.h" // nogncheck
#endif
#include "Video/objcvideotracksource.h"
@ -52,16 +54,13 @@
- (instancetype)init {
#ifdef HAVE_NO_MEDIA
return [self initWithNativeAudioEncoderFactory:nil
nativeAudioDecoderFactory:nil
nativeVideoEncoderFactory:nil
nativeVideoDecoderFactory:nil];
return [self initWithNoMedia];
#else
return [self initWithNativeAudioEncoderFactory:webrtc::CreateBuiltinAudioEncoderFactory()
nativeAudioDecoderFactory:webrtc::CreateBuiltinAudioDecoderFactory()
nativeVideoEncoderFactory:new webrtc::ObjCVideoEncoderFactory(
legacyNativeVideoEncoderFactory:new webrtc::ObjCVideoEncoderFactory(
[[RTCVideoEncoderFactoryH264 alloc] init])
nativeVideoDecoderFactory:new webrtc::ObjCVideoDecoderFactory(
legacyNativeVideoDecoderFactory:new webrtc::ObjCVideoDecoderFactory(
[[RTCVideoDecoderFactoryH264 alloc] init])];
#endif
}
@ -69,30 +68,24 @@
- (instancetype)initWithEncoderFactory:(nullable id<RTCVideoEncoderFactory>)encoderFactory
decoderFactory:(nullable id<RTCVideoDecoderFactory>)decoderFactory {
#ifdef HAVE_NO_MEDIA
return [self initWithNativeAudioEncoderFactory:nil
nativeAudioDecoderFactory:nil
nativeVideoEncoderFactory:nil
nativeVideoDecoderFactory:nil];
return [self initWithNoMedia];
#else
cricket::WebRtcVideoEncoderFactory *native_encoder_factory =
encoderFactory ? new webrtc::ObjCVideoEncoderFactory(encoderFactory) : nullptr;
cricket::WebRtcVideoDecoderFactory *native_decoder_factory =
decoderFactory ? new webrtc::ObjCVideoDecoderFactory(decoderFactory) : nullptr;
std::unique_ptr<webrtc::VideoEncoderFactory> native_encoder_factory;
std::unique_ptr<webrtc::VideoDecoderFactory> native_decoder_factory;
if (encoderFactory) {
native_encoder_factory.reset(new webrtc::ObjCVideoEncoderFactory(encoderFactory));
}
if (decoderFactory) {
native_decoder_factory.reset(new webrtc::ObjCVideoDecoderFactory(decoderFactory));
}
return [self initWithNativeAudioEncoderFactory:webrtc::CreateBuiltinAudioEncoderFactory()
nativeAudioDecoderFactory:webrtc::CreateBuiltinAudioDecoderFactory()
nativeVideoEncoderFactory:native_encoder_factory
nativeVideoDecoderFactory:native_decoder_factory];
nativeVideoEncoderFactory:std::move(native_encoder_factory)
nativeVideoDecoderFactory:std::move(native_decoder_factory)];
#endif
}
- (instancetype)initWithNativeAudioEncoderFactory:
(rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory
nativeAudioDecoderFactory:
(rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory
nativeVideoEncoderFactory:
(nullable cricket::WebRtcVideoEncoderFactory *)videoEncoderFactory
nativeVideoDecoderFactory:
(nullable cricket::WebRtcVideoDecoderFactory *)videoDecoderFactory {
- (instancetype)initNative {
if (self = [super init]) {
_networkThread = rtc::Thread::CreateWithSocketServer();
BOOL result = _networkThread->Start();
@ -105,7 +98,12 @@
_signalingThread = rtc::Thread::Create();
result = _signalingThread->Start();
NSAssert(result, @"Failed to start signaling thread.");
#ifdef HAVE_NO_MEDIA
}
return self;
}
- (instancetype)initWithNoMedia {
if (self = [self initNative]) {
_nativeFactory = webrtc::CreateModularPeerConnectionFactory(
_networkThread.get(),
_workerThread.get(),
@ -113,9 +111,51 @@
std::unique_ptr<cricket::MediaEngineInterface>(),
std::unique_ptr<webrtc::CallFactoryInterface>(),
std::unique_ptr<webrtc::RtcEventLogFactoryInterface>());
NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!");
}
return self;
}
- (instancetype)initWithNativeAudioEncoderFactory:
(rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory
nativeAudioDecoderFactory:
(rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory
nativeVideoEncoderFactory:
(std::unique_ptr<webrtc::VideoEncoderFactory>)videoEncoderFactory
nativeVideoDecoderFactory:
(std::unique_ptr<webrtc::VideoDecoderFactory>)videoDecoderFactory {
#ifdef HAVE_NO_MEDIA
return [self initWithNoMedia];
#else
// Ownership of encoder/decoder factories is passed on to the
// peerconnectionfactory, that handles deleting them.
if (self = [self initNative]) {
_nativeFactory = webrtc::CreatePeerConnectionFactory(_networkThread.get(),
_workerThread.get(),
_signalingThread.get(),
nullptr, // audio device module
audioEncoderFactory,
audioDecoderFactory,
std::move(videoEncoderFactory),
std::move(videoDecoderFactory),
nullptr, // audio mixer
nullptr // audio processing
);
NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!");
}
return self;
#endif
}
- (instancetype)
initWithNativeAudioEncoderFactory:
(rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory
nativeAudioDecoderFactory:
(rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory
legacyNativeVideoEncoderFactory:(cricket::WebRtcVideoEncoderFactory *)videoEncoderFactory
legacyNativeVideoDecoderFactory:(cricket::WebRtcVideoDecoderFactory *)videoDecoderFactory {
#ifdef HAVE_NO_MEDIA
return [self initWithNoMedia];
#else
if (self = [self initNative]) {
_nativeFactory = webrtc::CreatePeerConnectionFactory(_networkThread.get(),
_workerThread.get(),
_signalingThread.get(),
@ -124,10 +164,10 @@
audioDecoderFactory,
videoEncoderFactory,
videoDecoderFactory);
#endif
NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!");
}
return self;
#endif
}
- (RTCAudioSource *)audioSourceWithConstraints:(nullable RTCMediaConstraints *)constraints {

View File

@ -12,6 +12,7 @@
#import "WebRTC/RTCVideoCodecH264.h"
#include "api/video_codecs/sdp_video_format.h"
#include "common_video/include/video_frame.h"
#include "media/base/codec.h"
#include "modules/video_coding/include/video_codec_interface.h"
@ -29,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface RTCVideoEncoderSettings ()
- (instancetype)initWithNativeVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec;
- (webrtc::VideoCodec)nativeVideoCodec;
@end
@ -48,10 +50,11 @@ NS_ASSUME_NONNULL_BEGIN
@interface RTCVideoCodecInfo ()
- (instancetype)initWithNativeSdpVideoFormat:(webrtc::SdpVideoFormat)format;
- (webrtc::SdpVideoFormat)nativeSdpVideoFormat;
/* TODO(andersc): These are deprecated, remove when no longer in use. */
- (instancetype)initWithNativeVideoCodec:(cricket::VideoCodec)videoCodec;
- (instancetype)initWithPayload:(NSInteger)payload
name:(NSString *)name
parameters:(NSDictionary<NSString *, NSString *> *)parameters;
- (cricket::VideoCodec)nativeVideoCodec;
@end

View File

@ -16,7 +16,6 @@
@implementation RTCVideoCodecInfo
@synthesize payload = _payload;
@synthesize name = _name;
@synthesize parameters = _parameters;
@ -27,7 +26,6 @@
- (instancetype)initWithName:(NSString *)name
parameters:(nullable NSDictionary<NSString *, NSString *> *)parameters {
if (self = [super init]) {
_payload = 0;
_name = name;
_parameters = (parameters ? parameters : @{});
}
@ -35,40 +33,22 @@
return self;
}
- (instancetype)initWithNativeVideoCodec:(cricket::VideoCodec)videoCodec {
- (instancetype)initWithNativeSdpVideoFormat:(webrtc::SdpVideoFormat)format {
NSMutableDictionary *params = [NSMutableDictionary dictionary];
for (auto it = videoCodec.params.begin(); it != videoCodec.params.end(); ++it) {
for (auto it = format.parameters.begin(); it != format.parameters.end(); ++it) {
[params setObject:[NSString stringForStdString:it->second]
forKey:[NSString stringForStdString:it->first]];
}
return [self initWithPayload:videoCodec.id
name:[NSString stringForStdString:videoCodec.name]
parameters:params];
return [self initWithName:[NSString stringForStdString:format.name] parameters:params];
}
- (instancetype)initWithPayload:(NSInteger)payload
name:(NSString *)name
parameters:(NSDictionary<NSString *, NSString *> *)parameters {
if (self = [self initWithName:name parameters:parameters]) {
_payload = payload;
}
return self;
}
- (cricket::VideoCodec)nativeVideoCodec {
cricket::VideoCodec codec([NSString stdStringForString:_name]);
for (NSString *paramKey in _parameters.allKeys) {
codec.SetParam([NSString stdStringForString:paramKey],
[NSString stdStringForString:_parameters[paramKey]]);
}
return codec;
- (instancetype)initWithNativeVideoCodec:(cricket::VideoCodec)videoCodec {
return [self
initWithNativeSdpVideoFormat:webrtc::SdpVideoFormat(videoCodec.name, videoCodec.params)];
}
- (BOOL)isEqualToCodecInfo:(RTCVideoCodecInfo *)info {
if (!info ||
self.payload != info.payload ||
![self.name isEqualToString:info.name] ||
![self.parameters isEqualToDictionary:info.parameters]) {
return NO;
@ -85,7 +65,28 @@
}
- (NSUInteger)hash {
return [self.name hash] ^ self.payload ^ [self.parameters hash];
return [self.name hash] ^ [self.parameters hash];
}
- (webrtc::SdpVideoFormat)nativeSdpVideoFormat {
std::map<std::string, std::string> parameters;
for (NSString *paramKey in _parameters.allKeys) {
std::string key = [NSString stdStringForString:paramKey];
std::string value = [NSString stdStringForString:_parameters[paramKey]];
parameters[key] = value;
}
return webrtc::SdpVideoFormat([NSString stdStringForString:_name], parameters);
}
- (cricket::VideoCodec)nativeVideoCodec {
cricket::VideoCodec codec([NSString stdStringForString:_name]);
for (NSString *paramKey in _parameters.allKeys) {
codec.SetParam([NSString stdStringForString:paramKey],
[NSString stdStringForString:_parameters[paramKey]]);
}
return codec;
}
@end

View File

@ -20,6 +20,7 @@
#include "system_wrappers/include/field_trial.h"
const char kHighProfileExperiment[] = "WebRTC-H264HighProfile";
static NSString *kH264CodecName = @"H264";
static NSString *kLevel31ConstrainedHigh = @"640c1f";
static NSString *kLevel31ConstrainedBaseline = @"42e01f";
@ -35,7 +36,7 @@ bool IsHighProfileEnabled() {
- (webrtc::CodecSpecificInfo)nativeCodecSpecificInfo {
webrtc::CodecSpecificInfo codecSpecificInfo;
codecSpecificInfo.codecType = webrtc::kVideoCodecH264;
codecSpecificInfo.codec_name = "H264";
codecSpecificInfo.codec_name = [kH264CodecName cStringUsingEncoding:NSUTF8StringEncoding];
codecSpecificInfo.codecSpecific.H264.packetization_mode =
(webrtc::H264PacketizationMode)_packetizationMode;
@ -49,7 +50,7 @@ bool IsHighProfileEnabled() {
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
NSString *codecName = kH264CodecName;
if (IsHighProfileEnabled()) {
NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
@ -88,7 +89,7 @@ bool IsHighProfileEnabled() {
}
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
NSString *codecName = kH264CodecName;
return @[ [[RTCVideoCodecInfo alloc] initWithName:codecName parameters:nil] ];
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "RTCWrappedNativeVideoDecoder.h"
#import "RTCWrappedNativeVideoEncoder.h"
#import "WebRTC/RTCVideoDecoderVP8.h"
#import "WebRTC/RTCVideoEncoderVP8.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#pragma mark - Encoder
@implementation RTCVideoEncoderVP8
+ (id<RTCVideoEncoder>)vp8Encoder {
return [[RTCWrappedNativeVideoEncoder alloc]
initWithNativeEncoder:std::unique_ptr<webrtc::VideoEncoder>(webrtc::VP8Encoder::Create())];
}
@end
#pragma mark - Decoder
@implementation RTCVideoDecoderVP8
+ (id<RTCVideoDecoder>)vp8Decoder {
return [[RTCWrappedNativeVideoDecoder alloc]
initWithNativeDecoder:std::unique_ptr<webrtc::VideoDecoder>(webrtc::VP8Decoder::Create())];
}
@end

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "RTCWrappedNativeVideoDecoder.h"
#import "RTCWrappedNativeVideoEncoder.h"
#import "WebRTC/RTCVideoDecoderVP9.h"
#import "WebRTC/RTCVideoEncoderVP9.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#pragma mark - Encoder
@implementation RTCVideoEncoderVP9
+ (id<RTCVideoEncoder>)vp9Encoder {
return [[RTCWrappedNativeVideoEncoder alloc]
initWithNativeEncoder:std::unique_ptr<webrtc::VideoEncoder>(webrtc::VP9Encoder::Create())];
}
@end
#pragma mark - Decoder
@implementation RTCVideoDecoderVP9
+ (id<RTCVideoDecoder>)vp9Decoder {
return [[RTCWrappedNativeVideoDecoder alloc]
initWithNativeDecoder:std::unique_ptr<webrtc::VideoDecoder>(webrtc::VP9Decoder::Create())];
}
@end

View File

@ -48,4 +48,19 @@
return self;
}
- (webrtc::VideoCodec)nativeVideoCodec {
webrtc::VideoCodec videoCodec;
videoCodec.width = _width;
videoCodec.height = _height;
videoCodec.startBitrate = _startBitrate;
videoCodec.maxBitrate = _maxBitrate;
videoCodec.minBitrate = _minBitrate;
videoCodec.targetBitrate = _targetBitrate;
videoCodec.maxBitrate = _maxBitrate;
videoCodec.qpMax = _qpMax;
videoCodec.mode = (webrtc::VideoCodecMode)_mode;
return videoCodec;
}
@end

View File

@ -0,0 +1,27 @@
/*
* 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 "RTCI420Buffer+Private.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
#include "api/video/video_frame.h"
#include "sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
NS_ASSUME_NONNULL_BEGIN
@interface RTCVideoFrame ()
- (instancetype)initWithNativeVideoFrame:(const webrtc::VideoFrame &)frame;
- (webrtc::VideoFrame)nativeVideoFrame;
@end
NS_ASSUME_NONNULL_END

View File

@ -8,9 +8,21 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#import "RTCVideoFrame+Private.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
#include "api/video/video_frame.h"
#include "rtc_base/timeutils.h"
id<RTCVideoFrameBuffer> nativeToRtcFrameBuffer(
const rtc::scoped_refptr<webrtc::VideoFrameBuffer> &buffer) {
return buffer->type() == webrtc::VideoFrameBuffer::Type::kNative ?
static_cast<webrtc::ObjCFrameBuffer *>(buffer.get())->wrapped_frame_buffer() :
[[RTCI420Buffer alloc] initWithFrameBuffer:buffer->ToI420()];
}
@implementation RTCVideoFrame {
RTCVideoRotation _rotation;
int64_t _timeStampNs;
@ -80,4 +92,24 @@
return self;
}
- (instancetype)initWithNativeVideoFrame:(const webrtc::VideoFrame &)frame {
if (self = [self initWithBuffer:nativeToRtcFrameBuffer(frame.video_frame_buffer())
rotation:RTCVideoRotation(frame.rotation())
timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec]) {
self.timeStamp = frame.timestamp();
}
return self;
}
- (webrtc::VideoFrame)nativeVideoFrame {
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frameBuffer =
new rtc::RefCountedObject<webrtc::ObjCFrameBuffer>(self.buffer);
webrtc::VideoFrame videoFrame(frameBuffer,
(webrtc::VideoRotation)self.rotation,
self.timeStampNs / rtc::kNumNanosecsPerMicrosec);
videoFrame.set_timestamp(self.timeStamp);
return videoFrame;
}
@end

View File

@ -9,6 +9,7 @@
*/
#import "RTCI420Buffer+Private.h"
#import "RTCVideoFrame+Private.h"
#import "RTCVideoRendererAdapter+Private.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
@ -27,19 +28,7 @@ class VideoRendererAdapter
}
void OnFrame(const webrtc::VideoFrame& nativeVideoFrame) override {
rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer = nativeVideoFrame.video_frame_buffer();
id<RTCVideoFrameBuffer> rtc_frame_buffer;
if (video_frame_buffer->type() == VideoFrameBuffer::Type::kNative) {
rtc::scoped_refptr<ObjCFrameBuffer> objc_frame_buffer(
static_cast<ObjCFrameBuffer*>(video_frame_buffer.get()));
rtc_frame_buffer = (id<RTCVideoFrameBuffer>)objc_frame_buffer->wrapped_frame_buffer();
} else {
rtc_frame_buffer = [[RTCI420Buffer alloc] initWithFrameBuffer:video_frame_buffer->ToI420()];
}
RTCVideoFrame* videoFrame = [[RTCVideoFrame alloc]
initWithBuffer:rtc_frame_buffer
rotation:static_cast<RTCVideoRotation>(nativeVideoFrame.rotation())
timeStampNs:nativeVideoFrame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
RTCVideoFrame* videoFrame = [[RTCVideoFrame alloc] initWithNativeVideoFrame:nativeVideoFrame];
CGSize current_size = (videoFrame.rotation % 180 == 0)
? CGSizeMake(videoFrame.width, videoFrame.height)

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "WebRTC/RTCVideoCodec.h"
#include "api/video_codecs/video_decoder.h"
#include "media/base/codec.h"
@interface RTCWrappedNativeVideoDecoder : NSObject <RTCVideoDecoder>
- (instancetype)initWithNativeDecoder:(std::unique_ptr<webrtc::VideoDecoder>)decoder;
/* This moves the ownership of the wrapped decoder to the caller. */
- (std::unique_ptr<webrtc::VideoDecoder>)releaseWrappedDecoder;
@end

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "NSString+StdString.h"
#import "RTCWrappedNativeVideoDecoder.h"
@implementation RTCWrappedNativeVideoDecoder {
std::unique_ptr<webrtc::VideoDecoder> _wrappedDecoder;
}
- (instancetype)initWithNativeDecoder:(std::unique_ptr<webrtc::VideoDecoder>)decoder {
if (self = [super init]) {
_wrappedDecoder = std::move(decoder);
}
return self;
}
- (std::unique_ptr<webrtc::VideoDecoder>)releaseWrappedDecoder {
return std::move(_wrappedDecoder);
}
#pragma mark - RTCVideoDecoder
- (void)setCallback:(RTCVideoDecoderCallback)callback {
RTC_NOTREACHED();
}
- (NSInteger)startDecodeWithSettings:(RTCVideoEncoderSettings *)settings
numberOfCores:(int)numberOfCores {
RTC_NOTREACHED();
return 0;
}
- (NSInteger)releaseDecoder {
RTC_NOTREACHED();
return 0;
}
- (NSInteger)decode:(RTCEncodedImage *)encodedImage
missingFrames:(BOOL)missingFrames
fragmentationHeader:(RTCRtpFragmentationHeader *)fragmentationHeader
codecSpecificInfo:(__nullable id<RTCCodecSpecificInfo>)info
renderTimeMs:(int64_t)renderTimeMs {
RTC_NOTREACHED();
return 0;
}
- (NSString *)implementationName {
RTC_NOTREACHED();
return nil;
}
@end

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "WebRTC/RTCVideoCodec.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_encoder.h"
#include "media/base/codec.h"
@interface RTCWrappedNativeVideoEncoder : NSObject <RTCVideoEncoder>
- (instancetype)initWithNativeEncoder:(std::unique_ptr<webrtc::VideoEncoder>)encoder;
/* This moves the ownership of the wrapped encoder to the caller. */
- (std::unique_ptr<webrtc::VideoEncoder>)releaseWrappedEncoder;
@end

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 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 <Foundation/Foundation.h>
#import "NSString+StdString.h"
#import "RTCWrappedNativeVideoEncoder.h"
@implementation RTCWrappedNativeVideoEncoder {
std::unique_ptr<webrtc::VideoEncoder> _wrappedEncoder;
}
- (instancetype)initWithNativeEncoder:(std::unique_ptr<webrtc::VideoEncoder>)encoder {
if (self = [super init]) {
_wrappedEncoder = std::move(encoder);
}
return self;
}
- (std::unique_ptr<webrtc::VideoEncoder>)releaseWrappedEncoder {
return std::move(_wrappedEncoder);
}
#pragma mark - RTCVideoEncoder
- (void)setCallback:(RTCVideoEncoderCallback)callback {
RTC_NOTREACHED();
}
- (NSInteger)startEncodeWithSettings:(RTCVideoEncoderSettings *)settings
numberOfCores:(int)numberOfCores {
RTC_NOTREACHED();
return 0;
}
- (NSInteger)releaseEncoder {
RTC_NOTREACHED();
return 0;
}
- (NSInteger)encode:(RTCVideoFrame *)frame
codecSpecificInfo:(id<RTCCodecSpecificInfo>)info
frameTypes:(NSArray<NSNumber *> *)frameTypes {
RTC_NOTREACHED();
return 0;
}
- (int)setBitrate:(uint32_t)bitrateKbit framerate:(uint32_t)framerate {
RTC_NOTREACHED();
return 0;
}
- (NSString *)implementationName {
RTC_NOTREACHED();
return nil;
}
- (RTCVideoEncoderQpThresholds *)scalingSettings {
RTC_NOTREACHED();
return nil;
}
@end

View File

@ -169,9 +169,9 @@ void compressionOutputCallback(void *encoder,
// specific VideoToolbox profile for the specified level, AutoLevel will be
// returned. The user must initialize the encoder with a resolution and
// framerate conforming to the selected H264 level regardless.
CFStringRef ExtractProfile(const cricket::VideoCodec &codec) {
CFStringRef ExtractProfile(webrtc::SdpVideoFormat videoFormat) {
const rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id =
webrtc::H264::ParseSdpProfileLevelId(codec.params);
webrtc::H264::ParseSdpProfileLevelId(videoFormat.parameters);
RTC_DCHECK(profile_level_id);
switch (profile_level_id->profile) {
case webrtc::H264::kProfileConstrainedBaseline:
@ -302,7 +302,7 @@ CFStringRef ExtractProfile(const cricket::VideoCodec &codec) {
_bitrateAdjuster.reset(new webrtc::BitrateAdjuster(
webrtc::Clock::GetRealTimeClock(), .5, .95));
_packetizationMode = RTCH264PacketizationModeNonInterleaved;
_profile = ExtractProfile([codecInfo nativeVideoCodec]);
_profile = ExtractProfile([codecInfo nativeSdpVideoFormat]);
LOG(LS_INFO) << "Using profile " << CFStringToString(_profile);
RTC_CHECK([codecInfo.name isEqualToString:@"H264"]);

View File

@ -11,6 +11,7 @@
#ifndef SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_DECODER_FACTORY_H_
#define SDK_OBJC_FRAMEWORK_CLASSES_PEERCONNECTION_OBJC_VIDEO_DECODER_FACTORY_H_
#include "api/video_codecs/video_decoder_factory.h"
#include "media/base/codec.h"
#include "media/engine/webrtcvideodecoderfactory.h"
@ -18,22 +19,30 @@
namespace webrtc {
class ObjCVideoDecoderFactory : public cricket::WebRtcVideoDecoderFactory {
// TODO(andersc): Remove the inheritance from cricket::WebRtcVideoDecoderFactory
// when the legacy path in [RTCPeerConnectionFactory init] is no longer needed.
class ObjCVideoDecoderFactory : public VideoDecoderFactory,
public cricket::WebRtcVideoDecoderFactory {
public:
explicit ObjCVideoDecoderFactory(id<RTCVideoDecoderFactory>);
~ObjCVideoDecoderFactory();
id<RTCVideoDecoderFactory> wrapped_decoder_factory() const;
VideoDecoder* CreateVideoDecoderWithParams(
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
const SdpVideoFormat& format) override;
// Needed for WebRtcVideoDecoderFactory interface.
webrtc::VideoDecoder* CreateVideoDecoderWithParams(
const cricket::VideoCodec& codec,
cricket::VideoDecoderParams params) override;
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

View File

@ -12,12 +12,14 @@
#import "NSString+StdString.h"
#import "RTCVideoCodec+Private.h"
#import "RTCWrappedNativeVideoDecoder.h"
#import "WebRTC/RTCVideoCodec.h"
#import "WebRTC/RTCVideoCodecFactory.h"
#import "WebRTC/RTCVideoCodecH264.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "modules/include/module_common_types.h"
#include "modules/video_coding/include/video_codec_interface.h"
@ -103,19 +105,47 @@ id<RTCVideoDecoderFactory> ObjCVideoDecoderFactory::wrapped_decoder_factory() co
return decoder_factory_;
}
VideoDecoder *ObjCVideoDecoderFactory::CreateVideoDecoderWithParams(
const cricket::VideoCodec &codec, cricket::VideoDecoderParams params) {
NSString *codecName = [NSString stringWithUTF8String:codec.name.c_str()];
std::unique_ptr<VideoDecoder> ObjCVideoDecoderFactory::CreateVideoDecoder(
const SdpVideoFormat &format) {
NSString *codecName = [NSString stringWithUTF8String:format.name.c_str()];
for (RTCVideoCodecInfo *codecInfo in decoder_factory_.supportedCodecs) {
if ([codecName isEqualToString:codecInfo.name]) {
id<RTCVideoDecoder> decoder = [decoder_factory_ createDecoder:codecInfo];
return new ObjCVideoDecoder(decoder);
if ([decoder isKindOfClass:[RTCWrappedNativeVideoDecoder class]]) {
return [(RTCWrappedNativeVideoDecoder *)decoder releaseWrappedDecoder];
} else {
return std::unique_ptr<ObjCVideoDecoder>(new ObjCVideoDecoder(decoder));
}
}
}
return nullptr;
}
std::vector<SdpVideoFormat> ObjCVideoDecoderFactory::GetSupportedFormats() const {
std::vector<SdpVideoFormat> supported_formats;
for (RTCVideoCodecInfo *supportedCodec in decoder_factory_.supportedCodecs) {
SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat];
supported_formats.push_back(format);
}
return supported_formats;
}
// WebRtcVideoDecoderFactory
VideoDecoder *ObjCVideoDecoderFactory::CreateVideoDecoderWithParams(
const cricket::VideoCodec &codec, cricket::VideoDecoderParams params) {
return CreateVideoDecoder(SdpVideoFormat(codec.name, codec.params)).release();
}
VideoDecoder *ObjCVideoDecoderFactory::CreateVideoDecoder(VideoCodecType type) {
// This is implemented to avoid hiding an overloaded virtual function
RTC_NOTREACHED();
return nullptr;
}
void ObjCVideoDecoderFactory::DestroyVideoDecoder(VideoDecoder *decoder) {
delete decoder;
decoder = nullptr;

View File

@ -13,19 +13,29 @@
#import <Foundation/Foundation.h>
#include "api/video_codecs/video_encoder_factory.h"
#include "media/engine/webrtcvideoencoderfactory.h"
@protocol RTCVideoEncoderFactory;
namespace webrtc {
class ObjCVideoEncoderFactory : public cricket::WebRtcVideoEncoderFactory {
// TODO(andersc): Remove the inheritance from cricket::WebRtcVideoEncoderFactory
// when the legacy path in [RTCPeerConnectionFactory init] is no longer needed.
class ObjCVideoEncoderFactory : public VideoEncoderFactory,
public cricket::WebRtcVideoEncoderFactory {
public:
explicit ObjCVideoEncoderFactory(id<RTCVideoEncoderFactory>);
~ObjCVideoEncoderFactory();
id<RTCVideoEncoderFactory> wrapped_encoder_factory() const;
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
std::unique_ptr<VideoEncoder> CreateVideoEncoder(
const SdpVideoFormat& format) override;
CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
// Needed for WebRtcVideoEncoderFactory interface.
webrtc::VideoEncoder* CreateVideoEncoder(
const cricket::VideoCodec& codec) override;
const std::vector<cricket::VideoCodec>& supported_codecs() const override;
@ -33,6 +43,8 @@ class ObjCVideoEncoderFactory : public cricket::WebRtcVideoEncoderFactory {
private:
id<RTCVideoEncoderFactory> encoder_factory_;
// Needed for WebRtcVideoEncoderFactory interface.
mutable std::vector<cricket::VideoCodec> supported_codecs_;
};

View File

@ -15,6 +15,8 @@
#import "NSString+StdString.h"
#import "RTCI420Buffer+Private.h"
#import "RTCVideoCodec+Private.h"
#import "RTCVideoFrame+Private.h"
#import "RTCWrappedNativeVideoEncoder.h"
#import "WebRTC/RTCVideoCodec.h"
#import "WebRTC/RTCVideoCodecFactory.h"
#import "WebRTC/RTCVideoCodecH264.h"
@ -22,12 +24,12 @@
#import "WebRTC/RTCVideoFrameBuffer.h"
#include "api/video/video_frame.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_encoder.h"
#include "modules/include/module_common_types.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "sdk/objc/Framework/Classes/Common/helpers.h"
#include "sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
@ -35,21 +37,6 @@ namespace webrtc {
namespace {
id<RTCVideoFrameBuffer> nativeToRtcFrameBuffer(const rtc::scoped_refptr<VideoFrameBuffer> &buffer) {
return buffer->type() == VideoFrameBuffer::Type::kNative ?
static_cast<ObjCFrameBuffer *>(buffer.get())->wrapped_frame_buffer() :
[[RTCI420Buffer alloc] initWithFrameBuffer:buffer->ToI420()];
}
RTCVideoFrame *nativeToRtcFrame(const VideoFrame &frame) {
RTCVideoFrame *rtcFrame =
[[RTCVideoFrame alloc] initWithBuffer:nativeToRtcFrameBuffer(frame.video_frame_buffer())
rotation:RTCVideoRotation(frame.rotation())
timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
rtcFrame.timeStamp = frame.timestamp();
return rtcFrame;
}
class ObjCVideoEncoder : public VideoEncoder {
public:
ObjCVideoEncoder(id<RTCVideoEncoder> encoder)
@ -69,7 +56,7 @@ class ObjCVideoEncoder : public VideoEncoder {
RTCRtpFragmentationHeader *_Nonnull header) {
EncodedImage encodedImage = [frame nativeEncodedImage];
// Handle types than can be converted into one of CodecSpecificInfo's hard coded cases.
// Handle types that can be converted into one of CodecSpecificInfo's hard coded cases.
CodecSpecificInfo codecSpecificInfo;
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInfo];
@ -106,7 +93,7 @@ class ObjCVideoEncoder : public VideoEncoder {
[rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
}
return [encoder_ encode:nativeToRtcFrame(frame)
return [encoder_ encode:[[RTCVideoFrame alloc] initWithNativeVideoFrame:frame]
codecSpecificInfo:rtcCodecSpecificInfo
frameTypes:rtcFrameTypes];
}
@ -143,8 +130,44 @@ id<RTCVideoEncoderFactory> ObjCVideoEncoderFactory::wrapped_encoder_factory() co
return encoder_factory_;
}
std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetSupportedFormats() const {
std::vector<SdpVideoFormat> supported_formats;
for (RTCVideoCodecInfo *supportedCodec in encoder_factory_.supportedCodecs) {
SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat];
supported_formats.push_back(format);
}
return supported_formats;
}
VideoEncoderFactory::CodecInfo ObjCVideoEncoderFactory::QueryVideoEncoder(
const SdpVideoFormat &format) const {
// TODO(andersc): This is a hack until we figure out how this should be done properly.
NSString *formatName = [NSString stringForStdString:format.name];
NSSet *wrappedSoftwareFormats = [NSSet setWithObjects:@"VP8", @"VP9", nil];
CodecInfo codec_info;
codec_info.is_hardware_accelerated = ![wrappedSoftwareFormats containsObject:formatName];
codec_info.has_internal_source = false;
return codec_info;
}
std::unique_ptr<VideoEncoder> ObjCVideoEncoderFactory::CreateVideoEncoder(
const SdpVideoFormat &format) {
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeSdpVideoFormat:format];
id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
if ([encoder isKindOfClass:[RTCWrappedNativeVideoEncoder class]]) {
return [(RTCWrappedNativeVideoEncoder *)encoder releaseWrappedEncoder];
} else {
return std::unique_ptr<ObjCVideoEncoder>(new ObjCVideoEncoder(encoder));
}
}
// WebRtcVideoEncoderFactory
VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(const cricket::VideoCodec &codec) {
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeVideoCodec:codec];
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc]
initWithNativeSdpVideoFormat:SdpVideoFormat(codec.name, codec.params)];
id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
return new ObjCVideoEncoder(encoder);
}
@ -152,8 +175,8 @@ VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(const cricket::VideoCo
const std::vector<cricket::VideoCodec> &ObjCVideoEncoderFactory::supported_codecs() const {
supported_codecs_.clear();
for (RTCVideoCodecInfo *supportedCodec in encoder_factory_.supportedCodecs) {
cricket::VideoCodec codec = [supportedCodec nativeVideoCodec];
supported_codecs_.push_back(codec);
SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat];
supported_codecs_.push_back(cricket::VideoCodec(format));
}
return supported_codecs_;

View File

@ -69,19 +69,6 @@ RTC_EXPORT
@end
/** Class for H264 specific config. */
typedef NS_ENUM(NSUInteger, RTCH264PacketizationMode) {
RTCH264PacketizationModeNonInterleaved = 0, // Mode 1 - STAP-A, FU-A is allowed
RTCH264PacketizationModeSingleNalUnit // Mode 0 - only single NALU allowed
};
RTC_EXPORT
@interface RTCCodecSpecificInfoH264 : NSObject<RTCCodecSpecificInfo>
@property(nonatomic, assign) RTCH264PacketizationMode packetizationMode;
@end
/** Callback block for encoder. */
typedef BOOL (^RTCVideoEncoderCallback)(RTCEncodedImage *frame,
id<RTCCodecSpecificInfo> info,
@ -109,7 +96,6 @@ RTC_EXPORT
- (BOOL)isEqualToCodecInfo:(RTCVideoCodecInfo *)info;
@property(nonatomic, readonly) NSInteger payload;
@property(nonatomic, readonly) NSString *name;
@property(nonatomic, readonly) NSDictionary<NSString *, NSString *> *parameters;

View File

@ -15,21 +15,21 @@
NS_ASSUME_NONNULL_BEGIN
/** RTCVideoEncoderFactory is an Objective-C version of cricket::WebRtcVideoEncoderFactory. */
/** RTCVideoEncoderFactory is an Objective-C version of webrtc::VideoEncoderFactory. */
RTC_EXPORT
@protocol RTCVideoEncoderFactory <NSObject>
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info;
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs;
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs; // TODO(andersc): "supportedFormats" instead?
@end
/** RTCVideoDecoderFactory is an Objective-C version of cricket::WebRtcVideoDecoderFactory. */
/** RTCVideoDecoderFactory is an Objective-C version of webrtc::VideoDecoderFactory. */
RTC_EXPORT
@protocol RTCVideoDecoderFactory <NSObject>
- (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info;
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs;
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs; // TODO(andersc): "supportedFormats" instead?
@end

View File

@ -13,6 +13,19 @@
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCVideoCodecFactory.h>
/** Class for H264 specific config. */
typedef NS_ENUM(NSUInteger, RTCH264PacketizationMode) {
RTCH264PacketizationModeNonInterleaved = 0, // Mode 1 - STAP-A, FU-A is allowed
RTCH264PacketizationModeSingleNalUnit // Mode 0 - only single NALU allowed
};
RTC_EXPORT
@interface RTCCodecSpecificInfoH264 : NSObject <RTCCodecSpecificInfo>
@property(nonatomic, assign) RTCH264PacketizationMode packetizationMode;
@end
/** Encoder. */
RTC_EXPORT
@interface RTCVideoEncoderH264 : NSObject<RTCVideoEncoder>

View File

@ -0,0 +1,25 @@
/*
* 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 <Foundation/Foundation.h>
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCVideoCodec.h>
RTC_EXPORT
@interface RTCVideoDecoderVP8 : NSObject
/* This returns a VP8 decoder that can be returned from a RTCVideoDecoderFactory injected into
* RTCPeerConnectionFactory. Even though it implements the RTCVideoDecoder protocol, it can not be
* used independently from the RTCPeerConnectionFactory.
*/
+ (id<RTCVideoDecoder>)vp8Decoder;
@end

View File

@ -0,0 +1,25 @@
/*
* 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 <Foundation/Foundation.h>
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCVideoCodec.h>
RTC_EXPORT
@interface RTCVideoDecoderVP9 : NSObject
/* This returns a VP9 decoder that can be returned from a RTCVideoDecoderFactory injected into
* RTCPeerConnectionFactory. Even though it implements the RTCVideoDecoder protocol, it can not be
* used independently from the RTCPeerConnectionFactory.
*/
+ (id<RTCVideoDecoder>)vp9Decoder;
@end

View File

@ -0,0 +1,25 @@
/*
* 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 <Foundation/Foundation.h>
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCVideoCodec.h>
RTC_EXPORT
@interface RTCVideoEncoderVP8 : NSObject
/* This returns a VP8 encoder that can be returned from a RTCVideoEncoderFactory injected into
* RTCPeerConnectionFactory. Even though it implements the RTCVideoEncoder protocol, it can not be
* used independently from the RTCPeerConnectionFactory.
*/
+ (id<RTCVideoEncoder>)vp8Encoder;
@end

View File

@ -0,0 +1,25 @@
/*
* 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 <Foundation/Foundation.h>
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCVideoCodec.h>
RTC_EXPORT
@interface RTCVideoEncoderVP9 : NSObject
/* This returns a VP9 encoder that can be returned from a RTCVideoEncoderFactory injected into
* RTCPeerConnectionFactory. Even though it implements the RTCVideoEncoder protocol, it can not be
* used independently from the RTCPeerConnectionFactory.
*/
+ (id<RTCVideoEncoder>)vp9Encoder;
@end