• Home
  • History
  • Annotate
  • 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 android.filterfw.core;
19 
20 import android.annotation.UnsupportedAppUsage;
21 import android.filterfw.core.KeyValueMap;
22 import android.filterfw.core.MutableFrameFormat;
23 
24 import java.util.Arrays;
25 import java.util.Map.Entry;
26 
27 /**
28  * @hide
29  */
30 public class FrameFormat {
31 
32     public static final int TYPE_UNSPECIFIED = 0;
33     public static final int TYPE_BIT         = 1;
34     public static final int TYPE_BYTE        = 2;
35     public static final int TYPE_INT16       = 3;
36     public static final int TYPE_INT32       = 4;
37     public static final int TYPE_FLOAT       = 5;
38     public static final int TYPE_DOUBLE      = 6;
39     public static final int TYPE_POINTER     = 7;
40     public static final int TYPE_OBJECT      = 8;
41 
42     public static final int TARGET_UNSPECIFIED  = 0;
43     public static final int TARGET_SIMPLE       = 1;
44     public static final int TARGET_NATIVE       = 2;
45     public static final int TARGET_GPU          = 3;
46     public static final int TARGET_VERTEXBUFFER = 4;
47     public static final int TARGET_RS           = 5;
48 
49     public static final int SIZE_UNSPECIFIED = 0;
50 
51     // TODO: When convenience formats are used, consider changing this to 0 and have the convenience
52     // intializers use a proper BPS.
53     public static final int BYTES_PER_SAMPLE_UNSPECIFIED = 1;
54 
55     protected static final int SIZE_UNKNOWN = -1;
56 
57     protected int mBaseType = TYPE_UNSPECIFIED;
58     protected int mBytesPerSample = 1;
59     protected int mSize = SIZE_UNKNOWN;
60     protected int mTarget = TARGET_UNSPECIFIED;
61     protected int[] mDimensions;
62     protected KeyValueMap mMetaData;
63     protected Class mObjectClass;
64 
FrameFormat()65     protected FrameFormat() {
66     }
67 
FrameFormat(int baseType, int target)68     public FrameFormat(int baseType, int target) {
69         mBaseType = baseType;
70         mTarget = target;
71         initDefaults();
72     }
73 
unspecified()74     public static FrameFormat unspecified() {
75         return new FrameFormat(TYPE_UNSPECIFIED, TARGET_UNSPECIFIED);
76     }
77 
getBaseType()78     public int getBaseType() {
79         return mBaseType;
80     }
81 
isBinaryDataType()82     public boolean isBinaryDataType() {
83         return mBaseType >= TYPE_BIT && mBaseType <= TYPE_DOUBLE;
84     }
85 
getBytesPerSample()86     public int getBytesPerSample() {
87         return mBytesPerSample;
88     }
89 
getValuesPerSample()90     public int getValuesPerSample() {
91         return mBytesPerSample / bytesPerSampleOf(mBaseType);
92     }
93 
94     @UnsupportedAppUsage
getTarget()95     public int getTarget() {
96         return mTarget;
97     }
98 
getDimensions()99     public int[] getDimensions() {
100         return mDimensions;
101     }
102 
getDimension(int i)103     public int getDimension(int i) {
104         return mDimensions[i];
105     }
106 
getDimensionCount()107     public int getDimensionCount() {
108         return mDimensions == null ? 0 : mDimensions.length;
109     }
110 
hasMetaKey(String key)111     public boolean hasMetaKey(String key) {
112         return mMetaData != null ? mMetaData.containsKey(key) : false;
113     }
114 
hasMetaKey(String key, Class expectedClass)115     public boolean hasMetaKey(String key, Class expectedClass) {
116         if (mMetaData != null && mMetaData.containsKey(key)) {
117             if (!expectedClass.isAssignableFrom(mMetaData.get(key).getClass())) {
118                 throw new RuntimeException(
119                     "FrameFormat meta-key '" + key + "' is of type " +
120                     mMetaData.get(key).getClass() + " but expected to be of type " +
121                     expectedClass + "!");
122             }
123             return true;
124         }
125         return false;
126     }
127 
getMetaValue(String key)128     public Object getMetaValue(String key) {
129         return mMetaData != null ? mMetaData.get(key) : null;
130     }
131 
getNumberOfDimensions()132     public int getNumberOfDimensions() {
133         return mDimensions != null ? mDimensions.length : 0;
134     }
135 
getLength()136     public int getLength() {
137         return (mDimensions != null && mDimensions.length >= 1) ? mDimensions[0] : -1;
138     }
139 
140     @UnsupportedAppUsage
getWidth()141     public int getWidth() {
142         return getLength();
143     }
144 
145     @UnsupportedAppUsage
getHeight()146     public int getHeight() {
147         return (mDimensions != null && mDimensions.length >= 2) ? mDimensions[1] : -1;
148     }
149 
getDepth()150     public int getDepth() {
151         return (mDimensions != null && mDimensions.length >= 3) ? mDimensions[2] : -1;
152     }
153 
getSize()154     public int getSize() {
155         if (mSize == SIZE_UNKNOWN) mSize = calcSize(mDimensions);
156         return mSize;
157     }
158 
getObjectClass()159     public Class getObjectClass() {
160         return mObjectClass;
161     }
162 
163     @UnsupportedAppUsage
mutableCopy()164     public MutableFrameFormat mutableCopy() {
165         MutableFrameFormat result = new MutableFrameFormat();
166         result.setBaseType(getBaseType());
167         result.setTarget(getTarget());
168         result.setBytesPerSample(getBytesPerSample());
169         result.setDimensions(getDimensions());
170         result.setObjectClass(getObjectClass());
171         result.mMetaData = mMetaData == null ? null : (KeyValueMap)mMetaData.clone();
172         return result;
173     }
174 
175     @Override
equals(Object object)176     public boolean equals(Object object) {
177         if (this == object) {
178             return true;
179         }
180 
181         if (!(object instanceof FrameFormat)) {
182             return false;
183         }
184 
185         FrameFormat format = (FrameFormat)object;
186         return format.mBaseType == mBaseType &&
187                 format.mTarget == mTarget &&
188                 format.mBytesPerSample == mBytesPerSample &&
189                 Arrays.equals(format.mDimensions, mDimensions) &&
190                 format.mMetaData.equals(mMetaData);
191     }
192 
193     @Override
hashCode()194     public int hashCode() {
195         return 4211 ^ mBaseType ^ mBytesPerSample ^ getSize();
196     }
197 
isCompatibleWith(FrameFormat specification)198     public boolean isCompatibleWith(FrameFormat specification) {
199         // Check base type
200         if (specification.getBaseType() != TYPE_UNSPECIFIED
201             && getBaseType() != specification.getBaseType()) {
202             return false;
203         }
204 
205         // Check target
206         if (specification.getTarget() != TARGET_UNSPECIFIED
207             && getTarget() != specification.getTarget()) {
208             return false;
209         }
210 
211         // Check bytes per sample
212         if (specification.getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED
213             && getBytesPerSample() != specification.getBytesPerSample()) {
214             return false;
215         }
216 
217         // Check number of dimensions
218         if (specification.getDimensionCount() > 0
219             && getDimensionCount() != specification.getDimensionCount()) {
220             return false;
221         }
222 
223         // Check dimensions
224         for (int i = 0; i < specification.getDimensionCount(); ++i) {
225             int specDim = specification.getDimension(i);
226             if (specDim != SIZE_UNSPECIFIED && getDimension(i) != specDim) {
227                 return false;
228             }
229         }
230 
231         // Check class
232         if (specification.getObjectClass() != null) {
233             if (getObjectClass() == null
234                 || !specification.getObjectClass().isAssignableFrom(getObjectClass())) {
235                 return false;
236             }
237         }
238 
239         // Check meta-data
240         if (specification.mMetaData != null) {
241             for (String specKey : specification.mMetaData.keySet()) {
242                 if (mMetaData == null
243                 || !mMetaData.containsKey(specKey)
244                 || !mMetaData.get(specKey).equals(specification.mMetaData.get(specKey))) {
245                     return false;
246                 }
247             }
248         }
249 
250         // Passed all the tests
251         return true;
252     }
253 
mayBeCompatibleWith(FrameFormat specification)254     public boolean mayBeCompatibleWith(FrameFormat specification) {
255         // Check base type
256         if (specification.getBaseType() != TYPE_UNSPECIFIED
257             && getBaseType() != TYPE_UNSPECIFIED
258             && getBaseType() != specification.getBaseType()) {
259             return false;
260         }
261 
262         // Check target
263         if (specification.getTarget() != TARGET_UNSPECIFIED
264             && getTarget() != TARGET_UNSPECIFIED
265             && getTarget() != specification.getTarget()) {
266             return false;
267         }
268 
269         // Check bytes per sample
270         if (specification.getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED
271             && getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED
272             && getBytesPerSample() != specification.getBytesPerSample()) {
273             return false;
274         }
275 
276         // Check number of dimensions
277         if (specification.getDimensionCount() > 0
278             && getDimensionCount() > 0
279             && getDimensionCount() != specification.getDimensionCount()) {
280             return false;
281         }
282 
283         // Check dimensions
284         for (int i = 0; i < specification.getDimensionCount(); ++i) {
285             int specDim = specification.getDimension(i);
286             if (specDim != SIZE_UNSPECIFIED
287                 && getDimension(i) != SIZE_UNSPECIFIED
288                 && getDimension(i) != specDim) {
289                 return false;
290             }
291         }
292 
293         // Check class
294         if (specification.getObjectClass() != null && getObjectClass() != null) {
295             if (!specification.getObjectClass().isAssignableFrom(getObjectClass())) {
296                 return false;
297             }
298         }
299 
300         // Check meta-data
301         if (specification.mMetaData != null && mMetaData != null) {
302             for (String specKey : specification.mMetaData.keySet()) {
303                 if (mMetaData.containsKey(specKey)
304                     && !mMetaData.get(specKey).equals(specification.mMetaData.get(specKey))) {
305                     return false;
306                 }
307             }
308         }
309 
310         // Passed all the tests
311         return true;
312     }
313 
bytesPerSampleOf(int baseType)314     public static int bytesPerSampleOf(int baseType) {
315         // Defaults based on base-type
316         switch (baseType) {
317             case TYPE_BIT:
318             case TYPE_BYTE:
319                 return 1;
320             case TYPE_INT16:
321                 return 2;
322             case TYPE_INT32:
323             case TYPE_FLOAT:
324             case TYPE_POINTER:
325                 return 4;
326             case TYPE_DOUBLE:
327                 return 8;
328             default:
329                 return 1;
330         }
331     }
332 
dimensionsToString(int[] dimensions)333     public static String dimensionsToString(int[] dimensions) {
334         StringBuffer buffer = new StringBuffer();
335         if (dimensions != null) {
336             int n = dimensions.length;
337             for (int i = 0; i < n; ++i) {
338                 if (dimensions[i] == SIZE_UNSPECIFIED) {
339                     buffer.append("[]");
340                 } else {
341                     buffer.append("[" + String.valueOf(dimensions[i]) + "]");
342                 }
343             }
344         }
345         return buffer.toString();
346     }
347 
baseTypeToString(int baseType)348     public static String baseTypeToString(int baseType) {
349         switch (baseType) {
350             case TYPE_UNSPECIFIED: return "unspecified";
351             case TYPE_BIT:         return "bit";
352             case TYPE_BYTE:        return "byte";
353             case TYPE_INT16:       return "int";
354             case TYPE_INT32:       return "int";
355             case TYPE_FLOAT:       return "float";
356             case TYPE_DOUBLE:      return "double";
357             case TYPE_POINTER:     return "pointer";
358             case TYPE_OBJECT:      return "object";
359             default:               return "unknown";
360         }
361     }
362 
targetToString(int target)363     public static String targetToString(int target) {
364         switch (target) {
365             case TARGET_UNSPECIFIED:  return "unspecified";
366             case TARGET_SIMPLE:       return "simple";
367             case TARGET_NATIVE:       return "native";
368             case TARGET_GPU:          return "gpu";
369             case TARGET_VERTEXBUFFER: return "vbo";
370             case TARGET_RS:           return "renderscript";
371             default:                  return "unknown";
372         }
373     }
374 
metaDataToString(KeyValueMap metaData)375     public static String metaDataToString(KeyValueMap metaData) {
376         if (metaData == null) {
377             return "";
378         } else {
379             StringBuffer buffer = new StringBuffer();
380             buffer.append("{ ");
381             for (Entry<String, Object> entry : metaData.entrySet()) {
382                 buffer.append(entry.getKey() + ": " + entry.getValue() + " ");
383             }
384             buffer.append("}");
385             return buffer.toString();
386         }
387     }
388 
readTargetString(String targetString)389     public static int readTargetString(String targetString) {
390         if (targetString.equalsIgnoreCase("CPU") || targetString.equalsIgnoreCase("NATIVE")) {
391             return FrameFormat.TARGET_NATIVE;
392         } else if (targetString.equalsIgnoreCase("GPU")) {
393             return FrameFormat.TARGET_GPU;
394         } else if (targetString.equalsIgnoreCase("SIMPLE")) {
395             return FrameFormat.TARGET_SIMPLE;
396         } else if (targetString.equalsIgnoreCase("VERTEXBUFFER")) {
397             return FrameFormat.TARGET_VERTEXBUFFER;
398         } else if (targetString.equalsIgnoreCase("UNSPECIFIED")) {
399             return FrameFormat.TARGET_UNSPECIFIED;
400         } else {
401             throw new RuntimeException("Unknown target type '" + targetString + "'!");
402         }
403     }
404 
405     // TODO: FromString
406 
toString()407     public String toString() {
408         int valuesPerSample = getValuesPerSample();
409         String sampleCountString = valuesPerSample == 1 ? "" : String.valueOf(valuesPerSample);
410         String targetString = mTarget == TARGET_UNSPECIFIED ? "" : (targetToString(mTarget) + " ");
411         String classString = mObjectClass == null
412             ? ""
413             : (" class(" + mObjectClass.getSimpleName() + ") ");
414 
415         return targetString
416             + baseTypeToString(mBaseType)
417             + sampleCountString
418             + dimensionsToString(mDimensions)
419             + classString
420             + metaDataToString(mMetaData);
421     }
422 
initDefaults()423     private void initDefaults() {
424         mBytesPerSample = bytesPerSampleOf(mBaseType);
425     }
426 
427     // Core internal methods ///////////////////////////////////////////////////////////////////////
calcSize(int[] dimensions)428     int calcSize(int[] dimensions) {
429         if (dimensions != null && dimensions.length > 0) {
430             int size = getBytesPerSample();
431             for (int dim : dimensions) {
432                 size *= dim;
433             }
434             return size;
435         }
436         return 0;
437     }
438 
isReplaceableBy(FrameFormat format)439     boolean isReplaceableBy(FrameFormat format) {
440         return mTarget == format.mTarget
441             && getSize() == format.getSize()
442             && Arrays.equals(format.mDimensions, mDimensions);
443     }
444 }
445