Index: services/media/factory_service/media_timeline_controller_impl.h |
diff --git a/services/media/factory_service/media_timeline_controller_impl.h b/services/media/factory_service/media_timeline_controller_impl.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7dca89d08a030542c1ed18d96e22db97b6618325 |
--- /dev/null |
+++ b/services/media/factory_service/media_timeline_controller_impl.h |
@@ -0,0 +1,161 @@ |
+// 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_ |