summaryrefslogtreecommitdiffstats
path: root/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java')
-rw-r--r--tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java576
1 files changed, 576 insertions, 0 deletions
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
new file mode 100644
index 0000000..ef885e3
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.media.filterfw;
+
+import android.text.TextUtils;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A GraphReader allows obtaining filter graphs from XML graph files or strings.
+ */
+public class GraphReader {
+
+ private static interface Command {
+ public void execute(CommandStack stack);
+ }
+
+ private static class CommandStack {
+ private ArrayList<Command> mCommands = new ArrayList<Command>();
+ private FilterGraph.Builder mBuilder;
+ private FilterFactory mFactory;
+ private MffContext mContext;
+
+ public CommandStack(MffContext context) {
+ mContext = context;
+ mBuilder = new FilterGraph.Builder(mContext);
+ mFactory = new FilterFactory();
+ }
+
+ public void execute() {
+ for (Command command : mCommands) {
+ command.execute(this);
+ }
+ }
+
+ public void append(Command command) {
+ mCommands.add(command);
+ }
+
+ public FilterFactory getFactory() {
+ return mFactory;
+ }
+
+ public MffContext getContext() {
+ return mContext;
+ }
+
+ protected FilterGraph.Builder getBuilder() {
+ return mBuilder;
+ }
+ }
+
+ private static class ImportPackageCommand implements Command {
+ private String mPackageName;
+
+ public ImportPackageCommand(String packageName) {
+ mPackageName = packageName;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ try {
+ stack.getFactory().addPackage(mPackageName);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+
+ private static class AddLibraryCommand implements Command {
+ private String mLibraryName;
+
+ public AddLibraryCommand(String libraryName) {
+ mLibraryName = libraryName;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ FilterFactory.addFilterLibrary(mLibraryName);
+ }
+ }
+
+ private static class AllocateFilterCommand implements Command {
+ private String mClassName;
+ private String mFilterName;
+
+ public AllocateFilterCommand(String className, String filterName) {
+ mClassName = className;
+ mFilterName = filterName;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ Filter filter = null;
+ try {
+ filter = stack.getFactory().createFilterByClassName(mClassName,
+ mFilterName,
+ stack.getContext());
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Error creating filter " + mFilterName + "!", e);
+ }
+ stack.getBuilder().addFilter(filter);
+ }
+ }
+
+ private static class AddSourceSlotCommand implements Command {
+ private String mName;
+ private String mSlotName;
+
+ public AddSourceSlotCommand(String name, String slotName) {
+ mName = name;
+ mSlotName = slotName;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ stack.getBuilder().addFrameSlotSource(mName, mSlotName);
+ }
+ }
+
+ private static class AddTargetSlotCommand implements Command {
+ private String mName;
+ private String mSlotName;
+
+ public AddTargetSlotCommand(String name, String slotName) {
+ mName = name;
+ mSlotName = slotName;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ stack.getBuilder().addFrameSlotTarget(mName, mSlotName);
+ }
+ }
+
+ private static class AddVariableCommand implements Command {
+ private String mName;
+ private Object mValue;
+
+ public AddVariableCommand(String name, Object value) {
+ mName = name;
+ mValue = value;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ stack.getBuilder().addVariable(mName, mValue);
+ }
+ }
+
+ private static class SetFilterInputCommand implements Command {
+ private String mFilterName;
+ private String mFilterInput;
+ private Object mValue;
+
+ public SetFilterInputCommand(String filterName, String input, Object value) {
+ mFilterName = filterName;
+ mFilterInput = input;
+ mValue = value;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ if (mValue instanceof Variable) {
+ String varName = ((Variable)mValue).name;
+ stack.getBuilder().assignVariableToFilterInput(varName, mFilterName, mFilterInput);
+ } else {
+ stack.getBuilder().assignValueToFilterInput(mValue, mFilterName, mFilterInput);
+ }
+ }
+ }
+
+ private static class ConnectCommand implements Command {
+ private String mSourceFilter;
+ private String mSourcePort;
+ private String mTargetFilter;
+ private String mTargetPort;
+
+ public ConnectCommand(String sourceFilter,
+ String sourcePort,
+ String targetFilter,
+ String targetPort) {
+ mSourceFilter = sourceFilter;
+ mSourcePort = sourcePort;
+ mTargetFilter = targetFilter;
+ mTargetPort = targetPort;
+ }
+
+ @Override
+ public void execute(CommandStack stack) {
+ stack.getBuilder().connect(mSourceFilter, mSourcePort, mTargetFilter, mTargetPort);
+ }
+ }
+
+ private static class Variable {
+ public String name;
+
+ public Variable(String name) {
+ this.name = name;
+ }
+ }
+
+ private static class XmlGraphReader {
+
+ private SAXParserFactory mParserFactory;
+
+ private static class GraphDataHandler extends DefaultHandler {
+
+ private CommandStack mCommandStack;
+ private boolean mInGraph = false;
+ private String mCurFilterName = null;
+
+ public GraphDataHandler(CommandStack commandStack) {
+ mCommandStack = commandStack;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attr)
+ throws SAXException {
+ if (localName.equals("graph")) {
+ beginGraph();
+ } else {
+ assertInGraph(localName);
+ if (localName.equals("import")) {
+ addImportCommand(attr);
+ } else if (localName.equals("library")) {
+ addLibraryCommand(attr);
+ } else if (localName.equals("connect")) {
+ addConnectCommand(attr);
+ } else if (localName.equals("var")) {
+ addVarCommand(attr);
+ } else if (localName.equals("filter")) {
+ beginFilter(attr);
+ } else if (localName.equals("input")) {
+ addFilterInput(attr);
+ } else {
+ throw new SAXException("Unknown XML element '" + localName + "'!");
+ }
+ }
+ }
+
+ @Override
+ public void endElement (String uri, String localName, String qName) {
+ if (localName.equals("graph")) {
+ endGraph();
+ } else if (localName.equals("filter")) {
+ endFilter();
+ }
+ }
+
+ private void addImportCommand(Attributes attributes) throws SAXException {
+ String packageName = getRequiredAttribute(attributes, "package");
+ mCommandStack.append(new ImportPackageCommand(packageName));
+ }
+
+ private void addLibraryCommand(Attributes attributes) throws SAXException {
+ String libraryName = getRequiredAttribute(attributes, "name");
+ mCommandStack.append(new AddLibraryCommand(libraryName));
+ }
+
+ private void addConnectCommand(Attributes attributes) {
+ String sourcePortName = null;
+ String sourceFilterName = null;
+ String targetPortName = null;
+ String targetFilterName = null;
+
+ // check for shorthand: <connect source="filter:port" target="filter:port"/>
+ String sourceTag = attributes.getValue("source");
+ if (sourceTag != null) {
+ String[] sourceParts = sourceTag.split(":");
+ if (sourceParts.length == 2) {
+ sourceFilterName = sourceParts[0];
+ sourcePortName = sourceParts[1];
+ } else {
+ throw new RuntimeException(
+ "'source' tag needs to have format \"filter:port\"! " +
+ "Alternatively, you may use the form " +
+ "'sourceFilter=\"filter\" sourcePort=\"port\"'.");
+ }
+ } else {
+ sourceFilterName = attributes.getValue("sourceFilter");
+ sourcePortName = attributes.getValue("sourcePort");
+ }
+
+ String targetTag = attributes.getValue("target");
+ if (targetTag != null) {
+ String[] targetParts = targetTag.split(":");
+ if (targetParts.length == 2) {
+ targetFilterName = targetParts[0];
+ targetPortName = targetParts[1];
+ } else {
+ throw new RuntimeException(
+ "'target' tag needs to have format \"filter:port\"! " +
+ "Alternatively, you may use the form " +
+ "'targetFilter=\"filter\" targetPort=\"port\"'.");
+ }
+ } else {
+ targetFilterName = attributes.getValue("targetFilter");
+ targetPortName = attributes.getValue("targetPort");
+ }
+
+ String sourceSlotName = attributes.getValue("sourceSlot");
+ String targetSlotName = attributes.getValue("targetSlot");
+ if (sourceSlotName != null) {
+ sourceFilterName = "sourceSlot_" + sourceSlotName;
+ mCommandStack.append(new AddSourceSlotCommand(sourceFilterName,
+ sourceSlotName));
+ sourcePortName = "frame";
+ }
+ if (targetSlotName != null) {
+ targetFilterName = "targetSlot_" + targetSlotName;
+ mCommandStack.append(new AddTargetSlotCommand(targetFilterName,
+ targetSlotName));
+ targetPortName = "frame";
+ }
+ assertValueNotNull("sourceFilter", sourceFilterName);
+ assertValueNotNull("sourcePort", sourcePortName);
+ assertValueNotNull("targetFilter", targetFilterName);
+ assertValueNotNull("targetPort", targetPortName);
+ // TODO: Should slot connections auto-branch?
+ mCommandStack.append(new ConnectCommand(sourceFilterName,
+ sourcePortName,
+ targetFilterName,
+ targetPortName));
+ }
+
+ private void addVarCommand(Attributes attributes) throws SAXException {
+ String varName = getRequiredAttribute(attributes, "name");
+ Object varValue = getAssignmentValue(attributes);
+ mCommandStack.append(new AddVariableCommand(varName, varValue));
+ }
+
+ private void beginGraph() throws SAXException {
+ if (mInGraph) {
+ throw new SAXException("Found more than one graph element in XML!");
+ }
+ mInGraph = true;
+ }
+
+ private void endGraph() {
+ mInGraph = false;
+ }
+
+ private void beginFilter(Attributes attributes) throws SAXException {
+ String className = getRequiredAttribute(attributes, "class");
+ mCurFilterName = getRequiredAttribute(attributes, "name");
+ mCommandStack.append(new AllocateFilterCommand(className, mCurFilterName));
+ }
+
+ private void endFilter() {
+ mCurFilterName = null;
+ }
+
+ private void addFilterInput(Attributes attributes) throws SAXException {
+ // Make sure we are in a filter element
+ if (mCurFilterName == null) {
+ throw new SAXException("Found 'input' element outside of 'filter' "
+ + "element!");
+ }
+
+ // Get input name and value
+ String inputName = getRequiredAttribute(attributes, "name");
+ Object inputValue = getAssignmentValue(attributes);
+ if (inputValue == null) {
+ throw new SAXException("No value specified for input '" + inputName + "' "
+ + "of filter '" + mCurFilterName + "'!");
+ }
+
+ // Push commmand
+ mCommandStack.append(new SetFilterInputCommand(mCurFilterName,
+ inputName,
+ inputValue));
+ }
+
+ private void assertInGraph(String localName) throws SAXException {
+ if (!mInGraph) {
+ throw new SAXException("Encountered '" + localName + "' element outside of "
+ + "'graph' element!");
+ }
+ }
+
+ private static Object getAssignmentValue(Attributes attributes) {
+ String strValue = null;
+ if ((strValue = attributes.getValue("stringValue")) != null) {
+ return strValue;
+ } else if ((strValue = attributes.getValue("booleanValue")) != null) {
+ return Boolean.parseBoolean(strValue);
+ } else if ((strValue = attributes.getValue("intValue")) != null) {
+ return Integer.parseInt(strValue);
+ } else if ((strValue = attributes.getValue("floatValue")) != null) {
+ return Float.parseFloat(strValue);
+ } else if ((strValue = attributes.getValue("floatsValue")) != null) {
+ String[] floatStrings = TextUtils.split(strValue, ",");
+ float[] result = new float[floatStrings.length];
+ for (int i = 0; i < floatStrings.length; ++i) {
+ result[i] = Float.parseFloat(floatStrings[i]);
+ }
+ return result;
+ } else if ((strValue = attributes.getValue("varValue")) != null) {
+ return new Variable(strValue);
+ } else {
+ return null;
+ }
+ }
+
+ private static String getRequiredAttribute(Attributes attributes, String name)
+ throws SAXException {
+ String result = attributes.getValue(name);
+ if (result == null) {
+ throw new SAXException("Required attribute '" + name + "' not found!");
+ }
+ return result;
+ }
+
+ private static void assertValueNotNull(String valueName, Object value) {
+ if (value == null) {
+ throw new NullPointerException("Required value '" + value + "' not specified!");
+ }
+ }
+
+ }
+
+ public XmlGraphReader() {
+ mParserFactory = SAXParserFactory.newInstance();
+ }
+
+ public void parseString(String graphString, CommandStack commandStack) throws IOException {
+ try {
+ XMLReader reader = getReaderForCommandStack(commandStack);
+ reader.parse(new InputSource(new StringReader(graphString)));
+ } catch (SAXException e) {
+ throw new IOException("XML parse error during graph parsing!", e);
+ }
+ }
+
+ public void parseInput(InputStream inputStream, CommandStack commandStack)
+ throws IOException {
+ try {
+ XMLReader reader = getReaderForCommandStack(commandStack);
+ reader.parse(new InputSource(inputStream));
+ } catch (SAXException e) {
+ throw new IOException("XML parse error during graph parsing!", e);
+ }
+ }
+
+ private XMLReader getReaderForCommandStack(CommandStack commandStack) throws IOException {
+ try {
+ SAXParser parser = mParserFactory.newSAXParser();
+ XMLReader reader = parser.getXMLReader();
+ GraphDataHandler graphHandler = new GraphDataHandler(commandStack);
+ reader.setContentHandler(graphHandler);
+ return reader;
+ } catch (ParserConfigurationException e) {
+ throw new IOException("Error creating SAXParser for graph parsing!", e);
+ } catch (SAXException e) {
+ throw new IOException("Error creating XMLReader for graph parsing!", e);
+ }
+ }
+ }
+
+ /**
+ * Read an XML graph from a String.
+ *
+ * This function automatically checks each filters' signatures and throws a Runtime Exception
+ * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
+ *
+ * @param context the MffContext into which to load the graph.
+ * @param xmlSource the graph specified in XML.
+ * @return the FilterGraph instance for the XML source.
+ * @throws IOException if there was an error parsing the source.
+ */
+ public static FilterGraph readXmlGraph(MffContext context, String xmlSource)
+ throws IOException {
+ FilterGraph.Builder builder = getBuilderForXmlString(context, xmlSource);
+ return builder.build();
+ }
+
+ /**
+ * Read an XML sub-graph from a String.
+ *
+ * @param context the MffContext into which to load the graph.
+ * @param xmlSource the graph specified in XML.
+ * @param parentGraph the parent graph.
+ * @return the FilterGraph instance for the XML source.
+ * @throws IOException if there was an error parsing the source.
+ */
+ public static FilterGraph readXmlSubGraph(
+ MffContext context, String xmlSource, FilterGraph parentGraph)
+ throws IOException {
+ FilterGraph.Builder builder = getBuilderForXmlString(context, xmlSource);
+ return builder.buildSubGraph(parentGraph);
+ }
+
+ /**
+ * Read an XML graph from a resource.
+ *
+ * This function automatically checks each filters' signatures and throws a Runtime Exception
+ * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
+ *
+ * @param context the MffContext into which to load the graph.
+ * @param resourceId the XML resource ID.
+ * @return the FilterGraph instance for the XML source.
+ * @throws IOException if there was an error reading or parsing the resource.
+ */
+ public static FilterGraph readXmlGraphResource(MffContext context, int resourceId)
+ throws IOException {
+ FilterGraph.Builder builder = getBuilderForXmlResource(context, resourceId);
+ return builder.build();
+ }
+
+ /**
+ * Read an XML graph from a resource.
+ *
+ * This function automatically checks each filters' signatures and throws a Runtime Exception
+ * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
+ *
+ * @param context the MffContext into which to load the graph.
+ * @param resourceId the XML resource ID.
+ * @return the FilterGraph instance for the XML source.
+ * @throws IOException if there was an error reading or parsing the resource.
+ */
+ public static FilterGraph readXmlSubGraphResource(
+ MffContext context, int resourceId, FilterGraph parentGraph)
+ throws IOException {
+ FilterGraph.Builder builder = getBuilderForXmlResource(context, resourceId);
+ return builder.buildSubGraph(parentGraph);
+ }
+
+ private static FilterGraph.Builder getBuilderForXmlString(MffContext context, String source)
+ throws IOException {
+ XmlGraphReader reader = new XmlGraphReader();
+ CommandStack commands = new CommandStack(context);
+ reader.parseString(source, commands);
+ commands.execute();
+ return commands.getBuilder();
+ }
+
+ private static FilterGraph.Builder getBuilderForXmlResource(MffContext context, int resourceId)
+ throws IOException {
+ InputStream inputStream = context.getApplicationContext().getResources()
+ .openRawResource(resourceId);
+ XmlGraphReader reader = new XmlGraphReader();
+ CommandStack commands = new CommandStack(context);
+ reader.parseInput(inputStream, commands);
+ commands.execute();
+ return commands.getBuilder();
+ }
+}
+