Chromium Code Reviews| 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 |