1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// 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 {
namespace {
// Both input and output data are assumed to be RGBA32.
const int kBytesPerPixel = 4;
} // namespace
VideoDecoderVerbatim::VideoDecoderVerbatim()
: screen_size_(SkISize::Make(0, 0)) {}
VideoDecoderVerbatim::~VideoDecoderVerbatim() {}
bool VideoDecoderVerbatim::IsReadyForData() {
return true;
}
void VideoDecoderVerbatim::Initialize(const SkISize& screen_size) {
updated_region_.setEmpty();
screen_buffer_.reset();
screen_size_ = screen_size;
// Allocate the screen buffer, if necessary.
if (!screen_size_.isEmpty()) {
screen_buffer_.reset(
new uint8
[screen_size_.width() * screen_size_.height() * kBytesPerPixel]);
}
}
VideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket(
const VideoPacket* packet) {
SkRegion 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);
SkIRect rect = SkIRect::MakeXYWH(proto_rect.x(),
proto_rect.y(),
proto_rect.width(),
proto_rect.height());
region.op(rect, SkRegion::kUnion_Op);
if (!SkIRect::MakeSize(screen_size_).contains(rect)) {
LOG(ERROR) << "Invalid packet received";
return DECODE_ERROR;
}
int rect_row_size = kBytesPerPixel * rect.width();
uint8_t* out = screen_buffer_.get() + rect.y() * stride +
rect.x() * kBytesPerPixel;
for (int y = rect.y(); y < rect.y() + rect.height(); ++y) {
if (in + rect_row_size > packet->data().data() + packet->data().size()) {
LOG(ERROR) << "Invalid packet received";
return DECODE_ERROR;
}
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 DECODE_ERROR;
}
updated_region_.op(region, SkRegion::kUnion_Op);
return DECODE_DONE;
}
VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() {
return VideoPacketFormat::ENCODING_VERBATIM;
}
void VideoDecoderVerbatim::Invalidate(const SkISize& view_size,
const SkRegion& region) {
updated_region_.op(region, SkRegion::kUnion_Op);
}
void VideoDecoderVerbatim::RenderFrame(const SkISize& view_size,
const SkIRect& clip_area,
uint8* image_buffer,
int image_stride,
SkRegion* output_region) {
output_region->setEmpty();
// TODO(alexeypa): scaling is not implemented.
SkIRect clip_rect = SkIRect::MakeSize(screen_size_);
if (!clip_rect.intersect(clip_area))
return;
int screen_stride = screen_size_.width() * kBytesPerPixel;
for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) {
SkIRect rect(i.rect());
if (!rect.intersect(clip_rect))
continue;
CopyRGB32Rect(screen_buffer_.get(), screen_stride,
clip_rect,
image_buffer, image_stride,
clip_area,
rect);
output_region->op(rect, SkRegion::kUnion_Op);
}
updated_region_.setEmpty();
}
const SkRegion* VideoDecoderVerbatim::GetImageShape() {
return NULL;
}
} // namespace remoting
|