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/RTCRtpFragmentationHeader+Private.h" 21#import "sdk/objc/api/peerconnection/RTCVideoCodecInfo+Private.h" 22#import "sdk/objc/api/peerconnection/RTCVideoEncoderSettings+Private.h" 23#import "sdk/objc/api/video_codec/RTCVideoCodecConstants.h" 24#import "sdk/objc/api/video_codec/RTCWrappedNativeVideoEncoder.h" 25#import "sdk/objc/helpers/NSString+StdString.h" 26 27#include "api/video/video_frame.h" 28#include "api/video_codecs/sdp_video_format.h" 29#include "api/video_codecs/video_encoder.h" 30#include "modules/include/module_common_types.h" 31#include "modules/video_coding/include/video_codec_interface.h" 32#include "modules/video_coding/include/video_error_codes.h" 33#include "rtc_base/logging.h" 34#include "sdk/objc/native/src/objc_video_frame.h" 35 36namespace webrtc { 37 38namespace { 39 40class ObjCVideoEncoder : public VideoEncoder { 41 public: 42 ObjCVideoEncoder(id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder) 43 : encoder_(encoder), implementation_name_([encoder implementationName].stdString) {} 44 45 int32_t InitEncode(const VideoCodec *codec_settings, const Settings &encoder_settings) override { 46 RTC_OBJC_TYPE(RTCVideoEncoderSettings) *settings = 47 [[RTC_OBJC_TYPE(RTCVideoEncoderSettings) alloc] initWithNativeVideoCodec:codec_settings]; 48 return [encoder_ startEncodeWithSettings:settings 49 numberOfCores:encoder_settings.number_of_cores]; 50 } 51 52 int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) override { 53 [encoder_ setCallback:^BOOL(RTC_OBJC_TYPE(RTCEncodedImage) * _Nonnull frame, 54 id<RTC_OBJC_TYPE(RTCCodecSpecificInfo)> _Nonnull info, 55 RTC_OBJC_TYPE(RTCRtpFragmentationHeader) * _Nonnull header) { 56 EncodedImage encodedImage = [frame nativeEncodedImage]; 57 58 // Handle types that can be converted into one of CodecSpecificInfo's hard coded cases. 59 CodecSpecificInfo codecSpecificInfo; 60 if ([info isKindOfClass:[RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) class]]) { 61 codecSpecificInfo = 62 [(RTC_OBJC_TYPE(RTCCodecSpecificInfoH264) *)info nativeCodecSpecificInfo]; 63 } 64 65 std::unique_ptr<RTPFragmentationHeader> fragmentationHeader = 66 [header createNativeFragmentationHeader]; 67 EncodedImageCallback::Result res = 68 callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader.get()); 69 return res.error == EncodedImageCallback::Result::OK; 70 }]; 71 72 return WEBRTC_VIDEO_CODEC_OK; 73 } 74 75 int32_t Release() override { return [encoder_ releaseEncoder]; } 76 77 int32_t Encode(const VideoFrame &frame, 78 const std::vector<VideoFrameType> *frame_types) override { 79 NSMutableArray<NSNumber *> *rtcFrameTypes = [NSMutableArray array]; 80 for (size_t i = 0; i < frame_types->size(); ++i) { 81 [rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))]; 82 } 83 84 return [encoder_ encode:ToObjCVideoFrame(frame) 85 codecSpecificInfo:nil 86 frameTypes:rtcFrameTypes]; 87 } 88 89 void SetRates(const RateControlParameters ¶meters) override { 90 const uint32_t bitrate = parameters.bitrate.get_sum_kbps(); 91 const uint32_t framerate = static_cast<uint32_t>(parameters.framerate_fps + 0.5); 92 [encoder_ setBitrate:bitrate framerate:framerate]; 93 } 94 95 VideoEncoder::EncoderInfo GetEncoderInfo() const override { 96 EncoderInfo info; 97 info.supports_native_handle = true; 98 info.implementation_name = implementation_name_; 99 100 RTC_OBJC_TYPE(RTCVideoEncoderQpThresholds) *qp_thresholds = [encoder_ scalingSettings]; 101 info.scaling_settings = qp_thresholds ? ScalingSettings(qp_thresholds.low, qp_thresholds.high) : 102 ScalingSettings::kOff; 103 104 info.is_hardware_accelerated = true; 105 info.has_internal_source = false; 106 return info; 107 } 108 109 private: 110 id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder_; 111 const std::string implementation_name_; 112}; 113 114class ObjcVideoEncoderSelector : public VideoEncoderFactory::EncoderSelectorInterface { 115 public: 116 ObjcVideoEncoderSelector(id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector) { 117 selector_ = selector; 118 } 119 void OnCurrentEncoder(const SdpVideoFormat &format) override { 120 RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = 121 [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithNativeSdpVideoFormat:format]; 122 [selector_ registerCurrentEncoderInfo:info]; 123 } 124 absl::optional<SdpVideoFormat> OnEncoderBroken() override { 125 RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [selector_ encoderForBrokenEncoder]; 126 if (info) { 127 return [info nativeSdpVideoFormat]; 128 } 129 return absl::nullopt; 130 } 131 absl::optional<SdpVideoFormat> OnAvailableBitrate(const DataRate &rate) override { 132 RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [selector_ encoderForBitrate:rate.kbps<NSInteger>()]; 133 if (info) { 134 return [info nativeSdpVideoFormat]; 135 } 136 return absl::nullopt; 137 } 138 139 private: 140 id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector_; 141}; 142 143} // namespace 144 145ObjCVideoEncoderFactory::ObjCVideoEncoderFactory( 146 id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> encoder_factory) 147 : encoder_factory_(encoder_factory) {} 148 149ObjCVideoEncoderFactory::~ObjCVideoEncoderFactory() {} 150 151id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> ObjCVideoEncoderFactory::wrapped_encoder_factory() const { 152 return encoder_factory_; 153} 154 155std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetSupportedFormats() const { 156 std::vector<SdpVideoFormat> supported_formats; 157 for (RTC_OBJC_TYPE(RTCVideoCodecInfo) * supportedCodec in [encoder_factory_ supportedCodecs]) { 158 SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat]; 159 supported_formats.push_back(format); 160 } 161 162 return supported_formats; 163} 164 165std::vector<SdpVideoFormat> ObjCVideoEncoderFactory::GetImplementations() const { 166 if ([encoder_factory_ respondsToSelector:@selector(implementations)]) { 167 std::vector<SdpVideoFormat> supported_formats; 168 for (RTC_OBJC_TYPE(RTCVideoCodecInfo) * supportedCodec in [encoder_factory_ implementations]) { 169 SdpVideoFormat format = [supportedCodec nativeSdpVideoFormat]; 170 supported_formats.push_back(format); 171 } 172 return supported_formats; 173 } 174 return GetSupportedFormats(); 175} 176 177VideoEncoderFactory::CodecInfo ObjCVideoEncoderFactory::QueryVideoEncoder( 178 const SdpVideoFormat &format) const { 179 // TODO(andersc): This is a hack until we figure out how this should be done properly. 180 NSString *formatName = [NSString stringForStdString:format.name]; 181 NSSet *wrappedSoftwareFormats = 182 [NSSet setWithObjects:kRTCVideoCodecVp8Name, kRTCVideoCodecVp9Name, nil]; 183 184 CodecInfo codec_info; 185 codec_info.is_hardware_accelerated = ![wrappedSoftwareFormats containsObject:formatName]; 186 codec_info.has_internal_source = false; 187 return codec_info; 188} 189 190std::unique_ptr<VideoEncoder> ObjCVideoEncoderFactory::CreateVideoEncoder( 191 const SdpVideoFormat &format) { 192 RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = 193 [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithNativeSdpVideoFormat:format]; 194 id<RTC_OBJC_TYPE(RTCVideoEncoder)> encoder = [encoder_factory_ createEncoder:info]; 195 if ([encoder isKindOfClass:[RTCWrappedNativeVideoEncoder class]]) { 196 return [(RTCWrappedNativeVideoEncoder *)encoder releaseWrappedEncoder]; 197 } else { 198 return std::unique_ptr<ObjCVideoEncoder>(new ObjCVideoEncoder(encoder)); 199 } 200} 201 202std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> 203 ObjCVideoEncoderFactory::GetEncoderSelector() const { 204 if ([encoder_factory_ respondsToSelector:@selector(encoderSelector)]) { 205 id<RTC_OBJC_TYPE(RTCVideoEncoderSelector)> selector = [encoder_factory_ encoderSelector]; 206 if (selector) { 207 return absl::make_unique<ObjcVideoEncoderSelector>(selector); 208 } 209 } 210 return nullptr; 211} 212 213} // namespace webrtc 214