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_impl.h" | 5 #include "media/base/pipeline_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 void Suspend(); | 50 void Suspend(); |
51 void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time); | 51 void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time); |
52 void SetPlaybackRate(double playback_rate); | 52 void SetPlaybackRate(double playback_rate); |
53 void SetVolume(float volume); | 53 void SetVolume(float volume); |
54 base::TimeDelta GetMediaTime() const; | 54 base::TimeDelta GetMediaTime() const; |
55 Ranges<base::TimeDelta> GetBufferedTimeRanges() const; | 55 Ranges<base::TimeDelta> GetBufferedTimeRanges() const; |
56 bool DidLoadingProgress(); | 56 bool DidLoadingProgress(); |
57 PipelineStatistics GetStatistics() const; | 57 PipelineStatistics GetStatistics() const; |
58 void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb); | 58 void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb); |
59 | 59 |
| 60 // |enabledTrackIds| contains track ids of enabled audio tracks. |
| 61 void OnEnabledAudioTracksChanged( |
| 62 const std::vector<MediaTrack::Id>& enabledTrackIds); |
| 63 |
| 64 // |trackId| either empty, which means no video track is selected, or contain |
| 65 // one element - the selected video track id. |
| 66 void OnSelectedVideoTrackChanged( |
| 67 const std::vector<MediaTrack::Id>& selectedTrackId); |
| 68 |
60 private: | 69 private: |
61 // Contains state shared between main and media thread. | 70 // Contains state shared between main and media thread. |
62 // Main thread can only read. Media thread can both - read and write. | 71 // Main thread can only read. Media thread can both - read and write. |
63 // So it is not necessary to lock when reading from the media thread. | 72 // So it is not necessary to lock when reading from the media thread. |
64 // This struct should only contain state that is not immediately needed by | 73 // This struct should only contain state that is not immediately needed by |
65 // PipelineClient and can be cached on the media thread until queried. | 74 // PipelineClient and can be cached on the media thread until queried. |
66 // Alternatively we could cache it on the main thread by posting the | 75 // Alternatively we could cache it on the main thread by posting the |
67 // notification to the main thread. But some of the state change notifications | 76 // notification to the main thread. But some of the state change notifications |
68 // (OnStatisticsUpdate and OnBufferedTimeRangesChanged) arrive much more | 77 // (OnStatisticsUpdate and OnBufferedTimeRangesChanged) arrive much more |
69 // frequently than needed. Posting all those notifications to the main thread | 78 // frequently than needed. Posting all those notifications to the main thread |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 492 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
484 | 493 |
485 if (state_ != kPlaying) | 494 if (state_ != kPlaying) |
486 return; | 495 return; |
487 | 496 |
488 DCHECK(!renderer_ended_); | 497 DCHECK(!renderer_ended_); |
489 renderer_ended_ = true; | 498 renderer_ended_ = true; |
490 CheckPlaybackEnded(); | 499 CheckPlaybackEnded(); |
491 } | 500 } |
492 | 501 |
| 502 void PipelineImpl::OnEnabledAudioTracksChanged( |
| 503 const std::vector<MediaTrack::Id>& enabledTrackIds) { |
| 504 DCHECK(thread_checker_.CalledOnValidThread()); |
| 505 media_task_runner_->PostTask( |
| 506 FROM_HERE, |
| 507 base::Bind(&RendererWrapper::OnEnabledAudioTracksChanged, |
| 508 base::Unretained(renderer_wrapper_.get()), enabledTrackIds)); |
| 509 } |
| 510 |
| 511 void PipelineImpl::OnSelectedVideoTrackChanged( |
| 512 const std::vector<MediaTrack::Id>& selectedTrackId) { |
| 513 DCHECK(thread_checker_.CalledOnValidThread()); |
| 514 media_task_runner_->PostTask( |
| 515 FROM_HERE, |
| 516 base::Bind(&RendererWrapper::OnSelectedVideoTrackChanged, |
| 517 base::Unretained(renderer_wrapper_.get()), selectedTrackId)); |
| 518 } |
| 519 |
| 520 void PipelineImpl::RendererWrapper::OnEnabledAudioTracksChanged( |
| 521 const std::vector<MediaTrack::Id>& enabledTrackIds) { |
| 522 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 523 |
| 524 // Track status notifications might be delivered asynchronously. If we receive |
| 525 // a notification when pipeline is stopped/shut down, it's safe to ignore it. |
| 526 if (state_ == kStopping || state_ == kStopped) { |
| 527 return; |
| 528 } |
| 529 |
| 530 DCHECK(demuxer_); |
| 531 DCHECK(shared_state_.renderer); |
| 532 |
| 533 base::TimeDelta currTime = (state_ == kPlaying) |
| 534 ? shared_state_.renderer->GetMediaTime() |
| 535 : start_timestamp_; |
| 536 demuxer_->OnEnabledAudioTracksChanged(enabledTrackIds, currTime); |
| 537 } |
| 538 |
| 539 void PipelineImpl::RendererWrapper::OnSelectedVideoTrackChanged( |
| 540 const std::vector<MediaTrack::Id>& selectedTrackId) { |
| 541 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 542 |
| 543 // Track status notifications might be delivered asynchronously. If we receive |
| 544 // a notification when pipeline is stopped/shut down, it's safe to ignore it. |
| 545 if (state_ == kStopping || state_ == kStopped) { |
| 546 return; |
| 547 } |
| 548 |
| 549 DCHECK(demuxer_); |
| 550 DCHECK(shared_state_.renderer); |
| 551 |
| 552 base::TimeDelta currTime = (state_ == kPlaying) |
| 553 ? shared_state_.renderer->GetMediaTime() |
| 554 : start_timestamp_; |
| 555 demuxer_->OnSelectedVideoTrackChanged(selectedTrackId, currTime); |
| 556 } |
| 557 |
493 void PipelineImpl::RendererWrapper::OnStatisticsUpdate( | 558 void PipelineImpl::RendererWrapper::OnStatisticsUpdate( |
494 const PipelineStatistics& stats) { | 559 const PipelineStatistics& stats) { |
495 DVLOG(3) << __FUNCTION__; | 560 DVLOG(3) << __FUNCTION__; |
496 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 561 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
497 | 562 |
498 base::AutoLock auto_lock(shared_state_lock_); | 563 base::AutoLock auto_lock(shared_state_lock_); |
499 shared_state_.statistics.audio_bytes_decoded += stats.audio_bytes_decoded; | 564 shared_state_.statistics.audio_bytes_decoded += stats.audio_bytes_decoded; |
500 shared_state_.statistics.video_bytes_decoded += stats.video_bytes_decoded; | 565 shared_state_.statistics.video_bytes_decoded += stats.video_bytes_decoded; |
501 shared_state_.statistics.video_frames_decoded += stats.video_frames_decoded; | 566 shared_state_.statistics.video_frames_decoded += stats.video_frames_decoded; |
502 shared_state_.statistics.video_frames_dropped += stats.video_frames_dropped; | 567 shared_state_.statistics.video_frames_dropped += stats.video_frames_dropped; |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 seek_cb_.Reset(); | 1026 seek_cb_.Reset(); |
962 suspend_cb_.Reset(); | 1027 suspend_cb_.Reset(); |
963 client_ = nullptr; | 1028 client_ = nullptr; |
964 | 1029 |
965 // Invalidate self weak pointers effectively canceling all pending | 1030 // Invalidate self weak pointers effectively canceling all pending |
966 // notifications in the message queue. | 1031 // notifications in the message queue. |
967 weak_factory_.InvalidateWeakPtrs(); | 1032 weak_factory_.InvalidateWeakPtrs(); |
968 } | 1033 } |
969 | 1034 |
970 void PipelineImpl::Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) { | 1035 void PipelineImpl::Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) { |
971 DVLOG(2) << __FUNCTION__; | 1036 DVLOG(2) << __FUNCTION__ << " to " << time.InMicroseconds(); |
972 DCHECK(thread_checker_.CalledOnValidThread()); | 1037 DCHECK(thread_checker_.CalledOnValidThread()); |
973 DCHECK(!seek_cb.is_null()); | 1038 DCHECK(!seek_cb.is_null()); |
974 | 1039 |
975 if (!IsRunning()) { | 1040 if (!IsRunning()) { |
976 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; | 1041 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; |
977 return; | 1042 return; |
978 } | 1043 } |
979 | 1044 |
980 DCHECK(seek_cb_.is_null()); | 1045 DCHECK(seek_cb_.is_null()); |
981 seek_cb_ = seek_cb; | 1046 seek_cb_ = seek_cb; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 void PipelineImpl::OnSuspendDone(base::TimeDelta suspend_time) { | 1295 void PipelineImpl::OnSuspendDone(base::TimeDelta suspend_time) { |
1231 DVLOG(3) << __FUNCTION__ << "(" << suspend_time.InMicroseconds() << ")"; | 1296 DVLOG(3) << __FUNCTION__ << "(" << suspend_time.InMicroseconds() << ")"; |
1232 DCHECK(thread_checker_.CalledOnValidThread()); | 1297 DCHECK(thread_checker_.CalledOnValidThread()); |
1233 DCHECK(IsRunning()); | 1298 DCHECK(IsRunning()); |
1234 | 1299 |
1235 DCHECK(!suspend_cb_.is_null()); | 1300 DCHECK(!suspend_cb_.is_null()); |
1236 base::ResetAndReturn(&suspend_cb_).Run(PIPELINE_OK); | 1301 base::ResetAndReturn(&suspend_cb_).Run(PIPELINE_OK); |
1237 } | 1302 } |
1238 | 1303 |
1239 } // namespace media | 1304 } // namespace media |
OLD | NEW |