H264VideoToolboxEncoder: Add support for native handles

Support encoding from CVPixelBuffers directly in H264VideoToolboxEncoder.
If the frame needs to be scaled, it will fall back to the previous slow
path:
CVPixelBuffer -> NV12 -> I420 -> (scale) I420 -> NV12 -> CVPixelBuffer.

BUG=webrtc:4081

Review-Url: https://codereview.webrtc.org/2140573002
Cr-Commit-Position: refs/heads/master@{#13439}
This commit is contained in:
magjed
2016-07-12 01:26:42 -07:00
committed by Commit bot
parent b89257a51b
commit 11dd52bcc6
2 changed files with 53 additions and 33 deletions

View File

@ -250,7 +250,16 @@ H264VideoToolboxEncoder::GetScaledBufferOnEncode(
const rtc::scoped_refptr<VideoFrameBuffer>& frame) { const rtc::scoped_refptr<VideoFrameBuffer>& frame) {
rtc::CritScope lock(&quality_scaler_crit_); rtc::CritScope lock(&quality_scaler_crit_);
quality_scaler_.OnEncodeFrame(frame->width(), frame->height()); quality_scaler_.OnEncodeFrame(frame->width(), frame->height());
if (!frame->native_handle())
return quality_scaler_.GetScaledBuffer(frame); 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( int H264VideoToolboxEncoder::Encode(
@ -280,6 +289,11 @@ int H264VideoToolboxEncoder::Encode(
return ret; return ret;
} }
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. // Get a pixel buffer from the pool and copy frame data over.
CVPixelBufferPoolRef pixel_buffer_pool = CVPixelBufferPoolRef pixel_buffer_pool =
VTCompressionSessionGetPixelBufferPool(compression_session_); VTCompressionSessionGetPixelBufferPool(compression_session_);
@ -300,9 +314,8 @@ int H264VideoToolboxEncoder::Encode(
LOG(LS_ERROR) << "Failed to get pixel buffer pool."; LOG(LS_ERROR) << "Failed to get pixel buffer pool.";
return WEBRTC_VIDEO_CODEC_ERROR; return WEBRTC_VIDEO_CODEC_ERROR;
} }
CVPixelBufferRef pixel_buffer = nullptr; CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(
CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nullptr, pixel_buffer_pool, nullptr, pixel_buffer_pool, &pixel_buffer);
&pixel_buffer);
if (ret != kCVReturnSuccess) { if (ret != kCVReturnSuccess) {
LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret; LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret;
// We probably want to drop frames here, since failure probably means // We probably want to drop frames here, since failure probably means
@ -315,6 +328,7 @@ int H264VideoToolboxEncoder::Encode(
CVBufferRelease(pixel_buffer); CVBufferRelease(pixel_buffer);
return WEBRTC_VIDEO_CODEC_ERROR; return WEBRTC_VIDEO_CODEC_ERROR;
} }
}
// Check if we need a keyframe. // Check if we need a keyframe.
if (!is_keyframe_required && frame_types) { if (!is_keyframe_required && frame_types) {
@ -488,6 +502,10 @@ const char* H264VideoToolboxEncoder::ImplementationName() const {
return "VideoToolbox"; return "VideoToolbox";
} }
bool H264VideoToolboxEncoder::SupportsNativeHandle() const {
return true;
}
void H264VideoToolboxEncoder::SetBitrateBps(uint32_t bitrate_bps) { void H264VideoToolboxEncoder::SetBitrateBps(uint32_t bitrate_bps) {
if (encoder_bitrate_bps_ != bitrate_bps) { if (encoder_bitrate_bps_ != bitrate_bps) {
SetEncoderBitrateBps(bitrate_bps); SetEncoderBitrateBps(bitrate_bps);

View File

@ -56,6 +56,8 @@ class H264VideoToolboxEncoder : public H264Encoder {
const char* ImplementationName() const override; const char* ImplementationName() const override;
bool SupportsNativeHandle() const override;
void OnEncodedFrame(OSStatus status, void OnEncodedFrame(OSStatus status,
VTEncodeInfoFlags info_flags, VTEncodeInfoFlags info_flags,
CMSampleBufferRef sample_buffer, CMSampleBufferRef sample_buffer,