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