OLD | NEW |
| (Empty) |
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/base/decoder_row_based.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "remoting/base/decompressor.h" | |
9 #include "remoting/base/decompressor_zlib.h" | |
10 #include "remoting/base/decompressor_verbatim.h" | |
11 #include "remoting/base/util.h" | |
12 | |
13 namespace remoting { | |
14 | |
15 namespace { | |
16 // Both input and output data are assumed to be RGBA32. | |
17 const int kBytesPerPixel = 4; | |
18 } | |
19 | |
20 DecoderRowBased* DecoderRowBased::CreateZlibDecoder() { | |
21 return new DecoderRowBased(new DecompressorZlib(), | |
22 VideoPacketFormat::ENCODING_ZLIB); | |
23 } | |
24 | |
25 DecoderRowBased* DecoderRowBased::CreateVerbatimDecoder() { | |
26 return new DecoderRowBased(new DecompressorVerbatim(), | |
27 VideoPacketFormat::ENCODING_VERBATIM); | |
28 } | |
29 | |
30 DecoderRowBased::DecoderRowBased(Decompressor* decompressor, | |
31 VideoPacketFormat::Encoding encoding) | |
32 : state_(kUninitialized), | |
33 clip_(SkIRect::MakeEmpty()), | |
34 decompressor_(decompressor), | |
35 encoding_(encoding), | |
36 row_pos_(0), | |
37 row_y_(0), | |
38 screen_size_(SkISize::Make(0, 0)) { | |
39 } | |
40 | |
41 DecoderRowBased::~DecoderRowBased() { | |
42 } | |
43 | |
44 bool DecoderRowBased::IsReadyForData() { | |
45 switch (state_) { | |
46 case kUninitialized: | |
47 case kError: | |
48 return false; | |
49 case kReady: | |
50 case kProcessing: | |
51 case kPartitionDone: | |
52 case kDone: | |
53 return true; | |
54 } | |
55 NOTREACHED(); | |
56 return false; | |
57 } | |
58 | |
59 void DecoderRowBased::Initialize(const SkISize& screen_size) { | |
60 decompressor_->Reset(); | |
61 updated_region_.setEmpty(); | |
62 screen_buffer_.reset(NULL); | |
63 | |
64 screen_size_ = screen_size; | |
65 // Allocate the screen buffer, if necessary. | |
66 if (!screen_size_.isEmpty()) { | |
67 screen_buffer_.reset(new uint8[ | |
68 screen_size_.width() * screen_size_.height() * kBytesPerPixel]); | |
69 } | |
70 | |
71 state_ = kReady; | |
72 } | |
73 | |
74 Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) { | |
75 UpdateStateForPacket(packet); | |
76 | |
77 if (state_ == kError) { | |
78 return DECODE_ERROR; | |
79 } | |
80 | |
81 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data()); | |
82 const int in_size = packet->data().size(); | |
83 const int row_size = clip_.width() * kBytesPerPixel; | |
84 | |
85 int out_stride = screen_size_.width() * kBytesPerPixel; | |
86 uint8* out = screen_buffer_.get() + out_stride * (clip_.top() + row_y_) + | |
87 kBytesPerPixel * clip_.left(); | |
88 | |
89 // Consume all the data in the message. | |
90 bool decompress_again = true; | |
91 int used = 0; | |
92 while (decompress_again && used < in_size) { | |
93 if (row_y_ >= clip_.height()) { | |
94 state_ = kError; | |
95 LOG(WARNING) << "Too much data is received for the given rectangle."; | |
96 return DECODE_ERROR; | |
97 } | |
98 | |
99 int written = 0; | |
100 int consumed = 0; | |
101 decompress_again = decompressor_->Process( | |
102 in + used, in_size - used, out + row_pos_, row_size - row_pos_, | |
103 &consumed, &written); | |
104 used += consumed; | |
105 row_pos_ += written; | |
106 | |
107 // If this row is completely filled then move onto the next row. | |
108 if (row_pos_ == row_size) { | |
109 ++row_y_; | |
110 row_pos_ = 0; | |
111 out += out_stride; | |
112 } | |
113 } | |
114 | |
115 if (state_ == kPartitionDone || state_ == kDone) { | |
116 if (row_y_ < clip_.height()) { | |
117 state_ = kError; | |
118 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; | |
119 return DECODE_ERROR; | |
120 } | |
121 | |
122 updated_region_.op(clip_, SkRegion::kUnion_Op); | |
123 decompressor_->Reset(); | |
124 } | |
125 | |
126 if (state_ == kDone) { | |
127 return DECODE_DONE; | |
128 } else { | |
129 return DECODE_IN_PROGRESS; | |
130 } | |
131 } | |
132 | |
133 void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) { | |
134 if (state_ == kError) { | |
135 return; | |
136 } | |
137 | |
138 if (packet->flags() & VideoPacket::FIRST_PACKET) { | |
139 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { | |
140 state_ = kError; | |
141 LOG(WARNING) << "Received unexpected FIRST_PACKET."; | |
142 return; | |
143 } | |
144 | |
145 // Reset the buffer location status variables on the first packet. | |
146 clip_.setXYWH(packet->format().x(), packet->format().y(), | |
147 packet->format().width(), packet->format().height()); | |
148 if (!SkIRect::MakeSize(screen_size_).contains(clip_)) { | |
149 state_ = kError; | |
150 LOG(WARNING) << "Invalid clipping area received."; | |
151 return; | |
152 } | |
153 | |
154 state_ = kProcessing; | |
155 row_pos_ = 0; | |
156 row_y_ = 0; | |
157 } | |
158 | |
159 if (state_ != kProcessing) { | |
160 state_ = kError; | |
161 LOG(WARNING) << "Received unexpected packet."; | |
162 return; | |
163 } | |
164 | |
165 if (packet->flags() & VideoPacket::LAST_PACKET) { | |
166 if (state_ != kProcessing) { | |
167 state_ = kError; | |
168 LOG(WARNING) << "Received unexpected LAST_PACKET."; | |
169 return; | |
170 } | |
171 state_ = kPartitionDone; | |
172 } | |
173 | |
174 if (packet->flags() & VideoPacket::LAST_PARTITION) { | |
175 if (state_ != kPartitionDone) { | |
176 state_ = kError; | |
177 LOG(WARNING) << "Received unexpected LAST_PARTITION."; | |
178 return; | |
179 } | |
180 state_ = kDone; | |
181 } | |
182 | |
183 return; | |
184 } | |
185 | |
186 VideoPacketFormat::Encoding DecoderRowBased::Encoding() { | |
187 return encoding_; | |
188 } | |
189 | |
190 void DecoderRowBased::Invalidate(const SkISize& view_size, | |
191 const SkRegion& region) { | |
192 updated_region_.op(region, SkRegion::kUnion_Op); | |
193 } | |
194 | |
195 void DecoderRowBased::RenderFrame(const SkISize& view_size, | |
196 const SkIRect& clip_area, | |
197 uint8* image_buffer, | |
198 int image_stride, | |
199 SkRegion* output_region) { | |
200 output_region->setEmpty(); | |
201 | |
202 // TODO(alexeypa): scaling is not implemented. | |
203 SkIRect clip_rect = SkIRect::MakeSize(screen_size_); | |
204 if (!clip_rect.intersect(clip_area)) | |
205 return; | |
206 | |
207 int screen_stride = screen_size_.width() * kBytesPerPixel; | |
208 | |
209 for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) { | |
210 SkIRect rect(i.rect()); | |
211 if (!rect.intersect(clip_rect)) | |
212 continue; | |
213 | |
214 CopyRGB32Rect(screen_buffer_.get(), screen_stride, | |
215 clip_rect, | |
216 image_buffer, image_stride, | |
217 clip_area, | |
218 rect); | |
219 output_region->op(rect, SkRegion::kUnion_Op); | |
220 } | |
221 | |
222 updated_region_.setEmpty(); | |
223 } | |
224 | |
225 } // namespace remoting | |
OLD | NEW |