video_decoder_verbatim.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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
10namespace remoting {
11
12VideoDecoderVerbatim::VideoDecoderVerbatim() {}
13
14VideoDecoderVerbatim::~VideoDecoderVerbatim() {}
15
16void 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
29bool 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
72void VideoDecoderVerbatim::Invalidate(const webrtc::DesktopSize& view_size,
73                                      const webrtc::DesktopRegion& region) {
74  updated_region_.AddRegion(region);
75}
76
77void 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
110const webrtc::DesktopRegion* VideoDecoderVerbatim::GetImageShape() {
111  return NULL;
112}
113
114}  // namespace remoting
115