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 ¶meters) 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