OLD | NEW |
---|---|
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/codec/video_decoder_verbatim.h" | 5 #include "remoting/codec/video_decoder_verbatim.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "remoting/base/util.h" | 8 #include "remoting/base/util.h" |
9 | 9 |
10 namespace remoting { | 10 namespace remoting { |
11 | 11 |
12 namespace { | 12 namespace { |
13 // Both input and output data are assumed to be RGBA32. | 13 // Both input and output data are assumed to be RGBA32. |
14 const int kBytesPerPixel = 4; | 14 const int kBytesPerPixel = 4; |
15 } // namespace | 15 } // namespace |
16 | 16 |
17 VideoDecoderVerbatim::VideoDecoderVerbatim() | |
18 : screen_size_(SkISize::Make(0, 0)) {} | |
17 | 19 |
18 VideoDecoderVerbatim::VideoDecoderVerbatim() | 20 VideoDecoderVerbatim::~VideoDecoderVerbatim() {} |
19 : state_(kUninitialized), | |
20 clip_(SkIRect::MakeEmpty()), | |
21 row_pos_(0), | |
22 row_y_(0), | |
23 screen_size_(SkISize::Make(0, 0)) { | |
24 } | |
25 | |
26 VideoDecoderVerbatim::~VideoDecoderVerbatim() { | |
27 } | |
28 | 21 |
29 bool VideoDecoderVerbatim::IsReadyForData() { | 22 bool VideoDecoderVerbatim::IsReadyForData() { |
30 switch (state_) { | 23 return true; |
31 case kUninitialized: | |
32 case kError: | |
33 return false; | |
34 case kReady: | |
35 case kProcessing: | |
36 case kPartitionDone: | |
37 case kDone: | |
38 return true; | |
39 } | |
40 NOTREACHED(); | |
41 return false; | |
42 } | 24 } |
43 | 25 |
44 void VideoDecoderVerbatim::Initialize(const SkISize& screen_size) { | 26 void VideoDecoderVerbatim::Initialize(const SkISize& screen_size) { |
45 updated_region_.setEmpty(); | 27 updated_region_.setEmpty(); |
46 screen_buffer_.reset(); | 28 screen_buffer_.reset(); |
47 | 29 |
48 screen_size_ = screen_size; | 30 screen_size_ = screen_size; |
49 // Allocate the screen buffer, if necessary. | 31 // Allocate the screen buffer, if necessary. |
50 if (!screen_size_.isEmpty()) { | 32 if (!screen_size_.isEmpty()) { |
51 screen_buffer_.reset(new uint8[ | 33 screen_buffer_.reset( |
52 screen_size_.width() * screen_size_.height() * kBytesPerPixel]); | 34 new uint8 |
35 [screen_size_.width() * screen_size_.height() * kBytesPerPixel]); | |
53 } | 36 } |
54 | |
55 state_ = kReady; | |
56 } | 37 } |
57 | 38 |
58 VideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket( | 39 VideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket( |
59 const VideoPacket* packet) { | 40 const VideoPacket* packet) { |
60 UpdateStateForPacket(packet); | 41 SkRegion region; |
61 | 42 for (int i = 0; i < packet->dirty_rects_size(); ++i) { |
62 if (state_ == kError) { | 43 Rect remoting_rect = packet->dirty_rects(i); |
63 return DECODE_ERROR; | 44 SkIRect rect = |
45 SkIRect::MakeXYWH(remoting_rect.x(), remoting_rect.y(), | |
46 remoting_rect.width(), remoting_rect.height()); | |
47 region.op(rect, SkRegion::kUnion_Op); | |
64 } | 48 } |
65 | 49 |
66 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data()); | 50 updated_region_.op(region, SkRegion::kUnion_Op); |
67 const int in_size = packet->data().size(); | |
68 const int row_size = clip_.width() * kBytesPerPixel; | |
69 | 51 |
70 int out_stride = screen_size_.width() * kBytesPerPixel; | 52 const char* in = packet->data().data(); |
71 uint8* out = screen_buffer_.get() + out_stride * (clip_.top() + row_y_) + | 53 int stride = kBytesPerPixel * screen_size_.width(); |
Wez
2013/09/12 14:20:15
nit: buffer_row_bytes or buffer_stride?
Sergey Ulanov
2013/09/12 19:18:45
They are the same for the frames generated by this
| |
72 kBytesPerPixel * clip_.left(); | 54 for (SkRegion::Iterator iter(region); !iter.done(); iter.next()) { |
73 | 55 const SkIRect& rect = iter.rect(); |
Wez
2013/09/12 14:20:15
Need to check that |rect| is contained within |scr
Sergey Ulanov
2013/09/12 19:18:45
Done.
| |
74 // Consume all the data in the message. | 56 int row_size = kBytesPerPixel * rect.width(); |
Wez
2013/09/12 14:20:15
nit: row_bytes or source_stride or packet[_data]_s
Sergey Ulanov
2013/09/12 19:18:45
size of a single raw in the rect being decoded.
| |
75 int used = 0; | 57 uint8_t* out = screen_buffer_.get() + rect.top() * stride + |
76 while (used < in_size) { | 58 rect.left() * kBytesPerPixel; |
77 if (row_y_ >= clip_.height()) { | 59 for (int y = rect.y(); y < rect.y() + rect.height(); ++y) { |
78 state_ = kError; | 60 memcpy(out, in, row_size); |
79 LOG(WARNING) << "Too much data is received for the given rectangle."; | 61 in += row_size; |
80 return DECODE_ERROR; | 62 if (in > packet->data().data() + packet->data().size()) { |
81 } | 63 LOG(ERROR) << "Invalid packet received"; |
82 | 64 return DECODE_ERROR; |
83 int bytes_to_copy = std::min(in_size - used, row_size - row_pos_); | 65 } |
84 memcpy(out + row_pos_, in + used, bytes_to_copy); | 66 out += stride; |
85 | |
86 used += bytes_to_copy; | |
87 row_pos_ += bytes_to_copy; | |
88 | |
89 // If this row is completely filled then move onto the next row. | |
90 if (row_pos_ == row_size) { | |
91 ++row_y_; | |
92 row_pos_ = 0; | |
93 out += out_stride; | |
94 } | 67 } |
95 } | 68 } |
96 | 69 |
97 if (state_ == kPartitionDone || state_ == kDone) { | 70 return DECODE_DONE; |
98 if (row_y_ < clip_.height()) { | |
99 state_ = kError; | |
100 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; | |
101 return DECODE_ERROR; | |
102 } | |
103 | |
104 updated_region_.op(clip_, SkRegion::kUnion_Op); | |
105 } | |
106 | |
107 if (state_ == kDone) { | |
108 return DECODE_DONE; | |
109 } else { | |
110 return DECODE_IN_PROGRESS; | |
111 } | |
112 } | |
113 | |
114 void VideoDecoderVerbatim::UpdateStateForPacket(const VideoPacket* packet) { | |
115 if (state_ == kError) { | |
116 return; | |
117 } | |
118 | |
119 if (packet->flags() & VideoPacket::FIRST_PACKET) { | |
120 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { | |
121 state_ = kError; | |
122 LOG(WARNING) << "Received unexpected FIRST_PACKET."; | |
123 return; | |
124 } | |
125 | |
126 // Reset the buffer location status variables on the first packet. | |
127 clip_.setXYWH(packet->format().x(), packet->format().y(), | |
128 packet->format().width(), packet->format().height()); | |
129 if (!SkIRect::MakeSize(screen_size_).contains(clip_)) { | |
130 state_ = kError; | |
131 LOG(WARNING) << "Invalid clipping area received."; | |
132 return; | |
133 } | |
134 | |
135 state_ = kProcessing; | |
136 row_pos_ = 0; | |
137 row_y_ = 0; | |
138 } | |
139 | |
140 if (state_ != kProcessing) { | |
141 state_ = kError; | |
142 LOG(WARNING) << "Received unexpected packet."; | |
143 return; | |
144 } | |
145 | |
146 if (packet->flags() & VideoPacket::LAST_PACKET) { | |
147 if (state_ != kProcessing) { | |
148 state_ = kError; | |
149 LOG(WARNING) << "Received unexpected LAST_PACKET."; | |
150 return; | |
151 } | |
152 state_ = kPartitionDone; | |
153 } | |
154 | |
155 if (packet->flags() & VideoPacket::LAST_PARTITION) { | |
156 if (state_ != kPartitionDone) { | |
157 state_ = kError; | |
158 LOG(WARNING) << "Received unexpected LAST_PARTITION."; | |
159 return; | |
160 } | |
161 state_ = kDone; | |
162 } | |
163 | |
164 return; | |
165 } | 71 } |
166 | 72 |
167 VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() { | 73 VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() { |
168 return VideoPacketFormat::ENCODING_VERBATIM; | 74 return VideoPacketFormat::ENCODING_VERBATIM; |
169 } | 75 } |
170 | 76 |
171 void VideoDecoderVerbatim::Invalidate(const SkISize& view_size, | 77 void VideoDecoderVerbatim::Invalidate(const SkISize& view_size, |
172 const SkRegion& region) { | 78 const SkRegion& region) { |
173 updated_region_.op(region, SkRegion::kUnion_Op); | 79 updated_region_.op(region, SkRegion::kUnion_Op); |
174 } | 80 } |
(...skipping 26 matching lines...) Expand all Loading... | |
201 } | 107 } |
202 | 108 |
203 updated_region_.setEmpty(); | 109 updated_region_.setEmpty(); |
204 } | 110 } |
205 | 111 |
206 const SkRegion* VideoDecoderVerbatim::GetImageShape() { | 112 const SkRegion* VideoDecoderVerbatim::GetImageShape() { |
207 return NULL; | 113 return NULL; |
208 } | 114 } |
209 | 115 |
210 } // namespace remoting | 116 } // namespace remoting |
OLD | NEW |