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_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> | |
10 | |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "media/base/media.h" | 12 #include "media/base/media.h" |
11 #include "media/base/yuv_convert.h" | 13 #include "media/base/yuv_convert.h" |
12 #include "remoting/base/util.h" | 14 #include "remoting/base/util.h" |
13 | 15 |
14 extern "C" { | 16 extern "C" { |
15 #define VPX_CODEC_DISABLE_COMPAT 1 | 17 #define VPX_CODEC_DISABLE_COMPAT 1 |
16 #include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" | 18 #include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" |
17 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" | 19 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" |
18 } | 20 } |
19 | 21 |
20 namespace remoting { | 22 namespace remoting { |
21 | 23 |
24 enum { kBytesPerPixelRGB32 = 4 }; | |
25 | |
26 const uint32 kTransparent = 0; | |
27 | |
22 VideoDecoderVp8::VideoDecoderVp8() | 28 VideoDecoderVp8::VideoDecoderVp8() |
23 : state_(kUninitialized), | 29 : state_(kUninitialized), |
24 codec_(NULL), | 30 codec_(NULL), |
25 last_image_(NULL), | 31 last_image_(NULL), |
26 screen_size_(SkISize::Make(0, 0)) { | 32 screen_size_(SkISize::Make(0, 0)) { |
27 } | 33 } |
28 | 34 |
29 VideoDecoderVp8::~VideoDecoderVp8() { | 35 VideoDecoderVp8::~VideoDecoderVp8() { |
30 if (codec_) { | 36 if (codec_) { |
31 vpx_codec_err_t ret = vpx_codec_destroy(codec_); | 37 vpx_codec_err_t ret = vpx_codec_destroy(codec_); |
32 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; | 38 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; |
33 } | 39 } |
34 delete codec_; | 40 delete codec_; |
35 } | 41 } |
36 | 42 |
37 void VideoDecoderVp8::Initialize(const SkISize& screen_size) { | 43 void VideoDecoderVp8::Initialize(const SkISize& screen_size) { |
38 DCHECK(!screen_size.isEmpty()); | 44 DCHECK(!screen_size.isEmpty()); |
39 | 45 |
40 screen_size_ = screen_size; | 46 screen_size_ = screen_size; |
41 state_ = kReady; | 47 state_ = kReady; |
48 | |
49 transparent_region_.setRect(SkIRect::MakeSize(screen_size_)); | |
42 } | 50 } |
43 | 51 |
44 VideoDecoder::DecodeResult VideoDecoderVp8::DecodePacket( | 52 VideoDecoder::DecodeResult VideoDecoderVp8::DecodePacket( |
45 const VideoPacket* packet) { | 53 const VideoPacket* packet) { |
46 DCHECK_EQ(kReady, state_); | 54 DCHECK_EQ(kReady, state_); |
47 | 55 |
48 // Initialize the codec as needed. | 56 // Initialize the codec as needed. |
49 if (!codec_) { | 57 if (!codec_) { |
50 codec_ = new vpx_codec_ctx_t(); | 58 codec_ = new vpx_codec_ctx_t(); |
51 | 59 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 for (int i = 0; i < packet->dirty_rects_size(); ++i) { | 99 for (int i = 0; i < packet->dirty_rects_size(); ++i) { |
92 Rect remoting_rect = packet->dirty_rects(i); | 100 Rect remoting_rect = packet->dirty_rects(i); |
93 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), | 101 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), |
94 remoting_rect.y(), | 102 remoting_rect.y(), |
95 remoting_rect.width(), | 103 remoting_rect.width(), |
96 remoting_rect.height()); | 104 remoting_rect.height()); |
97 region.op(rect, SkRegion::kUnion_Op); | 105 region.op(rect, SkRegion::kUnion_Op); |
98 } | 106 } |
99 | 107 |
100 updated_region_.op(region, SkRegion::kUnion_Op); | 108 updated_region_.op(region, SkRegion::kUnion_Op); |
109 | |
110 // Update the desktop shape region. | |
111 SkRegion desktop_shape_region; | |
112 if (packet->has_use_desktop_shape()) { | |
113 for (int i = 0; i < packet->desktop_shape_rects_size(); ++i) { | |
114 Rect remoting_rect = packet->desktop_shape_rects(i); | |
115 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), | |
116 remoting_rect.y(), | |
117 remoting_rect.width(), | |
118 remoting_rect.height()); | |
119 desktop_shape_region.op(rect, SkRegion::kUnion_Op); | |
120 } | |
121 } else { | |
122 // Fallback for the case when the host didn't include the desktop shape | |
123 // region. | |
124 desktop_shape_region = SkRegion(SkIRect::MakeSize(screen_size_)); | |
125 } | |
126 | |
127 UpdateDesktopShapeRegion(&desktop_shape_region); | |
128 | |
101 return DECODE_DONE; | 129 return DECODE_DONE; |
102 } | 130 } |
103 | 131 |
104 bool VideoDecoderVp8::IsReadyForData() { | 132 bool VideoDecoderVp8::IsReadyForData() { |
105 return state_ == kReady; | 133 return state_ == kReady; |
106 } | 134 } |
107 | 135 |
108 VideoPacketFormat::Encoding VideoDecoderVp8::Encoding() { | 136 VideoPacketFormat::Encoding VideoDecoderVp8::Encoding() { |
109 return VideoPacketFormat::ENCODING_VP8; | 137 return VideoPacketFormat::ENCODING_VP8; |
110 } | 138 } |
111 | 139 |
112 void VideoDecoderVp8::Invalidate(const SkISize& view_size, | 140 void VideoDecoderVp8::Invalidate(const SkISize& view_size, |
113 const SkRegion& region) { | 141 const SkRegion& region) { |
114 DCHECK_EQ(kReady, state_); | 142 DCHECK_EQ(kReady, state_); |
115 DCHECK(!view_size.isEmpty()); | 143 DCHECK(!view_size.isEmpty()); |
116 | 144 |
117 for (SkRegion::Iterator i(region); !i.done(); i.next()) { | 145 for (SkRegion::Iterator i(region); !i.done(); i.next()) { |
118 SkIRect rect = i.rect(); | 146 SkIRect rect = i.rect(); |
119 rect = ScaleRect(rect, view_size, screen_size_); | 147 rect = ScaleRect(rect, view_size, screen_size_); |
120 updated_region_.op(rect, SkRegion::kUnion_Op); | 148 updated_region_.op(rect, SkRegion::kUnion_Op); |
121 } | 149 } |
150 | |
151 // Updated areas outside of the new desktop shape region should be made | |
152 // transparent, not repainted. | |
153 SkRegion diff_region = updated_region_; | |
154 diff_region.op(desktop_shape_region_, SkRegion::kDifference_Op); | |
155 updated_region_.op(diff_region, SkRegion::kDifference_Op); | |
156 transparent_region_.op(diff_region, SkRegion::kUnion_Op); | |
122 } | 157 } |
123 | 158 |
124 void VideoDecoderVp8::RenderFrame(const SkISize& view_size, | 159 void VideoDecoderVp8::RenderFrame(const SkISize& view_size, |
125 const SkIRect& clip_area, | 160 const SkIRect& clip_area, |
126 uint8* image_buffer, | 161 uint8* image_buffer, |
127 int image_stride, | 162 int image_stride, |
128 SkRegion* output_region) { | 163 SkRegion* output_region) { |
129 DCHECK_EQ(kReady, state_); | 164 DCHECK_EQ(kReady, state_); |
130 DCHECK(!view_size.isEmpty()); | 165 DCHECK(!view_size.isEmpty()); |
131 | 166 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 image_stride, | 236 image_stride, |
202 view_size, | 237 view_size, |
203 clip_area, | 238 clip_area, |
204 rect); | 239 rect); |
205 | 240 |
206 output_region->op(rect, SkRegion::kUnion_Op); | 241 output_region->op(rect, SkRegion::kUnion_Op); |
207 } | 242 } |
208 | 243 |
209 updated_region_.op(ScaleRect(clip_area, view_size, screen_size_), | 244 updated_region_.op(ScaleRect(clip_area, view_size, screen_size_), |
210 SkRegion::kDifference_Op); | 245 SkRegion::kDifference_Op); |
246 | |
247 for (SkRegion::Iterator i(transparent_region_); !i.done(); i.next()) { | |
248 // Determine the scaled area affected by this rectangle changing. | |
249 SkIRect rect = i.rect(); | |
250 if (!rect.intersect(source_clip)) | |
251 continue; | |
252 rect = ScaleRect(rect, screen_size_, view_size); | |
253 if (!rect.intersect(clip_area)) | |
254 continue; | |
255 | |
256 // Fill the rectange with transparent pixels. | |
257 FillRect(image_buffer, image_stride, rect, kTransparent); | |
258 output_region->op(rect, SkRegion::kUnion_Op); | |
259 } | |
260 | |
261 SkIRect scaled_clip_area = ScaleRect(clip_area, view_size, screen_size_); | |
262 updated_region_.op(scaled_clip_area, SkRegion::kDifference_Op); | |
263 transparent_region_.op(scaled_clip_area, SkRegion::kDifference_Op); | |
264 } | |
265 | |
266 const SkRegion* VideoDecoderVp8::GetImageShape() { | |
267 return &desktop_shape_region_; | |
268 } | |
269 | |
270 void VideoDecoderVp8::FillRect(uint8* buffer, | |
271 int stride, | |
272 const SkIRect& rect, | |
273 uint32 color) { | |
274 uint32* ptr = reinterpret_cast<uint32*>(buffer + (rect.top() * stride) + | |
275 (rect.left() * kBytesPerPixelRGB32)); | |
276 int width = rect.width(); | |
277 for (int height = rect.height(); height > 0; --height) { | |
278 std::fill(ptr, ptr + width, color); | |
279 ptr += stride / kBytesPerPixelRGB32; | |
280 } | |
281 } | |
282 | |
283 void VideoDecoderVp8::UpdateDesktopShapeRegion( | |
284 SkRegion* new_desktop_shape_region) { | |
285 // Areas that previously were within the desktop shape region and now are | |
286 // outside of it should be made transparent. | |
287 transparent_region_.op(desktop_shape_region_, SkRegion::kUnion_Op); | |
Jamie
2013/06/20 21:15:57
It took me a while to understand what was going on
alexeypa (please no reviews)
2013/06/20 22:05:11
Done.
| |
288 transparent_region_.op(*new_desktop_shape_region, SkRegion::kDifference_Op); | |
289 | |
290 // Areas that previously were outside of the desktop shape region and now are | |
291 // within the region should be repainted. | |
292 SkRegion region = *new_desktop_shape_region; | |
Jamie
2013/06/20 21:15:57
Can you use a more descriptive name for this? Mayb
alexeypa (please no reviews)
2013/06/20 22:05:11
Done.
| |
293 region.op(desktop_shape_region_, SkRegion::kDifference_Op); | |
294 updated_region_.op(region, SkRegion::kUnion_Op); | |
295 | |
296 // Set the new desktop shape region. | |
297 desktop_shape_region_.swap(*new_desktop_shape_region); | |
298 | |
299 // Updated areas outside of the new desktop shape region should be made | |
300 // transparent, not repainted. | |
301 region = updated_region_; | |
302 region.op(desktop_shape_region_, SkRegion::kDifference_Op); | |
303 updated_region_.op(region, SkRegion::kDifference_Op); | |
304 transparent_region_.op(region, SkRegion::kUnion_Op); | |
211 } | 305 } |
212 | 306 |
213 } // namespace remoting | 307 } // namespace remoting |
OLD | NEW |