| Index: services/media/factory_service/media_player_impl.cc
|
| diff --git a/services/media/factory_service/media_player_impl.cc b/services/media/factory_service/media_player_impl.cc
|
| index 8fa10af8d20ed73e2bccbb837b5487b225550cfe..a9632996f27bc8f6ad6860dc2fa5113bc5d5d1de 100644
|
| --- a/services/media/factory_service/media_player_impl.cc
|
| +++ b/services/media/factory_service/media_player_impl.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "base/logging.h"
|
| #include "mojo/public/cpp/application/connect.h"
|
| +#include "mojo/services/media/common/cpp/timeline.h"
|
| #include "services/media/factory_service/media_player_impl.h"
|
| #include "services/media/framework/parts/reader.h"
|
| #include "services/media/framework/util/callback_joiner.h"
|
| @@ -26,14 +27,14 @@ MediaPlayerImpl::MediaPlayerImpl(InterfaceHandle<SeekingReader> reader,
|
| : MediaFactoryService::Product<MediaPlayer>(this, request.Pass(), owner) {
|
| DCHECK(reader);
|
|
|
| - status_publisher_.SetCallbackRunner(
|
| - [this](const GetStatusCallback& callback, uint64_t version) {
|
| - MediaPlayerStatusPtr status = MediaPlayerStatus::New();
|
| - status->state = reported_media_state_;
|
| - status->timeline_transform = transform_.Clone();
|
| - status->metadata = metadata_.Clone();
|
| - callback.Run(version, status.Pass());
|
| - });
|
| + status_publisher_.SetCallbackRunner([this](const GetStatusCallback& callback,
|
| + uint64_t version) {
|
| + MediaPlayerStatusPtr status = MediaPlayerStatus::New();
|
| + status->timeline_transform = TimelineTransform::From(timeline_function_);
|
| + status->end_of_stream = AllSinksAtEndOfStream();
|
| + status->metadata = metadata_.Clone();
|
| + callback.Run(version, status.Pass());
|
| + });
|
|
|
| state_ = State::kWaiting;
|
|
|
| @@ -71,7 +72,6 @@ MediaPlayerImpl::MediaPlayerImpl(InterfaceHandle<SeekingReader> reader,
|
| callback_joiner->WhenJoined([this]() {
|
| // The enabled streams are prepared.
|
| factory_.reset();
|
| - SetReportedMediaState(MediaState::PAUSED);
|
| state_ = State::kPaused;
|
| Update();
|
| });
|
| @@ -84,63 +84,38 @@ void MediaPlayerImpl::Update() {
|
| while (true) {
|
| switch (state_) {
|
| case State::kPaused:
|
| - if (target_position_ != kNotSeeking) {
|
| + if (target_position_ != kUnspecifiedTime) {
|
| WhenPausedAndSeeking();
|
| break;
|
| }
|
|
|
| - if (target_state_ == MediaState::PLAYING) {
|
| + if (target_state_ == State::kPlaying) {
|
| if (!flushed_) {
|
| - ChangeSinkStates(MediaState::PLAYING);
|
| - state_ = State::kWaitingForSinksToPlay;
|
| + SetSinkTimelineTransforms(1, 1);
|
| + state_ = State::kWaiting;
|
| break;
|
| }
|
|
|
| flushed_ = false;
|
| state_ = State::kWaiting;
|
| demux_->Prime([this]() {
|
| - ChangeSinkStates(MediaState::PLAYING);
|
| - state_ = State::kWaitingForSinksToPlay;
|
| + SetSinkTimelineTransforms(1, 1);
|
| + state_ = State::kWaiting;
|
| Update();
|
| });
|
| }
|
| return;
|
|
|
| - case State::kWaitingForSinksToPlay:
|
| - if (AllSinksAre(SinkState::kPlayingOrEnded)) {
|
| - state_ = State::kPlaying;
|
| - if (target_state_ == MediaState::PLAYING) {
|
| - SetReportedMediaState(MediaState::PLAYING);
|
| - }
|
| - }
|
| - return;
|
| -
|
| case State::kPlaying:
|
| - if (target_position_ != kNotSeeking ||
|
| - target_state_ == MediaState::PAUSED) {
|
| - ChangeSinkStates(MediaState::PAUSED);
|
| - state_ = State::kWaitingForSinksToPause;
|
| + if (target_position_ != kUnspecifiedTime ||
|
| + target_state_ == State::kPaused) {
|
| + SetSinkTimelineTransforms(1, 0);
|
| + state_ = State::kWaiting;
|
| break;
|
| }
|
|
|
| - if (AllSinksAre(SinkState::kEnded)) {
|
| - target_state_ = MediaState::ENDED;
|
| - SetReportedMediaState(MediaState::ENDED);
|
| - state_ = State::kPaused;
|
| - break;
|
| - }
|
| - return;
|
| -
|
| - case State::kWaitingForSinksToPause:
|
| - if (AllSinksAre(SinkState::kPausedOrEnded)) {
|
| - if (target_state_ == MediaState::PAUSED) {
|
| - if (AllSinksAre(SinkState::kEnded)) {
|
| - SetReportedMediaState(MediaState::ENDED);
|
| - } else {
|
| - SetReportedMediaState(MediaState::PAUSED);
|
| - }
|
| - }
|
| -
|
| + if (AllSinksAtEndOfStream()) {
|
| + target_state_ = State::kPaused;
|
| state_ = State::kPaused;
|
| break;
|
| }
|
| @@ -166,69 +141,71 @@ void MediaPlayerImpl::WhenPausedAndSeeking() {
|
|
|
| void MediaPlayerImpl::WhenFlushedAndSeeking() {
|
| state_ = State::kWaiting;
|
| - DCHECK(target_position_ != kNotSeeking);
|
| + DCHECK(target_position_ != kUnspecifiedTime);
|
| demux_->Seek(target_position_, [this]() {
|
| - target_position_ = kNotSeeking;
|
| + transform_subject_time_ = target_position_;
|
| + target_position_ = kUnspecifiedTime;
|
| state_ = State::kPaused;
|
| Update();
|
| });
|
| }
|
|
|
| -void MediaPlayerImpl::ChangeSinkStates(MediaState media_state) {
|
| +void MediaPlayerImpl::SetSinkTimelineTransforms(uint32_t reference_delta,
|
| + uint32_t subject_delta) {
|
| + SetSinkTimelineTransforms(
|
| + transform_subject_time_, reference_delta, subject_delta,
|
| + Timeline::local_now() + kMinimumLeadTime, kUnspecifiedTime);
|
| +}
|
| +
|
| +void MediaPlayerImpl::SetSinkTimelineTransforms(
|
| + int64_t subject_time,
|
| + uint32_t reference_delta,
|
| + uint32_t subject_delta,
|
| + int64_t effective_reference_time,
|
| + int64_t effective_subject_time) {
|
| + std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create();
|
| +
|
| for (auto& stream : streams_) {
|
| if (stream->enabled_) {
|
| - if (media_state == MediaState::PAUSED) {
|
| - stream->sink_->Pause();
|
| - } else {
|
| - stream->sink_->Play();
|
| - }
|
| + DCHECK(stream->timeline_consumer_);
|
| + callback_joiner->Spawn();
|
| + stream->timeline_consumer_->SetTimelineTransform(
|
| + subject_time, reference_delta, subject_delta,
|
| + effective_reference_time, effective_subject_time,
|
| + [this, callback_joiner](bool completed) {
|
| + callback_joiner->Complete();
|
| + });
|
| }
|
| }
|
| +
|
| + transform_subject_time_ = kUnspecifiedTime;
|
| +
|
| + callback_joiner->WhenJoined([this, subject_delta]() {
|
| + RCHECK(state_ == State::kWaiting);
|
| +
|
| + if (subject_delta == 0) {
|
| + state_ = State::kPaused;
|
| + } else {
|
| + state_ = State::kPlaying;
|
| + }
|
| +
|
| + Update();
|
| + });
|
| }
|
|
|
| -bool MediaPlayerImpl::AllSinksAre(SinkState sink_state) {
|
| +bool MediaPlayerImpl::AllSinksAtEndOfStream() {
|
| + int result = false;
|
| +
|
| for (auto& stream : streams_) {
|
| if (stream->enabled_) {
|
| - switch (sink_state) {
|
| - case SinkState::kPaused:
|
| - if (stream->state_ != MediaState::PAUSED) {
|
| - return false;
|
| - }
|
| - break;
|
| - case SinkState::kPlaying:
|
| - if (stream->state_ != MediaState::PLAYING) {
|
| - return false;
|
| - }
|
| - break;
|
| - case SinkState::kEnded:
|
| - if (stream->state_ != MediaState::ENDED) {
|
| - return false;
|
| - }
|
| - break;
|
| - case SinkState::kPausedOrEnded:
|
| - if (stream->state_ != MediaState::PAUSED &&
|
| - stream->state_ != MediaState::ENDED) {
|
| - return false;
|
| - }
|
| - break;
|
| - case SinkState::kPlayingOrEnded:
|
| - if (stream->state_ != MediaState::PLAYING &&
|
| - stream->state_ != MediaState::ENDED) {
|
| - return false;
|
| - }
|
| - break;
|
| + result = stream->end_of_stream_;
|
| + if (!result) {
|
| + break;
|
| }
|
| }
|
| }
|
|
|
| - return true;
|
| -}
|
| -
|
| -void MediaPlayerImpl::SetReportedMediaState(MediaState media_state) {
|
| - if (reported_media_state_ != media_state) {
|
| - reported_media_state_ = media_state;
|
| - status_publisher_.SendUpdates();
|
| - }
|
| + return result;
|
| }
|
|
|
| void MediaPlayerImpl::GetStatus(uint64_t version_last_seen,
|
| @@ -237,12 +214,12 @@ void MediaPlayerImpl::GetStatus(uint64_t version_last_seen,
|
| }
|
|
|
| void MediaPlayerImpl::Play() {
|
| - target_state_ = MediaState::PLAYING;
|
| + target_state_ = State::kPlaying;
|
| Update();
|
| }
|
|
|
| void MediaPlayerImpl::Pause() {
|
| - target_state_ = MediaState::PAUSED;
|
| + target_state_ = State::kPaused;
|
| Update();
|
| }
|
|
|
| @@ -304,24 +281,22 @@ void MediaPlayerImpl::CreateSink(Stream* stream,
|
| DCHECK(factory_);
|
|
|
| factory_->CreateSink(url, input_media_type.Clone(), GetProxy(&stream->sink_));
|
| + stream->sink_->GetTimelineControlSite(
|
| + GetProxy(&stream->timeline_control_site_));
|
|
|
| - MediaConsumerPtr consumer;
|
| - stream->sink_->GetConsumer(GetProxy(&consumer));
|
| -
|
| - stream->decoded_producer_->Connect(
|
| - consumer.Pass(), [this, callback, stream]() {
|
| - stream->decoded_producer_.reset();
|
| -
|
| - DCHECK(stream->state_ == MediaState::UNPREPARED);
|
| - DCHECK(reported_media_state_ == MediaState::UNPREPARED ||
|
| - reported_media_state_ == MediaState::FAULT);
|
| + HandleTimelineControlSiteStatusUpdates(stream);
|
|
|
| - stream->state_ = MediaState::PAUSED;
|
| + stream->timeline_control_site_->GetTimelineConsumer(
|
| + GetProxy(&stream->timeline_consumer_));
|
|
|
| - HandleSinkStatusUpdates(stream);
|
| + MediaConsumerPtr consumer;
|
| + stream->sink_->GetConsumer(GetProxy(&consumer));
|
|
|
| - callback();
|
| - });
|
| + stream->decoded_producer_->Connect(consumer.Pass(),
|
| + [this, callback, stream]() {
|
| + stream->decoded_producer_.reset();
|
| + callback();
|
| + });
|
| }
|
|
|
| void MediaPlayerImpl::HandleDemuxMetadataUpdates(uint64_t version,
|
| @@ -337,21 +312,22 @@ void MediaPlayerImpl::HandleDemuxMetadataUpdates(uint64_t version,
|
| });
|
| }
|
|
|
| -void MediaPlayerImpl::HandleSinkStatusUpdates(Stream* stream,
|
| - uint64_t version,
|
| - MediaSinkStatusPtr status) {
|
| - if (status && status->state > MediaState::UNPREPARED) {
|
| - // We transition to PAUSED when Connect completes.
|
| - DCHECK(stream->state_ > MediaState::UNPREPARED);
|
| - stream->state_ = status->state;
|
| - transform_ = status->timeline_transform.Pass();
|
| +void MediaPlayerImpl::HandleTimelineControlSiteStatusUpdates(
|
| + Stream* stream,
|
| + uint64_t version,
|
| + MediaTimelineControlSiteStatusPtr status) {
|
| + if (status) {
|
| + // TODO(dalesat): Why does one sink determine timeline_function_?
|
| + timeline_function_ = status->timeline_transform.To<TimelineFunction>();
|
| + stream->end_of_stream_ = status->end_of_stream;
|
| status_publisher_.SendUpdates();
|
| Update();
|
| }
|
|
|
| - stream->sink_->GetStatus(
|
| - version, [this, stream](uint64_t version, MediaSinkStatusPtr status) {
|
| - HandleSinkStatusUpdates(stream, version, status.Pass());
|
| + stream->timeline_control_site_->GetStatus(
|
| + version, [this, stream](uint64_t version,
|
| + MediaTimelineControlSiteStatusPtr status) {
|
| + HandleTimelineControlSiteStatusUpdates(stream, version, status.Pass());
|
| });
|
| }
|
|
|
|
|