| 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; | 
|  |