| Index: services/media/framework/graph.cc
|
| diff --git a/services/media/framework/graph.cc b/services/media/framework/graph.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..931e1905c44cb6ab61db942b3a35b6d7aa1d6e66
|
| --- /dev/null
|
| +++ b/services/media/framework/graph.cc
|
| @@ -0,0 +1,219 @@
|
| +// 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()) {
|
| + LOG(ERROR) << "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()) {
|
| + LOG(ERROR) << "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::PrimeSinks() {
|
| + for (Stage* sink : sinks_) {
|
| + sink->Prime();
|
| + }
|
| +}
|
| +
|
| +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
|
|
|