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

Unified Diff: media/cast/sender/performance_metrics_overlay.cc

Issue 2775993002: Crash Fix (Cast Streaming): Render overlay on copy of source frame. (Closed)
Patch Set: Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/cast/sender/performance_metrics_overlay.h ('k') | media/cast/sender/video_sender.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/cast/sender/performance_metrics_overlay.cc
diff --git a/media/cast/sender/performance_metrics_overlay.cc b/media/cast/sender/performance_metrics_overlay.cc
index 389b6f37cd8c387a423e0f963f19700f04ad084a..d132db059db7cce0962695651b48799998caf2ed 100644
--- a/media/cast/sender/performance_metrics_overlay.cc
+++ b/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
« no previous file with comments | « media/cast/sender/performance_metrics_overlay.h ('k') | media/cast/sender/video_sender.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698