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

Side by Side Diff: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc

Issue 2020593002: Refactor scaling. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Address Per's comments. Add I420Buffer::Scale helper method. Created 4 years, 6 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 (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 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 */
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 int32_t width; 138 int32_t width;
139 int32_t height; 139 int32_t height;
140 int64_t render_time_ms; 140 int64_t render_time_ms;
141 uint32_t timestamp; 141 uint32_t timestamp;
142 webrtc::VideoRotation rotation; 142 webrtc::VideoRotation rotation;
143 }; 143 };
144 144
145 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the 145 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the
146 // encoder. This performs the copy and format conversion. 146 // encoder. This performs the copy and format conversion.
147 // TODO(tkchin): See if encoder will accept i420 frames and compare performance. 147 // TODO(tkchin): See if encoder will accept i420 frames and compare performance.
148 bool CopyVideoFrameToPixelBuffer(const webrtc::VideoFrame& frame, 148 bool CopyVideoFrameToPixelBuffer(
149 CVPixelBufferRef pixel_buffer) { 149 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& frame,
150 CVPixelBufferRef pixel_buffer) {
150 RTC_DCHECK(pixel_buffer); 151 RTC_DCHECK(pixel_buffer);
151 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == 152 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) ==
152 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); 153 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange);
153 RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) == 154 RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) ==
154 static_cast<size_t>(frame.height())); 155 static_cast<size_t>(frame->height()));
155 RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) == 156 RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) ==
156 static_cast<size_t>(frame.width())); 157 static_cast<size_t>(frame->width()));
157 158
158 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0); 159 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0);
159 if (cvRet != kCVReturnSuccess) { 160 if (cvRet != kCVReturnSuccess) {
160 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet; 161 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet;
161 return false; 162 return false;
162 } 163 }
163 uint8_t* dst_y = reinterpret_cast<uint8_t*>( 164 uint8_t* dst_y = reinterpret_cast<uint8_t*>(
164 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0)); 165 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0));
165 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); 166 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0);
166 uint8_t* dst_uv = reinterpret_cast<uint8_t*>( 167 uint8_t* dst_uv = reinterpret_cast<uint8_t*>(
167 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 1)); 168 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 1));
168 int dst_stride_uv = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 1); 169 int dst_stride_uv = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 1);
169 // Convert I420 to NV12. 170 // Convert I420 to NV12.
170 int ret = libyuv::I420ToNV12( 171 int ret = libyuv::I420ToNV12(
171 frame.video_frame_buffer()->DataY(), 172 frame->DataY(), frame->StrideY(),
172 frame.video_frame_buffer()->StrideY(), 173 frame->DataU(), frame->StrideU(),
173 frame.video_frame_buffer()->DataU(), 174 frame->DataV(), frame->StrideV(),
174 frame.video_frame_buffer()->StrideU(),
175 frame.video_frame_buffer()->DataV(),
176 frame.video_frame_buffer()->StrideV(),
177 dst_y, dst_stride_y, dst_uv, dst_stride_uv, 175 dst_y, dst_stride_y, dst_uv, dst_stride_uv,
178 frame.width(), frame.height()); 176 frame->width(), frame->height());
179 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); 177 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0);
180 if (ret) { 178 if (ret) {
181 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret; 179 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret;
182 return false; 180 return false;
183 } 181 }
184 return true; 182 return true;
185 } 183 }
186 184
187 // This is the callback function that VideoToolbox calls when encode is 185 // This is the callback function that VideoToolbox calls when encode is
188 // complete. From inspection this happens on its own queue. 186 // complete. From inspection this happens on its own queue.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 // We can only set average bitrate on the HW encoder. 238 // We can only set average bitrate on the HW encoder.
241 target_bitrate_bps_ = codec_settings->startBitrate; 239 target_bitrate_bps_ = codec_settings->startBitrate;
242 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); 240 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
243 241
244 // TODO(tkchin): Try setting payload size via 242 // TODO(tkchin): Try setting payload size via
245 // kVTCompressionPropertyKey_MaxH264SliceBytes. 243 // kVTCompressionPropertyKey_MaxH264SliceBytes.
246 244
247 return ResetCompressionSession(); 245 return ResetCompressionSession();
248 } 246 }
249 247
250 const VideoFrame& H264VideoToolboxEncoder::GetScaledFrameOnEncode( 248 rtc::scoped_refptr<VideoFrameBuffer>
251 const VideoFrame& frame) { 249 H264VideoToolboxEncoder::GetScaledBufferOnEncode(
250 const rtc::scoped_refptr<VideoFrameBuffer>& frame) {
252 rtc::CritScope lock(&quality_scaler_crit_); 251 rtc::CritScope lock(&quality_scaler_crit_);
253 quality_scaler_.OnEncodeFrame(frame); 252 quality_scaler_.OnEncodeFrame(frame->width(), frame->height());
254 return quality_scaler_.GetScaledFrame(frame); 253 return quality_scaler_.GetScaledBuffer(frame);
255 } 254 }
256 255
257 int H264VideoToolboxEncoder::Encode( 256 int H264VideoToolboxEncoder::Encode(
258 const VideoFrame& frame, 257 const VideoFrame& frame,
259 const CodecSpecificInfo* codec_specific_info, 258 const CodecSpecificInfo* codec_specific_info,
260 const std::vector<FrameType>* frame_types) { 259 const std::vector<FrameType>* frame_types) {
261 RTC_DCHECK(!frame.IsZeroSize()); 260 RTC_DCHECK(!frame.IsZeroSize());
262 if (!callback_ || !compression_session_) { 261 if (!callback_ || !compression_session_) {
263 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 262 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
264 } 263 }
265 #if defined(WEBRTC_IOS) 264 #if defined(WEBRTC_IOS)
266 if (!RTCIsUIApplicationActive()) { 265 if (!RTCIsUIApplicationActive()) {
267 // Ignore all encode requests when app isn't active. In this state, the 266 // Ignore all encode requests when app isn't active. In this state, the
268 // hardware encoder has been invalidated by the OS. 267 // hardware encoder has been invalidated by the OS.
269 return WEBRTC_VIDEO_CODEC_OK; 268 return WEBRTC_VIDEO_CODEC_OK;
270 } 269 }
271 #endif 270 #endif
272 bool is_keyframe_required = false; 271 bool is_keyframe_required = false;
273 const VideoFrame& input_image = GetScaledFrameOnEncode(frame); 272 rtc::scoped_refptr<VideoFrameBuffer> input_image(
273 GetScaledBufferOnEncode(frame.video_frame_buffer()));
274 274
275 if (input_image.width() != width_ || input_image.height() != height_) { 275 if (input_image->width() != width_ || input_image->height() != height_) {
276 width_ = input_image.width(); 276 width_ = input_image->width();
277 height_ = input_image.height(); 277 height_ = input_image->height();
278 int ret = ResetCompressionSession(); 278 int ret = ResetCompressionSession();
279 if (ret < 0) 279 if (ret < 0)
280 return ret; 280 return ret;
281 } 281 }
282 282
283 // Get a pixel buffer from the pool and copy frame data over. 283 // Get a pixel buffer from the pool and copy frame data over.
284 CVPixelBufferPoolRef pixel_buffer_pool = 284 CVPixelBufferPoolRef pixel_buffer_pool =
285 VTCompressionSessionGetPixelBufferPool(compression_session_); 285 VTCompressionSessionGetPixelBufferPool(compression_session_);
286 #if defined(WEBRTC_IOS) 286 #if defined(WEBRTC_IOS)
287 if (!pixel_buffer_pool) { 287 if (!pixel_buffer_pool) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 if (!is_keyframe_required && frame_types) { 320 if (!is_keyframe_required && frame_types) {
321 for (auto frame_type : *frame_types) { 321 for (auto frame_type : *frame_types) {
322 if (frame_type == kVideoFrameKey) { 322 if (frame_type == kVideoFrameKey) {
323 is_keyframe_required = true; 323 is_keyframe_required = true;
324 break; 324 break;
325 } 325 }
326 } 326 }
327 } 327 }
328 328
329 CMTime presentation_time_stamp = 329 CMTime presentation_time_stamp =
330 CMTimeMake(input_image.render_time_ms(), 1000); 330 CMTimeMake(frame.render_time_ms(), 1000);
331 CFDictionaryRef frame_properties = nullptr; 331 CFDictionaryRef frame_properties = nullptr;
332 if (is_keyframe_required) { 332 if (is_keyframe_required) {
333 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; 333 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame};
334 CFTypeRef values[] = {kCFBooleanTrue}; 334 CFTypeRef values[] = {kCFBooleanTrue};
335 frame_properties = internal::CreateCFDictionary(keys, values, 1); 335 frame_properties = internal::CreateCFDictionary(keys, values, 1);
336 } 336 }
337 std::unique_ptr<internal::FrameEncodeParams> encode_params; 337 std::unique_ptr<internal::FrameEncodeParams> encode_params;
338 encode_params.reset(new internal::FrameEncodeParams( 338 encode_params.reset(new internal::FrameEncodeParams(
339 this, codec_specific_info, width_, height_, input_image.render_time_ms(), 339 this, codec_specific_info, width_, height_, frame.render_time_ms(),
340 input_image.timestamp(), input_image.rotation())); 340 frame.timestamp(), frame.rotation()));
341 341
342 // Update the bitrate if needed. 342 // Update the bitrate if needed.
343 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); 343 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps());
344 344
345 OSStatus status = VTCompressionSessionEncodeFrame( 345 OSStatus status = VTCompressionSessionEncodeFrame(
346 compression_session_, pixel_buffer, presentation_time_stamp, 346 compression_session_, pixel_buffer, presentation_time_stamp,
347 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr); 347 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr);
348 if (frame_properties) { 348 if (frame_properties) {
349 CFRelease(frame_properties); 349 CFRelease(frame_properties);
350 } 350 }
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 if (result != 0) { 567 if (result != 0) {
568 LOG(LS_ERROR) << "Encode callback failed: " << result; 568 LOG(LS_ERROR) << "Encode callback failed: " << result;
569 return; 569 return;
570 } 570 }
571 bitrate_adjuster_.Update(frame._size); 571 bitrate_adjuster_.Update(frame._size);
572 } 572 }
573 573
574 } // namespace webrtc 574 } // namespace webrtc
575 575
576 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 576 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698