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:
@ -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);
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user