Implement ObjCVideoEncoderFactory::QueryCodecSupport
To allow objc video encoders to support scalability modes Bug: b/299588022 Change-Id: Id58f996b8c48c6688cccdc32caff6adb00370d5c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/358580 Reviewed-by: Kári Helgason <kthelgason@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42985}
This commit is contained in:
parent
0acbb7745f
commit
76aa330c24
@ -110,6 +110,7 @@ if (is_ios || is_mac) {
|
||||
"objc/base/RTCVideoDecoderFactory.h",
|
||||
"objc/base/RTCVideoEncoder.h",
|
||||
"objc/base/RTCVideoEncoderFactory.h",
|
||||
"objc/base/RTCVideoEncoderFactory.mm",
|
||||
"objc/base/RTCVideoEncoderQpThresholds.h",
|
||||
"objc/base/RTCVideoEncoderQpThresholds.m",
|
||||
"objc/base/RTCVideoEncoderSettings.h",
|
||||
|
||||
@ -32,6 +32,22 @@ RTC_OBJC_EXPORT
|
||||
|
||||
@end
|
||||
|
||||
/** RTCVideoEncoderCodecSupport is an Objective-C version of
|
||||
* webrtc::VideoEncoderFactory::CodecSupport. */
|
||||
RTC_OBJC_EXPORT
|
||||
@interface RTC_OBJC_TYPE (RTCVideoEncoderCodecSupport) : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithSupported:(bool)isSupported;
|
||||
- (instancetype)initWithSupported:(bool)isSupported
|
||||
isPowerEfficient:(bool)isPowerEfficient NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property(nonatomic, readonly) bool isSupported;
|
||||
@property(nonatomic, readonly) bool isPowerEfficient;
|
||||
|
||||
@end
|
||||
|
||||
/** RTCVideoEncoderFactory is an Objective-C version of webrtc::VideoEncoderFactory.
|
||||
*/
|
||||
RTC_OBJC_EXPORT
|
||||
@ -46,6 +62,10 @@ RTC_OBJC_EXPORT
|
||||
@optional
|
||||
- (NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)implementations;
|
||||
- (nullable id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)>)encoderSelector;
|
||||
/* TODO: b/299588022 - move to non-optional section when implemented by all derived classes. */
|
||||
- (RTC_OBJC_TYPE(RTCVideoEncoderCodecSupport) *)
|
||||
queryCodecSupport:(RTC_OBJC_TYPE(RTCVideoCodecInfo) *)info
|
||||
scalabilityMode:(nullable NSString *)scalabilityMode;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
32
sdk/objc/base/RTCVideoEncoderFactory.mm
Normal file
32
sdk/objc/base/RTCVideoEncoderFactory.mm
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2024 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 "RTCVideoEncoderFactory.h"
|
||||
#import "RTCMacros.h"
|
||||
|
||||
@implementation RTC_OBJC_TYPE (RTCVideoEncoderCodecSupport)
|
||||
|
||||
@synthesize isSupported = _isSupported;
|
||||
@synthesize isPowerEfficient = _isPowerEfficient;
|
||||
|
||||
- (instancetype)initWithSupported:(bool)isSupported {
|
||||
return [self initWithSupported:isSupported isPowerEfficient:false];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSupported:(bool)isSupported isPowerEfficient:(bool)isPowerEfficient {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_isSupported = isSupported;
|
||||
_isPowerEfficient = isPowerEfficient;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -13,10 +13,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "base/RTCMacros.h"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "api/environment/environment.h"
|
||||
#include "api/video_codecs/sdp_video_format.h"
|
||||
#include "api/video_codecs/video_encoder_factory.h"
|
||||
#import "base/RTCMacros.h"
|
||||
|
||||
@protocol RTC_OBJC_TYPE
|
||||
(RTCVideoEncoderFactory);
|
||||
@ -32,6 +35,8 @@ class ObjCVideoEncoderFactory : public VideoEncoderFactory {
|
||||
|
||||
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
|
||||
std::vector<SdpVideoFormat> GetImplementations() const override;
|
||||
CodecSupport QueryCodecSupport(const SdpVideoFormat& format,
|
||||
std::optional<std::string> scalability_mode) const override;
|
||||
std::unique_ptr<VideoEncoder> Create(const Environment& env,
|
||||
const SdpVideoFormat& format) override;
|
||||
std::unique_ptr<EncoderSelectorInterface> GetEncoderSelector() const override;
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "sdk/objc/native/src/objc_video_encoder_factory.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#import "base/RTCMacros.h"
|
||||
@ -184,6 +185,25 @@ std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetImplementations() const
|
||||
return GetSupportedFormats();
|
||||
}
|
||||
|
||||
VideoEncoderFactory::CodecSupport ObjCVideoEncoderFactory::QueryCodecSupport(
|
||||
const SdpVideoFormat &format, std::optional<std::string> scalability_mode) const {
|
||||
if ([encoder_factory_ respondsToSelector:@selector(queryCodecSupport:scalabilityMode:)]) {
|
||||
RTC_OBJC_TYPE(RTCVideoCodecInfo) *info =
|
||||
[[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithNativeSdpVideoFormat:format];
|
||||
NSString *mode;
|
||||
if (scalability_mode.has_value()) {
|
||||
mode = [NSString stringForAbslStringView:*scalability_mode];
|
||||
}
|
||||
|
||||
RTC_OBJC_TYPE(RTCVideoEncoderCodecSupport) *result = [encoder_factory_ queryCodecSupport:info
|
||||
scalabilityMode:mode];
|
||||
return {.is_supported = result.isSupported, .is_power_efficient = result.isPowerEfficient};
|
||||
}
|
||||
|
||||
// Use default implementation.
|
||||
return VideoEncoderFactory::QueryCodecSupport(format, scalability_mode);
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoEncoder> ObjCVideoEncoderFactory::Create(const Environment &env,
|
||||
const SdpVideoFormat &format) {
|
||||
RTC_OBJC_TYPE(RTCVideoCodecInfo) *info =
|
||||
|
||||
@ -52,6 +52,55 @@ id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> CreateErrorEncoderFactory() {
|
||||
return CreateEncoderFactoryReturning(WEBRTC_VIDEO_CODEC_ERROR);
|
||||
}
|
||||
|
||||
@interface RTCVideoEncoderFactoryFake : NSObject <RTC_OBJC_TYPE (RTCVideoEncoderFactory)>
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithScalabilityMode:(NSString *)scalabilityMode;
|
||||
- (instancetype)initWithScalabilityMode:(NSString *)scalabilityMode
|
||||
isPowerEfficient:(bool)isPowerEfficient NS_DESIGNATED_INITIALIZER;
|
||||
@end
|
||||
@implementation RTCVideoEncoderFactoryFake
|
||||
|
||||
NSString *_scalabilityMode;
|
||||
bool _isPowerEfficient;
|
||||
|
||||
- (instancetype)initWithScalabilityMode:(NSString *)scalabilityMode {
|
||||
return [self initWithScalabilityMode:scalabilityMode isPowerEfficient:false];
|
||||
}
|
||||
|
||||
- (instancetype)initWithScalabilityMode:(NSString *)scalabilityMode
|
||||
isPowerEfficient:(bool)isPowerEfficient {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_scalabilityMode = scalabilityMode;
|
||||
_isPowerEfficient = isPowerEfficient;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable id<RTC_OBJC_TYPE(RTCVideoEncoder)>)createEncoder:
|
||||
(RTC_OBJC_TYPE(RTCVideoCodecInfo) *)info {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)supportedCodecs {
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (RTC_OBJC_TYPE(RTCVideoEncoderCodecSupport) *)
|
||||
queryCodecSupport:(RTC_OBJC_TYPE(RTCVideoCodecInfo) *)info
|
||||
scalabilityMode:(nullable NSString *)scalabilityMode {
|
||||
if (_scalabilityMode ? [_scalabilityMode isEqualToString:scalabilityMode] :
|
||||
scalabilityMode == nil) {
|
||||
return [[RTC_OBJC_TYPE(RTCVideoEncoderCodecSupport) alloc] initWithSupported:true
|
||||
isPowerEfficient:_isPowerEfficient];
|
||||
} else {
|
||||
return [[RTC_OBJC_TYPE(RTCVideoEncoderCodecSupport) alloc] initWithSupported:false];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
std::unique_ptr<webrtc::VideoEncoder> GetObjCEncoder(
|
||||
id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> factory) {
|
||||
webrtc::ObjCVideoEncoderFactory encoder_factory(factory);
|
||||
@ -132,6 +181,36 @@ std::unique_ptr<webrtc::VideoEncoder> GetObjCEncoder(
|
||||
EXPECT_EQ(encoder->Release(), WEBRTC_VIDEO_CODEC_ERROR);
|
||||
}
|
||||
|
||||
- (void)testQueryCodecSupportDelegatesToObjcFactoryConvertsNulloptModeToNil {
|
||||
id fakeEncoderFactory = [[RTCVideoEncoderFactoryFake alloc] initWithScalabilityMode:nil];
|
||||
webrtc::SdpVideoFormat codec("VP8");
|
||||
webrtc::ObjCVideoEncoderFactory encoder_factory(fakeEncoderFactory);
|
||||
|
||||
webrtc::VideoEncoderFactory::CodecSupport s =
|
||||
encoder_factory.QueryCodecSupport(codec, std::nullopt);
|
||||
|
||||
EXPECT_TRUE(s.is_supported);
|
||||
}
|
||||
|
||||
- (void)testQueryCodecSupportDelegatesToObjcFactoryMayReturnUnsupported {
|
||||
id fakeEncoderFactory = [[RTCVideoEncoderFactoryFake alloc] initWithScalabilityMode:@"L1T2"];
|
||||
webrtc::SdpVideoFormat codec("VP8");
|
||||
webrtc::ObjCVideoEncoderFactory encoder_factory(fakeEncoderFactory);
|
||||
|
||||
EXPECT_FALSE(encoder_factory.QueryCodecSupport(codec, "S2T1").is_supported);
|
||||
}
|
||||
|
||||
- (void)testQueryCodecSupportDelegatesToObjcFactoryIncludesPowerEfficientFlag {
|
||||
id fakeEncoderFactory = [[RTCVideoEncoderFactoryFake alloc] initWithScalabilityMode:@"L1T2"
|
||||
isPowerEfficient:true];
|
||||
webrtc::SdpVideoFormat codec("VP8");
|
||||
webrtc::ObjCVideoEncoderFactory encoder_factory(fakeEncoderFactory);
|
||||
|
||||
webrtc::VideoEncoderFactory::CodecSupport s = encoder_factory.QueryCodecSupport(codec, "L1T2");
|
||||
EXPECT_TRUE(s.is_supported);
|
||||
EXPECT_TRUE(s.is_power_efficient);
|
||||
}
|
||||
|
||||
- (void)testGetSupportedFormats {
|
||||
webrtc::ObjCVideoEncoderFactory encoder_factory(CreateOKEncoderFactory());
|
||||
std::vector<webrtc::SdpVideoFormat> supportedFormats = encoder_factory.GetSupportedFormats();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user