[MSE] Removing samples when presentation order does not match decode order can cause...
[WebKit.git] / Tools / TestWebKitAPI / Tests / WebCore / SampleMap.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(MEDIA_SOURCE)
29
30 #include "Test.h"
31 #include <WebCore/MediaSample.h>
32 #include <WebCore/SampleMap.h>
33
34 namespace WTF {
35 inline std::ostream& operator<<(std::ostream& os, const MediaTime& time)
36 {
37     if (time.hasDoubleValue())
38         os << "{ " << time.toDouble() << " }";
39     else
40         os << "{ " << time.timeValue() << " / " << time.timeScale() << ", " << time.toDouble() << " }";
41     return os;
42 }
43 }
44
45 using namespace WebCore;
46
47 namespace TestWebKitAPI {
48
49 class TestSample : public MediaSample {
50 public:
51     static Ref<TestSample> create(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
52     {
53         return adoptRef(*new TestSample(presentationTime, decodeTime, duration, flags));
54     }
55     
56     MediaTime presentationTime() const final { return m_presentationTime; }
57     MediaTime decodeTime() const final { return m_decodeTime; }
58     MediaTime duration() const final { return m_duration; }
59     AtomicString trackID() const final { return m_trackID; }
60     void setTrackID(const String& trackID) final { m_trackID = trackID; }
61     size_t sizeInBytes() const final { return m_sizeInBytes; }
62     FloatSize presentationSize() const final { return m_presentationSize; }
63     void offsetTimestampsBy(const MediaTime& offset) final { m_presentationTime += offset; m_decodeTime += offset; }
64     void setTimestamps(const MediaTime& presentationTime, const MediaTime& decodeTime) final {
65         m_presentationTime = presentationTime;
66         m_decodeTime = decodeTime;
67     };
68     bool isDivisable() const final { return false; }
69     std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime& presentationTime) final { return { }; }
70     Ref<MediaSample> createNonDisplayingCopy() const final {
71         return create(m_presentationTime, m_decodeTime, m_duration, static_cast<SampleFlags>(m_flags | IsNonDisplaying));
72     }
73     SampleFlags flags() const final { return m_flags; }
74     PlatformSample platformSample() final { return { PlatformSample::None, {nullptr}}; }
75     void dump(PrintStream&) const final { }
76
77 private:
78     TestSample(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
79         : m_presentationTime(presentationTime)
80         , m_decodeTime(decodeTime)
81         , m_duration(duration)
82         , m_flags(flags)
83     {
84     }
85
86     MediaTime m_presentationTime;
87     MediaTime m_decodeTime;
88     MediaTime m_duration;
89     FloatSize m_presentationSize;
90     AtomicString m_trackID;
91     size_t m_sizeInBytes { 0 };
92     SampleFlags m_flags { None };
93 };
94
95 class SampleMapTest : public testing::Test {
96 public:
97     void SetUp() final {
98         map.addSample(TestSample::create(MediaTime(0, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
99         map.addSample(TestSample::create(MediaTime(1, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
100         map.addSample(TestSample::create(MediaTime(2, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
101         map.addSample(TestSample::create(MediaTime(3, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
102         map.addSample(TestSample::create(MediaTime(4, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
103         map.addSample(TestSample::create(MediaTime(5, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
104         map.addSample(TestSample::create(MediaTime(6, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
105         map.addSample(TestSample::create(MediaTime(7, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
106         map.addSample(TestSample::create(MediaTime(8, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
107         map.addSample(TestSample::create(MediaTime(9, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
108         // Gap at MediaTime(10, 1) -> MediaTime(11, 1);
109         map.addSample(TestSample::create(MediaTime(11, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
110         map.addSample(TestSample::create(MediaTime(12, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
111         map.addSample(TestSample::create(MediaTime(13, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
112         map.addSample(TestSample::create(MediaTime(14, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
113         map.addSample(TestSample::create(MediaTime(15, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
114         map.addSample(TestSample::create(MediaTime(16, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
115         map.addSample(TestSample::create(MediaTime(17, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
116         map.addSample(TestSample::create(MediaTime(18, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
117         map.addSample(TestSample::create(MediaTime(19, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
118     }
119
120     SampleMap map;
121 };
122
123 TEST_F(SampleMapTest, findSampleWithPresentationTime)
124 {
125     auto& presentationMap = map.presentationOrder();
126     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleWithPresentationTime(MediaTime(0, 1))->second->presentationTime());
127     EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleWithPresentationTime(MediaTime(19, 1))->second->presentationTime());
128     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(-1, 1)));
129     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(10, 1)));
130     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(20, 1)));
131     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(1, 2)));
132 }
133
134 TEST_F(SampleMapTest, findSampleContainingPresentationTime)
135 {
136     auto& presentationMap = map.presentationOrder();
137     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(0, 1))->second->presentationTime());
138     EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(19, 1))->second->presentationTime());
139     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(1, 2))->second->presentationTime());
140     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(-1, 1)));
141     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(10, 1)));
142     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
143 }
144
145 TEST_F(SampleMapTest, findSampleStartingOnOrAfterPresentationTime)
146 {
147     auto& presentationMap = map.presentationOrder();
148     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(0, 1))->second->presentationTime());
149     EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(19, 1))->second->presentationTime());
150     EXPECT_EQ(MediaTime(1, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(1, 2))->second->presentationTime());
151     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(-1, 1))->second->presentationTime());
152     EXPECT_EQ(MediaTime(11, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(10, 1))->second->presentationTime());
153     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
154 }
155
156 TEST_F(SampleMapTest, findSampleContainingOrAfterPresentationTime)
157 {
158     auto& presentationMap = map.presentationOrder();
159     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(0, 1))->second->presentationTime());
160     EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(19, 1))->second->presentationTime());
161     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(1, 2))->second->presentationTime());
162     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(-1, 1))->second->presentationTime());
163     EXPECT_EQ(MediaTime(11, 1), presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(10, 1))->second->presentationTime());
164     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingOrAfterPresentationTime(MediaTime(20, 1)));
165 }
166
167 TEST_F(SampleMapTest, findSampleStartingAfterPresentationTime)
168 {
169     auto& presentationMap = map.presentationOrder();
170     EXPECT_EQ(MediaTime(1, 1), presentationMap.findSampleStartingAfterPresentationTime(MediaTime(0, 1))->second->presentationTime());
171     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleStartingAfterPresentationTime(MediaTime(19, 1)));
172     EXPECT_EQ(MediaTime(1, 1), presentationMap.findSampleStartingAfterPresentationTime(MediaTime(1, 2))->second->presentationTime());
173     EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingAfterPresentationTime(MediaTime(-1, 1))->second->presentationTime());
174     EXPECT_EQ(MediaTime(11, 1), presentationMap.findSampleStartingAfterPresentationTime(MediaTime(10, 1))->second->presentationTime());
175     EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleStartingAfterPresentationTime(MediaTime(20, 1)));
176 }
177 TEST_F(SampleMapTest, findSamplesBetweenPresentationTimes)
178 {
179     auto& presentationMap = map.presentationOrder();
180     auto iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(0, 1), MediaTime(1, 1));
181     EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
182     EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
183
184     iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(1, 2), MediaTime(3, 2));
185     EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
186     EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
187
188     iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(9, 1), MediaTime(21, 1));
189     EXPECT_EQ(MediaTime(9, 1), iterator_range.first->second->presentationTime());
190     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
191
192     iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(-1, 1), MediaTime(0, 1));
193     EXPECT_TRUE(presentationMap.end() == iterator_range.first);
194     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
195
196     iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(19, 2), MediaTime(10, 1));
197     EXPECT_TRUE(presentationMap.end() == iterator_range.first);
198     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
199
200     iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(20, 1), MediaTime(21, 1));
201     EXPECT_TRUE(presentationMap.end() == iterator_range.first);
202     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
203 }
204
205 TEST_F(SampleMapTest, findSamplesWithinPresentationRange)
206 {
207     auto& presentationMap = map.presentationOrder();
208     auto iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(0, 1), MediaTime(1, 1));
209     EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
210     EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
211
212     iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(1, 2), MediaTime(3, 2));
213     EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
214     EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
215
216     iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(9, 1), MediaTime(21, 1));
217     EXPECT_EQ(MediaTime(11, 1), iterator_range.first->second->presentationTime());
218     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
219
220     iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(-1, 1), MediaTime(0, 1));
221     EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
222     EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
223
224     iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(10, 1), MediaTime(21, 2));
225     EXPECT_TRUE(presentationMap.end() == iterator_range.first);
226     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
227
228     iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(20, 1), MediaTime(21, 1));
229     EXPECT_TRUE(presentationMap.end() == iterator_range.first);
230     EXPECT_TRUE(presentationMap.end() == iterator_range.second);
231 }
232
233 TEST_F(SampleMapTest, reverseFindSampleBeforePresentationTime)
234 {
235     auto& presentationMap = map.presentationOrder();
236     EXPECT_EQ(MediaTime(0, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(0, 1))->second->presentationTime());
237     EXPECT_EQ(MediaTime(9, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(10, 1))->second->presentationTime());
238     EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(19, 1))->second->presentationTime());
239     EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(21, 1))->second->presentationTime());
240     EXPECT_TRUE(presentationMap.rend() == presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(-1, 1)));
241 }
242
243 }
244
245 #endif // ENABLE(MEDIA_SOURCE)