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 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 198 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
199 typedef std::deque<ReadCB> ReadCBQueue; | 199 typedef std::deque<ReadCB> ReadCBQueue; |
200 typedef std::deque<base::Closure> ClosureQueue; | 200 typedef std::deque<base::Closure> ClosureQueue; |
201 | 201 |
202 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, | 202 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
203 const LogCB& log_cb); | 203 const LogCB& log_cb); |
204 ChunkDemuxerStream(const VideoDecoderConfig& video_config, | 204 ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
205 const LogCB& log_cb); | 205 const LogCB& log_cb); |
206 virtual ~ChunkDemuxerStream(); | 206 virtual ~ChunkDemuxerStream(); |
207 | 207 |
208 void StartWaitingForSeek(); | 208 void AbortReads(); |
209 void Seek(TimeDelta time); | 209 void Seek(TimeDelta time); |
210 void CancelPendingSeek(); | |
211 bool IsSeekWaitingForData() const; | 210 bool IsSeekWaitingForData() const; |
212 | 211 |
213 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, | 212 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
214 // which handle ordering and overlap resolution. | 213 // which handle ordering and overlap resolution. |
215 // Returns true if buffers were successfully added. | 214 // Returns true if buffers were successfully added. |
216 bool Append(const StreamParser::BufferQueue& buffers); | 215 bool Append(const StreamParser::BufferQueue& buffers); |
217 | 216 |
218 // Signal to the stream that duration has changed to |duration|. | 217 // Signal to the stream that duration has changed to |duration|. |
219 void OnSetDuration(TimeDelta duration); | 218 void OnSetDuration(TimeDelta duration); |
220 | 219 |
(...skipping 17 matching lines...) Expand all Loading... | |
238 | 237 |
239 // DemuxerStream methods. | 238 // DemuxerStream methods. |
240 virtual void Read(const ReadCB& read_cb) OVERRIDE; | 239 virtual void Read(const ReadCB& read_cb) OVERRIDE; |
241 virtual Type type() OVERRIDE; | 240 virtual Type type() OVERRIDE; |
242 virtual void EnableBitstreamConverter() OVERRIDE; | 241 virtual void EnableBitstreamConverter() OVERRIDE; |
243 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; | 242 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; |
244 virtual VideoDecoderConfig video_decoder_config() OVERRIDE; | 243 virtual VideoDecoderConfig video_decoder_config() OVERRIDE; |
245 | 244 |
246 private: | 245 private: |
247 enum State { | 246 enum State { |
247 UNINITIALIZED, | |
248 RETURNING_DATA_FOR_READS, | 248 RETURNING_DATA_FOR_READS, |
249 WAITING_FOR_SEEK, | 249 RETURNING_ABORT_FOR_READS, |
250 CANCELED, | |
251 SHUTDOWN, | 250 SHUTDOWN, |
252 }; | 251 }; |
253 | 252 |
254 // Assigns |state_| to |state| | 253 // Assigns |state_| to |state| |
255 void ChangeState_Locked(State state); | 254 void ChangeState_Locked(State state); |
256 | 255 |
257 // Adds the callback to |read_cbs_| so it can be called later when we | 256 // Adds the callback to |read_cbs_| so it can be called later when we |
258 // have data. | 257 // have data. |
259 void DeferRead_Locked(const ReadCB& read_cb); | 258 void DeferRead_Locked(const ReadCB& read_cb); |
260 | 259 |
(...skipping 15 matching lines...) Expand all Loading... | |
276 mutable base::Lock lock_; | 275 mutable base::Lock lock_; |
277 State state_; | 276 State state_; |
278 ReadCBQueue read_cbs_; | 277 ReadCBQueue read_cbs_; |
279 | 278 |
280 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 279 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
281 }; | 280 }; |
282 | 281 |
283 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, | 282 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
284 const LogCB& log_cb) | 283 const LogCB& log_cb) |
285 : type_(AUDIO), | 284 : type_(AUDIO), |
286 state_(RETURNING_DATA_FOR_READS) { | 285 state_(UNINITIALIZED) { |
287 stream_.reset(new SourceBufferStream(audio_config, log_cb)); | 286 stream_.reset(new SourceBufferStream(audio_config, log_cb)); |
288 } | 287 } |
289 | 288 |
290 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, | 289 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
291 const LogCB& log_cb) | 290 const LogCB& log_cb) |
292 : type_(VIDEO), | 291 : type_(VIDEO), |
293 state_(RETURNING_DATA_FOR_READS) { | 292 state_(UNINITIALIZED) { |
294 stream_.reset(new SourceBufferStream(video_config, log_cb)); | 293 stream_.reset(new SourceBufferStream(video_config, log_cb)); |
295 } | 294 } |
296 | 295 |
297 void ChunkDemuxerStream::StartWaitingForSeek() { | 296 void ChunkDemuxerStream::AbortReads() { |
298 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; | 297 DVLOG(1) << "ChunkDemuxerStream::AbortReads()"; |
299 ReadCBQueue read_cbs; | 298 ReadCBQueue read_cbs; |
300 { | 299 { |
301 base::AutoLock auto_lock(lock_); | 300 base::AutoLock auto_lock(lock_); |
302 ChangeState_Locked(WAITING_FOR_SEEK); | 301 ChangeState_Locked(RETURNING_ABORT_FOR_READS); |
303 std::swap(read_cbs_, read_cbs); | 302 std::swap(read_cbs_, read_cbs); |
304 } | 303 } |
305 | 304 |
306 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 305 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
307 it->Run(kAborted, NULL); | 306 it->Run(kAborted, NULL); |
308 } | 307 } |
309 | 308 |
310 void ChunkDemuxerStream::Seek(TimeDelta time) { | 309 void ChunkDemuxerStream::Seek(TimeDelta time) { |
311 base::AutoLock auto_lock(lock_); | 310 base::AutoLock auto_lock(lock_); |
312 | |
313 DCHECK(read_cbs_.empty()); | 311 DCHECK(read_cbs_.empty()); |
314 | 312 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS); |
315 // Ignore seek requests when canceled. | |
316 if (state_ == CANCELED) | |
317 return; | |
318 | 313 |
319 stream_->Seek(time); | 314 stream_->Seek(time); |
320 | 315 ChangeState_Locked(RETURNING_DATA_FOR_READS); |
321 if (state_ == WAITING_FOR_SEEK) | |
322 ChangeState_Locked(RETURNING_DATA_FOR_READS); | |
323 } | |
324 | |
325 void ChunkDemuxerStream::CancelPendingSeek() { | |
326 DVLOG(1) << "ChunkDemuxerStream::CancelPendingSeek()"; | |
327 ReadCBQueue read_cbs; | |
328 { | |
329 base::AutoLock auto_lock(lock_); | |
330 ChangeState_Locked(CANCELED); | |
331 std::swap(read_cbs_, read_cbs); | |
332 } | |
333 | |
334 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | |
335 it->Run(kAborted, NULL); | |
336 } | 316 } |
337 | 317 |
338 bool ChunkDemuxerStream::IsSeekWaitingForData() const { | 318 bool ChunkDemuxerStream::IsSeekWaitingForData() const { |
339 base::AutoLock auto_lock(lock_); | 319 base::AutoLock auto_lock(lock_); |
340 return stream_->IsSeekPending(); | 320 return stream_->IsSeekPending(); |
341 } | 321 } |
342 | 322 |
343 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { | 323 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { |
344 base::AutoLock auto_lock(lock_); | 324 base::AutoLock auto_lock(lock_); |
345 stream_->OnNewMediaSegment(start_timestamp); | 325 stream_->OnNewMediaSegment(start_timestamp); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 message_loop_proxy->PostTask(FROM_HERE, base::Bind( | 422 message_loop_proxy->PostTask(FROM_HERE, base::Bind( |
443 &RunOnMessageLoop, read_cb, message_loop_proxy, status, buffer)); | 423 &RunOnMessageLoop, read_cb, message_loop_proxy, status, buffer)); |
444 return; | 424 return; |
445 } | 425 } |
446 | 426 |
447 read_cb.Run(status, buffer); | 427 read_cb.Run(status, buffer); |
448 } | 428 } |
449 | 429 |
450 // DemuxerStream methods. | 430 // DemuxerStream methods. |
451 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 431 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
432 base::AutoLock auto_lock(lock_); | |
433 DCHECK_NE(state_, UNINITIALIZED); | |
434 | |
452 DemuxerStream::Status status = kOk; | 435 DemuxerStream::Status status = kOk; |
453 scoped_refptr<StreamParserBuffer> buffer; | 436 scoped_refptr<StreamParserBuffer> buffer; |
454 { | 437 |
455 base::AutoLock auto_lock(lock_); | 438 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { |
456 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { | 439 DeferRead_Locked(read_cb); |
457 DeferRead_Locked(read_cb); | 440 return; |
458 return; | |
459 } | |
460 } | 441 } |
461 | 442 |
462 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( | 443 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( |
463 read_cb, status, buffer)); | 444 read_cb, status, buffer)); |
464 } | 445 } |
465 | 446 |
466 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 447 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
467 | 448 |
468 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 449 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
469 | 450 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 read_cbs_.pop_front(); | 494 read_cbs_.pop_front(); |
514 } | 495 } |
515 } | 496 } |
516 | 497 |
517 bool ChunkDemuxerStream::GetNextBuffer_Locked( | 498 bool ChunkDemuxerStream::GetNextBuffer_Locked( |
518 DemuxerStream::Status* status, | 499 DemuxerStream::Status* status, |
519 scoped_refptr<StreamParserBuffer>* buffer) { | 500 scoped_refptr<StreamParserBuffer>* buffer) { |
520 lock_.AssertAcquired(); | 501 lock_.AssertAcquired(); |
521 | 502 |
522 switch (state_) { | 503 switch (state_) { |
504 case UNINITIALIZED: | |
505 NOTREACHED(); | |
506 return false; | |
507 break; | |
xhwang
2013/06/21 20:44:13
nit: no need to break after return.
acolwell GONE FROM CHROMIUM
2013/06/21 22:08:38
Done.
| |
523 case RETURNING_DATA_FOR_READS: | 508 case RETURNING_DATA_FOR_READS: |
524 switch (stream_->GetNextBuffer(buffer)) { | 509 switch (stream_->GetNextBuffer(buffer)) { |
525 case SourceBufferStream::kSuccess: | 510 case SourceBufferStream::kSuccess: |
526 *status = DemuxerStream::kOk; | 511 *status = DemuxerStream::kOk; |
527 return true; | 512 return true; |
528 case SourceBufferStream::kNeedBuffer: | 513 case SourceBufferStream::kNeedBuffer: |
529 return false; | 514 return false; |
530 case SourceBufferStream::kEndOfStream: | 515 case SourceBufferStream::kEndOfStream: |
531 *status = DemuxerStream::kOk; | 516 *status = DemuxerStream::kOk; |
532 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 517 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
533 return true; | 518 return true; |
534 case SourceBufferStream::kConfigChange: | 519 case SourceBufferStream::kConfigChange: |
535 DVLOG(2) << "Config change reported to ChunkDemuxerStream."; | 520 DVLOG(2) << "Config change reported to ChunkDemuxerStream."; |
536 *status = kConfigChanged; | 521 *status = kConfigChanged; |
537 *buffer = NULL; | 522 *buffer = NULL; |
538 return true; | 523 return true; |
539 } | 524 } |
540 break; | 525 break; |
541 case CANCELED: | 526 case RETURNING_ABORT_FOR_READS: |
542 case WAITING_FOR_SEEK: | |
543 // Null buffers should be returned in this state since we are waiting | 527 // Null buffers should be returned in this state since we are waiting |
544 // for a seek. Any buffers in the SourceBuffer should NOT be returned | 528 // for a seek. Any buffers in the SourceBuffer should NOT be returned |
545 // because they are associated with the seek. | 529 // because they are associated with the seek. |
546 DCHECK(read_cbs_.empty()); | 530 DCHECK(read_cbs_.empty()); |
547 *status = DemuxerStream::kAborted; | 531 *status = DemuxerStream::kAborted; |
548 *buffer = NULL; | 532 *buffer = NULL; |
549 return true; | 533 return true; |
550 case SHUTDOWN: | 534 case SHUTDOWN: |
551 DCHECK(read_cbs_.empty()); | 535 DCHECK(read_cbs_.empty()); |
552 *status = DemuxerStream::kOk; | 536 *status = DemuxerStream::kOk; |
553 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 537 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
554 return true; | 538 return true; |
555 } | 539 } |
556 | 540 |
557 NOTREACHED(); | 541 NOTREACHED(); |
558 return false; | 542 return false; |
559 } | 543 } |
560 | 544 |
561 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, | 545 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, |
562 const NeedKeyCB& need_key_cb, | 546 const NeedKeyCB& need_key_cb, |
563 const AddTextTrackCB& add_text_track_cb, | 547 const AddTextTrackCB& add_text_track_cb, |
564 const LogCB& log_cb) | 548 const LogCB& log_cb) |
565 : state_(WAITING_FOR_INIT), | 549 : state_(WAITING_FOR_INIT), |
550 cancel_next_seek_(false), | |
566 host_(NULL), | 551 host_(NULL), |
567 open_cb_(open_cb), | 552 open_cb_(open_cb), |
568 need_key_cb_(need_key_cb), | 553 need_key_cb_(need_key_cb), |
569 add_text_track_cb_(add_text_track_cb), | 554 add_text_track_cb_(add_text_track_cb), |
570 log_cb_(log_cb), | 555 log_cb_(log_cb), |
571 duration_(kNoTimestamp()), | 556 duration_(kNoTimestamp()), |
572 user_specified_duration_(-1) { | 557 user_specified_duration_(-1) { |
573 DCHECK(!open_cb_.is_null()); | 558 DCHECK(!open_cb_.is_null()); |
574 DCHECK(!need_key_cb_.is_null()); | 559 DCHECK(!need_key_cb_.is_null()); |
575 } | 560 } |
(...skipping 18 matching lines...) Expand all Loading... | |
594 | 579 |
595 void ChunkDemuxer::Stop(const base::Closure& callback) { | 580 void ChunkDemuxer::Stop(const base::Closure& callback) { |
596 DVLOG(1) << "Stop()"; | 581 DVLOG(1) << "Stop()"; |
597 Shutdown(); | 582 Shutdown(); |
598 callback.Run(); | 583 callback.Run(); |
599 } | 584 } |
600 | 585 |
601 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { | 586 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { |
602 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; | 587 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; |
603 DCHECK(time >= TimeDelta()); | 588 DCHECK(time >= TimeDelta()); |
589 | |
590 base::AutoLock auto_lock(lock_); | |
604 DCHECK(seek_cb_.is_null()); | 591 DCHECK(seek_cb_.is_null()); |
605 | 592 |
606 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; | |
607 base::AutoLock auto_lock(lock_); | |
608 | |
609 seek_cb_ = BindToCurrentLoop(cb); | 593 seek_cb_ = BindToCurrentLoop(cb); |
610 if (state_ == INITIALIZED || state_ == ENDED) { | 594 if (state_ != INITIALIZED && state_ != ENDED) { |
611 if (audio_) | 595 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_INVALID_STATE); |
612 audio_->Seek(time); | 596 return; |
613 | |
614 if (video_) | |
615 video_->Seek(time); | |
616 | |
617 if (IsSeekWaitingForData_Locked()) { | |
618 DVLOG(1) << "Seek() : waiting for more data to arrive."; | |
619 return; | |
620 } | |
621 | |
622 status = PIPELINE_OK; | |
623 } | 597 } |
624 | 598 |
625 base::ResetAndReturn(&seek_cb_).Run(status); | 599 if (cancel_next_seek_) { |
600 cancel_next_seek_ = false; | |
601 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | |
602 return; | |
603 } | |
604 | |
605 if (audio_) | |
606 audio_->Seek(time); | |
607 | |
608 if (video_) | |
609 video_->Seek(time); | |
610 | |
611 if (IsSeekWaitingForData_Locked()) { | |
612 DVLOG(1) << "Seek() : waiting for more data to arrive."; | |
613 return; | |
614 } | |
615 | |
616 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | |
626 } | 617 } |
627 | 618 |
628 void ChunkDemuxer::OnAudioRendererDisabled() { | 619 void ChunkDemuxer::OnAudioRendererDisabled() { |
629 base::AutoLock auto_lock(lock_); | 620 base::AutoLock auto_lock(lock_); |
630 audio_->Shutdown(); | 621 audio_->Shutdown(); |
631 disabled_audio_ = audio_.Pass(); | 622 disabled_audio_ = audio_.Pass(); |
632 } | 623 } |
633 | 624 |
634 // Demuxer implementation. | 625 // Demuxer implementation. |
635 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { | 626 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { |
636 base::AutoLock auto_lock(lock_); | 627 base::AutoLock auto_lock(lock_); |
637 if (type == DemuxerStream::VIDEO) | 628 if (type == DemuxerStream::VIDEO) |
638 return video_.get(); | 629 return video_.get(); |
639 | 630 |
640 if (type == DemuxerStream::AUDIO) | 631 if (type == DemuxerStream::AUDIO) |
641 return audio_.get(); | 632 return audio_.get(); |
642 | 633 |
643 return NULL; | 634 return NULL; |
644 } | 635 } |
645 | 636 |
646 TimeDelta ChunkDemuxer::GetStartTime() const { | 637 TimeDelta ChunkDemuxer::GetStartTime() const { |
647 return TimeDelta(); | 638 return TimeDelta(); |
648 } | 639 } |
649 | 640 |
650 void ChunkDemuxer::StartWaitingForSeek() { | 641 void ChunkDemuxer::StartWaitingForSeek() { |
651 DVLOG(1) << "StartWaitingForSeek()"; | 642 DVLOG(1) << "StartWaitingForSeek()"; |
652 base::AutoLock auto_lock(lock_); | 643 base::AutoLock auto_lock(lock_); |
653 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN); | 644 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN); |
645 DCHECK(seek_cb_.is_null()); | |
654 | 646 |
655 if (state_ == SHUTDOWN) | 647 if (state_ == SHUTDOWN) |
656 return; | 648 return; |
657 | 649 |
658 if (audio_) | 650 if (audio_) |
659 audio_->StartWaitingForSeek(); | 651 audio_->AbortReads(); |
660 | 652 |
661 if (video_) | 653 if (video_) |
662 video_->StartWaitingForSeek(); | 654 video_->AbortReads(); |
655 | |
656 cancel_next_seek_ = false; | |
xhwang
2013/06/21 21:21:36
Can |cancel_next_seek_| be true here? If so, does
acolwell GONE FROM CHROMIUM
2013/06/21 22:08:38
This is needed to handle the case where the initia
| |
663 } | 657 } |
664 | 658 |
665 void ChunkDemuxer::CancelPendingSeek() { | 659 void ChunkDemuxer::CancelPendingSeek() { |
666 base::AutoLock auto_lock(lock_); | 660 base::AutoLock auto_lock(lock_); |
667 DCHECK(seek_cb_.is_null() != IsSeekWaitingForData_Locked()); | 661 DCHECK_NE(state_, INITIALIZING); |
662 DCHECK(seek_cb_.is_null() || IsSeekWaitingForData_Locked()); | |
acolwell GONE FROM CHROMIUM
2013/06/21 16:33:33
Changed this back to the original DCHECK because t
| |
663 | |
664 if (cancel_next_seek_) | |
665 return; | |
668 | 666 |
669 if (audio_) | 667 if (audio_) |
670 audio_->CancelPendingSeek(); | 668 audio_->AbortReads(); |
671 | 669 |
672 if (video_) | 670 if (video_) |
673 video_->CancelPendingSeek(); | 671 video_->AbortReads(); |
674 | 672 |
675 if (!seek_cb_.is_null()) | 673 if (seek_cb_.is_null()) { |
676 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | 674 cancel_next_seek_ = true; |
675 return; | |
676 } | |
677 | |
678 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | |
677 } | 679 } |
678 | 680 |
679 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 681 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
680 const std::string& type, | 682 const std::string& type, |
681 std::vector<std::string>& codecs) { | 683 std::vector<std::string>& codecs) { |
682 DCHECK_GT(codecs.size(), 0u); | 684 DCHECK_GT(codecs.size(), 0u); |
683 base::AutoLock auto_lock(lock_); | 685 base::AutoLock auto_lock(lock_); |
684 | 686 |
685 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) | 687 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) |
686 return kReachedIdLimit; | 688 return kReachedIdLimit; |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1077 } | 1079 } |
1078 | 1080 |
1079 if (duration != TimeDelta() && duration_ == kNoTimestamp()) | 1081 if (duration != TimeDelta() && duration_ == kNoTimestamp()) |
1080 UpdateDuration(duration); | 1082 UpdateDuration(duration); |
1081 | 1083 |
1082 // Wait until all streams have initialized. | 1084 // Wait until all streams have initialized. |
1083 if ((!source_id_audio_.empty() && !audio_) || | 1085 if ((!source_id_audio_.empty() && !audio_) || |
1084 (!source_id_video_.empty() && !video_)) | 1086 (!source_id_video_.empty() && !video_)) |
1085 return; | 1087 return; |
1086 | 1088 |
1089 TimeDelta start_time = GetStartTime(); | |
acolwell GONE FROM CHROMIUM
2013/06/21 16:33:33
This is just to make it clear what these initial s
| |
1087 if (audio_) | 1090 if (audio_) |
1088 audio_->Seek(TimeDelta()); | 1091 audio_->Seek(start_time); |
1089 | 1092 |
1090 if (video_) | 1093 if (video_) |
1091 video_->Seek(TimeDelta()); | 1094 video_->Seek(start_time); |
1092 | 1095 |
1093 if (duration_ == kNoTimestamp()) | 1096 if (duration_ == kNoTimestamp()) |
1094 duration_ = kInfiniteDuration(); | 1097 duration_ = kInfiniteDuration(); |
1095 | 1098 |
1096 // The demuxer is now initialized after the |start_timestamp_| was set. | 1099 // The demuxer is now initialized after the |start_timestamp_| was set. |
1097 ChangeState_Locked(INITIALIZED); | 1100 ChangeState_Locked(INITIALIZED); |
1098 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1101 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
1099 } | 1102 } |
1100 | 1103 |
1101 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, | 1104 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1276 | 1279 |
1277 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1280 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
1278 if (audio_ && !video_) | 1281 if (audio_ && !video_) |
1279 return audio_->GetBufferedRanges(duration_); | 1282 return audio_->GetBufferedRanges(duration_); |
1280 else if (!audio_ && video_) | 1283 else if (!audio_ && video_) |
1281 return video_->GetBufferedRanges(duration_); | 1284 return video_->GetBufferedRanges(duration_); |
1282 return ComputeIntersection(); | 1285 return ComputeIntersection(); |
1283 } | 1286 } |
1284 | 1287 |
1285 } // namespace media | 1288 } // namespace media |
OLD | NEW |