Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / platform / mock / mediasource / MockSourceBufferPrivate.cpp
1 /*
2  * Copyright (C) 2013-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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MockSourceBufferPrivate.h"
28
29 #if ENABLE(MEDIA_SOURCE)
30
31 #include "MediaDescription.h"
32 #include "MediaPlayer.h"
33 #include "MediaSample.h"
34 #include "MockBox.h"
35 #include "MockMediaPlayerMediaSource.h"
36 #include "MockMediaSourcePrivate.h"
37 #include "MockTracks.h"
38 #include "SourceBufferPrivateClient.h"
39 #include <map>
40 #include <runtime/ArrayBuffer.h>
41 #include <wtf/StringPrintStream.h>
42
43 namespace WebCore {
44
45 class MockMediaSample final : public MediaSample {
46 public:
47     static Ref<MockMediaSample> create(const MockSampleBox& box) { return adoptRef(*new MockMediaSample(box)); }
48     virtual ~MockMediaSample() = default;
49
50 private:
51     MockMediaSample(const MockSampleBox& box)
52         : m_box(box)
53         , m_id(String::format("%d", box.trackID()))
54     {
55     }
56
57     MediaTime presentationTime() const override { return m_box.presentationTimestamp(); }
58     MediaTime decodeTime() const override { return m_box.decodeTimestamp(); }
59     MediaTime duration() const override { return m_box.duration(); }
60     AtomicString trackID() const override { return m_id; }
61     void setTrackID(const String& id) override { m_id = id; }
62     size_t sizeInBytes() const override { return sizeof(m_box); }
63     SampleFlags flags() const override;
64     PlatformSample platformSample() override;
65     FloatSize presentationSize() const override { return FloatSize(); }
66     void dump(PrintStream&) const override;
67     void offsetTimestampsBy(const MediaTime& offset) override { m_box.offsetTimestampsBy(offset); }
68     void setTimestamps(const MediaTime& presentationTimestamp, const MediaTime& decodeTimestamp) override { m_box.setTimestamps(presentationTimestamp, decodeTimestamp); }
69     bool isDivisable() const override { return false; }
70     std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime&) override { return {nullptr, nullptr}; }
71     Ref<MediaSample> createNonDisplayingCopy() const override;
72
73     unsigned generation() const { return m_box.generation(); }
74
75     MockSampleBox m_box;
76     AtomicString m_id;
77 };
78
79 MediaSample::SampleFlags MockMediaSample::flags() const
80 {
81     unsigned flags = None;
82     if (m_box.isSync())
83         flags |= IsSync;
84     if (m_box.isNonDisplaying())
85         flags |= IsNonDisplaying;
86     return SampleFlags(flags);
87 }
88
89 PlatformSample MockMediaSample::platformSample()
90 {
91     PlatformSample sample = { PlatformSample::MockSampleBoxType, { &m_box } };
92     return sample;
93 }
94
95 void MockMediaSample::dump(PrintStream& out) const
96 {
97     out.print("{PTS(", presentationTime(), "), DTS(", decodeTime(), "), duration(", duration(), "), flags(", (int)flags(), "), generation(", generation(), ")}");
98 }
99
100 Ref<MediaSample> MockMediaSample::createNonDisplayingCopy() const
101 {
102     auto copy = MockMediaSample::create(m_box);
103     copy->m_box.setFlag(MockSampleBox::IsNonDisplaying);
104     return WTFMove(copy);
105 }
106
107 class MockMediaDescription final : public MediaDescription {
108 public:
109     static RefPtr<MockMediaDescription> create(const MockTrackBox& box) { return adoptRef(new MockMediaDescription(box)); }
110     virtual ~MockMediaDescription() = default;
111
112     AtomicString codec() const override { return m_box.codec(); }
113     bool isVideo() const override { return m_box.kind() == MockTrackBox::Video; }
114     bool isAudio() const override { return m_box.kind() == MockTrackBox::Audio; }
115     bool isText() const override { return m_box.kind() == MockTrackBox::Text; }
116
117 protected:
118     MockMediaDescription(const MockTrackBox& box) : m_box(box) { }
119     MockTrackBox m_box;
120 };
121
122 RefPtr<MockSourceBufferPrivate> MockSourceBufferPrivate::create(MockMediaSourcePrivate* parent)
123 {
124     return adoptRef(new MockSourceBufferPrivate(parent));
125 }
126
127 MockSourceBufferPrivate::MockSourceBufferPrivate(MockMediaSourcePrivate* parent)
128     : m_mediaSource(parent)
129     , m_client(0)
130 {
131 }
132
133 MockSourceBufferPrivate::~MockSourceBufferPrivate() = default;
134
135 void MockSourceBufferPrivate::setClient(SourceBufferPrivateClient* client)
136 {
137     m_client = client;
138 }
139
140 void MockSourceBufferPrivate::append(Vector<unsigned char>&& data)
141 {
142     m_inputBuffer.appendVector(data);
143     SourceBufferPrivateClient::AppendResult result = SourceBufferPrivateClient::AppendSucceeded;
144
145     while (m_inputBuffer.size() && result == SourceBufferPrivateClient::AppendSucceeded) {
146         RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_inputBuffer.data(), m_inputBuffer.size());
147         size_t boxLength = MockBox::peekLength(buffer.get());
148         if (boxLength > buffer->byteLength())
149             break;
150
151         String type = MockBox::peekType(buffer.get());
152         if (type == MockInitializationBox::type()) {
153             MockInitializationBox initBox = MockInitializationBox(buffer.get());
154             didReceiveInitializationSegment(initBox);
155         } else if (type == MockSampleBox::type()) {
156             MockSampleBox sampleBox = MockSampleBox(buffer.get());
157             didReceiveSample(sampleBox);
158         } else
159             result = SourceBufferPrivateClient::ParsingFailed;
160
161         m_inputBuffer.remove(0, boxLength);
162     }
163
164     if (m_client)
165         m_client->sourceBufferPrivateAppendComplete(result);
166 }
167
168 void MockSourceBufferPrivate::didReceiveInitializationSegment(const MockInitializationBox& initBox)
169 {
170     if (!m_client)
171         return;
172
173     SourceBufferPrivateClient::InitializationSegment segment;
174     segment.duration = initBox.duration();
175
176     for (auto it = initBox.tracks().begin(); it != initBox.tracks().end(); ++it) {
177         const MockTrackBox& trackBox = *it;
178         if (trackBox.kind() == MockTrackBox::Video) {
179             SourceBufferPrivateClient::InitializationSegment::VideoTrackInformation info;
180             info.track = MockVideoTrackPrivate::create(trackBox);
181             info.description = MockMediaDescription::create(trackBox);
182             segment.videoTracks.append(info);
183         } else if (trackBox.kind() == MockTrackBox::Audio) {
184             SourceBufferPrivateClient::InitializationSegment::AudioTrackInformation info;
185             info.track = MockAudioTrackPrivate::create(trackBox);
186             info.description = MockMediaDescription::create(trackBox);
187             segment.audioTracks.append(info);
188         } else if (trackBox.kind() == MockTrackBox::Text) {
189             SourceBufferPrivateClient::InitializationSegment::TextTrackInformation info;
190             info.track = MockTextTrackPrivate::create(trackBox);
191             info.description = MockMediaDescription::create(trackBox);
192             segment.textTracks.append(info);
193         }
194     }
195
196     m_client->sourceBufferPrivateDidReceiveInitializationSegment(segment);
197 }
198
199
200 void MockSourceBufferPrivate::didReceiveSample(const MockSampleBox& sampleBox)
201 {
202     if (!m_client)
203         return;
204
205     m_client->sourceBufferPrivateDidReceiveSample(MockMediaSample::create(sampleBox));
206 }
207
208 void MockSourceBufferPrivate::abort()
209 {
210 }
211
212 void MockSourceBufferPrivate::resetParserState()
213 {
214 }
215
216 void MockSourceBufferPrivate::removedFromMediaSource()
217 {
218     if (m_mediaSource)
219         m_mediaSource->removeSourceBuffer(this);
220 }
221
222 MediaPlayer::ReadyState MockSourceBufferPrivate::readyState() const
223 {
224     return m_mediaSource ? m_mediaSource->player()->readyState() : MediaPlayer::HaveNothing;
225 }
226
227 void MockSourceBufferPrivate::setReadyState(MediaPlayer::ReadyState readyState)
228 {
229     if (m_mediaSource)
230         m_mediaSource->player()->setReadyState(readyState);
231 }
232
233 void MockSourceBufferPrivate::setActive(bool isActive)
234 {
235     if (m_mediaSource)
236         m_mediaSource->sourceBufferPrivateDidChangeActiveState(this, isActive);
237 }
238
239 Vector<String> MockSourceBufferPrivate::enqueuedSamplesForTrackID(const AtomicString&)
240 {
241     return m_enqueuedSamples;
242 }
243
244 void MockSourceBufferPrivate::enqueueSample(Ref<MediaSample>&& sample, const AtomicString&)
245 {
246     if (!m_mediaSource)
247         return;
248
249     PlatformSample platformSample = sample->platformSample();
250     if (platformSample.type != PlatformSample::MockSampleBoxType)
251         return;
252
253     auto* box = platformSample.sample.mockSampleBox;
254     if (!box)
255         return;
256
257     m_mediaSource->incrementTotalVideoFrames();
258     if (box->isCorrupted())
259         m_mediaSource->incrementCorruptedFrames();
260     if (box->isDropped())
261         m_mediaSource->incrementDroppedFrames();
262     if (box->isDelayed())
263         m_mediaSource->incrementTotalFrameDelayBy(MediaTime(1, 1));
264
265     m_enqueuedSamples.append(toString(sample.get()));
266 }
267
268 bool MockSourceBufferPrivate::hasVideo() const
269 {
270     return m_client && m_client->sourceBufferPrivateHasVideo();
271 }
272
273 bool MockSourceBufferPrivate::hasAudio() const
274 {
275     return m_client && m_client->sourceBufferPrivateHasAudio();
276 }
277
278 MediaTime MockSourceBufferPrivate::fastSeekTimeForMediaTime(const MediaTime& time, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold)
279 {
280     if (m_client)
281         return m_client->sourceBufferPrivateFastSeekTimeForMediaTime(time, negativeThreshold, positiveThreshold);
282     return time;
283 }
284
285 void MockSourceBufferPrivate::seekToTime(const MediaTime& time)
286 {
287     if (m_client)
288         m_client->sourceBufferPrivateSeekToTime(time);
289 }
290
291 }
292
293 #endif
294