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

Side by Side Diff: remoting/codec/video_encoder_vp8.cc

Issue 13983010: Use webrtc::DesktopCapturer for screen capturer implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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
« no previous file with comments | « remoting/codec/video_encoder_vp8.h ('k') | remoting/codec/video_encoder_vp8_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/codec/video_encoder_vp8.h" 5 #include "remoting/codec/video_encoder_vp8.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/sys_info.h" 8 #include "base/sys_info.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "media/base/yuv_convert.h" 10 #include "media/base/yuv_convert.h"
11 #include "media/video/capture/screen/screen_capture_data.h"
12 #include "remoting/base/util.h" 11 #include "remoting/base/util.h"
13 #include "remoting/proto/video.pb.h" 12 #include "remoting/proto/video.pb.h"
13 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
14 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
14 15
15 extern "C" { 16 extern "C" {
16 #define VPX_CODEC_DISABLE_COMPAT 1 17 #define VPX_CODEC_DISABLE_COMPAT 1
17 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" 18 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
18 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" 19 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
19 } 20 }
20 21
21 namespace { 22 namespace {
22 23
23 // Defines the dimension of a macro block. This is used to compute the active 24 // Defines the dimension of a macro block. This is used to compute the active
(...skipping 18 matching lines...) Expand all
42 } 43 }
43 44
44 void VideoEncoderVp8::Destroy() { 45 void VideoEncoderVp8::Destroy() {
45 if (initialized_) { 46 if (initialized_) {
46 vpx_codec_err_t ret = vpx_codec_destroy(codec_.get()); 47 vpx_codec_err_t ret = vpx_codec_destroy(codec_.get());
47 DCHECK_EQ(ret, VPX_CODEC_OK) << "Failed to destroy codec"; 48 DCHECK_EQ(ret, VPX_CODEC_OK) << "Failed to destroy codec";
48 initialized_ = false; 49 initialized_ = false;
49 } 50 }
50 } 51 }
51 52
52 bool VideoEncoderVp8::Init(const SkISize& size) { 53 bool VideoEncoderVp8::Init(const webrtc::DesktopSize& size) {
53 Destroy(); 54 Destroy();
54 codec_.reset(new vpx_codec_ctx_t()); 55 codec_.reset(new vpx_codec_ctx_t());
55 image_.reset(new vpx_image_t()); 56 image_.reset(new vpx_image_t());
56 memset(image_.get(), 0, sizeof(vpx_image_t)); 57 memset(image_.get(), 0, sizeof(vpx_image_t));
57 58
58 image_->fmt = VPX_IMG_FMT_YV12; 59 image_->fmt = VPX_IMG_FMT_YV12;
59 60
60 // libvpx seems to require both to be assigned. 61 // libvpx seems to require both to be assigned.
61 image_->d_w = size.width(); 62 image_->d_w = size.width();
62 image_->w = size.width(); 63 image_->w = size.width();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 if (vpx_codec_control(codec_.get(), VP8E_SET_CPUUSED, 16)) 140 if (vpx_codec_control(codec_.get(), VP8E_SET_CPUUSED, 16))
140 return false; 141 return false;
141 142
142 // Use the lowest level of noise sensitivity so as to spend less time 143 // Use the lowest level of noise sensitivity so as to spend less time
143 // on motion estimation and inter-prediction mode. 144 // on motion estimation and inter-prediction mode.
144 if (vpx_codec_control(codec_.get(), VP8E_SET_NOISE_SENSITIVITY, 0)) 145 if (vpx_codec_control(codec_.get(), VP8E_SET_NOISE_SENSITIVITY, 0))
145 return false; 146 return false;
146 return true; 147 return true;
147 } 148 }
148 149
149 void VideoEncoderVp8::PrepareImage( 150 void VideoEncoderVp8::PrepareImage(const webrtc::DesktopFrame* frame,
150 scoped_refptr<media::ScreenCaptureData> capture_data, 151 SkRegion* updated_region) {
151 SkRegion* updated_region) { 152 if (frame->updated_region().is_empty()) {
152 const SkRegion& region = capture_data->dirty_region();
153 if (region.isEmpty()) {
154 updated_region->setEmpty(); 153 updated_region->setEmpty();
155 return; 154 return;
156 } 155 }
157 156
158 // Align the region to macroblocks, to avoid encoding artefacts. 157 // Align the region to macroblocks, to avoid encoding artefacts.
159 // This also ensures that all rectangles have even-aligned top-left, which 158 // This also ensures that all rectangles have even-aligned top-left, which
160 // is required for ConvertRGBToYUVWithRect() to work. 159 // is required for ConvertRGBToYUVWithRect() to work.
161 std::vector<SkIRect> aligned_rects; 160 std::vector<SkIRect> aligned_rects;
162 for (SkRegion::Iterator r(region); !r.done(); r.next()) { 161 for (webrtc::DesktopRegion::Iterator r(frame->updated_region());
163 aligned_rects.push_back(AlignRect(r.rect())); 162 !r.IsAtEnd(); r.Advance()) {
163 const webrtc::DesktopRect& rect = r.rect();
164 aligned_rects.push_back(AlignRect(
165 SkIRect::MakeLTRB(rect.left(), rect.top(), rect.right(), rect.bottom())));
164 } 166 }
165 DCHECK(!aligned_rects.empty()); 167 DCHECK(!aligned_rects.empty());
166 updated_region->setRects(&aligned_rects[0], aligned_rects.size()); 168 updated_region->setRects(&aligned_rects[0], aligned_rects.size());
167 169
168 // Clip back to the screen dimensions, in case they're not macroblock aligned. 170 // Clip back to the screen dimensions, in case they're not macroblock aligned.
169 // The conversion routines don't require even width & height, so this is safe 171 // The conversion routines don't require even width & height, so this is safe
170 // even if the source dimensions are not even. 172 // even if the source dimensions are not even.
171 updated_region->op(SkIRect::MakeWH(image_->w, image_->h), 173 updated_region->op(SkIRect::MakeWH(image_->w, image_->h),
172 SkRegion::kIntersect_Op); 174 SkRegion::kIntersect_Op);
173 175
174 // Convert the updated region to YUV ready for encoding. 176 // Convert the updated region to YUV ready for encoding.
175 const uint8* rgb_data = capture_data->data(); 177 const uint8* rgb_data = frame->data();
176 const int rgb_stride = capture_data->stride(); 178 const int rgb_stride = frame->stride();
177 const int y_stride = image_->stride[0]; 179 const int y_stride = image_->stride[0];
178 DCHECK_EQ(image_->stride[1], image_->stride[2]); 180 DCHECK_EQ(image_->stride[1], image_->stride[2]);
179 const int uv_stride = image_->stride[1]; 181 const int uv_stride = image_->stride[1];
180 uint8* y_data = image_->planes[0]; 182 uint8* y_data = image_->planes[0];
181 uint8* u_data = image_->planes[1]; 183 uint8* u_data = image_->planes[1];
182 uint8* v_data = image_->planes[2]; 184 uint8* v_data = image_->planes[2];
183 for (SkRegion::Iterator r(*updated_region); !r.done(); r.next()) { 185 for (SkRegion::Iterator r(*updated_region); !r.done(); r.next()) {
184 const SkIRect& rect = r.rect(); 186 const SkIRect& rect = r.rect();
185 ConvertRGB32ToYUVWithRect( 187 ConvertRGB32ToYUVWithRect(
186 rgb_data, y_data, u_data, v_data, 188 rgb_data, y_data, u_data, v_data,
(...skipping 19 matching lines...) Expand all
206 uint8* map = active_map_.get() + top * active_map_width_; 208 uint8* map = active_map_.get() + top * active_map_width_;
207 for (int y = top; y <= bottom; ++y) { 209 for (int y = top; y <= bottom; ++y) {
208 for (int x = left; x <= right; ++x) 210 for (int x = left; x <= right; ++x)
209 map[x] = 1; 211 map[x] = 1;
210 map += active_map_width_; 212 map += active_map_width_;
211 } 213 }
212 } 214 }
213 } 215 }
214 216
215 void VideoEncoderVp8::Encode( 217 void VideoEncoderVp8::Encode(
216 scoped_refptr<media::ScreenCaptureData> capture_data, 218 const webrtc::DesktopFrame* frame,
217 bool key_frame,
218 const DataAvailableCallback& data_available_callback) { 219 const DataAvailableCallback& data_available_callback) {
219 DCHECK_LE(32, capture_data->size().width()); 220 DCHECK_LE(32, frame->size().width());
220 DCHECK_LE(32, capture_data->size().height()); 221 DCHECK_LE(32, frame->size().height());
221 222
222 base::Time encode_start_time = base::Time::Now(); 223 base::Time encode_start_time = base::Time::Now();
223 224
224 if (!initialized_ || 225 if (!initialized_ ||
225 (capture_data->size() != SkISize::Make(image_->w, image_->h))) { 226 !frame->size().equals(webrtc::DesktopSize(image_->w, image_->h))) {
226 bool ret = Init(capture_data->size()); 227 bool ret = Init(frame->size());
227 // TODO(hclam): Handle error better. 228 // TODO(hclam): Handle error better.
228 CHECK(ret) << "Initialization of encoder failed"; 229 CHECK(ret) << "Initialization of encoder failed";
229 initialized_ = ret; 230 initialized_ = ret;
230 } 231 }
231 232
232 // Convert the updated capture data ready for encode. 233 // Convert the updated capture data ready for encode.
233 SkRegion updated_region; 234 SkRegion updated_region;
234 PrepareImage(capture_data, &updated_region); 235 PrepareImage(frame, &updated_region);
235 236
236 // Update active map based on updated region. 237 // Update active map based on updated region.
237 PrepareActiveMap(updated_region); 238 PrepareActiveMap(updated_region);
238 239
239 // Apply active map to the encoder. 240 // Apply active map to the encoder.
240 vpx_active_map_t act_map; 241 vpx_active_map_t act_map;
241 act_map.rows = active_map_height_; 242 act_map.rows = active_map_height_;
242 act_map.cols = active_map_width_; 243 act_map.cols = active_map_width_;
243 act_map.active_map = active_map_.get(); 244 act_map.active_map = active_map_.get();
244 if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { 245 if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 break; 280 break;
280 default: 281 default:
281 break; 282 break;
282 } 283 }
283 } 284 }
284 285
285 // Construct the VideoPacket message. 286 // Construct the VideoPacket message.
286 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); 287 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
287 packet->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET | 288 packet->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET |
288 VideoPacket::LAST_PARTITION); 289 VideoPacket::LAST_PARTITION);
289 packet->mutable_format()->set_screen_width(capture_data->size().width()); 290 packet->mutable_format()->set_screen_width(frame->size().width());
290 packet->mutable_format()->set_screen_height(capture_data->size().height()); 291 packet->mutable_format()->set_screen_height(frame->size().height());
291 packet->set_capture_time_ms(capture_data->capture_time_ms()); 292 packet->set_capture_time_ms(frame->capture_time_ms());
292 packet->set_encode_time_ms( 293 packet->set_encode_time_ms(
293 (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp()); 294 (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
294 packet->set_client_sequence_number(capture_data->client_sequence_number()); 295 if (!frame->dpi().is_zero()) {
295 SkIPoint dpi(capture_data->dpi()); 296 packet->mutable_format()->set_x_dpi(frame->dpi().x());
296 if (dpi.x()) 297 packet->mutable_format()->set_y_dpi(frame->dpi().y());
297 packet->mutable_format()->set_x_dpi(dpi.x()); 298 }
298 if (dpi.y())
299 packet->mutable_format()->set_y_dpi(dpi.y());
300 for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) { 299 for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) {
301 Rect* rect = packet->add_dirty_rects(); 300 Rect* rect = packet->add_dirty_rects();
302 rect->set_x(r.rect().x()); 301 rect->set_x(r.rect().x());
303 rect->set_y(r.rect().y()); 302 rect->set_y(r.rect().y());
304 rect->set_width(r.rect().width()); 303 rect->set_width(r.rect().width());
305 rect->set_height(r.rect().height()); 304 rect->set_height(r.rect().height());
306 } 305 }
307 306
308 data_available_callback.Run(packet.Pass()); 307 data_available_callback.Run(packet.Pass());
309 } 308 }
310 309
311 } // namespace remoting 310 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/codec/video_encoder_vp8.h ('k') | remoting/codec/video_encoder_vp8_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698