3dphotoshoot

annotate src/android/camera.c @ 25:ac80210d5fbe

preparing a pc version for easier development of non-android-specifics
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 18 Jun 2015 03:12:30 +0300
parents d1b456d08713
children
rev   line source
nuclear@6 1 #include <stdio.h>
nuclear@9 2 #include <string.h>
nuclear@6 3 #include <assert.h>
nuclear@6 4 #include <jni.h>
nuclear@6 5 #include "opengl.h"
nuclear@6 6 #include "camera.h"
nuclear@25 7 #include "sdr.h"
nuclear@25 8 #include "sanegl.h"
nuclear@6 9
nuclear@6 10
nuclear@6 11 static JavaVM *jvm;
nuclear@6 12 static JNIEnv *jni;
nuclear@6 13 static jclass activity_class;
nuclear@6 14 static unsigned int tex;
nuclear@9 15 static float tex_matrix[16];
nuclear@9 16 static const float identity_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
nuclear@9 17 static jfloatArray jtex_matrix;
nuclear@6 18 static int capturing;
nuclear@6 19
nuclear@25 20 static unsigned int sdr_cam;
nuclear@25 21 static int aloc_vertex, aloc_texcoord;
nuclear@25 22
nuclear@25 23
nuclear@6 24 int cam_init(void *platform_data)
nuclear@6 25 {
nuclear@6 26 int glerr;
nuclear@6 27 struct cam_android_platform_data *pdata = platform_data;
nuclear@6 28
nuclear@6 29 jvm = pdata->vm;
nuclear@6 30 jni = pdata->jni;
nuclear@6 31 activity_class = pdata->activity_class;
nuclear@6 32
nuclear@9 33 jtex_matrix = (*jni)->NewFloatArray(jni, 16);
nuclear@9 34
nuclear@25 35 // load preview shader
nuclear@25 36 if(!(sdr_cam = create_program_load("sdr/vertex.glsl", "sdr/android_cam_preview.p.glsl"))) {
nuclear@25 37 return -1;
nuclear@25 38 }
nuclear@25 39 aloc_vertex = glGetAttribLocation(sdr_cam, "attr_vertex");
nuclear@25 40 aloc_texcoord = glGetAttribLocation(sdr_cam, "attr_texcoord");
nuclear@25 41
nuclear@6 42 // create the camera texture
nuclear@6 43 assert(glGetError() == GL_NO_ERROR);
nuclear@6 44 glGenTextures(1, &tex);
nuclear@6 45 glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
nuclear@6 46 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
nuclear@6 47 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
nuclear@6 48
nuclear@6 49 glerr = glGetError();
nuclear@6 50 assert(glerr == GL_NO_ERROR);
nuclear@6 51 return glerr == GL_NO_ERROR ? 0 : -1;
nuclear@6 52 }
nuclear@6 53
nuclear@6 54 void cam_shutdown(void)
nuclear@6 55 {
nuclear@6 56 cam_stop_video();
nuclear@6 57 glDeleteTextures(1, &tex);
nuclear@6 58 tex = 0;
nuclear@9 59
nuclear@25 60 free_program(sdr_cam);
nuclear@25 61
nuclear@9 62 if(jni) {
nuclear@9 63 (*jni)->DeleteGlobalRef(jni, jtex_matrix);
nuclear@9 64 }
nuclear@6 65 }
nuclear@6 66
nuclear@6 67 unsigned int cam_texture(void)
nuclear@6 68 {
nuclear@6 69 return tex;
nuclear@6 70 }
nuclear@6 71
nuclear@9 72 const float *cam_texture_matrix(void)
nuclear@6 73 {
nuclear@9 74 return tex_matrix;
nuclear@6 75 }
nuclear@6 76
nuclear@6 77 int cam_start_video(void)
nuclear@6 78 {
nuclear@6 79 jmethodID method;
nuclear@6 80
nuclear@6 81 if(!jvm) {
nuclear@6 82 fprintf(stderr, "failed to start video, camera not initialized\n");
nuclear@6 83 return -1;
nuclear@6 84 }
nuclear@6 85 if(cam_is_capturing()) {
nuclear@6 86 return 0;
nuclear@6 87 }
nuclear@6 88
nuclear@6 89 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "start_video", "(I)I"))) {
nuclear@6 90 fprintf(stderr, "failed to find static method: start_video\n");
nuclear@6 91 return -1;
nuclear@6 92 }
nuclear@6 93 if((*jni)->CallStaticIntMethod(jni, activity_class, method, tex) == -1) {
nuclear@6 94 fprintf(stderr, "failed to start video capture\n");
nuclear@6 95 capturing = 0;
nuclear@6 96 return -1;
nuclear@6 97 }
nuclear@6 98 capturing = 1;
nuclear@6 99
nuclear@6 100 printf("video started\n");
nuclear@6 101
nuclear@6 102 return 1;
nuclear@6 103 }
nuclear@6 104
nuclear@6 105 int cam_stop_video(void)
nuclear@6 106 {
nuclear@6 107 jmethodID method;
nuclear@6 108
nuclear@6 109 if(!jvm) {
nuclear@6 110 fprintf(stderr, "failed to stop video, camera not initialized\n");
nuclear@6 111 return -1;
nuclear@6 112 }
nuclear@6 113
nuclear@6 114 if(!cam_is_capturing()) {
nuclear@6 115 return 0;
nuclear@6 116 }
nuclear@6 117
nuclear@6 118 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "stop_video", "()V"))) {
nuclear@6 119 fprintf(stderr, "failed to find static method: stop_video\n");
nuclear@6 120 return -1;
nuclear@6 121 }
nuclear@6 122 (*jni)->CallStaticVoidMethod(jni, activity_class, method);
nuclear@6 123 capturing = 0;
nuclear@6 124
nuclear@6 125 printf("video stopped\n");
nuclear@6 126
nuclear@6 127 return 0;
nuclear@6 128 }
nuclear@6 129
nuclear@8 130 int cam_update(void)
nuclear@7 131 {
nuclear@9 132 static int texmat_fail_warned;
nuclear@7 133 jmethodID method;
nuclear@9 134 float *ptr;
nuclear@7 135
nuclear@7 136 if(!jvm) {
nuclear@7 137 fprintf(stderr, "failed to update camera\n");
nuclear@7 138 return -1;
nuclear@7 139 }
nuclear@7 140 if(!cam_is_capturing()) {
nuclear@7 141 return 0;
nuclear@7 142 }
nuclear@7 143
nuclear@9 144 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "update", "([F)V"))) {
nuclear@7 145 fprintf(stderr, "failed to find static method: update\n");
nuclear@7 146 return -1;
nuclear@7 147 }
nuclear@9 148 (*jni)->CallStaticVoidMethod(jni, activity_class, method, jtex_matrix);
nuclear@9 149
nuclear@9 150 if(!(ptr = (*jni)->GetFloatArrayElements(jni, jtex_matrix, 0))) {
nuclear@9 151 if(!texmat_fail_warned) {
nuclear@9 152 fprintf(stderr, "failed to get texture matrix\n");
nuclear@9 153 texmat_fail_warned = 1;
nuclear@9 154 }
nuclear@9 155 memcpy(tex_matrix, identity_matrix, sizeof identity_matrix);
nuclear@9 156 } else {
nuclear@9 157 memcpy(tex_matrix, ptr, 16 * sizeof *ptr);
nuclear@9 158 (*jni)->ReleaseFloatArrayElements(jni, jtex_matrix, ptr, JNI_ABORT);
nuclear@9 159 }
nuclear@9 160
nuclear@8 161 return 0;
nuclear@7 162 }
nuclear@7 163
nuclear@6 164 int cam_is_capturing(void)
nuclear@6 165 {
nuclear@6 166 return capturing; // XXX is it better to do this properly through JNI?
nuclear@6 167 }
nuclear@6 168
nuclear@9 169 int cam_video_size(int *xsz, int *ysz)
nuclear@9 170 {
nuclear@9 171 jfieldID jwidth, jheight;
nuclear@9 172
nuclear@9 173 if(!(jwidth = (*jni)->GetStaticFieldID(jni, activity_class, "preview_width", "I")) ||
nuclear@9 174 !(jheight = (*jni)->GetStaticFieldID(jni, activity_class, "preview_height", "I"))) {
nuclear@9 175 fprintf(stderr, "failed to retrieve preview width/height fields\n");
nuclear@9 176 *xsz = *ysz = 0;
nuclear@9 177 return -1;
nuclear@9 178 }
nuclear@9 179
nuclear@9 180 *xsz = (*jni)->GetStaticIntField(jni, activity_class, jwidth);
nuclear@9 181 *ysz = (*jni)->GetStaticIntField(jni, activity_class, jheight);
nuclear@9 182 return 0;
nuclear@9 183 }
nuclear@9 184
nuclear@6 185 int cam_take_picture(void)
nuclear@6 186 {
nuclear@6 187 return -1; // TODO
nuclear@6 188 }
nuclear@25 189
nuclear@25 190 void cam_draw_preview(void)
nuclear@25 191 {
nuclear@25 192 const float *tex_matrix = cam_texture_matrix();
nuclear@25 193
nuclear@25 194 gl_matrix_mode(GL_TEXTURE);
nuclear@25 195 gl_load_matrixf(tex_matrix);
nuclear@25 196
nuclear@25 197 glUseProgram(sdr_cam);
nuclear@25 198 glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
nuclear@25 199
nuclear@25 200 gl_begin(GL_QUADS);
nuclear@25 201 gl_texcoord2f(0, 0);
nuclear@25 202 gl_vertex2f(-1, -1);
nuclear@25 203 gl_texcoord2f(1, 0);
nuclear@25 204 gl_vertex2f(1, -1);
nuclear@25 205 gl_texcoord2f(1, 1);
nuclear@25 206 gl_vertex2f(1, 1);
nuclear@25 207 gl_texcoord2f(0, 1);
nuclear@25 208 gl_vertex2f(-1, 1);
nuclear@25 209 gl_end();
nuclear@25 210
nuclear@25 211 gl_matrix_mode(GL_TEXTURE);
nuclear@25 212 gl_load_identity();
nuclear@25 213 }