in_memory_video_decode_stats_db_impl.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
  5. #include <memory>
  6. #include <tuple>
  7. #include "base/bind.h"
  8. #include "base/files/file_path.h"
  9. #include "base/format_macros.h"
  10. #include "base/logging.h"
  11. #include "base/metrics/histogram_macros.h"
  12. #include "base/sequence_checker.h"
  13. #include "media/base/bind_to_current_loop.h"
  14. #include "media/capabilities/video_decode_stats_db_provider.h"
  15. namespace media {
  16. InMemoryVideoDecodeStatsDBImpl::InMemoryVideoDecodeStatsDBImpl(
  17. VideoDecodeStatsDBProvider* seed_db_provider)
  18. : seed_db_provider_(seed_db_provider) {
  19. DVLOG(2) << __func__;
  20. }
  21. InMemoryVideoDecodeStatsDBImpl::~InMemoryVideoDecodeStatsDBImpl() {
  22. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  23. }
  24. void InMemoryVideoDecodeStatsDBImpl::Initialize(InitializeCB init_cb) {
  25. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  26. DCHECK(init_cb);
  27. DCHECK(!db_init_);
  28. // Tracking down crbug.com/1114128. Suspect we're double initializing somehow,
  29. // so this should show who the crash at the time of the second initialize
  30. // call.
  31. DCHECK(!seed_db_) << __func__ << " Already have a seed_db_?";
  32. // Fetch an *initialized* seed DB.
  33. if (seed_db_provider_) {
  34. seed_db_provider_->GetVideoDecodeStatsDB(
  35. base::BindOnce(&InMemoryVideoDecodeStatsDBImpl::OnGotSeedDB,
  36. weak_ptr_factory_.GetWeakPtr(), std::move(init_cb)));
  37. } else {
  38. // No seed DB provider (e.g. guest session) means no work to do.
  39. DVLOG(2) << __func__ << " NO seed db";
  40. db_init_ = true;
  41. // Bind to avoid reentrancy.
  42. std::move(BindToCurrentLoop(std::move(init_cb))).Run(true);
  43. }
  44. }
  45. void InMemoryVideoDecodeStatsDBImpl::OnGotSeedDB(InitializeCB init_cb,
  46. VideoDecodeStatsDB* db) {
  47. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  48. DVLOG(2) << __func__ << (db ? " has" : " null") << " seed db";
  49. db_init_ = true;
  50. DCHECK(!seed_db_) << __func__ << " Already have a seed_db_?";
  51. seed_db_ = db;
  52. // Hard coding success = true. There are rare cases (e.g. disk corruption)
  53. // where an incognito profile may fail to acquire a reference to the base
  54. // profile's DB. But this just means incognito is in the same boat as guest
  55. // profiles (never have a seed DB) and is not a show stopper.
  56. std::move(init_cb).Run(true);
  57. }
  58. void InMemoryVideoDecodeStatsDBImpl::AppendDecodeStats(
  59. const VideoDescKey& key,
  60. const DecodeStatsEntry& entry,
  61. AppendDecodeStatsCB append_done_cb) {
  62. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  63. DCHECK(db_init_);
  64. DVLOG(3) << __func__ << " Reading key " << key.ToLogString()
  65. << " from DB with intent to update with " << entry.ToLogString();
  66. auto it = in_memory_db_.find(key.Serialize());
  67. if (it == in_memory_db_.end()) {
  68. if (seed_db_) {
  69. // |seed_db_| exists and no in-memory entry is found for this key, means
  70. // we haven't checked the |seed_db_| yet. Query |seed_db_| and append new
  71. // stats to any seed values.
  72. seed_db_->GetDecodeStats(
  73. key, base::BindOnce(
  74. &InMemoryVideoDecodeStatsDBImpl::CompleteAppendWithSeedData,
  75. weak_ptr_factory_.GetWeakPtr(), key, entry,
  76. std::move(append_done_cb)));
  77. return;
  78. }
  79. // Otherwise, these are the first stats for this key. Add a a copy of
  80. // |entry| to the database.
  81. in_memory_db_.emplace(key.Serialize(), entry);
  82. } else {
  83. // We've already asked the |seed_db_| for its data. Just add the new stats
  84. // to our local copy via the iterators reference.
  85. it->second += entry;
  86. }
  87. // Bind to avoid reentrancy.
  88. std::move(BindToCurrentLoop(std::move(append_done_cb))).Run(true);
  89. }
  90. void InMemoryVideoDecodeStatsDBImpl::GetDecodeStats(
  91. const VideoDescKey& key,
  92. GetDecodeStatsCB get_stats_cb) {
  93. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  94. DCHECK(db_init_);
  95. DVLOG(3) << __func__ << " " << key.ToLogString();
  96. auto it = in_memory_db_.find(key.Serialize());
  97. if (it == in_memory_db_.end()) {
  98. if (seed_db_) {
  99. // |seed_db_| exists and no in-memory entry is found for this key, means
  100. // we haven't checked the |seed_db_| yet.
  101. seed_db_->GetDecodeStats(
  102. key, base::BindOnce(&InMemoryVideoDecodeStatsDBImpl::OnGotSeedEntry,
  103. weak_ptr_factory_.GetWeakPtr(), key,
  104. std::move(get_stats_cb)));
  105. } else {
  106. // No seed data. Return an empty entry. Bind to avoid reentrancy.
  107. std::move(BindToCurrentLoop(std::move(get_stats_cb)))
  108. .Run(true, std::make_unique<DecodeStatsEntry>(0, 0, 0));
  109. }
  110. } else {
  111. // Return whatever what we found. Bind to avoid reentrancy.
  112. std::move(BindToCurrentLoop(std::move(get_stats_cb)))
  113. .Run(true, std::make_unique<DecodeStatsEntry>(it->second));
  114. }
  115. }
  116. void InMemoryVideoDecodeStatsDBImpl::CompleteAppendWithSeedData(
  117. const VideoDescKey& key,
  118. const DecodeStatsEntry& entry,
  119. AppendDecodeStatsCB append_done_cb,
  120. bool read_success,
  121. std::unique_ptr<DecodeStatsEntry> seed_entry) {
  122. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  123. DCHECK(db_init_);
  124. if (!read_success) {
  125. // Not a show stopper. Log it and carry on as if the seed DB were empty.
  126. DVLOG(2) << __func__ << " FAILED seed DB read for " << key.ToLogString();
  127. DCHECK(!seed_entry);
  128. }
  129. if (!seed_entry)
  130. seed_entry = std::make_unique<DecodeStatsEntry>(0, 0, 0);
  131. // Add new stats to the seed entry and store in memory.
  132. *seed_entry += entry;
  133. in_memory_db_.emplace(key.Serialize(), *seed_entry);
  134. DVLOG(3) << __func__ << " Updating " << key.ToLogString() << " with "
  135. << entry.ToLogString() << " aggregate:" << seed_entry->ToLogString();
  136. std::move(append_done_cb).Run(true);
  137. }
  138. void InMemoryVideoDecodeStatsDBImpl::OnGotSeedEntry(
  139. const VideoDescKey& key,
  140. GetDecodeStatsCB get_stats_cb,
  141. bool success,
  142. std::unique_ptr<DecodeStatsEntry> seed_entry) {
  143. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  144. // Failure is not a show stopper. Just a debug log...
  145. DVLOG(3) << __func__ << " read " << (success ? "succeeded" : "FAILED!")
  146. << " entry: " << (seed_entry ? seed_entry->ToLogString() : "null");
  147. if (!seed_entry)
  148. seed_entry = std::make_unique<DecodeStatsEntry>(0, 0, 0);
  149. // Always write to |in_memory_db_| to avoid querying |seed_db_| for this key
  150. // going forward.
  151. in_memory_db_.emplace(key.Serialize(), *seed_entry);
  152. std::move(get_stats_cb).Run(true, std::move(seed_entry));
  153. }
  154. void InMemoryVideoDecodeStatsDBImpl::ClearStats(
  155. base::OnceClosure destroy_done_cb) {
  156. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  157. DVLOG(2) << __func__;
  158. // Really, this is not reachable code because user's can't clear the history
  159. // for a guest/incognito account. But if that ever changes, the reasonable
  160. // thing is to wipe only the |in_memory_db_|. |seed_db_| can be cleared by the
  161. // profile that owns it.
  162. in_memory_db_.clear();
  163. // Bind to avoid reentrancy.
  164. std::move(BindToCurrentLoop(std::move(destroy_done_cb))).Run();
  165. }
  166. } // namespace media