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 }
|