1/*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#pragma once
33
34#if ENABLE(MEDIA_SOURCE)
35
36#include "ActiveDOMObject.h"
37#include "AudioTrack.h"
38#include "EventTarget.h"
39#include "ExceptionOr.h"
40#include "GenericEventQueue.h"
41#include "SourceBufferPrivateClient.h"
42#include "TextTrack.h"
43#include "Timer.h"
44#include "VideoTrack.h"
45#include <wtf/LoggerHelper.h>
46
47namespace WebCore {
48
49class AudioTrackList;
50class BufferSource;
51class MediaSource;
52class PlatformTimeRanges;
53class SourceBufferPrivate;
54class TextTrackList;
55class TimeRanges;
56class VideoTrackList;
57
58class SourceBuffer final
59 : public RefCounted<SourceBuffer>
60 , public ActiveDOMObject
61 , public EventTargetWithInlineData
62 , private SourceBufferPrivateClient
63 , private AudioTrackClient
64 , private VideoTrackClient
65 , private TextTrackClient
66#if !RELEASE_LOG_DISABLED
67 , private LoggerHelper
68#endif
69{
70 WTF_MAKE_ISO_ALLOCATED(SourceBuffer);
71public:
72 static Ref<SourceBuffer> create(Ref<SourceBufferPrivate>&&, MediaSource*);
73 virtual ~SourceBuffer();
74
75 bool updating() const { return m_updating; }
76 ExceptionOr<Ref<TimeRanges>> buffered() const;
77 double timestampOffset() const;
78 ExceptionOr<void> setTimestampOffset(double);
79
80#if ENABLE(VIDEO_TRACK)
81 VideoTrackList& videoTracks();
82 AudioTrackList& audioTracks();
83 TextTrackList& textTracks();
84#endif
85
86 double appendWindowStart() const;
87 ExceptionOr<void> setAppendWindowStart(double);
88 double appendWindowEnd() const;
89 ExceptionOr<void> setAppendWindowEnd(double);
90
91 ExceptionOr<void> appendBuffer(const BufferSource&);
92 ExceptionOr<void> abort();
93 ExceptionOr<void> remove(double start, double end);
94 ExceptionOr<void> remove(const MediaTime&, const MediaTime&);
95 ExceptionOr<void> changeType(const String&);
96
97 const TimeRanges& bufferedInternal() const { ASSERT(m_buffered); return *m_buffered; }
98
99 void abortIfUpdating();
100 void removedFromMediaSource();
101 void seekToTime(const MediaTime&);
102
103 bool canPlayThroughRange(PlatformTimeRanges&);
104
105 bool hasVideo() const;
106
107 bool active() const { return m_active; }
108
109 ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
110
111 using RefCounted::ref;
112 using RefCounted::deref;
113
114 struct TrackBuffer;
115
116 Document& document() const;
117
118 enum class AppendMode { Segments, Sequence };
119 AppendMode mode() const { return m_mode; }
120 ExceptionOr<void> setMode(AppendMode);
121
122 void setShouldGenerateTimestamps(bool flag) { m_shouldGenerateTimestamps = flag; }
123
124 bool isBufferedDirty() const { return m_bufferedDirty; }
125 void setBufferedDirty(bool flag) { m_bufferedDirty = flag; }
126
127 MediaTime highestPresentationTimestamp() const;
128 void readyStateChanged();
129
130 bool hasPendingActivity() const final;
131
132 void trySignalAllSamplesEnqueued();
133
134#if !RELEASE_LOG_DISABLED
135 const Logger& logger() const final { return m_logger.get(); }
136 const void* logIdentifier() const final { return m_logIdentifier; }
137 const char* logClassName() const final { return "SourceBuffer"; }
138 WTFLogChannel& logChannel() const final;
139#endif
140
141private:
142 SourceBuffer(Ref<SourceBufferPrivate>&&, MediaSource*);
143
144 void refEventTarget() final { ref(); }
145 void derefEventTarget() final { deref(); }
146
147 void suspend(ReasonForSuspension) final;
148 void resume() final;
149 void stop() final;
150 const char* activeDOMObjectName() const final;
151 bool canSuspendForDocumentSuspension() const final;
152
153 void sourceBufferPrivateDidReceiveInitializationSegment(const InitializationSegment&) final;
154 void sourceBufferPrivateDidReceiveSample(MediaSample&) final;
155 bool sourceBufferPrivateHasAudio() const final;
156 bool sourceBufferPrivateHasVideo() const final;
157 void sourceBufferPrivateReenqueSamples(const AtomString& trackID) final;
158 void sourceBufferPrivateDidBecomeReadyForMoreSamples(const AtomString& trackID) final;
159 MediaTime sourceBufferPrivateFastSeekTimeForMediaTime(const MediaTime&, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold) final;
160 void sourceBufferPrivateAppendComplete(AppendResult) final;
161 void sourceBufferPrivateDidReceiveRenderingError(int errorCode) final;
162
163 void audioTrackEnabledChanged(AudioTrack&) final;
164 void videoTrackSelectedChanged(VideoTrack&) final;
165
166 void textTrackKindChanged(TextTrack&) final;
167 void textTrackModeChanged(TextTrack&) final;
168 void textTrackAddCues(TextTrack&, const TextTrackCueList&) final;
169 void textTrackRemoveCues(TextTrack&, const TextTrackCueList&) final;
170 void textTrackAddCue(TextTrack&, TextTrackCue&) final;
171 void textTrackRemoveCue(TextTrack&, TextTrackCue&) final;
172
173 EventTargetInterface eventTargetInterface() const final { return SourceBufferEventTargetInterfaceType; }
174
175 bool isRemoved() const;
176 void scheduleEvent(const AtomString& eventName);
177
178 ExceptionOr<void> appendBufferInternal(const unsigned char*, unsigned);
179 void appendBufferTimerFired();
180 void resetParserState();
181
182 void setActive(bool);
183
184 bool validateInitializationSegment(const InitializationSegment&);
185
186 void reenqueueMediaForTime(TrackBuffer&, const AtomString& trackID, const MediaTime&);
187 void provideMediaData(TrackBuffer&, const AtomString& trackID);
188 void didDropSample();
189 void evictCodedFrames(size_t newDataSize);
190 size_t maximumBufferSize() const;
191
192 void monitorBufferingRate();
193
194 void removeTimerFired();
195 void removeCodedFrames(const MediaTime& start, const MediaTime& end);
196
197 size_t extraMemoryCost() const;
198 void reportExtraMemoryAllocated();
199
200 void updateBufferedFromTrackBuffers();
201
202 void appendError(bool);
203
204 bool hasAudio() const;
205
206 void rangeRemoval(const MediaTime&, const MediaTime&);
207
208 void trySignalAllSamplesInTrackEnqueued(const AtomString&);
209
210 friend class Internals;
211 WEBCORE_EXPORT Vector<String> bufferedSamplesForTrackID(const AtomString&);
212 WEBCORE_EXPORT Vector<String> enqueuedSamplesForTrackID(const AtomString&);
213
214 Ref<SourceBufferPrivate> m_private;
215 MediaSource* m_source;
216 GenericEventQueue m_asyncEventQueue;
217 AppendMode m_mode { AppendMode::Segments };
218
219 Vector<unsigned char> m_pendingAppendData;
220 Timer m_appendBufferTimer;
221
222 RefPtr<VideoTrackList> m_videoTracks;
223 RefPtr<AudioTrackList> m_audioTracks;
224 RefPtr<TextTrackList> m_textTracks;
225
226 Vector<AtomString> m_videoCodecs;
227 Vector<AtomString> m_audioCodecs;
228 Vector<AtomString> m_textCodecs;
229
230 MediaTime m_timestampOffset;
231 MediaTime m_appendWindowStart;
232 MediaTime m_appendWindowEnd;
233
234 MediaTime m_groupStartTimestamp;
235 MediaTime m_groupEndTimestamp;
236
237 HashMap<AtomString, TrackBuffer> m_trackBufferMap;
238 RefPtr<TimeRanges> m_buffered;
239 bool m_bufferedDirty { true };
240
241 enum AppendStateType { WaitingForSegment, ParsingInitSegment, ParsingMediaSegment };
242 AppendStateType m_appendState;
243
244 MonotonicTime m_timeOfBufferingMonitor;
245 double m_bufferedSinceLastMonitor { 0 };
246 double m_averageBufferRate { 0 };
247
248 size_t m_reportedExtraMemoryCost { 0 };
249
250 MediaTime m_pendingRemoveStart;
251 MediaTime m_pendingRemoveEnd;
252 Timer m_removeTimer;
253
254#if !RELEASE_LOG_DISABLED
255 Ref<const Logger> m_logger;
256 const void* m_logIdentifier;
257#endif
258
259 bool m_updating { false };
260 bool m_receivedFirstInitializationSegment { false };
261 bool m_active { false };
262 bool m_bufferFull { false };
263 bool m_shouldGenerateTimestamps { false };
264 bool m_pendingInitializationSegmentForChangeType { false };
265};
266
267} // namespace WebCore
268
269#endif
270