| 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> |
| 8 |
| 7 #include "base/logging.h" | 9 #include "base/logging.h" |
| 8 #include "media/base/media.h" | 10 #include "media/base/media.h" |
| 9 #include "media/base/yuv_convert.h" | 11 #include "media/base/yuv_convert.h" |
| 10 #include "remoting/base/util.h" | 12 #include "remoting/base/util.h" |
| 11 | 13 |
| 12 extern "C" { | 14 extern "C" { |
| 13 #define VPX_CODEC_DISABLE_COMPAT 1 | 15 #define VPX_CODEC_DISABLE_COMPAT 1 |
| 14 #include "third_party/libvpx/libvpx.h" | 16 #include "third_party/libvpx/libvpx.h" |
| 15 } | 17 } |
| 16 | 18 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 if (!DoScaling()) | 149 if (!DoScaling()) |
| 148 ConvertRects(rects, &updated_rects_); | 150 ConvertRects(rects, &updated_rects_); |
| 149 else | 151 else |
| 150 ScaleAndConvertRects(rects, &updated_rects_); | 152 ScaleAndConvertRects(rects, &updated_rects_); |
| 151 } | 153 } |
| 152 | 154 |
| 153 bool DecoderVp8::DoScaling() const { | 155 bool DecoderVp8::DoScaling() const { |
| 154 return horizontal_scale_ratio_ != 1.0 || vertical_scale_ratio_ != 1.0; | 156 return horizontal_scale_ratio_ != 1.0 || vertical_scale_ratio_ != 1.0; |
| 155 } | 157 } |
| 156 | 158 |
| 157 void DecoderVp8::ConvertRects(const RectVector& rects, | 159 void DecoderVp8::ConvertRects(const RectVector& input_rects, |
| 158 RectVector* output_rects) { | 160 RectVector* output_rects) { |
| 159 if (!last_image_) | 161 if (!last_image_) |
| 160 return; | 162 return; |
| 161 | 163 |
| 162 uint8* data_start = frame_->data(media::VideoFrame::kRGBPlane); | 164 // The conversion routine we use is optimized for even widths & heights. |
| 163 const int stride = frame_->stride(media::VideoFrame::kRGBPlane); | 165 int image_width = RoundToTwosMultiple(last_image_->d_w); |
| 166 int image_height = RoundToTwosMultiple(last_image_->d_h); |
| 167 |
| 168 uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane); |
| 169 const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane); |
| 164 | 170 |
| 165 output_rects->clear(); | 171 output_rects->clear(); |
| 166 output_rects->reserve(rects.size()); | 172 |
| 167 for (size_t i = 0; i < rects.size(); ++i) { | 173 // Clip based on both the output dimensions and Pepper clip rect. |
| 168 // Clip by the clipping rectangle first. | 174 SkIRect clip_rect = clip_rect_; |
| 169 SkIRect dest_rect = rects[i]; | 175 if (!clip_rect.intersect(SkIRect::MakeWH(image_width, image_height))) |
| 170 if (!dest_rect.intersect(clip_rect_)) | 176 return; |
| 177 |
| 178 output_rects->reserve(input_rects.size()); |
| 179 |
| 180 for (size_t i = 0; i < input_rects.size(); ++i) { |
| 181 // Align the rectangle to avoid artifacts in color space conversion. |
| 182 SkIRect dest_rect = AlignRect(input_rects[i]); |
| 183 |
| 184 // Clip to the image and Pepper clip region. |
| 185 if (!dest_rect.intersect(clip_rect)) |
| 171 continue; | 186 continue; |
| 172 | 187 |
| 173 // Round down the image width and height. | |
| 174 int image_width = RoundToTwosMultiple(last_image_->d_w); | |
| 175 int image_height = RoundToTwosMultiple(last_image_->d_h); | |
| 176 | |
| 177 // Then clip by the rounded down dimension of the image for safety. | |
| 178 if (!dest_rect.intersect(SkIRect::MakeWH(image_width, image_height))) | |
| 179 continue; | |
| 180 | |
| 181 // Align the rectangle to avoid artifacts in color space conversion. | |
| 182 dest_rect = AlignRect(dest_rect); | |
| 183 | |
| 184 ConvertYUVToRGB32WithRect(last_image_->planes[0], | 188 ConvertYUVToRGB32WithRect(last_image_->planes[0], |
| 185 last_image_->planes[1], | 189 last_image_->planes[1], |
| 186 last_image_->planes[2], | 190 last_image_->planes[2], |
| 187 data_start, | 191 output_rgb_buf, |
| 188 dest_rect, | 192 dest_rect, |
| 189 last_image_->stride[0], | 193 last_image_->stride[0], |
| 190 last_image_->stride[1], | 194 last_image_->stride[1], |
| 191 stride); | 195 output_stride); |
| 196 |
| 192 output_rects->push_back(dest_rect); | 197 output_rects->push_back(dest_rect); |
| 193 } | 198 } |
| 194 } | 199 } |
| 195 | 200 |
| 196 void DecoderVp8::ScaleAndConvertRects(const RectVector& rects, | 201 void DecoderVp8::ScaleAndConvertRects(const RectVector& input_rects, |
| 197 RectVector* output_rects) { | 202 RectVector* output_rects) { |
| 198 if (!last_image_) | 203 if (!last_image_) |
| 199 return; | 204 return; |
| 200 | 205 |
| 201 uint8* data_start = frame_->data(media::VideoFrame::kRGBPlane); | 206 int input_width = last_image_->d_w; |
| 202 const int stride = frame_->stride(media::VideoFrame::kRGBPlane); | 207 int input_height = last_image_->d_h; |
| 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_); |
| 203 | 215 |
| 204 output_rects->clear(); | 216 output_rects->clear(); |
| 205 output_rects->reserve(rects.size()); | |
| 206 for (size_t i = 0; i < rects.size(); ++i) { | |
| 207 // Round down the image width and height. | |
| 208 int image_width = RoundToTwosMultiple(last_image_->d_w); | |
| 209 int image_height = RoundToTwosMultiple(last_image_->d_h); | |
| 210 | 217 |
| 211 // Clip by the rounded down dimension of the image for safety. | 218 // Clip based on both the output dimensions and Pepper clip rect. |
| 212 SkIRect dest_rect = rects[i]; | 219 SkIRect clip_rect = clip_rect_; |
| 213 if (!dest_rect.intersect(SkIRect::MakeWH(image_width, image_height))) | 220 if (!clip_rect.intersect(SkIRect::MakeWH(output_width, output_height))) |
| 221 return; |
| 222 |
| 223 output_rects->reserve(input_rects.size()); |
| 224 |
| 225 for (size_t i = 0; i < input_rects.size(); ++i) { |
| 226 // Determine the scaled area affected by this rectangle changing. |
| 227 SkIRect output_rect = ScaleRect(input_rects[i], |
| 228 horizontal_scale_ratio_, |
| 229 vertical_scale_ratio_); |
| 230 if (!output_rect.intersect(clip_rect)) |
| 214 continue; | 231 continue; |
| 215 | 232 |
| 216 // Align the rectangle to avoid artifacts in color space conversion. | 233 // The scaler will not to read outside the input dimensions. |
| 217 dest_rect = AlignRect(dest_rect); | 234 media::ScaleYUVToRGB32WithRect(last_image_->planes[0], |
| 218 | 235 last_image_->planes[1], |
| 219 SkIRect scaled_rect = ScaleRect(dest_rect, | 236 last_image_->planes[2], |
| 220 horizontal_scale_ratio_, | 237 output_rgb_buf, |
| 221 vertical_scale_ratio_); | 238 input_width, |
| 222 | 239 input_height, |
| 223 ScaleYUVToRGB32WithRect(last_image_->planes[0], | 240 output_width, output_height, |
| 224 last_image_->planes[1], | 241 output_rect.x(), |
| 225 last_image_->planes[2], | 242 output_rect.y(), |
| 226 data_start, | 243 output_rect.right(), |
| 227 dest_rect, | 244 output_rect.bottom(), |
| 228 scaled_rect, | 245 last_image_->stride[0], |
| 229 last_image_->stride[0], | 246 last_image_->stride[1], |
| 230 last_image_->stride[1], | 247 output_stride); |
| 231 stride); | 248 output_rects->push_back(output_rect); |
| 232 output_rects->push_back(scaled_rect); | |
| 233 } | 249 } |
| 234 } | 250 } |
| 235 | 251 |
| 236 } // namespace remoting | 252 } // namespace remoting |
| OLD | NEW |