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

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

Issue 1092813003: Enable Cyclic Refresh for VP9. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@chromium_vp9_6_1
Patch Set: Created 5 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
« no previous file with comments | « remoting/codec/video_encoder_vpx.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_vpx.h" 5 #include "remoting/codec/video_encoder_vpx.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/sys_info.h" 10 #include "base/sys_info.h"
(...skipping 21 matching lines...) Expand all
32 const int kBytesPerRgbPixel = 4; 32 const int kBytesPerRgbPixel = 4;
33 33
34 // Defines the dimension of a macro block. This is used to compute the active 34 // Defines the dimension of a macro block. This is used to compute the active
35 // map for the encoder. 35 // map for the encoder.
36 const int kMacroBlockSize = 16; 36 const int kMacroBlockSize = 16;
37 37
38 // Magic encoder profile numbers for I420 and I444 input formats. 38 // Magic encoder profile numbers for I420 and I444 input formats.
39 const int kVp9I420ProfileNumber = 0; 39 const int kVp9I420ProfileNumber = 0;
40 const int kVp9I444ProfileNumber = 1; 40 const int kVp9I444ProfileNumber = 1;
41 41
42 // Magic encoder constants for adaptive quantization strategy.
43 const int kVp9AqModeNone = 0;
44 const int kVp9AqModeCyclicRefresh = 3;
45
42 void SetCommonCodecParameters(vpx_codec_enc_cfg_t* config, 46 void SetCommonCodecParameters(vpx_codec_enc_cfg_t* config,
43 const webrtc::DesktopSize& size) { 47 const webrtc::DesktopSize& size) {
44 // Use millisecond granularity time base. 48 // Use millisecond granularity time base.
45 config->g_timebase.num = 1; 49 config->g_timebase.num = 1;
46 config->g_timebase.den = 1000; 50 config->g_timebase.den = 1000;
47 51
48 config->g_w = size.width(); 52 config->g_w = size.width();
49 config->g_h = size.height(); 53 config->g_h = size.height();
50 config->g_pass = VPX_RC_ONE_PASS; 54 config->g_pass = VPX_RC_ONE_PASS;
51 55
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 134
131 // Use the lowest level of noise sensitivity so as to spend less time 135 // Use the lowest level of noise sensitivity so as to spend less time
132 // on motion estimation and inter-prediction mode. 136 // on motion estimation and inter-prediction mode.
133 ret = vpx_codec_control(codec, VP9E_SET_NOISE_SENSITIVITY, 0); 137 ret = vpx_codec_control(codec, VP9E_SET_NOISE_SENSITIVITY, 0);
134 DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to set noise sensitivity"; 138 DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to set noise sensitivity";
135 139
136 // Configure the codec to tune it for screen media. 140 // Configure the codec to tune it for screen media.
137 ret = vpx_codec_control( 141 ret = vpx_codec_control(
138 codec, VP9E_SET_TUNE_CONTENT, VP9E_CONTENT_SCREEN); 142 codec, VP9E_SET_TUNE_CONTENT, VP9E_CONTENT_SCREEN);
139 DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to set screen content mode"; 143 DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to set screen content mode";
144
145 // Set cyclic refresh (aka "top-off") only for lossy encoding.
146 int aq_mode = lossless_encode ? kVp9AqModeNone : kVp9AqModeCyclicRefresh;
147 ret = vpx_codec_control(codec, VP9E_SET_AQ_MODE, aq_mode);
148 DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to set aq mode";
140 } 149 }
141 150
142 void FreeImageIfMismatched(bool use_i444, 151 void FreeImageIfMismatched(bool use_i444,
143 const webrtc::DesktopSize& size, 152 const webrtc::DesktopSize& size,
144 scoped_ptr<vpx_image_t>* out_image, 153 scoped_ptr<vpx_image_t>* out_image,
145 scoped_ptr<uint8[]>* out_image_buffer) { 154 scoped_ptr<uint8[]>* out_image_buffer) {
146 if (*out_image) { 155 if (*out_image) {
147 const vpx_img_fmt_t desired_fmt = 156 const vpx_img_fmt_t desired_fmt =
148 use_i444 ? VPX_IMG_FMT_I444 : VPX_IMG_FMT_I420; 157 use_i444 ? VPX_IMG_FMT_I444 : VPX_IMG_FMT_I420;
149 if (!size.equals(webrtc::DesktopSize((*out_image)->w, (*out_image)->h)) || 158 if (!size.equals(webrtc::DesktopSize((*out_image)->w, (*out_image)->h)) ||
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 (image_ && 275 (image_ &&
267 !frame.size().equals(webrtc::DesktopSize(image_->w, image_->h)))) { 276 !frame.size().equals(webrtc::DesktopSize(image_->w, image_->h)))) {
268 Configure(frame.size()); 277 Configure(frame.size());
269 } 278 }
270 279
271 // Convert the updated capture data ready for encode. 280 // Convert the updated capture data ready for encode.
272 webrtc::DesktopRegion updated_region; 281 webrtc::DesktopRegion updated_region;
273 PrepareImage(frame, &updated_region); 282 PrepareImage(frame, &updated_region);
274 283
275 // Update active map based on updated region. 284 // Update active map based on updated region.
276 PrepareActiveMap(updated_region); 285 SetActiveMapFromRegion(updated_region);
277 286
278 // Apply active map to the encoder. 287 // Apply active map to the encoder.
279 vpx_active_map_t act_map; 288 vpx_active_map_t act_map;
280 act_map.rows = active_map_height_; 289 act_map.rows = active_map_height_;
281 act_map.cols = active_map_width_; 290 act_map.cols = active_map_width_;
282 act_map.active_map = active_map_.get(); 291 act_map.active_map = active_map_.get();
283 if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { 292 if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) {
284 LOG(ERROR) << "Unable to apply active map"; 293 LOG(ERROR) << "Unable to apply active map";
285 } 294 }
286 295
287 // Do the actual encoding. 296 // Do the actual encoding.
288 int timestamp = (encode_start_time - timestamp_base_).InMilliseconds(); 297 int timestamp = (encode_start_time - timestamp_base_).InMilliseconds();
289 vpx_codec_err_t ret = vpx_codec_encode( 298 vpx_codec_err_t ret = vpx_codec_encode(
290 codec_.get(), image_.get(), timestamp, 1, 0, VPX_DL_REALTIME); 299 codec_.get(), image_.get(), timestamp, 1, 0, VPX_DL_REALTIME);
291 DCHECK_EQ(ret, VPX_CODEC_OK) 300 DCHECK_EQ(ret, VPX_CODEC_OK)
292 << "Encoding error: " << vpx_codec_err_to_string(ret) << "\n" 301 << "Encoding error: " << vpx_codec_err_to_string(ret) << "\n"
293 << "Details: " << vpx_codec_error(codec_.get()) << "\n" 302 << "Details: " << vpx_codec_error(codec_.get()) << "\n"
294 << vpx_codec_error_detail(codec_.get()); 303 << vpx_codec_error_detail(codec_.get());
295 304
305 if (use_vp9_ && !lossless_encode_) {
306 ret = vpx_codec_control(codec_.get(), VP9E_GET_ACTIVEMAP, &act_map);
307 DCHECK_EQ(ret, VPX_CODEC_OK)
308 << "Failed to fetch active map: "
309 << vpx_codec_err_to_string(ret) << "\n";
310 UpdateRegionFromActiveMap(&updated_region);
311 }
312
296 // Read the encoded data. 313 // Read the encoded data.
297 vpx_codec_iter_t iter = NULL; 314 vpx_codec_iter_t iter = NULL;
298 bool got_data = false; 315 bool got_data = false;
299 316
300 // TODO(hclam): Make sure we get exactly one frame from the packet. 317 // TODO(hclam): Make sure we get exactly one frame from the packet.
301 // TODO(hclam): We should provide the output buffer to avoid one copy. 318 // TODO(hclam): We should provide the output buffer to avoid one copy.
302 scoped_ptr<VideoPacket> packet( 319 scoped_ptr<VideoPacket> packet(
303 helper_.CreateVideoPacketWithUpdatedRegion(frame, updated_region)); 320 helper_.CreateVideoPacketWithUpdatedRegion(frame, updated_region));
304 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); 321 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
305 322
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 v_data + uv_offset, uv_stride, 495 v_data + uv_offset, uv_stride,
479 rect.width(), rect.height()); 496 rect.width(), rect.height());
480 } 497 }
481 break; 498 break;
482 default: 499 default:
483 NOTREACHED(); 500 NOTREACHED();
484 break; 501 break;
485 } 502 }
486 } 503 }
487 504
488 void VideoEncoderVpx::PrepareActiveMap( 505 void VideoEncoderVpx::SetActiveMapFromRegion(
489 const webrtc::DesktopRegion& updated_region) { 506 const webrtc::DesktopRegion& updated_region) {
490 // Clear active map first. 507 // Clear active map first.
491 memset(active_map_.get(), 0, active_map_width_ * active_map_height_); 508 memset(active_map_.get(), 0, active_map_width_ * active_map_height_);
492 509
493 // Mark updated areas active. 510 // Mark updated areas active.
494 for (webrtc::DesktopRegion::Iterator r(updated_region); !r.IsAtEnd(); 511 for (webrtc::DesktopRegion::Iterator r(updated_region); !r.IsAtEnd();
495 r.Advance()) { 512 r.Advance()) {
496 const webrtc::DesktopRect& rect = r.rect(); 513 const webrtc::DesktopRect& rect = r.rect();
497 int left = rect.left() / kMacroBlockSize; 514 int left = rect.left() / kMacroBlockSize;
498 int right = (rect.right() - 1) / kMacroBlockSize; 515 int right = (rect.right() - 1) / kMacroBlockSize;
499 int top = rect.top() / kMacroBlockSize; 516 int top = rect.top() / kMacroBlockSize;
500 int bottom = (rect.bottom() - 1) / kMacroBlockSize; 517 int bottom = (rect.bottom() - 1) / kMacroBlockSize;
501 DCHECK_LT(right, active_map_width_); 518 DCHECK_LT(right, active_map_width_);
502 DCHECK_LT(bottom, active_map_height_); 519 DCHECK_LT(bottom, active_map_height_);
503 520
504 uint8* map = active_map_.get() + top * active_map_width_; 521 uint8* map = active_map_.get() + top * active_map_width_;
505 for (int y = top; y <= bottom; ++y) { 522 for (int y = top; y <= bottom; ++y) {
506 for (int x = left; x <= right; ++x) 523 for (int x = left; x <= right; ++x)
507 map[x] = 1; 524 map[x] = 1;
508 map += active_map_width_; 525 map += active_map_width_;
509 } 526 }
510 } 527 }
511 } 528 }
512 529
530 void VideoEncoderVpx::UpdateRegionFromActiveMap(
531 webrtc::DesktopRegion* updated_region) {
532 const uint8* map = active_map_.get();
533 // Mark active areas updated.
Wez 2015/05/04 23:57:43 nit: This comment still seems redundant!
534 for (int y = 0; y < active_map_height_; ++y) {
535 for (int x0 = 0; x0 < active_map_width_;) {
536 int x1 = x0;
537 for (; x1 < active_map_width_; ++x1) {
538 if (map[y * active_map_width_ + x1] == 0)
539 break;
540 }
541 if (x1 > x0) {
542 updated_region->AddRect(webrtc::DesktopRect::MakeLTRB(
543 kMacroBlockSize * x0, kMacroBlockSize * y, kMacroBlockSize * x1,
544 kMacroBlockSize * (y + 1)));
545 }
546 x0 = x1 + 1;
547 }
548 }
549 updated_region->IntersectWith(
550 webrtc::DesktopRect::MakeWH(image_->w, image_->h));
551 }
552
513 } // namespace remoting 553 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/codec/video_encoder_vpx.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698