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