OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chromecast/media/cma/backend/media_pipeline_backend_manager.h" | 5 #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
| 10 #include "base/location.h" |
10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
11 #include "chromecast/chromecast_features.h" | 12 #include "chromecast/chromecast_features.h" |
12 #include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" | 13 #include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" |
13 #include "chromecast/public/cast_media_shlib.h" | |
14 | 14 |
15 namespace chromecast { | 15 namespace chromecast { |
16 namespace media { | 16 namespace media { |
17 namespace { | 17 namespace { |
18 #if BUILDFLAG(IS_CAST_AUDIO_ONLY) | 18 #if BUILDFLAG(IS_CAST_AUDIO_ONLY) |
19 constexpr int kAudioDecoderLimit = std::numeric_limits<int>::max(); | 19 constexpr int kAudioDecoderLimit = std::numeric_limits<int>::max(); |
20 #else | 20 #else |
21 constexpr int kAudioDecoderLimit = 2; | 21 constexpr int kAudioDecoderLimit = 1; |
22 #endif | 22 #endif |
23 } // namespace | 23 } // namespace |
24 | 24 |
25 MediaPipelineBackendManager::MediaPipelineBackendManager( | 25 MediaPipelineBackendManager::MediaPipelineBackendManager( |
26 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner) | 26 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner) |
27 : media_task_runner_(std::move(media_task_runner)) { | 27 : media_task_runner_(std::move(media_task_runner)), |
28 DCHECK_EQ(2, NUM_DECODER_TYPES); | 28 playing_noneffects_audio_streams_count_(0), |
29 decoder_count_[AUDIO_DECODER] = 0; | 29 allow_volume_feedback_observers_( |
30 decoder_count_[VIDEO_DECODER] = 0; | 30 new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()) { |
| 31 for (int i = 0; i < NUM_DECODER_TYPES; ++i) { |
| 32 decoder_count_[i] = 0; |
| 33 } |
31 } | 34 } |
32 | 35 |
33 MediaPipelineBackendManager::~MediaPipelineBackendManager() { | 36 MediaPipelineBackendManager::~MediaPipelineBackendManager() { |
34 } | 37 } |
35 | 38 |
36 std::unique_ptr<MediaPipelineBackend> | 39 std::unique_ptr<MediaPipelineBackend> |
37 MediaPipelineBackendManager::CreateMediaPipelineBackend( | 40 MediaPipelineBackendManager::CreateMediaPipelineBackend( |
38 const media::MediaPipelineDeviceParams& params) { | 41 const media::MediaPipelineDeviceParams& params) { |
39 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 42 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
40 return CreateMediaPipelineBackend(params, 0); | 43 return base::MakeUnique<MediaPipelineBackendWrapper>(params, this); |
41 } | |
42 | |
43 std::unique_ptr<MediaPipelineBackend> | |
44 MediaPipelineBackendManager::CreateMediaPipelineBackend( | |
45 const media::MediaPipelineDeviceParams& params, | |
46 int stream_type) { | |
47 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
48 LOG(INFO) << "Creating a " << params.device_id << " stream."; | |
49 std::unique_ptr<MediaPipelineBackend> backend_ptr( | |
50 new MediaPipelineBackendWrapper( | |
51 base::WrapUnique( | |
52 media::CastMediaShlib::CreateMediaPipelineBackend(params)), | |
53 stream_type, GetVolumeMultiplier(stream_type), this)); | |
54 media_pipeline_backends_.push_back(backend_ptr.get()); | |
55 return backend_ptr; | |
56 } | 44 } |
57 | 45 |
58 bool MediaPipelineBackendManager::IncrementDecoderCount(DecoderType type) { | 46 bool MediaPipelineBackendManager::IncrementDecoderCount(DecoderType type) { |
59 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 47 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
60 DCHECK(type < NUM_DECODER_TYPES); | 48 DCHECK(type < NUM_DECODER_TYPES); |
61 const int limit = (type == AUDIO_DECODER) ? kAudioDecoderLimit : 1; | 49 const int limit = (type == AUDIO_DECODER) ? kAudioDecoderLimit : 1; |
62 if (decoder_count_[type] >= limit) { | 50 if (decoder_count_[type] >= limit) { |
63 LOG(WARNING) << "Decoder limit reached for type " << type; | 51 LOG(WARNING) << "Decoder limit reached for type " << type; |
64 return false; | 52 return false; |
65 } | 53 } |
66 | 54 |
67 ++decoder_count_[type]; | 55 ++decoder_count_[type]; |
68 return true; | 56 return true; |
69 } | 57 } |
70 | 58 |
71 void MediaPipelineBackendManager::DecrementDecoderCount(DecoderType type) { | 59 void MediaPipelineBackendManager::DecrementDecoderCount(DecoderType type) { |
72 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 60 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
73 DCHECK(type < NUM_DECODER_TYPES); | 61 DCHECK(type < NUM_DECODER_TYPES); |
74 DCHECK(decoder_count_[type] > 0); | 62 DCHECK(decoder_count_[type] > 0); |
| 63 |
75 decoder_count_[type]--; | 64 decoder_count_[type]--; |
76 } | 65 } |
77 | 66 |
78 void MediaPipelineBackendManager::OnMediaPipelineBackendDestroyed( | 67 void MediaPipelineBackendManager::UpdatePlayingAudioCount(int change) { |
79 const MediaPipelineBackend* backend) { | 68 DCHECK(change == -1 || change == 1) << "bad count change: " << change; |
80 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
81 media_pipeline_backends_.erase( | |
82 std::remove(media_pipeline_backends_.begin(), | |
83 media_pipeline_backends_.end(), backend), | |
84 media_pipeline_backends_.end()); | |
85 } | |
86 | 69 |
87 void MediaPipelineBackendManager::SetVolumeMultiplier(int stream_type, | 70 // Volume feedback sounds are only allowed when there are no non-effects |
88 float volume) { | 71 // audio streams playing. |
89 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 72 bool prev_allow_feedback = (playing_noneffects_audio_streams_count_ == 0); |
90 volume = std::max(0.0f, std::min(volume, 1.0f)); | 73 playing_noneffects_audio_streams_count_ += change; |
91 volume_by_stream_type_[stream_type] = volume; | 74 DCHECK_GE(playing_noneffects_audio_streams_count_, 0); |
| 75 bool new_allow_feedback = (playing_noneffects_audio_streams_count_ == 0); |
92 | 76 |
93 // Set volume for each open media pipeline backends. | 77 if (new_allow_feedback != prev_allow_feedback) { |
94 for (auto it = media_pipeline_backends_.begin(); | 78 allow_volume_feedback_observers_->Notify( |
95 it != media_pipeline_backends_.end(); it++) { | 79 FROM_HERE, &AllowVolumeFeedbackObserver::AllowVolumeFeedbackSounds, |
96 MediaPipelineBackendWrapper* wrapper = | 80 new_allow_feedback); |
97 static_cast<MediaPipelineBackendWrapper*>(*it); | |
98 if (wrapper->GetStreamType() == stream_type) | |
99 wrapper->SetStreamTypeVolume(volume); | |
100 } | 81 } |
101 } | 82 } |
102 | 83 |
103 float MediaPipelineBackendManager::GetVolumeMultiplier(int stream_type) { | 84 void MediaPipelineBackendManager::AddAllowVolumeFeedbackObserver( |
104 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 85 AllowVolumeFeedbackObserver* observer) { |
105 auto it = volume_by_stream_type_.find(stream_type); | 86 allow_volume_feedback_observers_->AddObserver(observer); |
106 if (it == volume_by_stream_type_.end()) { | 87 } |
107 return 1.0; | 88 |
108 } else { | 89 void MediaPipelineBackendManager::RemoveAllowVolumeFeedbackObserver( |
109 return it->second; | 90 AllowVolumeFeedbackObserver* observer) { |
110 } | 91 allow_volume_feedback_observers_->RemoveObserver(observer); |
111 } | 92 } |
112 | 93 |
113 } // namespace media | 94 } // namespace media |
114 } // namespace chromecast | 95 } // namespace chromecast |
OLD | NEW |