| Index: media/cast/sender/external_video_encoder.cc
|
| diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
|
| index 70a57772c2289b374c00a6e4519831da81f9c9ed..bff088cc1e91f4460c63bff985e2dd173ddc968f 100644
|
| --- a/media/cast/sender/external_video_encoder.cc
|
| +++ b/media/cast/sender/external_video_encoder.cc
|
| @@ -8,6 +8,7 @@
|
| #include <utility>
|
|
|
| #include "base/bind.h"
|
| +#include "base/command_line.h"
|
| #include "base/debug/crash_logging.h"
|
| #include "base/debug/dump_without_crashing.h"
|
| #include "base/format_macros.h"
|
| @@ -16,9 +17,11 @@
|
| #include "base/memory/shared_memory.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/metrics/histogram.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "build/build_config.h"
|
| #include "media/base/bind_to_current_loop.h"
|
| +#include "media/base/media_switches.h"
|
| #include "media/base/video_frame.h"
|
| #include "media/base/video_types.h"
|
| #include "media/base/video_util.h"
|
| @@ -40,6 +43,40 @@ constexpr size_t kOutputBufferCount = 3;
|
| // used when copy is needed to match the required coded size.
|
| constexpr size_t kExtraInputBufferCount = 2;
|
|
|
| +// Parses the command-line flag and returns 0 (default) to use the old/flawed
|
| +// "deadline utilization" heuristic to measure encoder utilization. Otherwise,
|
| +// returns the "redline" value for the "backlog" heuristic (i.e., num_frames /
|
| +// redline = utilization).
|
| +//
|
| +// Example command line switches and results:
|
| +//
|
| +// --cast-encoder-util-heuristic=foobar ==> 0 (unrecognized, use deadline)
|
| +// --cast-encoder-util-heuristic=backlog ==> 6 (use backlog, default)
|
| +// --cast-encoder-util-heuristic=backlog7 ==> 7 (use backlog, redline=7)
|
| +//
|
| +// TODO(miu): This is temporary, for lab performance testing, until a
|
| +// good "works for all" solution is confirmed.
|
| +// https://code.google.com/p/chrome-os-partner/issues/detail?id=54806
|
| +int GetConfiguredBacklogRedline() {
|
| + constexpr char kBacklogSwitchValue[] = "backlog";
|
| + constexpr int kBacklogDefaultRedline = 6;
|
| +
|
| + const std::string& switch_value =
|
| + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
|
| + switches::kCastEncoderUtilHeuristic);
|
| + if (switch_value.find(kBacklogSwitchValue) == 0) {
|
| + int redline = kBacklogDefaultRedline;
|
| + if (!base::StringToInt(switch_value.substr(sizeof(kBacklogSwitchValue) - 1),
|
| + &redline)) {
|
| + redline = kBacklogDefaultRedline;
|
| + }
|
| + VLOG(1) << "Using 'backlog' heuristic with a redline of " << redline
|
| + << " to compute encoder utilization.";
|
| + return redline;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace media {
|
| @@ -96,6 +133,7 @@ class ExternalVideoEncoder::VEAClientImpl
|
| status_change_cb_(status_change_cb),
|
| create_video_encode_memory_cb_(create_video_encode_memory_cb),
|
| video_encode_accelerator_(std::move(vea)),
|
| + backlog_redline_threshold_(GetConfiguredBacklogRedline()),
|
| encoder_active_(false),
|
| next_frame_id_(FrameId::first()),
|
| key_frame_encountered_(false),
|
| @@ -307,12 +345,30 @@ class ExternalVideoEncoder::VEAClientImpl
|
| if (request.video_frame->metadata()->GetTimeDelta(
|
| media::VideoFrameMetadata::FRAME_DURATION, &frame_duration) &&
|
| frame_duration > base::TimeDelta()) {
|
| - // Compute encoder utilization as the real-world time elapsed divided
|
| - // by the frame duration.
|
| - const base::TimeDelta processing_time =
|
| - base::TimeTicks::Now() - request.start_time;
|
| - encoded_frame->encoder_utilization =
|
| - processing_time.InSecondsF() / frame_duration.InSecondsF();
|
| + if (backlog_redline_threshold_ == 0) {
|
| + // Compute encoder utilization as the real-world time elapsed divided
|
| + // by the frame duration.
|
| + const base::TimeDelta processing_time =
|
| + base::TimeTicks::Now() - request.start_time;
|
| + encoded_frame->encoder_utilization =
|
| + processing_time.InSecondsF() / frame_duration.InSecondsF();
|
| + } else {
|
| + // Compute encoder utilization in terms of the number of frames in
|
| + // backlog, including the current frame encode that is finishing
|
| + // here. This "backlog" model works as follows: First, assume that all
|
| + // frames utilize the encoder by the same amount. This is actually a
|
| + // false assumption, but it still works well because any frame that
|
| + // takes longer to encode will naturally cause the backlog to
|
| + // increase, and this will result in a higher computed utilization for
|
| + // the offending frame. If the backlog continues to increase, because
|
| + // the following frames are also taking too long to encode, the
|
| + // computed utilization for each successive frame will be higher. At
|
| + // some point, upstream control logic will decide that the data volume
|
| + // must be reduced.
|
| + encoded_frame->encoder_utilization =
|
| + static_cast<double>(in_progress_frame_encodes_.size()) /
|
| + backlog_redline_threshold_;
|
| + }
|
|
|
| const double actual_bit_rate =
|
| encoded_frame->data.size() * 8.0 / frame_duration.InSecondsF();
|
| @@ -540,6 +596,7 @@ class ExternalVideoEncoder::VEAClientImpl
|
| const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread.
|
| const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_;
|
| std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
|
| + const int backlog_redline_threshold_;
|
| bool encoder_active_;
|
| FrameId next_frame_id_;
|
| bool key_frame_encountered_;
|
|
|