Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: remoting/codec/video_decoder_vpx.cc

Issue 1236663002: Allow shaped-desktop hosts to send shape only when it changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Pepper 2D renderer build Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/codec/video_decoder_vpx.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/codec/video_decoder_vpx.cc
diff --git a/remoting/codec/video_decoder_vpx.cc b/remoting/codec/video_decoder_vpx.cc
index 7a8020f58eee0981e080d13e01ec81aa166299cf..b14d88886cc688a7ec2d0cf510395622045140f9 100644
--- a/remoting/codec/video_decoder_vpx.cc
+++ b/remoting/codec/video_decoder_vpx.cc
@@ -22,80 +22,25 @@ extern "C" {
namespace remoting {
-namespace {
-
-const uint32 kTransparentColor = 0;
-
-// Fills the rectangle |rect| with the given ARGB color |color| in |buffer|.
-void FillRect(uint8* buffer,
- int stride,
- const webrtc::DesktopRect& rect,
- uint32 color) {
- uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) +
- (rect.left() * VideoDecoder::kBytesPerPixel));
- int width = rect.width();
- for (int height = rect.height(); height > 0; --height) {
- std::fill(ptr, ptr + width, color);
- ptr += stride / VideoDecoder::kBytesPerPixel;
- }
-}
-
-} // namespace
-
// static
scoped_ptr<VideoDecoderVpx> VideoDecoderVpx::CreateForVP8() {
- ScopedVpxCodec codec(new vpx_codec_ctx_t);
-
- // TODO(hclam): Scale the number of threads with number of cores of the
- // machine.
- vpx_codec_dec_cfg config;
- config.w = 0;
- config.h = 0;
- config.threads = 2;
- vpx_codec_err_t ret =
- vpx_codec_dec_init(codec.get(), vpx_codec_vp8_dx(), &config, 0);
- if (ret != VPX_CODEC_OK) {
- LOG(ERROR) << "Cannot initialize codec.";
- return nullptr;
- }
-
- return make_scoped_ptr(new VideoDecoderVpx(codec.Pass()));
+ return make_scoped_ptr(new VideoDecoderVpx(vpx_codec_vp8_dx()));
}
// static
scoped_ptr<VideoDecoderVpx> VideoDecoderVpx::CreateForVP9() {
- ScopedVpxCodec codec(new vpx_codec_ctx_t);
-
- // TODO(hclam): Scale the number of threads with number of cores of the
- // machine.
- vpx_codec_dec_cfg config;
- config.w = 0;
- config.h = 0;
- config.threads = 2;
- vpx_codec_err_t ret =
- vpx_codec_dec_init(codec.get(), vpx_codec_vp9_dx(), &config, 0);
- if (ret != VPX_CODEC_OK) {
- LOG(ERROR) << "Cannot initialize codec.";
- return nullptr;
- }
-
- return make_scoped_ptr(new VideoDecoderVpx(codec.Pass()));
+ return make_scoped_ptr(new VideoDecoderVpx(vpx_codec_vp9_dx()));
}
VideoDecoderVpx::~VideoDecoderVpx() {}
-void VideoDecoderVpx::Initialize(const webrtc::DesktopSize& screen_size) {
- DCHECK(!screen_size.is_empty());
-
- screen_size_ = screen_size;
-
- transparent_region_.SetRect(webrtc::DesktopRect::MakeSize(screen_size_));
+void VideoDecoderVpx::Initialize(const webrtc::DesktopSize& source_size) {
+ // Nothing to do here; the codec handles resizing internally, and returns
+ // the source dimensions as part of the vpx_image_t.
}
bool VideoDecoderVpx::DecodePacket(const VideoPacket& packet) {
- DCHECK(!screen_size_.is_empty());
-
- // Do the actual decoding.
+ // Pass the packet to the codec to process.
vpx_codec_err_t ret = vpx_codec_decode(
codec_.get(), reinterpret_cast<const uint8*>(packet.data().data()),
packet.data().size(), nullptr, 0);
@@ -107,15 +52,16 @@ bool VideoDecoderVpx::DecodePacket(const VideoPacket& packet) {
return false;
}
- // Gets the decoded data.
+ // Fetch the decoded video frame.
vpx_codec_iter_t iter = nullptr;
- vpx_image_t* image = vpx_codec_get_frame(codec_.get(), &iter);
- if (!image) {
+ image_ = vpx_codec_get_frame(codec_.get(), &iter);
+ if (!image_) {
LOG(ERROR) << "No video frame decoded";
return false;
}
- last_image_ = image;
+ DCHECK(!image_size().is_empty());
+ // Determine which areas have been updated.
webrtc::DesktopRegion region;
for (int i = 0; i < packet.dirty_rects_size(); ++i) {
Rect remoting_rect = packet.dirty_rects(i);
@@ -123,27 +69,25 @@ bool VideoDecoderVpx::DecodePacket(const VideoPacket& packet) {
remoting_rect.x(), remoting_rect.y(),
remoting_rect.width(), remoting_rect.height()));
}
-
updated_region_.AddRegion(region);
- // Update the desktop shape region.
- webrtc::DesktopRegion desktop_shape_region;
+ // Process the frame shape, if supplied.
if (packet.has_use_desktop_shape()) {
- for (int i = 0; i < packet.desktop_shape_rects_size(); ++i) {
- Rect remoting_rect = packet.desktop_shape_rects(i);
- desktop_shape_region.AddRect(webrtc::DesktopRect::MakeXYWH(
- remoting_rect.x(), remoting_rect.y(),
- remoting_rect.width(), remoting_rect.height()));
+ if (packet.use_desktop_shape()) {
+ if (!desktop_shape_)
+ desktop_shape_ = make_scoped_ptr(new webrtc::DesktopRegion);
+ desktop_shape_->Clear();
+ for (int i = 0; i < packet.desktop_shape_rects_size(); ++i) {
+ Rect remoting_rect = packet.desktop_shape_rects(i);
+ desktop_shape_->AddRect(webrtc::DesktopRect::MakeXYWH(
+ remoting_rect.x(), remoting_rect.y(), remoting_rect.width(),
+ remoting_rect.height()));
+ }
+ } else {
+ desktop_shape_.reset();
}
- } else {
- // Fallback for the case when the host didn't include the desktop shape
- // region.
- desktop_shape_region =
- webrtc::DesktopRegion(webrtc::DesktopRect::MakeSize(screen_size_));
}
- UpdateImageShapeRegion(&desktop_shape_region);
-
return true;
}
@@ -152,15 +96,8 @@ void VideoDecoderVpx::Invalidate(const webrtc::DesktopSize& view_size,
DCHECK(!view_size.is_empty());
for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) {
- updated_region_.AddRect(ScaleRect(i.rect(), view_size, screen_size_));
+ updated_region_.AddRect(ScaleRect(i.rect(), view_size, image_size()));
}
-
- // Updated areas outside of the new desktop shape region should be made
- // transparent, not repainted.
- webrtc::DesktopRegion difference = updated_region_;
- difference.Subtract(desktop_shape_);
- updated_region_.Subtract(difference);
- transparent_region_.AddRegion(difference);
}
void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
@@ -168,21 +105,20 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
uint8* image_buffer,
int image_stride,
webrtc::DesktopRegion* output_region) {
- DCHECK(!screen_size_.is_empty());
+ DCHECK(!image_size().is_empty());
DCHECK(!view_size.is_empty());
// Early-return and do nothing if we haven't yet decoded any frames.
- if (!last_image_)
+ if (!image_)
return;
- webrtc::DesktopRect source_clip =
- webrtc::DesktopRect::MakeWH(last_image_->d_w, last_image_->d_h);
+ webrtc::DesktopRect source_clip = webrtc::DesktopRect::MakeSize(image_size());
// VP8 only outputs I420 frames, but VP9 can also produce I444.
- switch (last_image_->fmt) {
+ switch (image_->fmt) {
case VPX_IMG_FMT_I444: {
// TODO(wez): Add scaling support to the I444 conversion path.
- if (view_size.equals(screen_size_)) {
+ if (view_size.equals(image_size())) {
for (webrtc::DesktopRegion::Iterator i(updated_region_);
!i.IsAtEnd(); i.Advance()) {
// Determine the scaled area affected by this rectangle changing.
@@ -194,15 +130,12 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
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],
+ int y_offset = image_->stride[0] * rect.top() + rect.left();
+ int u_offset = image_->stride[1] * rect.top() + rect.left();
+ int v_offset = image_->stride[2] * rect.top() + rect.left();
+ libyuv::I444ToARGB(image_->planes[0] + y_offset, image_->stride[0],
+ image_->planes[1] + u_offset, image_->stride[1],
+ image_->planes[2] + v_offset, image_->stride[2],
image_buffer + image_offset, image_stride,
rect.width(), rect.height());
@@ -224,7 +157,7 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
// 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_);
+ ScaleRect(clip_area, view_size, image_size());
source_rect = webrtc::DesktopRect::MakeLTRB(
RoundToTwosMultiple(source_rect.left()),
RoundToTwosMultiple(source_rect.top()),
@@ -240,23 +173,15 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
// Scale & convert the entire clip area.
int y_offset = CalculateYOffset(source_rect.left(), source_rect.top(),
- last_image_->stride[0]);
+ 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);
+ image_->stride[1]);
+ ScaleYUVToRGB32(
+ image_->planes[0] + y_offset, image_->planes[1] + uv_offset,
+ image_->planes[2] + uv_offset, image_buffer, source_rect.width(),
+ source_rect.height(), clip_area.width(), clip_area.height(),
+ image_->stride[0], image_->stride[1], image_stride, media::YV12,
+ media::ROTATE_0, media::FILTER_BILINEAR);
output_region->AddRect(clip_area);
updated_region_.Subtract(source_rect);
@@ -270,86 +195,51 @@ void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size,
rect.IntersectWith(source_clip);
if (rect.is_empty())
continue;
- rect = ScaleRect(rect, screen_size_, view_size);
+ rect = ScaleRect(rect, image_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);
+ ConvertAndScaleYUVToRGB32Rect(
+ image_->planes[0], image_->planes[1], image_->planes[2],
+ image_->stride[0], image_->stride[1], image_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_));
+ updated_region_.Subtract(ScaleRect(clip_area, view_size, image_size()));
break;
}
default: {
- LOG(ERROR) << "Unsupported image format:" << last_image_->fmt;
+ LOG(ERROR) << "Unsupported image format:" << image_->fmt;
return;
}
}
- for (webrtc::DesktopRegion::Iterator i(transparent_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;
-
- // Fill the rectange with transparent pixels.
- FillRect(image_buffer, image_stride, rect, kTransparentColor);
- output_region->AddRect(rect);
- }
-
webrtc::DesktopRect scaled_clip_area =
- ScaleRect(clip_area, view_size, screen_size_);
+ ScaleRect(clip_area, view_size, image_size());
updated_region_.Subtract(scaled_clip_area);
- transparent_region_.Subtract(scaled_clip_area);
}
const webrtc::DesktopRegion* VideoDecoderVpx::GetImageShape() {
- return &desktop_shape_;
+ return desktop_shape_.get();
}
-VideoDecoderVpx::VideoDecoderVpx(ScopedVpxCodec codec)
- : codec_(codec.Pass()),
- last_image_(nullptr) {
- DCHECK(codec_);
+VideoDecoderVpx::VideoDecoderVpx(vpx_codec_iface_t* codec) : image_(nullptr) {
+ codec_.reset(new vpx_codec_ctx_t);
+
+ vpx_codec_dec_cfg config;
+ config.w = 0;
+ config.h = 0;
+ config.threads = 2;
+ vpx_codec_err_t ret = vpx_codec_dec_init(codec_.get(), codec, &config, 0);
+ CHECK_EQ(VPX_CODEC_OK, ret);
}
-void VideoDecoderVpx::UpdateImageShapeRegion(
- webrtc::DesktopRegion* new_desktop_shape) {
- // Add all areas that have been updated or become transparent to the
- // transparent region. Exclude anything within the new desktop shape.
- transparent_region_.AddRegion(desktop_shape_);
- transparent_region_.AddRegion(updated_region_);
- transparent_region_.Subtract(*new_desktop_shape);
-
- // Add newly exposed areas to the update region and limit updates to the new
- // desktop shape.
- webrtc::DesktopRegion difference = *new_desktop_shape;
- difference.Subtract(desktop_shape_);
- updated_region_.AddRegion(difference);
- updated_region_.IntersectWith(*new_desktop_shape);
-
- // Set the new desktop shape region.
- desktop_shape_.Swap(new_desktop_shape);
+webrtc::DesktopSize VideoDecoderVpx::image_size() const {
+ return image_ ? webrtc::DesktopSize(image_->d_w, image_->d_h)
+ : webrtc::DesktopSize();
}
} // namespace remoting
« no previous file with comments | « remoting/codec/video_decoder_vpx.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698