video_decoder_vpx.cc revision f2477e01787aa58f445919b809d89e252beef54f
18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "remoting/codec/video_decoder_vpx.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <algorithm> 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VPX_CODEC_DISABLE_COMPAT 1 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace { 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const uint32 kTransparentColor = 0; 278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Fills the rectangle |rect| with the given ARGB color |color| in |buffer|. 298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FillRect(uint8* buffer, 308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int stride, 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const webrtc::DesktopRect& rect, 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint32 color) { 338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) + 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (rect.left() * VideoDecoder::kBytesPerPixel)); 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int width = rect.width(); 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int height = rect.height(); height > 0; --height) { 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::fill(ptr, ptr + width, color); 388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ptr += stride / VideoDecoder::kBytesPerPixel; 398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<VideoDecoderVpx> VideoDecoderVpx::CreateForVP8() { 468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ScopedVpxCodec codec(new vpx_codec_ctx_t); 478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(hclam): Scale the number of threads with number of cores of the 498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // machine. 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_dec_cfg config; 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.w = 0; 528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.h = 0; 538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.threads = 2; 548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_err_t ret = 558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_dec_init(codec.get(), vpx_codec_vp8_dx(), &config, 0); 568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (ret != VPX_CODEC_OK) { 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Cannot initialize codec."; 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return scoped_ptr<VideoDecoderVpx>(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return scoped_ptr<VideoDecoderVpx>(new VideoDecoderVpx(codec.Pass())); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<VideoDecoderVpx> VideoDecoderVpx::CreateForVP9() { 668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ScopedVpxCodec codec(new vpx_codec_ctx_t); 678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(hclam): Scale the number of threads with number of cores of the 698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // machine. 708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_dec_cfg config; 718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.w = 0; 728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.h = 0; 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) config.threads = 2; 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_err_t ret = 758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_codec_dec_init(codec.get(), vpx_codec_vp9_dx(), &config, 0); 768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (ret != VPX_CODEC_OK) { 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Cannot initialize codec."; 788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return scoped_ptr<VideoDecoderVpx>(); 798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return scoped_ptr<VideoDecoderVpx>(new VideoDecoderVpx(codec.Pass())); 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)VideoDecoderVpx::~VideoDecoderVpx() {} 858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void VideoDecoderVpx::Initialize(const webrtc::DesktopSize& screen_size) { 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!screen_size.is_empty()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_size_ = screen_size; 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.SetRect(webrtc::DesktopRect::MakeSize(screen_size_)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool VideoDecoderVpx::DecodePacket(const VideoPacket& packet) { 958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(!screen_size_.is_empty()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do the actual decoding. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vpx_codec_err_t ret = vpx_codec_decode( 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) codec_.get(), reinterpret_cast<const uint8*>(packet.data().data()), 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) packet.data().size(), NULL, 0); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != VPX_CODEC_OK) { 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n" 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << "Details: " << vpx_codec_error(codec_.get()) << "\n" 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << vpx_codec_error_detail(codec_.get()); 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the decoded data. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vpx_codec_iter_t iter = NULL; 1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) vpx_image_t* image = vpx_codec_get_frame(codec_.get(), &iter); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image) { 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "No video frame decoded"; 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_ = image; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion region; 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (int i = 0; i < packet.dirty_rects_size(); ++i) { 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Rect remoting_rect = packet.dirty_rects(i); 120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) region.AddRect(webrtc::DesktopRect::MakeXYWH( 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) remoting_rect.x(), remoting_rect.y(), 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) remoting_rect.width(), remoting_rect.height())); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.AddRegion(region); 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Update the desktop shape region. 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion desktop_shape_region; 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (packet.has_use_desktop_shape()) { 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (int i = 0; i < packet.desktop_shape_rects_size(); ++i) { 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Rect remoting_rect = packet.desktop_shape_rects(i); 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) desktop_shape_region.AddRect(webrtc::DesktopRect::MakeXYWH( 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) remoting_rect.x(), remoting_rect.y(), 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) remoting_rect.width(), remoting_rect.height())); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Fallback for the case when the host didn't include the desktop shape 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // region. 139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) desktop_shape_region = 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion(webrtc::DesktopRect::MakeSize(screen_size_)); 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UpdateImageShapeRegion(&desktop_shape_region); 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void VideoDecoderVpx::Invalidate(const webrtc::DesktopSize& view_size, 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRegion& region) { 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!view_size.is_empty()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.AddRect(ScaleRect(i.rect(), view_size, screen_size_)); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Updated areas outside of the new desktop shape region should be made 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // transparent, not repainted. 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion difference = updated_region_; 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) difference.Subtract(desktop_shape_); 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Subtract(difference); 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.AddRegion(difference); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void VideoDecoderVpx::RenderFrame(const webrtc::DesktopSize& view_size, 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& clip_area, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* image_buffer, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_stride, 168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion* output_region) { 1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(!screen_size_.is_empty()); 170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!view_size.is_empty()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Early-return and do nothing if we haven't yet decoded any frames. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!last_image_) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect source_clip = 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect::MakeWH(last_image_->d_w, last_image_->d_h); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ScaleYUVToRGB32WithRect does not currently support up-scaling. We won't 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be asked to up-scale except during resizes or if page zoom is >100%, so 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we work-around the limitation by using the slower ScaleYUVToRGB32. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can up-scale. 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!updated_region_.is_empty() && 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (source_clip.width() < view_size.width() || 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_clip.height() < view_size.height())) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're scaling only |clip_area| into the |image_buffer|, so we need to 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // work out which source rectangle that corresponds to. 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect source_rect = 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScaleRect(clip_area, view_size, screen_size_); 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_rect = webrtc::DesktopRect::MakeLTRB( 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RoundToTwosMultiple(source_rect.left()), 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RoundToTwosMultiple(source_rect.top()), 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_rect.right(), 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_rect.bottom()); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there were no changes within the clip source area then don't render. 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion intersection(source_rect); 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) intersection.IntersectWith(updated_region_); 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (intersection.is_empty()) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scale & convert the entire clip area. 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int y_offset = CalculateYOffset(source_rect.left(), source_rect.top(), 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[0]); 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int uv_offset = CalculateUVOffset(source_rect.left(), source_rect.top(), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[1]); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScaleYUVToRGB32(last_image_->planes[0] + y_offset, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->planes[1] + uv_offset, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->planes[2] + uv_offset, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_buffer, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_rect.width(), 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_rect.height(), 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area.width(), 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area.height(), 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[0], 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[1], 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_stride, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::YV12, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ROTATE_0, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::FILTER_BILINEAR); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_region->AddRect(clip_area); 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Subtract(source_rect); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(updated_region_); 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the scaled area affected by this rectangle changing. 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect rect = i.rect(); 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.IntersectWith(source_clip); 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rect.is_empty()) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect = ScaleRect(rect, screen_size_, view_size); 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.IntersectWith(clip_area); 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rect.is_empty()) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->planes[1], 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->planes[2], 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[0], 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_image_->stride[1], 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_size_, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_clip, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_buffer, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_stride, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_size, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_region->AddRect(rect); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Subtract(ScaleRect(clip_area, view_size, screen_size_)); 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(transparent_region_); 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Determine the scaled area affected by this rectangle changing. 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect rect = i.rect(); 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.IntersectWith(source_clip); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rect.is_empty()) 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rect = ScaleRect(rect, screen_size_, view_size); 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.IntersectWith(clip_area); 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rect.is_empty()) 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Fill the rectange with transparent pixels. 2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FillRect(image_buffer, image_stride, rect, kTransparentColor); 271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_region->AddRect(rect); 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect scaled_clip_area = 275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScaleRect(clip_area, view_size, screen_size_); 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Subtract(scaled_clip_area); 277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.Subtract(scaled_clip_area); 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const webrtc::DesktopRegion* VideoDecoderVpx::GetImageShape() { 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return &desktop_shape_; 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)VideoDecoderVpx::VideoDecoderVpx(ScopedVpxCodec codec) 2858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : codec_(codec.Pass()), 2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) last_image_(NULL) { 2878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(codec_); 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void VideoDecoderVpx::UpdateImageShapeRegion( 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion* new_desktop_shape) { 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Add all areas that have been updated or become transparent to the 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // transparent region. Exclude anything within the new desktop shape. 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.AddRegion(desktop_shape_); 295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.AddRegion(updated_region_); 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) transparent_region_.Subtract(*new_desktop_shape); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Add newly exposed areas to the update region and limit updates to the new 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // desktop shape. 300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion difference = *new_desktop_shape; 301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) difference.Subtract(desktop_shape_); 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.AddRegion(difference); 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.IntersectWith(*new_desktop_shape); 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Set the new desktop shape region. 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) desktop_shape_.Swap(new_desktop_shape); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 310