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

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: q Created 7 years, 8 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/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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(
150 scoped_refptr<media::ScreenCaptureData> capture_data, 151 webrtc::DesktopFrame* frame,
151 SkRegion* updated_region) { 152 SkRegion* updated_region) {
152 const SkRegion& region = capture_data->dirty_region(); 153 if (frame->updated_region().is_empty()) {
153 if (region.isEmpty()) {
154 updated_region->setEmpty(); 154 updated_region->setEmpty();
155 return; 155 return;
156 } 156 }
157 157
158 // Align the region to macroblocks, to avoid encoding artefacts. 158 // Align the region to macroblocks, to avoid encoding artefacts.
159 // This also ensures that all rectangles have even-aligned top-left, which 159 // This also ensures that all rectangles have even-aligned top-left, which
160 // is required for ConvertRGBToYUVWithRect() to work. 160 // is required for ConvertRGBToYUVWithRect() to work.
161 std::vector<SkIRect> aligned_rects; 161 std::vector<SkIRect> aligned_rects;
162 for (SkRegion::Iterator r(region); !r.done(); r.next()) { 162 for (webrtc::DesktopRegion::Iterator r(frame->updated_region());
163 aligned_rects.push_back(AlignRect(r.rect())); 163 !r.IsAtEnd(); r.Advance()) {
164 const webrtc::DesktopRect& rect = r.rect();
165 aligned_rects.push_back(AlignRect(
166 SkIRect::MakeLTRB(rect.left(), rect.top(), rect.right(), rect.bottom())));
164 } 167 }
165 DCHECK(!aligned_rects.empty()); 168 DCHECK(!aligned_rects.empty());
166 updated_region->setRects(&aligned_rects[0], aligned_rects.size()); 169 updated_region->setRects(&aligned_rects[0], aligned_rects.size());
167 170
168 // Clip back to the screen dimensions, in case they're not macroblock aligned. 171 // 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 172 // The conversion routines don't require even width & height, so this is safe
170 // even if the source dimensions are not even. 173 // even if the source dimensions are not even.
171 updated_region->op(SkIRect::MakeWH(image_->w, image_->h), 174 updated_region->op(SkIRect::MakeWH(image_->w, image_->h),
172 SkRegion::kIntersect_Op); 175 SkRegion::kIntersect_Op);
173 176
174 // Convert the updated region to YUV ready for encoding. 177 // Convert the updated region to YUV ready for encoding.
175 const uint8* rgb_data = capture_data->data(); 178 const uint8* rgb_data = frame->data();
176 const int rgb_stride = capture_data->stride(); 179 const int rgb_stride = frame->stride();
177 const int y_stride = image_->stride[0]; 180 const int y_stride = image_->stride[0];
178 DCHECK_EQ(image_->stride[1], image_->stride[2]); 181 DCHECK_EQ(image_->stride[1], image_->stride[2]);
179 const int uv_stride = image_->stride[1]; 182 const int uv_stride = image_->stride[1];
180 uint8* y_data = image_->planes[0]; 183 uint8* y_data = image_->planes[0];
181 uint8* u_data = image_->planes[1]; 184 uint8* u_data = image_->planes[1];
182 uint8* v_data = image_->planes[2]; 185 uint8* v_data = image_->planes[2];
183 for (SkRegion::Iterator r(*updated_region); !r.done(); r.next()) { 186 for (SkRegion::Iterator r(*updated_region); !r.done(); r.next()) {
184 const SkIRect& rect = r.rect(); 187 const SkIRect& rect = r.rect();
185 ConvertRGB32ToYUVWithRect( 188 ConvertRGB32ToYUVWithRect(
186 rgb_data, y_data, u_data, v_data, 189 rgb_data, y_data, u_data, v_data,
(...skipping 19 matching lines...) Expand all
206 uint8* map = active_map_.get() + top * active_map_width_; 209 uint8* map = active_map_.get() + top * active_map_width_;
207 for (int y = top; y <= bottom; ++y) { 210 for (int y = top; y <= bottom; ++y) {
208 for (int x = left; x <= right; ++x) 211 for (int x = left; x <= right; ++x)
209 map[x] = 1; 212 map[x] = 1;
210 map += active_map_width_; 213 map += active_map_width_;
211 } 214 }
212 } 215 }
213 } 216 }
214 217
215 void VideoEncoderVp8::Encode( 218 void VideoEncoderVp8::Encode(
216 scoped_refptr<media::ScreenCaptureData> capture_data, 219 webrtc::DesktopFrame* frame,
217 bool key_frame,
218 const DataAvailableCallback& data_available_callback) { 220 const DataAvailableCallback& data_available_callback) {
219 DCHECK_LE(32, capture_data->size().width()); 221 DCHECK_LE(32, frame->size().width());
alexeypa (please no reviews) 2013/04/26 21:33:58 nit: it is not immediately obvious where 32 came f
Sergey Ulanov 2013/05/07 22:25:50 Not related to this CL.
220 DCHECK_LE(32, capture_data->size().height()); 222 DCHECK_LE(32, frame->size().height());
221 223
222 base::Time encode_start_time = base::Time::Now(); 224 base::Time encode_start_time = base::Time::Now();
223 225
224 if (!initialized_ || 226 if (!initialized_ ||
225 (capture_data->size() != SkISize::Make(image_->w, image_->h))) { 227 !frame->size().equals(webrtc::DesktopSize(image_->w, image_->h))) {
226 bool ret = Init(capture_data->size()); 228 bool ret = Init(frame->size());
227 // TODO(hclam): Handle error better. 229 // TODO(hclam): Handle error better.
228 CHECK(ret) << "Initialization of encoder failed"; 230 CHECK(ret) << "Initialization of encoder failed";
229 initialized_ = ret; 231 initialized_ = ret;
230 } 232 }
231 233
234 SkRegion updated_region;
alexeypa (please no reviews) 2013/04/26 21:33:58 nit: I think it is better to keep it under the com
Sergey Ulanov 2013/05/07 22:25:50 Done.
235
232 // Convert the updated capture data ready for encode. 236 // Convert the updated capture data ready for encode.
233 SkRegion updated_region; 237 PrepareImage(frame, &updated_region);
234 PrepareImage(capture_data, &updated_region);
235 238
236 // Update active map based on updated region. 239 // Update active map based on updated region.
237 PrepareActiveMap(updated_region); 240 PrepareActiveMap(updated_region);
238 241
239 // Apply active map to the encoder. 242 // Apply active map to the encoder.
240 vpx_active_map_t act_map; 243 vpx_active_map_t act_map;
241 act_map.rows = active_map_height_; 244 act_map.rows = active_map_height_;
242 act_map.cols = active_map_width_; 245 act_map.cols = active_map_width_;
243 act_map.active_map = active_map_.get(); 246 act_map.active_map = active_map_.get();
244 if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { 247 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; 282 break;
280 default: 283 default:
281 break; 284 break;
282 } 285 }
283 } 286 }
284 287
285 // Construct the VideoPacket message. 288 // Construct the VideoPacket message.
286 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); 289 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
287 packet->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET | 290 packet->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET |
288 VideoPacket::LAST_PARTITION); 291 VideoPacket::LAST_PARTITION);
289 packet->mutable_format()->set_screen_width(capture_data->size().width()); 292 packet->mutable_format()->set_screen_width(frame->size().width());
290 packet->mutable_format()->set_screen_height(capture_data->size().height()); 293 packet->mutable_format()->set_screen_height(frame->size().height());
291 packet->set_capture_time_ms(capture_data->capture_time_ms()); 294 packet->set_capture_time_ms(frame->capture_time_ms());
292 packet->set_encode_time_ms( 295 packet->set_encode_time_ms(
293 (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp()); 296 (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
294 packet->set_client_sequence_number(capture_data->client_sequence_number()); 297 if (!frame->dpi().is_zero()) {
295 SkIPoint dpi(capture_data->dpi()); 298 packet->mutable_format()->set_x_dpi(frame->dpi().x());
296 if (dpi.x()) 299 packet->mutable_format()->set_y_dpi(frame->dpi().y());
297 packet->mutable_format()->set_x_dpi(dpi.x()); 300 }
298 if (dpi.y())
299 packet->mutable_format()->set_y_dpi(dpi.y());
300 for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) { 301 for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) {
301 Rect* rect = packet->add_dirty_rects(); 302 Rect* rect = packet->add_dirty_rects();
302 rect->set_x(r.rect().x()); 303 rect->set_x(r.rect().x());
303 rect->set_y(r.rect().y()); 304 rect->set_y(r.rect().y());
304 rect->set_width(r.rect().width()); 305 rect->set_width(r.rect().width());
305 rect->set_height(r.rect().height()); 306 rect->set_height(r.rect().height());
306 } 307 }
307 308
308 data_available_callback.Run(packet.Pass()); 309 data_available_callback.Run(packet.Pass());
309 } 310 }
310 311
311 } // namespace remoting 312 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698