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

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

Issue 2103043005: media/cast/sender: Rename deadline_utilization to encoder_utilization. (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') | 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 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 13 matching lines...) Expand all
24 // pause in the video stream. 24 // pause in the video stream.
25 const int kRestartFramePeriods = 3; 25 const int kRestartFramePeriods = 3;
26 26
27 // The following constants are used to automactically tune the encoder 27 // The following constants are used to automactically tune the encoder
28 // parameters: |cpu_used| and |min_quantizer|. 28 // parameters: |cpu_used| and |min_quantizer|.
29 29
30 // The |half-life| of the encoding speed accumulator. 30 // The |half-life| of the encoding speed accumulator.
31 // The smaller, the shorter of the time averaging window. 31 // The smaller, the shorter of the time averaging window.
32 const int kEncodingSpeedAccHalfLife = 120000; // 0.12 second. 32 const int kEncodingSpeedAccHalfLife = 120000; // 0.12 second.
33 33
34 // The target deadline utilization signal. This is a trade-off between quality 34 // The target encoder utilization signal. This is a trade-off between quality
35 // and less CPU usage. The range of this value is [0, 1]. Higher the value, 35 // and less CPU usage. The range of this value is [0, 1]. Higher the value,
36 // better the quality and higher the CPU usage. 36 // better the quality and higher the CPU usage.
37 // 37 //
38 // For machines with more than two encoding threads. 38 // For machines with more than two encoding threads.
39 const double kHiTargetDeadlineUtilization = 0.7; 39 const double kHiTargetEncoderUtilization = 0.7;
40 // For machines with two encoding threads. 40 // For machines with two encoding threads.
41 const double kMidTargetDeadlineUtilization = 0.6; 41 const double kMidTargetEncoderUtilization = 0.6;
42 // For machines with single encoding thread. 42 // For machines with single encoding thread.
43 const double kLoTargetDeadlineUtilization = 0.5; 43 const double kLoTargetEncoderUtilization = 0.5;
44 44
45 // This is the equivalent change on encoding speed for the change on each 45 // This is the equivalent change on encoding speed for the change on each
46 // quantizer step. 46 // quantizer step.
47 const double kEquivalentEncodingSpeedStepPerQpStep = 1 / 20.0; 47 const double kEquivalentEncodingSpeedStepPerQpStep = 1 / 20.0;
48 48
49 // Highest/lowest allowed encoding speed set to the encoder. The valid range 49 // Highest/lowest allowed encoding speed set to the encoder. The valid range
50 // is [4, 16]. Experiments show that with speed higher than 12, the saving of 50 // is [4, 16]. Experiments show that with speed higher than 12, the saving of
51 // the encoding time is not worth the dropping of the quality. And with speed 51 // the encoding time is not worth the dropping of the quality. And with speed
52 // lower than 6, the increasing of quality is not worth the increasing of 52 // lower than 6, the increasing of quality is not worth the increasing of
53 // encoding time. 53 // encoding time.
54 const int kHighestEncodingSpeed = 12; 54 const int kHighestEncodingSpeed = 12;
55 const int kLowestEncodingSpeed = 6; 55 const int kLowestEncodingSpeed = 6;
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 VideoSenderConfig& video_config) 66 Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config)
67 : cast_config_(video_config), 67 : cast_config_(video_config),
68 target_deadline_utilization_( 68 target_encoder_utilization_(
69 video_config.number_of_encode_threads > 2 69 video_config.number_of_encode_threads > 2
70 ? kHiTargetDeadlineUtilization 70 ? kHiTargetEncoderUtilization
71 : (video_config.number_of_encode_threads > 1 71 : (video_config.number_of_encode_threads > 1
72 ? kMidTargetDeadlineUtilization 72 ? kMidTargetEncoderUtilization
73 : kLoTargetDeadlineUtilization)), 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_.min_qp, cast_config_.max_cpu_saver_qp); 82 DCHECK_LE(cast_config_.min_qp, cast_config_.max_cpu_saver_qp);
83 DCHECK_LE(cast_config_.max_cpu_saver_qp, cast_config_.max_qp); 83 DCHECK_LE(cast_config_.max_cpu_saver_qp, cast_config_.max_qp);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -encoding_speed_), 185 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -encoding_speed_),
186 VPX_CODEC_OK); 186 VPX_CODEC_OK);
187 } 187 }
188 188
189 void Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, 189 void Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame,
190 const base::TimeTicks& reference_time, 190 const base::TimeTicks& reference_time,
191 SenderEncodedFrame* encoded_frame) { 191 SenderEncodedFrame* encoded_frame) {
192 DCHECK(thread_checker_.CalledOnValidThread()); 192 DCHECK(thread_checker_.CalledOnValidThread());
193 DCHECK(encoded_frame); 193 DCHECK(encoded_frame);
194 194
195 // Note: This is used to compute the |deadline_utilization| and so it uses the 195 // Note: This is used to compute the |encoder_utilization| and so it uses the
196 // real-world clock instead of the CastEnvironment clock, the latter of which 196 // real-world clock instead of the CastEnvironment clock, the latter of which
197 // might be simulated. 197 // might be simulated.
198 const base::TimeTicks start_time = base::TimeTicks::Now(); 198 const base::TimeTicks start_time = base::TimeTicks::Now();
199 199
200 // Initialize on-demand. Later, if the video frame size has changed, update 200 // Initialize on-demand. Later, if the video frame size has changed, update
201 // the encoder configuration. 201 // the encoder configuration.
202 const gfx::Size frame_size = video_frame->visible_rect().size(); 202 const gfx::Size frame_size = video_frame->visible_rect().size();
203 if (!is_initialized() || gfx::Size(config_.g_w, config_.g_h) != frame_size) 203 if (!is_initialized() || gfx::Size(config_.g_w, config_.g_h) != frame_size)
204 ConfigureForNewFrameSize(frame_size); 204 ConfigureForNewFrameSize(frame_size);
205 205
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 encoded_frame->frame_id.lower_32_bits(), 301 encoded_frame->frame_id.lower_32_bits(),
302 encoded_frame->rtp_timestamp.lower_32_bits(), 302 encoded_frame->rtp_timestamp.lower_32_bits(),
303 static_cast<int>(config_.rc_target_bitrate), 303 static_cast<int>(config_.rc_target_bitrate),
304 key_frame_requested_ ? 'Y' : 'N'); 304 key_frame_requested_ ? 'Y' : 'N');
305 base::debug::SetCrashKeyValue(kZeroEncodeDetails, details); 305 base::debug::SetCrashKeyValue(kZeroEncodeDetails, details);
306 // Please forward crash reports to http://crbug.com/519022: 306 // Please forward crash reports to http://crbug.com/519022:
307 base::debug::DumpWithoutCrashing(); 307 base::debug::DumpWithoutCrashing();
308 base::debug::ClearCrashKey(kZeroEncodeDetails); 308 base::debug::ClearCrashKey(kZeroEncodeDetails);
309 } 309 }
310 310
311 // Compute deadline utilization as the real-world time elapsed divided by the 311 // Compute encoder utilization as the real-world time elapsed divided by the
312 // frame duration. 312 // frame duration.
313 const base::TimeDelta processing_time = base::TimeTicks::Now() - start_time; 313 const base::TimeDelta processing_time = base::TimeTicks::Now() - start_time;
314 encoded_frame->deadline_utilization = 314 encoded_frame->encoder_utilization =
315 processing_time.InSecondsF() / predicted_frame_duration.InSecondsF(); 315 processing_time.InSecondsF() / predicted_frame_duration.InSecondsF();
316 316
317 // Compute lossy utilization. The VP8 encoder took an estimated guess at what 317 // Compute lossy utilization. The VP8 encoder took an estimated guess at what
318 // quantizer value would produce an encoded frame size as close to the target 318 // quantizer value would produce an encoded frame size as close to the target
319 // as possible. Now that the frame has been encoded and the number of bytes 319 // as possible. Now that the frame has been encoded and the number of bytes
320 // is known, the perfect quantizer value (i.e., the one that should have been 320 // is known, the perfect quantizer value (i.e., the one that should have been
321 // used) can be determined. This perfect quantizer is then normalized and 321 // used) can be determined. This perfect quantizer is then normalized and
322 // used as the lossy utilization. 322 // used as the lossy utilization.
323 const double actual_bitrate = 323 const double actual_bitrate =
324 encoded_frame->data.size() * 8.0 / predicted_frame_duration.InSecondsF(); 324 encoded_frame->data.size() * 8.0 / predicted_frame_duration.InSecondsF();
325 const double target_bitrate = 1000.0 * config_.rc_target_bitrate; 325 const double target_bitrate = 1000.0 * config_.rc_target_bitrate;
326 DCHECK_GT(target_bitrate, 0.0); 326 DCHECK_GT(target_bitrate, 0.0);
327 const double bitrate_utilization = actual_bitrate / target_bitrate; 327 const double bitrate_utilization = actual_bitrate / target_bitrate;
328 int quantizer = -1; 328 int quantizer = -1;
329 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_GET_LAST_QUANTIZER_64, &quantizer), 329 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_GET_LAST_QUANTIZER_64, &quantizer),
330 VPX_CODEC_OK); 330 VPX_CODEC_OK);
331 const double perfect_quantizer = bitrate_utilization * std::max(0, quantizer); 331 const double perfect_quantizer = bitrate_utilization * std::max(0, quantizer);
332 // Side note: If it was possible for the encoder to encode within the target 332 // Side note: If it was possible for the encoder to encode within the target
333 // number of bytes, the |perfect_quantizer| will be in the range [0.0,63.0]. 333 // number of bytes, the |perfect_quantizer| will be in the range [0.0,63.0].
334 // If it was never possible, the value will be greater than 63.0. 334 // If it was never possible, the value will be greater than 63.0.
335 encoded_frame->lossy_utilization = perfect_quantizer / 63.0; 335 encoded_frame->lossy_utilization = perfect_quantizer / 63.0;
336 336
337 DVLOG(2) << "VP8 encoded frame_id " << encoded_frame->frame_id 337 DVLOG(2) << "VP8 encoded frame_id " << encoded_frame->frame_id
338 << ", sized: " << encoded_frame->data.size() 338 << ", sized: " << encoded_frame->data.size()
339 << ", deadline_utilization: " << encoded_frame->deadline_utilization 339 << ", encoder_utilization: " << encoded_frame->encoder_utilization
340 << ", lossy_utilization: " << encoded_frame->lossy_utilization 340 << ", lossy_utilization: " << encoded_frame->lossy_utilization
341 << " (quantizer chosen by the encoder was " << quantizer << ')'; 341 << " (quantizer chosen by the encoder was " << quantizer << ')';
342 342
343 if (encoded_frame->dependency == EncodedFrame::KEY) { 343 if (encoded_frame->dependency == EncodedFrame::KEY) {
344 key_frame_requested_ = false; 344 key_frame_requested_ = false;
345 } 345 }
346 if (encoded_frame->dependency == EncodedFrame::KEY) { 346 if (encoded_frame->dependency == EncodedFrame::KEY) {
347 encoding_speed_acc_.Reset(kHighestEncodingSpeed, video_frame->timestamp()); 347 encoding_speed_acc_.Reset(kHighestEncodingSpeed, video_frame->timestamp());
348 } else { 348 } else {
349 // Equivalent encoding speed considering both cpu_used setting and 349 // Equivalent encoding speed considering both cpu_used setting and
350 // quantizer. 350 // quantizer.
351 double actual_encoding_speed = 351 double actual_encoding_speed =
352 encoding_speed_ + 352 encoding_speed_ +
353 kEquivalentEncodingSpeedStepPerQpStep * 353 kEquivalentEncodingSpeedStepPerQpStep *
354 std::max(0, quantizer - cast_config_.min_qp); 354 std::max(0, quantizer - cast_config_.min_qp);
355 double adjusted_encoding_speed = actual_encoding_speed * 355 double adjusted_encoding_speed = actual_encoding_speed *
356 encoded_frame->deadline_utilization / 356 encoded_frame->encoder_utilization /
357 target_deadline_utilization_; 357 target_encoder_utilization_;
358 encoding_speed_acc_.Update(adjusted_encoding_speed, 358 encoding_speed_acc_.Update(adjusted_encoding_speed,
359 video_frame->timestamp()); 359 video_frame->timestamp());
360 } 360 }
361 361
362 if (HasSufficientFeedback(encoding_speed_acc_)) { 362 if (HasSufficientFeedback(encoding_speed_acc_)) {
363 // Predict |encoding_speed_| and |min_quantizer| for next frame. 363 // Predict |encoding_speed_| and |min_quantizer| for next frame.
364 // When CPU is constrained, increase encoding speed and increase 364 // When CPU is constrained, increase encoding speed and increase
365 // |min_quantizer| if needed. 365 // |min_quantizer| if needed.
366 double next_encoding_speed = encoding_speed_acc_.current(); 366 double next_encoding_speed = encoding_speed_acc_.current();
367 int next_min_qp; 367 int next_min_qp;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 VLOG(1) << "VP8 new rc_target_bitrate: " << new_bitrate_kbit << " kbps"; 409 VLOG(1) << "VP8 new rc_target_bitrate: " << new_bitrate_kbit << " kbps";
410 } 410 }
411 411
412 void Vp8Encoder::GenerateKeyFrame() { 412 void Vp8Encoder::GenerateKeyFrame() {
413 DCHECK(thread_checker_.CalledOnValidThread()); 413 DCHECK(thread_checker_.CalledOnValidThread());
414 key_frame_requested_ = true; 414 key_frame_requested_ = true;
415 } 415 }
416 416
417 } // namespace cast 417 } // namespace cast
418 } // namespace media 418 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/sender/vp8_encoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698