Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: remoting/base/decoder_vp8.cc

Issue 9331003: Improving the decoder pipeline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_),
Wez 2012/02/17 23:42:17 This isn't strictly correct, I don't think. It'll
alexeypa (please no reviews) 2012/02/21 23:00:44 Yes, but leaving such pixels invalidated will lead
Wez 2012/02/23 00:11:09 Unless the view is scaled because of page zoom. ;)
alexeypa (please no reviews) 2012/02/23 17:10:33 Currently we scale it back to fit the screen even
150 SkRegion::kDifference_Op);
188 } 151 }
189 152
190 } // namespace remoting 153 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698