blob: 7bd1d4c26020d0053f2743c8c4f34f35e576ad4b [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 "services/media/framework/graph.h"
namespace mojo {
namespace media {
Graph::Graph() {
update_function_ = [this](Stage* stage) { engine_.RequestUpdate(stage); };
}
Graph::~Graph() {
Reset();
}
void Graph::RemovePart(PartRef part) {
DCHECK(part.valid());
Stage* stage = part.stage_;
size_t input_count = stage->input_count();
for (size_t input_index = 0; input_index < input_count; input_index++) {
if (stage->input(input_index).connected()) {
DisconnectInput(InputRef(stage, input_index));
}
}
size_t output_count = stage->output_count();
for (size_t output_index = 0; output_index < output_count; output_index++) {
if (stage->output(output_index).connected()) {
DisconnectOutput(OutputRef(stage, output_index));
}
}
stage->SetUpdateCallback(nullptr);
sources_.remove(stage);
sinks_.remove(stage);
stages_.remove(stage);
delete stage;
}
PartRef Graph::Connect(const OutputRef& output, const InputRef& input) {
DCHECK(output.valid());
DCHECK(input.valid());
if (output.connected()) {
DisconnectOutput(output);
}
if (input.connected()) {
DisconnectInput(input);
}
output.actual().Connect(input);
input.actual().Connect(output);
return input.part();
}
PartRef Graph::ConnectParts(PartRef upstream_part, PartRef downstream_part) {
DCHECK(upstream_part.valid());
DCHECK(downstream_part.valid());
Connect(upstream_part.output(), downstream_part.input());
return downstream_part;
}
PartRef Graph::ConnectOutputToPart(const OutputRef& output,
PartRef downstream_part) {
DCHECK(output.valid());
DCHECK(downstream_part.valid());
Connect(output, downstream_part.input());
return downstream_part;
}
PartRef Graph::ConnectPartToInput(PartRef upstream_part,
const InputRef& input) {
DCHECK(upstream_part.valid());
DCHECK(input.valid());
Connect(upstream_part.output(), input);
return input.part();
}
void Graph::DisconnectOutput(const OutputRef& output) {
DCHECK(output.valid());
if (!output.connected()) {
return;
}
Input& mate = output.mate().actual();
if (mate.prepared()) {
CHECK(false) << "attempt to disconnect prepared output";
return;
}
mate.Disconnect();
output.actual().Disconnect();
}
void Graph::DisconnectInput(const InputRef& input) {
DCHECK(input.valid());
if (!input.connected()) {
return;
}
Output& mate = input.mate().actual();
if (input.actual().prepared()) {
CHECK(false) << "attempt to disconnect prepared input";
return;
}
mate.Disconnect();
input.actual().Disconnect();
}
void Graph::RemovePartsConnectedToPart(PartRef part) {
DCHECK(part.valid());
std::deque<PartRef> to_remove{part};
while (!to_remove.empty()) {
PartRef part = to_remove.front();
to_remove.pop_front();
for (size_t i = 0; i < part.input_count(); ++i) {
to_remove.push_back(part.input(i).part());
}
for (size_t i = 0; i < part.output_count(); ++i) {
to_remove.push_back(part.output(i).part());
}
RemovePart(part);
}
}
void Graph::RemovePartsConnectedToOutput(const OutputRef& output) {
DCHECK(output.valid());
if (!output.connected()) {
return;
}
PartRef downstream_part = output.mate().part();
DisconnectOutput(output);
RemovePartsConnectedToPart(downstream_part);
}
void Graph::RemovePartsConnectedToInput(const InputRef& input) {
DCHECK(input.valid());
if (!input.connected()) {
return;
}
PartRef upstream_part = input.mate().part();
DisconnectInput(input);
RemovePartsConnectedToPart(upstream_part);
}
void Graph::Reset() {
sources_.clear();
sinks_.clear();
while (!stages_.empty()) {
Stage* stage = stages_.front();
stages_.pop_front();
delete stage;
}
}
void Graph::Prepare() {
for (Stage* sink : sinks_) {
for (size_t i = 0; i < sink->input_count(); ++i) {
engine_.PrepareInput(InputRef(sink, i));
}
}
}
void Graph::PrepareInput(const InputRef& input) {
DCHECK(input.valid());
engine_.PrepareInput(input);
}
void Graph::FlushOutput(const OutputRef& output) {
DCHECK(output);
engine_.FlushOutput(output);
}
void Graph::FlushAllOutputs(PartRef part) {
DCHECK(part.valid());
size_t output_count = part.output_count();
for (size_t output_index = 0; output_index < output_count; output_index++) {
FlushOutput(part.output(output_index));
}
}
PartRef Graph::Add(Stage* stage) {
stages_.push_back(stage);
if (stage->input_count() == 0) {
sources_.push_back(stage);
}
if (stage->output_count() == 0) {
sinks_.push_back(stage);
}
stage->SetUpdateCallback(update_function_);
return PartRef(stage);
}
} // namespace media
} // namespace mojo