Chromium Code Reviews| 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 |