1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package android.filterfw; 19 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.Context; 22 import android.filterfw.core.AsyncRunner; 23 import android.filterfw.core.FilterContext; 24 import android.filterfw.core.FilterGraph; 25 import android.filterfw.core.FrameManager; 26 import android.filterfw.core.GraphRunner; 27 import android.filterfw.core.RoundRobinScheduler; 28 import android.filterfw.core.SyncRunner; 29 import android.filterfw.io.GraphIOException; 30 import android.filterfw.io.GraphReader; 31 import android.filterfw.io.TextGraphReader; 32 33 import java.util.ArrayList; 34 35 /** 36 * A GraphEnvironment provides a simple front-end to filter graph setup and execution using the 37 * mobile filter framework. Typically, you use a GraphEnvironment in the following fashion: 38 * 1. Instantiate a new GraphEnvironment instance. 39 * 2. Perform any configuration, such as adding graph references and setting a GL environment. 40 * 3. Load a graph file using loadGraph() or add a graph using addGraph(). 41 * 4. Obtain a GraphRunner instance using getRunner(). 42 * 5. Execute the obtained runner. 43 * Note that it is possible to add multiple graphs and runners to a single GraphEnvironment. 44 * 45 * @hide 46 */ 47 public class GraphEnvironment extends MffEnvironment { 48 49 public static final int MODE_ASYNCHRONOUS = 1; 50 public static final int MODE_SYNCHRONOUS = 2; 51 52 private GraphReader mGraphReader; 53 private ArrayList<GraphHandle> mGraphs = new ArrayList<GraphHandle>(); 54 55 private class GraphHandle { 56 private FilterGraph mGraph; 57 private AsyncRunner mAsyncRunner; 58 private SyncRunner mSyncRunner; 59 GraphHandle(FilterGraph graph)60 public GraphHandle(FilterGraph graph) { 61 mGraph = graph; 62 } 63 getGraph()64 public FilterGraph getGraph() { 65 return mGraph; 66 } 67 getAsyncRunner(FilterContext environment)68 public AsyncRunner getAsyncRunner(FilterContext environment) { 69 if (mAsyncRunner == null) { 70 mAsyncRunner = new AsyncRunner(environment, RoundRobinScheduler.class); 71 mAsyncRunner.setGraph(mGraph); 72 } 73 return mAsyncRunner; 74 } 75 getSyncRunner(FilterContext environment)76 public GraphRunner getSyncRunner(FilterContext environment) { 77 if (mSyncRunner == null) { 78 mSyncRunner = new SyncRunner(environment, mGraph, RoundRobinScheduler.class); 79 } 80 return mSyncRunner; 81 } 82 } 83 84 /** 85 * Create a new GraphEnvironment with default components. 86 */ 87 @UnsupportedAppUsage GraphEnvironment()88 public GraphEnvironment() { 89 super(null); 90 } 91 92 /** 93 * Create a new GraphEnvironment with a custom FrameManager and GraphReader. Specifying null 94 * for either of these, will auto-create a default instance. 95 * 96 * @param frameManager The FrameManager to use, or null to auto-create one. 97 * @param reader The GraphReader to use for graph loading, or null to auto-create one. 98 * Note, that the reader will not be created until it is required. Pass 99 * null if you will not load any graph files. 100 */ GraphEnvironment(FrameManager frameManager, GraphReader reader)101 public GraphEnvironment(FrameManager frameManager, GraphReader reader) { 102 super(frameManager); 103 mGraphReader = reader; 104 } 105 106 /** 107 * Returns the used graph reader. This will create one, if a reader has not been set already. 108 */ getGraphReader()109 public GraphReader getGraphReader() { 110 if (mGraphReader == null) { 111 mGraphReader = new TextGraphReader(); 112 } 113 return mGraphReader; 114 } 115 116 /** 117 * Add graph references to resolve during graph reading. The references added here are shared 118 * among all graphs. 119 * 120 * @param references An alternating argument list of keys (Strings) and values. 121 */ 122 @UnsupportedAppUsage addReferences(Object... references)123 public void addReferences(Object... references) { 124 getGraphReader().addReferencesByKeysAndValues(references); 125 } 126 127 /** 128 * Loads a graph file from the specified resource and adds it to this environment. 129 * 130 * @param context The context in which to read the resource. 131 * @param resourceId The ID of the graph resource to load. 132 * @return A unique ID for the graph. 133 */ 134 @UnsupportedAppUsage loadGraph(Context context, int resourceId)135 public int loadGraph(Context context, int resourceId) { 136 // Read the file into a graph 137 FilterGraph graph = null; 138 try { 139 graph = getGraphReader().readGraphResource(context, resourceId); 140 } catch (GraphIOException e) { 141 throw new RuntimeException("Could not read graph: " + e.getMessage()); 142 } 143 144 // Add graph to our list of graphs 145 return addGraph(graph); 146 } 147 148 /** 149 * Add a graph to the environment. Consider using loadGraph() if you are loading a graph from 150 * a graph file. 151 * 152 * @param graph The graph to add to the environment. 153 * @return A unique ID for the added graph. 154 */ addGraph(FilterGraph graph)155 public int addGraph(FilterGraph graph) { 156 GraphHandle graphHandle = new GraphHandle(graph); 157 mGraphs.add(graphHandle); 158 return mGraphs.size() - 1; 159 } 160 161 /** 162 * Access a specific graph of this environment given a graph ID (previously returned from 163 * loadGraph() or addGraph()). Throws an InvalidArgumentException if no graph with the 164 * specified ID could be found. 165 * 166 * @param graphId The ID of the graph to get. 167 * @return The graph with the specified ID. 168 */ getGraph(int graphId)169 public FilterGraph getGraph(int graphId) { 170 if (graphId < 0 || graphId >= mGraphs.size()) { 171 throw new IllegalArgumentException( 172 "Invalid graph ID " + graphId + " specified in runGraph()!"); 173 } 174 return mGraphs.get(graphId).getGraph(); 175 } 176 177 /** 178 * Get a GraphRunner instance for the graph with the specified ID. The GraphRunner instance can 179 * be used to execute the graph. Throws an InvalidArgumentException if no graph with the 180 * specified ID could be found. 181 * 182 * @param graphId The ID of the graph to get. 183 * @param executionMode The mode of graph execution. Currently this can be either 184 MODE_SYNCHRONOUS or MODE_ASYNCHRONOUS. 185 * @return A GraphRunner instance for this graph. 186 */ 187 @UnsupportedAppUsage getRunner(int graphId, int executionMode)188 public GraphRunner getRunner(int graphId, int executionMode) { 189 switch (executionMode) { 190 case MODE_ASYNCHRONOUS: 191 return mGraphs.get(graphId).getAsyncRunner(getContext()); 192 193 case MODE_SYNCHRONOUS: 194 return mGraphs.get(graphId).getSyncRunner(getContext()); 195 196 default: 197 throw new RuntimeException( 198 "Invalid execution mode " + executionMode + " specified in getRunner()!"); 199 } 200 } 201 202 } 203