Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm

Issue 2987413002: ObjC: Implement HW codecs in ObjC instead of C++ (Closed)
Patch Set: Move RTCH264PacketizationMode to RTCVideoCodec.h Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #import "WebRTC/RTCVideoCodecH264.h" 11 #import "WebRTC/RTCVideoCodecH264.h"
12 12
13 #include <vector> 13 #include <vector>
14 14
15 #import "RTCVideoCodec+Private.h" 15 #import "RTCVideoCodec+Private.h"
16 #import "WebRTC/RTCVideoCodec.h" 16 #import "WebRTC/RTCVideoCodec.h"
17 #import "WebRTC/RTCVideoFrame.h" 17 #import "WebRTC/RTCVideoFrame.h"
18 #import "WebRTC/RTCVideoFrameBuffer.h" 18 #import "WebRTC/RTCVideoFrameBuffer.h"
19 19
20 #include "webrtc/rtc_base/timeutils.h" 20 #include "webrtc/rtc_base/timeutils.h"
21 #include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h" 21 #include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
22 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h"
23 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/encoder.h"
24 #include "webrtc/system_wrappers/include/field_trial.h" 22 #include "webrtc/system_wrappers/include/field_trial.h"
25 23
26 const size_t kDefaultPayloadSize = 1440;
27
28 const char kHighProfileExperiment[] = "WebRTC-H264HighProfile"; 24 const char kHighProfileExperiment[] = "WebRTC-H264HighProfile";
29 25 static NSString *kLevel31ConstrainedHigh = @"640c1f";
30 // These thresholds deviate from the default h264 QP thresholds, as they have be en found to work 26 static NSString *kLevel31ConstrainedBaseline = @"42e01f";
31 // better on devices that support VideoToolbox
32 const int kLowH264QpThreshold = 28;
33 const int kHighH264QpThreshold = 39;
34 27
35 bool IsHighProfileEnabled() { 28 bool IsHighProfileEnabled() {
36 return webrtc::field_trial::IsEnabled(kHighProfileExperiment); 29 return webrtc::field_trial::IsEnabled(kHighProfileExperiment);
37 } 30 }
38 31
39 // H264 specific settings. 32 // H264 specific settings.
40 @implementation RTCCodecSpecificInfoH264 33 @implementation RTCCodecSpecificInfoH264
41 34
42 @synthesize packetizationMode = _packetizationMode; 35 @synthesize packetizationMode = _packetizationMode;
43 36
44 - (webrtc::CodecSpecificInfo)nativeCodecSpecificInfo { 37 - (webrtc::CodecSpecificInfo)nativeCodecSpecificInfo {
45 webrtc::CodecSpecificInfo codecSpecificInfo; 38 webrtc::CodecSpecificInfo codecSpecificInfo;
46 codecSpecificInfo.codecType = webrtc::kVideoCodecH264; 39 codecSpecificInfo.codecType = webrtc::kVideoCodecH264;
47 codecSpecificInfo.codec_name = "H264"; 40 codecSpecificInfo.codec_name = "H264";
48 codecSpecificInfo.codecSpecific.H264.packetization_mode = 41 codecSpecificInfo.codecSpecific.H264.packetization_mode =
49 (webrtc::H264PacketizationMode)_packetizationMode; 42 (webrtc::H264PacketizationMode)_packetizationMode;
50 43
51 return codecSpecificInfo; 44 return codecSpecificInfo;
52 } 45 }
53 46
54 @end 47 @end
55 48
56 namespace {
57
58 class H264VideoToolboxEncodeCompleteCallback : public webrtc::EncodedImageCallba ck {
59 public:
60 Result OnEncodedImage(const webrtc::EncodedImage &encoded_image,
61 const webrtc::CodecSpecificInfo *codec_specific_info,
62 const webrtc::RTPFragmentationHeader *fragmentation) {
63 RTCEncodedImage *image = [[RTCEncodedImage alloc] initWithNativeEncodedImage :encoded_image];
64
65 RTCCodecSpecificInfoH264 *info = [[RTCCodecSpecificInfoH264 alloc] init];
66 info.packetizationMode =
67 (RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packet ization_mode;
68
69 RTCRtpFragmentationHeader *header =
70 [[RTCRtpFragmentationHeader alloc] initWithNativeFragmentationHeader:fra gmentation];
71
72 callback(image, info, header);
73 return Result(Result::OK, 0);
74 }
75
76 RTCVideoEncoderCallback callback;
77 };
78
79 class H264VideoToolboxDecodeCompleteCallback : public webrtc::DecodedImageCallba ck {
80 public:
81 int32_t Decoded(webrtc::VideoFrame &decodedImage) {
82 rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer =
83 decodedImage.video_frame_buffer();
84 id<RTCVideoFrameBuffer> rtcFrameBuffer;
85 rtc::scoped_refptr<webrtc::ObjCFrameBuffer> objc_frame_buffer(
86 static_cast<webrtc::ObjCFrameBuffer *>(video_frame_buffer.get()));
87 rtcFrameBuffer = (id<RTCVideoFrameBuffer>)objc_frame_buffer->wrapped_frame_b uffer();
88
89 RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc]
90 initWithBuffer:rtcFrameBuffer
91 rotation:static_cast<RTCVideoRotation>(decodedImage.rotation())
92 timeStampNs:decodedImage.timestamp_us() * rtc::kNumNanosecsPerMicrose c];
93 videoFrame.timeStamp = decodedImage.timestamp();
94
95 callback(videoFrame);
96
97 return 0;
98 }
99
100 RTCVideoDecoderCallback callback;
101 };
102
103 } // namespace
104
105 // Encoder.
106 @implementation RTCVideoEncoderH264 {
107 webrtc::H264VideoToolboxEncoder *_videoToolboxEncoder;
108 H264VideoToolboxEncodeCompleteCallback *_toolboxCallback;
109 }
110
111 - (instancetype)initWithCodecInfo:(RTCVideoCodecInfo *)codecInfo {
112 if (self = [super init]) {
113 cricket::VideoCodec codec = [codecInfo nativeVideoCodec];
114 _videoToolboxEncoder = new webrtc::H264VideoToolboxEncoder(codec);
115 }
116 return self;
117 }
118
119 - (void)setCallback:(RTCVideoEncoderCallback)callback {
120 if (!_toolboxCallback) _toolboxCallback = new H264VideoToolboxEncodeCompleteCa llback();
121 _toolboxCallback->callback = callback;
122 _videoToolboxEncoder->RegisterEncodeCompleteCallback(_toolboxCallback);
123 }
124
125 - (void)destroy {
126 delete _videoToolboxEncoder;
127 _videoToolboxEncoder = nullptr;
128 delete _toolboxCallback;
129 _toolboxCallback = nullptr;
130 }
131
132 -(void)dealloc {
133 // Make sure C++ objects have been properly cleaned up before this
134 // is dealloc'd.
135 RTC_DCHECK(!_videoToolboxEncoder);
136 RTC_DCHECK(!_toolboxCallback);
137 }
138
139 - (NSInteger)startEncodeWithSettings:(RTCVideoEncoderSettings *)settings
140 numberOfCores:(int)numberOfCores {
141 std::unique_ptr<webrtc::VideoCodec> codecSettings = [settings createNativeVide oEncoderSettings];
142 return _videoToolboxEncoder->InitEncode(
143 codecSettings.release(), numberOfCores, kDefaultPayloadSize);
144 }
145
146 - (NSInteger)releaseEncoder {
147 return _videoToolboxEncoder->Release();
148 }
149
150 - (NSInteger)encode:(RTCVideoFrame *)frame
151 codecSpecificInfo:(id<RTCCodecSpecificInfo>)info
152 frameTypes:(NSArray<NSNumber *> *)frameTypes {
153 rtc::scoped_refptr<webrtc::VideoFrameBuffer> frameBuffer =
154 new rtc::RefCountedObject<webrtc::ObjCFrameBuffer>(frame.buffer);
155 webrtc::VideoFrame videoFrame(frameBuffer,
156 (webrtc::VideoRotation)frame.rotation,
157 frame.timeStampNs / rtc::kNumNanosecsPerMicrosec );
158 videoFrame.set_timestamp(frame.timeStamp);
159
160 // Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
161 webrtc::CodecSpecificInfo codecSpecificInfo;
162 if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
163 codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInf o];
164 }
165
166 std::vector<webrtc::FrameType> nativeFrameTypes;
167 for (NSNumber *frameType in frameTypes) {
168 RTCFrameType rtcFrameType = (RTCFrameType)frameType.unsignedIntegerValue;
169 nativeFrameTypes.push_back((webrtc::FrameType)rtcFrameType);
170 }
171
172 return _videoToolboxEncoder->Encode(videoFrame, &codecSpecificInfo, &nativeFra meTypes);
173 }
174
175 - (BOOL)setBitrate:(uint32_t)bitrateKbit framerate:(uint32_t)framerate {
176 return _videoToolboxEncoder->SetRates(bitrateKbit, framerate) == WEBRTC_VIDEO_ CODEC_OK;
177 }
178
179 - (RTCVideoEncoderQpThresholds *)scalingSettings {
180 return [[RTCVideoEncoderQpThresholds alloc] initWithThresholdsLow:kLowH264QpTh reshold
181 high:kHighH264QpT hreshold];
182 }
183
184 - (NSString *)implementationName {
185 return @"VideoToolbox";
186 }
187
188 @end
189
190 // Decoder.
191 @implementation RTCVideoDecoderH264 {
192 webrtc::H264VideoToolboxDecoder *_videoToolboxDecoder;
193 H264VideoToolboxDecodeCompleteCallback *_toolboxCallback;
194 }
195
196 - (instancetype)init {
197 if (self = [super init]) {
198 cricket::VideoCodec codec(cricket::kH264CodecName);
199 _videoToolboxDecoder = new webrtc::H264VideoToolboxDecoder();
200 }
201 return self;
202 }
203
204 - (NSInteger)startDecodeWithSettings:(RTCVideoEncoderSettings *)settings
205 numberOfCores:(int)numberOfCores {
206 std::unique_ptr<webrtc::VideoCodec> codecSettings = [settings createNativeVide oEncoderSettings];
207 return _videoToolboxDecoder->InitDecode(codecSettings.release(), numberOfCores );
208 }
209
210 - (void)setCallback:(RTCVideoDecoderCallback)callback {
211 if (!_toolboxCallback) _toolboxCallback = new H264VideoToolboxDecodeCompleteCa llback();
212 _toolboxCallback->callback = callback;
213 _videoToolboxDecoder->RegisterDecodeCompleteCallback(_toolboxCallback);
214 }
215
216 - (NSInteger)releaseDecoder {
217 return _videoToolboxDecoder->Release();
218 }
219
220 - (void)destroy {
221 delete _videoToolboxDecoder;
222 _videoToolboxDecoder = nullptr;
223 delete _toolboxCallback;
224 _toolboxCallback = nullptr;
225 }
226
227 -(void)dealloc {
228 // Make sure C++ objects have been properly cleaned up before this
229 // is dealloc'd.
230 RTC_DCHECK(!_videoToolboxDecoder);
231 RTC_DCHECK(!_toolboxCallback);
232 }
233
234 - (NSInteger)decode:(RTCEncodedImage *)encodedImage
235 missingFrames:(BOOL)missingFrames
236 fragmentationHeader:(RTCRtpFragmentationHeader *)fragmentationHeader
237 codecSpecificInfo:(__nullable id<RTCCodecSpecificInfo>)info
238 renderTimeMs:(int64_t)renderTimeMs {
239 webrtc::EncodedImage image = [encodedImage nativeEncodedImage];
240
241 // Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
242 webrtc::CodecSpecificInfo codecSpecificInfo;
243 if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
244 codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInf o];
245 }
246
247 std::unique_ptr<webrtc::RTPFragmentationHeader> header =
248 [fragmentationHeader createNativeFragmentationHeader];
249
250 return _videoToolboxDecoder->Decode(
251 image, missingFrames, header.release(), &codecSpecificInfo, renderTimeMs);
252 }
253
254 - (NSString *)implementationName {
255 return @"VideoToolbox";
256 }
257
258 @end
259
260 // Encoder factory. 49 // Encoder factory.
261 @implementation RTCVideoEncoderFactoryH264 50 @implementation RTCVideoEncoderFactoryH264
262 51
263 - (NSArray<RTCVideoCodecInfo *> *)supportedCodecs { 52 - (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
264 NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array]; 53 NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];
265 NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName]; 54 NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
266 55
267 if (IsHighProfileEnabled()) { 56 if (IsHighProfileEnabled()) {
268 NSDictionary<NSString *, NSString *> *constrainedHighParams = @{ 57 NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
269 @"profile-level-id" : @"640c1f", // Level 3.1 Constrained High. 58 @"profile-level-id" : kLevel31ConstrainedHigh,
270 @"level-asymmetry-allowed" : @"1", 59 @"level-asymmetry-allowed" : @"1",
271 @"packetization-mode" : @"1", 60 @"packetization-mode" : @"1",
272 }; 61 };
273 RTCVideoCodecInfo *constrainedHighInfo = 62 RTCVideoCodecInfo *constrainedHighInfo =
274 [[RTCVideoCodecInfo alloc] initWithPayload:0 63 [[RTCVideoCodecInfo alloc] initWithPayload:0
275 name:codecName 64 name:codecName
276 parameters:constrainedHighParams]; 65 parameters:constrainedHighParams];
277 [codecs addObject:constrainedHighInfo]; 66 [codecs addObject:constrainedHighInfo];
278 } 67 }
279 68
280 NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{ 69 NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
281 @"profile-level-id" : @"42e01f", // Level 3.1 Constrained Baseline. 70 @"profile-level-id" : kLevel31ConstrainedBaseline,
282 @"level-asymmetry-allowed" : @"1", 71 @"level-asymmetry-allowed" : @"1",
283 @"packetization-mode" : @"1", 72 @"packetization-mode" : @"1",
284 }; 73 };
285 RTCVideoCodecInfo *constrainedBaselineInfo = 74 RTCVideoCodecInfo *constrainedBaselineInfo =
286 [[RTCVideoCodecInfo alloc] initWithPayload:0 75 [[RTCVideoCodecInfo alloc] initWithPayload:0
287 name:codecName 76 name:codecName
288 parameters:constrainedBaselineParams]; 77 parameters:constrainedBaselineParams];
289 [codecs addObject:constrainedBaselineInfo]; 78 [codecs addObject:constrainedBaselineInfo];
290 79
291 return [codecs copy]; 80 return [codecs copy];
(...skipping 11 matching lines...) Expand all
303 - (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info { 92 - (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info {
304 return [[RTCVideoDecoderH264 alloc] init]; 93 return [[RTCVideoDecoderH264 alloc] init];
305 } 94 }
306 95
307 - (NSArray<RTCVideoCodecInfo *> *)supportedCodecs { 96 - (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
308 NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName]; 97 NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
309 return @[ [[RTCVideoCodecInfo alloc] initWithPayload:0 name:codecName paramete rs:@{}] ]; 98 return @[ [[RTCVideoCodecInfo alloc] initWithPayload:0 name:codecName paramete rs:@{}] ];
310 } 99 }
311 100
312 @end 101 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698