1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/codec/video_decoder_verbatim.h" 6 7 #include "base/logging.h" 8 #include "remoting/base/util.h" 9 10 namespace remoting { 11 12 VideoDecoderVerbatim::VideoDecoderVerbatim() {} 13 14 VideoDecoderVerbatim::~VideoDecoderVerbatim() {} 15 16 void VideoDecoderVerbatim::Initialize(const webrtc::DesktopSize& screen_size) { 17 updated_region_.Clear(); 18 screen_buffer_.reset(); 19 20 screen_size_ = screen_size; 21 // Allocate the screen buffer, if necessary. 22 if (!screen_size_.is_empty()) { 23 screen_buffer_.reset( 24 new uint8[screen_size_.width() * screen_size_.height() * 25 kBytesPerPixel]); 26 } 27 } 28 29 bool VideoDecoderVerbatim::DecodePacket(const VideoPacket& packet) { 30 webrtc::DesktopRegion region; 31 32 const char* in = packet.data().data(); 33 int stride = kBytesPerPixel * screen_size_.width(); 34 for (int i = 0; i < packet.dirty_rects_size(); ++i) { 35 Rect proto_rect = packet.dirty_rects(i); 36 webrtc::DesktopRect rect = 37 webrtc::DesktopRect::MakeXYWH(proto_rect.x(), 38 proto_rect.y(), 39 proto_rect.width(), 40 proto_rect.height()); 41 region.AddRect(rect); 42 43 if (!DoesRectContain(webrtc::DesktopRect::MakeSize(screen_size_), rect)) { 44 LOG(ERROR) << "Invalid packet received"; 45 return false; 46 } 47 48 int rect_row_size = kBytesPerPixel * rect.width(); 49 uint8_t* out = screen_buffer_.get() + rect.top() * stride + 50 rect.left() * kBytesPerPixel; 51 for (int y = rect.top(); y < rect.top() + rect.height(); ++y) { 52 if (in + rect_row_size > packet.data().data() + packet.data().size()) { 53 LOG(ERROR) << "Invalid packet received"; 54 return false; 55 } 56 memcpy(out, in, rect_row_size); 57 in += rect_row_size; 58 out += stride; 59 } 60 } 61 62 if (in != packet.data().data() + packet.data().size()) { 63 LOG(ERROR) << "Invalid packet received"; 64 return false; 65 } 66 67 updated_region_.AddRegion(region); 68 69 return true; 70 } 71 72 void VideoDecoderVerbatim::Invalidate(const webrtc::DesktopSize& view_size, 73 const webrtc::DesktopRegion& region) { 74 updated_region_.AddRegion(region); 75 } 76 77 void VideoDecoderVerbatim::RenderFrame(const webrtc::DesktopSize& view_size, 78 const webrtc::DesktopRect& clip_area, 79 uint8* image_buffer, 80 int image_stride, 81 webrtc::DesktopRegion* output_region) { 82 output_region->Clear(); 83 84 // TODO(alexeypa): scaling is not implemented. 85 webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(screen_size_); 86 clip_rect.IntersectWith(clip_area); 87 if (clip_rect.is_empty()) 88 return; 89 90 int screen_stride = screen_size_.width() * kBytesPerPixel; 91 92 for (webrtc::DesktopRegion::Iterator i(updated_region_); 93 !i.IsAtEnd(); i.Advance()) { 94 webrtc::DesktopRect rect(i.rect()); 95 rect.IntersectWith(clip_rect); 96 if (rect.is_empty()) 97 continue; 98 99 CopyRGB32Rect(screen_buffer_.get(), screen_stride, 100 clip_rect, 101 image_buffer, image_stride, 102 clip_area, 103 rect); 104 output_region->AddRect(rect); 105 } 106 107 updated_region_.Clear(); 108 } 109 110 const webrtc::DesktopRegion* VideoDecoderVerbatim::GetImageShape() { 111 return NULL; 112 } 113 114 } // namespace remoting 115