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/base/decoder_vp8.h" | 5 #include "remoting/base/decoder_vp8.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/base/media.h" | 10 #include "media/base/media.h" |
11 #include "media/base/yuv_convert.h" | 11 #include "media/base/yuv_convert.h" |
12 #include "remoting/base/util.h" | 12 #include "remoting/base/util.h" |
13 | 13 |
14 extern "C" { | 14 extern "C" { |
15 #define VPX_CODEC_DISABLE_COMPAT 1 | 15 #define VPX_CODEC_DISABLE_COMPAT 1 |
16 #include "third_party/libvpx/libvpx.h" | 16 #include "third_party/libvpx/libvpx.h" |
17 } | 17 } |
18 | 18 |
19 namespace remoting { | 19 namespace remoting { |
20 | 20 |
21 DecoderVp8::DecoderVp8() | 21 DecoderVp8::DecoderVp8() |
22 : state_(kUninitialized), | 22 : state_(kUninitialized), |
23 codec_(NULL), | 23 codec_(NULL), |
24 last_image_(NULL), | 24 last_image_(NULL), |
25 clip_rect_(SkIRect::MakeEmpty()), | 25 screen_size_(SkISize::Make(0, 0)) { |
26 output_size_(SkISize::Make(0, 0)) { | |
27 } | 26 } |
28 | 27 |
29 DecoderVp8::~DecoderVp8() { | 28 DecoderVp8::~DecoderVp8() { |
30 if (codec_) { | 29 if (codec_) { |
31 vpx_codec_err_t ret = vpx_codec_destroy(codec_); | 30 vpx_codec_err_t ret = vpx_codec_destroy(codec_); |
32 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; | 31 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; |
33 } | 32 } |
34 delete codec_; | 33 delete codec_; |
35 } | 34 } |
36 | 35 |
37 void DecoderVp8::Initialize(scoped_refptr<media::VideoFrame> frame) { | 36 void DecoderVp8::Initialize(const SkISize& screen_size) { |
38 DCHECK_EQ(kUninitialized, state_); | 37 screen_size_ = screen_size; |
39 | |
40 if (frame->format() != media::VideoFrame::RGB32) { | |
41 LOG(INFO) << "DecoderVp8 only supports RGB32 as output"; | |
42 state_ = kError; | |
43 return; | |
44 } | |
45 frame_ = frame; | |
46 | |
47 state_ = kReady; | 38 state_ = kReady; |
48 } | 39 } |
49 | 40 |
50 Decoder::DecodeResult DecoderVp8::DecodePacket(const VideoPacket* packet) { | 41 Decoder::DecodeResult DecoderVp8::DecodePacket(const VideoPacket* packet) { |
51 DCHECK_EQ(kReady, state_); | 42 DCHECK_EQ(kReady, state_); |
52 | 43 |
53 // Initialize the codec as needed. | 44 // Initialize the codec as needed. |
54 if (!codec_) { | 45 if (!codec_) { |
55 codec_ = new vpx_codec_ctx_t(); | 46 codec_ = new vpx_codec_ctx_t(); |
56 | 47 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 SkRegion region; | 86 SkRegion region; |
96 for (int i = 0; i < packet->dirty_rects_size(); ++i) { | 87 for (int i = 0; i < packet->dirty_rects_size(); ++i) { |
97 Rect remoting_rect = packet->dirty_rects(i); | 88 Rect remoting_rect = packet->dirty_rects(i); |
98 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), | 89 SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), |
99 remoting_rect.y(), | 90 remoting_rect.y(), |
100 remoting_rect.width(), | 91 remoting_rect.width(), |
101 remoting_rect.height()); | 92 remoting_rect.height()); |
102 region.op(rect, SkRegion::kUnion_Op); | 93 region.op(rect, SkRegion::kUnion_Op); |
103 } | 94 } |
104 | 95 |
105 RefreshRegion(region); | 96 updated_region_.op(region, SkRegion::kUnion_Op); |
106 return DECODE_DONE; | 97 return DECODE_DONE; |
107 } | 98 } |
108 | 99 |
109 void DecoderVp8::GetUpdatedRegion(SkRegion* region) { | |
110 region->swap(updated_region_); | |
111 } | |
112 | |
113 void DecoderVp8::Reset() { | |
114 frame_ = NULL; | |
115 state_ = kUninitialized; | |
116 } | |
117 | |
118 bool DecoderVp8::IsReadyForData() { | 100 bool DecoderVp8::IsReadyForData() { |
119 return state_ == kReady; | 101 return state_ == kReady; |
120 } | 102 } |
121 | 103 |
122 VideoPacketFormat::Encoding DecoderVp8::Encoding() { | 104 VideoPacketFormat::Encoding DecoderVp8::Encoding() { |
123 return VideoPacketFormat::ENCODING_VP8; | 105 return VideoPacketFormat::ENCODING_VP8; |
124 } | 106 } |
125 | 107 |
126 void DecoderVp8::SetOutputSize(const SkISize& size) { | 108 void DecoderVp8::Invalidate(const SkISize& view_size, |
127 output_size_ = size; | 109 const SkRegion& region) { |
| 110 for (SkRegion::Iterator i(region); !i.done(); i.next()) { |
| 111 SkIRect rect = i.rect(); |
| 112 rect = ScaleRect(rect, view_size, screen_size_); |
| 113 updated_region_.op(rect, SkRegion::kUnion_Op); |
| 114 } |
128 } | 115 } |
129 | 116 |
130 void DecoderVp8::SetClipRect(const SkIRect& clip_rect) { | 117 void DecoderVp8::RenderFrame(const SkISize& view_size, |
131 clip_rect_ = clip_rect; | 118 const SkIRect& clip_area, |
132 } | 119 uint8* image_buffer, |
| 120 int image_stride, |
| 121 SkRegion* output_region) { |
| 122 SkIRect source_clip = SkIRect::MakeWH(last_image_->d_w, last_image_->d_h); |
133 | 123 |
134 void DecoderVp8::RefreshRegion(const SkRegion& region) { | 124 for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) { |
135 // TODO(wez): Fix the rest of the decode pipeline not to assume the frame | |
136 // size is the host dimensions, since it's not when scaling. If the host | |
137 // gets smaller, then the output size will be too big and we'll overrun the | |
138 // frame, so currently we render 1:1 in that case; the app will see the | |
139 // host size change and resize us if need be. | |
140 if (output_size_.width() > static_cast<int>(frame_->width())) | |
141 output_size_.set(frame_->width(), output_size_.height()); | |
142 if (output_size_.height() > static_cast<int>(frame_->height())) | |
143 output_size_.set(output_size_.width(), frame_->height()); | |
144 | |
145 if (!last_image_) | |
146 return; | |
147 | |
148 updated_region_.setEmpty(); | |
149 | |
150 // Clip based on both the output dimensions and Pepper clip rect. | |
151 // ConvertAndScaleYUVToRGB32Rect() requires even X and Y coordinates, so we | |
152 // align |clip_rect| to prevent clipping from breaking alignment. We then | |
153 // clamp it to the image dimensions, which may lead to odd width & height, | |
154 // which we can cope with. | |
155 SkIRect clip_rect = AlignRect(clip_rect_); | |
156 if (!clip_rect.intersect(SkIRect::MakeSize(output_size_))) | |
157 return; | |
158 | |
159 SkISize image_size = SkISize::Make(last_image_->d_w, last_image_->d_h); | |
160 uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane); | |
161 const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane); | |
162 | |
163 for (SkRegion::Iterator i(region); !i.done(); i.next()) { | |
164 // Determine the scaled area affected by this rectangle changing. | 125 // Determine the scaled area affected by this rectangle changing. |
165 // Align the rectangle so the top-left coordinates are even, for | 126 SkIRect rect = i.rect(); |
166 // ConvertAndScaleYUVToRGB32Rect(). | 127 if (!rect.intersect(source_clip)) |
167 SkIRect output_rect = ScaleRect(AlignRect(i.rect()), | 128 continue; |
168 image_size, output_size_); | 129 rect = ScaleRect(rect, screen_size_, view_size); |
169 if (!output_rect.intersect(clip_rect)) | 130 if (!rect.intersect(clip_area)) |
170 continue; | 131 continue; |
171 | 132 |
172 // The scaler will not to read outside the input dimensions. | |
173 ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], | 133 ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], |
174 last_image_->planes[1], | 134 last_image_->planes[1], |
175 last_image_->planes[2], | 135 last_image_->planes[2], |
176 last_image_->stride[0], | 136 last_image_->stride[0], |
177 last_image_->stride[1], | 137 last_image_->stride[1], |
178 image_size, | 138 screen_size_, |
179 SkIRect::MakeSize(image_size), | 139 source_clip, |
180 output_rgb_buf, | 140 image_buffer, |
181 output_stride, | 141 image_stride, |
182 output_size_, | 142 view_size, |
183 SkIRect::MakeSize(output_size_), | 143 clip_area, |
184 output_rect); | 144 rect); |
185 | 145 |
186 updated_region_.op(output_rect, SkRegion::kUnion_Op); | 146 output_region->op(rect, SkRegion::kUnion_Op); |
187 } | 147 } |
| 148 |
| 149 updated_region_.op(ScaleRect(clip_area, view_size, screen_size_), |
| 150 SkRegion::kDifference_Op); |
188 } | 151 } |
189 | 152 |
190 } // namespace remoting | 153 } // namespace remoting |
OLD | NEW |