blob: 82a10d79280df2a123ee9d6b1ac2a6ebb06f8000 [file] [log] [blame]
// 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_