Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: remoting/base/decoder_row_based.cc

Issue 9331003: Improving the decoder pipeline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/base/decoder_row_based.h" 5 #include "remoting/base/decoder_row_based.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "remoting/base/decompressor.h" 8 #include "remoting/base/decompressor.h"
9 #include "remoting/base/decompressor_zlib.h" 9 #include "remoting/base/decompressor_zlib.h"
10 #include "remoting/base/decompressor_verbatim.h" 10 #include "remoting/base/decompressor_verbatim.h"
(...skipping 16 matching lines...) Expand all
27 VideoPacketFormat::ENCODING_VERBATIM); 27 VideoPacketFormat::ENCODING_VERBATIM);
28 } 28 }
29 29
30 DecoderRowBased::DecoderRowBased(Decompressor* decompressor, 30 DecoderRowBased::DecoderRowBased(Decompressor* decompressor,
31 VideoPacketFormat::Encoding encoding) 31 VideoPacketFormat::Encoding encoding)
32 : state_(kUninitialized), 32 : state_(kUninitialized),
33 clip_(SkIRect::MakeEmpty()), 33 clip_(SkIRect::MakeEmpty()),
34 decompressor_(decompressor), 34 decompressor_(decompressor),
35 encoding_(encoding), 35 encoding_(encoding),
36 row_pos_(0), 36 row_pos_(0),
37 row_y_(0) { 37 row_y_(0),
38 screen_size_(SkISize::Make(0, 0)) {
38 } 39 }
39 40
40 DecoderRowBased::~DecoderRowBased() { 41 DecoderRowBased::~DecoderRowBased() {
41 } 42 }
42 43
43 void DecoderRowBased::Reset() { 44 void DecoderRowBased::Reset() {
44 frame_ = NULL;
45 decompressor_->Reset(); 45 decompressor_->Reset();
46 state_ = kUninitialized; 46 state_ = kUninitialized;
47 updated_region_.setEmpty(); 47 updated_region_.setEmpty();
48 screen_buffer_.reset(NULL);
48 } 49 }
49 50
50 bool DecoderRowBased::IsReadyForData() { 51 bool DecoderRowBased::IsReadyForData() {
51 switch (state_) { 52 switch (state_) {
52 case kUninitialized: 53 case kUninitialized:
53 case kError: 54 case kError:
54 return false; 55 return false;
55 case kReady: 56 case kReady:
56 case kProcessing: 57 case kProcessing:
57 case kPartitionDone: 58 case kPartitionDone:
58 case kDone: 59 case kDone:
59 return true; 60 return true;
60 } 61 }
61 NOTREACHED(); 62 NOTREACHED();
62 return false; 63 return false;
63 } 64 }
64 65
65 void DecoderRowBased::Initialize(scoped_refptr<media::VideoFrame> frame) { 66 void DecoderRowBased::Initialize(const SkISize& screen_size) {
66 // Make sure we are not currently initialized. 67 // Make sure we are not currently initialized.
67 CHECK_EQ(kUninitialized, state_); 68 CHECK_EQ(kUninitialized, state_);
69 DCHECK(screen_buffer_.get() == NULL);
68 70
69 if (frame->format() != media::VideoFrame::RGB32) { 71 screen_size_ = screen_size;
70 LOG(WARNING) << "DecoderRowBased only supports RGB32."; 72 // Allocate the screen buffer, if necessary.
71 state_ = kError; 73 if (!screen_size_.isZero()) {
72 return; 74 screen_buffer_.reset(new uint8[
75 screen_size_.width() * screen_size_.height() * kBytesPerPixel]);
73 } 76 }
74 77
75 frame_ = frame;
76 state_ = kReady; 78 state_ = kReady;
77 } 79 }
78 80
79 Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) { 81 Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) {
80 UpdateStateForPacket(packet); 82 UpdateStateForPacket(packet);
81 83
82 if (state_ == kError) { 84 if (state_ == kError) {
83 return DECODE_ERROR; 85 return DECODE_ERROR;
84 } 86 }
85 87
88 // The input buffer is a linear vector of pixel data.
86 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data()); 89 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data());
87 const int in_size = packet->data().size(); 90 const int in_size = packet->data().size();
91 const int row_size = clip_.width() * kBytesPerPixel;
88 92
89 const int row_size = clip_.width() * kBytesPerPixel; 93 // Access the pixel buffer directly.
90 int stride = frame_->stride(media::VideoFrame::kRGBPlane); 94 int out_stride = screen_size_.width() * kBytesPerPixel;
91 uint8* rect_begin = frame_->data(media::VideoFrame::kRGBPlane); 95 uint8* out = screen_buffer_.get() + out_stride * (clip_.top() + row_y_) +
92 96 kBytesPerPixel * clip_.left();
93 uint8* out = rect_begin + stride * (clip_.fTop + row_y_) +
94 kBytesPerPixel * clip_.fLeft;
95 97
96 // Consume all the data in the message. 98 // Consume all the data in the message.
97 bool decompress_again = true; 99 bool decompress_again = true;
98 int used = 0; 100 int used = 0;
99 while (decompress_again && used < in_size) { 101 while (decompress_again && used < in_size) {
100 if (row_y_ >= clip_.height()) { 102 if (row_y_ >= clip_.height()) {
101 state_ = kError; 103 state_ = kError;
102 LOG(WARNING) << "Too much data is received for the given rectangle."; 104 LOG(WARNING) << "Too much data is received for the given rectangle.";
103 return DECODE_ERROR; 105 return DECODE_ERROR;
104 } 106 }
105 107
106 int written = 0; 108 int written = 0;
107 int consumed = 0; 109 int consumed = 0;
108 // TODO(ajwong): This assume source and dest stride are the same, which is
109 // incorrect.
110 decompress_again = decompressor_->Process( 110 decompress_again = decompressor_->Process(
111 in + used, in_size - used, out + row_pos_, row_size - row_pos_, 111 in + used, in_size - used, out + row_pos_, row_size - row_pos_,
112 &consumed, &written); 112 &consumed, &written);
113 used += consumed; 113 used += consumed;
114 row_pos_ += written; 114 row_pos_ += written;
115 115
116 // If this row is completely filled then move onto the next row. 116 // If this row is completely filled then move onto the next row.
117 if (row_pos_ == row_size) { 117 if (row_pos_ == row_size) {
118 ++row_y_; 118 ++row_y_;
119 row_pos_ = 0; 119 row_pos_ = 0;
120 out += stride; 120 out += out_stride;
121 } 121 }
122 } 122 }
123 123
124 if (state_ == kPartitionDone || state_ == kDone) { 124 if (state_ == kPartitionDone || state_ == kDone) {
125 if (row_y_ < clip_.height()) { 125 if (row_y_ < clip_.height()) {
126 state_ = kError; 126 state_ = kError;
127 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; 127 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data.";
128 return DECODE_ERROR; 128 return DECODE_ERROR;
129 } 129 }
130 130
(...skipping 12 matching lines...) Expand all
143 if (state_ == kError) { 143 if (state_ == kError) {
144 return; 144 return;
145 } 145 }
146 146
147 if (packet->flags() & VideoPacket::FIRST_PACKET) { 147 if (packet->flags() & VideoPacket::FIRST_PACKET) {
148 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { 148 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) {
149 state_ = kError; 149 state_ = kError;
150 LOG(WARNING) << "Received unexpected FIRST_PACKET."; 150 LOG(WARNING) << "Received unexpected FIRST_PACKET.";
151 return; 151 return;
152 } 152 }
153 state_ = kProcessing;
154 153
155 // Reset the buffer location status variables on the first packet. 154 // Reset the buffer location status variables on the first packet.
156 clip_.setXYWH(packet->format().x(), packet->format().y(), 155 clip_.setXYWH(packet->format().x(), packet->format().y(),
157 packet->format().width(), packet->format().height()); 156 packet->format().width(), packet->format().height());
157 if (!SkIRect::MakeSize(screen_size_).contains(clip_)) {
158 state_ = kError;
159 LOG(WARNING) << "Invalid clipping area received.";
160 return;
161 }
162
163 state_ = kProcessing;
158 row_pos_ = 0; 164 row_pos_ = 0;
159 row_y_ = 0; 165 row_y_ = 0;
160 } 166 }
161 167
162 if (state_ != kProcessing) { 168 if (state_ != kProcessing) {
163 state_ = kError; 169 state_ = kError;
164 LOG(WARNING) << "Received unexpected packet."; 170 LOG(WARNING) << "Received unexpected packet.";
165 return; 171 return;
166 } 172 }
167 173
(...skipping 11 matching lines...) Expand all
179 state_ = kError; 185 state_ = kError;
180 LOG(WARNING) << "Received unexpected LAST_PARTITION."; 186 LOG(WARNING) << "Received unexpected LAST_PARTITION.";
181 return; 187 return;
182 } 188 }
183 state_ = kDone; 189 state_ = kDone;
184 } 190 }
185 191
186 return; 192 return;
187 } 193 }
188 194
189 void DecoderRowBased::GetUpdatedRegion(SkRegion* region) {
190 region->swap(updated_region_);
191 updated_region_.setEmpty();
192 }
193
194 VideoPacketFormat::Encoding DecoderRowBased::Encoding() { 195 VideoPacketFormat::Encoding DecoderRowBased::Encoding() {
195 return encoding_; 196 return encoding_;
196 } 197 }
197 198
199 void DecoderRowBased::UpdateRegion(const SkRegion& region) {
200 updated_region_.op(region, SkRegion::kUnion_Op);
201 }
202
203 void DecoderRowBased::Draw(const SkISize& view_size,
204 const SkIRect& clip_area,
205 uint8* image_buffer,
206 int image_stride,
207 SkRegion* output_region) {
208 output_region->setEmpty();
209
210 // TODO(alexeypa): implement scaling in the case when |view_size| does
211 // not match |screen_size_|.
212 SkIRect clip_rect = SkIRect::MakeSize(screen_size_);
213 if (!clip_rect.intersect(clip_area))
214 return;
215
216 int screen_stride = screen_size_.width() * kBytesPerPixel;
217
218 for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) {
219 SkIRect rect(i.rect());
220 if (!rect.intersect(clip_rect))
221 continue;
222
223 CopyRGB32Rect(screen_buffer_.get(), screen_stride,
224 clip_rect,
225 image_buffer, image_stride,
226 clip_area,
227 rect);
228 output_region->op(rect, SkRegion::kUnion_Op);
229 }
230
231 updated_region_.setEmpty();
232 }
233
198 } // namespace remoting 234 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698