1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
media / mojo / services / webrtc_video_perf_recorder.cc [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "media/mojo/services/webrtc_video_perf_recorder.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace media {
namespace {
constexpr int EncodeOrDecodeIndex(bool is_decode) {
return is_decode ? 0 : 1;
}
} // namespace
// static
void WebrtcVideoPerfRecorder::Create(
media::WebrtcVideoPerfHistory* webrtc_video_perf_history,
mojo::PendingReceiver<media::mojom::WebrtcVideoPerfRecorder> receiver) {
// Only save video stats when BrowserContext provides a
// WebrtcVideoPerfHistory. Off-the-record contexts will internally use an
// in-memory history DB.
media::WebrtcVideoPerfHistory::SaveCallback save_stats_cb;
if (webrtc_video_perf_history) {
save_stats_cb = webrtc_video_perf_history->GetSaveCallback();
}
mojo::MakeSelfOwnedReceiver(
std::make_unique<WebrtcVideoPerfRecorder>(std::move(save_stats_cb)),
std::move(receiver));
}
WebrtcVideoPerfRecorder::WebrtcVideoPerfRecorder(
WebrtcVideoPerfHistory::SaveCallback save_cb)
: save_cb_(std::move(save_cb)) {
DCHECK(save_cb_);
}
WebrtcVideoPerfRecorder::~WebrtcVideoPerfRecorder() {
DVLOG(2) << __func__ << " Finalize for IPC disconnect";
FinalizeRecord(EncodeOrDecodeIndex(/*is_decode=*/true));
FinalizeRecord(EncodeOrDecodeIndex(/*is_decode=*/false));
}
void WebrtcVideoPerfRecorder::UpdateRecord(
media::mojom::WebrtcPredictionFeaturesPtr features,
media::mojom::WebrtcVideoStatsPtr video_stats) {
// `features` and `video_stats` are potentially compromised and should not be
// used in any calculations directly. They are sanity checked in
// WebrtcVideoPerfHistory before stored to the database.
int encode_or_decode_index = EncodeOrDecodeIndex(features->is_decode_stats);
if (features_[encode_or_decode_index].profile != features->profile ||
features_[encode_or_decode_index].video_pixels !=
features->video_pixels ||
features_[encode_or_decode_index].hardware_accelerated !=
features->hardware_accelerated) {
StartNewRecord(std::move(features));
}
DVLOG(3) << __func__ << " frames_processed:" << video_stats->frames_processed
<< " key_frames_processed:" << video_stats->key_frames_processed
<< " p99_processing_time_ms:" << video_stats->p99_processing_time_ms;
video_stats_[encode_or_decode_index] = *video_stats;
}
void WebrtcVideoPerfRecorder::StartNewRecord(
media::mojom::WebrtcPredictionFeaturesPtr features) {
DVLOG(3) << __func__ << " is_decode_stats:" << features->is_decode_stats
<< " profile:" << features->profile
<< " video_pixels:" << features->video_pixels
<< " hardware_accelerated:" << features->hardware_accelerated;
// Finalize existing stats with the current state.
int encode_or_decode_index = EncodeOrDecodeIndex(features->is_decode_stats);
FinalizeRecord(encode_or_decode_index);
features_[encode_or_decode_index] = *features;
// Reinitialize to defaults.
video_stats_[encode_or_decode_index] = media::mojom::WebrtcVideoStats();
}
void WebrtcVideoPerfRecorder::FinalizeRecord(int encode_or_decode_index) {
if (features_[encode_or_decode_index].profile ==
VIDEO_CODEC_PROFILE_UNKNOWN ||
features_[encode_or_decode_index].video_pixels == 0 ||
video_stats_[encode_or_decode_index].frames_processed == 0) {
return;
}
DVLOG(3) << __func__ << " is_decode_stats"
<< features_[encode_or_decode_index].is_decode_stats
<< " profile:" << features_[encode_or_decode_index].profile
<< " video_pixels:" << features_[encode_or_decode_index].video_pixels
<< " hardware_accelerated:"
<< features_[encode_or_decode_index].hardware_accelerated
<< " frames_processed:"
<< video_stats_[encode_or_decode_index].frames_processed
<< " key_frames_processed:"
<< video_stats_[encode_or_decode_index].key_frames_processed
<< " p99_processing_time_ms:"
<< video_stats_[encode_or_decode_index].p99_processing_time_ms;
// Final argument is an empty save-done-callback. No action to take if save
// fails (DB already records UMAs on failure). Callback mainly used by tests.
save_cb_.Run(features_[encode_or_decode_index],
video_stats_[encode_or_decode_index], base::OnceClosure());
}
} // namespace media