// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/codec/video_decoder_verbatim.h"
#include "base/logging.h"
#include "remoting/base/util.h"
namespace remoting {
VideoDecoderVerbatim::VideoDecoderVerbatim() {}
VideoDecoderVerbatim::~VideoDecoderVerbatim() {}
void VideoDecoderVerbatim::Initialize(const webrtc::DesktopSize& screen_size) {
updated_region_.Clear();
screen_buffer_.reset();
screen_size_ = screen_size;
// Allocate the screen buffer, if necessary.
if (!screen_size_.is_empty()) {
screen_buffer_.reset(
new uint8[screen_size_.width() * screen_size_.height() *
kBytesPerPixel]);
}
}
bool VideoDecoderVerbatim::DecodePacket(const VideoPacket& packet) {
webrtc::DesktopRegion region;
const char* in = packet.data().data();
int stride = kBytesPerPixel * screen_size_.width();
for (int i = 0; i < packet.dirty_rects_size(); ++i) {
Rect proto_rect = packet.dirty_rects(i);
webrtc::DesktopRect rect =
webrtc::DesktopRect::MakeXYWH(proto_rect.x(),
proto_rect.y(),
proto_rect.width(),
proto_rect.height());
region.AddRect(rect);
if (!DoesRectContain(webrtc::DesktopRect::MakeSize(screen_size_), rect)) {
LOG(ERROR) << "Invalid packet received";
return false;
}
int rect_row_size = kBytesPerPixel * rect.width();
uint8_t* out = screen_buffer_.get() + rect.top() * stride +
rect.left() * kBytesPerPixel;
for (int y = rect.top(); y < rect.top() + rect.height(); ++y) {
if (in + rect_row_size > packet.data().data() + packet.data().size()) {
LOG(ERROR) << "Invalid packet received";
return false;
}
memcpy(out, in, rect_row_size);
in += rect_row_size;
out += stride;
}
}
if (in != packet.data().data() + packet.data().size()) {
LOG(ERROR) << "Invalid packet received";
return false;
}
updated_region_.AddRegion(region);
return true;
}
void VideoDecoderVerbatim::Invalidate(const webrtc::DesktopSize& view_size,
const webrtc::DesktopRegion& region) {
updated_region_.AddRegion(region);
}
void VideoDecoderVerbatim::RenderFrame(const webrtc::DesktopSize& view_size,
const webrtc::DesktopRect& clip_area,
uint8* image_buffer,
int image_stride,
webrtc::DesktopRegion* output_region) {
output_region->Clear();
// TODO(alexeypa): scaling is not implemented.
webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(screen_size_);
clip_rect.IntersectWith(clip_area);
if (clip_rect.is_empty())
return;
int screen_stride = screen_size_.width() * kBytesPerPixel;
for (webrtc::DesktopRegion::Iterator i(updated_region_);
!i.IsAtEnd(); i.Advance()) {
webrtc::DesktopRect rect(i.rect());
rect.IntersectWith(clip_rect);
if (rect.is_empty())
continue;
CopyRGB32Rect(screen_buffer_.get(), screen_stride,
clip_rect,
image_buffer, image_stride,
clip_area,
rect);
output_region->AddRect(rect);
}
updated_region_.Clear();
}
const webrtc::DesktopRegion* VideoDecoderVerbatim::GetImageShape() {
return NULL;
}
} // namespace remoting