1 // Copyright (c) 2012 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 // SourceBufferStream is a data structure that stores media Buffers in ranges. 6 // Buffers can be appended out of presentation order. Buffers are retrieved by 7 // seeking to the desired start point and calling GetNextBuffer(). Buffers are 8 // returned in sequential presentation order. 9 10 #ifndef MEDIA_FILTERS_SOURCE_BUFFER_STREAM_H_ 11 #define MEDIA_FILTERS_SOURCE_BUFFER_STREAM_H_ 12 13 #include <deque> 14 #include <list> 15 #include <string> 16 #include <utility> 17 #include <vector> 18 19 #include "base/memory/ref_counted.h" 20 #include "media/base/audio_decoder_config.h" 21 #include "media/base/media_export.h" 22 #include "media/base/media_log.h" 23 #include "media/base/ranges.h" 24 #include "media/base/stream_parser_buffer.h" 25 #include "media/base/video_decoder_config.h" 26 27 namespace media { 28 29 class SourceBufferRange; 30 31 // See file-level comment for complete description. 32 class MEDIA_EXPORT SourceBufferStream { 33 public: 34 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 35 36 // Status returned by GetNextBuffer(). 37 // kSuccess: Indicates that the next buffer was returned. 38 // kNeedBuffer: Indicates that we need more data before a buffer can be 39 // returned. 40 // kConfigChange: Indicates that the next buffer requires a config change. 41 enum Status { 42 kSuccess, 43 kNeedBuffer, 44 kConfigChange, 45 kEndOfStream 46 }; 47 48 SourceBufferStream(const AudioDecoderConfig& audio_config, 49 const LogCB& log_cb); 50 SourceBufferStream(const VideoDecoderConfig& video_config, 51 const LogCB& log_cb); 52 53 ~SourceBufferStream(); 54 55 // Signals that the next buffers appended are part of a new media segment 56 // starting at |media_segment_start_time|. 57 void OnNewMediaSegment(base::TimeDelta media_segment_start_time); 58 59 // Add the |buffers| to the SourceBufferStream. Buffers within the queue are 60 // expected to be in order, but multiple calls to Append() may add buffers out 61 // of order or overlapping. Assumes all buffers within |buffers| are in 62 // presentation order and are non-overlapping. 63 // Returns true if Append() was successful, false if |buffers| are not added. 64 // TODO(vrk): Implement garbage collection. (crbug.com/125070) 65 bool Append(const BufferQueue& buffers); 66 67 // Removes buffers between |start| and |end| according to the steps 68 // in the "Coded Frame Removal Algorithm" in the Media Source 69 // Extensions Spec. 70 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-coded-frame-removal 71 // 72 // |duration| is the current duration of the presentation. It is 73 // required by the computation outlined in the spec. 74 void Remove(base::TimeDelta start, base::TimeDelta end, 75 base::TimeDelta duration); 76 77 // Changes the SourceBufferStream's state so that it will start returning 78 // buffers starting from the closest keyframe before |timestamp|. 79 void Seek(base::TimeDelta timestamp); 80 81 // Returns true if the SourceBufferStream has seeked to a time without 82 // buffered data and is waiting for more data to be appended. 83 bool IsSeekPending() const; 84 85 // Notifies the SourceBufferStream that the media duration has been changed to 86 // |duration| so it should drop any data past that point. 87 void OnSetDuration(base::TimeDelta duration); 88 89 // Fills |out_buffer| with a new buffer. Buffers are presented in order from 90 // the last call to Seek(), or starting with the first buffer appended if 91 // Seek() has not been called yet. 92 // |out_buffer|'s timestamp may be earlier than the |timestamp| passed to 93 // the last Seek() call. 94 // Returns kSuccess if |out_buffer| is filled with a valid buffer, kNeedBuffer 95 // if there is not enough data buffered to fulfill the request, and 96 // kConfigChange if the next buffer requires a config change. 97 Status GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); 98 99 // Returns a list of the buffered time ranges. 100 Ranges<base::TimeDelta> GetBufferedTime() const; 101 102 // Notifies this object that end of stream has been signalled. 103 void MarkEndOfStream(); 104 105 // Clear the end of stream state set by MarkEndOfStream(). 106 void UnmarkEndOfStream(); 107 108 const AudioDecoderConfig& GetCurrentAudioDecoderConfig(); 109 const VideoDecoderConfig& GetCurrentVideoDecoderConfig(); 110 111 // Notifies this object that the audio config has changed and buffers in 112 // future Append() calls should be associated with this new config. 113 bool UpdateAudioConfig(const AudioDecoderConfig& config); 114 115 // Notifies this object that the video config has changed and buffers in 116 // future Append() calls should be associated with this new config. 117 bool UpdateVideoConfig(const VideoDecoderConfig& config); 118 119 // Returns the largest distance between two adjacent buffers in this stream, 120 // or an estimate if no two adjacent buffers have been appended to the stream 121 // yet. 122 base::TimeDelta GetMaxInterbufferDistance() const; 123 124 void set_memory_limit_for_testing(int memory_limit) { 125 memory_limit_ = memory_limit; 126 } 127 128 private: 129 typedef std::list<SourceBufferRange*> RangeList; 130 131 // Frees up space if the SourceBufferStream is taking up too much memory. 132 void GarbageCollectIfNeeded(); 133 134 // Attempts to delete approximately |total_bytes_to_free| amount of data 135 // |ranges_|, starting at the front of |ranges_| and moving linearly forward 136 // through the buffers. Deletes starting from the back if |reverse_direction| 137 // is true. Returns the number of bytes freed. 138 int FreeBuffers(int total_bytes_to_free, bool reverse_direction); 139 140 // Appends |new_buffers| into |range_for_new_buffers_itr|, handling start and 141 // end overlaps if necessary. 142 // |deleted_buffers| is an output parameter containing candidates for 143 // |track_buffer_|. 144 // Returns true if the buffers were successfully inserted into the existing 145 // range. 146 // Returns false if the buffers being inserted triggered an error. 147 bool InsertIntoExistingRange( 148 const RangeList::iterator& range_for_new_buffers_itr, 149 const BufferQueue& new_buffers, 150 BufferQueue* deleted_buffers); 151 152 // Resolve overlapping ranges such that no ranges overlap anymore. 153 // |range_with_new_buffers_itr| points to the range that has newly appended 154 // buffers. 155 // |deleted_buffers| is an output parameter containing candidates for 156 // |track_buffer_|. 157 void ResolveCompleteOverlaps( 158 const RangeList::iterator& range_with_new_buffers_itr, 159 BufferQueue* deleted_buffers); 160 void ResolveEndOverlap( 161 const RangeList::iterator& range_with_new_buffers_itr, 162 BufferQueue* deleted_buffers); 163 164 // Removes buffers, from the |track_buffer_|, that come after |timestamp|. 165 void PruneTrackBuffer(const base::TimeDelta timestamp); 166 167 // Checks to see if |range_with_new_buffers_itr| can be merged with the range 168 // next to it, and merges them if so. 169 void MergeWithAdjacentRangeIfNecessary( 170 const RangeList::iterator& range_with_new_buffers_itr); 171 172 // Deletes the buffers between |start_timestamp|, |end_timestamp| from 173 // the range that |range_itr| points to. Deletes between [start,end] if 174 // |is_range_exclusive| is true, or (start,end) if |is_range_exclusive| is 175 // false. Buffers are deleted in GOPs, so this method may delete buffers past 176 // |end_timestamp| if the keyframe a buffer depends on was deleted. 177 void DeleteBetween(const RangeList::iterator& range_itr, 178 base::TimeDelta start_timestamp, 179 base::TimeDelta end_timestamp, 180 bool is_range_exclusive, 181 BufferQueue* deleted_buffers); 182 183 // Returns true if |second_timestamp| is the timestamp of the next buffer in 184 // sequence after |first_timestamp|, false otherwise. 185 bool AreAdjacentInSequence( 186 base::TimeDelta first_timestamp, base::TimeDelta second_timestamp) const; 187 188 // Helper method that returns the timestamp for the next buffer that 189 // |selected_range_| will return from GetNextBuffer() call, or kNoTimestamp() 190 // if in between seeking (i.e. |selected_range_| is null). 191 base::TimeDelta GetNextBufferTimestamp(); 192 193 // Returns the timestamp of the last buffer in the |selected_range_| or 194 // kNoTimestamp() if |selected_range_| is null. 195 base::TimeDelta GetEndBufferTimestamp(); 196 197 // Finds the range that should contain a media segment that begins with 198 // |start_timestamp| and returns the iterator pointing to it. Returns 199 // |ranges_.end()| if there's no such existing range. 200 RangeList::iterator FindExistingRangeFor(base::TimeDelta start_timestamp); 201 202 // Inserts |new_range| into |ranges_| preserving sorted order. Returns an 203 // iterator in |ranges_| that points to |new_range|. 204 RangeList::iterator AddToRanges(SourceBufferRange* new_range); 205 206 // Returns an iterator that points to the place in |ranges_| where 207 // |selected_range_| lives. 208 RangeList::iterator GetSelectedRangeItr(); 209 210 // Sets the |selected_range_| to |range| and resets the next buffer position 211 // for the previous |selected_range_|. 212 void SetSelectedRange(SourceBufferRange* range); 213 214 // Seeks |range| to |seek_timestamp| and then calls SetSelectedRange() with 215 // |range|. 216 void SeekAndSetSelectedRange(SourceBufferRange* range, 217 base::TimeDelta seek_timestamp); 218 219 // Resets this stream back to an unseeked state. 220 void ResetSeekState(); 221 222 // Returns true if |seek_timestamp| refers to the beginning of the first range 223 // in |ranges_|, false otherwise or if |ranges_| is empty. 224 bool ShouldSeekToStartOfBuffered(base::TimeDelta seek_timestamp) const; 225 226 // Returns true if the |prev_is_keyframe| & |current_is_keyframe| combination 227 // on buffers with the same timestamp should be allowed. Returns false if the 228 // combination should signal an error. 229 bool AllowSameTimestamp(bool prev_is_keyframe, 230 bool current_is_keyframe) const; 231 232 // Returns true if the timestamps of |buffers| are monotonically increasing 233 // since the previous append to the media segment, false otherwise. 234 bool IsMonotonicallyIncreasing(const BufferQueue& buffers) const; 235 236 // Returns true if |selected_range_| is the only range in |ranges_| that 237 // HasNextBufferPosition(). 238 bool OnlySelectedRangeIsSeeked() const; 239 240 // Measures the distances between buffer timestamps and tracks the max. 241 void UpdateMaxInterbufferDistance(const BufferQueue& buffers); 242 243 // Sets the config ID for each buffer to |append_config_index_|. 244 void SetConfigIds(const BufferQueue& buffers); 245 246 // Called to complete a config change. Updates |current_config_index_| to 247 // match the index of the next buffer. Calling this method causes 248 // GetNextBuffer() to stop returning kConfigChange and start returning 249 // kSuccess. 250 void CompleteConfigChange(); 251 252 // Sets |selected_range_| and seeks to the nearest keyframe after 253 // |timestamp| if necessary and possible. This method only attempts to 254 // set |selected_range_| if |seleted_range_| is null and |track_buffer_| 255 // is empty. 256 void SetSelectedRangeIfNeeded(const base::TimeDelta timestamp); 257 258 // Find a keyframe timestamp that is >= |start_timestamp| and can be used to 259 // find a new selected range. 260 // Returns kNoTimestamp() if an appropriate keyframe timestamp could not be 261 // found. 262 base::TimeDelta FindNewSelectedRangeSeekTimestamp( 263 const base::TimeDelta start_timestamp); 264 265 // Searches |ranges_| for the first keyframe timestamp that is >= |timestamp|. 266 // If |ranges_| doesn't contain a GOP that covers |timestamp| or doesn't 267 // have a keyframe after |timestamp| then kNoTimestamp() is returned. 268 base::TimeDelta FindKeyframeAfterTimestamp(const base::TimeDelta timestamp); 269 270 // Returns "VIDEO" for a video SourceBufferStream and "AUDIO" for an audio 271 // one. 272 std::string GetStreamTypeName() const; 273 274 // Returns true if we don't have any ranges or the last range is selected 275 // or there is a pending seek beyond any existing ranges. 276 bool IsEndSelected() const; 277 278 // Callback used to report error strings that can help the web developer 279 // figure out what is wrong with the content. 280 LogCB log_cb_; 281 282 // List of disjoint buffered ranges, ordered by start time. 283 RangeList ranges_; 284 285 // Indicates which decoder config is being used by the decoder. 286 // GetNextBuffer() is only allows to return buffers that have a 287 // config ID that matches this index. If there is a mismatch then 288 // it must signal that a config change is needed. 289 int current_config_index_; 290 291 // Indicates which decoder config to associate with new buffers 292 // being appended. Each new buffer appended has its config ID set 293 // to the value of this field. 294 int append_config_index_; 295 296 // Holds the audio/video configs for this stream. |current_config_index_| 297 // and |append_config_index_| represent indexes into one of these vectors. 298 std::vector<AudioDecoderConfig> audio_configs_; 299 std::vector<VideoDecoderConfig> video_configs_; 300 301 // True if more data needs to be appended before the Seek() can complete, 302 // false if no Seek() has been requested or the Seek() is completed. 303 bool seek_pending_; 304 305 // True if the end of the stream has been signalled. 306 bool end_of_stream_; 307 308 // Timestamp of the last request to Seek(). 309 base::TimeDelta seek_buffer_timestamp_; 310 311 // Pointer to the seeked-to Range. This is the range from which 312 // GetNextBuffer() calls are fulfilled after the |track_buffer_| has been 313 // emptied. 314 SourceBufferRange* selected_range_; 315 316 // Queue of the next buffers to be returned from calls to GetNextBuffer(). If 317 // |track_buffer_| is empty, return buffers from |selected_range_|. 318 BufferQueue track_buffer_; 319 320 // The start time of the current media segment being appended. 321 base::TimeDelta media_segment_start_time_; 322 323 // Points to the range containing the current media segment being appended. 324 RangeList::iterator range_for_next_append_; 325 326 // True when the next call to Append() begins a new media segment. 327 bool new_media_segment_; 328 329 // The timestamp of the last buffer appended to the media segment, set to 330 // kNoTimestamp() if the beginning of the segment. 331 base::TimeDelta last_appended_buffer_timestamp_; 332 bool last_appended_buffer_is_keyframe_; 333 334 // The decode timestamp on the last buffer returned by the most recent 335 // GetNextBuffer() call. Set to kNoTimestamp() if GetNextBuffer() hasn't been 336 // called yet or a seek has happened since the last GetNextBuffer() call. 337 base::TimeDelta last_output_buffer_timestamp_; 338 339 // Stores the largest distance between two adjacent buffers in this stream. 340 base::TimeDelta max_interbuffer_distance_; 341 342 // The maximum amount of data in bytes the stream will keep in memory. 343 int memory_limit_; 344 345 // Indicates that a kConfigChanged status has been reported by GetNextBuffer() 346 // and GetCurrentXXXDecoderConfig() must be called to update the current 347 // config. GetNextBuffer() must not be called again until 348 // GetCurrentXXXDecoderConfig() has been called. 349 bool config_change_pending_; 350 351 DISALLOW_COPY_AND_ASSIGN(SourceBufferStream); 352 }; 353 354 } // namespace media 355 356 #endif // MEDIA_FILTERS_SOURCE_BUFFER_STREAM_H_ 357