blob: 795d123251330416d66df70e1b719cee4f7c5846 [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 SERVICES_MEDIA_FACTORY_SERVICE_MEDIA_PLAYER_IMPL_H_
#define SERVICES_MEDIA_FACTORY_SERVICE_MEDIA_PLAYER_IMPL_H_
#include <limits>
#include <vector>
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/media/common/cpp/timeline.h"
#include "mojo/services/media/common/cpp/timeline_function.h"
#include "mojo/services/media/common/interfaces/media_transport.mojom.h"
#include "mojo/services/media/control/interfaces/media_factory.mojom.h"
#include "mojo/services/media/core/interfaces/seeking_reader.mojom.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 renders streams from an origin specified by URL.
class MediaPlayerImpl : public MediaFactoryService::Product<MediaPlayer>,
public MediaPlayer {
public:
static std::shared_ptr<MediaPlayerImpl> Create(
InterfaceHandle<SeekingReader> reader,
InterfaceHandle<MediaRenderer> audio_renderer,
InterfaceHandle<MediaRenderer> video_renderer,
InterfaceRequest<MediaPlayer> request,
MediaFactoryService* 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;
private:
static constexpr int64_t kMinimumLeadTime = Timeline::ns_from_ms(30);
// Internal state.
enum class State {
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.
};
struct Stream {
Stream();
~Stream();
// TODO(dalesat): Have the sink enlist the decoder.
MediaTypeConverterPtr decoder_;
MediaSinkPtr sink_;
// The following fields are just temporaries used to solve lambda capture
// problems.
MediaPacketProducerPtr encoded_producer_;
MediaPacketProducerPtr decoded_producer_;
InterfaceHandle<MediaRenderer> renderer_;
};
MediaPlayerImpl(InterfaceHandle<SeekingReader> reader,
InterfaceHandle<MediaRenderer> audio_renderer,
InterfaceHandle<MediaRenderer> video_renderer,
InterfaceRequest<MediaPlayer> request,
MediaFactoryService* owner);
// Takes action based on current state.
void Update();
// Creates a TimelineTransform for the specified rate.
TimelineTransformPtr CreateTimelineTransform(float rate);
// Prepares a stream.
void PrepareStream(Stream* stream,
size_t index,
const MediaTypePtr& input_media_type,
const std::function<void()>& callback);
// Creates a sink for a stream.
void CreateSink(Stream* stream,
const MediaTypePtr& input_media_type,
const std::function<void()>& callback);
// Handles a metadata update from the demux. When called with the default
// argument values, initiates demux metadata updates.
void HandleDemuxMetadataUpdates(
uint64_t version = MediaDemux::kInitialMetadata,
MediaMetadataPtr metadata = 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);
MediaFactoryPtr factory_;
MediaDemuxPtr demux_;
MediaTimelineControllerPtr timeline_controller_;
MediaTimelineControlPointPtr timeline_control_point_;
TimelineConsumerPtr timeline_consumer_;
std::vector<std::unique_ptr<Stream>> streams_;
// The state we're currently in.
State state_ = State::kWaiting;
// The state we 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;
// A function that translates local time into presentation time in ns.
TimelineFunction timeline_function_;
CallbackJoiner set_transform_joiner_;
MediaMetadataPtr metadata_;
MojoPublisher<GetStatusCallback> status_publisher_;
// The following fields are just temporaries used to solve lambda capture
// problems.
InterfaceHandle<MediaRenderer> audio_renderer_;
InterfaceHandle<MediaRenderer> video_renderer_;
};
} // namespace media
} // namespace mojo
#endif // SERVICES_MEDIA_FACTORY_SERVICE_MEDIA_PLAYER_IMPL_H_