| // Copyright 2018 The Fuchsia 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 GARNET_BIN_MEDIAPLAYER_RENDER_RENDERER_H_ |
| #define GARNET_BIN_MEDIAPLAYER_RENDER_RENDERER_H_ |
| |
| #include <limits> |
| |
| #include <fuchsia/media/cpp/fidl.h> |
| |
| #include "garnet/bin/mediaplayer/graph/nodes/node.h" |
| #include "garnet/bin/mediaplayer/graph/types/stream_type.h" |
| #include "lib/media/timeline/timeline_function.h" |
| |
| namespace media_player { |
| |
| // Abstract base class for sinks that render packets. |
| class Renderer : public Node { |
| public: |
| Renderer(); |
| |
| ~Renderer() override; |
| |
| // Provides an dispatcher object and update callback to the renderer. The |
| // callback should be called to notify of changes in the value returned by |
| // end_of_stream(). Subclasses of Renderer may use this callback to signal |
| // additional changes. |
| void Provision(async_dispatcher_t* dispatcher, fit::closure update_callback); |
| |
| // Revokes the task runner and update callback provided in a previous call to |
| // |Provision|. |
| void Deprovision(); |
| |
| // Node implementation. |
| void Dump(std::ostream& os) const override; |
| |
| void ConfigureConnectors() override; |
| |
| // Returns the types of the streams the renderer is able |
| // to consume. |
| virtual const std::vector<std::unique_ptr<StreamTypeSet>>& |
| GetSupportedStreamTypes() = 0; |
| |
| // Sets the type of stream the renderer will consume. |
| virtual void SetStreamType(const StreamType& stream_type) = 0; |
| |
| // Prepares renderer for playback by satisfying initial demand. |
| virtual void Prime(fit::closure callback) = 0; |
| |
| // Sets the timeline function. |
| virtual void SetTimelineFunction(media::TimelineFunction timeline_function, |
| fit::closure callback); |
| |
| // Sets a program range for this renderer. |
| virtual void SetProgramRange(uint64_t program, int64_t min_pts, |
| int64_t max_pts); |
| |
| // Determines whether end-of-stream has been reached. |
| bool end_of_stream() const; |
| |
| protected: |
| async_dispatcher_t* dispatcher() const { |
| FXL_DCHECK(dispatcher_) << "dispatcher() called on unprovisioned renderer."; |
| return dispatcher_; |
| } |
| |
| // Notifies of state updates (calls the update callback). |
| void NotifyUpdate(); |
| |
| // Called when the value returned by |Progressing| transitions from false to |
| // true. The default implementation does nothing. |
| virtual void OnProgressStarted() {} |
| |
| // Determines if presentation time is progressing or a pending change will |
| // cause it to progress. |
| bool Progressing(); |
| |
| // Sets the PTS at which end of stream will occur. Passing kUnspecifiedTime |
| // indicates that end-of-stream PTS isn't known. |
| void SetEndOfStreamPts(int64_t end_of_stream_pts); |
| |
| // Checks for timeline transitions or end-of-stream. |reference_time| is the |
| // current reference time. |
| void UpdateTimeline(int64_t reference_time); |
| |
| // Posts a task to check for timeline transitions or end-of-stream at the |
| // specified reference time. |
| void UpdateTimelineAt(int64_t reference_time); |
| |
| // Called when the timeline function changes. The default implementation |
| // does nothing. |
| virtual void OnTimelineTransition(); |
| |
| // Gets the current timeline function. |
| const media::TimelineFunction& current_timeline_function() const { |
| return current_timeline_function_; |
| } |
| |
| // Indicates whether the end of stream packet has been encountered. |
| bool end_of_stream_pending() const { |
| return end_of_stream_pts_ != fuchsia::media::NO_TIMESTAMP; |
| } |
| |
| // PTS at which end-of-stream is to occur or |kUnspecifiedTime| if an end- |
| // of-stream packet has not yet been encountered. |
| int64_t end_of_stream_pts() const { return end_of_stream_pts_; } |
| |
| // Returns the minimum PTS for the specified program. |
| int64_t min_pts(uint64_t program) { |
| FXL_DCHECK(program == 0); |
| return program_0_min_pts_; |
| } |
| |
| // Returns the maximum PTS for the specified program. |
| int64_t max_pts(uint64_t program) { |
| FXL_DCHECK(program == 0); |
| return program_0_max_pts_; |
| } |
| |
| private: |
| // Applies pending_timeline_function_ if it's time to do so based on the |
| // given reference time. |
| void ApplyPendingChanges(int64_t reference_time); |
| |
| // If we need to signal end-of-stream in the future, and we know when that is |
| // (because we have a timeline with a non-zero rate), call |UpdateTimelineAt| |
| // so we wake up to do that. It's harmless to call |UpdateTimeline| when |
| // there's nothing to do, so there's no need to cancel this if conditions |
| // change. |
| void MaybeScheduleEndOfStreamPublication(); |
| |
| // Clears the pending timeline function and calls its associated callback. |
| void ClearPendingTimelineFunction(); |
| |
| // Determines if an unrealized timeline function is currently pending. |
| bool TimelineFunctionPending() { |
| return pending_timeline_function_.reference_time() != |
| fuchsia::media::NO_TIMESTAMP; |
| } |
| |
| async_dispatcher_t* dispatcher_; |
| fit::closure update_callback_; |
| media::TimelineFunction current_timeline_function_; |
| media::TimelineFunction pending_timeline_function_; |
| int64_t end_of_stream_pts_ = fuchsia::media::NO_TIMESTAMP; |
| bool end_of_stream_published_ = false; |
| fit::closure set_timeline_function_callback_; |
| int64_t program_0_min_pts_ = std::numeric_limits<int64_t>::min(); |
| int64_t program_0_max_pts_ = std::numeric_limits<int64_t>::max(); |
| }; |
| |
| } // namespace media_player |
| |
| #endif // GARNET_BIN_MEDIAPLAYER_RENDER_RENDERER_H_ |