OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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_zlib.h" | |
6 | |
7 #include "remoting/base/decompressor_zlib.h" | |
8 #include "remoting/base/protocol_util.h" | |
9 | |
10 namespace remoting { | |
11 | |
12 DecoderZlib::DecoderZlib() | |
13 : state_(kWaitingForBeginRect), | |
14 rect_x_(0), | |
15 rect_y_(0), | |
16 rect_width_(0), | |
17 rect_height_(0), | |
18 bytes_per_pixel_(0), | |
19 updated_rects_(NULL), | |
20 row_pos_(0), | |
21 row_y_(0), | |
22 // TODO(hclam): We should use the information from the update stream | |
23 // to determine whether we should reverse the rows or not. | |
24 // But for simplicity we set to be always true. | |
25 reverse_rows_(true) { | |
26 encoding_ = EncodingZlib; | |
27 } | |
28 | |
29 bool DecoderZlib::BeginDecode(scoped_refptr<media::VideoFrame> frame, | |
30 UpdatedRects* updated_rects, | |
31 Task* partial_decode_done, | |
32 Task* decode_done) { | |
33 DCHECK(!partial_decode_done_.get()); | |
34 DCHECK(!decode_done_.get()); | |
35 DCHECK(!updated_rects_); | |
36 DCHECK_EQ(kWaitingForBeginRect, state_); | |
37 DCHECK(!started_); | |
38 | |
39 if (static_cast<PixelFormat>(frame->format()) != PixelFormatRgb32) { | |
40 LOG(INFO) << "DecoderZlib only supports RGB32."; | |
41 return false; | |
42 } | |
43 | |
44 partial_decode_done_.reset(partial_decode_done); | |
45 decode_done_.reset(decode_done); | |
46 updated_rects_ = updated_rects; | |
47 frame_ = frame; | |
48 | |
49 // Create the decompressor. | |
50 decompressor_.reset(new DecompressorZlib()); | |
51 | |
52 started_ = true; | |
53 return true; | |
54 } | |
55 | |
56 bool DecoderZlib::PartialDecode(ChromotingHostMessage* message) { | |
57 scoped_ptr<ChromotingHostMessage> msg_deleter(message); | |
58 DCHECK(message->has_update_stream_packet()); | |
59 DCHECK(started_); | |
60 | |
61 bool ret = true; | |
62 if (message->update_stream_packet().has_begin_rect()) | |
63 ret = HandleBeginRect(message); | |
64 if (ret && message->update_stream_packet().has_rect_data()) | |
65 ret = HandleRectData(message); | |
66 if (ret && message->update_stream_packet().has_end_rect()) | |
67 ret = HandleEndRect(message); | |
68 return ret; | |
69 } | |
70 | |
71 void DecoderZlib::EndDecode() { | |
72 DCHECK_EQ(kWaitingForBeginRect, state_); | |
73 DCHECK(started_); | |
74 | |
75 decode_done_->Run(); | |
76 | |
77 partial_decode_done_.reset(); | |
78 decode_done_.reset(); | |
79 updated_rects_ = NULL; | |
80 frame_ = NULL; | |
81 decompressor_.reset(); | |
82 started_ = false; | |
83 } | |
84 | |
85 bool DecoderZlib::HandleBeginRect(ChromotingHostMessage* message) { | |
86 DCHECK_EQ(kWaitingForBeginRect, state_); | |
87 state_ = kWaitingForRectData; | |
88 | |
89 rect_width_ = message->update_stream_packet().begin_rect().width(); | |
90 rect_height_ = message->update_stream_packet().begin_rect().height(); | |
91 rect_x_ = message->update_stream_packet().begin_rect().x(); | |
92 rect_y_ = message->update_stream_packet().begin_rect().y(); | |
93 | |
94 PixelFormat pixel_format = | |
95 message->update_stream_packet().begin_rect().pixel_format(); | |
96 | |
97 if (static_cast<PixelFormat>(frame_->format()) != pixel_format) { | |
98 NOTREACHED() << "Pixel format of message doesn't match the video frame. " | |
99 "Expected vs received = " | |
100 << frame_->format() << " vs " << pixel_format | |
101 << " Color space conversion required."; | |
102 return false; | |
103 } | |
104 | |
105 bytes_per_pixel_ = GetBytesPerPixel(pixel_format); | |
106 row_pos_ = 0; | |
107 row_y_ = 0; | |
108 return true; | |
109 } | |
110 | |
111 bool DecoderZlib::HandleRectData(ChromotingHostMessage* message) { | |
112 DCHECK_EQ(kWaitingForRectData, state_); | |
113 DCHECK_EQ(0, | |
114 message->update_stream_packet().rect_data().sequence_number()); | |
115 | |
116 const uint8* in = | |
117 (const uint8*)message->update_stream_packet().rect_data().data().data(); | |
118 const int in_size = | |
119 message->update_stream_packet().rect_data().data().size(); | |
120 const int row_size = rect_width_ * bytes_per_pixel_; | |
121 int stride = frame_->stride(media::VideoFrame::kRGBPlane); | |
122 uint8* rect_begin = frame_->data(media::VideoFrame::kRGBPlane); | |
123 if (reverse_rows_) { | |
124 // Advance the pointer to the last row. | |
125 rect_begin += (frame_->height() - 1) * stride; | |
126 | |
127 // And then make the stride negative. | |
128 stride = -stride; | |
129 } | |
130 | |
131 uint8* out = rect_begin + stride * (rect_y_ + row_y_) + | |
132 bytes_per_pixel_ * rect_x_; | |
133 | |
134 // Consume all the data in the message. | |
135 bool decompress_again = true; | |
136 int used = 0; | |
137 while (decompress_again && used < in_size) { | |
138 int written = 0; | |
139 int consumed = 0; | |
140 decompress_again = decompressor_->Process( | |
141 in + used, in_size - used, out + row_pos_, row_size - row_pos_, | |
142 &consumed, &written); | |
143 used += consumed; | |
144 row_pos_ += written; | |
145 | |
146 // If this row is completely filled then move onto the next row. | |
147 if (row_pos_ == row_size) { | |
148 ++row_y_; | |
149 row_pos_ = 0; | |
150 out += stride; | |
151 } | |
152 } | |
153 return true; | |
154 } | |
155 | |
156 bool DecoderZlib::HandleEndRect(ChromotingHostMessage* message) { | |
157 DCHECK_EQ(kWaitingForRectData, state_); | |
158 state_ = kWaitingForBeginRect; | |
159 | |
160 updated_rects_->clear(); | |
161 updated_rects_->push_back(gfx::Rect(rect_x_, rect_y_, | |
162 rect_width_, rect_height_)); | |
163 partial_decode_done_->Run(); | |
164 return true; | |
165 } | |
166 | |
167 } // namespace remoting | |
OLD | NEW |