1 /*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "modules/skottie/include/Skottie.h"
9
10 #include "tests/Test.h"
11
12 using namespace skottie;
13 using namespace skresources;
14
DEF_TEST(Skottie_AudioLayer,r)15 DEF_TEST(Skottie_AudioLayer, r) {
16 static constexpr char json[] =
17 R"({
18 "v": "5.2.1",
19 "w": 100,
20 "h": 100,
21 "fr": 10,
22 "ip": 0,
23 "op": 100,
24 "assets": [
25 {
26 "id": "audio_0",
27 "p" : "audio.mp3",
28 "u" : "assets/"
29 }
30 ],
31 "layers": [
32 {
33 "ty" : 6,
34 "ind" : 0,
35 "ip" : 20,
36 "op" : 70,
37 "refId": "audio_0"
38 },
39 {
40 "ty" : 6,
41 "ind" : 0,
42 "ip" : 50,
43 "op" : 80,
44 "refId": "audio_0"
45 },
46 {
47 "ty": 1,
48 "ip": 0,
49 "op": 100,
50 "sw": 100,
51 "sh": 100,
52 "sc": "#ffffff"
53 }
54 ]
55 })";
56
57 class MockTracker final : public ExternalTrackAsset {
58 public:
59 bool isPlaying() const { return fCurrentTime >= 0; }
60 float currentTime() const { return fCurrentTime; }
61
62 private:
63 void seek(float t) override {
64 fCurrentTime = t;
65 }
66
67 float fCurrentTime = 0;
68 };
69
70 class MockResourceProvider final : public ResourceProvider {
71 public:
72 explicit MockResourceProvider(skiatest::Reporter* r) : fReporter(r) {}
73
74 const std::vector<sk_sp<MockTracker>>& tracks() const { return fTracks; }
75
76 private:
77 sk_sp<ExternalTrackAsset> loadAudioAsset(const char path[],
78 const char name[],
79 const char id[]) override {
80 REPORTER_ASSERT(fReporter, !strcmp(path, "assets/"));
81 REPORTER_ASSERT(fReporter, !strcmp(name, "audio.mp3"));
82 REPORTER_ASSERT(fReporter, !strcmp(id , "audio_0"));
83
84 fTracks.push_back(sk_make_sp<MockTracker>());
85
86 return fTracks.back();
87 }
88
89 skiatest::Reporter* fReporter;
90 std::vector<sk_sp<MockTracker>> fTracks;
91 };
92
93 SkMemoryStream stream(json, strlen(json));
94 auto rp = sk_make_sp<MockResourceProvider>(r);
95
96 auto skottie = skottie::Animation::Builder()
97 .setResourceProvider(rp)
98 .make(&stream);
99
100 const auto& tracks = rp->tracks();
101
102 REPORTER_ASSERT(r, skottie);
103 REPORTER_ASSERT(r, tracks.size() == 2);
104
105 skottie->seekFrame(0);
106 REPORTER_ASSERT(r, !tracks[0]->isPlaying());
107 REPORTER_ASSERT(r, !tracks[1]->isPlaying());
108
109 skottie->seekFrame(20);
110 REPORTER_ASSERT(r, tracks[0]->isPlaying());
111 REPORTER_ASSERT(r, !tracks[1]->isPlaying());
112 REPORTER_ASSERT(r, tracks[0]->currentTime() == 0);
113
114 skottie->seekFrame(50);
115 REPORTER_ASSERT(r, tracks[0]->isPlaying());
116 REPORTER_ASSERT(r, tracks[1]->isPlaying());
117 REPORTER_ASSERT(r, tracks[0]->currentTime() == 3);
118 REPORTER_ASSERT(r, tracks[1]->currentTime() == 0);
119
120 skottie->seekFrame(70);
121 REPORTER_ASSERT(r, tracks[0]->isPlaying());
122 REPORTER_ASSERT(r, tracks[1]->isPlaying());
123 REPORTER_ASSERT(r, tracks[0]->currentTime() == 5);
124 REPORTER_ASSERT(r, tracks[1]->currentTime() == 2);
125
126 skottie->seekFrame(80);
127 REPORTER_ASSERT(r, !tracks[0]->isPlaying());
128 REPORTER_ASSERT(r, tracks[1]->isPlaying());
129 REPORTER_ASSERT(r, tracks[1]->currentTime() == 3);
130
131 skottie->seekFrame(100);
132 REPORTER_ASSERT(r, !tracks[0]->isPlaying());
133 REPORTER_ASSERT(r, !tracks[1]->isPlaying());
134 }
135