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
ash / ambient / model / ambient_animation_photo_config.cc [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/ambient/model/ambient_animation_photo_config.h"
#include "ash/ambient/util/ambient_util.h"
#include "ash/utility/lottie_util.h"
#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "cc/paint/skottie_resource_metadata.h"
namespace ash {
namespace {
void ParseDynamicAssetsIdsInAnimation(
const cc::SkottieResourceMetadataMap& skottie_resource_metadata,
std::size_t& num_total_positions_out,
std::size_t& num_assets_per_position_out) {
base::flat_map<std::string, std::size_t> position_to_num_assets;
ambient::util::ParsedDynamicAssetId parsed_asset_id;
for (const auto& [asset_id, _] : skottie_resource_metadata.asset_storage()) {
if (!IsCustomizableLottieId(asset_id)) {
DVLOG(4) << "Ignoring static image asset id";
continue;
}
if (!ambient::util::ParseDynamicLottieAssetId(asset_id, parsed_asset_id)) {
NOTREACHED() << "Lottie file contains invalid dynamic asset id "
<< asset_id;
}
auto iter =
position_to_num_assets
.try_emplace(parsed_asset_id.position_id, /*initial count*/ 0)
.first;
++iter->second;
}
if (position_to_num_assets.empty()) {
num_total_positions_out = 0;
num_assets_per_position_out = 0;
return;
}
// Currently, it's expected that all positions in the animations have the same
// number of assets assigned to it. If this fails, the animation is invalid
// and must be updated by the designer as the rest of the pipeline was not
// designed with case in mind.
num_total_positions_out = position_to_num_assets.size();
num_assets_per_position_out = position_to_num_assets.begin()->second;
for (const auto& [position, num_assets_assigned] : position_to_num_assets) {
if (num_assets_assigned != num_assets_per_position_out) {
LOG(FATAL) << "Position " << position << " has " << num_assets_assigned
<< "assets. Expected " << num_assets_per_position_out;
}
}
}
} // namespace
ASH_EXPORT AmbientPhotoConfig CreateAmbientAnimationPhotoConfig(
const cc::SkottieResourceMetadataMap& skottie_resource_metadata) {
AmbientPhotoConfig config;
config.should_split_topics = true;
// Example: If there are 6 positions and 2 assets per position, this will
// initially prepare and buffer 6 * 2 = 12 topics. Afterwards, all future
// refreshes will prepare 6 topics, effectively giving each position a new
// topic.
ParseDynamicAssetsIdsInAnimation(
skottie_resource_metadata,
/*num_total_positions_out=*/config.topic_set_size,
/*num_assets_per_position_out=*/config.num_topic_sets_to_buffer);
// In the worst case scenario, the same topic can be replicated across all
// of the assets in the animation. The screen will not burn due to the jitter
// applied to the animation.
config.min_total_topics_required = 1;
// Once an animation cycle starts rendering (including the very first
// cycle), start preparing the next set of decoded topics for the next
// cycle. Unlike the slideshow view, this view waits until a new animation
// cycle starts, then pulls the most recent topics from the model at that
// time.
config.refresh_topic_markers = {AmbientPhotoConfig::Marker::kUiStartRendering,
AmbientPhotoConfig::Marker::kUiCycleEnded};
return config;
}
} // namespace ash