Index: remoting/codec/video_decoder_vpx.cc |
diff --git a/remoting/codec/video_decoder_vpx.cc b/remoting/codec/video_decoder_vpx.cc |
index e414ee8e5e7a026c9e35a6351b16881c4259c19c..0be92018a618fd927b0818c3e1b53fd3c9ab36d5 100644 |
--- a/remoting/codec/video_decoder_vpx.cc |
+++ b/remoting/codec/video_decoder_vpx.cc |
@@ -12,6 +12,7 @@ |
#include "media/base/media.h" |
#include "media/base/yuv_convert.h" |
#include "remoting/base/util.h" |
+#include "third_party/libyuv/include/libyuv/convert_argb.h" |
extern "C" { |
#define VPX_CODEC_DISABLE_COMPAT 1 |
@@ -177,84 +178,128 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size, |
webrtc::DesktopRect source_clip = |
webrtc::DesktopRect::MakeWH(last_image_->d_w, last_image_->d_h); |
- // ScaleYUVToRGB32WithRect does not currently support up-scaling. We won't |
- // be asked to up-scale except during resizes or if page zoom is >100%, so |
- // we work-around the limitation by using the slower ScaleYUVToRGB32. |
- // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can up-scale. |
- if (!updated_region_.is_empty() && |
- (source_clip.width() < view_size.width() || |
- source_clip.height() < view_size.height())) { |
- // We're scaling only |clip_area| into the |image_buffer|, so we need to |
- // work out which source rectangle that corresponds to. |
- webrtc::DesktopRect source_rect = |
- ScaleRect(clip_area, view_size, screen_size_); |
- source_rect = webrtc::DesktopRect::MakeLTRB( |
- RoundToTwosMultiple(source_rect.left()), |
- RoundToTwosMultiple(source_rect.top()), |
- source_rect.right(), |
- source_rect.bottom()); |
- |
- // If there were no changes within the clip source area then don't render. |
- webrtc::DesktopRegion intersection(source_rect); |
- intersection.IntersectWith(updated_region_); |
- if (intersection.is_empty()) |
+ // VP8 only outputs I420 frames, but VP9 can also produce I444. |
+ switch (last_image_->fmt) { |
+ case VPX_IMG_FMT_I444: { |
+ // TODO(wez): Add scaling support to the I444 conversion path. |
+ if (view_size.equals(screen_size_)) { |
+ for (webrtc::DesktopRegion::Iterator i(updated_region_); |
+ !i.IsAtEnd(); i.Advance()) { |
+ // Determine the scaled area affected by this rectangle changing. |
+ webrtc::DesktopRect rect = i.rect(); |
+ rect.IntersectWith(source_clip); |
+ rect.IntersectWith(clip_area); |
+ if (rect.is_empty()) |
+ continue; |
+ |
+ int image_offset = image_stride * rect.top() + |
+ rect.left() * VideoDecoder::kBytesPerPixel; |
+ int y_offset = last_image_->stride[0] * rect.top() + rect.left(); |
+ int u_offset = last_image_->stride[1] * rect.top() + rect.left(); |
+ int v_offset = last_image_->stride[2] * rect.top() + rect.left(); |
+ libyuv::I444ToARGB(last_image_->planes[0] + y_offset, |
+ last_image_->stride[0], |
+ last_image_->planes[1] + u_offset, |
+ last_image_->stride[1], |
+ last_image_->planes[2] + v_offset, |
+ last_image_->stride[2], |
+ image_buffer + image_offset, image_stride, |
+ rect.width(), rect.height()); |
+ |
+ output_region->AddRect(rect); |
+ } |
+ } |
+ break; |
+ } |
+ case VPX_IMG_FMT_I420: { |
+ // ScaleYUVToRGB32WithRect does not currently support up-scaling. We |
+ // won't be asked to up-scale except during resizes or if page zoom is |
+ // >100%, so we work-around the limitation by using the slower |
+ // ScaleYUVToRGB32. |
+ // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can |
+ // up-scale. |
+ if (!updated_region_.is_empty() && |
+ (source_clip.width() < view_size.width() || |
+ source_clip.height() < view_size.height())) { |
+ // We're scaling only |clip_area| into the |image_buffer|, so we need to |
+ // work out which source rectangle that corresponds to. |
+ webrtc::DesktopRect source_rect = |
+ ScaleRect(clip_area, view_size, screen_size_); |
+ source_rect = webrtc::DesktopRect::MakeLTRB( |
+ RoundToTwosMultiple(source_rect.left()), |
+ RoundToTwosMultiple(source_rect.top()), |
+ source_rect.right(), |
+ source_rect.bottom()); |
+ |
+ // If there were no changes within the clip source area then don't |
+ // render. |
+ webrtc::DesktopRegion intersection(source_rect); |
+ intersection.IntersectWith(updated_region_); |
+ if (intersection.is_empty()) |
+ return; |
+ |
+ // Scale & convert the entire clip area. |
+ int y_offset = CalculateYOffset(source_rect.left(), source_rect.top(), |
+ last_image_->stride[0]); |
+ int uv_offset = CalculateUVOffset(source_rect.left(), source_rect.top(), |
+ last_image_->stride[1]); |
+ ScaleYUVToRGB32(last_image_->planes[0] + y_offset, |
+ last_image_->planes[1] + uv_offset, |
+ last_image_->planes[2] + uv_offset, |
+ image_buffer, |
+ source_rect.width(), |
+ source_rect.height(), |
+ clip_area.width(), |
+ clip_area.height(), |
+ last_image_->stride[0], |
+ last_image_->stride[1], |
+ image_stride, |
+ media::YV12, |
+ media::ROTATE_0, |
+ media::FILTER_BILINEAR); |
+ |
+ output_region->AddRect(clip_area); |
+ updated_region_.Subtract(source_rect); |
+ return; |
+ } |
+ |
+ for (webrtc::DesktopRegion::Iterator i(updated_region_); |
+ !i.IsAtEnd(); i.Advance()) { |
+ // Determine the scaled area affected by this rectangle changing. |
+ webrtc::DesktopRect rect = i.rect(); |
+ rect.IntersectWith(source_clip); |
+ if (rect.is_empty()) |
+ continue; |
+ rect = ScaleRect(rect, screen_size_, view_size); |
+ rect.IntersectWith(clip_area); |
+ if (rect.is_empty()) |
+ continue; |
+ |
+ ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], |
+ last_image_->planes[1], |
+ last_image_->planes[2], |
+ last_image_->stride[0], |
+ last_image_->stride[1], |
+ screen_size_, |
+ source_clip, |
+ image_buffer, |
+ image_stride, |
+ view_size, |
+ clip_area, |
+ rect); |
+ |
+ output_region->AddRect(rect); |
+ } |
+ |
+ updated_region_.Subtract(ScaleRect(clip_area, view_size, screen_size_)); |
+ break; |
+ } |
+ default: { |
+ LOG(ERROR) << "Unsupported image format:" << last_image_->fmt; |
return; |
- |
- // Scale & convert the entire clip area. |
- int y_offset = CalculateYOffset(source_rect.left(), source_rect.top(), |
- last_image_->stride[0]); |
- int uv_offset = CalculateUVOffset(source_rect.left(), source_rect.top(), |
- last_image_->stride[1]); |
- ScaleYUVToRGB32(last_image_->planes[0] + y_offset, |
- last_image_->planes[1] + uv_offset, |
- last_image_->planes[2] + uv_offset, |
- image_buffer, |
- source_rect.width(), |
- source_rect.height(), |
- clip_area.width(), |
- clip_area.height(), |
- last_image_->stride[0], |
- last_image_->stride[1], |
- image_stride, |
- media::YV12, |
- media::ROTATE_0, |
- media::FILTER_BILINEAR); |
- |
- output_region->AddRect(clip_area); |
- updated_region_.Subtract(source_rect); |
- return; |
- } |
- |
- for (webrtc::DesktopRegion::Iterator i(updated_region_); |
- !i.IsAtEnd(); i.Advance()) { |
- // Determine the scaled area affected by this rectangle changing. |
- webrtc::DesktopRect rect = i.rect(); |
- rect.IntersectWith(source_clip); |
- if (rect.is_empty()) |
- continue; |
- rect = ScaleRect(rect, screen_size_, view_size); |
- rect.IntersectWith(clip_area); |
- if (rect.is_empty()) |
- continue; |
- |
- ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], |
- last_image_->planes[1], |
- last_image_->planes[2], |
- last_image_->stride[0], |
- last_image_->stride[1], |
- screen_size_, |
- source_clip, |
- image_buffer, |
- image_stride, |
- view_size, |
- clip_area, |
- rect); |
- |
- output_region->AddRect(rect); |
+ } |
} |
- updated_region_.Subtract(ScaleRect(clip_area, view_size, screen_size_)); |
- |
for (webrtc::DesktopRegion::Iterator i(transparent_region_); |
!i.IsAtEnd(); i.Advance()) { |
// Determine the scaled area affected by this rectangle changing. |