diff --git a/examples/BUILD.gn b/examples/BUILD.gn index c976512b09..8f7ce889c8 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -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", diff --git a/examples/objc/AppRTCMobile/ARDAppClient.m b/examples/objc/AppRTCMobile/ARDAppClient.m index c699381842..2dfc617637 100644 --- a/examples/objc/AppRTCMobile/ARDAppClient.m +++ b/examples/objc/AppRTCMobile/ARDAppClient.m @@ -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]; diff --git a/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.h b/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.h new file mode 100644 index 0000000000..bc8be99214 --- /dev/null +++ b/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.h @@ -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 +#import "WebRTC/RTCVideoCodecFactory.h" + +@interface ARDVideoDecoderFactory : NSObject + +@end diff --git a/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.m b/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.m new file mode 100644 index 0000000000..172635ebb4 --- /dev/null +++ b/examples/objc/AppRTCMobile/ARDVideoDecoderFactory.m @@ -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)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 *)supportedCodecs { + return @[ + [[RTCVideoCodecInfo alloc] initWithName:@"H264" parameters:nil], + [[RTCVideoCodecInfo alloc] initWithName:@"VP8" parameters:nil], + [[RTCVideoCodecInfo alloc] initWithName:@"VP9" parameters:nil] + ]; +} + +@end diff --git a/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.h b/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.h new file mode 100644 index 0000000000..9927ce4161 --- /dev/null +++ b/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.h @@ -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 +#import "WebRTC/RTCVideoCodecFactory.h" + +@interface ARDVideoEncoderFactory : NSObject + +@end diff --git a/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.m b/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.m new file mode 100644 index 0000000000..a895011a72 --- /dev/null +++ b/examples/objc/AppRTCMobile/ARDVideoEncoderFactory.m @@ -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)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 *)supportedCodecs { + NSMutableArray *codecs = [NSMutableArray array]; + + NSDictionary *constrainedHighParams = @{ + @"profile-level-id" : kLevel31ConstrainedHigh, + @"level-asymmetry-allowed" : @"1", + @"packetization-mode" : @"1", + }; + RTCVideoCodecInfo *constrainedHighInfo = + [[RTCVideoCodecInfo alloc] initWithName:@"H264" parameters:constrainedHighParams]; + [codecs addObject:constrainedHighInfo]; + + NSDictionary *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 diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index e24ae4acdc..ffc1e8da03 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -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) { diff --git a/sdk/objc/DEPS b/sdk/objc/DEPS index 634cabeee0..d0a5c328c1 100644 --- a/sdk/objc/DEPS +++ b/sdk/objc/DEPS @@ -15,4 +15,6 @@ include_rules = [ "+modules/video_coding", "+pc", "+system_wrappers", -] \ No newline at end of file + "+modules/audio_device", + "+modules/audio_processing", +] diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h index a4122de96f..5763151087 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h @@ -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)audioEncoderFactory nativeAudioDecoderFactory: (rtc::scoped_refptr)audioDecoderFactory nativeVideoEncoderFactory: - (nullable cricket::WebRtcVideoEncoderFactory *)videoEncoderFactory + (std::unique_ptr)videoEncoderFactory nativeVideoDecoderFactory: - (nullable cricket::WebRtcVideoDecoderFactory *)videoDecoderFactory - NS_DESIGNATED_INITIALIZER; + (std::unique_ptr)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)audioEncoderFactory + nativeAudioDecoderFactory: + (rtc::scoped_refptr)audioDecoderFactory + legacyNativeVideoEncoderFactory:(cricket::WebRtcVideoEncoderFactory*)videoEncoderFactory + legacyNativeVideoDecoderFactory:(cricket::WebRtcVideoDecoderFactory*)videoDecoderFactory; @end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm index 594ee95775..34d21a56f4 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm @@ -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)encoderFactory decoderFactory:(nullable id)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 native_encoder_factory; + std::unique_ptr 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)audioEncoderFactory - nativeAudioDecoderFactory: - (rtc::scoped_refptr)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(), std::unique_ptr(), std::unique_ptr()); + NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!"); + } + return self; +} + +- (instancetype)initWithNativeAudioEncoderFactory: + (rtc::scoped_refptr)audioEncoderFactory + nativeAudioDecoderFactory: + (rtc::scoped_refptr)audioDecoderFactory + nativeVideoEncoderFactory: + (std::unique_ptr)videoEncoderFactory + nativeVideoDecoderFactory: + (std::unique_ptr)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)audioEncoderFactory + nativeAudioDecoderFactory: + (rtc::scoped_refptr)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 { diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h index 1edaf15a9c..97ee5138ad 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h @@ -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 *)parameters; - (cricket::VideoCodec)nativeVideoCodec; @end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm index 3e4c3162a1..df5946df81 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm @@ -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 *)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 *)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 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 diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm index 1a09fe158b..b5322b601a 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm @@ -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 *)supportedCodecs { NSMutableArray *codecs = [NSMutableArray array]; - NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName]; + NSString *codecName = kH264CodecName; if (IsHighProfileEnabled()) { NSDictionary *constrainedHighParams = @{ @@ -88,7 +89,7 @@ bool IsHighProfileEnabled() { } - (NSArray *)supportedCodecs { - NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName]; + NSString *codecName = kH264CodecName; return @[ [[RTCVideoCodecInfo alloc] initWithName:codecName parameters:nil] ]; } diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP8.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP8.mm new file mode 100644 index 0000000000..fa785f4ca4 --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP8.mm @@ -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 + +#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)vp8Encoder { + return [[RTCWrappedNativeVideoEncoder alloc] + initWithNativeEncoder:std::unique_ptr(webrtc::VP8Encoder::Create())]; +} + +@end + +#pragma mark - Decoder + +@implementation RTCVideoDecoderVP8 + ++ (id)vp8Decoder { + return [[RTCWrappedNativeVideoDecoder alloc] + initWithNativeDecoder:std::unique_ptr(webrtc::VP8Decoder::Create())]; +} + +@end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm new file mode 100644 index 0000000000..60fe54f6cb --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm @@ -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 + +#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)vp9Encoder { + return [[RTCWrappedNativeVideoEncoder alloc] + initWithNativeEncoder:std::unique_ptr(webrtc::VP9Encoder::Create())]; +} + +@end + +#pragma mark - Decoder + +@implementation RTCVideoDecoderVP9 + ++ (id)vp9Decoder { + return [[RTCWrappedNativeVideoDecoder alloc] + initWithNativeDecoder:std::unique_ptr(webrtc::VP9Decoder::Create())]; +} + +@end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm index 0fb8e46f2e..95233ec4ba 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm @@ -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 diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame+Private.h new file mode 100644 index 0000000000..43d3fbf68e --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame+Private.h @@ -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 diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame.mm index cf4216e825..19dd2452cd 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoFrame.mm @@ -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 nativeToRtcFrameBuffer( + const rtc::scoped_refptr &buffer) { + return buffer->type() == webrtc::VideoFrameBuffer::Type::kNative ? + static_cast(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 frameBuffer = + new rtc::RefCountedObject(self.buffer); + webrtc::VideoFrame videoFrame(frameBuffer, + (webrtc::VideoRotation)self.rotation, + self.timeStampNs / rtc::kNumNanosecsPerMicrosec); + videoFrame.set_timestamp(self.timeStamp); + return videoFrame; +} + @end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm index 736803b913..79cc1a71dd 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm @@ -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 video_frame_buffer = nativeVideoFrame.video_frame_buffer(); - id rtc_frame_buffer; - if (video_frame_buffer->type() == VideoFrameBuffer::Type::kNative) { - rtc::scoped_refptr objc_frame_buffer( - static_cast(video_frame_buffer.get())); - rtc_frame_buffer = (id)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(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) diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h new file mode 100644 index 0000000000..74cfaeb861 --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h @@ -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 + +#import "WebRTC/RTCVideoCodec.h" +#include "api/video_codecs/video_decoder.h" +#include "media/base/codec.h" + +@interface RTCWrappedNativeVideoDecoder : NSObject + +- (instancetype)initWithNativeDecoder:(std::unique_ptr)decoder; + +/* This moves the ownership of the wrapped decoder to the caller. */ +- (std::unique_ptr)releaseWrappedDecoder; + +@end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm new file mode 100644 index 0000000000..7d82c5b8e3 --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm @@ -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 + +#import "NSString+StdString.h" +#import "RTCWrappedNativeVideoDecoder.h" + +@implementation RTCWrappedNativeVideoDecoder { + std::unique_ptr _wrappedDecoder; +} + +- (instancetype)initWithNativeDecoder:(std::unique_ptr)decoder { + if (self = [super init]) { + _wrappedDecoder = std::move(decoder); + } + + return self; +} + +- (std::unique_ptr)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)info + renderTimeMs:(int64_t)renderTimeMs { + RTC_NOTREACHED(); + return 0; +} + +- (NSString *)implementationName { + RTC_NOTREACHED(); + return nil; +} + +@end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h new file mode 100644 index 0000000000..5b95d33eba --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h @@ -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 + +#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 + +- (instancetype)initWithNativeEncoder:(std::unique_ptr)encoder; + +/* This moves the ownership of the wrapped encoder to the caller. */ +- (std::unique_ptr)releaseWrappedEncoder; + +@end diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm new file mode 100644 index 0000000000..9d2f81b3cc --- /dev/null +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm @@ -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 + +#import "NSString+StdString.h" +#import "RTCWrappedNativeVideoEncoder.h" + +@implementation RTCWrappedNativeVideoEncoder { + std::unique_ptr _wrappedEncoder; +} + +- (instancetype)initWithNativeEncoder:(std::unique_ptr)encoder { + if (self = [super init]) { + _wrappedEncoder = std::move(encoder); + } + + return self; +} + +- (std::unique_ptr)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)info + frameTypes:(NSArray *)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 diff --git a/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm b/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm index a953ce035f..7a6629ed36 100644 --- a/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm +++ b/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoEncoderH264.mm @@ -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 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"]); diff --git a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.h b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.h index 93510e755d..a0106ff83f 100644 --- a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.h +++ b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.h @@ -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); ~ObjCVideoDecoderFactory(); id wrapped_decoder_factory() const; - VideoDecoder* CreateVideoDecoderWithParams( + std::vector GetSupportedFormats() const override; + std::unique_ptr 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 decoder_factory_; - std::vector supported_codecs_; }; } // namespace webrtc diff --git a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.mm b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.mm index e20f1ae5c0..ab615a3968 100644 --- a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.mm +++ b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_decoder_factory.mm @@ -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 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 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 decoder = [decoder_factory_ createDecoder:codecInfo]; - return new ObjCVideoDecoder(decoder); + + if ([decoder isKindOfClass:[RTCWrappedNativeVideoDecoder class]]) { + return [(RTCWrappedNativeVideoDecoder *)decoder releaseWrappedDecoder]; + } else { + return std::unique_ptr(new ObjCVideoDecoder(decoder)); + } } } return nullptr; } +std::vector ObjCVideoDecoderFactory::GetSupportedFormats() const { + std::vector 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; diff --git a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.h b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.h index cb8dda6a0a..6cdfc56f54 100644 --- a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.h +++ b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.h @@ -13,19 +13,29 @@ #import +#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); ~ObjCVideoEncoderFactory(); id wrapped_encoder_factory() const; + std::vector GetSupportedFormats() const override; + std::unique_ptr 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& supported_codecs() const override; @@ -33,6 +43,8 @@ class ObjCVideoEncoderFactory : public cricket::WebRtcVideoEncoderFactory { private: id encoder_factory_; + + // Needed for WebRtcVideoEncoderFactory interface. mutable std::vector supported_codecs_; }; diff --git a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.mm b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.mm index 230719ec6d..f78b74b182 100644 --- a/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.mm +++ b/sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.mm @@ -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 nativeToRtcFrameBuffer(const rtc::scoped_refptr &buffer) { - return buffer->type() == VideoFrameBuffer::Type::kNative ? - static_cast(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 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 ObjCVideoEncoderFactory::wrapped_encoder_factory() co return encoder_factory_; } +std::vector ObjCVideoEncoderFactory::GetSupportedFormats() const { + std::vector 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 ObjCVideoEncoderFactory::CreateVideoEncoder( + const SdpVideoFormat &format) { + RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeSdpVideoFormat:format]; + id encoder = [encoder_factory_ createEncoder:info]; + if ([encoder isKindOfClass:[RTCWrappedNativeVideoEncoder class]]) { + return [(RTCWrappedNativeVideoEncoder *)encoder releaseWrappedEncoder]; + } else { + return std::unique_ptr(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 encoder = [encoder_factory_ createEncoder:info]; return new ObjCVideoEncoder(encoder); } @@ -152,8 +175,8 @@ VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(const cricket::VideoCo const std::vector &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_; diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h index bcfb87fc6c..ad56a5dea9 100644 --- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h @@ -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 - -@property(nonatomic, assign) RTCH264PacketizationMode packetizationMode; - -@end - /** Callback block for encoder. */ typedef BOOL (^RTCVideoEncoderCallback)(RTCEncodedImage *frame, id 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 *parameters; diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecFactory.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecFactory.h index 42842eb020..aa5f746398 100644 --- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecFactory.h +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecFactory.h @@ -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 - (id)createEncoder:(RTCVideoCodecInfo *)info; -- (NSArray *)supportedCodecs; +- (NSArray *)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 - (id)createDecoder:(RTCVideoCodecInfo *)info; -- (NSArray *)supportedCodecs; +- (NSArray *)supportedCodecs; // TODO(andersc): "supportedFormats" instead? @end diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h index 449fcbba1b..1c307ebe84 100644 --- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h @@ -13,6 +13,19 @@ #import #import +/** 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 + +@property(nonatomic, assign) RTCH264PacketizationMode packetizationMode; + +@end + /** Encoder. */ RTC_EXPORT @interface RTCVideoEncoderH264 : NSObject diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP8.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP8.h new file mode 100644 index 0000000000..962b6312f7 --- /dev/null +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP8.h @@ -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 + +#import +#import + +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)vp8Decoder; + +@end diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP9.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP9.h new file mode 100644 index 0000000000..faf66ef065 --- /dev/null +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoDecoderVP9.h @@ -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 + +#import +#import + +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)vp9Decoder; + +@end diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP8.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP8.h new file mode 100644 index 0000000000..e63b24dde7 --- /dev/null +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP8.h @@ -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 + +#import +#import + +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)vp8Encoder; + +@end diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP9.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP9.h new file mode 100644 index 0000000000..cef8c82e96 --- /dev/null +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoEncoderVP9.h @@ -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 + +#import +#import + +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)vp9Encoder; + +@end