Multi-Project Commit: Move of filterfw out of system/media (2 of 7)
This is part of the multi-project commit to move the filter-framework
from system/media/mca to frameworks/base/media/mca.
Note that the filter-framework will soon be replaced with a refactored
version currently under API review (also to go under frameworks/base).
This move is done now to unblock the PDK efforts.
Change-Id: I9f42be5a12a9e8157512be11f04e38e4548970be
diff --git a/media/mca/structgen.py b/media/mca/structgen.py
new file mode 100644
index 0000000..437326c
--- /dev/null
+++ b/media/mca/structgen.py
@@ -0,0 +1,367 @@
+#!/usr/bin/env python
+
+#
+# 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.
+#
+
+import os
+import sys
+
+hFileTemplate = """/**
+ * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
+ **/
+
+#ifndef %s
+#define %s
+
+%s
+
+#endif // %s
+"""
+
+jniFileTemplate = """/**
+ * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
+ **/
+
+#include <stdint.h>
+#include "native/%s.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "jni.h"
+
+// Helper functions ////////////////////////////////////////////////////////////////////////////////
+%s* Get%sAtIndex(JNIEnv* env, jobject buffer, int index) {
+ jclass base_class = (*env)->FindClass(env, "android/filterfw/core/NativeBuffer");
+ jfieldID ptr_field = (*env)->GetFieldID(env, base_class, "mDataPointer", "J");
+ uintptr_t data_ptr = (*env)->GetLongField(env, buffer, ptr_field);
+ %s* array = (%s*)data_ptr;
+ (*env)->DeleteLocalRef(env, base_class);
+ return &array[index];
+}
+
+// Declarations ////////////////////////////////////////////////////////////////////////////////////
+JNIEXPORT jint JNICALL
+Java_%s_getElementSize(JNIEnv* env, jobject thiz);
+
+%s
+
+#ifdef __cplusplus
+}
+#endif
+
+// Implementation //////////////////////////////////////////////////////////////////////////////////
+jint Java_%s_getElementSize(JNIEnv* env, jobject thiz) {
+ return sizeof(%s);
+}
+
+%s
+"""
+
+javaFileTemplate = """/**
+ * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
+ **/
+
+package %s;
+
+import android.filterfw.core.NativeBuffer;
+
+%s
+"""
+
+
+def ToJavaName(cname, start_upper_at = 1):
+ lower = cname.split("_")
+ upper = [c.title() for c in lower]
+ return "".join(lower[:start_upper_at] + upper[start_upper_at:])
+
+def ToJNIPackage(package, jclassname):
+ return "%s_%s" % (package.replace(".", "_"), jclassname)
+
+def ToMacroDefName(cname, pname):
+ return "%s_%s" % (pname.replace(".", "_").upper(), cname.upper())
+
+class ParseError:
+ def __init__(self, lineno, message):
+ self.lineno = lineno
+ self.message = message
+
+ def __str__(self):
+ return "On line %d: %s" % (self.lineno, self.message)
+
+class FieldType_BasePOD:
+ def __init__(self, name, structname, jclassname, package, javatype, ctype, jtype, defval):
+ self.name = name
+ self.structname = structname
+ self.jclassname = jclassname
+ self.package = package
+ self.javatype = javatype
+ self.ctype = ctype
+ self.jtype = jtype
+ self.defval = defval
+
+ def cString(self):
+ return " %s %s;" % (self.ctype, self.name)
+
+ def javaGetter(self):
+ return " public %s get%s(int index) {\n"\
+ " assertReadable();\n"\
+ " return nativeGet%s(index);\n"\
+ " }" % (self.javatype, ToJavaName(self.name, 0), ToJavaName(self.name, 0))
+
+ def javaSetter(self):
+ return " public void set%s(int index, %s value) {\n"\
+ " assertWritable();\n"\
+ " nativeSet%s(index, value);\n"\
+ " }" % (ToJavaName(self.name, 0), self.javatype, ToJavaName(self.name, 0))
+
+ def javaNativeGetter(self):
+ return " private native %s nativeGet%s(int index);"\
+ % (self.javatype, ToJavaName(self.name, 0))
+
+ def javaNativeSetter(self):
+ return " private native boolean nativeSet%s(int index, %s value);"\
+ % (ToJavaName(self.name, 0), self.javatype)
+
+ def jniGetterDefString(self):
+ return "JNIEXPORT %s JNICALL\n" \
+ "Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index);" \
+ % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0))
+
+ def jniGetterImplString(self):
+ return \
+ "%s Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index) {\n"\
+ " %s* instance = Get%sAtIndex(env, thiz, index);\n"\
+ " return instance ? instance->%s : %s;\n"\
+ "}\n" % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
+ self.structname, self.structname, self.name, self.defval)
+
+ def jniSetterDefString(self):
+ return "JNIEXPORT jboolean JNICALL\n" \
+ "Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value);" \
+ % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0), self.jtype)
+
+ def jniSetterImplString(self):
+ return \
+ "jboolean Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value) {\n"\
+ " %s* instance = Get%sAtIndex(env, thiz, index);\n"\
+ " if (instance) {\n"\
+ " instance->%s = value;\n"\
+ " return JNI_TRUE;\n"\
+ " }\n"\
+ " return JNI_FALSE;\n"\
+ "}\n" % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
+ self.jtype, self.structname, self.structname, self.name)
+
+class FieldType_Float(FieldType_BasePOD):
+ def __init__(self, name, structname, jclassname, package):
+ FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "float", "float", "jfloat", "0.0")
+
+class FieldType_Int(FieldType_BasePOD):
+ def __init__(self, name, structname, jclassname, package):
+ FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "int", "int", "jint", "0")
+
+class FieldType_Long(FieldType_BasePOD):
+ def __init__(self, name, structname, jclassname, package):
+ FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "long", "long long", "jlong", "0")
+
+class StructSpec:
+
+ def parseTextFile(self, filepath):
+ # Init
+ self.name = None
+ self.package = None
+ self.fields = []
+ self.structname = None
+ self.jclassname = None
+ self.libname = None
+
+ # Open the file
+ txtfile = open(filepath)
+
+ # Parse it line by line
+ lineno = 0
+ for line in txtfile:
+ # Split line into components
+ linecomps = line.split()
+ if len(linecomps) == 0:
+ continue
+
+ # Execute command
+ cmd = linecomps[0]
+ if cmd == "@name":
+ self.commandArgAssert(linecomps, 1, lineno)
+ self.name = linecomps[1]
+ if not self.structname:
+ self.structname = self.name
+ if not self.jclassname:
+ self.jclassname = self.name
+ elif cmd == "@package":
+ self.commandArgAssert(linecomps, 1, lineno)
+ self.package = linecomps[1]
+ elif cmd == "@libname":
+ self.commandArgAssert(linecomps, 1, lineno)
+ self.libname = linecomps[1]
+ elif cmd == "@structname":
+ self.commandArgAssert(linecomps, 1, lineno)
+ self.structname = linecomps[1]
+ elif cmd == "@javaclassname":
+ self.commandArgAssert(linecomps, 1, lineno)
+ self.jclassname = linecomps[1]
+ elif cmd == "@field":
+ self.commandArgAssert(linecomps, 2, lineno)
+ typestr = linecomps[1]
+ if typestr == "int":
+ fieldtype = FieldType_Int(linecomps[2], self.structname, self.jclassname, self.package)
+ elif typestr == "long":
+ fieldtype = FieldType_Long(linecomps[2], self.structname, self.jclassname, self.package)
+ elif typestr == "float":
+ fieldtype = FieldType_Float(linecomps[2], self.structname, self.jclassname, self.package)
+ else:
+ raise ParseError(lineno, "Unknown field type '%s'!" % typestr)
+ self.fields.append(fieldtype)
+ else:
+ raise ParseError(lineno, "Unknown command: '%s'!" % cmd)
+
+ lineno = lineno + 1
+
+ # Make sure we have all required info
+ if not self.name:
+ raise ParseError(lineno, "Required field '@name' missing!")
+ elif not self.package:
+ raise ParseError(lineno, "Required field '@package' missing!")
+ elif not self.libname:
+ raise ParseError(lineno, "Required field '@libname' missing!")
+
+ # Normalize values
+ if self.libname[:3] == "lib":
+ self.libname = self.libname[3:]
+
+ def commandArgAssert(self, linecomps, expectedcount, lineno):
+ foundcount = len(linecomps) - 1
+ if foundcount < expectedcount:
+ raise ParseError(lineno, "Not enough arguments specifed for command '%s'! Expected %d, " \
+ "but got only %d!" % (linecomps[0], expectedcount, foundcount))
+ elif foundcount > expectedcount + 1:
+ raise ParseError(lineno, "Too many arguments specifed for command '%s'! Expected %d, " \
+ "but got %d!" % (linecomps[0], expectedcount, foundcount))
+
+
+ def cStructString(self):
+ cfields = [f.cString() for f in self.fields]
+ return "typedef struct Struct%s {\n%s\n} %s;\n" % (self.structname,\
+ "\n".join(cfields),\
+ self.structname)
+
+ def javaClassString(self):
+ jgetters = [f.javaGetter() for f in self.fields]
+ jsetters = [f.javaSetter() for f in self.fields]
+ jnativesetters = [f.javaNativeSetter() for f in self.fields]
+ jnativegetters = [f.javaNativeGetter() for f in self.fields]
+ return "public class %s extends NativeBuffer {\n\n"\
+ " public %s() {\n"\
+ " super();\n"\
+ " }\n"\
+ "\n"\
+ " public %s(int count) {\n"\
+ " super(count);\n"\
+ " }\n"\
+ "\n"\
+ " public native int getElementSize();\n"\
+ "\n"\
+ "%s\n\n"\
+ "%s\n\n"\
+ "%s\n\n"\
+ "%s\n\n"\
+ " static {\n"\
+ " System.loadLibrary(\"%s\");\n"\
+ " }\n"\
+ "\n"\
+ "};\n" % (self.jclassname,\
+ self.jclassname,\
+ self.jclassname,\
+ "\n\n".join(jgetters),\
+ "\n\n".join(jsetters),\
+ "\n\n".join(jnativegetters),\
+ "\n\n".join(jnativesetters),\
+ self.libname)
+
+ def jniDeclString(self):
+ jnigetters = [f.jniGetterDefString() for f in self.fields]
+ jnisetters = [f.jniSetterDefString() for f in self.fields]
+ return "\n\n".join(jnigetters + jnisetters)
+
+ def jniImplString(self):
+ jnigetters = [f.jniGetterImplString() for f in self.fields]
+ jnisetters = [f.jniSetterImplString() for f in self.fields]
+ return "\n\n".join(jnigetters + jnisetters)
+
+ def hFileString(self):
+ defname = ToMacroDefName(self.structname, self.package)
+ return hFileTemplate % (defname, defname, self.cStructString(), defname)
+
+ def javaFileString(self):
+ return javaFileTemplate % (self.package, self.javaClassString())
+
+ def jniFileString(self):
+ return jniFileTemplate % (self.structname.lower(),\
+ self.structname,\
+ self.structname,\
+ self.structname,\
+ self.structname,\
+ ToJNIPackage(self.package, self.jclassname),\
+ self.jniDeclString(),\
+ ToJNIPackage(self.package, self.jclassname),\
+ self.structname,
+ self.jniImplString())
+
+def main(argv):
+ if len(argv) != 2:
+ print("Usage: %s <file.struct>" % argv[0])
+ return -1
+
+ filepath = argv[1]
+
+ structspec = StructSpec()
+ structspec.parseTextFile(filepath)
+
+ hfilename = "%s.h" % structspec.structname.lower()
+ javafilename = "%s.java" % structspec.jclassname
+ jnifilename = "jni_%s.c" % structspec.structname.lower()
+
+ javapackagepath = structspec.package.replace('.','/')
+
+ rootdir = os.path.dirname(filepath)
+ hfilepath = "%s/../native/%s" % (rootdir, hfilename)
+ javafilepath = "%s/../java/%s/%s" % (rootdir, javapackagepath, javafilename)
+ jnifilepath = "%s/../jni/%s" % (rootdir, jnifilename)
+
+ hfile = open(hfilepath, 'w')
+ hfile.write(structspec.hFileString())
+ hfile.close()
+
+ javafile = open(javafilepath, 'w')
+ javafile.write(structspec.javaFileString())
+ javafile.close()
+
+ jnifile = open(jnifilepath, 'w')
+ jnifile.write(structspec.jniFileString())
+ jnifile.close()
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))