summaryrefslogtreecommitdiff
path: root/chromium/media/cast
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-12 14:07:37 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 10:29:26 +0000
commitec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch)
tree25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/media/cast
parentbb09965444b5bb20b096a291445170876225268d (diff)
downloadqtwebengine-chromium-ec02ee4181c49b61fce1c8fb99292dbb8139cc90.tar.gz
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/media/cast')
-rw-r--r--chromium/media/cast/BUILD.gn3
-rw-r--r--chromium/media/cast/sender/congestion_control.cc80
-rw-r--r--chromium/media/cast/sender/congestion_control_unittest.cc47
-rw-r--r--chromium/media/cast/sender/h264_vt_encoder_unittest.cc7
-rw-r--r--chromium/media/cast/sender/performance_metrics_overlay.cc110
-rw-r--r--chromium/media/cast/sender/performance_metrics_overlay.h40
-rw-r--r--chromium/media/cast/sender/video_sender.cc22
7 files changed, 210 insertions, 99 deletions
diff --git a/chromium/media/cast/BUILD.gn b/chromium/media/cast/BUILD.gn
index 43b3db19559..bd5a8484c7a 100644
--- a/chromium/media/cast/BUILD.gn
+++ b/chromium/media/cast/BUILD.gn
@@ -42,6 +42,7 @@ source_set("common") {
"logging/logging_defines.cc",
"logging/logging_defines.h",
"logging/proto/proto_utils.cc",
+ "logging/proto/proto_utils.h",
"logging/raw_event_subscriber.h",
"logging/raw_event_subscriber_bundle.cc",
"logging/raw_event_subscriber_bundle.h",
@@ -80,6 +81,7 @@ source_set("net") {
"net/pacing/paced_sender.cc",
"net/pacing/paced_sender.h",
"net/rtcp/receiver_rtcp_event_subscriber.cc",
+ "net/rtcp/receiver_rtcp_event_subscriber.h",
"net/rtcp/receiver_rtcp_session.cc",
"net/rtcp/receiver_rtcp_session.h",
"net/rtcp/rtcp_builder.cc",
@@ -310,6 +312,7 @@ test("cast_unittests") {
"net/rtp/packet_storage_unittest.cc",
"net/rtp/receiver_stats_unittest.cc",
"net/rtp/rtp_packet_builder.cc",
+ "net/rtp/rtp_packet_builder.h",
"net/rtp/rtp_packetizer_unittest.cc",
"net/rtp/rtp_parser_unittest.cc",
"net/udp_transport_unittest.cc",
diff --git a/chromium/media/cast/sender/congestion_control.cc b/chromium/media/cast/sender/congestion_control.cc
index c7d81ad3659..7cdbb5d98f8 100644
--- a/chromium/media/cast/sender/congestion_control.cc
+++ b/chromium/media/cast/sender/congestion_control.cc
@@ -60,7 +60,10 @@ class AdaptiveCongestionControl : public CongestionControl {
// Calculate how much "dead air" (idle time) there is between two frames.
static base::TimeDelta DeadTime(const FrameStats& a, const FrameStats& b);
- // Get the FrameStats for a given |frame_id|. Never returns nullptr.
+ // Get the FrameStats for a given |frame_id|, auto-creating a new FrameStats
+ // for newer frames, but possibly returning nullptr for older frames that have
+ // been pruned. Never returns nullptr for |frame_id|s equal to or greater than
+ // |last_checkpoint_frame_|.
// Note: Older FrameStats will be removed automatically.
FrameStats* GetFrameStats(FrameId frame_id);
// Discard old FrameStats.
@@ -202,7 +205,8 @@ base::TimeDelta AdaptiveCongestionControl::DeadTime(const FrameStats& a,
}
double AdaptiveCongestionControl::CalculateSafeBitrate() {
- double transmit_time =
+ DCHECK(!frame_stats_.empty());
+ const double transmit_time =
(GetFrameStats(last_checkpoint_frame_)->ack_time -
frame_stats_.front().enqueue_time - dead_time_in_history_)
.InSecondsF();
@@ -215,24 +219,41 @@ double AdaptiveCongestionControl::CalculateSafeBitrate() {
AdaptiveCongestionControl::FrameStats* AdaptiveCongestionControl::GetFrameStats(
FrameId frame_id) {
- DCHECK_LT(frame_id - last_frame_stats_, static_cast<int64_t>(kHistorySize));
int offset = frame_id - last_frame_stats_;
if (offset > 0) {
+ // Sanity-check: Make sure the new |frame_id| will not cause an unreasonably
+ // large increase in the history dataset.
+ DCHECK_LE(offset, kMaxUnackedFrames + 1);
+
frame_stats_.resize(frame_stats_.size() + offset);
- last_frame_stats_ += offset;
+ last_frame_stats_ = frame_id;
offset = 0;
}
PruneFrameStats();
offset += frame_stats_.size() - 1;
- // TODO(miu): Change the following to DCHECK once crash fix is confirmed.
- // http://crbug.com/517145
- CHECK(offset >= 0 && offset < static_cast<int32_t>(frame_stats_.size()));
+ if (offset < 0) {
+ DCHECK_LT(frame_id, last_checkpoint_frame_);
+ return nullptr; // Old frame has been pruned from the dataset.
+ }
return &frame_stats_[offset];
}
void AdaptiveCongestionControl::PruneFrameStats() {
- while (frame_stats_.size() > history_size_) {
- DCHECK_GT(frame_stats_.size(), 1UL);
+ // Maintain a minimal amount of history, specified by |history_size_|, that
+ // MUST also include all frames from the last ACK'ed frame.
+ const size_t retention_count = std::max<size_t>(
+ history_size_, last_frame_stats_ - last_checkpoint_frame_ + 1);
+
+ // Sanity-check: At least one entry must be kept, but the dataset should not
+ // grow indefinitely.
+ DCHECK_GE(retention_count, 1u);
+ constexpr size_t kMaxInFlightRangeSize =
+ kMaxUnackedFrames + // Maximum unACKed frames.
+ 1 + // The last ACKed frame.
+ 1; // One not-yet-enqueued frame (see call to EstimatedSendingTime()).
+ DCHECK_LE(retention_count, std::max(history_size_, kMaxInFlightRangeSize));
+
+ while (frame_stats_.size() > retention_count) {
DCHECK(!frame_stats_[0].ack_time.is_null());
acked_bits_in_history_ -= frame_stats_[0].frame_size_in_bits;
dead_time_in_history_ -= DeadTime(frame_stats_[0], frame_stats_[1]);
@@ -249,12 +270,14 @@ void AdaptiveCongestionControl::AckFrame(FrameId frame_id,
while (last_checkpoint_frame_ < frame_id) {
FrameStats* last_frame_stats = frame_stats;
frame_stats = GetFrameStats(last_checkpoint_frame_ + 1);
- if (frame_stats->enqueue_time.is_null()) {
- // Can't ack a frame that hasn't been sent yet.
- return;
- }
+ // Note: This increment must happen AFTER the GetFrameStats() call to
+ // prevent the |last_frame_stats| pointer from being invalidated.
last_checkpoint_frame_++;
- if (when < frame_stats->enqueue_time)
+ // When ACKing a frame that was never sent, just pretend it was sent and
+ // ACKed at the same point-in-time.
+ if (frame_stats->enqueue_time.is_null())
+ frame_stats->enqueue_time = when;
+ else if (when < frame_stats->enqueue_time)
when = frame_stats->enqueue_time;
// Don't overwrite the ack time for those frames that were already acked in
// previous extended ACKs.
@@ -270,20 +293,21 @@ void AdaptiveCongestionControl::AckFrame(FrameId frame_id,
void AdaptiveCongestionControl::AckLaterFrames(
std::vector<FrameId> received_frames,
base::TimeTicks when) {
+ DCHECK(std::is_sorted(received_frames.begin(), received_frames.end()));
for (FrameId frame_id : received_frames) {
- if (last_checkpoint_frame_ < frame_id) {
- FrameStats* frame_stats = GetFrameStats(frame_id);
- if (frame_stats->enqueue_time.is_null()) {
- // Can't ack a frame that hasn't been sent yet.
- continue;
- }
- if (when < frame_stats->enqueue_time)
- when = frame_stats->enqueue_time;
- // Don't overwrite the ack time for those frames that were acked before.
- if (frame_stats->ack_time.is_null())
- frame_stats->ack_time = when;
- DCHECK_GE(when, frame_stats->ack_time);
- }
+ if (frame_id <= last_checkpoint_frame_)
+ continue;
+ FrameStats* frame_stats = GetFrameStats(frame_id);
+ // When ACKing a frame that was never sent, just pretend it was sent and
+ // ACKed at the same point-in-time.
+ if (frame_stats->enqueue_time.is_null())
+ frame_stats->enqueue_time = when;
+ else if (when < frame_stats->enqueue_time)
+ when = frame_stats->enqueue_time;
+ // Don't overwrite the ack time for those frames that were acked before.
+ if (frame_stats->ack_time.is_null())
+ frame_stats->ack_time = when;
+ DCHECK_GE(when, frame_stats->ack_time);
}
}
@@ -292,6 +316,7 @@ void AdaptiveCongestionControl::SendFrameToTransport(FrameId frame_id,
base::TimeTicks when) {
last_enqueued_frame_ = frame_id;
FrameStats* frame_stats = GetFrameStats(frame_id);
+ DCHECK(frame_stats);
frame_stats->enqueue_time = when;
frame_stats->frame_size_in_bits = frame_size_in_bits;
}
@@ -357,6 +382,7 @@ base::TimeTicks AdaptiveCongestionControl::EstimatedSendingTime(
}
FrameStats* const frame_stats = GetFrameStats(frame_id);
+ DCHECK(frame_stats);
if (frame_stats->enqueue_time.is_null()) {
// The frame has not yet been enqueued for transport. Since it cannot be
// enqueued in the past, ensure the result is lower-bounded by |now|.
diff --git a/chromium/media/cast/sender/congestion_control_unittest.cc b/chromium/media/cast/sender/congestion_control_unittest.cc
index b3884137ed6..561ce87bb2e 100644
--- a/chromium/media/cast/sender/congestion_control_unittest.cc
+++ b/chromium/media/cast/sender/congestion_control_unittest.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "media/base/fake_single_thread_task_runner.h"
+#include "media/cast/constants.h"
#include "media/cast/sender/congestion_control.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -143,5 +144,51 @@ TEST_F(CongestionControlTest, SimpleRun) {
safe_bitrate * 0.05);
}
+// Regression test for http://crbug.com/685392: This confirms that enough
+// history is maintained in AdaptiveCongestionControl to avoid invalid
+// indexing offsets. This test is successful if it does not crash the process.
+TEST_F(CongestionControlTest, RetainsSufficientHistory) {
+ constexpr base::TimeDelta kFakePlayoutDelay =
+ base::TimeDelta::FromMilliseconds(400);
+
+ // Sanity-check: With no data, GetBitrate() returns an in-range value.
+ const int bitrate = congestion_control_->GetBitrate(
+ testing_clock_.NowTicks() + kFakePlayoutDelay, kFakePlayoutDelay);
+ ASSERT_GE(bitrate, kMinBitrateConfigured);
+ ASSERT_LE(bitrate, kMaxBitrateConfigured);
+
+ // Notify AdaptiveCongestionControl of a large number (the maximum possible)
+ // of frames being enqueued for transport, but not yet ACKed. Confirm
+ // GetBitrate() returns an in-range value at each step.
+ FrameId frame_id = FrameId::first();
+ for (int i = 0; i < kMaxUnackedFrames; ++i) {
+ congestion_control_->SendFrameToTransport(frame_id, 16384,
+ testing_clock_.NowTicks());
+
+ const int bitrate = congestion_control_->GetBitrate(
+ testing_clock_.NowTicks() + kFakePlayoutDelay, kFakePlayoutDelay);
+ ASSERT_GE(bitrate, kMinBitrateConfigured);
+ ASSERT_LE(bitrate, kMaxBitrateConfigured);
+
+ task_runner_->Sleep(base::TimeDelta::FromMilliseconds(kFrameDelayMs));
+ ++frame_id;
+ }
+
+ // Notify AdaptiveCongestionControl that each frame is ACK'ed, again checking
+ // that GetBitrate() returns an in-range value at each step.
+ frame_id = FrameId::first();
+ for (int i = 0; i < kMaxUnackedFrames; ++i) {
+ congestion_control_->AckFrame(frame_id, testing_clock_.NowTicks());
+
+ const int bitrate = congestion_control_->GetBitrate(
+ testing_clock_.NowTicks() + kFakePlayoutDelay, kFakePlayoutDelay);
+ ASSERT_GE(bitrate, kMinBitrateConfigured);
+ ASSERT_LE(bitrate, kMaxBitrateConfigured);
+
+ task_runner_->Sleep(base::TimeDelta::FromMilliseconds(kFrameDelayMs));
+ ++frame_id;
+ }
+}
+
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/sender/h264_vt_encoder_unittest.cc b/chromium/media/cast/sender/h264_vt_encoder_unittest.cc
index 72ff6735224..8fdf50ab900 100644
--- a/chromium/media/cast/sender/h264_vt_encoder_unittest.cc
+++ b/chromium/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_monitor.h"
#include "base/run_loop.h"
@@ -19,6 +20,7 @@
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media.h"
+#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/media_util.h"
#include "media/cast/common/rtp_time.h"
@@ -128,7 +130,8 @@ class EndToEndFrameChecker
: public base::RefCountedThreadSafe<EndToEndFrameChecker> {
public:
explicit EndToEndFrameChecker(const VideoDecoderConfig& config)
- : decoder_(), count_frames_checked_(0) {
+ : decoder_(make_scoped_refptr(new media::MediaLog())),
+ count_frames_checked_(0) {
bool decoder_init_result;
decoder_.Initialize(
config, false, nullptr,
@@ -178,7 +181,7 @@ void CreateFrameAndMemsetPlane(VideoFrameFactory* const video_frame_factory) {
video_frame_factory->MaybeCreateFrame(
gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta());
ASSERT_TRUE(video_frame.get());
- auto* cv_pixel_buffer = video_frame->cv_pixel_buffer();
+ auto* cv_pixel_buffer = video_frame->CvPixelBuffer();
ASSERT_TRUE(cv_pixel_buffer);
CVPixelBufferLockBaseAddress(cv_pixel_buffer, 0);
auto* ptr = CVPixelBufferGetBaseAddressOfPlane(cv_pixel_buffer, 0);
diff --git a/chromium/media/cast/sender/performance_metrics_overlay.cc b/chromium/media/cast/sender/performance_metrics_overlay.cc
index 389b6f37cd8..d132db059db 100644
--- a/chromium/media/cast/sender/performance_metrics_overlay.cc
+++ b/chromium/media/cast/sender/performance_metrics_overlay.cc
@@ -10,6 +10,7 @@
#include <algorithm>
#include <string>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
@@ -20,12 +21,12 @@ namespace cast {
namespace {
-const int kScale = 4; // Physical pixels per one logical pixel.
-const int kCharacterWidth = 3; // Logical pixel width of one character.
-const int kCharacterHeight = 5; // Logical pixel height of one character.
-const int kCharacterSpacing = 1; // Logical pixels between each character.
-const int kLineSpacing = 2; // Logical pixels between each line of characters.
-const int kPlane = 0; // Y-plane in YUV formats.
+constexpr int kScale = 4; // Physical pixels per one logical pixel.
+constexpr int kCharacterWidth = 3; // Logical pixel width of one character.
+constexpr int kCharacterHeight = 5; // Logical pixel height of one character.
+constexpr int kCharacterSpacing = 1; // Logical pixels between each character.
+constexpr int kLineSpacing = 2; // Logical pixels between each line of chars.
+constexpr int kPlane = 0; // Y-plane in YUV formats.
// For each pixel in the |rect| (logical coordinates), either decrease the
// intensity or increase it so that the resulting pixel has a perceivably
@@ -214,29 +215,60 @@ void RenderLineOfText(const std::string& line, int top, VideoFrame* frame) {
} // namespace
-void MaybeRenderPerformanceMetricsOverlay(base::TimeDelta target_playout_delay,
- bool in_low_latency_mode,
- int target_bitrate,
- int frames_ago,
- double encoder_utilization,
- double lossy_utilization,
- VideoFrame* frame) {
- if (VideoFrame::PlaneHorizontalBitsPerPixel(frame->format(), kPlane) != 8) {
+scoped_refptr<VideoFrame> MaybeRenderPerformanceMetricsOverlay(
+ base::TimeDelta target_playout_delay,
+ bool in_low_latency_mode,
+ int target_bitrate,
+ int frames_ago,
+ double encoder_utilization,
+ double lossy_utilization,
+ scoped_refptr<VideoFrame> source) {
+ if (!VLOG_IS_ON(1))
+ return source;
+
+ if (VideoFrame::PlaneHorizontalBitsPerPixel(source->format(), kPlane) != 8) {
DLOG(WARNING) << "Cannot render overlay: Plane " << kPlane << " not 8bpp.";
- return;
+ return source;
}
- // Can't render to unmappable memory (DmaBuf, CVPixelBuffer).
- if (!frame->IsMappable()) {
+ // Can't read from unmappable memory (DmaBuf, CVPixelBuffer).
+ if (!source->IsMappable()) {
DVLOG(2) << "Cannot render overlay: frame uses unmappable memory.";
- return;
+ return source;
}
// Compute the physical pixel top row for the bottom-most line of text.
const int line_height = (kCharacterHeight + kLineSpacing) * kScale;
- int top = frame->visible_rect().height() - line_height;
- if (top < 0 || !VLOG_IS_ON(1))
- return;
+ int top = source->visible_rect().height() - line_height;
+ if (top < 0)
+ return source; // No pixels would change: Return source frame.
+
+ // Allocate a new frame, identical in configuration to |source| and copy over
+ // all data and metadata.
+ const scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
+ source->format(), source->coded_size(), source->visible_rect(),
+ source->natural_size(), source->timestamp());
+ if (!frame)
+ return source; // Allocation failure: Return source frame.
+ for (size_t plane = 0, num_planes = VideoFrame::NumPlanes(source->format());
+ plane < num_planes; ++plane) {
+ memcpy(frame->data(plane), source->data(plane),
+ source->stride(plane) * source->rows(plane));
+ }
+ frame->metadata()->MergeMetadataFrom(source->metadata());
+ // Important: After all consumers are done with the frame, copy-back the
+ // changed/new metadata to the source frame, as it contains feedback signals
+ // that need to propagate back up the video stack. The destruction callback
+ // for the |frame| holds a ref-counted reference to the source frame to ensure
+ // the source frame has the right metadata before its destruction observers
+ // are invoked.
+ frame->AddDestructionObserver(base::Bind(
+ [](const VideoFrameMetadata* sent_frame_metadata,
+ const scoped_refptr<VideoFrame>& source_frame) {
+ source_frame->metadata()->Clear();
+ source_frame->metadata()->MergeMetadataFrom(sent_frame_metadata);
+ },
+ frame->metadata(), std::move(source)));
// Line 3: Frame duration, resolution, and timestamp.
int frame_duration_ms = 0;
@@ -255,21 +287,17 @@ void MaybeRenderPerformanceMetricsOverlay(base::TimeDelta target_playout_delay,
const int seconds = static_cast<int>(rem.InSeconds());
rem -= base::TimeDelta::FromSeconds(seconds);
const int hundredth_seconds = static_cast<int>(rem.InMilliseconds() / 10);
- RenderLineOfText(base::StringPrintf("%d.%01d %dx%d %d:%02d.%02d",
- frame_duration_ms,
- frame_duration_ms_frac,
- frame->visible_rect().width(),
- frame->visible_rect().height(),
- minutes,
- seconds,
- hundredth_seconds),
- top,
- frame);
+ RenderLineOfText(
+ base::StringPrintf("%d.%01d %dx%d %d:%02d.%02d", frame_duration_ms,
+ frame_duration_ms_frac, frame->visible_rect().width(),
+ frame->visible_rect().height(), minutes, seconds,
+ hundredth_seconds),
+ top, frame.get());
// Move up one line's worth of pixels.
top -= line_height;
if (top < 0 || !VLOG_IS_ON(2))
- return;
+ return frame;
// Line 2: Capture duration, target playout delay, low-latency mode, and
// target bitrate.
@@ -285,18 +313,16 @@ void MaybeRenderPerformanceMetricsOverlay(base::TimeDelta target_playout_delay,
const int target_playout_delay_ms =
static_cast<int>(target_playout_delay.InMillisecondsF() + 0.5);
const int target_kbits = target_bitrate / 1000;
- RenderLineOfText(base::StringPrintf("%d %4.1d%c %4.1d",
- capture_duration_ms,
- target_playout_delay_ms,
- in_low_latency_mode ? '!' : '.',
- target_kbits),
- top,
- frame);
+ RenderLineOfText(
+ base::StringPrintf("%d %4.1d%c %4.1d", capture_duration_ms,
+ target_playout_delay_ms,
+ in_low_latency_mode ? '!' : '.', target_kbits),
+ top, frame.get());
// Move up one line's worth of pixels.
top -= line_height;
if (top < 0 || !VLOG_IS_ON(3))
- return;
+ return frame;
// Line 1: Recent utilization metrics.
const int encoder_pct =
@@ -305,7 +331,9 @@ void MaybeRenderPerformanceMetricsOverlay(base::TimeDelta target_playout_delay,
base::saturated_cast<int>(lossy_utilization * 100.0 + 0.5);
RenderLineOfText(base::StringPrintf("%d %3.1d%% %3.1d%%", frames_ago,
encoder_pct, lossy_pct),
- top, frame);
+ top, frame.get());
+
+ return frame;
}
} // namespace cast
diff --git a/chromium/media/cast/sender/performance_metrics_overlay.h b/chromium/media/cast/sender/performance_metrics_overlay.h
index e9a66524b8b..774effe19da 100644
--- a/chromium/media/cast/sender/performance_metrics_overlay.h
+++ b/chromium/media/cast/sender/performance_metrics_overlay.h
@@ -6,6 +6,7 @@
#define MEDIA_CAST_SENDER_PERFORMANCE_METRICS_OVERLAY_H_
#include "base/time/time.h"
+#include "media/base/video_frame.h"
// This module provides a display of frame-level performance metrics, rendered
// in the lower-right corner of a VideoFrame. It looks like this:
@@ -48,25 +49,30 @@
// media timestamp in minutes:seconds.hundredths format.
namespace media {
-
-class VideoFrame;
-
namespace cast {
-// Renders an overlay of frame-level performance metrics in the lower-right
-// corner of the |frame|, as described above. The verbose logging level for
-// video_frame_overlay.cc determines which lines, if any, are rendered: VLOG
-// level 1 renders the bottom line only, level 2 renders the bottom and middle
-// lines, and level 3 renders all three lines. So, use the
-// --vmodule=performance_metrics_overlay=3 command line argument to turn on
-// rendering of the entire overlay.
-void MaybeRenderPerformanceMetricsOverlay(base::TimeDelta target_playout_delay,
- bool in_low_latency_mode,
- int target_bitrate,
- int frames_ago,
- double encoder_utilization,
- double lossy_utilization,
- VideoFrame* frame);
+// If the user has requested VideoFrames have a performance metrics overlay
+// rendered on them, this function copies the |source| frame and then renders an
+// overlay on the copy. Frame-level performance metrics will be rendered in the
+// lower-right corner of the frame, as described in the module-level comments
+// above.
+//
+// The verbose logging level for video_frame_overlay.cc determines which lines,
+// if any, are rendered: no VLOG level does nothing, level 1 renders the bottom
+// line only, level 2 renders the bottom and middle lines, and level 3 renders
+// all three lines. So, use the --vmodule=performance_metrics_overlay=3 command
+// line argument to turn on rendering of the entire overlay.
+//
+// Note: If |source| is an unsupported format, or no pixels need to be modified,
+// this function will just return |source|.
+scoped_refptr<VideoFrame> MaybeRenderPerformanceMetricsOverlay(
+ base::TimeDelta target_playout_delay,
+ bool in_low_latency_mode,
+ int target_bitrate,
+ int frames_ago,
+ double encoder_utilization,
+ double lossy_utilization,
+ scoped_refptr<VideoFrame> source);
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/sender/video_sender.cc b/chromium/media/cast/sender/video_sender.cc
index a0c15e02f54..8447223d1e9 100644
--- a/chromium/media/cast/sender/video_sender.cc
+++ b/chromium/media/cast/sender/video_sender.cc
@@ -250,20 +250,18 @@ void VideoSender::InsertRawVideoFrame(
TRACE_COUNTER_ID1("cast.stream", "Video Target Bitrate", this, bitrate);
- MaybeRenderPerformanceMetricsOverlay(
- GetTargetPlayoutDelay(), low_latency_mode_, bitrate,
- frames_in_encoder_ + 1, last_reported_encoder_utilization_,
- last_reported_lossy_utilization_, video_frame.get());
-
+ const scoped_refptr<VideoFrame> frame_to_encode =
+ MaybeRenderPerformanceMetricsOverlay(
+ GetTargetPlayoutDelay(), low_latency_mode_, bitrate,
+ frames_in_encoder_ + 1, last_reported_encoder_utilization_,
+ last_reported_lossy_utilization_, video_frame);
if (video_encoder_->EncodeVideoFrame(
- video_frame,
- reference_time,
+ frame_to_encode, reference_time,
base::Bind(&VideoSender::OnEncodedVideoFrame,
- weak_factory_.GetWeakPtr(),
- video_frame,
- bitrate))) {
- TRACE_EVENT_ASYNC_BEGIN1("cast.stream", "Video Encode", video_frame.get(),
- "rtp_timestamp", rtp_timestamp.lower_32_bits());
+ weak_factory_.GetWeakPtr(), frame_to_encode, bitrate))) {
+ TRACE_EVENT_ASYNC_BEGIN1("cast.stream", "Video Encode",
+ frame_to_encode.get(), "rtp_timestamp",
+ rtp_timestamp.lower_32_bits());
frames_in_encoder_++;
duration_in_encoder_ += duration_added_by_next_frame;
last_enqueued_frame_rtp_timestamp_ = rtp_timestamp;