OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/remoting/remoting_controller.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "media/base/bind_to_current_loop.h" | |
xhwang
2016/10/04 06:30:29
nit: not needed?
xjz
2016/10/04 19:21:29
Done.
| |
10 | |
11 namespace media { | |
12 | |
13 RemotingController::RemotingController( | |
14 mojom::RemotingSourceRequest source_request, | |
15 mojom::RemoterPtr remoter) | |
16 : is_fullscreen_(false), | |
17 is_sink_available_(false), | |
18 is_remoting_(false), | |
19 binding_(this, std::move(source_request)), | |
20 remoter_(std::move(remoter)), | |
21 task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
22 weak_factory_(this) {} | |
xhwang
2016/10/04 06:30:29
|has_audio| and |has_video| are not initialized. T
xjz
2016/10/04 19:21:29
Done.
| |
23 | |
24 RemotingController::~RemotingController() {} | |
25 | |
26 void RemotingController::OnSinkAvailable() { | |
27 DCHECK(task_runner_->BelongsToCurrentThread()); | |
xhwang
2016/10/04 06:30:29
Add include for base::SingleThreadTaskRunner
xjz
2016/10/04 19:21:29
Done.
| |
28 | |
29 is_sink_available_ = true; | |
30 UpdateAndMaybeSwitch(); | |
31 } | |
32 | |
33 void RemotingController::OnSinkGone() { | |
34 DCHECK(task_runner_->BelongsToCurrentThread()); | |
35 | |
36 is_sink_available_ = false; | |
37 UpdateAndMaybeSwitch(); | |
38 } | |
39 | |
40 void RemotingController::OnStarted() { | |
41 DCHECK(task_runner_->BelongsToCurrentThread()); | |
42 | |
43 VLOG(1) << "Remoting started successively."; | |
44 if (is_remoting_) | |
45 switch_renderer_cb_.Run(); | |
46 else | |
47 remoter_->Stop(mojom::RemotingStopReason::LOCAL_PLAYBACK); | |
48 } | |
49 | |
50 void RemotingController::OnStartFailed(mojom::RemotingStartFailReason reason) { | |
51 DCHECK(task_runner_->BelongsToCurrentThread()); | |
52 | |
53 VLOG(1) << "Failed to start remoting:" << reason; | |
54 is_remoting_ = false; | |
55 } | |
56 | |
57 void RemotingController::OnMessageFromSink( | |
58 const std::vector<uint8_t>& message) { | |
59 DCHECK(task_runner_->BelongsToCurrentThread()); | |
60 | |
61 // TODO(xjz): Merge with Eric's CL to handle the RPC messages here. | |
62 NOTIMPLEMENTED(); | |
63 } | |
64 | |
65 void RemotingController::OnStopped(mojom::RemotingStopReason reason) { | |
66 DCHECK(task_runner_->BelongsToCurrentThread()); | |
67 | |
68 VLOG(1) << "Remoting stopped: " << reason; | |
69 is_remoting_ = false; | |
70 } | |
71 | |
72 void RemotingController::OnEnteredFullscreen() { | |
73 DCHECK(task_runner_->BelongsToCurrentThread()); | |
74 | |
75 is_fullscreen_ = true; | |
76 UpdateAndMaybeSwitch(); | |
77 } | |
78 | |
79 void RemotingController::OnExitedFullscreen() { | |
80 DCHECK(task_runner_->BelongsToCurrentThread()); | |
81 | |
82 is_fullscreen_ = false; | |
83 UpdateAndMaybeSwitch(); | |
84 } | |
85 | |
86 void RemotingController::OnSetCdm(CdmContext* cdm_context) { | |
87 DCHECK(task_runner_->BelongsToCurrentThread()); | |
88 | |
89 // TODO(xjz): Not implemented. Will add in up-coming change. | |
90 NOTIMPLEMENTED(); | |
91 } | |
92 | |
93 void RemotingController::SetSwitchRenderCallback( | |
94 const SwitchRendererCallback& cb) { | |
95 DCHECK(task_runner_->BelongsToCurrentThread()); | |
96 DCHECK(!cb.is_null()); | |
97 | |
98 switch_renderer_cb_ = cb; | |
99 } | |
100 | |
101 void RemotingController::OnMetadata(const PipelineMetadata& metadata) { | |
102 DCHECK(task_runner_->BelongsToCurrentThread()); | |
103 | |
104 has_video_ = metadata.has_video; | |
105 has_audio_ = metadata.has_audio; | |
106 DCHECK(has_video_ || has_audio_); | |
107 | |
108 if (has_video_) { | |
109 DCHECK(metadata.video_decoder_config.IsValidConfig()); | |
110 video_decoder_config_ = metadata.video_decoder_config; | |
111 } | |
112 if (has_audio_) { | |
113 DCHECK(metadata.audio_decoder_config.IsValidConfig()); | |
114 audio_decoder_config_ = metadata.audio_decoder_config; | |
115 } | |
116 UpdateAndMaybeSwitch(); | |
117 } | |
118 | |
119 bool RemotingController::IsVideoConfigSupported() { | |
120 DCHECK(task_runner_->BelongsToCurrentThread()); | |
121 | |
122 if (!has_video_) | |
123 return true; | |
xhwang
2016/10/04 06:30:29
API-wise, it's really odd that IsVideoConfigSuppor
xjz
2016/10/04 19:21:29
Done.
| |
124 | |
125 switch (video_decoder_config_.codec()) { | |
126 case VideoCodec::kCodecH264: | |
127 case VideoCodec::kCodecVP8: | |
128 return true; | |
129 default: | |
130 VLOG(2) << "Remoting does not support video codec: " | |
131 << video_decoder_config_.codec(); | |
132 return false; | |
133 } | |
134 } | |
135 | |
136 bool RemotingController::IsAudioConfigSupported() { | |
137 DCHECK(task_runner_->BelongsToCurrentThread()); | |
138 | |
139 if (!has_audio_) | |
140 return true; | |
xhwang
2016/10/04 06:30:30
ditto
xjz
2016/10/04 19:21:29
Done.
| |
141 | |
142 switch (audio_decoder_config_.codec()) { | |
143 case AudioCodec::kCodecAAC: | |
144 case AudioCodec::kCodecMP3: | |
145 case AudioCodec::kCodecPCM: | |
146 case AudioCodec::kCodecVorbis: | |
147 case AudioCodec::kCodecFLAC: | |
148 case AudioCodec::kCodecAMR_NB: | |
149 case AudioCodec::kCodecAMR_WB: | |
150 case AudioCodec::kCodecPCM_MULAW: | |
151 case AudioCodec::kCodecGSM_MS: | |
152 case AudioCodec::kCodecPCM_S16BE: | |
153 case AudioCodec::kCodecPCM_S24BE: | |
154 case AudioCodec::kCodecOpus: | |
155 case AudioCodec::kCodecEAC3: | |
156 case AudioCodec::kCodecPCM_ALAW: | |
157 case AudioCodec::kCodecALAC: | |
158 case AudioCodec::kCodecAC3: | |
159 return true; | |
160 default: | |
161 VLOG(2) << "Remoting does not support audio codec: " | |
162 << audio_decoder_config_.codec(); | |
163 return false; | |
164 } | |
165 } | |
166 | |
167 void RemotingController::UpdateAndMaybeSwitch() { | |
168 DCHECK(task_runner_->BelongsToCurrentThread()); | |
169 | |
170 // TODO(xjz): The switching logic for encrypted content will be added in a | |
171 // later CL. | |
172 | |
173 // Demuxer is not initialized yet. | |
174 if (!has_audio_ && !has_video_) | |
175 return; | |
176 | |
177 bool should_be_remoting = | |
178 is_sink_available_ && is_fullscreen_ && IsVideoConfigSupported() && | |
179 IsAudioConfigSupported() && !video_decoder_config_.is_encrypted() && | |
xhwang
2016/10/04 06:30:30
What if the audio is encrypted?
xjz
2016/10/04 19:21:29
Add check for encrypted audio too.
| |
180 !switch_renderer_cb_.is_null(); | |
xhwang
2016/10/04 06:30:29
In what case can |switch_renderer_cb_| be null? Ca
xhwang
2016/10/04 06:30:30
This line is a bit hard to reason about. Could you
xjz
2016/10/04 19:21:29
Done.
xjz
2016/10/04 19:21:29
Done.
| |
181 if (is_remoting_ == should_be_remoting) | |
182 return; | |
183 | |
184 // Switch between local and remoting. | |
185 is_remoting_ = should_be_remoting; | |
186 if (is_remoting_) { | |
187 remoter_->Start(); | |
xhwang
2016/10/04 06:30:29
Please add a comment that switch_renderer_cb_.Run(
xjz
2016/10/04 19:21:29
Done.
| |
188 } else { | |
189 switch_renderer_cb_.Run(); | |
190 remoter_->Stop(mojom::RemotingStopReason::LOCAL_PLAYBACK); | |
191 } | |
192 } | |
193 | |
194 } // namespace media | |
OLD | NEW |