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}
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h
index a4122de..5763151 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory+Native.h
@@ -16,6 +16,8 @@
class AudioEncoderFactory;
class AudioDecoderFactory;
+class VideoEncoderFactory;
+class VideoDecoderFactory;
} // namespace webrtc
@@ -33,16 +35,31 @@
*/
@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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnectionFactory.mm
index 594ee95..34d21a5 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<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 {
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h
index 1edaf15..97ee513 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 @@
@interface RTCVideoEncoderSettings ()
- (instancetype)initWithNativeVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec;
+- (webrtc::VideoCodec)nativeVideoCodec;
@end
@@ -48,10 +50,11 @@
@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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm
index 3e4c316..df5946d 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<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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm
index 1a09fe1..b5322b6 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 @@
- (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 @@
- (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 @@
}
- (NSArray<RTCVideoCodecInfo *> *)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 0000000..fa785f4
--- /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 <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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecVP9.mm
new file mode 100644
index 0000000..60fe54f
--- /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 <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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoEncoderSettings.mm
index 0fb8e46..95233ec 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 0000000..43d3fbf
--- /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 cf4216e..19dd245 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<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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoRendererAdapter.mm
index 736803b..79cc1a7 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 @@
}
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)
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.h
new file mode 100644
index 0000000..74cfaeb
--- /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 <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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoDecoder.mm
new file mode 100644
index 0000000..7d82c5b
--- /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 <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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.h
new file mode 100644
index 0000000..5b95d33
--- /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 <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
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCWrappedNativeVideoEncoder.mm
new file mode 100644
index 0000000..9d2f81b
--- /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 <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