| /* |
| * 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 android.filterfw.core; |
| |
| import android.filterfw.core.KeyValueMap; |
| import android.filterfw.core.MutableFrameFormat; |
| |
| import java.util.Arrays; |
| import java.util.Map.Entry; |
| |
| /** |
| * @hide |
| */ |
| public class FrameFormat { |
| |
| public static final int TYPE_UNSPECIFIED = 0; |
| public static final int TYPE_BIT = 1; |
| public static final int TYPE_BYTE = 2; |
| public static final int TYPE_INT16 = 3; |
| public static final int TYPE_INT32 = 4; |
| public static final int TYPE_FLOAT = 5; |
| public static final int TYPE_DOUBLE = 6; |
| public static final int TYPE_POINTER = 7; |
| public static final int TYPE_OBJECT = 8; |
| |
| public static final int TARGET_UNSPECIFIED = 0; |
| public static final int TARGET_SIMPLE = 1; |
| public static final int TARGET_NATIVE = 2; |
| public static final int TARGET_GPU = 3; |
| public static final int TARGET_VERTEXBUFFER = 4; |
| public static final int TARGET_RS = 5; |
| |
| public static final int SIZE_UNSPECIFIED = 0; |
| |
| // TODO: When convenience formats are used, consider changing this to 0 and have the convenience |
| // intializers use a proper BPS. |
| public static final int BYTES_PER_SAMPLE_UNSPECIFIED = 1; |
| |
| protected static final int SIZE_UNKNOWN = -1; |
| |
| protected int mBaseType = TYPE_UNSPECIFIED; |
| protected int mBytesPerSample = 1; |
| protected int mSize = SIZE_UNKNOWN; |
| protected int mTarget = TARGET_UNSPECIFIED; |
| protected int[] mDimensions; |
| protected KeyValueMap mMetaData; |
| protected Class mObjectClass; |
| |
| protected FrameFormat() { |
| } |
| |
| public FrameFormat(int baseType, int target) { |
| mBaseType = baseType; |
| mTarget = target; |
| initDefaults(); |
| } |
| |
| public static FrameFormat unspecified() { |
| return new FrameFormat(TYPE_UNSPECIFIED, TARGET_UNSPECIFIED); |
| } |
| |
| public int getBaseType() { |
| return mBaseType; |
| } |
| |
| public boolean isBinaryDataType() { |
| return mBaseType >= TYPE_BIT && mBaseType <= TYPE_DOUBLE; |
| } |
| |
| public int getBytesPerSample() { |
| return mBytesPerSample; |
| } |
| |
| public int getValuesPerSample() { |
| return mBytesPerSample / bytesPerSampleOf(mBaseType); |
| } |
| |
| public int getTarget() { |
| return mTarget; |
| } |
| |
| public int[] getDimensions() { |
| return mDimensions; |
| } |
| |
| public int getDimension(int i) { |
| return mDimensions[i]; |
| } |
| |
| public int getDimensionCount() { |
| return mDimensions == null ? 0 : mDimensions.length; |
| } |
| |
| public boolean hasMetaKey(String key) { |
| return mMetaData != null ? mMetaData.containsKey(key) : false; |
| } |
| |
| public boolean hasMetaKey(String key, Class expectedClass) { |
| if (mMetaData != null && mMetaData.containsKey(key)) { |
| if (!expectedClass.isAssignableFrom(mMetaData.get(key).getClass())) { |
| throw new RuntimeException( |
| "FrameFormat meta-key '" + key + "' is of type " + |
| mMetaData.get(key).getClass() + " but expected to be of type " + |
| expectedClass + "!"); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| public Object getMetaValue(String key) { |
| return mMetaData != null ? mMetaData.get(key) : null; |
| } |
| |
| public int getNumberOfDimensions() { |
| return mDimensions != null ? mDimensions.length : 0; |
| } |
| |
| public int getLength() { |
| return (mDimensions != null && mDimensions.length >= 1) ? mDimensions[0] : -1; |
| } |
| |
| public int getWidth() { |
| return getLength(); |
| } |
| |
| public int getHeight() { |
| return (mDimensions != null && mDimensions.length >= 2) ? mDimensions[1] : -1; |
| } |
| |
| public int getDepth() { |
| return (mDimensions != null && mDimensions.length >= 3) ? mDimensions[2] : -1; |
| } |
| |
| public int getSize() { |
| if (mSize == SIZE_UNKNOWN) mSize = calcSize(mDimensions); |
| return mSize; |
| } |
| |
| public Class getObjectClass() { |
| return mObjectClass; |
| } |
| |
| public MutableFrameFormat mutableCopy() { |
| MutableFrameFormat result = new MutableFrameFormat(); |
| result.setBaseType(getBaseType()); |
| result.setTarget(getTarget()); |
| result.setBytesPerSample(getBytesPerSample()); |
| result.setDimensions(getDimensions()); |
| result.setObjectClass(getObjectClass()); |
| result.mMetaData = mMetaData == null ? null : (KeyValueMap)mMetaData.clone(); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object object) { |
| if (this == object) { |
| return true; |
| } |
| |
| if (!(object instanceof FrameFormat)) { |
| return false; |
| } |
| |
| FrameFormat format = (FrameFormat)object; |
| return format.mBaseType == mBaseType && |
| format.mTarget == mTarget && |
| format.mBytesPerSample == mBytesPerSample && |
| Arrays.equals(format.mDimensions, mDimensions) && |
| format.mMetaData.equals(mMetaData); |
| } |
| |
| @Override |
| public int hashCode() { |
| return 4211 ^ mBaseType ^ mBytesPerSample ^ getSize(); |
| } |
| |
| public boolean isCompatibleWith(FrameFormat specification) { |
| // Check base type |
| if (specification.getBaseType() != TYPE_UNSPECIFIED |
| && getBaseType() != specification.getBaseType()) { |
| return false; |
| } |
| |
| // Check target |
| if (specification.getTarget() != TARGET_UNSPECIFIED |
| && getTarget() != specification.getTarget()) { |
| return false; |
| } |
| |
| // Check bytes per sample |
| if (specification.getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED |
| && getBytesPerSample() != specification.getBytesPerSample()) { |
| return false; |
| } |
| |
| // Check number of dimensions |
| if (specification.getDimensionCount() > 0 |
| && getDimensionCount() != specification.getDimensionCount()) { |
| return false; |
| } |
| |
| // Check dimensions |
| for (int i = 0; i < specification.getDimensionCount(); ++i) { |
| int specDim = specification.getDimension(i); |
| if (specDim != SIZE_UNSPECIFIED && getDimension(i) != specDim) { |
| return false; |
| } |
| } |
| |
| // Check class |
| if (specification.getObjectClass() != null) { |
| if (getObjectClass() == null |
| || !specification.getObjectClass().isAssignableFrom(getObjectClass())) { |
| return false; |
| } |
| } |
| |
| // Check meta-data |
| if (specification.mMetaData != null) { |
| for (String specKey : specification.mMetaData.keySet()) { |
| if (mMetaData == null |
| || !mMetaData.containsKey(specKey) |
| || !mMetaData.get(specKey).equals(specification.mMetaData.get(specKey))) { |
| return false; |
| } |
| } |
| } |
| |
| // Passed all the tests |
| return true; |
| } |
| |
| public boolean mayBeCompatibleWith(FrameFormat specification) { |
| // Check base type |
| if (specification.getBaseType() != TYPE_UNSPECIFIED |
| && getBaseType() != TYPE_UNSPECIFIED |
| && getBaseType() != specification.getBaseType()) { |
| return false; |
| } |
| |
| // Check target |
| if (specification.getTarget() != TARGET_UNSPECIFIED |
| && getTarget() != TARGET_UNSPECIFIED |
| && getTarget() != specification.getTarget()) { |
| return false; |
| } |
| |
| // Check bytes per sample |
| if (specification.getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED |
| && getBytesPerSample() != BYTES_PER_SAMPLE_UNSPECIFIED |
| && getBytesPerSample() != specification.getBytesPerSample()) { |
| return false; |
| } |
| |
| // Check number of dimensions |
| if (specification.getDimensionCount() > 0 |
| && getDimensionCount() > 0 |
| && getDimensionCount() != specification.getDimensionCount()) { |
| return false; |
| } |
| |
| // Check dimensions |
| for (int i = 0; i < specification.getDimensionCount(); ++i) { |
| int specDim = specification.getDimension(i); |
| if (specDim != SIZE_UNSPECIFIED |
| && getDimension(i) != SIZE_UNSPECIFIED |
| && getDimension(i) != specDim) { |
| return false; |
| } |
| } |
| |
| // Check class |
| if (specification.getObjectClass() != null && getObjectClass() != null) { |
| if (!specification.getObjectClass().isAssignableFrom(getObjectClass())) { |
| return false; |
| } |
| } |
| |
| // Check meta-data |
| if (specification.mMetaData != null && mMetaData != null) { |
| for (String specKey : specification.mMetaData.keySet()) { |
| if (mMetaData.containsKey(specKey) |
| && !mMetaData.get(specKey).equals(specification.mMetaData.get(specKey))) { |
| return false; |
| } |
| } |
| } |
| |
| // Passed all the tests |
| return true; |
| } |
| |
| public static int bytesPerSampleOf(int baseType) { |
| // Defaults based on base-type |
| switch (baseType) { |
| case TYPE_BIT: |
| case TYPE_BYTE: |
| return 1; |
| case TYPE_INT16: |
| return 2; |
| case TYPE_INT32: |
| case TYPE_FLOAT: |
| case TYPE_POINTER: |
| return 4; |
| case TYPE_DOUBLE: |
| return 8; |
| default: |
| return 1; |
| } |
| } |
| |
| public static String dimensionsToString(int[] dimensions) { |
| StringBuffer buffer = new StringBuffer(); |
| if (dimensions != null) { |
| int n = dimensions.length; |
| for (int i = 0; i < n; ++i) { |
| if (dimensions[i] == SIZE_UNSPECIFIED) { |
| buffer.append("[]"); |
| } else { |
| buffer.append("[" + String.valueOf(dimensions[i]) + "]"); |
| } |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| public static String baseTypeToString(int baseType) { |
| switch (baseType) { |
| case TYPE_UNSPECIFIED: return "unspecified"; |
| case TYPE_BIT: return "bit"; |
| case TYPE_BYTE: return "byte"; |
| case TYPE_INT16: return "int"; |
| case TYPE_INT32: return "int"; |
| case TYPE_FLOAT: return "float"; |
| case TYPE_DOUBLE: return "double"; |
| case TYPE_POINTER: return "pointer"; |
| case TYPE_OBJECT: return "object"; |
| default: return "unknown"; |
| } |
| } |
| |
| public static String targetToString(int target) { |
| switch (target) { |
| case TARGET_UNSPECIFIED: return "unspecified"; |
| case TARGET_SIMPLE: return "simple"; |
| case TARGET_NATIVE: return "native"; |
| case TARGET_GPU: return "gpu"; |
| case TARGET_VERTEXBUFFER: return "vbo"; |
| case TARGET_RS: return "renderscript"; |
| default: return "unknown"; |
| } |
| } |
| |
| public static String metaDataToString(KeyValueMap metaData) { |
| if (metaData == null) { |
| return ""; |
| } else { |
| StringBuffer buffer = new StringBuffer(); |
| buffer.append("{ "); |
| for (Entry<String, Object> entry : metaData.entrySet()) { |
| buffer.append(entry.getKey() + ": " + entry.getValue() + " "); |
| } |
| buffer.append("}"); |
| return buffer.toString(); |
| } |
| } |
| |
| public static int readTargetString(String targetString) { |
| if (targetString.equalsIgnoreCase("CPU") || targetString.equalsIgnoreCase("NATIVE")) { |
| return FrameFormat.TARGET_NATIVE; |
| } else if (targetString.equalsIgnoreCase("GPU")) { |
| return FrameFormat.TARGET_GPU; |
| } else if (targetString.equalsIgnoreCase("SIMPLE")) { |
| return FrameFormat.TARGET_SIMPLE; |
| } else if (targetString.equalsIgnoreCase("VERTEXBUFFER")) { |
| return FrameFormat.TARGET_VERTEXBUFFER; |
| } else if (targetString.equalsIgnoreCase("UNSPECIFIED")) { |
| return FrameFormat.TARGET_UNSPECIFIED; |
| } else { |
| throw new RuntimeException("Unknown target type '" + targetString + "'!"); |
| } |
| } |
| |
| // TODO: FromString |
| |
| public String toString() { |
| int valuesPerSample = getValuesPerSample(); |
| String sampleCountString = valuesPerSample == 1 ? "" : String.valueOf(valuesPerSample); |
| String targetString = mTarget == TARGET_UNSPECIFIED ? "" : (targetToString(mTarget) + " "); |
| String classString = mObjectClass == null |
| ? "" |
| : (" class(" + mObjectClass.getSimpleName() + ") "); |
| |
| return targetString |
| + baseTypeToString(mBaseType) |
| + sampleCountString |
| + dimensionsToString(mDimensions) |
| + classString |
| + metaDataToString(mMetaData); |
| } |
| |
| private void initDefaults() { |
| mBytesPerSample = bytesPerSampleOf(mBaseType); |
| } |
| |
| // Core internal methods /////////////////////////////////////////////////////////////////////// |
| int calcSize(int[] dimensions) { |
| if (dimensions != null && dimensions.length > 0) { |
| int size = getBytesPerSample(); |
| for (int dim : dimensions) { |
| size *= dim; |
| } |
| return size; |
| } |
| return 0; |
| } |
| |
| boolean isReplaceableBy(FrameFormat format) { |
| return mTarget == format.mTarget |
| && getSize() == format.getSize() |
| && Arrays.equals(format.mDimensions, mDimensions); |
| } |
| } |