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

Side by Side Diff: trunk/src/remoting/codec/video_decoder_vp8.cc

Issue 24217003: Revert 224101 "Remove dependency on Skia from chromoting client." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 3 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/codec/video_decoder_vp8.h" 5 #include "remoting/codec/video_decoder_vp8.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 10 matching lines...) Expand all
21 21
22 namespace remoting { 22 namespace remoting {
23 23
24 enum { kBytesPerPixelRGB32 = 4 }; 24 enum { kBytesPerPixelRGB32 = 4 };
25 25
26 const uint32 kTransparent = 0; 26 const uint32 kTransparent = 0;
27 27
28 VideoDecoderVp8::VideoDecoderVp8() 28 VideoDecoderVp8::VideoDecoderVp8()
29 : state_(kUninitialized), 29 : state_(kUninitialized),
30 codec_(NULL), 30 codec_(NULL),
31 last_image_(NULL) { 31 last_image_(NULL),
32 screen_size_(SkISize::Make(0, 0)) {
32 } 33 }
33 34
34 VideoDecoderVp8::~VideoDecoderVp8() { 35 VideoDecoderVp8::~VideoDecoderVp8() {
35 if (codec_) { 36 if (codec_) {
36 vpx_codec_err_t ret = vpx_codec_destroy(codec_); 37 vpx_codec_err_t ret = vpx_codec_destroy(codec_);
37 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; 38 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
38 } 39 }
39 delete codec_; 40 delete codec_;
40 } 41 }
41 42
42 bool VideoDecoderVp8::IsReadyForData() { 43 void VideoDecoderVp8::Initialize(const SkISize& screen_size) {
43 return state_ == kReady; 44 DCHECK(!screen_size.isEmpty());
44 }
45
46 void VideoDecoderVp8::Initialize(const webrtc::DesktopSize& screen_size) {
47 DCHECK(!screen_size.is_empty());
48 45
49 screen_size_ = screen_size; 46 screen_size_ = screen_size;
50 state_ = kReady; 47 state_ = kReady;
51 48
52 transparent_region_.SetRect(webrtc::DesktopRect::MakeSize(screen_size_)); 49 transparent_region_.setRect(SkIRect::MakeSize(screen_size_));
53 } 50 }
54 51
55 VideoDecoder::DecodeResult VideoDecoderVp8::DecodePacket( 52 VideoDecoder::DecodeResult VideoDecoderVp8::DecodePacket(
56 const VideoPacket* packet) { 53 const VideoPacket* packet) {
57 DCHECK_EQ(kReady, state_); 54 DCHECK_EQ(kReady, state_);
58 55
59 // Initialize the codec as needed. 56 // Initialize the codec as needed.
60 if (!codec_) { 57 if (!codec_) {
61 codec_ = new vpx_codec_ctx_t(); 58 codec_ = new vpx_codec_ctx_t();
62 59
63 // TODO(hclam): Scale the number of threads with number of cores of the 60 // TODO(hclam): Scale the number of threads with number of cores of the
64 // machine. 61 // machine.
65 vpx_codec_dec_cfg config; 62 vpx_codec_dec_cfg config;
66 config.w = 0; 63 config.w = 0;
67 config.h = 0; 64 config.h = 0;
68 config.threads = 2; 65 config.threads = 2;
69 vpx_codec_err_t ret = 66 vpx_codec_err_t ret =
70 vpx_codec_dec_init(codec_, vpx_codec_vp8_dx(), &config, 0); 67 vpx_codec_dec_init(
68 codec_, vpx_codec_vp8_dx(), &config, 0);
71 if (ret != VPX_CODEC_OK) { 69 if (ret != VPX_CODEC_OK) {
72 LOG(INFO) << "Cannot initialize codec."; 70 LOG(INFO) << "Cannot initialize codec.";
73 delete codec_; 71 delete codec_;
74 codec_ = NULL; 72 codec_ = NULL;
75 state_ = kError; 73 state_ = kError;
76 return DECODE_ERROR; 74 return DECODE_ERROR;
77 } 75 }
78 } 76 }
79 77
80 // Do the actual decoding. 78 // Do the actual decoding.
81 vpx_codec_err_t ret = vpx_codec_decode( 79 vpx_codec_err_t ret = vpx_codec_decode(
82 codec_, reinterpret_cast<const uint8*>(packet->data().data()), 80 codec_, reinterpret_cast<const uint8*>(packet->data().data()),
83 packet->data().size(), NULL, 0); 81 packet->data().size(), NULL, 0);
84 if (ret != VPX_CODEC_OK) { 82 if (ret != VPX_CODEC_OK) {
85 LOG(INFO) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n" 83 LOG(INFO) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n"
86 << "Details: " << vpx_codec_error(codec_) << "\n" 84 << "Details: " << vpx_codec_error(codec_) << "\n"
87 << vpx_codec_error_detail(codec_); 85 << vpx_codec_error_detail(codec_);
88 return DECODE_ERROR; 86 return DECODE_ERROR;
89 } 87 }
90 88
91 // Gets the decoded data. 89 // Gets the decoded data.
92 vpx_codec_iter_t iter = NULL; 90 vpx_codec_iter_t iter = NULL;
93 vpx_image_t* image = vpx_codec_get_frame(codec_, &iter); 91 vpx_image_t* image = vpx_codec_get_frame(codec_, &iter);
94 if (!image) { 92 if (!image) {
95 LOG(INFO) << "No video frame decoded"; 93 LOG(INFO) << "No video frame decoded";
96 return DECODE_ERROR; 94 return DECODE_ERROR;
97 } 95 }
98 last_image_ = image; 96 last_image_ = image;
99 97
100 webrtc::DesktopRegion region; 98 SkRegion region;
101 for (int i = 0; i < packet->dirty_rects_size(); ++i) { 99 for (int i = 0; i < packet->dirty_rects_size(); ++i) {
102 Rect remoting_rect = packet->dirty_rects(i); 100 Rect remoting_rect = packet->dirty_rects(i);
103 region.AddRect(webrtc::DesktopRect::MakeXYWH( 101 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(),
104 remoting_rect.x(), remoting_rect.y(), 102 remoting_rect.y(),
105 remoting_rect.width(), remoting_rect.height())); 103 remoting_rect.width(),
104 remoting_rect.height());
105 region.op(rect, SkRegion::kUnion_Op);
106 } 106 }
107 107
108 updated_region_.AddRegion(region); 108 updated_region_.op(region, SkRegion::kUnion_Op);
109 109
110 // Update the desktop shape region. 110 // Update the desktop shape region.
111 webrtc::DesktopRegion desktop_shape_region; 111 SkRegion desktop_shape_region;
112 if (packet->has_use_desktop_shape()) { 112 if (packet->has_use_desktop_shape()) {
113 for (int i = 0; i < packet->desktop_shape_rects_size(); ++i) { 113 for (int i = 0; i < packet->desktop_shape_rects_size(); ++i) {
114 Rect remoting_rect = packet->desktop_shape_rects(i); 114 Rect remoting_rect = packet->desktop_shape_rects(i);
115 desktop_shape_region.AddRect(webrtc::DesktopRect::MakeXYWH( 115 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(),
116 remoting_rect.x(), remoting_rect.y(), 116 remoting_rect.y(),
117 remoting_rect.width(), remoting_rect.height())); 117 remoting_rect.width(),
118 remoting_rect.height());
119 desktop_shape_region.op(rect, SkRegion::kUnion_Op);
118 } 120 }
119 } else { 121 } else {
120 // Fallback for the case when the host didn't include the desktop shape 122 // Fallback for the case when the host didn't include the desktop shape
121 // region. 123 // region.
122 desktop_shape_region = 124 desktop_shape_region = SkRegion(SkIRect::MakeSize(screen_size_));
123 webrtc::DesktopRegion(webrtc::DesktopRect::MakeSize(screen_size_));
124 } 125 }
125 126
126 UpdateImageShapeRegion(&desktop_shape_region); 127 UpdateImageShapeRegion(&desktop_shape_region);
127 128
128 return DECODE_DONE; 129 return DECODE_DONE;
129 } 130 }
130 131
132 bool VideoDecoderVp8::IsReadyForData() {
133 return state_ == kReady;
134 }
135
131 VideoPacketFormat::Encoding VideoDecoderVp8::Encoding() { 136 VideoPacketFormat::Encoding VideoDecoderVp8::Encoding() {
132 return VideoPacketFormat::ENCODING_VP8; 137 return VideoPacketFormat::ENCODING_VP8;
133 } 138 }
134 139
135 void VideoDecoderVp8::Invalidate(const webrtc::DesktopSize& view_size, 140 void VideoDecoderVp8::Invalidate(const SkISize& view_size,
136 const webrtc::DesktopRegion& region) { 141 const SkRegion& region) {
137 DCHECK_EQ(kReady, state_); 142 DCHECK_EQ(kReady, state_);
138 DCHECK(!view_size.is_empty()); 143 DCHECK(!view_size.isEmpty());
139 144
140 for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { 145 for (SkRegion::Iterator i(region); !i.done(); i.next()) {
141 updated_region_.AddRect(ScaleRect(i.rect(), view_size, screen_size_)); 146 SkIRect rect = i.rect();
147 rect = ScaleRect(rect, view_size, screen_size_);
148 updated_region_.op(rect, SkRegion::kUnion_Op);
142 } 149 }
143 150
144 // Updated areas outside of the new desktop shape region should be made 151 // Updated areas outside of the new desktop shape region should be made
145 // transparent, not repainted. 152 // transparent, not repainted.
146 webrtc::DesktopRegion difference = updated_region_; 153 SkRegion difference = updated_region_;
147 difference.Subtract(desktop_shape_); 154 difference.op(desktop_shape_, SkRegion::kDifference_Op);
148 updated_region_.Subtract(difference); 155 updated_region_.op(difference, SkRegion::kDifference_Op);
149 transparent_region_.AddRegion(difference); 156 transparent_region_.op(difference, SkRegion::kUnion_Op);
150 } 157 }
151 158
152 void VideoDecoderVp8::RenderFrame(const webrtc::DesktopSize& view_size, 159 void VideoDecoderVp8::RenderFrame(const SkISize& view_size,
153 const webrtc::DesktopRect& clip_area, 160 const SkIRect& clip_area,
154 uint8* image_buffer, 161 uint8* image_buffer,
155 int image_stride, 162 int image_stride,
156 webrtc::DesktopRegion* output_region) { 163 SkRegion* output_region) {
157 DCHECK_EQ(kReady, state_); 164 DCHECK_EQ(kReady, state_);
158 DCHECK(!view_size.is_empty()); 165 DCHECK(!view_size.isEmpty());
159 166
160 // Early-return and do nothing if we haven't yet decoded any frames. 167 // Early-return and do nothing if we haven't yet decoded any frames.
161 if (!last_image_) 168 if (!last_image_)
162 return; 169 return;
163 170
164 webrtc::DesktopRect source_clip = 171 SkIRect source_clip = SkIRect::MakeWH(last_image_->d_w, last_image_->d_h);
165 webrtc::DesktopRect::MakeWH(last_image_->d_w, last_image_->d_h);
166 172
167 // ScaleYUVToRGB32WithRect does not currently support up-scaling. We won't 173 // ScaleYUVToRGB32WithRect does not currently support up-scaling. We won't
168 // be asked to up-scale except during resizes or if page zoom is >100%, so 174 // be asked to up-scale except during resizes or if page zoom is >100%, so
169 // we work-around the limitation by using the slower ScaleYUVToRGB32. 175 // we work-around the limitation by using the slower ScaleYUVToRGB32.
170 // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can up-scale. 176 // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can up-scale.
171 if (!updated_region_.is_empty() && 177 if (!updated_region_.isEmpty() &&
172 (source_clip.width() < view_size.width() || 178 (source_clip.width() < view_size.width() ||
173 source_clip.height() < view_size.height())) { 179 source_clip.height() < view_size.height())) {
174 // We're scaling only |clip_area| into the |image_buffer|, so we need to 180 // We're scaling only |clip_area| into the |image_buffer|, so we need to
175 // work out which source rectangle that corresponds to. 181 // work out which source rectangle that corresponds to.
176 webrtc::DesktopRect source_rect = 182 SkIRect source_rect = ScaleRect(clip_area, view_size, screen_size_);
177 ScaleRect(clip_area, view_size, screen_size_); 183 source_rect = SkIRect::MakeLTRB(RoundToTwosMultiple(source_rect.left()),
178 source_rect = webrtc::DesktopRect::MakeLTRB( 184 RoundToTwosMultiple(source_rect.top()),
179 RoundToTwosMultiple(source_rect.left()), 185 source_rect.right(),
180 RoundToTwosMultiple(source_rect.top()), 186 source_rect.bottom());
181 source_rect.right(),
182 source_rect.bottom());
183 187
184 // If there were no changes within the clip source area then don't render. 188 // If there were no changes within the clip source area then don't render.
185 webrtc::DesktopRegion intersection(source_rect); 189 if (!updated_region_.intersects(source_rect))
186 intersection.IntersectWith(updated_region_);
187 if (intersection.is_empty())
188 return; 190 return;
189 191
190 // Scale & convert the entire clip area. 192 // Scale & convert the entire clip area.
191 int y_offset = CalculateYOffset(source_rect.left(), source_rect.top(), 193 int y_offset = CalculateYOffset(source_rect.x(),
194 source_rect.y(),
192 last_image_->stride[0]); 195 last_image_->stride[0]);
193 int uv_offset = CalculateUVOffset(source_rect.left(), source_rect.top(), 196 int uv_offset = CalculateUVOffset(source_rect.x(),
197 source_rect.y(),
194 last_image_->stride[1]); 198 last_image_->stride[1]);
195 ScaleYUVToRGB32(last_image_->planes[0] + y_offset, 199 ScaleYUVToRGB32(last_image_->planes[0] + y_offset,
196 last_image_->planes[1] + uv_offset, 200 last_image_->planes[1] + uv_offset,
197 last_image_->planes[2] + uv_offset, 201 last_image_->planes[2] + uv_offset,
198 image_buffer, 202 image_buffer,
199 source_rect.width(), 203 source_rect.width(),
200 source_rect.height(), 204 source_rect.height(),
201 clip_area.width(), 205 clip_area.width(),
202 clip_area.height(), 206 clip_area.height(),
203 last_image_->stride[0], 207 last_image_->stride[0],
204 last_image_->stride[1], 208 last_image_->stride[1],
205 image_stride, 209 image_stride,
206 media::YV12, 210 media::YV12,
207 media::ROTATE_0, 211 media::ROTATE_0,
208 media::FILTER_BILINEAR); 212 media::FILTER_BILINEAR);
209 213
210 output_region->AddRect(clip_area); 214 output_region->op(clip_area, SkRegion::kUnion_Op);
211 updated_region_.Subtract(source_rect); 215 updated_region_.op(source_rect, SkRegion::kDifference_Op);
212 return; 216 return;
213 } 217 }
214 218
215 for (webrtc::DesktopRegion::Iterator i(updated_region_); 219 for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) {
216 !i.IsAtEnd(); i.Advance()) {
217 // Determine the scaled area affected by this rectangle changing. 220 // Determine the scaled area affected by this rectangle changing.
218 webrtc::DesktopRect rect = i.rect(); 221 SkIRect rect = i.rect();
219 rect.IntersectWith(source_clip); 222 if (!rect.intersect(source_clip))
220 if (rect.is_empty())
221 continue; 223 continue;
222 rect = ScaleRect(rect, screen_size_, view_size); 224 rect = ScaleRect(rect, screen_size_, view_size);
223 rect.IntersectWith(clip_area); 225 if (!rect.intersect(clip_area))
224 if (rect.is_empty())
225 continue; 226 continue;
226 227
227 ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], 228 ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0],
228 last_image_->planes[1], 229 last_image_->planes[1],
229 last_image_->planes[2], 230 last_image_->planes[2],
230 last_image_->stride[0], 231 last_image_->stride[0],
231 last_image_->stride[1], 232 last_image_->stride[1],
232 screen_size_, 233 screen_size_,
233 source_clip, 234 source_clip,
234 image_buffer, 235 image_buffer,
235 image_stride, 236 image_stride,
236 view_size, 237 view_size,
237 clip_area, 238 clip_area,
238 rect); 239 rect);
239 240
240 output_region->AddRect(rect); 241 output_region->op(rect, SkRegion::kUnion_Op);
241 } 242 }
242 243
243 updated_region_.Subtract(ScaleRect(clip_area, view_size, screen_size_)); 244 updated_region_.op(ScaleRect(clip_area, view_size, screen_size_),
245 SkRegion::kDifference_Op);
244 246
245 for (webrtc::DesktopRegion::Iterator i(transparent_region_); 247 for (SkRegion::Iterator i(transparent_region_); !i.done(); i.next()) {
246 !i.IsAtEnd(); i.Advance()) {
247 // Determine the scaled area affected by this rectangle changing. 248 // Determine the scaled area affected by this rectangle changing.
248 webrtc::DesktopRect rect = i.rect(); 249 SkIRect rect = i.rect();
249 rect.IntersectWith(source_clip); 250 if (!rect.intersect(source_clip))
250 if (rect.is_empty())
251 continue; 251 continue;
252 rect = ScaleRect(rect, screen_size_, view_size); 252 rect = ScaleRect(rect, screen_size_, view_size);
253 rect.IntersectWith(clip_area); 253 if (!rect.intersect(clip_area))
254 if (rect.is_empty())
255 continue; 254 continue;
256 255
257 // Fill the rectange with transparent pixels. 256 // Fill the rectange with transparent pixels.
258 FillRect(image_buffer, image_stride, rect, kTransparent); 257 FillRect(image_buffer, image_stride, rect, kTransparent);
259 output_region->AddRect(rect); 258 output_region->op(rect, SkRegion::kUnion_Op);
260 } 259 }
261 260
262 webrtc::DesktopRect scaled_clip_area = 261 SkIRect scaled_clip_area = ScaleRect(clip_area, view_size, screen_size_);
263 ScaleRect(clip_area, view_size, screen_size_); 262 updated_region_.op(scaled_clip_area, SkRegion::kDifference_Op);
264 updated_region_.Subtract(scaled_clip_area); 263 transparent_region_.op(scaled_clip_area, SkRegion::kDifference_Op);
265 transparent_region_.Subtract(scaled_clip_area);
266 } 264 }
267 265
268 const webrtc::DesktopRegion* VideoDecoderVp8::GetImageShape() { 266 const SkRegion* VideoDecoderVp8::GetImageShape() {
269 return &desktop_shape_; 267 return &desktop_shape_;
270 } 268 }
271 269
272 void VideoDecoderVp8::FillRect(uint8* buffer, 270 void VideoDecoderVp8::FillRect(uint8* buffer,
273 int stride, 271 int stride,
274 const webrtc::DesktopRect& rect, 272 const SkIRect& rect,
275 uint32 color) { 273 uint32 color) {
276 uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) + 274 uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) +
277 (rect.left() * kBytesPerPixelRGB32)); 275 (rect.left() * kBytesPerPixelRGB32));
278 int width = rect.width(); 276 int width = rect.width();
279 for (int height = rect.height(); height > 0; --height) { 277 for (int height = rect.height(); height > 0; --height) {
280 std::fill(ptr, ptr + width, color); 278 std::fill(ptr, ptr + width, color);
281 ptr += stride / kBytesPerPixelRGB32; 279 ptr += stride / kBytesPerPixelRGB32;
282 } 280 }
283 } 281 }
284 282
285 void VideoDecoderVp8::UpdateImageShapeRegion( 283 void VideoDecoderVp8::UpdateImageShapeRegion(SkRegion* new_desktop_shape) {
286 webrtc::DesktopRegion* new_desktop_shape) {
287 // Add all areas that have been updated or become transparent to the 284 // Add all areas that have been updated or become transparent to the
288 // transparent region. Exclude anything within the new desktop shape. 285 // transparent region. Exclude anything within the new desktop shape.
289 transparent_region_.AddRegion(desktop_shape_); 286 transparent_region_.op(desktop_shape_, SkRegion::kUnion_Op);
290 transparent_region_.AddRegion(updated_region_); 287 transparent_region_.op(updated_region_, SkRegion::kUnion_Op);
291 transparent_region_.Subtract(*new_desktop_shape); 288 transparent_region_.op(*new_desktop_shape, SkRegion::kDifference_Op);
292 289
293 // Add newly exposed areas to the update region and limit updates to the new 290 // Add newly exposed areas to the update region and limit updates to the new
294 // desktop shape. 291 // desktop shape.
295 webrtc::DesktopRegion difference = *new_desktop_shape; 292 SkRegion difference = *new_desktop_shape;
296 difference.Subtract(desktop_shape_); 293 difference.op(desktop_shape_, SkRegion::kDifference_Op);
297 updated_region_.AddRegion(difference); 294 updated_region_.op(difference, SkRegion::kUnion_Op);
298 updated_region_.IntersectWith(*new_desktop_shape); 295 updated_region_.op(*new_desktop_shape, SkRegion::kIntersect_Op);
299 296
300 // Set the new desktop shape region. 297 // Set the new desktop shape region.
301 desktop_shape_.Swap(new_desktop_shape); 298 desktop_shape_.swap(*new_desktop_shape);
302 } 299 }
303 300
304 } // namespace remoting 301 } // namespace remoting
OLDNEW
« no previous file with comments | « trunk/src/remoting/codec/video_decoder_vp8.h ('k') | trunk/src/remoting/codec/video_encoder_vp8.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698