#!/usr/bin/python
+ from optparse import OptionParser
+ from shutil import rmtree
import os
- import sys
-
- ANDROID_SDK_PATH = "/opt/android-sdk-linux"
- ANDROID_NDK_PATH = None
- INSTALL_DIRECTORY = None
- CLASS_PATH = None
- TMP_HEADER_PATH="tmp_include"
- HEADER_EXTS = set(['h', 'hpp'])
- SYS_INCLUDES = ["platforms/android-8/arch-arm/usr/include", "sources/cxx-stl/gnu-libstdc++/include", "sources/cxx-stl/gnu-libstdc++/libs/armeabi/include"]
-
- PROJECT_NAME = "OpenCV-branch"
- TARGET_LIBS = ["libopencv_java.so"]
- ARCH = "armeabi"
- GCC_OPTIONS = "-fpermissive"
- EXCLUDE_HEADERS = set(["hdf5.h", "eigen.hpp", "cxeigen.hpp"]);
-
- def FindClasses(root, prefix):
+
+
+ architecture = 'armeabi'
-excludedHeaders = set(['hdf5.h', 'cap_ios.h',
++excludedHeaders = set(['hdf5.h', 'cap_ios.h',
+ 'eigen.hpp', 'cxeigen.hpp' #TOREMOVE
+ ])
+ systemIncludes = ['sources/cxx-stl/gnu-libstdc++/4.6/include', \
+ '/opt/android-ndk-r8c/platforms/android-8/arch-arm', # TODO: check if this one could be passed as command line arg
+ 'sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include']
+ targetLibs = ['libopencv_java.so']
+ preamble = ['Eigen/Core']
+ # TODO: get gcc_options automatically
+ gcc_options = ['-fexceptions', '-frtti', '-Wno-psabi', '--sysroot=/opt/android-ndk-r8c/platforms/android-8/arch-arm', '-fpic', '-D__ARM_ARCH_5__', '-D__ARM_ARCH_5T__', '-D__ARM_ARCH_5E__', '-D__ARM_ARCH_5TE__', '-fsigned-char', '-march=armv5te', '-mtune=xscale', '-msoft-float', '-fdata-sections', '-ffunction-sections', '-Wa,--noexecstack ', '-W', '-Wall', '-Werror=return-type', '-Werror=address', '-Werror=sequence-point', '-Wformat', '-Werror=format-security', '-Wmissing-declarations', '-Wundef', '-Winit-self', '-Wpointer-arith', '-Wshadow', '-Wsign-promo', '-Wno-narrowing', '-fdiagnostics-show-option', '-fomit-frame-pointer', '-mthumb', '-fomit-frame-pointer', '-O3', '-DNDEBUG ', '-DNDEBUG']
+ excludedOptionsPrefix = '-W'
+
+
+
+ def GetHeaderFiles(root):
+ headers = []
+ for path in os.listdir(root):
+ if not os.path.isdir(os.path.join(root, path)) \
+ and os.path.splitext(path)[1] in ['.h', '.hpp'] \
+ and not path in excludedHeaders:
+ headers.append(os.path.join(root, path))
+ return sorted(headers)
+
+
+
+ def GetClasses(root, prefix):
classes = []
- if ("" != prefix):
- prefix = prefix + "."
+ if ('' != prefix):
+ prefix = prefix + '.'
for path in os.listdir(root):
- currentPath = os.path.join(root, path)
- if (os.path.isdir(currentPath)):
- classes += FindClasses(currentPath, prefix + path)
- else:
- name = str.split(path, ".")[0]
- ext = str.split(path, ".")[1]
- if (ext == "class"):
- #print("class: %s" % (prefix + name))
- classes.append(prefix+name)
+ currentPath = os.path.join(root, path)
+ if (os.path.isdir(currentPath)):
+ classes += GetClasses(currentPath, prefix + path)
+ else:
+ name = str.split(path, '.')[0]
+ ext = str.split(path, '.')[1]
+ if (ext == 'class'):
+ classes.append(prefix + name)
return classes
- def FindHeaders(root):
+
+
+ def GetJavaHHeaders():
+ print('\nGenerating JNI headers for Java API ...')
+
+ javahHeaders = os.path.join(managerDir, 'javah_generated_headers')
+ if os.path.exists(javahHeaders):
+ rmtree(javahHeaders)
+ os.makedirs(os.path.join(os.getcwd(), javahHeaders))
+
+ AndroidJavaDeps = os.path.join(SDK_path, 'platforms/android-11/android.jar')
+
+ classPath = os.path.join(managerDir, 'sdk/java/bin/classes')
+ if not os.path.exists(classPath):
+ print('Error: no Java classes found in \'%s\'' % classPath)
+ quit()
+
+ allJavaClasses = GetClasses(classPath, '')
+ if not allJavaClasses:
+ print('Error: no Java classes found')
+ quit()
+
+ for currentClass in allJavaClasses:
+ os.system('javah -d %s -classpath %s:%s %s' % (javahHeaders, classPath, \
+ AndroidJavaDeps, currentClass))
+
+ print('\nBuilding JNI headers list ...')
+ jniHeaders = GetHeaderFiles(javahHeaders)
+
+ return jniHeaders
+
+
+
+ def GetImmediateSubdirs(dir):
+ return [name for name in os.listdir(dir)
+ if os.path.isdir(os.path.join(dir, name))]
+
+
+
+ def GetOpenCVModules():
+ makefile = open(os.path.join(managerDir, 'sdk/native/jni/OpenCV.mk'), 'r')
+ makefileStr = makefile.read()
+ left = makefileStr.find('OPENCV_MODULES:=') + len('OPENCV_MODULES:=')
+ right = makefileStr[left:].find('\n')
+ modules = makefileStr[left:left+right].split()
+ modules = filter(lambda x: x != 'ts' and x != 'androidcamera', modules)
+ return modules
+
+
+
+ def FindHeaders():
headers = []
- for path in os.listdir(root):
- currentPath = os.path.join(root, path)
- if (os.path.isdir(currentPath)):
- headers += FindHeaders(currentPath)
- else:
- ext = str.split(path, ".")[-1]
- #print("%s: \"%s\"" % (currentPath, ext))
- if (ext in HEADER_EXTS):
- #print("Added as header file")
- if (path not in EXCLUDE_HEADERS):
- headers.append(currentPath)
+
+ print('\nBuilding Native OpenCV header list ...')
+
+ cppHeadersFolder = os.path.join(managerDir, 'sdk/native/jni/include/opencv2')
+
+ modulesFolders = GetImmediateSubdirs(cppHeadersFolder)
+ modules = GetOpenCVModules()
+
+ cppHeaders = []
+ for m in modules:
+ for f in modulesFolders:
+ moduleHeaders = []
+ if f == m:
+ moduleHeaders += GetHeaderFiles(os.path.join(cppHeadersFolder, f))
+ if m == 'flann':
- flann = os.path.join(cppHeadersFolder, f, 'flann.hpp')
++ flann = os.path.join(cppHeadersFolder, f, 'flann.hpp')
+ moduleHeaders.remove(flann)
+ moduleHeaders.insert(0, flann)
+ cppHeaders += moduleHeaders
+
+
+ cppHeaders += GetHeaderFiles(cppHeadersFolder)
+ headers += cppHeaders
+
+ cHeaders = GetHeaderFiles(os.path.join(managerDir, \
+ 'sdk/native/jni/include/opencv'))
+ headers += cHeaders
+
+ headers += GetJavaHHeaders()
+
return headers
- if (len(sys.argv) < 3):
- print("Error: Invalid command line arguments")
- exit(-1)
-
- INSTALL_DIRECTORY = sys.argv[1]
- PROJECT_NAME = sys.argv[2]
-
- CLASS_PATH = os.path.join(INSTALL_DIRECTORY, "sdk/java/bin/classes")
- if (not os.path.exists(CLASS_PATH)):
- print("Error: no java classes found in \"%s\"" % CLASS_PATH)
- exit(-2)
-
- if (os.environ.has_key("NDK_ROOT")):
- ANDROID_NDK_PATH = os.environ["NDK_ROOT"];
- print("Using Android NDK from NDK_ROOT (\"%s\")" % ANDROID_NDK_PATH)
-
- if (not ANDROID_NDK_PATH):
- pipe = os.popen("which ndk-build")
- tmp = str.strip(pipe.readline(), "\n")
- while(not tmp):
- tmp = str.strip(pipe.readline(), "\n")
- pipe.close()
- ANDROID_NDK_PATH = os.path.split(tmp)[0]
- print("Using Android NDK from PATH (\"%s\")" % ANDROID_NDK_PATH)
-
- print("Using Android SDK from \"%s\"" % ANDROID_SDK_PATH)
-
- outputFileName = PROJECT_NAME + ".xml"
- try:
- outputFile = open(outputFileName, "w")
- except:
- print("Error: Cannot open output file \"%s\" for writing" % outputFileName)
-
- allJavaClasses = FindClasses(CLASS_PATH, "")
- if (not allJavaClasses):
- print("Error: No Java classes found :(")
- exit(-1)
-
- if (not os.path.exists(TMP_HEADER_PATH)):
- os.makedirs(os.path.join(os.getcwd(), TMP_HEADER_PATH))
-
- print("Generating JNI headers for Java API ...")
- AndroidJavaDeps = os.path.join(ANDROID_SDK_PATH, "platforms/android-11/android.jar")
- for currentClass in allJavaClasses:
- os.system("javah -d %s -classpath %s:%s %s" % (TMP_HEADER_PATH, CLASS_PATH, AndroidJavaDeps, currentClass))
-
- print("Building JNI headers list ...")
- jniHeaders = FindHeaders(TMP_HEADER_PATH)
- #print(jniHeaders)
-
- print("Building Native OpenCV header list ...")
- cHeaders = FindHeaders(os.path.join(INSTALL_DIRECTORY, "sdk/native/jni/include/opencv"))
- cppHeaders = FindHeaders(os.path.join(INSTALL_DIRECTORY, "sdk/native/jni/include/opencv2"))
- #print(cHeaders)
- #print(cppHeaders)
-
- print("Writing config file ...")
- outputFile.write("<descriptor>\n\n<version>\n\t%s\n</version>\n\n<headers>\n" % PROJECT_NAME)
- outputFile.write("\t" + "\n\t".join(cHeaders))
- outputFile.write("\n\t" + "\n\t".join(cppHeaders))
- outputFile.write("\n\t" + "\n\t".join(jniHeaders))
- outputFile.write("\n</headers>\n\n")
-
- includes = [os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include"),
- os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include", "opencv"),
- os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include", "opencv2")]
-
- for inc in SYS_INCLUDES:
- includes.append(os.path.join(ANDROID_NDK_PATH, inc))
-
- outputFile.write("<include_paths>\n\t%s\n</include_paths>\n\n" % "\n\t".join(includes))
-
- libraries = []
- for lib in TARGET_LIBS:
- libraries.append(os.path.join(INSTALL_DIRECTORY, "sdk/native/libs", ARCH, lib))
-
- outputFile.write("<libs>\n\t%s\n</libs>\n\n" % "\n\t".join(libraries))
- outputFile.write("<gcc_options>\n\t%s\n</gcc_options>\n\n</descriptor>" % GCC_OPTIONS)
-
- print("done!")
+
+
+ def FindLibraries():
+ libraries = []
+ for lib in targetLibs:
+ libraries.append(os.path.join(managerDir, 'sdk/native/libs', architecture, lib))
+ return libraries
+
+
+
+ def FindIncludes():
+ includes = [os.path.join(managerDir, 'sdk', 'native', 'jni', 'include'),
+ os.path.join(managerDir, 'sdk', 'native', 'jni', 'include', 'opencv'),
+ os.path.join(managerDir, 'sdk', 'native', 'jni', 'include', 'opencv2')]
+
+ for inc in systemIncludes:
+ includes.append(os.path.join(NDK_path, inc))
+
+ return includes
+
+
+
+ def FilterGCCOptions():
+ gcc = filter(lambda x: not x.startswith(excludedOptionsPrefix), gcc_options)
+ return sorted(gcc)
+
+
+
+ def WriteXml(version, headers, includes, libraries):
+ xmlName = version + '.xml'
+
+ print '\noutput file: ' + xmlName
+ try:
+ xml = open(xmlName, 'w')
+ except:
+ print 'Error: Cannot open output file "%s" for writing' % xmlName
+ quit()
+
+ xml.write('<descriptor>')
+
+ xml.write('\n\n<version>')
+ xml.write('\n\t%s' % version)
+ xml.write('\n</version>')
+
+ xml.write('\n\n<headers>')
+ xml.write('\n\t%s' % '\n\t'.join(headers))
+ xml.write('\n</headers>')
+
+ xml.write('\n\n<include_paths>')
+ xml.write('\n\t%s' % '\n\t'.join(includes))
+ xml.write('\n</include_paths>')
+
+ # TODO: uncomment when Eigen problem is solved
+ # xml.write('\n\n<include_preamble>')
+ # xml.write('\n\t%s' % '\n\t'.join(preamble))
+ # xml.write('\n</include_preamble>')
+
+ xml.write('\n\n<libs>')
+ xml.write('\n\t%s' % '\n\t'.join(libraries))
+ xml.write('\n</libs>')
+
+ xml.write('\n\n<gcc_options>')
+ xml.write('\n\t%s' % '\n\t'.join(gcc_options))
+ xml.write('\n</gcc_options>')
+
+ xml.write('\n\n</descriptor>')
+
+
+
+ if __name__ == '__main__':
+ usage = '%prog <OpenCV_Manager install directory> <OpenCV_Manager version>'
+ parser = OptionParser(usage = usage)
+
+ args = parser.parse_args()
+ if 2 != len(args):
+ parser.print_help()
+ quit()
+
+ managerDir = args[1][0]
+ version = args[1][1]
+
+ NDK_path = '/opt/android-ndk-r8c'
+ print '\nUsing Android NDK from "%s"' % NDK_path
+
+ SDK_path = '~/NVPACK/android-sdk-linux'
+ print '\nUsing Android SDK from "%s"' % SDK_path
+
+ headers = FindHeaders()
+
+ includes = FindIncludes()
+
+ libraries = FindLibraries()
+
+ gcc_options = FilterGCCOptions()
+
+ WriteXml(version, headers, includes, libraries)
#define AVSEEK_FLAG_ANY 1
#endif
- static void icvInitFFMPEG_internal()
+ class ImplMutex
{
- static volatile bool initialized = false;
- if( !initialized )
+ public:
- ImplMutex() { init(); }
- ~ImplMutex() { destroy(); }
-
++ ImplMutex() { init(); }
++ ~ImplMutex() { destroy(); }
++
+ void init();
+ void destroy();
+
+ void lock();
+ bool trylock();
+ void unlock();
+
+ struct Impl;
+ protected:
+ Impl* impl;
+
+ private:
+ ImplMutex(const ImplMutex&);
+ ImplMutex& operator = (const ImplMutex& m);
+ };
+
+ #if defined WIN32 || defined _WIN32 || defined WINCE
+
+ struct ImplMutex::Impl
+ {
+ void init() { InitializeCriticalSection(&cs); refcount = 1; }
+ void destroy() { DeleteCriticalSection(&cs); }
+
+ void lock() { EnterCriticalSection(&cs); }
+ bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
+ void unlock() { LeaveCriticalSection(&cs); }
+
+ CRITICAL_SECTION cs;
+ int refcount;
+ };
+
+ #ifndef __GNUC__
+ static int _interlockedExchangeAdd(int* addr, int delta)
+ {
+ #if defined _MSC_VER && _MSC_VER >= 1500
+ return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
+ #else
+ return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
+ #endif
+ }
+ #endif // __GNUC__
+
+ #elif defined __APPLE__
+
+ #include <libkern/OSAtomic.h>
+
+ struct ImplMutex::Impl
+ {
+ void init() { sl = OS_SPINLOCK_INIT; refcount = 1; }
+ void destroy() { }
+
+ void lock() { OSSpinLockLock(&sl); }
+ bool trylock() { return OSSpinLockTry(&sl); }
+ void unlock() { OSSpinLockUnlock(&sl); }
+
+ OSSpinLock sl;
+ int refcount;
+ };
+
+ #elif defined __linux__ && !defined ANDROID
+
+ struct ImplMutex::Impl
+ {
+ void init() { pthread_spin_init(&sl, 0); refcount = 1; }
+ void destroy() { pthread_spin_destroy(&sl); }
+
+ void lock() { pthread_spin_lock(&sl); }
+ bool trylock() { return pthread_spin_trylock(&sl) == 0; }
+ void unlock() { pthread_spin_unlock(&sl); }
+
+ pthread_spinlock_t sl;
+ int refcount;
+ };
+
+ #else
+
+ struct ImplMutex::Impl
+ {
+ void init() { pthread_mutex_init(&sl, 0); refcount = 1; }
+ void destroy() { pthread_mutex_destroy(&sl); }
+
+ void lock() { pthread_mutex_lock(&sl); }
+ bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
+ void unlock() { pthread_mutex_unlock(&sl); }
+
+ pthread_mutex_t sl;
+ int refcount;
+ };
+
+ #endif
+
+ void ImplMutex::init()
+ {
- impl = (Impl*)malloc(sizeof(Impl));
- impl->init();
++ impl = (Impl*)malloc(sizeof(Impl));
++ impl->init();
+ }
-void ImplMutex::destroy()
++void ImplMutex::destroy()
+ {
- impl->destroy();
- free(impl);
- impl = NULL;
++ impl->destroy();
++ free(impl);
++ impl = NULL;
+ }
+ void ImplMutex::lock() { impl->lock(); }
+ void ImplMutex::unlock() { impl->unlock(); }
+ bool ImplMutex::trylock() { return impl->trylock(); }
+
+ static int LockCallBack(void **mutex, AVLockOp op)
+ {
+ ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex);
+ switch (op)
{
+ case AV_LOCK_CREATE:
+ localMutex = reinterpret_cast<ImplMutex*>(malloc(sizeof(ImplMutex)));
+ localMutex->init();
+ *mutex = localMutex;
+ if (!*mutex)
+ return 1;
+ break;
+
+ case AV_LOCK_OBTAIN:
+ localMutex->lock();
+ break;
+
+ case AV_LOCK_RELEASE:
+ localMutex->unlock();
+ break;
+
+ case AV_LOCK_DESTROY:
+ localMutex->destroy();
+ free(localMutex);
+ localMutex = NULL;
+ break;
+ }
+ return 0;
+ }
+
+ static ImplMutex _mutex;
+ static bool _initialized = false;
+
+ class InternalFFMpegRegister
+ {
+ public:
+ InternalFFMpegRegister()
+ {
+ _mutex.lock();
+ if (!_initialized)
+ {
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
- avformat_network_init();
+ avformat_network_init();
#endif
- /* register all codecs, demux and protocols */
- av_register_all();
+ /* register all codecs, demux and protocols */
+ av_register_all();
- av_log_set_level(AV_LOG_ERROR);
+ /* register a callback function for synchronization */
+ av_lockmgr_register(&LockCallBack);
- initialized = true;
+ av_log_set_level(AV_LOG_ERROR);
+
+ _initialized = true;
+ }
+ _mutex.unlock();
}
- }
+
+ ~InternalFFMpegRegister()
+ {
+ _initialized = false;
+ av_lockmgr_register(NULL);
+ }
+ };
+
+ static InternalFFMpegRegister _init;
bool CvCapture_FFMPEG::open( const char* _filename )
{