1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.View; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.BranchFilter; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.FrameSlotSource; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.FrameSlotTarget; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.GraphInputSource; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.GraphOutputTarget; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.ValueTarget; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.ValueTarget.ValueListener; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterpacks.base.VariableSource; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Collection; 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashMap; 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashSet; 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Map.Entry; 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Set; 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A graph of Filter nodes. 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A FilterGraph instance contains a set of Filter instances connected by their output and input 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * ports. Every filter belongs to exactly one graph and cannot be moved to another graph. 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * FilterGraphs may contain sub-graphs that are dependent on the parent graph. These are typically 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * used when inserting sub-graphs into MetaFilters. When a parent graph is torn down so are its 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * sub-graphs. The same applies to flushing frames of a graph. 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class FilterGraph { 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static boolean DEBUG = false; 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The context that this graph lives in */ 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private MffContext mContext; 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Map from name of filter to the filter instance */ 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private HashMap<String, Filter> mFilterMap = new HashMap<String, Filter>(); 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Allows quick access to array of all filters. */ 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Filter[] mAllFilters = null; 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The GraphRunner currently attached to this graph */ 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GraphRunner mRunner; 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The set of sub-graphs of this graph */ 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks HashSet<FilterGraph> mSubGraphs = new HashSet<FilterGraph>(); 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The parent graph of this graph, or null it this graph is a root graph. */ 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FilterGraph mParentGraph; 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static class Builder { 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The context that this builder lives in */ 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private MffContext mContext; 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Map from name of filter to the filter instance */ 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private HashMap<String, Filter> mFilterMap = new HashMap<String, Filter>(); 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Creates a new builder for specifying a graph structure. 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param context The context the graph will live in. 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Builder(MffContext context) { 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext = context; 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Add a filter to the graph. 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Adds the specified filter to the set of filters of this graph. The filter must not be in 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the graph already, and the filter's name must be unique within the graph. 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param filter the filter to add to the graph. 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalArgumentException if the filter is in the graph already, or its name is 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * is already taken. 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void addFilter(Filter filter) { 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mFilterMap.values().contains(filter)) { 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Attempting to add filter " + filter + " that " 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "is in the graph already!"); 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (mFilterMap.containsKey(filter.getName())) { 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Graph contains filter with name '" 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + filter.getName() + "' already!"); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFilterMap.put(filter.getName(), filter); 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Adds a variable to the graph. 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: More documentation. 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param name the name of the variable. 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param value the value of the variable or null if no value is to be set yet. 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the VariableSource filter that holds the value of this variable. 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public VariableSource addVariable(String name, Object value) { 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (getFilter(name) != null) { 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Filter named '" + name + "' exists already!"); 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VariableSource valueSource = new VariableSource(mContext, name); 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks addFilter(valueSource); 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (value != null) { 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks valueSource.setValue(value); 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return valueSource; 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public FrameSlotSource addFrameSlotSource(String name, String slotName) { 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameSlotSource filter = new FrameSlotSource(mContext, name, slotName); 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks addFilter(filter); 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return filter; 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public FrameSlotTarget addFrameSlotTarget(String name, String slotName) { 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameSlotTarget filter = new FrameSlotTarget(mContext, name, slotName); 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks addFilter(filter); 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return filter; 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Connect two filters by their ports. 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The filters specified must have been previously added to the graph builder. 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sourceFilterName The name of the source filter. 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sourcePort The name of the source port. 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param targetFilterName The name of the target filter. 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param targetPort The name of the target port. 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void connect(String sourceFilterName, String sourcePort, 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String targetFilterName, String targetPort) { 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter sourceFilter = getFilter(sourceFilterName); 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter targetFilter = getFilter(targetFilterName); 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (sourceFilter == null) { 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown filter '" + sourceFilterName + "'!"); 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (targetFilter == null) { 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown filter '" + targetFilterName + "'!"); 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks connect(sourceFilter, sourcePort, targetFilter, targetPort); 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Connect two filters by their ports. 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The filters specified must have been previously added to the graph builder. 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sourceFilter The source filter. 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sourcePort The name of the source port. 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param targetFilter The target filter. 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param targetPort The name of the target port. 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void connect(Filter sourceFilter, String sourcePort, 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter targetFilter, String targetPort) { 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sourceFilter.connect(sourcePort, targetFilter, targetPort); 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the filter with the specified name. 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the filter with the specified name, or null if no such filter exists. 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Filter getFilter(String name) { 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mFilterMap.get(name); 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Builds the graph and checks signatures. 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The new graph instance. 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public FilterGraph build() { 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkSignatures(); 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return buildWithParent(null); 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Builds the sub-graph and checks signatures. 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param parentGraph the parent graph of the built sub-graph. 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The new graph instance. 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public FilterGraph buildSubGraph(FilterGraph parentGraph) { 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (parentGraph == null) { 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new NullPointerException("Parent graph must be non-null!"); 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkSignatures(); 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return buildWithParent(parentGraph); 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VariableSource assignValueToFilterInput(Object value, String filterName, String inputName) { 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Get filter to connect to 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter filter = getFilter(filterName); 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (filter == null) { 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown filter '" + filterName + "'!"); 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Construct a name for our value source and make sure it does not exist already 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String valueSourceName = filterName + "." + inputName; 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (getFilter(valueSourceName) != null) { 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("VariableSource for '" + filterName + "' and " 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "input '" + inputName + "' exists already!"); 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Create new VariableSource and connect it to the target filter and port 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VariableSource valueSource = new VariableSource(mContext, valueSourceName); 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks addFilter(valueSource); 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((Filter)valueSource).connect("value", filter, inputName); 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (RuntimeException e) { 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not connect VariableSource to input '" + inputName 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "' of filter '" + filterName + "'!", e); 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Assign the value to the VariableSource 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (value != null) { 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks valueSource.setValue(value); 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return valueSource; 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VariableSource assignVariableToFilterInput(String varName, 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String filterName, 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String inputName) { 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Get filter to connect to 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter filter = getFilter(filterName); 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (filter == null) { 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown filter '" + filterName + "'!"); 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Get variable 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter variable = getFilter(varName); 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (variable == null || !(variable instanceof VariableSource)) { 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown variable '" + varName + "'!"); 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Connect variable (and possibly branch) variable to filter 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks connectAndBranch(variable, "value", filter, inputName); 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (RuntimeException e) { 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not connect VariableSource to input '" + inputName 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "' of filter '" + filterName + "'!", e); 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (VariableSource)variable; 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Builds the graph without checking signatures. 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * If parent is non-null, build a sub-graph of the specified parent. 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The new graph instance. 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FilterGraph buildWithParent(FilterGraph parent) { 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FilterGraph graph = new FilterGraph(mContext, parent); 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks graph.mFilterMap = mFilterMap; 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks graph.mAllFilters = mFilterMap.values().toArray(new Filter[0]); 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (Entry<String, Filter> filterEntry : mFilterMap.entrySet()) { 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filterEntry.getValue().insertIntoFilterGraph(graph); 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return graph; 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void checkSignatures() { 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkSignaturesForFilters(mFilterMap.values()); 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // TODO: Currently this always branches even if the connection is a 1:1 connection. Later 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // we may optimize to pass through directly in the 1:1 case (may require disconnecting 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // ports). 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void connectAndBranch(Filter sourceFilter, 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String sourcePort, 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter targetFilter, 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String targetPort) { 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String branchName = "__" + sourceFilter.getName() + "_" + sourcePort + "Branch"; 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter branch = getFilter(branchName); 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (branch == null) { 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks branch = new BranchFilter(mContext, branchName, false); 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks addFilter(branch); 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sourceFilter.connect(sourcePort, branch, "input"); 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String portName = "to" + targetFilter.getName() + "_" + targetPort; 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks branch.connect(portName, targetFilter, targetPort); 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Attach the graph and its subgraphs to a custom GraphRunner. 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Call this if you want the graph to be executed by a specific GraphRunner. You must call 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * this before any other runner is set. Note that calls to {@code getRunner()} and 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@code run()} auto-create a GraphRunner. 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param runner The GraphRunner instance that should execute this graph. 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #getRunner() 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #run() 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void attachToRunner(GraphRunner runner) { 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mRunner == null) { 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (FilterGraph subGraph : mSubGraphs) { 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks subGraph.attachToRunner(runner); 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks runner.attachGraph(this); 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunner = runner; 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (mRunner != runner) { 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Cannot attach FilterGraph to GraphRunner that is already " 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "attached to another GraphRunner!"); 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Forcibly tear down a filter graph. 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Call this to release any resources associated with the filter graph, its filters and any of 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * its sub-graphs. This method must not be called if the graph (or any sub-graph) is running. 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may no longer access this graph instance or any of its subgraphs after calling this 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * method. 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Tearing down of sub-graphs is not supported. You must tear down the root graph, which will 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * tear down all of its sub-graphs. 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalStateException if the graph is still running. 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws RuntimeException if you attempt to tear down a sub-graph. 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void tearDown() { 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks assertNotRunning(); 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mParentGraph != null) { 347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Attempting to tear down sub-graph!"); 348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mRunner != null) { 350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunner.tearDownGraph(this); 351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (FilterGraph subGraph : mSubGraphs) { 353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks subGraph.mParentGraph = null; 354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks subGraph.tearDown(); 355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSubGraphs.clear(); 357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the context of the graph. 361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the MffContext instance that this graph is bound to. 363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public MffContext getContext() { 365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mContext; 366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the filter with the specified name. 370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the filter with the specified name, or null if no such filter exists. 372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Filter getFilter(String name) { 374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mFilterMap.get(name); 375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the VariableSource for the specified variable. 379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: More documentation. 381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: More specialized error handling. 382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param name The name of the VariableSource. 384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The VariableSource filter instance with the specified name. 385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public VariableSource getVariable(String name) { 387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter result = mFilterMap.get(name); 388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (result != null && result instanceof VariableSource) { 389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (VariableSource)result; 390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown variable '" + name + "' specified!"); 392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the GraphOutputTarget with the specified name. 397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param name The name of the target. 399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The GraphOutputTarget instance with the specified name. 400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphOutputTarget getGraphOutput(String name) { 402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter result = mFilterMap.get(name); 403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (result != null && result instanceof GraphOutputTarget) { 404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (GraphOutputTarget)result; 405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown target '" + name + "' specified!"); 407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the GraphInputSource with the specified name. 412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param name The name of the source. 414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The GraphInputSource instance with the specified name. 415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphInputSource getGraphInput(String name) { 417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter result = mFilterMap.get(name); 418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (result != null && result instanceof GraphInputSource) { 419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (GraphInputSource)result; 420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown source '" + name + "' specified!"); 422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Binds a filter to a view. 427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * ViewFilter instances support visualizing their data to a view. See the specific filter 429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * documentation for details. Views may be bound only if the graph is not running. 430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param filterName the name of the filter to bind. 432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param view the view to bind to. 433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalStateException if the filter is in an illegal state. 434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalArgumentException if no such view-filter exists. 435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void bindFilterToView(String filterName, View view) { 437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter filter = mFilterMap.get(filterName); 438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (filter != null && filter instanceof ViewFilter) { 439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((ViewFilter)filter).bindToView(view); 440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown view filter '" + filterName + "'!"); 442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: Documentation. 447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void bindValueTarget(String filterName, ValueListener listener, boolean onCallerThread) { 449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter filter = mFilterMap.get(filterName); 450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (filter != null && filter instanceof ValueTarget) { 451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((ValueTarget)filter).setListener(listener, onCallerThread); 452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown ValueTarget filter '" + filterName + "'!"); 454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Running Graphs ////////////////////////////////////////////////////////////////////////////// 458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Convenience method to run the graph. 460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Creates a new runner for this graph in the specified mode and executes it. Returns the 462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * runner to allow control of execution. 463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalStateException if the graph is already running. 465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the GraphRunner instance that was used for execution. 466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphRunner run() { 468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GraphRunner runner = getRunner(); 469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks runner.setIsVerbose(false); 470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks runner.start(this); 471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return runner; 472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the GraphRunner for this graph. 476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Every FilterGraph instance has a GraphRunner instance associated with it for executing the 478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * graph. 479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the GraphRunner instance for this graph. 481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphRunner getRunner() { 483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mRunner == null) { 484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GraphRunner runner = new GraphRunner(mContext); 485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks attachToRunner(runner); 486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunner; 488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the graph is currently running. 492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true if the graph is currently running. 494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isRunning() { 496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunner != null && mRunner.isRunning(); 497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Check each filter's signatures if all requirements are fulfilled. 501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This will throw a RuntimeException if any unfulfilled requirements are found. 503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Note that FilterGraph.Builder also has a function checkSignatures(), which allows 504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to do the same /before/ the FilterGraph is built. 505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void checkSignatures() { 507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkSignaturesForFilters(mFilterMap.values()); 508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // MFF Internal Methods //////////////////////////////////////////////////////////////////////// 511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter[] getAllFilters() { 512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mAllFilters; 513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks static void checkSignaturesForFilters(Collection<Filter> filters) { 516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (Filter filter : filters) { 517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (DEBUG) { 518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.d("FilterGraph", "Checking filter " + filter.getName() + "..."); 519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Signature signature = filter.getSignature(); 521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks signature.checkInputPortsConform(filter); 522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks signature.checkOutputPortsConform(filter); 523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Wipes the filter references in this graph, so that they may be collected. 528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This must be called only after a tearDown as this will make the FilterGraph invalid. 530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void wipe() { 532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mAllFilters = null; 533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFilterMap = null; 534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void flushFrames() { 537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (Filter filter : mFilterMap.values()) { 538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (InputPort inputPort : filter.getConnectedInputPorts()) { 539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks inputPort.clear(); 540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (OutputPort outputPort : filter.getConnectedOutputPorts()) { 542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputPort.clear(); 543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Set<FilterGraph> getSubGraphs() { 548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mSubGraphs; 549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Internal Methods //////////////////////////////////////////////////////////////////////////// 552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FilterGraph(MffContext context, FilterGraph parentGraph) { 553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext = context; 554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext.addGraph(this); 555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (parentGraph != null) { 556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParentGraph = parentGraph; 557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParentGraph.mSubGraphs.add(this); 558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void assertNotRunning() { 562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (isRunning()) { 563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalStateException("Attempting to modify running graph!"); 564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 568