| Index: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
|
| index a7bd5e2040d131dd03c462d7b1b47a511bea6fdf..bbf3f0f8f62ce90f4375770db4361a6b833e9707 100644
|
| --- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
|
| +++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
|
| @@ -250,7 +250,16 @@ H264VideoToolboxEncoder::GetScaledBufferOnEncode(
|
| const rtc::scoped_refptr<VideoFrameBuffer>& frame) {
|
| rtc::CritScope lock(&quality_scaler_crit_);
|
| quality_scaler_.OnEncodeFrame(frame->width(), frame->height());
|
| - return quality_scaler_.GetScaledBuffer(frame);
|
| + if (!frame->native_handle())
|
| + return quality_scaler_.GetScaledBuffer(frame);
|
| +
|
| + // Handle native (CVImageRef) scaling.
|
| + const QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
| + if (res.width == frame->width() && res.height == frame->height())
|
| + return frame;
|
| + // TODO(magjed): Implement efficient CVImageRef -> CVImageRef scaling instead
|
| + // of doing it via I420.
|
| + return quality_scaler_.GetScaledBuffer(frame->NativeToI420Buffer());
|
| }
|
|
|
| int H264VideoToolboxEncoder::Encode(
|
| @@ -280,40 +289,45 @@ int H264VideoToolboxEncoder::Encode(
|
| return ret;
|
| }
|
|
|
| - // Get a pixel buffer from the pool and copy frame data over.
|
| - CVPixelBufferPoolRef pixel_buffer_pool =
|
| - VTCompressionSessionGetPixelBufferPool(compression_session_);
|
| -#if defined(WEBRTC_IOS)
|
| - if (!pixel_buffer_pool) {
|
| - // Kind of a hack. On backgrounding, the compression session seems to get
|
| - // invalidated, which causes this pool call to fail when the application
|
| - // is foregrounded and frames are being sent for encoding again.
|
| - // Resetting the session when this happens fixes the issue.
|
| - // In addition we request a keyframe so video can recover quickly.
|
| - ResetCompressionSession();
|
| - pixel_buffer_pool =
|
| + CVPixelBufferRef pixel_buffer =
|
| + static_cast<CVPixelBufferRef>(input_image->native_handle());
|
| + if (pixel_buffer) {
|
| + CVBufferRetain(pixel_buffer);
|
| + } else {
|
| + // Get a pixel buffer from the pool and copy frame data over.
|
| + CVPixelBufferPoolRef pixel_buffer_pool =
|
| VTCompressionSessionGetPixelBufferPool(compression_session_);
|
| - is_keyframe_required = true;
|
| - }
|
| +#if defined(WEBRTC_IOS)
|
| + if (!pixel_buffer_pool) {
|
| + // Kind of a hack. On backgrounding, the compression session seems to get
|
| + // invalidated, which causes this pool call to fail when the application
|
| + // is foregrounded and frames are being sent for encoding again.
|
| + // Resetting the session when this happens fixes the issue.
|
| + // In addition we request a keyframe so video can recover quickly.
|
| + ResetCompressionSession();
|
| + pixel_buffer_pool =
|
| + VTCompressionSessionGetPixelBufferPool(compression_session_);
|
| + is_keyframe_required = true;
|
| + }
|
| #endif
|
| - if (!pixel_buffer_pool) {
|
| - LOG(LS_ERROR) << "Failed to get pixel buffer pool.";
|
| - return WEBRTC_VIDEO_CODEC_ERROR;
|
| - }
|
| - CVPixelBufferRef pixel_buffer = nullptr;
|
| - CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nullptr, pixel_buffer_pool,
|
| - &pixel_buffer);
|
| - if (ret != kCVReturnSuccess) {
|
| - LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret;
|
| - // We probably want to drop frames here, since failure probably means
|
| - // that the pool is empty.
|
| - return WEBRTC_VIDEO_CODEC_ERROR;
|
| - }
|
| - RTC_DCHECK(pixel_buffer);
|
| - if (!internal::CopyVideoFrameToPixelBuffer(input_image, pixel_buffer)) {
|
| - LOG(LS_ERROR) << "Failed to copy frame data.";
|
| - CVBufferRelease(pixel_buffer);
|
| - return WEBRTC_VIDEO_CODEC_ERROR;
|
| + if (!pixel_buffer_pool) {
|
| + LOG(LS_ERROR) << "Failed to get pixel buffer pool.";
|
| + return WEBRTC_VIDEO_CODEC_ERROR;
|
| + }
|
| + CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(
|
| + nullptr, pixel_buffer_pool, &pixel_buffer);
|
| + if (ret != kCVReturnSuccess) {
|
| + LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret;
|
| + // We probably want to drop frames here, since failure probably means
|
| + // that the pool is empty.
|
| + return WEBRTC_VIDEO_CODEC_ERROR;
|
| + }
|
| + RTC_DCHECK(pixel_buffer);
|
| + if (!internal::CopyVideoFrameToPixelBuffer(input_image, pixel_buffer)) {
|
| + LOG(LS_ERROR) << "Failed to copy frame data.";
|
| + CVBufferRelease(pixel_buffer);
|
| + return WEBRTC_VIDEO_CODEC_ERROR;
|
| + }
|
| }
|
|
|
| // Check if we need a keyframe.
|
| @@ -488,6 +502,10 @@ const char* H264VideoToolboxEncoder::ImplementationName() const {
|
| return "VideoToolbox";
|
| }
|
|
|
| +bool H264VideoToolboxEncoder::SupportsNativeHandle() const {
|
| + return true;
|
| +}
|
| +
|
| void H264VideoToolboxEncoder::SetBitrateBps(uint32_t bitrate_bps) {
|
| if (encoder_bitrate_bps_ != bitrate_bps) {
|
| SetEncoderBitrateBps(bitrate_bps);
|
|
|