OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 cancelled. | |
acolwell GONE FROM CHROMIUM
2012/08/07 23:36:11
s/cancelled/canceled/
vrk (LEFT CHROMIUM)
2012/08/08 00:01:21
Done.
| |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
637 | |
638 if (audio_) | |
639 audio_->CancelPendingSeek(); | |
acolwell GONE FROM CHROMIUM
2012/08/07 23:36:11
I think these should to be inside the locked secti
vrk (LEFT CHROMIUM)
2012/08/08 00:01:21
Oops, yes! Just the callback should be run outside
| |
640 | |
641 if (video_) | |
642 video_->CancelPendingSeek(); | |
643 | |
644 if (!cb.is_null()) | |
645 cb.Run(PIPELINE_OK); | |
646 } | |
647 | |
608 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 648 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
609 const std::string& type, | 649 const std::string& type, |
610 std::vector<std::string>& codecs) { | 650 std::vector<std::string>& codecs) { |
611 DCHECK_GT(codecs.size(), 0u); | 651 DCHECK_GT(codecs.size(), 0u); |
612 base::AutoLock auto_lock(lock_); | 652 base::AutoLock auto_lock(lock_); |
613 | 653 |
614 if (state_ != WAITING_FOR_INIT && state_ != INITIALIZING) | 654 if (state_ != WAITING_FOR_INIT && state_ != INITIALIZING) |
615 return kReachedIdLimit; | 655 return kReachedIdLimit; |
616 | 656 |
617 bool has_audio = false; | 657 bool has_audio = false; |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1150 | 1190 |
1151 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1191 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
1152 if (audio_ && !video_) | 1192 if (audio_ && !video_) |
1153 return audio_->GetBufferedRanges(duration_); | 1193 return audio_->GetBufferedRanges(duration_); |
1154 else if (!audio_ && video_) | 1194 else if (!audio_ && video_) |
1155 return video_->GetBufferedRanges(duration_); | 1195 return video_->GetBufferedRanges(duration_); |
1156 return ComputeIntersection(); | 1196 return ComputeIntersection(); |
1157 } | 1197 } |
1158 | 1198 |
1159 } // namespace media | 1199 } // namespace media |
OLD | NEW |