Chromium Code Reviews| OLD | NEW | 
|---|---|
| 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 */ | 
| 11 | 11 | 
| 12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h" | 12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h" | 
| 13 | 13 | 
| 14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 
| 15 | 15 | 
| 16 #include <memory> | 16 #include <memory> | 
| 17 #include <string> | 17 #include <string> | 
| 18 #include <vector> | 18 #include <vector> | 
| 19 | 19 | 
| 20 #if defined(WEBRTC_IOS) | 20 #if defined(WEBRTC_IOS) | 
| 21 #import "WebRTC/UIDevice+RTCDevice.h" | 21 #import "WebRTC/UIDevice+RTCDevice.h" | 
| 22 #include "RTCUIApplication.h" | 22 #include "RTCUIApplication.h" | 
| 23 #endif | 23 #endif | 
| 24 #include "libyuv/convert_from.h" | 24 #include "libyuv/convert_from.h" | 
| 25 #include "webrtc/base/checks.h" | 25 #include "webrtc/base/checks.h" | 
| 26 #include "webrtc/base/logging.h" | 26 #include "webrtc/base/logging.h" | 
| 27 #include "webrtc/common_video/include/corevideo_frame_buffer.h" | |
| 27 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h" | 28 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h" | 
| 28 #include "webrtc/system_wrappers/include/clock.h" | 29 #include "webrtc/system_wrappers/include/clock.h" | 
| 29 | 30 | 
| 30 namespace internal { | 31 namespace internal { | 
| 31 | 32 | 
| 32 // The ratio between kVTCompressionPropertyKey_DataRateLimits and | 33 // The ratio between kVTCompressionPropertyKey_DataRateLimits and | 
| 33 // kVTCompressionPropertyKey_AverageBitRate. The data rate limit is set higher | 34 // kVTCompressionPropertyKey_AverageBitRate. The data rate limit is set higher | 
| 34 // than the average bit rate to avoid undershooting the target. | 35 // than the average bit rate to avoid undershooting the target. | 
| 35 const float kLimitToAverageBitRateFactor = 1.5f; | 36 const float kLimitToAverageBitRateFactor = 1.5f; | 
| 36 // These thresholds deviate from the default h264 QP thresholds, as they | 37 // These thresholds deviate from the default h264 QP thresholds, as they | 
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 dst_y, dst_stride_y, dst_uv, dst_stride_uv, | 186 dst_y, dst_stride_y, dst_uv, dst_stride_uv, | 
| 186 frame->width(), frame->height()); | 187 frame->width(), frame->height()); | 
| 187 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); | 188 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); | 
| 188 if (ret) { | 189 if (ret) { | 
| 189 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret; | 190 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret; | 
| 190 return false; | 191 return false; | 
| 191 } | 192 } | 
| 192 return true; | 193 return true; | 
| 193 } | 194 } | 
| 194 | 195 | 
| 196 CVPixelBufferRef CreatePixelBuffer(CVPixelBufferPoolRef pixel_buffer_pool) { | |
| 197 if (!pixel_buffer_pool) { | |
| 198 LOG(LS_ERROR) << "Failed to get pixel buffer pool."; | |
| 199 return nil; | |
| 
 
tkchin_webrtc
2016/10/19 00:48:32
nullptr
 
magjed_webrtc
2016/10/19 13:19:34
Done.
 
 | |
| 200 } | |
| 201 CVPixelBufferRef pixel_buffer; | |
| 202 CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nullptr, pixel_buffer_pool, | |
| 203 &pixel_buffer); | |
| 204 if (ret != kCVReturnSuccess) { | |
| 205 LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret; | |
| 206 // We probably want to drop frames here, since failure probably means | |
| 207 // that the pool is empty. | |
| 208 return nil; | |
| 
 
tkchin_webrtc
2016/10/19 00:48:32
CVPixelBufferRef isn't an object, so return nullpt
 
magjed_webrtc
2016/10/19 13:19:34
Done.
 
 | |
| 209 } | |
| 210 return pixel_buffer; | |
| 211 } | |
| 212 | |
| 195 // This is the callback function that VideoToolbox calls when encode is | 213 // This is the callback function that VideoToolbox calls when encode is | 
| 196 // complete. From inspection this happens on its own queue. | 214 // complete. From inspection this happens on its own queue. | 
| 197 void VTCompressionOutputCallback(void* encoder, | 215 void VTCompressionOutputCallback(void* encoder, | 
| 198 void* params, | 216 void* params, | 
| 199 OSStatus status, | 217 OSStatus status, | 
| 200 VTEncodeInfoFlags info_flags, | 218 VTEncodeInfoFlags info_flags, | 
| 201 CMSampleBufferRef sample_buffer) { | 219 CMSampleBufferRef sample_buffer) { | 
| 202 std::unique_ptr<FrameEncodeParams> encode_params( | 220 std::unique_ptr<FrameEncodeParams> encode_params( | 
| 203 reinterpret_cast<FrameEncodeParams*>(params)); | 221 reinterpret_cast<FrameEncodeParams*>(params)); | 
| 204 encode_params->encoder->OnEncodedFrame( | 222 encode_params->encoder->OnEncodedFrame( | 
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 pixel_buffer_pool = | 317 pixel_buffer_pool = | 
| 300 VTCompressionSessionGetPixelBufferPool(compression_session_); | 318 VTCompressionSessionGetPixelBufferPool(compression_session_); | 
| 301 is_keyframe_required = true; | 319 is_keyframe_required = true; | 
| 302 LOG(LS_INFO) << "Resetting compression session due to invalid pool."; | 320 LOG(LS_INFO) << "Resetting compression session due to invalid pool."; | 
| 303 } | 321 } | 
| 304 #endif | 322 #endif | 
| 305 | 323 | 
| 306 CVPixelBufferRef pixel_buffer = static_cast<CVPixelBufferRef>( | 324 CVPixelBufferRef pixel_buffer = static_cast<CVPixelBufferRef>( | 
| 307 frame.video_frame_buffer()->native_handle()); | 325 frame.video_frame_buffer()->native_handle()); | 
| 308 if (pixel_buffer) { | 326 if (pixel_buffer) { | 
| 309 // This pixel buffer might have a higher resolution than what the | 327 // Native frame. | 
| 310 // compression session is configured to. The compression session can handle | 328 rtc::scoped_refptr<CoreVideoFrameBuffer> core_video_frame_buffer( | 
| 311 // that and will output encoded frames in the configured resolution | 329 static_cast<CoreVideoFrameBuffer*>(frame.video_frame_buffer().get())); | 
| 312 // regardless of the input pixel buffer resolution. | 330 if (!core_video_frame_buffer->RequiresCropping()) { | 
| 313 CVBufferRetain(pixel_buffer); | 331 // This pixel buffer might have a higher resolution than what the | 
| 314 pixel_buffer_pool = nullptr; | 332 // compression session is configured to. The compression session can | 
| 333 // handle that and will output encoded frames in the configured | |
| 334 // resolution regardless of the input pixel buffer resolution. | |
| 335 CVBufferRetain(pixel_buffer); | |
| 336 } else { | |
| 337 // Cropping required, we need to crop and scale to a new pixel buffer. | |
| 338 pixel_buffer = internal::CreatePixelBuffer(pixel_buffer_pool); | |
| 339 if (!pixel_buffer) { | |
| 340 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 341 } | |
| 342 if (!core_video_frame_buffer->CropAndScaleTo(&nv12_scale_buffer_, | |
| 343 pixel_buffer)) { | |
| 344 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 345 } | |
| 346 } | |
| 315 } else { | 347 } else { | 
| 316 if (!pixel_buffer_pool) { | 348 pixel_buffer = internal::CreatePixelBuffer(pixel_buffer_pool); | 
| 317 LOG(LS_ERROR) << "Failed to get pixel buffer pool."; | 349 if (!pixel_buffer) { | 
| 318 return WEBRTC_VIDEO_CODEC_ERROR; | 350 return WEBRTC_VIDEO_CODEC_ERROR; | 
| 319 } | 351 } | 
| 320 CVReturn ret = CVPixelBufferPoolCreatePixelBuffer( | |
| 321 nullptr, pixel_buffer_pool, &pixel_buffer); | |
| 322 if (ret != kCVReturnSuccess) { | |
| 323 LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret; | |
| 324 // We probably want to drop frames here, since failure probably means | |
| 325 // that the pool is empty. | |
| 326 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 327 } | |
| 328 RTC_DCHECK(pixel_buffer); | |
| 329 // TODO(magjed): Optimize by merging scaling and NV12 pixel buffer | 352 // TODO(magjed): Optimize by merging scaling and NV12 pixel buffer | 
| 330 // conversion once libyuv::MergeUVPlanes is available. | 353 // conversion once libyuv::MergeUVPlanes is available. | 
| 331 rtc::scoped_refptr<VideoFrameBuffer> scaled_i420_buffer = | 354 rtc::scoped_refptr<VideoFrameBuffer> scaled_i420_buffer = | 
| 332 quality_scaler_.GetScaledBuffer(frame.video_frame_buffer()); | 355 quality_scaler_.GetScaledBuffer(frame.video_frame_buffer()); | 
| 333 if (!internal::CopyVideoFrameToPixelBuffer(scaled_i420_buffer, | 356 if (!internal::CopyVideoFrameToPixelBuffer(scaled_i420_buffer, | 
| 334 pixel_buffer)) { | 357 pixel_buffer)) { | 
| 335 LOG(LS_ERROR) << "Failed to copy frame data."; | 358 LOG(LS_ERROR) << "Failed to copy frame data."; | 
| 336 CVBufferRelease(pixel_buffer); | 359 CVBufferRelease(pixel_buffer); | 
| 337 return WEBRTC_VIDEO_CODEC_ERROR; | 360 return WEBRTC_VIDEO_CODEC_ERROR; | 
| 338 } | 361 } | 
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 if (result != 0) { | 654 if (result != 0) { | 
| 632 LOG(LS_ERROR) << "Encode callback failed: " << result; | 655 LOG(LS_ERROR) << "Encode callback failed: " << result; | 
| 633 return; | 656 return; | 
| 634 } | 657 } | 
| 635 bitrate_adjuster_.Update(frame._size); | 658 bitrate_adjuster_.Update(frame._size); | 
| 636 } | 659 } | 
| 637 | 660 | 
| 638 } // namespace webrtc | 661 } // namespace webrtc | 
| 639 | 662 | 
| 640 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 663 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 
| OLD | NEW |