blob: 7dca89d08a030542c1ed18d96e22db97b6618325 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_SERVICES_MEDIA_FACTORY_TIMELINE_CONTROLLER_IMPL_H_
#define MOJO_SERVICES_MEDIA_FACTORY_TIMELINE_CONTROLLER_IMPL_H_
#include <memory>
#include <vector>
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/media/common/cpp/local_time.h"
#include "mojo/services/media/common/cpp/timeline.h"
#include "mojo/services/media/common/cpp/timeline_function.h"
#include "mojo/services/media/core/interfaces/timeline_controller.mojom.h"
#include "services/media/common/mojo_publisher.h"
#include "services/media/factory_service/factory_service.h"
#include "services/media/framework/util/callback_joiner.h"
namespace mojo {
namespace media {
// Mojo agent that controls timing in a graph.
class MediaTimelineControllerImpl
: public MediaFactoryService::Product<MediaTimelineController>,
public MediaTimelineController,
public MediaTimelineControlSite,
public TimelineConsumer {
public:
static std::shared_ptr<MediaTimelineControllerImpl> Create(
InterfaceRequest<MediaTimelineController> request,
MediaFactoryService* owner);
~MediaTimelineControllerImpl() override;
// MediaTimelineController implementation.
void AddControlSite(
InterfaceHandle<MediaTimelineControlSite> control_site) override;
void GetControlSite(
InterfaceRequest<MediaTimelineControlSite> control_site) override;
// MediaTimelineControlSite implementation.
void GetStatus(uint64_t version_last_seen,
const GetStatusCallback& callback) override;
void GetTimelineConsumer(
InterfaceRequest<TimelineConsumer> timeline_consumer) override;
// TimelineConsumer implementation.
void SetTimelineTransform(
int64_t subject_time,
uint32_t reference_delta,
uint32_t subject_delta,
int64_t effective_reference_time,
int64_t effective_subject_time,
const SetTimelineTransformCallback& callback) override;
private:
static constexpr int64_t kDefaultLeadTime = Timeline::ns_from_ms(30);
// Relationship to subordinate control site.
struct SiteState {
SiteState(MediaTimelineControllerImpl* parent,
MediaTimelineControlSitePtr site);
SiteState(SiteState&& other);
~SiteState();
void HandleStatusUpdates(
uint64_t version = MediaTimelineControlSite::kInitialStatus,
MediaTimelineControlSiteStatusPtr status = nullptr);
MediaTimelineControllerImpl* parent_;
MediaTimelineControlSitePtr site_;
TimelineConsumerPtr consumer_;
bool end_of_stream_ = false;
};
class TimelineTransition
: public std::enable_shared_from_this<TimelineTransition> {
public:
TimelineTransition(int64_t reference_time,
int64_t subject_time,
uint32_t reference_delta,
uint32_t subject_delta,
const SetTimelineTransformCallback& callback);
~TimelineTransition();
// Calls returns a new callback for a child (site) transition. THIS METHOD
// WILL ONLY WORK IF THERE IS ALREADY A SHARED POINTER TO THIS OBJECT.
std::function<void(bool)> NewCallback() {
callback_joiner_.Spawn();
std::shared_ptr<TimelineTransition> this_ptr = shared_from_this();
DCHECK(!this_ptr.unique());
return [this_ptr](bool completed) {
DCHECK(this_ptr);
if (!completed && !this_ptr->cancelled_) {
LOG(WARNING) << "A site transition was cancelled unexpectedly.";
}
this_ptr->callback_joiner_.Complete();
};
}
// Cancels this transition.
void Cancel() {
DCHECK(!cancelled_);
cancelled_ = true;
DCHECK(callback_.is_null());
callback_.Run(false);
callback_.reset();
completed_callback_.reset();
}
// Specifies a callback to be called if and when the transition is complete.
// The callback will never be called if the transition is cancelled.
void WhenCompleted(const mojo::Callback<void()>& completed_callback) {
DCHECK(completed_callback_.is_null());
if (callback_.is_null() && !cancelled_) {
completed_callback.Run();
} else {
completed_callback_ = completed_callback;
}
}
// Returns the TimelineFunction that will result from this transition.
const TimelineFunction& new_timeline_function() const {
return new_timeline_function_;
}
private:
TimelineFunction new_timeline_function_;
SetTimelineTransformCallback callback_;
CallbackJoiner callback_joiner_;
bool cancelled_ = false;
Callback<void()> completed_callback_;
};
MediaTimelineControllerImpl(InterfaceRequest<MediaTimelineController> request,
MediaFactoryService* owner);
// Takes action when a site changes its end-of-stream value.
void HandleSiteEndOfStreamChange();
Binding<MediaTimelineControlSite> control_site_binding_;
Binding<TimelineConsumer> consumer_binding_;
MojoPublisher<GetStatusCallback> status_publisher_;
std::vector<SiteState> site_states_;
TimelineFunction current_timeline_function_;
bool end_of_stream_;
std::weak_ptr<TimelineTransition> pending_transition_;
};
} // namespace media
} // namespace mojo
#endif // MOJO_SERVICES_MEDIA_FACTORY_TIMELINE_CONTROLLER_IMPL_H_