123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- // 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 "media/base/bind_to_current_loop.h"
- #include "media/capabilities/video_decode_stats_db_provider.h"
- namespace media {
- InMemoryVideoDecodeStatsDBImpl::InMemoryVideoDecodeStatsDBImpl(
- VideoDecodeStatsDBProvider* seed_db_provider)
- : seed_db_provider_(seed_db_provider) {
- DVLOG(2) << __func__;
- }
- InMemoryVideoDecodeStatsDBImpl::~InMemoryVideoDecodeStatsDBImpl() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- }
- void InMemoryVideoDecodeStatsDBImpl::Initialize(InitializeCB init_cb) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(init_cb);
- DCHECK(!db_init_);
- // Tracking down crbug.com/1114128. Suspect we're double initializing somehow,
- // so this should show who the crash at the time of the second initialize
- // call.
- DCHECK(!seed_db_) << __func__ << " Already have a seed_db_?";
- // 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;
- DCHECK(!seed_db_) << __func__ << " Already have a seed_db_?";
- seed_db_ = db;
- // 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
|