• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 androidx.media.filterfw;
19 
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Map.Entry;
23 import java.util.Set;
24 
25 /**
26  * A Signature holds the specification for a filter's input and output ports.
27  *
28  * A Signature instance must be returned by the filter's {@link Filter#getSignature()} method. It
29  * specifies the number and names of the filter's input and output ports, whether or not they
30  * are required, how data for those ports are accessed, and more. A Signature does not change over
31  * time. This makes Signatures useful for understanding how a filter can be integrated into a
32  * graph.
33  *
34  * There are a number of flags that can be specified for each input and output port. The flag
35  * {@code PORT_REQUIRED} indicates that the user must connect the specified port. On the other hand,
36  * {@code PORT_OPTIONAL} indicates that a port may be connected by the user.
37  *
38  * If ports other than the ones in the Signature are allowed, they default to the most generic
39  * format, that allows passing in any type of Frame. Thus, if more granular access is needed to
40  * a frame's data, it must be specified in the Signature.
41  */
42 public class Signature {
43 
44     private HashMap<String, PortInfo> mInputPorts = null;
45     private HashMap<String, PortInfo> mOutputPorts = null;
46     private boolean mAllowOtherInputs = true;
47     private boolean mAllowOtherOutputs = true;
48 
49     static class PortInfo {
50         public int flags;
51         public FrameType type;
52 
PortInfo()53         public PortInfo() {
54             flags = 0;
55             type = FrameType.any();
56         }
57 
PortInfo(int flags, FrameType type)58         public PortInfo(int flags, FrameType type) {
59             this.flags = flags;
60             this.type = type;
61         }
62 
isRequired()63         public boolean isRequired() {
64             return (flags & PORT_REQUIRED) != 0;
65         }
66 
toString(String ioMode, String name)67         public String toString(String ioMode, String name) {
68             String ioName = ioMode + " " + name;
69             String modeName = isRequired() ? "required" : "optional";
70             return modeName + " " + ioName + ": " + type.toString();
71         }
72     }
73 
74     /** Indicates that the port must be connected in the graph. */
75     public static final int PORT_REQUIRED = 0x02;
76     /** Indicates that the port may be connected in the graph . */
77     public static final int PORT_OPTIONAL = 0x01;
78 
79     /**
80      * Creates a new empty Signature.
81      */
Signature()82     public Signature() {
83     }
84 
85     /**
86      * Adds an input port to the Signature.
87      *
88      * @param name the name of the input port. Must be unique among input port names.
89      * @param flags a combination of port flags.
90      * @param type the type of the input frame.
91      * @return this Signature instance.
92      */
addInputPort(String name, int flags, FrameType type)93     public Signature addInputPort(String name, int flags, FrameType type) {
94         addInputPort(name, new PortInfo(flags, type));
95         return this;
96     }
97 
98     /**
99      * Adds an output port to the Signature.
100      *
101      * @param name the name of the output port. Must be unique among output port names.
102      * @param flags a combination of port flags.
103      * @param type the type of the output frame.
104      * @return this Signature instance.
105      */
addOutputPort(String name, int flags, FrameType type)106     public Signature addOutputPort(String name, int flags, FrameType type) {
107         addOutputPort(name, new PortInfo(flags, type));
108         return this;
109     }
110 
111     /**
112      * Disallows the user from adding any other input ports.
113      * Adding any input port not explicitly specified in this Signature will cause an error.
114      * @return this Signature instance.
115      */
disallowOtherInputs()116     public Signature disallowOtherInputs() {
117         mAllowOtherInputs = false;
118         return this;
119     }
120 
121     /**
122      * Disallows the user from adding any other output ports.
123      * Adding any output port not explicitly specified in this Signature will cause an error.
124      * @return this Signature instance.
125      */
disallowOtherOutputs()126     public Signature disallowOtherOutputs() {
127         mAllowOtherOutputs = false;
128         return this;
129     }
130 
131     /**
132      * Disallows the user from adding any other ports.
133      * Adding any input or output port not explicitly specified in this Signature will cause an
134      * error.
135      * @return this Signature instance.
136      */
disallowOtherPorts()137     public Signature disallowOtherPorts() {
138         mAllowOtherInputs = false;
139         mAllowOtherOutputs = false;
140         return this;
141     }
142 
143     @Override
toString()144     public String toString() {
145         StringBuffer stringBuffer = new StringBuffer();
146         for (Entry<String, PortInfo> entry : mInputPorts.entrySet()) {
147             stringBuffer.append(entry.getValue().toString("input", entry.getKey()) + "\n");
148         }
149         for (Entry<String, PortInfo> entry : mOutputPorts.entrySet()) {
150             stringBuffer.append(entry.getValue().toString("output", entry.getKey()) + "\n");
151         }
152         if (!mAllowOtherInputs) {
153             stringBuffer.append("disallow other inputs\n");
154         }
155         if (!mAllowOtherOutputs) {
156             stringBuffer.append("disallow other outputs\n");
157         }
158         return stringBuffer.toString();
159     }
160 
getInputPortInfo(String name)161     PortInfo getInputPortInfo(String name) {
162         PortInfo result = mInputPorts != null ? mInputPorts.get(name) : null;
163         return result != null ? result : new PortInfo();
164     }
165 
getOutputPortInfo(String name)166     PortInfo getOutputPortInfo(String name) {
167         PortInfo result = mOutputPorts != null ? mOutputPorts.get(name) : null;
168         return result != null ? result : new PortInfo();
169     }
170 
checkInputPortsConform(Filter filter)171     void checkInputPortsConform(Filter filter) {
172         Set<String> filterInputs = new HashSet<String>();
173         filterInputs.addAll(filter.getConnectedInputPortMap().keySet());
174         if (mInputPorts != null) {
175             for (Entry<String, PortInfo> entry : mInputPorts.entrySet()) {
176                 String portName = entry.getKey();
177                 PortInfo portInfo = entry.getValue();
178                 InputPort inputPort = filter.getConnectedInputPort(portName);
179                 if (inputPort == null && portInfo.isRequired()) {
180                     throw new RuntimeException("Filter " + filter + " does not have required "
181                         + "input port '" + portName + "'!");
182                 }
183                 filterInputs.remove(portName);
184             }
185         }
186         if (!mAllowOtherInputs && !filterInputs.isEmpty()) {
187             throw new RuntimeException("Filter " + filter + " has invalid input ports: "
188                 + filterInputs + "!");
189         }
190     }
191 
checkOutputPortsConform(Filter filter)192     void checkOutputPortsConform(Filter filter) {
193         Set<String> filterOutputs = new HashSet<String>();
194         filterOutputs.addAll(filter.getConnectedOutputPortMap().keySet());
195         if (mOutputPorts != null) {
196             for (Entry<String, PortInfo> entry : mOutputPorts.entrySet()) {
197                 String portName = entry.getKey();
198                 PortInfo portInfo = entry.getValue();
199                 OutputPort outputPort = filter.getConnectedOutputPort(portName);
200                 if (outputPort == null && portInfo.isRequired()) {
201                     throw new RuntimeException("Filter " + filter + " does not have required "
202                         + "output port '" + portName + "'!");
203                 }
204                 filterOutputs.remove(portName);
205             }
206         }
207         if (!mAllowOtherOutputs && !filterOutputs.isEmpty()) {
208             throw new RuntimeException("Filter " + filter + " has invalid output ports: "
209                 + filterOutputs + "!");
210         }
211     }
212 
getInputPorts()213     HashMap<String, PortInfo> getInputPorts() {
214         return mInputPorts;
215     }
216 
getOutputPorts()217     HashMap<String, PortInfo> getOutputPorts() {
218         return mOutputPorts;
219     }
220 
addInputPort(String name, PortInfo portInfo)221     private void addInputPort(String name, PortInfo portInfo) {
222         if (mInputPorts == null) {
223             mInputPorts = new HashMap<String, PortInfo>();
224         }
225         if (mInputPorts.containsKey(name)) {
226             throw new RuntimeException("Attempting to add duplicate input port '" + name + "'!");
227         }
228         mInputPorts.put(name, portInfo);
229     }
230 
addOutputPort(String name, PortInfo portInfo)231     private void addOutputPort(String name, PortInfo portInfo) {
232         if (mOutputPorts == null) {
233             mOutputPorts = new HashMap<String, PortInfo>();
234         }
235         if (mOutputPorts.containsKey(name)) {
236             throw new RuntimeException("Attempting to add duplicate output port '" + name + "'!");
237         }
238         mOutputPorts.put(name, portInfo);
239     }
240 }
241 
242