forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathin_memory_video_decode_stats_db_impl.cc
207 lines (169 loc) · 7.17 KB
/
in_memory_video_decode_stats_db_impl.cc
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
#include <memory>
#include <tuple>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capabilities/video_decode_stats_db_impl.h"
#include "media/capabilities/video_decode_stats_db_provider.h"
namespace media {
InMemoryVideoDecodeStatsDBImpl::InMemoryVideoDecodeStatsDBImpl(
VideoDecodeStatsDBProvider* seed_db_provider)
: seed_db_provider_(seed_db_provider), weak_ptr_factory_(this) {
DVLOG(2) << __func__;
}
InMemoryVideoDecodeStatsDBImpl::~InMemoryVideoDecodeStatsDBImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (seed_db_)
seed_db_->set_dependent_db(nullptr);
}
void InMemoryVideoDecodeStatsDBImpl::Initialize(InitializeCB init_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(init_cb);
DCHECK(!db_init_);
// Fetch an *initialized* seed DB.
if (seed_db_provider_) {
seed_db_provider_->GetVideoDecodeStatsDB(
base::BindOnce(&InMemoryVideoDecodeStatsDBImpl::OnGotSeedDB,
weak_ptr_factory_.GetWeakPtr(), std::move(init_cb)));
} else {
// No seed DB provider (e.g. guest session) means no work to do.
DVLOG(2) << __func__ << " NO seed db";
db_init_ = true;
// Bind to avoid reentrancy.
std::move(BindToCurrentLoop(std::move(init_cb))).Run(true);
}
}
void InMemoryVideoDecodeStatsDBImpl::OnGotSeedDB(InitializeCB init_cb,
VideoDecodeStatsDB* db) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(2) << __func__ << (db ? " has" : " null") << " seed db";
db_init_ = true;
CHECK(!seed_db_) << __func__ << " Already have a seed_db_?";
seed_db_ = db;
if (seed_db_)
seed_db_->set_dependent_db(this);
// Hard coding success = true. There are rare cases (e.g. disk corruption)
// where an incognito profile may fail to acquire a reference to the base
// profile's DB. But this just means incognito is in the same boat as guest
// profiles (never have a seed DB) and is not a show stopper.
std::move(init_cb).Run(true);
}
void InMemoryVideoDecodeStatsDBImpl::AppendDecodeStats(
const VideoDescKey& key,
const DecodeStatsEntry& entry,
AppendDecodeStatsCB append_done_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(db_init_);
DVLOG(3) << __func__ << " Reading key " << key.ToLogString()
<< " from DB with intent to update with " << entry.ToLogString();
auto it = in_memory_db_.find(key.Serialize());
if (it == in_memory_db_.end()) {
if (seed_db_) {
// |seed_db_| exists and no in-memory entry is found for this key, means
// we haven't checked the |seed_db_| yet. Query |seed_db_| and append new
// stats to any seed values.
seed_db_->GetDecodeStats(
key, base::BindOnce(
&InMemoryVideoDecodeStatsDBImpl::CompleteAppendWithSeedData,
weak_ptr_factory_.GetWeakPtr(), key, entry,
std::move(append_done_cb)));
return;
}
// Otherwise, these are the first stats for this key. Add a a copy of
// |entry| to the database.
in_memory_db_.emplace(key.Serialize(), entry);
} else {
// We've already asked the |seed_db_| for its data. Just add the new stats
// to our local copy via the iterators reference.
it->second += entry;
}
// Bind to avoid reentrancy.
std::move(BindToCurrentLoop(std::move(append_done_cb))).Run(true);
}
void InMemoryVideoDecodeStatsDBImpl::GetDecodeStats(
const VideoDescKey& key,
GetDecodeStatsCB get_stats_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(db_init_);
DVLOG(3) << __func__ << " " << key.ToLogString();
auto it = in_memory_db_.find(key.Serialize());
if (it == in_memory_db_.end()) {
if (seed_db_) {
// |seed_db_| exists and no in-memory entry is found for this key, means
// we haven't checked the |seed_db_| yet.
seed_db_->GetDecodeStats(
key, base::BindOnce(&InMemoryVideoDecodeStatsDBImpl::OnGotSeedEntry,
weak_ptr_factory_.GetWeakPtr(), key,
std::move(get_stats_cb)));
} else {
// No seed data. Return an empty entry. Bind to avoid reentrancy.
std::move(BindToCurrentLoop(std::move(get_stats_cb)))
.Run(true, std::make_unique<DecodeStatsEntry>(0, 0, 0));
}
} else {
// Return whatever what we found. Bind to avoid reentrancy.
std::move(BindToCurrentLoop(std::move(get_stats_cb)))
.Run(true, std::make_unique<DecodeStatsEntry>(it->second));
}
}
void InMemoryVideoDecodeStatsDBImpl::CompleteAppendWithSeedData(
const VideoDescKey& key,
const DecodeStatsEntry& entry,
AppendDecodeStatsCB append_done_cb,
bool read_success,
std::unique_ptr<DecodeStatsEntry> seed_entry) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(db_init_);
if (!read_success) {
// Not a show stopper. Log it and carry on as if the seed DB were empty.
DVLOG(2) << __func__ << " FAILED seed DB read for " << key.ToLogString();
DCHECK(!seed_entry);
}
if (!seed_entry)
seed_entry = std::make_unique<DecodeStatsEntry>(0, 0, 0);
// Add new stats to the seed entry and store in memory.
*seed_entry += entry;
in_memory_db_.emplace(key.Serialize(), *seed_entry);
DVLOG(3) << __func__ << " Updating " << key.ToLogString() << " with "
<< entry.ToLogString() << " aggregate:" << seed_entry->ToLogString();
std::move(append_done_cb).Run(true);
}
void InMemoryVideoDecodeStatsDBImpl::OnGotSeedEntry(
const VideoDescKey& key,
GetDecodeStatsCB get_stats_cb,
bool success,
std::unique_ptr<DecodeStatsEntry> seed_entry) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Failure is not a show stopper. Just a debug log...
DVLOG(3) << __func__ << " read " << (success ? "succeeded" : "FAILED!")
<< " entry: " << (seed_entry ? seed_entry->ToLogString() : "null");
if (!seed_entry)
seed_entry = std::make_unique<DecodeStatsEntry>(0, 0, 0);
// Always write to |in_memory_db_| to avoid querying |seed_db_| for this key
// going forward.
in_memory_db_.emplace(key.Serialize(), *seed_entry);
std::move(get_stats_cb).Run(true, std::move(seed_entry));
}
void InMemoryVideoDecodeStatsDBImpl::ClearStats(
base::OnceClosure destroy_done_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(2) << __func__;
// Really, this is not reachable code because user's can't clear the history
// for a guest/incognito account. But if that ever changes, the reasonable
// thing is to wipe only the |in_memory_db_|. |seed_db_| can be cleared by the
// profile that owns it.
in_memory_db_.clear();
// Bind to avoid reentrancy.
std::move(BindToCurrentLoop(std::move(destroy_done_cb))).Run();
}
} // namespace media