| Index: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.mm
|
| diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.mm b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.mm
|
| index 43c3fe575bdc1e9886a2de1966e529bbe1aeeb38..2d1e2a1416d350e02da3db3a17f7ec00a085c206 100644
|
| --- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.mm
|
| +++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.mm
|
| @@ -155,12 +155,12 @@ bool CopyVideoFrameToPixelBuffer(
|
| const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& frame,
|
| CVPixelBufferRef pixel_buffer) {
|
| RTC_DCHECK(pixel_buffer);
|
| - RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) ==
|
| - kCVPixelFormatType_420YpCbCr8BiPlanarFullRange);
|
| - RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) ==
|
| - static_cast<size_t>(frame->height()));
|
| - RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) ==
|
| - static_cast<size_t>(frame->width()));
|
| + RTC_DCHECK_EQ(CVPixelBufferGetPixelFormatType(pixel_buffer),
|
| + kCVPixelFormatType_420YpCbCr8BiPlanarFullRange);
|
| + RTC_DCHECK_EQ(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0),
|
| + static_cast<size_t>(frame->height()));
|
| + RTC_DCHECK_EQ(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0),
|
| + static_cast<size_t>(frame->width()));
|
|
|
| CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0);
|
| if (cvRet != kCVReturnSuccess) {
|
| @@ -218,13 +218,7 @@ namespace webrtc {
|
| H264VideoToolboxEncoder::H264VideoToolboxEncoder()
|
| : callback_(nullptr),
|
| compression_session_(nullptr),
|
| - bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95),
|
| - enable_scaling_(true) {
|
| -#if defined(WEBRTC_IOS)
|
| - if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) {
|
| - enable_scaling_ = false;
|
| - }
|
| -#endif
|
| + bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95) {
|
| }
|
|
|
| H264VideoToolboxEncoder::~H264VideoToolboxEncoder() {
|
| @@ -236,8 +230,6 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
|
| size_t max_payload_size) {
|
| RTC_DCHECK(codec_settings);
|
| RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
|
| - width_ = codec_settings->width;
|
| - height_ = codec_settings->height;
|
| {
|
| rtc::CritScope lock(&quality_scaler_crit_);
|
| quality_scaler_.Init(QualityScaler::kLowH264QpThreshold,
|
| @@ -247,10 +239,8 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
|
| QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
| // TODO(tkchin): We may need to enforce width/height dimension restrictions
|
| // to match what the encoder supports.
|
| - if (enable_scaling_) {
|
| - width_ = res.width;
|
| - height_ = res.height;
|
| - }
|
| + width_ = res.width;
|
| + height_ = res.height;
|
| }
|
| // We can only set average bitrate on the HW encoder.
|
| target_bitrate_bps_ = codec_settings->startBitrate;
|
| @@ -262,24 +252,6 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
|
| return ResetCompressionSession();
|
| }
|
|
|
| -rtc::scoped_refptr<VideoFrameBuffer>
|
| -H264VideoToolboxEncoder::GetScaledBufferOnEncode(
|
| - const rtc::scoped_refptr<VideoFrameBuffer>& frame) {
|
| - rtc::CritScope lock(&quality_scaler_crit_);
|
| - quality_scaler_.OnEncodeFrame(frame->width(), frame->height());
|
| - if (!frame->native_handle())
|
| - return quality_scaler_.GetScaledBuffer(frame);
|
| -
|
| - // Handle native (CVImageRef) scaling.
|
| - const QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
| - if (!enable_scaling_ ||
|
| - (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(
|
| const VideoFrame& frame,
|
| const CodecSpecificInfo* codec_specific_info,
|
| @@ -296,12 +268,14 @@ int H264VideoToolboxEncoder::Encode(
|
| }
|
| #endif
|
| bool is_keyframe_required = false;
|
| - rtc::scoped_refptr<VideoFrameBuffer> input_image(
|
| - GetScaledBufferOnEncode(frame.video_frame_buffer()));
|
|
|
| - if (input_image->width() != width_ || input_image->height() != height_) {
|
| - width_ = input_image->width();
|
| - height_ = input_image->height();
|
| + quality_scaler_.OnEncodeFrame(frame.width(), frame.height());
|
| + const QualityScaler::Resolution scaled_res =
|
| + quality_scaler_.GetScaledResolution();
|
| +
|
| + if (scaled_res.width != width_ || scaled_res.height != height_) {
|
| + width_ = scaled_res.width;
|
| + height_ = scaled_res.height;
|
| int ret = ResetCompressionSession();
|
| if (ret < 0)
|
| return ret;
|
| @@ -325,9 +299,13 @@ int H264VideoToolboxEncoder::Encode(
|
| }
|
| #endif
|
|
|
| - CVPixelBufferRef pixel_buffer =
|
| - static_cast<CVPixelBufferRef>(input_image->native_handle());
|
| + CVPixelBufferRef pixel_buffer = static_cast<CVPixelBufferRef>(
|
| + frame.video_frame_buffer()->native_handle());
|
| if (pixel_buffer) {
|
| + // This pixel buffer might have a higher resolution than what the
|
| + // compression session is configured to. The compression session can handle
|
| + // that and will output encoded frames in the configured resolution
|
| + // regardless of the input pixel buffer resolution.
|
| CVBufferRetain(pixel_buffer);
|
| pixel_buffer_pool = nullptr;
|
| } else {
|
| @@ -344,7 +322,12 @@ int H264VideoToolboxEncoder::Encode(
|
| return WEBRTC_VIDEO_CODEC_ERROR;
|
| }
|
| RTC_DCHECK(pixel_buffer);
|
| - if (!internal::CopyVideoFrameToPixelBuffer(input_image, pixel_buffer)) {
|
| + // TODO(magjed): Optimize by merging scaling and NV12 pixel buffer
|
| + // conversion once libyuv::MergeUVPlanes is available.
|
| + rtc::scoped_refptr<VideoFrameBuffer> scaled_i420_buffer =
|
| + quality_scaler_.GetScaledBuffer(frame.video_frame_buffer());
|
| + if (!internal::CopyVideoFrameToPixelBuffer(scaled_i420_buffer,
|
| + pixel_buffer)) {
|
| LOG(LS_ERROR) << "Failed to copy frame data.";
|
| CVBufferRelease(pixel_buffer);
|
| return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|