| 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/base/pipeline.h" | 5 #include "media/base/pipeline.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 | 516 |
| 517 case kStopping: | 517 case kStopping: |
| 518 case kStopped: | 518 case kStopped: |
| 519 case kCreated: | 519 case kCreated: |
| 520 case kSeeking: | 520 case kSeeking: |
| 521 NOTREACHED() << "State has no transition: " << state_; | 521 NOTREACHED() << "State has no transition: " << state_; |
| 522 return; | 522 return; |
| 523 } | 523 } |
| 524 } | 524 } |
| 525 | 525 |
| 526 // Note that the usage of base::Unretained() with the audio/video renderers | |
| 527 // in the following DoXXX() functions is considered safe as they are owned by | |
| 528 // |pending_callbacks_| and share the same lifetime. | |
| 529 // | |
| 530 // That being said, deleting the renderers while keeping |pending_callbacks_| | |
| 531 // running on the media thread would result in crashes. | |
| 532 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { | 526 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { |
| 533 DCHECK(message_loop_->BelongsToCurrentThread()); | 527 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 534 DCHECK(!pending_callbacks_.get()); | 528 DCHECK(!pending_callbacks_.get()); |
| 535 SerialRunner::Queue bound_fns; | 529 SerialRunner::Queue bound_fns; |
| 536 | 530 |
| 537 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); | 531 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); |
| 538 | 532 |
| 539 // Preroll renderers. | 533 // Preroll renderers. |
| 540 if (audio_renderer_) { | 534 if (audio_renderer_) { |
| 541 bound_fns.Push(base::Bind( | 535 bound_fns.Push(base::Bind( |
| 542 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), | 536 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); |
| 543 seek_timestamp)); | |
| 544 } | 537 } |
| 545 | 538 |
| 546 if (video_renderer_) { | 539 if (video_renderer_) { |
| 547 bound_fns.Push(base::Bind( | 540 bound_fns.Push(base::Bind( |
| 548 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), | 541 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); |
| 549 seek_timestamp)); | |
| 550 } | 542 } |
| 551 | 543 |
| 552 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 544 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
| 553 } | 545 } |
| 554 | 546 |
| 555 void Pipeline::DoSeek( | 547 void Pipeline::DoSeek( |
| 556 base::TimeDelta seek_timestamp, | 548 base::TimeDelta seek_timestamp, |
| 557 const PipelineStatusCB& done_cb) { | 549 const PipelineStatusCB& done_cb) { |
| 558 DCHECK(message_loop_->BelongsToCurrentThread()); | 550 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 559 DCHECK(!pending_callbacks_.get()); | 551 DCHECK(!pending_callbacks_.get()); |
| 560 SerialRunner::Queue bound_fns; | 552 SerialRunner::Queue bound_fns; |
| 561 | 553 |
| 562 // Pause. | 554 // Pause. |
| 563 if (audio_renderer_) { | 555 if (audio_renderer_) |
| 564 bound_fns.Push(base::Bind( | 556 bound_fns.Push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); |
| 565 &AudioRenderer::Pause, base::Unretained(audio_renderer_.get()))); | 557 if (video_renderer_) |
| 566 } | 558 bound_fns.Push(base::Bind(&VideoRenderer::Pause, video_renderer_)); |
| 567 if (video_renderer_) { | |
| 568 bound_fns.Push(base::Bind( | |
| 569 &VideoRenderer::Pause, base::Unretained(video_renderer_.get()))); | |
| 570 } | |
| 571 | 559 |
| 572 // Flush. | 560 // Flush. |
| 573 if (audio_renderer_) { | 561 if (audio_renderer_) |
| 574 bound_fns.Push(base::Bind( | 562 bound_fns.Push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); |
| 575 &AudioRenderer::Flush, base::Unretained(audio_renderer_.get()))); | 563 if (video_renderer_) |
| 576 } | 564 bound_fns.Push(base::Bind(&VideoRenderer::Flush, video_renderer_)); |
| 577 if (video_renderer_) { | |
| 578 bound_fns.Push(base::Bind( | |
| 579 &VideoRenderer::Flush, base::Unretained(video_renderer_.get()))); | |
| 580 } | |
| 581 | 565 |
| 582 // Seek demuxer. | 566 // Seek demuxer. |
| 583 bound_fns.Push(base::Bind( | 567 bound_fns.Push(base::Bind( |
| 584 &Demuxer::Seek, demuxer_, seek_timestamp)); | 568 &Demuxer::Seek, demuxer_, seek_timestamp)); |
| 585 | 569 |
| 586 // Preroll renderers. | 570 // Preroll renderers. |
| 587 if (audio_renderer_) { | 571 if (audio_renderer_) { |
| 588 bound_fns.Push(base::Bind( | 572 bound_fns.Push(base::Bind( |
| 589 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), | 573 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); |
| 590 seek_timestamp)); | |
| 591 } | 574 } |
| 592 | 575 |
| 593 if (video_renderer_) { | 576 if (video_renderer_) { |
| 594 bound_fns.Push(base::Bind( | 577 bound_fns.Push(base::Bind( |
| 595 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), | 578 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); |
| 596 seek_timestamp)); | |
| 597 } | 579 } |
| 598 | 580 |
| 599 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 581 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
| 600 } | 582 } |
| 601 | 583 |
| 602 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) { | 584 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) { |
| 603 DCHECK(message_loop_->BelongsToCurrentThread()); | 585 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 604 DCHECK(!pending_callbacks_.get()); | 586 DCHECK(!pending_callbacks_.get()); |
| 605 SerialRunner::Queue bound_fns; | 587 SerialRunner::Queue bound_fns; |
| 606 | 588 |
| 607 PlaybackRateChangedTask(GetPlaybackRate()); | 589 PlaybackRateChangedTask(GetPlaybackRate()); |
| 608 VolumeChangedTask(GetVolume()); | 590 VolumeChangedTask(GetVolume()); |
| 609 | 591 |
| 610 if (audio_renderer_) { | 592 if (audio_renderer_) |
| 611 bound_fns.Push(base::Bind( | 593 bound_fns.Push(base::Bind(&AudioRenderer::Play, audio_renderer_)); |
| 612 &AudioRenderer::Play, base::Unretained(audio_renderer_.get()))); | |
| 613 } | |
| 614 | 594 |
| 615 if (video_renderer_) { | 595 if (video_renderer_) |
| 616 bound_fns.Push(base::Bind( | 596 bound_fns.Push(base::Bind(&VideoRenderer::Play, video_renderer_)); |
| 617 &VideoRenderer::Play, base::Unretained(video_renderer_.get()))); | |
| 618 } | |
| 619 | 597 |
| 620 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 598 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
| 621 } | 599 } |
| 622 | 600 |
| 623 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { | 601 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { |
| 624 DCHECK(message_loop_->BelongsToCurrentThread()); | 602 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 625 DCHECK(!pending_callbacks_.get()); | 603 DCHECK(!pending_callbacks_.get()); |
| 626 SerialRunner::Queue bound_fns; | 604 SerialRunner::Queue bound_fns; |
| 627 | 605 |
| 628 if (demuxer_) | 606 if (demuxer_) |
| 629 bound_fns.Push(base::Bind(&Demuxer::Stop, demuxer_)); | 607 bound_fns.Push(base::Bind(&Demuxer::Stop, demuxer_)); |
| 630 | 608 |
| 631 if (audio_renderer_) { | 609 if (audio_renderer_) |
| 632 bound_fns.Push(base::Bind( | 610 bound_fns.Push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); |
| 633 &AudioRenderer::Stop, base::Unretained(audio_renderer_.get()))); | |
| 634 } | |
| 635 | 611 |
| 636 if (video_renderer_) { | 612 if (video_renderer_) |
| 637 bound_fns.Push(base::Bind( | 613 bound_fns.Push(base::Bind(&VideoRenderer::Stop, video_renderer_)); |
| 638 &VideoRenderer::Stop, base::Unretained(video_renderer_.get()))); | |
| 639 } | |
| 640 | 614 |
| 641 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 615 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
| 642 } | 616 } |
| 643 | 617 |
| 644 void Pipeline::OnStopCompleted(PipelineStatus status) { | 618 void Pipeline::OnStopCompleted(PipelineStatus status) { |
| 645 DCHECK(message_loop_->BelongsToCurrentThread()); | 619 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 646 DCHECK_EQ(state_, kStopping); | 620 DCHECK_EQ(state_, kStopping); |
| 647 { | 621 { |
| 648 base::AutoLock l(lock_); | 622 base::AutoLock l(lock_); |
| 649 running_ = false; | 623 running_ = false; |
| 650 } | 624 } |
| 651 | 625 |
| 652 SetState(kStopped); | 626 SetState(kStopped); |
| 653 pending_callbacks_.reset(); | 627 pending_callbacks_.reset(); |
| 654 filter_collection_.reset(); | 628 filter_collection_.reset(); |
| 655 audio_renderer_.reset(); | 629 audio_renderer_ = NULL; |
| 656 video_renderer_.reset(); | 630 video_renderer_ = NULL; |
| 657 demuxer_ = NULL; | 631 demuxer_ = NULL; |
| 658 | 632 |
| 659 // If we stop during initialization/seeking we want to run |seek_cb_| | 633 // If we stop during initialization/seeking we want to run |seek_cb_| |
| 660 // followed by |stop_cb_| so we don't leave outstanding callbacks around. | 634 // followed by |stop_cb_| so we don't leave outstanding callbacks around. |
| 661 if (!seek_cb_.is_null()) { | 635 if (!seek_cb_.is_null()) { |
| 662 base::ResetAndReturn(&seek_cb_).Run(status_); | 636 base::ResetAndReturn(&seek_cb_).Run(status_); |
| 663 error_cb_.Reset(); | 637 error_cb_.Reset(); |
| 664 } | 638 } |
| 665 if (!stop_cb_.is_null()) { | 639 if (!stop_cb_.is_null()) { |
| 666 base::ResetAndReturn(&stop_cb_).Run(); | 640 base::ResetAndReturn(&stop_cb_).Run(); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 demuxer_->Initialize(this, done_cb); | 877 demuxer_->Initialize(this, done_cb); |
| 904 } | 878 } |
| 905 | 879 |
| 906 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { | 880 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { |
| 907 DCHECK(message_loop_->BelongsToCurrentThread()); | 881 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 908 | 882 |
| 909 scoped_refptr<DemuxerStream> stream = | 883 scoped_refptr<DemuxerStream> stream = |
| 910 demuxer_->GetStream(DemuxerStream::AUDIO); | 884 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 911 DCHECK(stream); | 885 DCHECK(stream); |
| 912 | 886 |
| 913 audio_renderer_ = filter_collection_->GetAudioRenderer(); | 887 filter_collection_->SelectAudioRenderer(&audio_renderer_); |
| 914 audio_renderer_->Initialize( | 888 audio_renderer_->Initialize( |
| 915 stream, | 889 stream, |
| 916 *filter_collection_->GetAudioDecoders(), | 890 *filter_collection_->GetAudioDecoders(), |
| 917 done_cb, | 891 done_cb, |
| 918 base::Bind(&Pipeline::OnUpdateStatistics, this), | 892 base::Bind(&Pipeline::OnUpdateStatistics, this), |
| 919 base::Bind(&Pipeline::OnAudioUnderflow, this), | 893 base::Bind(&Pipeline::OnAudioUnderflow, this), |
| 920 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 894 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
| 921 base::Bind(&Pipeline::OnAudioRendererEnded, this), | 895 base::Bind(&Pipeline::OnAudioRendererEnded, this), |
| 922 base::Bind(&Pipeline::OnAudioDisabled, this), | 896 base::Bind(&Pipeline::OnAudioDisabled, this), |
| 923 base::Bind(&Pipeline::SetError, this)); | 897 base::Bind(&Pipeline::SetError, this)); |
| 924 filter_collection_->GetAudioDecoders()->clear(); | 898 filter_collection_->GetAudioDecoders()->clear(); |
| 925 } | 899 } |
| 926 | 900 |
| 927 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { | 901 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { |
| 928 DCHECK(message_loop_->BelongsToCurrentThread()); | 902 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 929 | 903 |
| 930 scoped_refptr<DemuxerStream> stream = | 904 scoped_refptr<DemuxerStream> stream = |
| 931 demuxer_->GetStream(DemuxerStream::VIDEO); | 905 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 932 DCHECK(stream); | 906 DCHECK(stream); |
| 933 | 907 |
| 934 { | 908 { |
| 935 // Get an initial natural size so we have something when we signal | 909 // Get an initial natural size so we have something when we signal |
| 936 // the kHaveMetadata buffering state. | 910 // the kHaveMetadata buffering state. |
| 937 base::AutoLock l(lock_); | 911 base::AutoLock l(lock_); |
| 938 natural_size_ = stream->video_decoder_config().natural_size(); | 912 natural_size_ = stream->video_decoder_config().natural_size(); |
| 939 } | 913 } |
| 940 | 914 |
| 941 video_renderer_ = filter_collection_->GetVideoRenderer(); | 915 filter_collection_->SelectVideoRenderer(&video_renderer_); |
| 942 video_renderer_->Initialize( | 916 video_renderer_->Initialize( |
| 943 stream, | 917 stream, |
| 944 *filter_collection_->GetVideoDecoders(), | 918 *filter_collection_->GetVideoDecoders(), |
| 945 done_cb, | 919 done_cb, |
| 946 base::Bind(&Pipeline::OnUpdateStatistics, this), | 920 base::Bind(&Pipeline::OnUpdateStatistics, this), |
| 947 base::Bind(&Pipeline::OnVideoTimeUpdate, this), | 921 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
| 948 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), | 922 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
| 949 base::Bind(&Pipeline::OnVideoRendererEnded, this), | 923 base::Bind(&Pipeline::OnVideoRendererEnded, this), |
| 950 base::Bind(&Pipeline::SetError, this), | 924 base::Bind(&Pipeline::SetError, this), |
| 951 base::Bind(&Pipeline::GetMediaTime, this), | 925 base::Bind(&Pipeline::GetMediaTime, this), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 970 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 944 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 971 lock_.AssertAcquired(); | 945 lock_.AssertAcquired(); |
| 972 if (!waiting_for_clock_update_) | 946 if (!waiting_for_clock_update_) |
| 973 return; | 947 return; |
| 974 | 948 |
| 975 waiting_for_clock_update_ = false; | 949 waiting_for_clock_update_ = false; |
| 976 clock_->Play(); | 950 clock_->Play(); |
| 977 } | 951 } |
| 978 | 952 |
| 979 } // namespace media | 953 } // namespace media |
| OLD | NEW |