blob: 37478e46172b56c1769d0e0d26a71358f8d620e0 [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.
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "services/media/factory_service/media_demux_impl.h"
#include "services/media/framework/parts/reader_cache.h"
#include "services/media/framework/util/callback_joiner.h"
#include "services/media/framework_mojo/mojo_reader.h"
#include "services/media/framework_mojo/mojo_type_conversions.h"
namespace mojo {
namespace media {
// static
std::shared_ptr<MediaDemuxImpl> MediaDemuxImpl::Create(
InterfaceHandle<SeekingReader> reader,
InterfaceRequest<MediaDemux> request,
MediaFactoryService* owner) {
return std::shared_ptr<MediaDemuxImpl>(
new MediaDemuxImpl(reader.Pass(), request.Pass(), owner));
}
MediaDemuxImpl::MediaDemuxImpl(InterfaceHandle<SeekingReader> reader,
InterfaceRequest<MediaDemux> request,
MediaFactoryService* owner)
: MediaFactoryService::Product<MediaDemux>(this, request.Pass(), owner) {
DCHECK(reader);
task_runner_ = base::MessageLoop::current()->task_runner();
DCHECK(task_runner_);
metadata_publisher_.SetCallbackRunner(
[this](const GetMetadataCallback& callback, uint64_t version) {
callback.Run(version, demux_ ? MediaMetadata::From(demux_->metadata())
: nullptr);
});
std::shared_ptr<Reader> reader_ptr = MojoReader::Create(reader.Pass());
if (!reader_ptr) {
NOTREACHED() << "couldn't create reader";
return;
}
std::shared_ptr<ReaderCache> reader_cache_ptr =
ReaderCache::Create(reader_ptr);
if (!reader_cache_ptr) {
NOTREACHED() << "couldn't create reader cache";
return;
}
demux_ = Demux::Create(std::shared_ptr<Reader>(reader_cache_ptr));
if (!demux_) {
NOTREACHED() << "couldn't create demux";
return;
}
demux_->WhenInitialized([this](Result result) {
task_runner_->PostTask(FROM_HERE,
base::Bind(&MediaDemuxImpl::OnDemuxInitialized,
base::Unretained(this), result));
});
}
MediaDemuxImpl::~MediaDemuxImpl() {}
void MediaDemuxImpl::OnDemuxInitialized(Result result) {
demux_part_ = graph_.Add(demux_);
const std::vector<Demux::DemuxStream*>& demux_streams = demux_->streams();
for (Demux::DemuxStream* demux_stream : demux_streams) {
streams_.push_back(std::unique_ptr<Stream>(
new Stream(demux_part_.output(demux_stream->index()),
demux_stream->stream_type(), &graph_)));
}
graph_.Prepare();
metadata_publisher_.SendUpdates();
init_complete_.Occur();
}
void MediaDemuxImpl::Describe(const DescribeCallback& callback) {
init_complete_.When([this, callback]() {
Array<MediaTypePtr> result = Array<MediaTypePtr>::New(streams_.size());
for (size_t i = 0; i < streams_.size(); i++) {
MediaSourceStreamDescriptorPtr descriptor =
MediaSourceStreamDescriptor::New();
result[i] = streams_[i]->media_type();
}
callback.Run(result.Pass());
});
}
void MediaDemuxImpl::GetProducer(uint32_t stream_index,
InterfaceRequest<MediaProducer> producer) {
RCHECK(init_complete_.occurred());
if (stream_index >= streams_.size()) {
return;
}
streams_[stream_index]->GetProducer(producer.Pass());
}
void MediaDemuxImpl::GetMetadata(uint64_t version_last_seen,
const GetMetadataCallback& callback) {
metadata_publisher_.Get(version_last_seen, callback);
}
void MediaDemuxImpl::Prime(const PrimeCallback& callback) {
RCHECK(init_complete_.occurred());
std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create();
for (std::unique_ptr<Stream>& stream : streams_) {
stream->PrimeConnection(callback_joiner->NewCallback());
}
callback_joiner->WhenJoined(callback);
}
void MediaDemuxImpl::Flush(const FlushCallback& callback) {
RCHECK(init_complete_.occurred());
graph_.FlushAllOutputs(demux_part_);
std::shared_ptr<CallbackJoiner> callback_joiner = CallbackJoiner::Create();
for (std::unique_ptr<Stream>& stream : streams_) {
stream->FlushConnection(callback_joiner->NewCallback());
}
callback_joiner->WhenJoined(callback);
}
void MediaDemuxImpl::Seek(int64_t position, const SeekCallback& callback) {
RCHECK(init_complete_.occurred());
demux_->Seek(position, [this, callback]() {
task_runner_->PostTask(FROM_HERE, base::Bind(&RunSeekCallback, callback));
});
}
// static
void MediaDemuxImpl::RunSeekCallback(const SeekCallback& callback) {
callback.Run();
}
MediaDemuxImpl::Stream::Stream(OutputRef output,
std::unique_ptr<StreamType> stream_type,
Graph* graph)
: stream_type_(std::move(stream_type)), graph_(graph), output_(output) {
DCHECK(stream_type_);
DCHECK(graph);
producer_ = MojoProducer::Create();
graph_->ConnectOutputToPart(output_, graph_->Add(producer_));
}
MediaDemuxImpl::Stream::~Stream() {}
MediaTypePtr MediaDemuxImpl::Stream::media_type() const {
return MediaType::From(stream_type_);
}
void MediaDemuxImpl::Stream::GetProducer(
InterfaceRequest<MediaProducer> producer) {
DCHECK(producer_);
producer_->AddBinding(producer.Pass());
}
void MediaDemuxImpl::Stream::PrimeConnection(
const MojoProducer::PrimeConnectionCallback callback) {
DCHECK(producer_);
producer_->PrimeConnection(callback);
}
void MediaDemuxImpl::Stream::FlushConnection(
const MojoProducer::FlushConnectionCallback callback) {
DCHECK(producer_);
producer_->FlushConnection(callback);
}
} // namespace media
} // namespace mojo