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