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:
Danil Chapovalov 2024-09-09 15:02:29 +02:00 committed by WebRTC LUCI CQ
parent 0acbb7745f
commit 76aa330c24
6 changed files with 158 additions and 1 deletions

View File

@ -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",

View File

@ -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

View 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

View File

@ -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;

View File

@ -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 =

View File

@ -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();