Using native memory for camera buffer - android

I want to use native memory instead of Java heap, for camera buffer in camera.addCallbackBuffer();
I write some code, but it's wrong. I get null -array.
How to do it properly?
Java PART
buflen=allocBuffer(1280,720);
byte[] x= getBuffern(0,1280,720);//than i want to use this for addCallbackBuffer()
freeBuffer();
NDK PART
signed char * yuvm;
size_t getTotalSystemMemory()
{
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
return pages * page_size;
}
jint Java_com_example_testdvr_mycamview_allocBuffer(JNIEnv * env, jclass obj, jint width, jint height){
jint bufLength=getTotalSystemMemory()/4;
bufLength=bufLength/(width*height*1.5);
yuvm = (signed char*) malloc (bufLength*width*height*1.5);
return bufLength;
}
void Java_com_example_testdvr_mycamview_freeBuffer(JNIEnv * env, jclass obj){
if (sizeof(yuvm)!=0){
free(yuvm);
}
}
jbyteArray Java_com_example_testdvr_mycamview_getBuffern(JNIEnv * env, jclass obj, jint numbuf, jint width, jint height){
jbyteArray res;
env->SetByteArrayRegion(res,width*height*1.5*numbuf,width*height*1.5,yuvm);
return res;
}
Also i have idea to use camera object from NDK for native memory for buffer.
LIKE THIS:
JNIEXPORT void JNICALL Java_com_test_jnicall_ld(
JNIEnv *env,
jclass clazs,
jobject camera) {
jclass clazz = env->GetObjectClass(camera);
jmethodID voidVoidMethod = env->GetMethodID(clazz,"addCallbackBuffer", "([B)V");
jbyteArray* b=malloc(640*480*3/2);
env->CallVoidMethod(camera, voidVoidMethod,b);
}
But have a problem to:
09-18 13:24:22.982: W/dalvikvm(27090): Invalid indirect reference 0x783f8008 in decodeIndirectRef
09-18 13:24:22.982: E/dalvikvm(27090): VM aborting
09-18 13:24:22.982: A/libc(27090): Fatal signal 6 (SIGABRT) at 0x000069d2 (code=-6), thread 27123 (Thread-4070)

Related

JNI Issue on certain devices

Hi everyone I have a problem on certain android devices (This device is running android 5.1)
I have the following code
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_peachss_sadldecoder_Decoder_getDecodedPhoto(JNIEnv *env, jclass clazz,
jbyteArray photo_data, jint size) {
jbyte* input= env->GetByteArrayElements(photo_data, 0);
WiResultImage decode = DecodeImage((unsigned char*)input, size + 1);
env->ReleaseByteArrayElements(photo_data, input, JNI_ABORT);
jbyteArray output = env->NewByteArray(decode.size);
env->SetByteArrayRegion(output, 0, decode.size, (jbyte*)decode.raw);
return output;
}
The moment it reaches 'NewByteArray' I get the following error
Signal: SIGABRT (signal SIGABRT)

NDK memory saturation

I had to use NDK in my java code to call some audio processing functions, but i have never tried JNI or C/C++ coding. I tried to start from the scratch but i really have no time. so i found this library here and tried to use it. I always get a fatal signal 11 (sigsegv) error. I really don't know where to start. here's what i have done so far:
in the Android Activity:
public native int transform(double[] real,double[]imag, int n);
public native int convolve(double[]xreal,double[]ximag,double[]yreal,double[]yimag,double[]outreal,double[]outim, int n);
and they are called in the same file like this :
transform(raw1, imag1,raw1.length);//result back into each vector
transform(raw2, imag2,raw2.length);
convolve(raw1,imag1,raw2,imag2,outre,outim,raw1.length);
in the C file:
JNIEXPORT jint JNICALL Java_com_example_ffttest_FFTActivity_transform
(JNIEnv *env, jobject obj, jdoubleArray real, jdoubleArray imag, jint n)
{
if (n == 0)
return 1;
else if ((n & (n - 1)) == 0) // Is power of 2
return transform_radix2(real, imag, n);
else // More complicated algorithm for arbitrary sizes
return transform_bluestein(real, imag, n);
}
and made some changes to the convolve function:
JNIEXPORT jint JNICALL Java_com_example_ffttest_FFTActivity_convolve
(JNIEnv *env, jobject obj, jdoubleArray xreal, jdoubleArray ximag, jdoubleArray yreal, jdoubleArray yimag, jdoubleArray outreal, jdoubleArray outimag, jint n)
{
//size = n * sizeof(double);
n = (*env)->GetArrayLength(env, xreal);
jdouble *a=(*env)->GetDoubleArrayElements(env,xreal,0);
jdouble *b=(*env)->GetDoubleArrayElements(env,ximag,0);
jdouble *c=(*env)->GetDoubleArrayElements(env,yreal,0);
jdouble *d=(*env)->GetDoubleArrayElements(env,yimag,0);
jdouble *e=(*env)->GetDoubleArrayElements(env,outreal,0);
jdouble *f=(*env)->GetDoubleArrayElements(env,outimag,0);
...
Is there some changes i need to know from C to JNI?

Return a double pointer in JNI

I want return a pointer to a double array in JNI, and then, use this values in Java's code. So i did this:
JNIEXPORT jlong JNICALL Java_com_sistoleaudiocapture_Processing_prueba_1nativa(
JNIEnv * env, jclass, jlong retorno, jbyteArray data, jint lenbytes) {
//PROCESS
long dirt;
dirt=(long)d_est;
return(dirt);
}
In my java funcition:
public void prueba(byte[] data, int lenbytes) {
prueba=prueba_nativa(retorno, data, lenbytes);
}
So now, How can I acess to my values?
Thanks
You can either create additional functions to access the array on the native side, exposing them to Java. Or you can create a jDoubleArray within your native code, and return that to Java.
const double * arrayPtr = (const double *)&yourDoubleArray;
jint lengthOfArray = 0; //Fill dynamically with the length of your native double array.
jdoubleArray doubleArray = (*env)->NewDoubleArray(env, lengthOfArray);
(*env)->SetDoubleArrayRegion( env, doubleArray, 0, 16, arrayPtr);
return doubleArray;

pass uint_8 array using params

I tryed to writer method like InputStream:read(byte[] buffer,int offset,int length):
/*
* Class: com_readium_ResourceStream
* Method: readNative
* Signature: ([BII)I
*/
JNIEXPORT jint JNICALL Java_com_readium_ResourceStream_readNative
(JNIEnv *, jobject, jbyteArray, jint, jint);
How can I write uint_8 array to jbyteArray from params?
This is my answer. It must be compiled as a c++ compilation unit. Otherwise you have to pass env as the first param (ie env->GetArrayLength(...); become in c GetArrayLength(env, ...).
/*
* Class: com_readium_ResourceStream
* Method: readNative
* Signature: ([BII)I
*/
JNIEXPORT jint JNICALL Java_com_readium_ResourceStream_readNative
(JNIEnv *env, jobject obj, jbyteArray buffer, jint offset, jint len)
{
jint readed;
// Read data and set readed
jboolean isCopy;
jsize arrayLen = env->GetArrayLength(buffer);
jbyte* array = env->GetByteArrayElements(env, buffer, &isCopy);
// Use array here
env->ReleaseByteArrayElements(buffer, array, 0);
return readed;
}
Remeber, java bytes are always signed.

Use a simple c++ class in Android NDK

I'm trying to learn the basics of Android NDK but I'm stucked when I have to use it with a c++ class.
I understand how to use it with a simple function but what should I do to be able to manipulate the fields and the methods of a c++ class ?
I'm trying to do it with this simple c++ class :
#include <cstdlib>
#include <jni.h>
using namespace std;
class Point {
int x, y; // coordonnées du point
public:
Point() {
this->x = 0;
this->y = 0;
}
Point(int x, int y) {
this->x = x;
this->y = y;
}
int getX() const {
return x;
}
int getY() const {
return y;
}
Point symetrique() const {
return Point(-x, -y);
}
bool operator ==(const Point &p) const {
return this->x == p.getX() && this->y == p.getY();
}
};
extern "C" {
JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__
(JNIEnv *, jobject);
JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__II
(JNIEnv *, jobject, jint, jint);
JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetX
(JNIEnv *, jobject, jlong);
JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetY
(JNIEnv *, jobject, jlong);
JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_nativeSymetrique
(JNIEnv *, jobject, jlong);
};
JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__(JNIEnv* env, jobject thiz) {
return (jlong)(new Point());
}
JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__II(JNIEnv* env, jobject thiz, jint x, jint y) {
return (jlong)(new Point(x, y));
}
JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetX(JNIEnv* env, jobject thiz, jlong nativePointer) {
return ((Point*)nativePointer)->getX();
}
JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetY(JNIEnv* env, jobject thiz, jlong nativePointer) {
return ((Point*)nativePointer)->getY();
}
jlong Java_com_example_jnipoint_JPoint_nativeSymetrique(JNIEnv* env, jobject thiz, jlong nativePointer) {
return ((Point*)nativePointer)->symetrique();
}
I tried to find samples but nothing so far... Maybe I'm not using the right keywords
* UPDATE *
I created a Java wrapper for the c++ Point class and added to the c++ file JNI methods. The code is the following :
public class JPoint {
private long nativePointer;
public JPoint() {
nativePointer = createPoint();
}
public JPoint(int x, int y) {
nativePointer = createPoint(x, y);
}
public int getX() {
return nativeGetX(nativePointer);
}
public int getY() {
return nativeGetY(nativePointer);
}
public JPoint symetrique() {
JPoint tmp = new JPoint();
tmp.nativePointer = nativeSymetrique(nativePointer);
return tmp;
}
// TODO
/*public boolean equals(Object o) {
return nativeEquals(o);
}*/
private native long createPoint(); // Void constructor
private native long createPoint(int x, int y);
private native int nativeGetX(long nativePointer);
private native int nativeGetY(long nativePointer);
private native long nativeSymetrique(long nativePointer);
//private native boolean nativeEquals(Object p); TODO
}
Right now I'm stucked with the nativeSymetrique function, it says that I cannot convert 'Point' to 'jlong'. Can anyone help me on this ? Thanks
* UPDATE 2 *
SWIG solved my issues, you don't have to handwrite the wrappers and it seems to be a good choice for big libraries.
Have a look at JNA.
JNI is meant to access Java classes/objects from C. Which means that JNI gives you C functions for accessing JVM. But there is no way vice versa: to access C structures (C++ classes) from JVM. Java has no such methods. So if you want to have a "class reflection" between C++ and Java, the only you can do is to have the class on Java side and a set of JNI C calls to access, modify and call methods on the Java object. JNI native methods on Java side are of no use for you, because the only parameters it can take (in or out) can be again only Java objects (or primitives or arrays). There is simply no way to pass C(++) structures/objects to Java side.
You can manipulate with your C code as you wish and pass\return values via JNI, you can find JNI samples in androidndk/samples - helloJni.
For example:
JNIEXPORT jfloat JNICALL Java_com_opengl_glworld_GLWorldRenderer_changeCurrentArea(JNIEnv *env, jobject obj, jfloat curArea)
{
area = curArea;
return area;
// here you can execude you C code, you can access to methods of class,
// or method that use your classes.
}
As I said in my second update, SWIG was the perfect match for my needs.

Categories

Resources