1/* 2 * Copyright (C) 2013-2014 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/PrintStream.h> 42 43namespace WebCore { 44 45class MockMediaSample final : public MediaSample { 46public: 47 static RefPtr<MockMediaSample> create(const MockSampleBox& box) { return adoptRef(new MockMediaSample(box)); } 48 virtual ~MockMediaSample() { } 49 50private: 51 MockMediaSample(const MockSampleBox& box) 52 : m_box(box) 53 , m_id(String::format("%d", box.trackID())) 54 { 55 } 56 57 virtual MediaTime presentationTime() const override { return m_box.presentationTimestamp(); } 58 virtual MediaTime decodeTime() const override { return m_box.decodeTimestamp(); } 59 virtual MediaTime duration() const override { return m_box.duration(); } 60 virtual AtomicString trackID() const override { return m_id; } 61 virtual size_t sizeInBytes() const override { return sizeof(m_box); } 62 virtual SampleFlags flags() const override; 63 virtual PlatformSample platformSample() override; 64 virtual FloatSize presentationSize() const override { return FloatSize(); } 65 virtual void dump(PrintStream&) const override; 66 67 unsigned generation() const { return m_box.generation(); } 68 69 MockSampleBox m_box; 70 AtomicString m_id; 71}; 72 73MediaSample::SampleFlags MockMediaSample::flags() const 74{ 75 unsigned flags = None; 76 if (m_box.flags() & MockSampleBox::IsSync) 77 flags |= IsSync; 78 return SampleFlags(flags); 79} 80 81PlatformSample MockMediaSample::platformSample() 82{ 83 PlatformSample sample = { PlatformSample::MockSampleBoxType, { &m_box } }; 84 return sample; 85} 86 87void MockMediaSample::dump(PrintStream& out) const 88{ 89 out.print("{PTS(", presentationTime(), "), DTS(", decodeTime(), "), duration(", duration(), "), flags(", (int)flags(), "), generation(", generation(), ")}"); 90} 91 92class MockMediaDescription final : public MediaDescription { 93public: 94 static RefPtr<MockMediaDescription> create(const MockTrackBox& box) { return adoptRef(new MockMediaDescription(box)); } 95 virtual ~MockMediaDescription() { } 96 97 virtual AtomicString codec() const override { return m_box.codec(); } 98 virtual bool isVideo() const override { return m_box.kind() == MockTrackBox::Video; } 99 virtual bool isAudio() const override { return m_box.kind() == MockTrackBox::Audio; } 100 virtual bool isText() const override { return m_box.kind() == MockTrackBox::Text; } 101 102protected: 103 MockMediaDescription(const MockTrackBox& box) : m_box(box) { } 104 MockTrackBox m_box; 105}; 106 107RefPtr<MockSourceBufferPrivate> MockSourceBufferPrivate::create(MockMediaSourcePrivate* parent) 108{ 109 return adoptRef(new MockSourceBufferPrivate(parent)); 110} 111 112MockSourceBufferPrivate::MockSourceBufferPrivate(MockMediaSourcePrivate* parent) 113 : m_mediaSource(parent) 114 , m_client(0) 115{ 116} 117 118MockSourceBufferPrivate::~MockSourceBufferPrivate() 119{ 120} 121 122void MockSourceBufferPrivate::setClient(SourceBufferPrivateClient* client) 123{ 124 m_client = client; 125} 126 127void MockSourceBufferPrivate::append(const unsigned char* data, unsigned length) 128{ 129 m_inputBuffer.append(data, length); 130 SourceBufferPrivateClient::AppendResult result = SourceBufferPrivateClient::AppendSucceeded; 131 132 while (m_inputBuffer.size() && result == SourceBufferPrivateClient::AppendSucceeded) { 133 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_inputBuffer.data(), m_inputBuffer.size()); 134 size_t boxLength = MockBox::peekLength(buffer.get()); 135 if (boxLength > buffer->byteLength()) 136 break; 137 138 String type = MockBox::peekType(buffer.get()); 139 if (type == MockInitializationBox::type()) { 140 MockInitializationBox initBox = MockInitializationBox(buffer.get()); 141 didReceiveInitializationSegment(initBox); 142 } else if (type == MockSampleBox::type()) { 143 MockSampleBox sampleBox = MockSampleBox(buffer.get()); 144 didReceiveSample(sampleBox); 145 } else 146 result = SourceBufferPrivateClient::ParsingFailed; 147 148 m_inputBuffer.remove(0, boxLength); 149 } 150 151 if (m_client) 152 m_client->sourceBufferPrivateAppendComplete(this, result); 153} 154 155void MockSourceBufferPrivate::didReceiveInitializationSegment(const MockInitializationBox& initBox) 156{ 157 if (!m_client) 158 return; 159 160 SourceBufferPrivateClient::InitializationSegment segment; 161 segment.duration = initBox.duration(); 162 163 for (auto it = initBox.tracks().begin(); it != initBox.tracks().end(); ++it) { 164 const MockTrackBox& trackBox = *it; 165 if (trackBox.kind() == MockTrackBox::Video) { 166 SourceBufferPrivateClient::InitializationSegment::VideoTrackInformation info; 167 info.track = MockVideoTrackPrivate::create(trackBox); 168 info.description = MockMediaDescription::create(trackBox); 169 segment.videoTracks.append(info); 170 } else if (trackBox.kind() == MockTrackBox::Audio) { 171 SourceBufferPrivateClient::InitializationSegment::AudioTrackInformation info; 172 info.track = MockAudioTrackPrivate::create(trackBox); 173 info.description = MockMediaDescription::create(trackBox); 174 segment.audioTracks.append(info); 175 } else if (trackBox.kind() == MockTrackBox::Text) { 176 SourceBufferPrivateClient::InitializationSegment::TextTrackInformation info; 177 info.track = MockTextTrackPrivate::create(trackBox); 178 info.description = MockMediaDescription::create(trackBox); 179 segment.textTracks.append(info); 180 } 181 } 182 183 m_client->sourceBufferPrivateDidReceiveInitializationSegment(this, segment); 184} 185 186 187void MockSourceBufferPrivate::didReceiveSample(const MockSampleBox& sampleBox) 188{ 189 if (!m_client) 190 return; 191 192 m_client->sourceBufferPrivateDidReceiveSample(this, MockMediaSample::create(sampleBox)); 193} 194 195void MockSourceBufferPrivate::abort() 196{ 197} 198 199void MockSourceBufferPrivate::removedFromMediaSource() 200{ 201 if (m_mediaSource) 202 m_mediaSource->removeSourceBuffer(this); 203} 204 205MediaPlayer::ReadyState MockSourceBufferPrivate::readyState() const 206{ 207 return m_mediaSource ? m_mediaSource->player()->readyState() : MediaPlayer::HaveNothing; 208} 209 210void MockSourceBufferPrivate::setReadyState(MediaPlayer::ReadyState readyState) 211{ 212 if (m_mediaSource) 213 m_mediaSource->player()->setReadyState(readyState); 214} 215 216void MockSourceBufferPrivate::setActive(bool isActive) 217{ 218 if (m_mediaSource) 219 m_mediaSource->sourceBufferPrivateDidChangeActiveState(this, isActive); 220} 221 222void MockSourceBufferPrivate::enqueueSample(PassRefPtr<MediaSample> sample, AtomicString) 223{ 224 if (!m_mediaSource || !sample) 225 return; 226 227 PlatformSample platformSample = sample->platformSample(); 228 if (platformSample.type != PlatformSample::MockSampleBoxType) 229 return; 230 231 MockSampleBox* box = platformSample.sample.mockSampleBox; 232 if (!box) 233 return; 234 235 m_mediaSource->incrementTotalVideoFrames(); 236 if (box->isCorrupted()) 237 m_mediaSource->incrementCorruptedFrames(); 238 if (box->isDropped()) 239 m_mediaSource->incrementDroppedFrames(); 240 if (box->isDelayed()) 241 m_mediaSource->incrementTotalFrameDelayBy(1); 242} 243 244bool MockSourceBufferPrivate::hasVideo() const 245{ 246 if (!m_client) 247 return false; 248 249 return m_client->sourceBufferPrivateHasVideo(this); 250} 251 252bool MockSourceBufferPrivate::hasAudio() const 253{ 254 if (!m_client) 255 return false; 256 257 return m_client->sourceBufferPrivateHasAudio(this); 258} 259 260 261MediaTime MockSourceBufferPrivate::fastSeekTimeForMediaTime(const MediaTime& time, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold) 262{ 263 if (m_client) 264 return m_client->sourceBufferPrivateFastSeekTimeForMediaTime(this, time, negativeThreshold, positiveThreshold); 265 return time; 266} 267 268void MockSourceBufferPrivate::seekToTime(const MediaTime& time) 269{ 270 if (m_client) 271 m_client->sourceBufferPrivateSeekToTime(this, time); 272} 273 274} 275 276#endif 277 278