1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef MEDIA_FILTERS_SOURCE_BUFFER_STATE_H_
6 #define MEDIA_FILTERS_SOURCE_BUFFER_STATE_H_
7 
8 #include <list>
9 
10 #include "base/bind.h"
11 #include "base/macros.h"
12 #include "base/memory/memory_pressure_listener.h"
13 #include "media/base/audio_codecs.h"
14 #include "media/base/demuxer.h"
15 #include "media/base/demuxer_stream.h"
16 #include "media/base/media_export.h"
17 #include "media/base/media_log.h"
18 #include "media/base/stream_parser.h"
19 #include "media/base/stream_parser_buffer.h"
20 #include "media/base/video_codecs.h"
21 #include "media/filters/source_buffer_parse_warnings.h"
22 
23 namespace media {
24 
25 using base::TimeDelta;
26 
27 class ChunkDemuxerStream;
28 class FrameProcessor;
29 
30 // Contains state belonging to a source id.
31 class MEDIA_EXPORT SourceBufferState {
32  public:
33   // Callback signature used to create ChunkDemuxerStreams.
34   using CreateDemuxerStreamCB =
35       base::RepeatingCallback<ChunkDemuxerStream*(DemuxerStream::Type)>;
36 
37   using NewTextTrackCB = base::RepeatingCallback<void(ChunkDemuxerStream*,
38                                                       const TextTrackConfig&)>;
39 
40   SourceBufferState(std::unique_ptr<StreamParser> stream_parser,
41                     std::unique_ptr<FrameProcessor> frame_processor,
42                     CreateDemuxerStreamCB create_demuxer_stream_cb,
43                     MediaLog* media_log);
44 
45   ~SourceBufferState();
46 
47   void Init(StreamParser::InitCB init_cb,
48             const std::string& expected_codecs,
49             const StreamParser::EncryptedMediaInitDataCB&
50                 encrypted_media_init_data_cb,
51             NewTextTrackCB new_text_track_cb);
52 
53   // Reconfigures this source buffer to use |new_stream_parser|. Caller must
54   // first ensure that ResetParserState() was done to flush any pending frames
55   // from the old stream parser.
56   void ChangeType(std::unique_ptr<StreamParser> new_stream_parser,
57                   const std::string& new_expected_codecs);
58 
59   // Appends new data to the StreamParser.
60   // Returns true if the data was successfully appended. Returns false if an
61   // error occurred. |*timestamp_offset| is used and possibly updated by the
62   // append. |append_window_start| and |append_window_end| correspond to the MSE
63   // spec's similarly named source buffer attributes that are used in coded
64   // frame processing.
65   bool Append(const uint8_t* data,
66               size_t length,
67               TimeDelta append_window_start,
68               TimeDelta append_window_end,
69               TimeDelta* timestamp_offset);
70 
71   // Aborts the current append sequence and resets the parser.
72   void ResetParserState(TimeDelta append_window_start,
73                         TimeDelta append_window_end,
74                         TimeDelta* timestamp_offset);
75 
76   // Calls Remove(|start|, |end|, |duration|) on all
77   // ChunkDemuxerStreams managed by this object.
78   void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
79 
80   // If the buffer is full, attempts to try to free up space, as specified in
81   // the "Coded Frame Eviction Algorithm" in the Media Source Extensions Spec.
82   // Returns false iff buffer is still full after running eviction.
83   // https://w3c.github.io/media-source/#sourcebuffer-coded-frame-eviction
84   bool EvictCodedFrames(base::TimeDelta media_time, size_t newDataSize);
85 
86   // Gets invoked when the system is experiencing memory pressure, i.e. there's
87   // not enough free memory. The |media_time| is the media playback position at
88   // the time of memory pressure notification (needed for accurate GC). The
89   // |memory_pressure_level| indicates memory pressure severity. The
90   // |force_instant_gc| is used to force the MSE garbage collection algorithm to
91   // be run right away, without waiting for the next append.
92   void OnMemoryPressure(
93       base::TimeDelta media_time,
94       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
95       bool force_instant_gc);
96 
97   // Returns true if currently parsing a media segment, or false otherwise.
parsing_media_segment()98   bool parsing_media_segment() const { return parsing_media_segment_; }
99 
100   // Returns the 'Generate Timestamps Flag' for this SourceBuffer's byte stream
101   // format parser as described in the MSE Byte Stream Format Registry.
generate_timestamps_flag()102   bool generate_timestamps_flag() const {
103     return stream_parser_->GetGenerateTimestampsFlag();
104   }
105 
106   // Sets |frame_processor_|'s sequence mode to |sequence_mode|.
107   void SetSequenceMode(bool sequence_mode);
108 
109   // Signals the coded frame processor to update its group start timestamp to be
110   // |timestamp_offset| if it is in sequence append mode.
111   void SetGroupStartTimestampIfInSequenceMode(base::TimeDelta timestamp_offset);
112 
113   // Returns the range of buffered data in this source, capped at |duration|.
114   // |ended| - Set to true if end of stream has been signaled and the special
115   // end of stream range logic needs to be executed.
116   Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const;
117 
118   // Returns the highest PTS of currently buffered frames in this source, or
119   // base::TimeDelta() if none of the streams contain buffered data.
120   TimeDelta GetHighestPresentationTimestamp() const;
121 
122   // Returns the highest buffered duration across all streams managed
123   // by this object.
124   // Returns TimeDelta() if none of the streams contain buffered data.
125   TimeDelta GetMaxBufferedDuration() const;
126 
127   // Helper methods that call methods with similar names on all the
128   // ChunkDemuxerStreams managed by this object.
129   void StartReturningData();
130   void AbortReads();
131   void Seek(TimeDelta seek_time);
132   void CompletePendingReadIfPossible();
133   void OnSetDuration(TimeDelta duration);
134   void MarkEndOfStream();
135   void UnmarkEndOfStream();
136   void Shutdown();
137   // Sets the memory limit on each stream of a specific type.
138   // |memory_limit| is the maximum number of bytes each stream of type |type|
139   // is allowed to hold in its buffer.
140   void SetMemoryLimits(DemuxerStream::Type type, size_t memory_limit);
141   bool IsSeekWaitingForData() const;
142 
143   using RangesList = std::vector<Ranges<TimeDelta>>;
144   static Ranges<TimeDelta> ComputeRangesIntersection(
145       const RangesList& active_ranges,
146       bool ended);
147 
148   void SetTracksWatcher(const Demuxer::MediaTracksUpdatedCB& tracks_updated_cb);
149 
150   void SetParseWarningCallback(SourceBufferParseWarningCB parse_warning_cb);
151 
152  private:
153   // State advances through this list to PARSER_INITIALIZED.
154   // The intent is to ensure at least one config is received prior to parser
155   // calling initialization callback, and that such initialization callback
156   // occurs at most once per parser.
157   // PENDING_PARSER_RECONFIG occurs if State had reached PARSER_INITIALIZED
158   // before changing to a new StreamParser in ChangeType(). In such case, State
159   // would then advance to PENDING_PARSER_REINIT, then PARSER_INITIALIZED upon
160   // the next initialization segment parsed, but would not run the
161   // initialization callback in this case (since such would already have
162   // occurred on the initial transition from PENDING_PARSER_INIT to
163   // PARSER_INITIALIZED.)
164   enum State {
165     UNINITIALIZED = 0,
166     PENDING_PARSER_CONFIG,
167     PENDING_PARSER_INIT,
168     PARSER_INITIALIZED,
169     PENDING_PARSER_RECONFIG,
170     PENDING_PARSER_REINIT
171   };
172 
173   // Initializes |stream_parser_|. Also, updates |expected_audio_codecs| and
174   // |expected_video_codecs|.
175   void InitializeParser(const std::string& expected_codecs);
176 
177   // Called by the |stream_parser_| when a new initialization segment is
178   // encountered.
179   // Returns true on a successful call. Returns false if an error occurred while
180   // processing decoder configurations.
181   bool OnNewConfigs(std::string expected_codecs,
182                     std::unique_ptr<MediaTracks> tracks,
183                     const StreamParser::TextTrackConfigMap& text_configs);
184 
185   // Called by the |stream_parser_| at the beginning of a new media segment.
186   void OnNewMediaSegment();
187 
188   // Called by the |stream_parser_| at the end of a media segment.
189   void OnEndOfMediaSegment();
190 
191   // Called by the |stream_parser_| when new buffers have been parsed.
192   // It processes the new buffers using |frame_processor_|, which includes
193   // appending the processed frames to associated demuxer streams for each
194   // frame's track.
195   // Returns true on a successful call. Returns false if an error occurred while
196   // processing the buffers.
197   bool OnNewBuffers(const StreamParser::BufferQueueMap& buffer_queue_map);
198 
199   // Called when StreamParser encounters encrypted media init data.
200   void OnEncryptedMediaInitData(EmeInitDataType type,
201                                 const std::vector<uint8_t>& init_data);
202 
203   void OnSourceInitDone(const StreamParser::InitParameters& params);
204 
205   // Sets memory limits for all demuxer streams.
206   void SetStreamMemoryLimits();
207 
208   // Tracks the number of MEDIA_LOGs emitted for segments missing expected audio
209   // or video blocks. Useful to prevent log spam.
210   int num_missing_track_logs_ = 0;
211 
212   // During Append(), if OnNewBuffers() coded frame processing updates the
213   // timestamp offset then |*timestamp_offset_during_append_| is also updated
214   // so Append()'s caller can know the new offset. This pointer is only non-NULL
215   // during the lifetime of an Append() call.
216   TimeDelta* timestamp_offset_during_append_;
217 
218   // During Append(), coded frame processing triggered by OnNewBuffers()
219   // requires these two attributes. These are only valid during the lifetime of
220   // an Append() call.
221   TimeDelta append_window_start_during_append_;
222   TimeDelta append_window_end_during_append_;
223 
224   // Keeps track of whether a media segment is being parsed.
225   bool parsing_media_segment_;
226 
227   // Valid only while |parsing_media_segment_| is true. These flags enable
228   // warning when the parsed media segment doesn't have frames for some track.
229   std::map<StreamParser::TrackId, bool> media_segment_has_data_for_track_;
230 
231   // The object used to parse appended data.
232   std::unique_ptr<StreamParser> stream_parser_;
233 
234   // Note that ChunkDemuxerStreams are created and owned by the parent
235   // ChunkDemuxer. They are not owned by |this|.
236   using DemuxerStreamMap = std::map<StreamParser::TrackId, ChunkDemuxerStream*>;
237   DemuxerStreamMap audio_streams_;
238   DemuxerStreamMap video_streams_;
239   DemuxerStreamMap text_streams_;
240 
241   std::unique_ptr<FrameProcessor> frame_processor_;
242   const CreateDemuxerStreamCB create_demuxer_stream_cb_;
243   MediaLog* media_log_;
244 
245   StreamParser::InitCB init_cb_;
246   StreamParser::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
247   NewTextTrackCB new_text_track_cb_;
248 
249   State state_;
250 
251   // During Append(), OnNewConfigs() will trigger the initialization segment
252   // received algorithm. Note, the MSE spec explicitly disallows this algorithm
253   // during an Abort(), since Abort() is allowed only to emit coded frames, and
254   // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). So we
255   // also have a flag here that indicates if Append is in progress and we can
256   // invoke this callback.
257   Demuxer::MediaTracksUpdatedCB init_segment_received_cb_;
258   bool append_in_progress_ = false;
259   bool first_init_segment_received_ = false;
260   bool encrypted_media_init_data_reported_ = false;
261 
262   std::vector<AudioCodec> expected_audio_codecs_;
263   std::vector<VideoCodec> expected_video_codecs_;
264 
265   DISALLOW_COPY_AND_ASSIGN(SourceBufferState);
266 };
267 
268 }  // namespace media
269 
270 #endif  // MEDIA_FILTERS_SOURCE_BUFFER_STATE_H_
271