Index: media/filters/chunk_demuxer.cc |
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
index 581b245dbc2bb77782ce893c5a05ad7f26dcdbe4..1fdbde0bfbd164288e865a6c84b6c75cb56dd53c 100644 |
--- a/media/filters/chunk_demuxer.cc |
+++ b/media/filters/chunk_demuxer.cc |
@@ -173,6 +173,7 @@ class ChunkDemuxerStream : public DemuxerStream { |
void StartWaitingForSeek(); |
void Seek(TimeDelta time); |
+ void CancelPendingSeek(); |
bool IsSeekPending() const; |
// Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
@@ -214,6 +215,7 @@ class ChunkDemuxerStream : public DemuxerStream { |
enum State { |
RETURNING_DATA_FOR_READS, |
WAITING_FOR_SEEK, |
+ CANCELED, |
SHUTDOWN, |
}; |
@@ -280,12 +282,29 @@ void ChunkDemuxerStream::Seek(TimeDelta time) { |
DCHECK(read_cbs_.empty()); |
+ // Ignore seek requests when canceled. |
+ if (state_ == CANCELED) |
+ return; |
+ |
stream_->Seek(time); |
if (state_ == WAITING_FOR_SEEK) |
ChangeState_Locked(RETURNING_DATA_FOR_READS); |
} |
+void ChunkDemuxerStream::CancelPendingSeek() { |
+ DVLOG(1) << "CancelPendingSeek()"; |
+ ReadCBQueue read_cbs; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ ChangeState_Locked(CANCELED); |
+ std::swap(read_cbs_, read_cbs); |
+ } |
+ |
+ for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
+ it->Run(kAborted, NULL); |
+} |
+ |
bool ChunkDemuxerStream::IsSeekPending() const { |
base::AutoLock auto_lock(lock_); |
return stream_->IsSeekPending(); |
@@ -490,6 +509,7 @@ bool ChunkDemuxerStream::GetNextBuffer_Locked( |
return true; |
} |
break; |
+ case CANCELED: |
case WAITING_FOR_SEEK: |
// Null buffers should be returned in this state since we are waiting |
// for a seek. Any buffers in the SourceBuffer should NOT be returned |
@@ -540,6 +560,7 @@ void ChunkDemuxer::Stop(const base::Closure& callback) { |
void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { |
DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; |
DCHECK(time >= start_time_); |
+ DCHECK(seek_cb_.is_null()); |
PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; |
{ |
@@ -605,6 +626,24 @@ void ChunkDemuxer::StartWaitingForSeek() { |
ChangeState_Locked(INITIALIZED); |
} |
+void ChunkDemuxer::CancelPendingSeek() { |
+ PipelineStatusCB cb; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ if (IsSeekPending_Locked() && !seek_cb_.is_null()) { |
+ std::swap(cb, seek_cb_); |
+ } |
+ if (audio_) |
+ audio_->CancelPendingSeek(); |
+ |
+ if (video_) |
+ video_->CancelPendingSeek(); |
+ } |
+ |
+ if (!cb.is_null()) |
+ cb.Run(PIPELINE_OK); |
+} |
+ |
ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
const std::string& type, |
std::vector<std::string>& codecs) { |