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

Side by Side Diff: media/cast/sender/vp8_encoder.cc

Issue 2133223003: Revert of Refactoring: Merge VideoSenderConfig and AudioSenderConfig. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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 | « media/cast/sender/vp8_encoder.h ('k') | media/cast/sender/vp8_quantizer_parser_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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "media/cast/sender/vp8_encoder.h" 5 #include "media/cast/sender/vp8_encoder.h"
6 6
7 #include "base/debug/crash_logging.h" 7 #include "base/debug/crash_logging.h"
8 #include "base/debug/dump_without_crashing.h" 8 #include "base/debug/dump_without_crashing.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 bool HasSufficientFeedback( 57 bool HasSufficientFeedback(
58 const FeedbackSignalAccumulator<base::TimeDelta>& accumulator) { 58 const FeedbackSignalAccumulator<base::TimeDelta>& accumulator) {
59 const base::TimeDelta amount_of_history = 59 const base::TimeDelta amount_of_history =
60 accumulator.update_time() - accumulator.reset_time(); 60 accumulator.update_time() - accumulator.reset_time();
61 return amount_of_history.InMicroseconds() >= 250000; // 0.25 second. 61 return amount_of_history.InMicroseconds() >= 250000; // 0.25 second.
62 } 62 }
63 63
64 } // namespace 64 } // namespace
65 65
66 Vp8Encoder::Vp8Encoder(const FrameSenderConfig& video_config) 66 Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config)
67 : cast_config_(video_config), 67 : cast_config_(video_config),
68 target_encoder_utilization_( 68 target_encoder_utilization_(
69 video_config.video_codec_params.number_of_encode_threads > 2 69 video_config.number_of_encode_threads > 2
70 ? kHiTargetEncoderUtilization 70 ? kHiTargetEncoderUtilization
71 : (video_config.video_codec_params.number_of_encode_threads > 1 71 : (video_config.number_of_encode_threads > 1
72 ? kMidTargetEncoderUtilization 72 ? kMidTargetEncoderUtilization
73 : kLoTargetEncoderUtilization)), 73 : kLoTargetEncoderUtilization)),
74 key_frame_requested_(true), 74 key_frame_requested_(true),
75 bitrate_kbit_(cast_config_.start_bitrate / 1000), 75 bitrate_kbit_(cast_config_.start_bitrate / 1000),
76 next_frame_id_(FrameId::first()), 76 next_frame_id_(FrameId::first()),
77 has_seen_zero_length_encoded_frame_(false), 77 has_seen_zero_length_encoded_frame_(false),
78 encoding_speed_acc_( 78 encoding_speed_acc_(
79 base::TimeDelta::FromMicroseconds(kEncodingSpeedAccHalfLife)), 79 base::TimeDelta::FromMicroseconds(kEncodingSpeedAccHalfLife)),
80 encoding_speed_(kHighestEncodingSpeed) { 80 encoding_speed_(kHighestEncodingSpeed) {
81 config_.g_timebase.den = 0; // Not initialized. 81 config_.g_timebase.den = 0; // Not initialized.
82 DCHECK_LE(cast_config_.video_codec_params.min_qp, 82 DCHECK_LE(cast_config_.min_qp, cast_config_.max_cpu_saver_qp);
83 cast_config_.video_codec_params.max_cpu_saver_qp); 83 DCHECK_LE(cast_config_.max_cpu_saver_qp, cast_config_.max_qp);
84 DCHECK_LE(cast_config_.video_codec_params.max_cpu_saver_qp,
85 cast_config_.video_codec_params.max_qp);
86 84
87 thread_checker_.DetachFromThread(); 85 thread_checker_.DetachFromThread();
88 } 86 }
89 87
90 Vp8Encoder::~Vp8Encoder() { 88 Vp8Encoder::~Vp8Encoder() {
91 DCHECK(thread_checker_.CalledOnValidThread()); 89 DCHECK(thread_checker_.CalledOnValidThread());
92 if (is_initialized()) 90 if (is_initialized())
93 vpx_codec_destroy(&encoder_); 91 vpx_codec_destroy(&encoder_);
94 } 92 }
95 93
96 void Vp8Encoder::Initialize() { 94 void Vp8Encoder::Initialize() {
97 DCHECK(thread_checker_.CalledOnValidThread()); 95 DCHECK(thread_checker_.CalledOnValidThread());
98 DCHECK(!is_initialized()); 96 DCHECK(!is_initialized());
99 // The encoder will be created/configured when the first frame encode is 97 // The encoder will be created/configured when the first frame encode is
100 // requested. 98 // requested.
101 } 99 }
102 100
103 void Vp8Encoder::ConfigureForNewFrameSize(const gfx::Size& frame_size) { 101 void Vp8Encoder::ConfigureForNewFrameSize(const gfx::Size& frame_size) {
104 if (is_initialized()) { 102 if (is_initialized()) {
105 // Workaround for VP8 bug: If the new size is strictly less-than-or-equal to 103 // Workaround for VP8 bug: If the new size is strictly less-than-or-equal to
106 // the old size, in terms of area, the existing encoder instance can 104 // the old size, in terms of area, the existing encoder instance can
107 // continue. Otherwise, completely tear-down and re-create a new encoder to 105 // continue. Otherwise, completely tear-down and re-create a new encoder to
108 // avoid a shutdown crash. 106 // avoid a shutdown crash.
109 if (frame_size.GetArea() <= gfx::Size(config_.g_w, config_.g_h).GetArea()) { 107 if (frame_size.GetArea() <= gfx::Size(config_.g_w, config_.g_h).GetArea()) {
110 DVLOG(1) << "Continuing to use existing encoder at smaller frame size: " 108 DVLOG(1) << "Continuing to use existing encoder at smaller frame size: "
111 << gfx::Size(config_.g_w, config_.g_h).ToString() << " --> " 109 << gfx::Size(config_.g_w, config_.g_h).ToString() << " --> "
112 << frame_size.ToString(); 110 << frame_size.ToString();
113 config_.g_w = frame_size.width(); 111 config_.g_w = frame_size.width();
114 config_.g_h = frame_size.height(); 112 config_.g_h = frame_size.height();
115 config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp; 113 config_.rc_min_quantizer = cast_config_.min_qp;
116 if (vpx_codec_enc_config_set(&encoder_, &config_) == VPX_CODEC_OK) 114 if (vpx_codec_enc_config_set(&encoder_, &config_) == VPX_CODEC_OK)
117 return; 115 return;
118 DVLOG(1) << "libvpx rejected the attempt to use a smaller frame size in " 116 DVLOG(1) << "libvpx rejected the attempt to use a smaller frame size in "
119 "the current instance."; 117 "the current instance.";
120 } 118 }
121 119
122 DVLOG(1) << "Destroying/Re-Creating encoder for larger frame size: " 120 DVLOG(1) << "Destroying/Re-Creating encoder for larger frame size: "
123 << gfx::Size(config_.g_w, config_.g_h).ToString() << " --> " 121 << gfx::Size(config_.g_w, config_.g_h).ToString() << " --> "
124 << frame_size.ToString(); 122 << frame_size.ToString();
125 vpx_codec_destroy(&encoder_); 123 vpx_codec_destroy(&encoder_);
126 } else { 124 } else {
127 DVLOG(1) << "Creating encoder for the first frame; size: " 125 DVLOG(1) << "Creating encoder for the first frame; size: "
128 << frame_size.ToString(); 126 << frame_size.ToString();
129 } 127 }
130 128
131 // Populate encoder configuration with default values. 129 // Populate encoder configuration with default values.
132 CHECK_EQ(vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0), 130 CHECK_EQ(vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0),
133 VPX_CODEC_OK); 131 VPX_CODEC_OK);
134 132
135 config_.g_threads = cast_config_.video_codec_params.number_of_encode_threads; 133 config_.g_threads = cast_config_.number_of_encode_threads;
136 config_.g_w = frame_size.width(); 134 config_.g_w = frame_size.width();
137 config_.g_h = frame_size.height(); 135 config_.g_h = frame_size.height();
138 // Set the timebase to match that of base::TimeDelta. 136 // Set the timebase to match that of base::TimeDelta.
139 config_.g_timebase.num = 1; 137 config_.g_timebase.num = 1;
140 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond; 138 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
141 139
142 // |g_pass| and |g_lag_in_frames| must be "one pass" and zero, respectively, 140 // |g_pass| and |g_lag_in_frames| must be "one pass" and zero, respectively,
143 // in order for VP8 to support changing frame sizes during encoding: 141 // in order for VP8 to support changing frame sizes during encoding:
144 config_.g_pass = VPX_RC_ONE_PASS; 142 config_.g_pass = VPX_RC_ONE_PASS;
145 config_.g_lag_in_frames = 0; // Immediate data output for each frame. 143 config_.g_lag_in_frames = 0; // Immediate data output for each frame.
146 144
147 // Rate control settings. 145 // Rate control settings.
148 config_.rc_dropframe_thresh = 0; // The encoder may not drop any frames. 146 config_.rc_dropframe_thresh = 0; // The encoder may not drop any frames.
149 config_.rc_resize_allowed = 0; // TODO(miu): Why not? Investigate this. 147 config_.rc_resize_allowed = 0; // TODO(miu): Why not? Investigate this.
150 config_.rc_end_usage = VPX_CBR; 148 config_.rc_end_usage = VPX_CBR;
151 config_.rc_target_bitrate = bitrate_kbit_; 149 config_.rc_target_bitrate = bitrate_kbit_;
152 config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp; 150 config_.rc_min_quantizer = cast_config_.min_qp;
153 config_.rc_max_quantizer = cast_config_.video_codec_params.max_qp; 151 config_.rc_max_quantizer = cast_config_.max_qp;
154 // TODO(miu): Revisit these now that the encoder is being successfully 152 // TODO(miu): Revisit these now that the encoder is being successfully
155 // micro-managed. 153 // micro-managed.
156 config_.rc_undershoot_pct = 100; 154 config_.rc_undershoot_pct = 100;
157 config_.rc_overshoot_pct = 15; 155 config_.rc_overshoot_pct = 15;
158 // TODO(miu): Document why these rc_buf_*_sz values were chosen and/or 156 // TODO(miu): Document why these rc_buf_*_sz values were chosen and/or
159 // research for better values. Should they be computed from the target 157 // research for better values. Should they be computed from the target
160 // playout delay? 158 // playout delay?
161 config_.rc_buf_initial_sz = 500; 159 config_.rc_buf_initial_sz = 500;
162 config_.rc_buf_optimal_sz = 600; 160 config_.rc_buf_optimal_sz = 600;
163 config_.rc_buf_sz = 1000; 161 config_.rc_buf_sz = 1000;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 key_frame_requested_ = false; 344 key_frame_requested_ = false;
347 } 345 }
348 if (encoded_frame->dependency == EncodedFrame::KEY) { 346 if (encoded_frame->dependency == EncodedFrame::KEY) {
349 encoding_speed_acc_.Reset(kHighestEncodingSpeed, video_frame->timestamp()); 347 encoding_speed_acc_.Reset(kHighestEncodingSpeed, video_frame->timestamp());
350 } else { 348 } else {
351 // Equivalent encoding speed considering both cpu_used setting and 349 // Equivalent encoding speed considering both cpu_used setting and
352 // quantizer. 350 // quantizer.
353 double actual_encoding_speed = 351 double actual_encoding_speed =
354 encoding_speed_ + 352 encoding_speed_ +
355 kEquivalentEncodingSpeedStepPerQpStep * 353 kEquivalentEncodingSpeedStepPerQpStep *
356 std::max(0, quantizer - cast_config_.video_codec_params.min_qp); 354 std::max(0, quantizer - cast_config_.min_qp);
357 double adjusted_encoding_speed = actual_encoding_speed * 355 double adjusted_encoding_speed = actual_encoding_speed *
358 encoded_frame->encoder_utilization / 356 encoded_frame->encoder_utilization /
359 target_encoder_utilization_; 357 target_encoder_utilization_;
360 encoding_speed_acc_.Update(adjusted_encoding_speed, 358 encoding_speed_acc_.Update(adjusted_encoding_speed,
361 video_frame->timestamp()); 359 video_frame->timestamp());
362 } 360 }
363 361
364 if (HasSufficientFeedback(encoding_speed_acc_)) { 362 if (HasSufficientFeedback(encoding_speed_acc_)) {
365 // Predict |encoding_speed_| and |min_quantizer| for next frame. 363 // Predict |encoding_speed_| and |min_quantizer| for next frame.
366 // When CPU is constrained, increase encoding speed and increase 364 // When CPU is constrained, increase encoding speed and increase
367 // |min_quantizer| if needed. 365 // |min_quantizer| if needed.
368 double next_encoding_speed = encoding_speed_acc_.current(); 366 double next_encoding_speed = encoding_speed_acc_.current();
369 int next_min_qp; 367 int next_min_qp;
370 if (next_encoding_speed > kHighestEncodingSpeed) { 368 if (next_encoding_speed > kHighestEncodingSpeed) {
371 double remainder = next_encoding_speed - kHighestEncodingSpeed; 369 double remainder = next_encoding_speed - kHighestEncodingSpeed;
372 next_encoding_speed = kHighestEncodingSpeed; 370 next_encoding_speed = kHighestEncodingSpeed;
373 next_min_qp = 371 next_min_qp =
374 static_cast<int>(remainder / kEquivalentEncodingSpeedStepPerQpStep + 372 static_cast<int>(remainder / kEquivalentEncodingSpeedStepPerQpStep +
375 cast_config_.video_codec_params.min_qp + 0.5); 373 cast_config_.min_qp + 0.5);
376 next_min_qp = std::min(next_min_qp, 374 next_min_qp = std::min(next_min_qp, cast_config_.max_cpu_saver_qp);
377 cast_config_.video_codec_params.max_cpu_saver_qp);
378 } else { 375 } else {
379 next_encoding_speed = 376 next_encoding_speed =
380 std::max<double>(kLowestEncodingSpeed, next_encoding_speed) + 0.5; 377 std::max<double>(kLowestEncodingSpeed, next_encoding_speed) + 0.5;
381 next_min_qp = cast_config_.video_codec_params.min_qp; 378 next_min_qp = cast_config_.min_qp;
382 } 379 }
383 if (encoding_speed_ != static_cast<int>(next_encoding_speed)) { 380 if (encoding_speed_ != static_cast<int>(next_encoding_speed)) {
384 encoding_speed_ = static_cast<int>(next_encoding_speed); 381 encoding_speed_ = static_cast<int>(next_encoding_speed);
385 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -encoding_speed_), 382 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -encoding_speed_),
386 VPX_CODEC_OK); 383 VPX_CODEC_OK);
387 } 384 }
388 if (config_.rc_min_quantizer != static_cast<unsigned int>(next_min_qp)) { 385 if (config_.rc_min_quantizer != static_cast<unsigned int>(next_min_qp)) {
389 config_.rc_min_quantizer = static_cast<unsigned int>(next_min_qp); 386 config_.rc_min_quantizer = static_cast<unsigned int>(next_min_qp);
390 CHECK_EQ(vpx_codec_enc_config_set(&encoder_, &config_), VPX_CODEC_OK); 387 CHECK_EQ(vpx_codec_enc_config_set(&encoder_, &config_), VPX_CODEC_OK);
391 } 388 }
(...skipping 20 matching lines...) Expand all
412 VLOG(1) << "VP8 new rc_target_bitrate: " << new_bitrate_kbit << " kbps"; 409 VLOG(1) << "VP8 new rc_target_bitrate: " << new_bitrate_kbit << " kbps";
413 } 410 }
414 411
415 void Vp8Encoder::GenerateKeyFrame() { 412 void Vp8Encoder::GenerateKeyFrame() {
416 DCHECK(thread_checker_.CalledOnValidThread()); 413 DCHECK(thread_checker_.CalledOnValidThread());
417 key_frame_requested_ = true; 414 key_frame_requested_ = true;
418 } 415 }
419 416
420 } // namespace cast 417 } // namespace cast
421 } // namespace media 418 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/sender/vp8_encoder.h ('k') | media/cast/sender/vp8_quantizer_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698