OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 clip_rect_(SkIRect::MakeEmpty()), |
26 horizontal_scale_ratio_(1.0), | 26 output_size_(SkISize::Make(0, 0)) { |
27 vertical_scale_ratio_(1.0) { | |
28 } | 27 } |
29 | 28 |
30 DecoderVp8::~DecoderVp8() { | 29 DecoderVp8::~DecoderVp8() { |
31 if (codec_) { | 30 if (codec_) { |
32 vpx_codec_err_t ret = vpx_codec_destroy(codec_); | 31 vpx_codec_err_t ret = vpx_codec_destroy(codec_); |
33 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; | 32 CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; |
34 } | 33 } |
35 delete codec_; | 34 delete codec_; |
36 } | 35 } |
37 | 36 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 RectVector rects; | 95 RectVector rects; |
97 rects.reserve(packet->dirty_rects_size()); | 96 rects.reserve(packet->dirty_rects_size()); |
98 for (int i = 0; i < packet->dirty_rects_size(); ++i) { | 97 for (int i = 0; i < packet->dirty_rects_size(); ++i) { |
99 Rect remoting_rect = packet->dirty_rects(i); | 98 Rect remoting_rect = packet->dirty_rects(i); |
100 rects.push_back(SkIRect::MakeXYWH(remoting_rect.x(), | 99 rects.push_back(SkIRect::MakeXYWH(remoting_rect.x(), |
101 remoting_rect.y(), | 100 remoting_rect.y(), |
102 remoting_rect.width(), | 101 remoting_rect.width(), |
103 remoting_rect.height())); | 102 remoting_rect.height())); |
104 } | 103 } |
105 | 104 |
106 if (!DoScaling()) | 105 // TODO(wez): Fix the rest of the decode pipeline not to assume the frame |
107 ConvertRects(rects, &updated_rects_); | 106 // size is the host dimensions, since it's not when scaling. If the host |
108 else | 107 // gets smaller, then the output size will be too big and we'll overrun the |
109 ScaleAndConvertRects(rects, &updated_rects_); | 108 // frame, so currently we render 1:1 in that case; the app will see the |
109 // host size change and resize us if need be. | |
110 if ((output_size_.width() > static_cast<int>(frame_->width())) || | |
111 (output_size_.height() > static_cast<int>(frame_->height()))) { | |
112 output_size_.set(frame_->width(), frame_->height()); | |
113 } | |
114 | |
115 RefreshRects(rects); | |
110 return DECODE_DONE; | 116 return DECODE_DONE; |
111 } | 117 } |
112 | 118 |
113 void DecoderVp8::GetUpdatedRects(RectVector* rects) { | 119 void DecoderVp8::GetUpdatedRects(RectVector* rects) { |
114 rects->swap(updated_rects_); | 120 rects->swap(updated_rects_); |
115 } | 121 } |
116 | 122 |
117 void DecoderVp8::Reset() { | 123 void DecoderVp8::Reset() { |
118 frame_ = NULL; | 124 frame_ = NULL; |
119 state_ = kUninitialized; | 125 state_ = kUninitialized; |
120 } | 126 } |
121 | 127 |
122 bool DecoderVp8::IsReadyForData() { | 128 bool DecoderVp8::IsReadyForData() { |
123 return state_ == kReady; | 129 return state_ == kReady; |
124 } | 130 } |
125 | 131 |
126 VideoPacketFormat::Encoding DecoderVp8::Encoding() { | 132 VideoPacketFormat::Encoding DecoderVp8::Encoding() { |
127 return VideoPacketFormat::ENCODING_VP8; | 133 return VideoPacketFormat::ENCODING_VP8; |
128 } | 134 } |
129 | 135 |
130 void DecoderVp8::SetScaleRatios(double horizontal_ratio, | 136 void DecoderVp8::SetOutputSize(const SkISize& size) { |
131 double vertical_ratio) { | 137 output_size_ = size; |
132 // TODO(hclam): Ratio greater than 1.0 is not supported. This is | |
133 // because we need to reallocate the backing video frame and this | |
134 // is not implemented yet. | |
135 if (horizontal_ratio > 1.0 || horizontal_ratio <= 0.0 || | |
136 vertical_ratio > 1.0 || vertical_ratio <= 0.0) { | |
137 return; | |
138 } | |
139 | |
140 horizontal_scale_ratio_ = horizontal_ratio; | |
141 vertical_scale_ratio_ = vertical_ratio; | |
142 } | 138 } |
143 | 139 |
144 void DecoderVp8::SetClipRect(const SkIRect& clip_rect) { | 140 void DecoderVp8::SetClipRect(const SkIRect& clip_rect) { |
145 clip_rect_ = clip_rect; | 141 clip_rect_ = clip_rect; |
146 } | 142 } |
147 | 143 |
148 void DecoderVp8::RefreshRects(const RectVector& rects) { | 144 void DecoderVp8::RefreshRects(const RectVector& rects) { |
149 if (!DoScaling()) | 145 if (!DoScaling()) |
150 ConvertRects(rects, &updated_rects_); | 146 ConvertRects(rects, &updated_rects_); |
151 else | 147 else |
152 ScaleAndConvertRects(rects, &updated_rects_); | 148 ScaleAndConvertRects(rects, &updated_rects_); |
153 } | 149 } |
154 | 150 |
155 bool DecoderVp8::DoScaling() const { | 151 bool DecoderVp8::DoScaling() const { |
156 return horizontal_scale_ratio_ != 1.0 || vertical_scale_ratio_ != 1.0; | 152 DCHECK(last_image_); |
153 return !output_size_.equals(last_image_->d_w, last_image_->d_h); | |
157 } | 154 } |
158 | 155 |
159 void DecoderVp8::ConvertRects(const RectVector& input_rects, | 156 void DecoderVp8::ConvertRects(const RectVector& input_rects, |
160 RectVector* output_rects) { | 157 RectVector* output_rects) { |
161 if (!last_image_) | 158 if (!last_image_) |
162 return; | 159 return; |
163 | 160 |
164 // The conversion routine we use is optimized for even widths & heights. | 161 // The conversion routine we use is optimized for even widths & heights. |
165 int image_width = RoundToTwosMultiple(last_image_->d_w); | 162 int image_width = RoundToTwosMultiple(last_image_->d_w); |
166 int image_height = RoundToTwosMultiple(last_image_->d_h); | 163 int image_height = RoundToTwosMultiple(last_image_->d_h); |
(...skipping 29 matching lines...) Expand all Loading... | |
196 | 193 |
197 output_rects->push_back(dest_rect); | 194 output_rects->push_back(dest_rect); |
198 } | 195 } |
199 } | 196 } |
200 | 197 |
201 void DecoderVp8::ScaleAndConvertRects(const RectVector& input_rects, | 198 void DecoderVp8::ScaleAndConvertRects(const RectVector& input_rects, |
202 RectVector* output_rects) { | 199 RectVector* output_rects) { |
203 if (!last_image_) | 200 if (!last_image_) |
204 return; | 201 return; |
205 | 202 |
206 int input_width = last_image_->d_w; | 203 DCHECK(output_size_.width() <= static_cast<int>(frame_->width())); |
207 int input_height = last_image_->d_h; | 204 DCHECK(output_size_.height() <= static_cast<int>(frame_->height())); |
208 | |
209 uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane); | |
210 const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane); | |
211 | |
212 // TODO(wez): Resize |frame_| to our desired output dimensions when scaling. | |
213 int output_width = ceil(input_width * horizontal_scale_ratio_); | |
214 int output_height = ceil(input_height * vertical_scale_ratio_); | |
215 | 205 |
216 output_rects->clear(); | 206 output_rects->clear(); |
217 | 207 |
218 // Clip based on both the output dimensions and Pepper clip rect. | 208 // Clip based on both the output dimensions and Pepper clip rect. |
219 SkIRect clip_rect = clip_rect_; | 209 SkIRect clip_rect = clip_rect_; |
220 if (!clip_rect.intersect(SkIRect::MakeWH(output_width, output_height))) | 210 if (!clip_rect.intersect(output_size_)) |
Sergey Ulanov
2011/12/21 02:38:19
Does this compile given that |output_size_| is a n
| |
221 return; | 211 return; |
222 | 212 |
213 SkISize image_size(last_image_->d_w, last_image_->d_h); | |
214 uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane); | |
215 const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane); | |
216 | |
223 output_rects->reserve(input_rects.size()); | 217 output_rects->reserve(input_rects.size()); |
224 | 218 |
225 for (size_t i = 0; i < input_rects.size(); ++i) { | 219 for (size_t i = 0; i < input_rects.size(); ++i) { |
226 // Determine the scaled area affected by this rectangle changing. | 220 // Determine the scaled area affected by this rectangle changing. |
227 SkIRect output_rect = ScaleRect(input_rects[i], | 221 SkIRect output_rect = ScaleRect(dest_rect, image_size, output_size_); |
228 horizontal_scale_ratio_, | |
229 vertical_scale_ratio_); | |
230 if (!output_rect.intersect(clip_rect)) | 222 if (!output_rect.intersect(clip_rect)) |
231 continue; | 223 continue; |
232 | 224 |
233 // The scaler will not read outside the input dimensions. | 225 // The scaler will not read outside the input dimensions. |
234 ScaleYUVToRGB32WithRect(last_image_->planes[0], | 226 ScaleYUVToRGB32WithRect(last_image_->planes[0], |
235 last_image_->planes[1], | 227 last_image_->planes[1], |
236 last_image_->planes[2], | 228 last_image_->planes[2], |
237 output_rgb_buf, | 229 output_rgb_buf, |
238 input_rects[i], | 230 input_rects[i], |
239 output_rect, | 231 output_rect, |
240 last_image_->stride[0], | 232 last_image_->stride[0], |
241 last_image_->stride[1], | 233 last_image_->stride[1], |
242 output_stride); | 234 output_stride); |
243 output_rects->push_back(output_rect); | 235 output_rects->push_back(output_rect); |
244 } | 236 } |
245 } | 237 } |
246 | 238 |
247 } // namespace remoting | 239 } // namespace remoting |
OLD | NEW |