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