| Index: media/filters/chunk_demuxer.cc
|
| diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
|
| index d641ded72c00e74a3fd48b9805c1e5f319cf9efa..7ad4c84a436e2695c55abba43d8a9c76f6fdf2ab 100644
|
| --- a/media/filters/chunk_demuxer.cc
|
| +++ b/media/filters/chunk_demuxer.cc
|
| @@ -133,6 +133,14 @@ class SourceState {
|
| // ChunkDemuxerStreams managed by this object.
|
| void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
|
|
|
| + // Attempts to perform garbage collection in SourceBuffers associated with
|
| + // this ChunkDemuxer. Returns true if garbage collection was successful.
|
| + // |media_time| parameter should indicate the current playback position.
|
| + // If it's a valid time value, the garbage collection algorithm will make sure
|
| + // to preserve unconsumed data buffers in the range between last read position
|
| + // and the current playback position.
|
| + bool EvictFrames(DecodeTimestamp media_time);
|
| +
|
| // Returns true if currently parsing a media segment, or false otherwise.
|
| bool parsing_media_segment() const { return parsing_media_segment_; }
|
|
|
| @@ -374,6 +382,23 @@ void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) {
|
| }
|
| }
|
|
|
| +bool SourceState::EvictFrames(DecodeTimestamp media_time) {
|
| + bool success = true;
|
| +
|
| + if (audio_)
|
| + success = audio_->EvictFrames(media_time) && success;
|
| +
|
| + if (video_)
|
| + success = video_->EvictFrames(media_time) && success;
|
| +
|
| + for (TextStreamMap::iterator itr = text_stream_map_.begin();
|
| + itr != text_stream_map_.end(); ++itr) {
|
| + success = itr->second->EvictFrames(media_time) && success;
|
| + }
|
| +
|
| + return success;
|
| +}
|
| +
|
| Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration,
|
| bool ended) const {
|
| // TODO(acolwell): When we start allowing disabled tracks we'll need to update
|
| @@ -883,6 +908,11 @@ void ChunkDemuxerStream::Remove(TimeDelta start, TimeDelta end,
|
| stream_->Remove(start, end, duration);
|
| }
|
|
|
| +bool ChunkDemuxerStream::EvictFrames(DecodeTimestamp media_time) {
|
| + base::AutoLock auto_lock(lock_);
|
| + return stream_->GarbageCollectIfNeeded(media_time);
|
| +}
|
| +
|
| void ChunkDemuxerStream::OnSetDuration(TimeDelta duration) {
|
| base::AutoLock auto_lock(lock_);
|
| stream_->OnSetDuration(duration);
|
| @@ -1106,6 +1136,7 @@ ChunkDemuxer::ChunkDemuxer(
|
| const base::Closure& open_cb,
|
| const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
| const LogCB& log_cb,
|
| + const GetMediaTimeCB& get_media_time_cb,
|
| const scoped_refptr<MediaLog>& media_log,
|
| bool splice_frames_enabled)
|
| : state_(WAITING_FOR_INIT),
|
| @@ -1115,6 +1146,7 @@ ChunkDemuxer::ChunkDemuxer(
|
| encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
|
| enable_text_(false),
|
| log_cb_(log_cb),
|
| + get_media_time_cb_(get_media_time_cb),
|
| media_log_(media_log),
|
| duration_(kNoTimestamp()),
|
| user_specified_duration_(-1),
|
| @@ -1317,6 +1349,23 @@ Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
|
| return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
|
| }
|
|
|
| +bool ChunkDemuxer::EvictFrames() {
|
| + DecodeTimestamp current_media_time;
|
| + if (!get_media_time_cb_.is_null()) {
|
| + current_media_time =
|
| + DecodeTimestamp::FromPresentationTime(get_media_time_cb_.Run());
|
| + } else {
|
| + current_media_time = kNoDecodeTimestamp();
|
| + }
|
| +
|
| + bool success = true;
|
| + for (SourceStateMap::iterator itr = source_state_map_.begin();
|
| + itr != source_state_map_.end(); ++itr) {
|
| + success = itr->second->EvictFrames(current_media_time) && success;
|
| + }
|
| + return success;
|
| +}
|
| +
|
| void ChunkDemuxer::AppendData(
|
| const std::string& id,
|
| const uint8* data,
|
|
|