blob: cf89677a75decde8c36a6cc7b7ba8be80d88e689 [file] [log] [blame]
[email protected]bcad2682011-09-30 20:35:261// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]8ea7a1672010-10-04 19:48:422// 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
[email protected]1e1cb3b2011-11-10 02:07:417#include "base/logging.h"
[email protected]8ea7a1672010-10-04 19:48:428#include "remoting/base/decompressor.h"
9#include "remoting/base/decompressor_zlib.h"
10#include "remoting/base/decompressor_verbatim.h"
[email protected]c3af26f332010-10-06 22:46:0011#include "remoting/base/util.h"
[email protected]8ea7a1672010-10-04 19:48:4212
13namespace remoting {
14
[email protected]3adf1b22010-11-09 23:22:2015namespace {
16// Both input and output data are assumed to be RGBA32.
17const int kBytesPerPixel = 4;
18}
19
[email protected]8ea7a1672010-10-04 19:48:4220DecoderRowBased* DecoderRowBased::CreateZlibDecoder() {
[email protected]04b36142010-11-02 01:08:1921 return new DecoderRowBased(new DecompressorZlib(),
22 VideoPacketFormat::ENCODING_ZLIB);
[email protected]8ea7a1672010-10-04 19:48:4223}
24
25DecoderRowBased* DecoderRowBased::CreateVerbatimDecoder() {
[email protected]04b36142010-11-02 01:08:1926 return new DecoderRowBased(new DecompressorVerbatim(),
27 VideoPacketFormat::ENCODING_VERBATIM);
[email protected]8ea7a1672010-10-04 19:48:4228}
29
30DecoderRowBased::DecoderRowBased(Decompressor* decompressor,
[email protected]04b36142010-11-02 01:08:1931 VideoPacketFormat::Encoding encoding)
[email protected]8ea7a1672010-10-04 19:48:4232 : state_(kUninitialized),
33 decompressor_(decompressor),
34 encoding_(encoding),
[email protected]8ea7a1672010-10-04 19:48:4235 row_pos_(0),
[email protected]d3a4b09d2011-02-22 18:16:5336 row_y_(0) {
[email protected]8ea7a1672010-10-04 19:48:4237}
38
39DecoderRowBased::~DecoderRowBased() {
40}
41
42void DecoderRowBased::Reset() {
43 frame_ = NULL;
44 decompressor_->Reset();
45 state_ = kUninitialized;
[email protected]5bc71832010-12-09 01:34:0846 updated_rects_.clear();
[email protected]8ea7a1672010-10-04 19:48:4247}
48
49bool DecoderRowBased::IsReadyForData() {
[email protected]5bc71832010-12-09 01:34:0850 switch (state_) {
51 case kUninitialized:
52 case kError:
53 return false;
54 case kReady:
55 case kProcessing:
56 case kPartitionDone:
57 case kDone:
58 return true;
59 }
60 NOTREACHED();
61 return false;
[email protected]8ea7a1672010-10-04 19:48:4262}
63
[email protected]3adf1b22010-11-09 23:22:2064void DecoderRowBased::Initialize(scoped_refptr<media::VideoFrame> frame) {
[email protected]8ea7a1672010-10-04 19:48:4265 // Make sure we are not currently initialized.
66 CHECK_EQ(kUninitialized, state_);
67
[email protected]3adf1b22010-11-09 23:22:2068 if (frame->format() != media::VideoFrame::RGB32) {
[email protected]8ea7a1672010-10-04 19:48:4269 LOG(WARNING) << "DecoderRowBased only supports RGB32.";
70 state_ = kError;
71 return;
72 }
73
74 frame_ = frame;
[email protected]8ea7a1672010-10-04 19:48:4275 state_ = kReady;
76}
77
[email protected]2c229682010-12-02 20:23:3578Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) {
[email protected]3adf1b22010-11-09 23:22:2079 UpdateStateForPacket(packet);
[email protected]8ea7a1672010-10-04 19:48:4280
[email protected]3adf1b22010-11-09 23:22:2081 if (state_ == kError) {
82 return DECODE_ERROR;
83 }
84
85 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data());
86 const int in_size = packet->data().size();
87
88 const int row_size = clip_.width() * kBytesPerPixel;
[email protected]8ea7a1672010-10-04 19:48:4289 int stride = frame_->stride(media::VideoFrame::kRGBPlane);
90 uint8* rect_begin = frame_->data(media::VideoFrame::kRGBPlane);
91
[email protected]bcad2682011-09-30 20:35:2692 uint8* out = rect_begin + stride * (clip_.fTop + row_y_) +
93 kBytesPerPixel * clip_.fLeft;
[email protected]8ea7a1672010-10-04 19:48:4294
95 // Consume all the data in the message.
96 bool decompress_again = true;
97 int used = 0;
98 while (decompress_again && used < in_size) {
[email protected]3adf1b22010-11-09 23:22:2099 if (row_y_ >= clip_.height()) {
100 state_ = kError;
101 LOG(WARNING) << "Too much data is received for the given rectangle.";
102 return DECODE_ERROR;
103 }
104
[email protected]8ea7a1672010-10-04 19:48:42105 int written = 0;
106 int consumed = 0;
107 // TODO(ajwong): This assume source and dest stride are the same, which is
108 // incorrect.
109 decompress_again = decompressor_->Process(
110 in + used, in_size - used, out + row_pos_, row_size - row_pos_,
111 &consumed, &written);
112 used += consumed;
113 row_pos_ += written;
114
115 // If this row is completely filled then move onto the next row.
116 if (row_pos_ == row_size) {
117 ++row_y_;
118 row_pos_ = 0;
119 out += stride;
120 }
121 }
[email protected]3adf1b22010-11-09 23:22:20122
[email protected]5bc71832010-12-09 01:34:08123 if (state_ == kPartitionDone || state_ == kDone) {
[email protected]9b2b3ae82010-11-16 00:36:08124 if (row_y_ < clip_.height()) {
125 state_ = kError;
126 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data.";
127 return DECODE_ERROR;
128 }
[email protected]3adf1b22010-11-09 23:22:20129
[email protected]5bc71832010-12-09 01:34:08130 updated_rects_.push_back(clip_);
[email protected]9b2b3ae82010-11-16 00:36:08131 decompressor_->Reset();
[email protected]5bc71832010-12-09 01:34:08132 }
133
134 if (state_ == kDone) {
[email protected]9b2b3ae82010-11-16 00:36:08135 return DECODE_DONE;
136 } else {
137 return DECODE_IN_PROGRESS;
138 }
[email protected]3adf1b22010-11-09 23:22:20139}
140
141void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) {
142 if (state_ == kError) {
143 return;
144 }
145
146 if (packet->flags() & VideoPacket::FIRST_PACKET) {
[email protected]5bc71832010-12-09 01:34:08147 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) {
[email protected]3adf1b22010-11-09 23:22:20148 state_ = kError;
149 LOG(WARNING) << "Received unexpected FIRST_PACKET.";
150 return;
151 }
152 state_ = kProcessing;
153
154 // Reset the buffer location status variables on the first packet.
[email protected]bcad2682011-09-30 20:35:26155 clip_.setXYWH(packet->format().x(), packet->format().y(),
[email protected]3adf1b22010-11-09 23:22:20156 packet->format().width(), packet->format().height());
157 row_pos_ = 0;
158 row_y_ = 0;
159 }
160
161 if (state_ != kProcessing) {
162 state_ = kError;
163 LOG(WARNING) << "Received unexpected packet.";
164 return;
165 }
166
167 if (packet->flags() & VideoPacket::LAST_PACKET) {
168 if (state_ != kProcessing) {
169 state_ = kError;
170 LOG(WARNING) << "Received unexpected LAST_PACKET.";
171 return;
172 }
[email protected]5bc71832010-12-09 01:34:08173 state_ = kPartitionDone;
174 }
175
176 if (packet->flags() & VideoPacket::LAST_PARTITION) {
177 if (state_ != kPartitionDone) {
178 state_ = kError;
179 LOG(WARNING) << "Received unexpected LAST_PARTITION.";
180 return;
181 }
[email protected]3adf1b22010-11-09 23:22:20182 state_ = kDone;
183 }
184
185 return;
186}
187
[email protected]bcad2682011-09-30 20:35:26188void DecoderRowBased::GetUpdatedRects(RectVector* rects) {
[email protected]5bc71832010-12-09 01:34:08189 rects->swap(updated_rects_);
190 updated_rects_.clear();
[email protected]3adf1b22010-11-09 23:22:20191}
192
193VideoPacketFormat::Encoding DecoderRowBased::Encoding() {
194 return encoding_;
[email protected]8ea7a1672010-10-04 19:48:42195}
196
197} // namespace remoting