xref: /aosp_15_r20/external/webrtc/sdk/objc/native/src/objc_video_encoder_factory.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1/*
2 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "sdk/objc/native/src/objc_video_encoder_factory.h"
12
13#include <string>
14
15#import "base/RTCMacros.h"
16#import "base/RTCVideoEncoder.h"
17#import "base/RTCVideoEncoderFactory.h"
18#import "components/video_codec/RTCCodecSpecificInfoH264+Private.h"
19#import "sdk/objc/api/peerconnection/RTCEncodedImage+Private.h"
20#import "sdk/objc/api/peerconnection/RTCVideoCodecInfo+Private.h"
21#import "sdk/objc/api/peerconnection/RTCVideoEncoderSettings+Private.h"
22#import "sdk/objc/api/video_codec/RTCVideoCodecConstants.h"
23#import "sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.h"
24#import "sdk/objc/helpers/NSString+StdString.h"
25
26#include "api/video/video_frame.h"
27#include "api/video_codecs/sdp_video_format.h"
28#include "api/video_codecs/video_encoder.h"
29#include "modules/video_coding/include/video_codec_interface.h"
30#include "modules/video_coding/include/video_error_codes.h"
31#include "rtc_base/logging.h"
32#include "sdk/objc/native/src/objc_video_frame.h"
33
34namespace webrtc {
35
36namespace {
37
38class ObjCVideoEncoder : public VideoEncoder {
39 public:
40  ObjCVideoEncoder(id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder)
41      : encoder_(encoder), implementation_name_([encoder implementationName].stdString) {}
42
43  int32_t InitEncode(const VideoCodec *codec_settings, const Settings &encoder_settings) override {
44    RTC_OBJC_TYPE(RTCVideoEncoderSettings) *settings =
45        [[RTC_OBJC_TYPE(RTCVideoEncoderSettings) alloc] initWithNativeVideoCodec:codec_settings];
46    return [encoder_ startEncodeWithSettings:settings
47                               numberOfCores:encoder_settings.number_of_cores];
48  }
49
50  int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) override {
51    if (callback) {
52      [encoder_ setCallback:^BOOL(RTC_OBJC_TYPE(RTCEncodedImage) * _Nonnull frame,
53                                  id<RTC_OBJC_TYPE(RTCCodecSpecificInfo)> _Nonnull info) {
54        EncodedImage encodedImage = [frame nativeEncodedImage];
55
56        // Handle types that can be converted into one of CodecSpecificInfo's hard coded cases.
57        CodecSpecificInfo codecSpecificInfo;
58        if ([info isKindOfClass:[RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) class]]) {
59          codecSpecificInfo =
60              [(RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) *)info nativeCodecSpecificInfo];
61        }
62
63        EncodedImageCallback::Result res = callback->OnEncodedImage(encodedImage, &codecSpecificInfo);
64        return res.error == EncodedImageCallback::Result::OK;
65      }];
66    } else {
67      [encoder_ setCallback:nil];
68    }
69    return WEBRTC_VIDEO_CODEC_OK;
70  }
71
72  int32_t Release() override { return [encoder_ releaseEncoder]; }
73
74  int32_t Encode(const VideoFrame &frame,
75                 const std::vector<VideoFrameType> *frame_types) override {
76    NSMutableArray<NSNumber *> *rtcFrameTypes = [NSMutableArray array];
77    for (size_t i = 0; i < frame_types->size(); ++i) {
78      [rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
79    }
80
81    return [encoder_ encode:ToObjCVideoFrame(frame)
82          codecSpecificInfo:nil
83                 frameTypes:rtcFrameTypes];
84  }
85
86  void SetRates(const RateControlParameters &parameters) override {
87    const uint32_t bitrate = parameters.bitrate.get_sum_kbps();
88    const uint32_t framerate = static_cast<uint32_t>(parameters.framerate_fps + 0.5);
89    [encoder_ setBitrate:bitrate framerate:framerate];
90  }
91
92  VideoEncoder::EncoderInfo GetEncoderInfo() const override {
93    EncoderInfo info;
94    info.implementation_name = implementation_name_;
95
96    RTC_OBJC_TYPE(RTCVideoEncoderQpThresholds) *qp_thresholds = [encoder_ scalingSettings];
97    info.scaling_settings = qp_thresholds ? ScalingSettings(qp_thresholds.low, qp_thresholds.high) :
98                                            ScalingSettings::kOff;
99
100    info.requested_resolution_alignment = encoder_.resolutionAlignment > 0 ?: 1;
101    info.apply_alignment_to_all_simulcast_layers = encoder_.applyAlignmentToAllSimulcastLayers;
102    info.supports_native_handle = encoder_.supportsNativeHandle;
103    info.is_hardware_accelerated = true;
104    return info;
105  }
106
107 private:
108  id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder_;
109  const std::string implementation_name_;
110};
111
112class ObjcVideoEncoderSelector : public VideoEncoderFactory::EncoderSelectorInterface {
113 public:
114  ObjcVideoEncoderSelector(id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector) {
115    selector_ = selector;
116  }
117  void OnCurrentEncoder(const SdpVideoFormat &format) override {
118    RTC_OBJC_TYPE(RTCVideoCodecInfo) *info =
119        [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithNativeSdpVideoFormat:format];
120    [selector_ registerCurrentEncoderInfo:info];
121  }
122  absl::optional<SdpVideoFormat> OnEncoderBroken() override {
123    RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [selector_ encoderForBrokenEncoder];
124    if (info) {
125      return [info nativeSdpVideoFormat];
126    }
127    return absl::nullopt;
128  }
129  absl::optional<SdpVideoFormat> OnAvailableBitrate(const DataRate &rate) override {
130    RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [selector_ encoderForBitrate:rate.kbps<NSInteger>()];
131    if (info) {
132      return [info nativeSdpVideoFormat];
133    }
134    return absl::nullopt;
135  }
136
137  absl::optional<SdpVideoFormat> OnResolutionChange(const RenderResolution &resolution) override {
138    if ([selector_ respondsToSelector:@selector(encoderForResolutionChangeBySize:)]) {
139      RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [selector_
140          encoderForResolutionChangeBySize:CGSizeMake(resolution.Width(), resolution.Height())];
141      if (info) {
142        return [info nativeSdpVideoFormat];
143      }
144    }
145    return absl::nullopt;
146  }
147
148 private:
149  id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector_;
150};
151
152}  // namespace
153
154ObjCVideoEncoderFactory::ObjCVideoEncoderFactory(
155    id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> encoder_factory)
156    : encoder_factory_(encoder_factory) {}
157
158ObjCVideoEncoderFactory::~ObjCVideoEncoderFactory() {}
159
160id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> ObjCVideoEncoderFactory::wrapped_encoder_factory() const {
161  return encoder_factory_;
162}
163
164std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetSupportedFormats() const {
165  std::vector<SdpVideoFormat> supported_formats;
166  for (RTC_OBJC_TYPE(RTCVideoCodecInfo) * supportedCodec in [encoder_factory_ supportedCodecs]) {
167    SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat];
168    supported_formats.push_back(format);
169  }
170
171  return supported_formats;
172}
173
174std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetImplementations() const {
175  if ([encoder_factory_ respondsToSelector:@selector(implementations)]) {
176    std::vector<SdpVideoFormat> supported_formats;
177    for (RTC_OBJC_TYPE(RTCVideoCodecInfo) * supportedCodec in [encoder_factory_ implementations]) {
178      SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat];
179      supported_formats.push_back(format);
180    }
181    return supported_formats;
182  }
183  return GetSupportedFormats();
184}
185
186std::unique_ptr<VideoEncoder> ObjCVideoEncoderFactory::CreateVideoEncoder(
187    const SdpVideoFormat &format) {
188  RTC_OBJC_TYPE(RTCVideoCodecInfo) *info =
189      [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithNativeSdpVideoFormat:format];
190  id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder = [encoder_factory_ createEncoder:info];
191  if ([encoder isKindOfClass:[RTC_OBJC_TYPE(RTCWrappedNativeVideoEncoder) class]]) {
192    return [(RTC_OBJC_TYPE(RTCWrappedNativeVideoEncoder) *)encoder releaseWrappedEncoder];
193  } else {
194    return std::unique_ptr<ObjCVideoEncoder>(new ObjCVideoEncoder(encoder));
195  }
196}
197
198std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface>
199    ObjCVideoEncoderFactory::GetEncoderSelector() const {
200  if ([encoder_factory_ respondsToSelector:@selector(encoderSelector)]) {
201    id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector = [encoder_factory_ encoderSelector];
202    if (selector) {
203      return absl::make_unique<ObjcVideoEncoderSelector>(selector);
204    }
205  }
206  return nullptr;
207}
208
209}  // namespace webrtc
210