FastCV Part 3
Part 1 - FastCV introduction and installation
Part 2 - How To Use Android NDK to Build FastCV for the RICOH THETA
This article was originally published in Japanese by roohi_3.
Create a FastCV application
Attempt to use FastCV API in the project.
- Adding an NDK source file
Select Project from the window tool bar and put the view in Project mode.
- Follow (project) > app> src > main > jni from the project tree, right click and select New > C/C++ Source File
- Enter the appropriate C++ file name and click OK
- Create a header file from New> C/C++ Header File
- A file will be created under jni
Open Android.mk and add the .cpp
file name added to LOCAL_SRC_FILES
Example:
LOCAL_SRC_FILES := \
FastCVSample.cpp
Click Sync Now displayed at the top of the editor window.
Implementation
Exchange of Java and native functions
As I am still learning about the NDK, I am not able to explain too much detail about the Java and native functions work together. There seems to be special rules for functions used for Java ↔ native (C++) exchanges.
It seems to use a special return type and argument type.
For details, refer to the JNI type and data structure etc.
Native side function naming convention.
JNIEXPORT [return type] JNICALL Java _ [relative path of Java source from top level source directory] _ [caller's Java class name] _ [function name] (JNIEnv *, jobject, [argument], ... ))
Example:
JNIEXPORT jstring Java_com_theta360_fastcvsimplesample_MainActivity_getFastCVVersion(JNIEnv * env, jobject obj);
Calling native functions from Java
It seems necessary to do the following
-
Call System.loadLibrary (“[.so file name]”) at startup
-
Declare function with native keyword
// example
static {
// Load JNI Library
Log.i(TAG, “Load JNI Library”);
System.loadLibrary(“fastcvsimplesample”); // ←
}
…private void foo(){
// call native function
String versionText = "FastCV Version: " + getFastCVVersion(); // ←
Log.i(TAG, versionText);
}
}
…// Define native function
public native String getFastCVVersion(); // ←
Basic API of FastCV
The basic API is defined in the Miscellaneous module.
When using FastCV, it is necessary to call the following initialization / termination processing API.
- Initialization processing: fcvSetOperationMode (fcvOperationMode mode);
- It seems to set performance level as argument.
- As in the document (fcvOperationMode section), five level setting values are defined.
- Termination processing: fcvCleanUp (void);
- Version acquisition: fcvGetVersion (char * version, unsigned int versionLength);
- In the argument, pass a pointer and number of characters for storing version information.
Code description example
Native Header File
FastCVSample.h
#ifndef THETA_PLUGIN_FASTCV_SIMPLE_SAMPLE_FASTCVSAMPLE_H
#define THETA_PLUGIN_FASTCV_SIMPLE_SAMPLE_FASTCVSAMPLE_H
#include <jni.h>
// Declarations
extern "C" {
JNIEXPORT void JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_initFastCV
(
JNIEnv* env,
jobject obj
);
JNIEXPORT void JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_cleanupFastCV
(
JNIEnv * env,
jobject obj
);
JNIEXPORT jstring JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_getFastCVVersion
(
JNIEnv* env,
jobject obj
);
};
#endif //THETA_PLUGIN_FASTCV_SIMPLE_SAMPLE_FASTCVSAMPLE_H
Native C++ File
FastCVSample.cpp
#include <fastcv/fastcv.h>
#include "FastCVSample.h"
JNIEXPORT void JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_initFastCV
(
JNIEnv* env,
jobject obj
)
{
fcvSetOperationMode( (fcvOperationMode) FASTCV_OP_PERFORMANCE );
return;
}
JNIEXPORT void JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_cleanupFastCV
(
JNIEnv * env,
jobject obj
)
{
fcvCleanUp();
}
JNIEXPORT jstring JNICALL Java_com_theta360_fastcvsimplesample_MainActivity_getFastCVVersion
(
JNIEnv * env,
jobject obj
)
{
char sVersion[32];
fcvGetVersion(sVersion, 32);
return env->NewStringUTF(sVersion);
}
Java File
I’m implementing the Java file based on MainActivity.java
of the RICOH THETA Plug-in SDK.
I am trying to call getFastCVVersion()
in onKeyDown()
. This makes it possible to display the version when you press the shutter button of THETA.
// MainActivity.java
// (partial snippet)
public class MainActivity extends PluginActivity {
private static final String TAG = "FastCVSimpleSample";
static {
// Load JNI Library
Log.i(TAG, "Load JNI Library");
System.loadLibrary("fastcvsimplesample"); // <--
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set enable to close by pluginlibrary, If you set false, please call close() after finishing your end processing.
setAutoClose(true);
// Set a callback when a button operation event is acquired.
setKeyCallback(new KeyCallback() {
@Override
public void onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
// call native function
String versionText = "FastCV Version: " + getFastCVVersion(); // <--
Log.i(TAG, versionText);
}
}
@Override
public void onKeyUp(int keyCode, KeyEvent event) {
}
@Override
public void onKeyLongPress(int keyCode, KeyEvent event) {
}
});
}
@Override
protected void onResume()
{
super.onResume();
initFastCV(); // <--
}
@Override
protected void onPause() {
cleanupFastCV(); // <--
super.onPause();
}
// define native function
public native void initFastCV(); // <--
public native void cleanupFastCV(); // <--
public native String getFastCVVersion(); // <--
}
Build and run
- Click Run > Run app from the menu to build and execute
- When the Select Deployment Target window appears, select THETA V and click OK
- Check Build in the tool window to confirm that the build succeeded
When describing the code, the version of FastCV is displayed in Logcat when the shutter button is pressed.
Note: Filtering with the TAG name set in Log.i () is easy to see
Conclusion
I think that the work to be completed this time was somewhat fun and challenging. It was quite a difficult task …
In the next article series, we will introduce the procedure to actually process the image.