| 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 "mojo/public/cpp/application/connect.h" | 6 #include "mojo/public/cpp/application/connect.h" |
| 7 #include "services/media/factory_service/media_player_impl.h" | 7 #include "services/media/factory_service/media_player_impl.h" |
| 8 #include "services/media/framework/parts/reader.h" | 8 #include "services/media/framework/parts/reader.h" |
| 9 #include "services/media/framework/util/callback_joiner.h" | 9 #include "services/media/framework/util/callback_joiner.h" |
| 10 | 10 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 // Populate streams_ and enable the streams we want. | 50 // Populate streams_ and enable the streams we want. |
| 51 std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create(); | 51 std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create(); |
| 52 | 52 |
| 53 for (MediaTypePtr& stream_type : stream_types) { | 53 for (MediaTypePtr& stream_type : stream_types) { |
| 54 streams_.push_back(std::unique_ptr<Stream>( | 54 streams_.push_back(std::unique_ptr<Stream>( |
| 55 new Stream(streams_.size(), stream_type.Pass()))); | 55 new Stream(streams_.size(), stream_type.Pass()))); |
| 56 Stream& stream = *streams_.back(); | 56 Stream& stream = *streams_.back(); |
| 57 switch (stream.media_type_->medium) { | 57 switch (stream.media_type_->medium) { |
| 58 case MediaTypeMedium::AUDIO: | 58 case MediaTypeMedium::AUDIO: |
| 59 stream.enabled_ = true; | 59 stream.enabled_ = true; |
| 60 PrepareStream(streams_.back(), "mojo:audio_server", | 60 PrepareStream(&stream, "mojo:audio_server", |
| 61 callback_joiner->NewCallback()); | 61 callback_joiner->NewCallback()); |
| 62 break; | 62 break; |
| 63 case MediaTypeMedium::VIDEO: |
| 64 stream.enabled_ = true; |
| 65 // TODO(dalesat): Send video somewhere. |
| 66 PrepareStream(&stream, "nowhere", callback_joiner->NewCallback()); |
| 67 break; |
| 63 // TODO(dalesat): Enable other stream types. | 68 // TODO(dalesat): Enable other stream types. |
| 64 default: | 69 default: |
| 65 break; | 70 break; |
| 66 } | 71 } |
| 67 } | 72 } |
| 68 | 73 |
| 69 callback_joiner->WhenJoined([this]() { | 74 callback_joiner->WhenJoined([this]() { |
| 70 // The enabled streams are prepared. | 75 // The enabled streams are prepared. |
| 71 factory_.reset(); | 76 factory_.reset(); |
| 72 SetReportedMediaState(MediaState::PAUSED); | 77 SetReportedMediaState(MediaState::PAUSED); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 void MediaPlayerImpl::Pause() { | 247 void MediaPlayerImpl::Pause() { |
| 243 target_state_ = MediaState::PAUSED; | 248 target_state_ = MediaState::PAUSED; |
| 244 Update(); | 249 Update(); |
| 245 } | 250 } |
| 246 | 251 |
| 247 void MediaPlayerImpl::Seek(int64_t position) { | 252 void MediaPlayerImpl::Seek(int64_t position) { |
| 248 target_position_ = position; | 253 target_position_ = position; |
| 249 Update(); | 254 Update(); |
| 250 } | 255 } |
| 251 | 256 |
| 252 void MediaPlayerImpl::PrepareStream(const std::unique_ptr<Stream>& stream, | 257 void MediaPlayerImpl::PrepareStream(Stream* stream, |
| 253 const String& url, | 258 const String& url, |
| 254 const std::function<void()>& callback) { | 259 const std::function<void()>& callback) { |
| 255 DCHECK(factory_); | 260 DCHECK(factory_); |
| 256 | 261 |
| 257 demux_->GetProducer(stream->index_, GetProxy(&stream->encoded_producer_)); | 262 demux_->GetProducer(stream->index_, GetProxy(&stream->encoded_producer_)); |
| 258 | 263 |
| 259 if (stream->media_type_->encoding != MediaType::kAudioEncodingLpcm) { | 264 if (stream->media_type_->encoding != MediaType::kAudioEncodingLpcm && |
| 265 stream->media_type_->encoding != MediaType::kVideoEncodingUncompressed) { |
| 260 std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create(); | 266 std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create(); |
| 261 | 267 |
| 262 // Compressed audio. Insert a decoder in front of the sink. The sink would | 268 // Compressed media. Insert a decoder in front of the sink. The sink would |
| 263 // add its own internal decoder, but we want to test the decoder. | 269 // add its own internal decoder, but we want to test the decoder. |
| 264 factory_->CreateDecoder(stream->media_type_.Clone(), | 270 factory_->CreateDecoder(stream->media_type_.Clone(), |
| 265 GetProxy(&stream->decoder_)); | 271 GetProxy(&stream->decoder_)); |
| 266 | 272 |
| 267 MediaConsumerPtr decoder_consumer; | 273 MediaConsumerPtr decoder_consumer; |
| 268 stream->decoder_->GetConsumer(GetProxy(&decoder_consumer)); | 274 stream->decoder_->GetConsumer(GetProxy(&decoder_consumer)); |
| 269 | 275 |
| 270 callback_joiner->Spawn(); | 276 callback_joiner->Spawn(); |
| 271 stream->encoded_producer_->Connect(decoder_consumer.Pass(), | 277 stream->encoded_producer_->Connect(decoder_consumer.Pass(), |
| 272 [&stream, callback_joiner]() { | 278 [stream, callback_joiner]() { |
| 273 stream->encoded_producer_.reset(); | 279 stream->encoded_producer_.reset(); |
| 274 callback_joiner->Complete(); | 280 callback_joiner->Complete(); |
| 275 }); | 281 }); |
| 276 | 282 |
| 277 callback_joiner->Spawn(); | 283 callback_joiner->Spawn(); |
| 278 stream->decoder_->GetOutputType( | 284 stream->decoder_->GetOutputType( |
| 279 [this, &stream, url, callback_joiner](MediaTypePtr output_type) { | 285 [this, stream, url, callback_joiner](MediaTypePtr output_type) { |
| 280 stream->decoder_->GetProducer(GetProxy(&stream->decoded_producer_)); | 286 stream->decoder_->GetProducer(GetProxy(&stream->decoded_producer_)); |
| 281 CreateSink(stream, output_type, url, callback_joiner->NewCallback()); | 287 CreateSink(stream, output_type, url, callback_joiner->NewCallback()); |
| 282 callback_joiner->Complete(); | 288 callback_joiner->Complete(); |
| 283 }); | 289 }); |
| 284 | 290 |
| 285 callback_joiner->WhenJoined(callback); | 291 callback_joiner->WhenJoined(callback); |
| 286 } else { | 292 } else { |
| 287 // Uncompressed audio. Connect the demux stream directly to the sink. This | 293 // Uncompressed media. Connect the demux stream directly to the sink. This |
| 288 // would work for compressed audio as well (the sink would decode), but we | 294 // would work for compressed media as well (the sink would decode), but we |
| 289 // want to test the decoder. | 295 // want to test the decoder. |
| 290 stream->decoded_producer_ = stream->encoded_producer_.Pass(); | 296 stream->decoded_producer_ = stream->encoded_producer_.Pass(); |
| 291 CreateSink(stream, stream->media_type_, url, callback); | 297 CreateSink(stream, stream->media_type_, url, callback); |
| 292 } | 298 } |
| 293 } | 299 } |
| 294 | 300 |
| 295 void MediaPlayerImpl::CreateSink(const std::unique_ptr<Stream>& stream, | 301 void MediaPlayerImpl::CreateSink(Stream* stream, |
| 296 const MediaTypePtr& input_media_type, | 302 const MediaTypePtr& input_media_type, |
| 297 const String& url, | 303 const String& url, |
| 298 const std::function<void()>& callback) { | 304 const std::function<void()>& callback) { |
| 299 DCHECK(input_media_type); | 305 DCHECK(input_media_type); |
| 300 DCHECK(stream->decoded_producer_); | 306 DCHECK(stream->decoded_producer_); |
| 301 DCHECK(factory_); | 307 DCHECK(factory_); |
| 302 | 308 |
| 303 factory_->CreateSink(url, input_media_type.Clone(), GetProxy(&stream->sink_)); | 309 factory_->CreateSink(url, input_media_type.Clone(), GetProxy(&stream->sink_)); |
| 304 | 310 |
| 305 MediaConsumerPtr consumer; | 311 MediaConsumerPtr consumer; |
| 306 stream->sink_->GetConsumer(GetProxy(&consumer)); | 312 stream->sink_->GetConsumer(GetProxy(&consumer)); |
| 307 | 313 |
| 308 stream->decoded_producer_->Connect( | 314 stream->decoded_producer_->Connect( |
| 309 consumer.Pass(), [this, callback, &stream]() { | 315 consumer.Pass(), [this, callback, stream]() { |
| 310 stream->decoded_producer_.reset(); | 316 stream->decoded_producer_.reset(); |
| 311 | 317 |
| 312 DCHECK(stream->state_ == MediaState::UNPREPARED); | 318 DCHECK(stream->state_ == MediaState::UNPREPARED); |
| 313 DCHECK(reported_media_state_ == MediaState::UNPREPARED || | 319 DCHECK(reported_media_state_ == MediaState::UNPREPARED || |
| 314 reported_media_state_ == MediaState::FAULT); | 320 reported_media_state_ == MediaState::FAULT); |
| 315 | 321 |
| 316 stream->state_ = MediaState::PAUSED; | 322 stream->state_ = MediaState::PAUSED; |
| 317 | 323 |
| 318 HandleSinkStatusUpdates(stream); | 324 HandleSinkStatusUpdates(stream); |
| 319 | 325 |
| 320 callback(); | 326 callback(); |
| 321 }); | 327 }); |
| 322 } | 328 } |
| 323 | 329 |
| 324 void MediaPlayerImpl::HandleDemuxMetadataUpdates(uint64_t version, | 330 void MediaPlayerImpl::HandleDemuxMetadataUpdates(uint64_t version, |
| 325 MediaMetadataPtr metadata) { | 331 MediaMetadataPtr metadata) { |
| 326 if (metadata) { | 332 if (metadata) { |
| 327 metadata_ = metadata.Pass(); | 333 metadata_ = metadata.Pass(); |
| 328 status_publisher_.SendUpdates(); | 334 status_publisher_.SendUpdates(); |
| 329 } | 335 } |
| 330 | 336 |
| 331 demux_->GetMetadata(version, | 337 demux_->GetMetadata(version, |
| 332 [this](uint64_t version, MediaMetadataPtr metadata) { | 338 [this](uint64_t version, MediaMetadataPtr metadata) { |
| 333 HandleDemuxMetadataUpdates(version, metadata.Pass()); | 339 HandleDemuxMetadataUpdates(version, metadata.Pass()); |
| 334 }); | 340 }); |
| 335 } | 341 } |
| 336 | 342 |
| 337 void MediaPlayerImpl::HandleSinkStatusUpdates( | 343 void MediaPlayerImpl::HandleSinkStatusUpdates(Stream* stream, |
| 338 const std::unique_ptr<Stream>& stream, | 344 uint64_t version, |
| 339 uint64_t version, | 345 MediaSinkStatusPtr status) { |
| 340 MediaSinkStatusPtr status) { | |
| 341 if (status && status->state > MediaState::UNPREPARED) { | 346 if (status && status->state > MediaState::UNPREPARED) { |
| 342 // We transition to PAUSED when Connect completes. | 347 // We transition to PAUSED when Connect completes. |
| 343 DCHECK(stream->state_ > MediaState::UNPREPARED); | 348 DCHECK(stream->state_ > MediaState::UNPREPARED); |
| 344 stream->state_ = status->state; | 349 stream->state_ = status->state; |
| 345 transform_ = status->timeline_transform.Pass(); | 350 transform_ = status->timeline_transform.Pass(); |
| 346 status_publisher_.SendUpdates(); | 351 status_publisher_.SendUpdates(); |
| 347 Update(); | 352 Update(); |
| 348 } | 353 } |
| 349 | 354 |
| 350 stream->sink_->GetStatus( | 355 stream->sink_->GetStatus( |
| 351 version, [this, &stream](uint64_t version, MediaSinkStatusPtr status) { | 356 version, [this, stream](uint64_t version, MediaSinkStatusPtr status) { |
| 352 HandleSinkStatusUpdates(stream, version, status.Pass()); | 357 HandleSinkStatusUpdates(stream, version, status.Pass()); |
| 353 }); | 358 }); |
| 354 } | 359 } |
| 355 | 360 |
| 356 MediaPlayerImpl::Stream::Stream(size_t index, MediaTypePtr media_type) | 361 MediaPlayerImpl::Stream::Stream(size_t index, MediaTypePtr media_type) |
| 357 : index_(index), media_type_(media_type.Pass()) {} | 362 : index_(index), media_type_(media_type.Pass()) {} |
| 358 | 363 |
| 359 MediaPlayerImpl::Stream::~Stream() {} | 364 MediaPlayerImpl::Stream::~Stream() {} |
| 360 | 365 |
| 361 } // namespace media | 366 } // namespace media |
| 362 } // namespace mojo | 367 } // namespace mojo |
| OLD | NEW |