Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 10835044: Cancel pending seek in ChunkDemuxer when a new seek occurs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: response to CR Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/chunk_demuxer.h" 5 #include "media/filters/chunk_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 public: 166 public:
167 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 167 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
168 typedef std::deque<ReadCB> ReadCBQueue; 168 typedef std::deque<ReadCB> ReadCBQueue;
169 typedef std::deque<base::Closure> ClosureQueue; 169 typedef std::deque<base::Closure> ClosureQueue;
170 170
171 explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config); 171 explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config);
172 explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config); 172 explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config);
173 173
174 void StartWaitingForSeek(); 174 void StartWaitingForSeek();
175 void Seek(TimeDelta time); 175 void Seek(TimeDelta time);
176 void CancelPendingSeek();
176 bool IsSeekPending() const; 177 bool IsSeekPending() const;
177 178
178 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, 179 // Add buffers to this stream. Buffers are stored in SourceBufferStreams,
179 // which handle ordering and overlap resolution. 180 // which handle ordering and overlap resolution.
180 // Returns true if buffers were successfully added. 181 // Returns true if buffers were successfully added.
181 bool Append(const StreamParser::BufferQueue& buffers); 182 bool Append(const StreamParser::BufferQueue& buffers);
182 183
183 // Returns the range of buffered data in this stream, capped at |duration|. 184 // Returns the range of buffered data in this stream, capped at |duration|.
184 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; 185 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const;
185 186
(...skipping 21 matching lines...) Expand all
207 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; 208 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE;
208 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; 209 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE;
209 210
210 protected: 211 protected:
211 virtual ~ChunkDemuxerStream(); 212 virtual ~ChunkDemuxerStream();
212 213
213 private: 214 private:
214 enum State { 215 enum State {
215 RETURNING_DATA_FOR_READS, 216 RETURNING_DATA_FOR_READS,
216 WAITING_FOR_SEEK, 217 WAITING_FOR_SEEK,
218 CANCELED,
217 SHUTDOWN, 219 SHUTDOWN,
218 }; 220 };
219 221
220 // Assigns |state_| to |state| 222 // Assigns |state_| to |state|
221 void ChangeState_Locked(State state); 223 void ChangeState_Locked(State state);
222 224
223 // Adds the callback to |read_cbs_| so it can be called later when we 225 // Adds the callback to |read_cbs_| so it can be called later when we
224 // have data. 226 // have data.
225 void DeferRead_Locked(const ReadCB& read_cb); 227 void DeferRead_Locked(const ReadCB& read_cb);
226 228
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 275
274 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) 276 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it)
275 it->Run(kAborted, NULL); 277 it->Run(kAborted, NULL);
276 } 278 }
277 279
278 void ChunkDemuxerStream::Seek(TimeDelta time) { 280 void ChunkDemuxerStream::Seek(TimeDelta time) {
279 base::AutoLock auto_lock(lock_); 281 base::AutoLock auto_lock(lock_);
280 282
281 DCHECK(read_cbs_.empty()); 283 DCHECK(read_cbs_.empty());
282 284
285 // Ignore seek requests when canceled.
286 if (state_ == CANCELED)
287 return;
288
283 stream_->Seek(time); 289 stream_->Seek(time);
284 290
285 if (state_ == WAITING_FOR_SEEK) 291 if (state_ == WAITING_FOR_SEEK)
286 ChangeState_Locked(RETURNING_DATA_FOR_READS); 292 ChangeState_Locked(RETURNING_DATA_FOR_READS);
287 } 293 }
288 294
295 void ChunkDemuxerStream::CancelPendingSeek() {
296 DVLOG(1) << "CancelPendingSeek()";
297 ReadCBQueue read_cbs;
298 {
299 base::AutoLock auto_lock(lock_);
300 ChangeState_Locked(CANCELED);
301 std::swap(read_cbs_, read_cbs);
302 }
303
304 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it)
305 it->Run(kAborted, NULL);
306 }
307
289 bool ChunkDemuxerStream::IsSeekPending() const { 308 bool ChunkDemuxerStream::IsSeekPending() const {
290 base::AutoLock auto_lock(lock_); 309 base::AutoLock auto_lock(lock_);
291 return stream_->IsSeekPending(); 310 return stream_->IsSeekPending();
292 } 311 }
293 312
294 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { 313 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) {
295 base::AutoLock auto_lock(lock_); 314 base::AutoLock auto_lock(lock_);
296 DCHECK(!end_of_stream_); 315 DCHECK(!end_of_stream_);
297 stream_->OnNewMediaSegment(start_timestamp); 316 stream_->OnNewMediaSegment(start_timestamp);
298 } 317 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 *buffer = StreamParserBuffer::CreateEOSBuffer(); 502 *buffer = StreamParserBuffer::CreateEOSBuffer();
484 return true; 503 return true;
485 } 504 }
486 return false; 505 return false;
487 case SourceBufferStream::kConfigChange: 506 case SourceBufferStream::kConfigChange:
488 *status = kConfigChanged; 507 *status = kConfigChanged;
489 *buffer = NULL; 508 *buffer = NULL;
490 return true; 509 return true;
491 } 510 }
492 break; 511 break;
512 case CANCELED:
493 case WAITING_FOR_SEEK: 513 case WAITING_FOR_SEEK:
494 // Null buffers should be returned in this state since we are waiting 514 // Null buffers should be returned in this state since we are waiting
495 // for a seek. Any buffers in the SourceBuffer should NOT be returned 515 // for a seek. Any buffers in the SourceBuffer should NOT be returned
496 // because they are associated with the seek. 516 // because they are associated with the seek.
497 DCHECK(read_cbs_.empty()); 517 DCHECK(read_cbs_.empty());
498 *status = DemuxerStream::kAborted; 518 *status = DemuxerStream::kAborted;
499 *buffer = NULL; 519 *buffer = NULL;
500 return true; 520 return true;
501 case SHUTDOWN: 521 case SHUTDOWN:
502 DCHECK(read_cbs_.empty()); 522 DCHECK(read_cbs_.empty());
(...skipping 30 matching lines...) Expand all
533 553
534 void ChunkDemuxer::Stop(const base::Closure& callback) { 554 void ChunkDemuxer::Stop(const base::Closure& callback) {
535 DVLOG(1) << "Stop()"; 555 DVLOG(1) << "Stop()";
536 Shutdown(); 556 Shutdown();
537 callback.Run(); 557 callback.Run();
538 } 558 }
539 559
540 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { 560 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) {
541 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; 561 DVLOG(1) << "Seek(" << time.InSecondsF() << ")";
542 DCHECK(time >= start_time_); 562 DCHECK(time >= start_time_);
563 DCHECK(seek_cb_.is_null());
543 564
544 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; 565 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE;
545 { 566 {
546 base::AutoLock auto_lock(lock_); 567 base::AutoLock auto_lock(lock_);
547 568
548 if (state_ == INITIALIZED || state_ == ENDED) { 569 if (state_ == INITIALIZED || state_ == ENDED) {
549 if (audio_) 570 if (audio_)
550 audio_->Seek(time); 571 audio_->Seek(time);
551 572
552 if (video_) 573 if (video_)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 619
599 if (audio_) 620 if (audio_)
600 audio_->StartWaitingForSeek(); 621 audio_->StartWaitingForSeek();
601 622
602 if (video_) 623 if (video_)
603 video_->StartWaitingForSeek(); 624 video_->StartWaitingForSeek();
604 625
605 ChangeState_Locked(INITIALIZED); 626 ChangeState_Locked(INITIALIZED);
606 } 627 }
607 628
629 void ChunkDemuxer::CancelPendingSeek() {
630 PipelineStatusCB cb;
631 {
632 base::AutoLock auto_lock(lock_);
633 if (IsSeekPending_Locked() && !seek_cb_.is_null()) {
634 std::swap(cb, seek_cb_);
635 }
636 if (audio_)
637 audio_->CancelPendingSeek();
638
639 if (video_)
640 video_->CancelPendingSeek();
641 }
642
643 if (!cb.is_null())
644 cb.Run(PIPELINE_OK);
645 }
646
608 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, 647 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
609 const std::string& type, 648 const std::string& type,
610 std::vector<std::string>& codecs) { 649 std::vector<std::string>& codecs) {
611 DCHECK_GT(codecs.size(), 0u); 650 DCHECK_GT(codecs.size(), 0u);
612 base::AutoLock auto_lock(lock_); 651 base::AutoLock auto_lock(lock_);
613 652
614 if (state_ != WAITING_FOR_INIT && state_ != INITIALIZING) 653 if (state_ != WAITING_FOR_INIT && state_ != INITIALIZING)
615 return kReachedIdLimit; 654 return kReachedIdLimit;
616 655
617 bool has_audio = false; 656 bool has_audio = false;
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 1189
1151 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { 1190 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1152 if (audio_ && !video_) 1191 if (audio_ && !video_)
1153 return audio_->GetBufferedRanges(duration_); 1192 return audio_->GetBufferedRanges(duration_);
1154 else if (!audio_ && video_) 1193 else if (!audio_ && video_)
1155 return video_->GetBufferedRanges(duration_); 1194 return video_->GetBufferedRanges(duration_);
1156 return ComputeIntersection(); 1195 return ComputeIntersection();
1157 } 1196 }
1158 1197
1159 } // namespace media 1198 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698