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 "base/logging.h" | 5 #include "base/logging.h" |
6 #include "services/media/factory_service/media_player_impl.h" | 6 #include "services/media/factory_service/media_player_impl.h" |
7 #include "services/media/factory_service/watched.h" | 7 #include "services/media/factory_service/watched.h" |
8 #include "services/media/framework/parts/reader.h" | 8 #include "services/media/framework/parts/reader.h" |
9 #include "url/gurl.h" | 9 #include "url/gurl.h" |
10 | 10 |
11 namespace mojo { | 11 namespace mojo { |
12 namespace media { | 12 namespace media { |
13 | 13 |
14 // static | 14 // static |
15 std::shared_ptr<MediaPlayerImpl> MediaPlayerImpl::Create( | 15 std::shared_ptr<MediaPlayerImpl> MediaPlayerImpl::Create( |
16 const String& origin_url, | 16 const String& origin_url, |
17 InterfaceRequest<MediaPlayer> request, | 17 InterfaceRequest<MediaPlayer> request, |
18 MediaFactoryService* owner) { | 18 MediaFactoryService* owner) { |
19 return std::shared_ptr<MediaPlayerImpl>( | 19 return std::shared_ptr<MediaPlayerImpl>( |
20 new MediaPlayerImpl(origin_url, request.Pass(), owner)); | 20 new MediaPlayerImpl(origin_url, request.Pass(), owner)); |
21 } | 21 } |
22 | 22 |
23 MediaPlayerImpl::MediaPlayerImpl( | 23 MediaPlayerImpl::MediaPlayerImpl(const String& origin_url, |
24 const String& origin_url, | 24 InterfaceRequest<MediaPlayer> request, |
25 InterfaceRequest<MediaPlayer> request, | 25 MediaFactoryService* owner) |
26 MediaFactoryService* owner) | 26 : MediaFactoryService::Product(owner), binding_(this, request.Pass()) { |
27 : MediaFactoryService::Product(owner), | |
28 binding_(this, request.Pass()) { | |
29 DCHECK(origin_url); | 27 DCHECK(origin_url); |
30 | 28 |
31 target_state_.SetWithConsequences(MediaState::PAUSED); | 29 target_state_.SetWithConsequences(MediaState::PAUSED); |
32 target_position_.SetWithConsequences(kNotSeeking); | 30 target_position_.SetWithConsequences(kNotSeeking); |
33 | 31 |
34 // Go away when the client is no longer connected. | 32 // Go away when the client is no longer connected. |
35 binding_.set_connection_error_handler([this]() { | 33 binding_.set_connection_error_handler([this]() { ReleaseFromOwner(); }); |
36 ReleaseFromOwner(); | |
37 }); | |
38 | 34 |
39 app()->ConnectToService("mojo:media_factory", &factory_); | 35 app()->ConnectToService("mojo:media_factory", &factory_); |
40 | 36 |
41 factory_->CreateSource( | 37 factory_->CreateSource(origin_url, |
42 origin_url, | 38 nullptr, // allowed_media_types |
43 nullptr, // allowed_media_types | 39 GetProxy(&source_)); |
44 GetProxy(&source_)); | |
45 | 40 |
46 HandleSourceStatusUpdates(); | 41 HandleSourceStatusUpdates(); |
47 | 42 |
48 source_->GetStreams( | 43 source_->GetStreams( |
49 [this](mojo::Array<MediaSourceStreamDescriptorPtr> descriptors) { | 44 [this](mojo::Array<MediaSourceStreamDescriptorPtr> descriptors) { |
50 // Populate streams_ and enable the streams we want. | 45 // Populate streams_ and enable the streams we want. |
51 std::vector<Event> stream_prepared_events; | 46 std::vector<Event> stream_prepared_events; |
52 | 47 |
53 for (MediaSourceStreamDescriptorPtr& descriptor : descriptors) { | 48 for (MediaSourceStreamDescriptorPtr& descriptor : descriptors) { |
54 streams_.push_back(std::unique_ptr<Stream>(new Stream())); | 49 streams_.push_back(std::unique_ptr<Stream>(new Stream())); |
55 Stream& stream = *streams_.back(); | 50 Stream& stream = *streams_.back(); |
56 stream.descriptor_ = descriptor.Pass(); | 51 stream.descriptor_ = descriptor.Pass(); |
57 switch (stream.descriptor_->media_type->scheme) { | 52 switch (stream.descriptor_->media_type->scheme) { |
58 case MediaTypeScheme::COMPRESSED_AUDIO: | 53 case MediaTypeScheme::COMPRESSED_AUDIO: |
59 case MediaTypeScheme::LPCM: | 54 case MediaTypeScheme::LPCM: |
60 stream.enabled_ = true; | 55 stream.enabled_ = true; |
61 stream_prepared_events.push_back( | 56 stream_prepared_events.push_back( |
62 PrepareStream(streams_.back(), "mojo:audio_server")); | 57 PrepareStream(streams_.back(), "mojo:audio_server")); |
63 break; | 58 break; |
64 // TODO(dalesat): Enable other stream types. | 59 // TODO(dalesat): Enable other stream types. |
65 default: | 60 default: |
66 break; | 61 break; |
67 } | 62 } |
68 } | 63 } |
69 | 64 |
70 event_ = Event::All(stream_prepared_events).When([this]() { | 65 event_ = Event::All(stream_prepared_events).When([this]() { |
71 // The enabled streams are prepared. Prepare the source. | 66 // The enabled streams are prepared. Prepare the source. |
72 factory_.reset(); | 67 factory_.reset(); |
73 source_->Prepare([this]() { | 68 source_->Prepare([this]() { |
74 SetReportedMediaState(MediaState::PAUSED); | 69 SetReportedMediaState(MediaState::PAUSED); |
75 WhenPaused(); | 70 WhenPaused(); |
| 71 }); |
| 72 }); |
76 }); | 73 }); |
77 }); | |
78 }); | |
79 } | 74 } |
80 | 75 |
81 MediaPlayerImpl::~MediaPlayerImpl() { | 76 MediaPlayerImpl::~MediaPlayerImpl() { |
82 event_.Cancel(); | 77 event_.Cancel(); |
83 } | 78 } |
84 | 79 |
85 void MediaPlayerImpl::WhenPaused() { | 80 void MediaPlayerImpl::WhenPaused() { |
86 Event seek_requested = target_position_.BecomesOtherThan(kNotSeeking); | 81 Event seek_requested = target_position_.BecomesOtherThan(kNotSeeking); |
87 Event play_requested = target_state_.Becomes(MediaState::PLAYING); | 82 Event play_requested = target_state_.Becomes(MediaState::PLAYING); |
88 | 83 |
89 event_ = Event::First({ seek_requested, play_requested }); | 84 event_ = Event::First({seek_requested, play_requested}); |
90 | 85 |
91 seek_requested.When([this]() { | 86 seek_requested.When([this]() { WhenPausedAndSeeking(); }); |
92 WhenPausedAndSeeking(); | |
93 }); | |
94 | 87 |
95 play_requested.When([this]() { | 88 play_requested.When([this]() { |
96 flushed_ = false; | 89 flushed_ = false; |
97 | 90 |
98 source_->Prime([this]() { | 91 source_->Prime([this]() { |
99 event_ = ChangeSinkStates(MediaState::PLAYING).When([this]() { | 92 event_ = ChangeSinkStates(MediaState::PLAYING).When([this]() { |
100 WhenPlaying(); | 93 WhenPlaying(); |
101 }); | 94 }); |
102 }); | 95 }); |
103 }); | 96 }); |
104 } | 97 } |
105 | 98 |
106 void MediaPlayerImpl::WhenPlaying() { | 99 void MediaPlayerImpl::WhenPlaying() { |
107 SetReportedMediaState(MediaState::PLAYING); | 100 SetReportedMediaState(MediaState::PLAYING); |
108 | 101 |
109 Event seek_requested = target_position_.BecomesOtherThan(kNotSeeking); | 102 Event seek_requested = target_position_.BecomesOtherThan(kNotSeeking); |
110 Event pause_requested = target_state_.Becomes(MediaState::PAUSED); | 103 Event pause_requested = target_state_.Becomes(MediaState::PAUSED); |
111 Event sinks_ended = AllSinkStatesBecome(MediaState::ENDED); | 104 Event sinks_ended = AllSinkStatesBecome(MediaState::ENDED); |
112 | 105 |
113 event_ = Event::First({ seek_requested, pause_requested, sinks_ended }); | 106 event_ = Event::First({seek_requested, pause_requested, sinks_ended}); |
114 | 107 |
115 seek_requested.When([this]() { | 108 seek_requested.When([this]() { |
116 event_ = ChangeSinkStates(MediaState::PAUSED).When([this]() { | 109 event_ = ChangeSinkStates(MediaState::PAUSED).When([this]() { |
117 WhenPausedAndSeeking(); | 110 WhenPausedAndSeeking(); |
118 }); | 111 }); |
119 }); | 112 }); |
120 | 113 |
121 pause_requested.When([this]() { | 114 pause_requested.When([this]() { |
122 event_ = ChangeSinkStates(MediaState::PAUSED).When([this]() { | 115 event_ = ChangeSinkStates(MediaState::PAUSED).When([this]() { |
123 SetReportedMediaState(MediaState::PAUSED); | 116 SetReportedMediaState(MediaState::PAUSED); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 return Event::All(precursors); | 169 return Event::All(precursors); |
177 } | 170 } |
178 | 171 |
179 void MediaPlayerImpl::SetReportedMediaState(MediaState media_state) { | 172 void MediaPlayerImpl::SetReportedMediaState(MediaState media_state) { |
180 if (reported_media_state_ != media_state) { | 173 if (reported_media_state_ != media_state) { |
181 reported_media_state_ = media_state; | 174 reported_media_state_ = media_state; |
182 StatusUpdated(); | 175 StatusUpdated(); |
183 } | 176 } |
184 } | 177 } |
185 | 178 |
186 void MediaPlayerImpl::GetStatus( | 179 void MediaPlayerImpl::GetStatus(uint64_t version_last_seen, |
187 uint64_t version_last_seen, | 180 const GetStatusCallback& callback) { |
188 const GetStatusCallback& callback) { | |
189 if (version_last_seen < status_version_) { | 181 if (version_last_seen < status_version_) { |
190 RunStatusCallback(callback); | 182 RunStatusCallback(callback); |
191 } else { | 183 } else { |
192 pending_status_requests_.push_back(callback); | 184 pending_status_requests_.push_back(callback); |
193 } | 185 } |
194 } | 186 } |
195 | 187 |
196 void MediaPlayerImpl::Play() { | 188 void MediaPlayerImpl::Play() { |
197 target_state_.SetWithConsequences(MediaState::PLAYING); | 189 target_state_.SetWithConsequences(MediaState::PLAYING); |
198 } | 190 } |
199 | 191 |
200 void MediaPlayerImpl::Pause() { | 192 void MediaPlayerImpl::Pause() { |
201 target_state_.SetWithConsequences(MediaState::PAUSED); | 193 target_state_.SetWithConsequences(MediaState::PAUSED); |
202 } | 194 } |
203 | 195 |
204 void MediaPlayerImpl::Seek(int64_t position) { | 196 void MediaPlayerImpl::Seek(int64_t position) { |
205 DCHECK(position != kNotSeeking); | 197 DCHECK(position != kNotSeeking); |
206 target_position_.SetWithConsequences(position); | 198 target_position_.SetWithConsequences(position); |
207 } | 199 } |
208 | 200 |
209 Event MediaPlayerImpl::PrepareStream( | 201 Event MediaPlayerImpl::PrepareStream(const std::unique_ptr<Stream>& stream, |
210 const std::unique_ptr<Stream>& stream, | 202 const String& url) { |
211 const String& url) { | |
212 DCHECK(factory_); | 203 DCHECK(factory_); |
213 | 204 |
214 Event event = Event::Create(); | 205 Event event = Event::Create(); |
215 | 206 |
216 source_->GetProducer( | 207 source_->GetProducer(stream->descriptor_->index, |
217 stream->descriptor_->index, | 208 GetProxy(&stream->encoded_producer_)); |
218 GetProxy(&stream->encoded_producer_)); | |
219 | 209 |
220 if (stream->descriptor_->media_type->scheme == | 210 if (stream->descriptor_->media_type->scheme == |
221 MediaTypeScheme::COMPRESSED_AUDIO) { | 211 MediaTypeScheme::COMPRESSED_AUDIO) { |
222 // Compressed audio. Insert a decoder in front of the sink. The sink would | 212 // Compressed audio. Insert a decoder in front of the sink. The sink would |
223 // add its own internal decoder, but we want to test the decoder. | 213 // add its own internal decoder, but we want to test the decoder. |
224 factory_->CreateDecoder( | 214 factory_->CreateDecoder(stream->descriptor_->media_type.Clone(), |
225 stream->descriptor_->media_type.Clone(), | 215 GetProxy(&stream->decoder_)); |
226 GetProxy(&stream->decoder_)); | |
227 | 216 |
228 MediaConsumerPtr decoder_consumer; | 217 MediaConsumerPtr decoder_consumer; |
229 stream->decoder_->GetConsumer(GetProxy(&decoder_consumer)); | 218 stream->decoder_->GetConsumer(GetProxy(&decoder_consumer)); |
230 | 219 |
231 Event connect_complete = Event::Create(); | 220 Event connect_complete = Event::Create(); |
232 stream->encoded_producer_->Connect( | 221 stream->encoded_producer_->Connect(decoder_consumer.Pass(), |
233 decoder_consumer.Pass(), | 222 [&stream, connect_complete]() { |
234 [&stream, connect_complete]() { | 223 stream->encoded_producer_.reset(); |
235 stream->encoded_producer_.reset(); | 224 connect_complete.Occur(); |
236 connect_complete.Occur(); | 225 }); |
237 }); | |
238 | 226 |
239 stream->decoder_->GetOutputType( | 227 stream->decoder_->GetOutputType( |
240 [this, &stream, url, event](MediaTypePtr output_type) { | 228 [this, &stream, url, event](MediaTypePtr output_type) { |
241 stream->decoder_->GetProducer(GetProxy(&stream->decoded_producer_)); | 229 stream->decoder_->GetProducer(GetProxy(&stream->decoded_producer_)); |
242 | 230 |
243 CreateSink( | 231 CreateSink(stream, output_type, url, event); |
244 stream, | |
245 output_type, | |
246 url, | |
247 event); | |
248 }); | 232 }); |
249 | 233 |
250 return Event::All({ connect_complete, event }); | 234 return Event::All({connect_complete, event}); |
251 } else { | 235 } else { |
252 // Uncompressed audio. Connect the source stream directly to the sink. This | 236 // Uncompressed audio. Connect the source stream directly to the sink. This |
253 // would work for compressed audio as well (the sink would decode), but we | 237 // would work for compressed audio as well (the sink would decode), but we |
254 // want to test the decoder. | 238 // want to test the decoder. |
255 DCHECK(stream->descriptor_->media_type->scheme == MediaTypeScheme::LPCM); | 239 DCHECK(stream->descriptor_->media_type->scheme == MediaTypeScheme::LPCM); |
256 stream->decoded_producer_ = stream->encoded_producer_.Pass(); | 240 stream->decoded_producer_ = stream->encoded_producer_.Pass(); |
257 CreateSink( | 241 CreateSink(stream, stream->descriptor_->media_type, url, event); |
258 stream, | |
259 stream->descriptor_->media_type, | |
260 url, | |
261 event); | |
262 return event; | 242 return event; |
263 } | 243 } |
264 } | 244 } |
265 | 245 |
266 void MediaPlayerImpl::CreateSink( | 246 void MediaPlayerImpl::CreateSink(const std::unique_ptr<Stream>& stream, |
267 const std::unique_ptr<Stream>& stream, | 247 const MediaTypePtr& input_media_type, |
268 const MediaTypePtr& input_media_type, | 248 const String& url, |
269 const String& url, | 249 Event event) { |
270 Event event) { | |
271 DCHECK(input_media_type); | 250 DCHECK(input_media_type); |
272 DCHECK(stream->decoded_producer_); | 251 DCHECK(stream->decoded_producer_); |
273 DCHECK(factory_); | 252 DCHECK(factory_); |
274 | 253 |
275 factory_->CreateSink( | 254 factory_->CreateSink(url, input_media_type.Clone(), GetProxy(&stream->sink_)); |
276 url, | |
277 input_media_type.Clone(), | |
278 GetProxy(&stream->sink_)); | |
279 | 255 |
280 MediaConsumerPtr consumer; | 256 MediaConsumerPtr consumer; |
281 stream->sink_->GetConsumer(GetProxy(&consumer)); | 257 stream->sink_->GetConsumer(GetProxy(&consumer)); |
282 | 258 |
283 stream->decoded_producer_->Connect( | 259 stream->decoded_producer_->Connect(consumer.Pass(), [this, event, &stream]() { |
284 consumer.Pass(), | 260 stream->decoded_producer_.reset(); |
285 [this, event, &stream]() { | |
286 stream->decoded_producer_.reset(); | |
287 | 261 |
288 DCHECK(stream->state_ == MediaState::UNPREPARED); | 262 DCHECK(stream->state_ == MediaState::UNPREPARED); |
289 DCHECK(reported_media_state_ == MediaState::UNPREPARED || | 263 DCHECK(reported_media_state_ == MediaState::UNPREPARED || |
290 reported_media_state_ == MediaState::FAULT); | 264 reported_media_state_ == MediaState::FAULT); |
291 | 265 |
292 stream->state_.SetWithConsequences(MediaState::PAUSED); | 266 stream->state_.SetWithConsequences(MediaState::PAUSED); |
293 | 267 |
294 HandleSinkStatusUpdates(stream); | 268 HandleSinkStatusUpdates(stream); |
295 | 269 |
296 event.Occur(); | 270 event.Occur(); |
297 }); | 271 }); |
298 } | 272 } |
299 | 273 |
300 void MediaPlayerImpl::StatusUpdated() { | 274 void MediaPlayerImpl::StatusUpdated() { |
301 ++status_version_; | 275 ++status_version_; |
302 while (!pending_status_requests_.empty()) { | 276 while (!pending_status_requests_.empty()) { |
303 RunStatusCallback(pending_status_requests_.front()); | 277 RunStatusCallback(pending_status_requests_.front()); |
304 pending_status_requests_.pop_front(); | 278 pending_status_requests_.pop_front(); |
305 } | 279 } |
306 } | 280 } |
307 | 281 |
308 void MediaPlayerImpl::RunStatusCallback(const GetStatusCallback& callback) | 282 void MediaPlayerImpl::RunStatusCallback( |
309 const { | 283 const GetStatusCallback& callback) const { |
310 MediaPlayerStatusPtr status = MediaPlayerStatus::New(); | 284 MediaPlayerStatusPtr status = MediaPlayerStatus::New(); |
311 status->state = reported_media_state_; | 285 status->state = reported_media_state_; |
312 status->timeline_transform = transform_.Clone(); | 286 status->timeline_transform = transform_.Clone(); |
313 status->metadata = metadata_.Clone(); | 287 status->metadata = metadata_.Clone(); |
314 callback.Run(status_version_, status.Pass()); | 288 callback.Run(status_version_, status.Pass()); |
315 } | 289 } |
316 | 290 |
317 void MediaPlayerImpl::HandleSourceStatusUpdates( | 291 void MediaPlayerImpl::HandleSourceStatusUpdates(uint64_t version, |
318 uint64_t version, | 292 MediaSourceStatusPtr status) { |
319 MediaSourceStatusPtr status) { | |
320 if (status) { | 293 if (status) { |
321 metadata_ = status->metadata.Pass(); | 294 metadata_ = status->metadata.Pass(); |
322 StatusUpdated(); | 295 StatusUpdated(); |
323 } | 296 } |
324 | 297 |
325 source_->GetStatus( | 298 source_->GetStatus(version, |
326 version, | 299 [this](uint64_t version, MediaSourceStatusPtr status) { |
327 [this](uint64_t version, MediaSourceStatusPtr status) { | 300 HandleSourceStatusUpdates(version, status.Pass()); |
328 HandleSourceStatusUpdates(version, status.Pass()); | 301 }); |
329 }); | |
330 } | 302 } |
331 | 303 |
332 void MediaPlayerImpl::HandleSinkStatusUpdates( | 304 void MediaPlayerImpl::HandleSinkStatusUpdates( |
333 const std::unique_ptr<Stream>& stream, | 305 const std::unique_ptr<Stream>& stream, |
334 uint64_t version, | 306 uint64_t version, |
335 MediaSinkStatusPtr status) { | 307 MediaSinkStatusPtr status) { |
336 if (status && status->state > MediaState::UNPREPARED) { | 308 if (status && status->state > MediaState::UNPREPARED) { |
337 // We transition to PAUSED when Connect completes. | 309 // We transition to PAUSED when Connect completes. |
338 DCHECK(stream->state_ > MediaState::UNPREPARED); | 310 DCHECK(stream->state_ > MediaState::UNPREPARED); |
339 stream->state_.SetWithConsequences(status->state); | 311 stream->state_.SetWithConsequences(status->state); |
340 transform_ = status->timeline_transform.Pass(); | 312 transform_ = status->timeline_transform.Pass(); |
341 StatusUpdated(); | 313 StatusUpdated(); |
342 } | 314 } |
343 | 315 |
344 stream->sink_->GetStatus( | 316 stream->sink_->GetStatus( |
345 version, | 317 version, [this, &stream](uint64_t version, MediaSinkStatusPtr status) { |
346 [this, &stream](uint64_t version, MediaSinkStatusPtr status) { | |
347 HandleSinkStatusUpdates(stream, version, status.Pass()); | 318 HandleSinkStatusUpdates(stream, version, status.Pass()); |
348 }); | 319 }); |
349 } | 320 } |
350 | 321 |
351 MediaPlayerImpl::Stream::Stream() { | 322 MediaPlayerImpl::Stream::Stream() { |
352 state_.SetWithConsequences(MediaState::UNPREPARED); | 323 state_.SetWithConsequences(MediaState::UNPREPARED); |
353 } | 324 } |
354 | 325 |
355 MediaPlayerImpl::Stream::~Stream() {} | 326 MediaPlayerImpl::Stream::~Stream() {} |
356 | 327 |
357 } // namespace media | 328 } // namespace media |
358 } // namespace mojo | 329 } // namespace mojo |
OLD | NEW |