nuclear@6: #include nuclear@9: #include nuclear@6: #include nuclear@6: #include nuclear@6: #include "opengl.h" nuclear@6: #include "camera.h" nuclear@6: nuclear@6: nuclear@6: static JavaVM *jvm; nuclear@6: static JNIEnv *jni; nuclear@6: static jclass activity_class; nuclear@6: static unsigned int tex; nuclear@9: static float tex_matrix[16]; nuclear@9: static const float identity_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@9: static jfloatArray jtex_matrix; nuclear@6: static int capturing; nuclear@6: nuclear@6: int cam_init(void *platform_data) nuclear@6: { nuclear@6: int glerr; nuclear@6: struct cam_android_platform_data *pdata = platform_data; nuclear@6: nuclear@6: jvm = pdata->vm; nuclear@6: jni = pdata->jni; nuclear@6: activity_class = pdata->activity_class; nuclear@6: nuclear@9: jtex_matrix = (*jni)->NewFloatArray(jni, 16); nuclear@9: nuclear@6: // create the camera texture nuclear@6: assert(glGetError() == GL_NO_ERROR); nuclear@6: glGenTextures(1, &tex); nuclear@6: glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); nuclear@6: glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); nuclear@6: glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); nuclear@6: nuclear@6: glerr = glGetError(); nuclear@6: assert(glerr == GL_NO_ERROR); nuclear@6: return glerr == GL_NO_ERROR ? 0 : -1; nuclear@6: } nuclear@6: nuclear@6: void cam_shutdown(void) nuclear@6: { nuclear@6: cam_stop_video(); nuclear@6: glDeleteTextures(1, &tex); nuclear@6: tex = 0; nuclear@9: nuclear@9: if(jni) { nuclear@9: (*jni)->DeleteGlobalRef(jni, jtex_matrix); nuclear@9: } nuclear@6: } nuclear@6: nuclear@6: unsigned int cam_texture(void) nuclear@6: { nuclear@6: return tex; nuclear@6: } nuclear@6: nuclear@9: const float *cam_texture_matrix(void) nuclear@6: { nuclear@9: return tex_matrix; nuclear@6: } nuclear@6: nuclear@6: int cam_start_video(void) nuclear@6: { nuclear@6: jmethodID method; nuclear@6: nuclear@6: if(!jvm) { nuclear@6: fprintf(stderr, "failed to start video, camera not initialized\n"); nuclear@6: return -1; nuclear@6: } nuclear@6: if(cam_is_capturing()) { nuclear@6: return 0; nuclear@6: } nuclear@6: nuclear@6: if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "start_video", "(I)I"))) { nuclear@6: fprintf(stderr, "failed to find static method: start_video\n"); nuclear@6: return -1; nuclear@6: } nuclear@6: if((*jni)->CallStaticIntMethod(jni, activity_class, method, tex) == -1) { nuclear@6: fprintf(stderr, "failed to start video capture\n"); nuclear@6: capturing = 0; nuclear@6: return -1; nuclear@6: } nuclear@6: capturing = 1; nuclear@6: nuclear@6: printf("video started\n"); nuclear@6: nuclear@6: return 1; nuclear@6: } nuclear@6: nuclear@6: int cam_stop_video(void) nuclear@6: { nuclear@6: jmethodID method; nuclear@6: nuclear@6: if(!jvm) { nuclear@6: fprintf(stderr, "failed to stop video, camera not initialized\n"); nuclear@6: return -1; nuclear@6: } nuclear@6: nuclear@6: if(!cam_is_capturing()) { nuclear@6: return 0; nuclear@6: } nuclear@6: nuclear@6: if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "stop_video", "()V"))) { nuclear@6: fprintf(stderr, "failed to find static method: stop_video\n"); nuclear@6: return -1; nuclear@6: } nuclear@6: (*jni)->CallStaticVoidMethod(jni, activity_class, method); nuclear@6: capturing = 0; nuclear@6: nuclear@6: printf("video stopped\n"); nuclear@6: nuclear@6: return 0; nuclear@6: } nuclear@6: nuclear@8: int cam_update(void) nuclear@7: { nuclear@9: static int texmat_fail_warned; nuclear@7: jmethodID method; nuclear@9: float *ptr; nuclear@7: nuclear@7: if(!jvm) { nuclear@7: fprintf(stderr, "failed to update camera\n"); nuclear@7: return -1; nuclear@7: } nuclear@7: if(!cam_is_capturing()) { nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@9: if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "update", "([F)V"))) { nuclear@7: fprintf(stderr, "failed to find static method: update\n"); nuclear@7: return -1; nuclear@7: } nuclear@9: (*jni)->CallStaticVoidMethod(jni, activity_class, method, jtex_matrix); nuclear@9: nuclear@9: if(!(ptr = (*jni)->GetFloatArrayElements(jni, jtex_matrix, 0))) { nuclear@9: if(!texmat_fail_warned) { nuclear@9: fprintf(stderr, "failed to get texture matrix\n"); nuclear@9: texmat_fail_warned = 1; nuclear@9: } nuclear@9: memcpy(tex_matrix, identity_matrix, sizeof identity_matrix); nuclear@9: } else { nuclear@9: memcpy(tex_matrix, ptr, 16 * sizeof *ptr); nuclear@9: (*jni)->ReleaseFloatArrayElements(jni, jtex_matrix, ptr, JNI_ABORT); nuclear@9: } nuclear@9: nuclear@8: return 0; nuclear@7: } nuclear@7: nuclear@6: int cam_is_capturing(void) nuclear@6: { nuclear@6: return capturing; // XXX is it better to do this properly through JNI? nuclear@6: } nuclear@6: nuclear@9: int cam_video_size(int *xsz, int *ysz) nuclear@9: { nuclear@9: jfieldID jwidth, jheight; nuclear@9: nuclear@9: if(!(jwidth = (*jni)->GetStaticFieldID(jni, activity_class, "preview_width", "I")) || nuclear@9: !(jheight = (*jni)->GetStaticFieldID(jni, activity_class, "preview_height", "I"))) { nuclear@9: fprintf(stderr, "failed to retrieve preview width/height fields\n"); nuclear@9: *xsz = *ysz = 0; nuclear@9: return -1; nuclear@9: } nuclear@9: nuclear@9: *xsz = (*jni)->GetStaticIntField(jni, activity_class, jwidth); nuclear@9: *ysz = (*jni)->GetStaticIntField(jni, activity_class, jheight); nuclear@9: return 0; nuclear@9: } nuclear@9: nuclear@6: int cam_take_picture(void) nuclear@6: { nuclear@6: return -1; // TODO nuclear@6: }