15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_decoder_verbatim.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoDecoderVerbatim::VideoDecoderVerbatim() {} 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoDecoderVerbatim::~VideoDecoderVerbatim() {} 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoDecoderVerbatim::Initialize(const webrtc::DesktopSize& screen_size) { 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Clear(); 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screen_buffer_.reset(); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_size_ = screen_size; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocate the screen buffer, if necessary. 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!screen_size_.is_empty()) { 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) screen_buffer_.reset( 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new uint8[screen_size_.width() * screen_size_.height() * 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kBytesPerPixel]); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool VideoDecoderVerbatim::DecodePacket(const VideoPacket& packet) { 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion region; 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const char* in = packet.data().data(); 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int stride = kBytesPerPixel * screen_size_.width(); 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (int i = 0; i < packet.dirty_rects_size(); ++i) { 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Rect proto_rect = packet.dirty_rects(i); 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect rect = 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) webrtc::DesktopRect::MakeXYWH(proto_rect.x(), 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) proto_rect.y(), 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) proto_rect.width(), 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) proto_rect.height()); 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) region.AddRect(rect); 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!DoesRectContain(webrtc::DesktopRect::MakeSize(screen_size_), rect)) { 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "Invalid packet received"; 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rect_row_size = kBytesPerPixel * rect.width(); 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint8_t* out = screen_buffer_.get() + rect.top() * stride + 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.left() * kBytesPerPixel; 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int y = rect.top(); y < rect.top() + rect.height(); ++y) { 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (in + rect_row_size > packet.data().data() + packet.data().size()) { 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "Invalid packet received"; 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) memcpy(out, in, rect_row_size); 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) in += rect_row_size; 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) out += stride; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (in != packet.data().data() + packet.data().size()) { 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(ERROR) << "Invalid packet received"; 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.AddRegion(region); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoDecoderVerbatim::Invalidate(const webrtc::DesktopSize& view_size, 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRegion& region) { 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.AddRegion(region); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoDecoderVerbatim::RenderFrame(const webrtc::DesktopSize& view_size, 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& clip_area, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* image_buffer, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_stride, 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion* output_region) { 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_region->Clear(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(alexeypa): scaling is not implemented. 85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(screen_size_); 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) clip_rect.IntersectWith(clip_area); 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (clip_rect.is_empty()) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int screen_stride = screen_size_.width() * kBytesPerPixel; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(updated_region_); 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect rect(i.rect()); 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.IntersectWith(clip_rect); 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rect.is_empty()) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyRGB32Rect(screen_buffer_.get(), screen_stride, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_rect, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_buffer, image_stride, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect); 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_region->AddRect(rect); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) updated_region_.Clear(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const webrtc::DesktopRegion* VideoDecoderVerbatim::GetImageShape() { 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return NULL; 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 115