Home | History | Annotate | Download | only in codec
      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