blob: 97b410985648910ec906e5bdd9cc31ea99187b41 [file] [log] [blame]
// Copyright 2016 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.
#pragma once
#include <unordered_map>
#include "garnet/bin/media/media_service/media_service_impl.h"
#include "garnet/bin/media/util/callback_joiner.h"
#include "garnet/bin/media/util/fidl_publisher.h"
#include "lib/fidl/cpp/bindings/binding.h"
#include "lib/media/fidl/logs/media_player_channel.fidl.h"
#include "lib/media/fidl/media_service.fidl.h"
#include "lib/media/fidl/media_source.fidl.h"
#include "lib/media/fidl/media_transport.fidl.h"
#include "lib/media/fidl/seeking_reader.fidl.h"
#include "lib/media/fidl/timeline_controller.fidl.h"
#include "lib/media/flog/flog.h"
#include "lib/media/timeline/timeline.h"
#include "lib/media/timeline/timeline_function.h"
namespace media {
// Fidl agent that renders streams derived from a SeekingReader.
class MediaPlayerImpl : public MediaServiceImpl::Product<MediaPlayer>,
public MediaPlayer {
public:
static std::shared_ptr<MediaPlayerImpl> Create(
fidl::InterfaceHandle<SeekingReader> reader,
fidl::InterfaceHandle<MediaRenderer> audio_renderer_handle,
fidl::InterfaceHandle<MediaRenderer> video_renderer_handle,
fidl::InterfaceRequest<MediaPlayer> request,
MediaServiceImpl* owner);
~MediaPlayerImpl() override;
// MediaPlayer implementation.
void GetStatus(uint64_t version_last_seen,
const GetStatusCallback& callback) override;
void Play() override;
void Pause() override;
void Seek(int64_t position) override;
void SetFileChannel(zx::channel file_channel) override;
void SetReader(fidl::InterfaceHandle<SeekingReader> reader_handle) override;
private:
static constexpr int64_t kMinimumLeadTime = Timeline::ns_from_ms(30);
// Internal state.
enum class State {
kInactive, // Waiting for a reader to be supplied.
kWaiting, // Waiting for some work to complete.
kFlushed, // Paused with no data in the pipeline.
kPrimed, // Paused with data in the pipeline.
kPlaying, // Time is progressing.
};
// Holds per-stream info. |renderer_handle_| remains set until the renderer is
// needed, at which point |renderer_handle_| is cleared and |sink_| is set.
// Media for which no renderer was supplied are not represented in
// |streams_by_medium_|.
struct Stream {
fidl::InterfaceHandle<MediaRenderer> renderer_handle_;
MediaSinkPtr sink_;
bool connected_ = false;
};
MediaPlayerImpl(fidl::InterfaceHandle<SeekingReader> reader_handle,
fidl::InterfaceHandle<MediaRenderer> audio_renderer_handle,
fidl::InterfaceHandle<MediaRenderer> video_renderer_handle,
fidl::InterfaceRequest<MediaPlayer> request,
MediaServiceImpl* owner);
// If |reader_handle_| is set, creates the source and call |ConnectSinks|,
// otherwise does nothing.
void MaybeCreateSource();
// Creates sinks as needed and connects enabled streams.
void ConnectSinks();
// Prepares a stream.
void PrepareStream(Stream* stream,
size_t index,
const MediaTypePtr& input_media_type,
const std::function<void()>& callback);
// Takes action based on current state.
void Update();
// Sets the timeline transform.
void SetTimelineTransform(
float rate,
int64_t reference_time,
const TimelineConsumer::SetTimelineTransformCallback callback);
// Creates a TimelineTransform for the specified rate.
TimelineTransformPtr CreateTimelineTransform(float rate,
int64_t reference_time);
// Handles a status update from the source. When called with the default
// argument values, initiates source status updates.
void HandleSourceStatusUpdates(uint64_t version = MediaSource::kInitialStatus,
MediaSourceStatusPtr status = nullptr);
// Handles a status update from the control point. When called with the
// default argument values, initiates control point. status updates.
void HandleTimelineControlPointStatusUpdates(
uint64_t version = MediaTimelineControlPoint::kInitialStatus,
MediaTimelineControlPointStatusPtr status = nullptr);
MediaServicePtr media_service_;
fidl::InterfaceHandle<SeekingReader> reader_handle_;
MediaSourcePtr source_;
fidl::Array<MediaTypePtr> stream_types_;
std::unordered_map<MediaTypeMedium, Stream> streams_by_medium_;
MediaTimelineControllerPtr timeline_controller_;
MediaTimelineControlPointPtr timeline_control_point_;
TimelineConsumerPtr timeline_consumer_;
bool reader_transition_pending_ = false;
// The state we're currently in.
State state_ = State::kWaiting;
// The state we're trying to transition to, either because the client has
// called |Play| or |Pause| or because we've hit end-of-stream.
State target_state_ = State::kFlushed;
// Whether we're currently at end-of-stream.
bool end_of_stream_ = false;
// The position we want to seek to (because the client called Seek) or
// kUnspecifiedTime, which indicates there's no desire to seek.
int64_t target_position_ = kUnspecifiedTime;
// The subject time to be used for SetTimelineTransform. The value is
// kUnspecifiedTime if there's no need to seek or the position we want to
// seek to if there is.
int64_t transform_subject_time_ = kUnspecifiedTime;
// The minimum program range PTS to be used for SetProgramRange.
int64_t program_range_min_pts_ = kMinTime;
// A function that translates local time into presentation time in ns.
TimelineFunction timeline_function_;
MediaSourceStatusPtr source_status_;
FidlPublisher<GetStatusCallback> status_publisher_;
FLOG_INSTANCE_CHANNEL(logs::MediaPlayerChannel, log_channel_);
};
} // namespace media