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@6
|
7
|
nuclear@6
|
8
|
nuclear@6
|
9 static JavaVM *jvm;
|
nuclear@6
|
10 static JNIEnv *jni;
|
nuclear@6
|
11 static jclass activity_class;
|
nuclear@6
|
12 static unsigned int tex;
|
nuclear@9
|
13 static float tex_matrix[16];
|
nuclear@9
|
14 static const float identity_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
nuclear@9
|
15 static jfloatArray jtex_matrix;
|
nuclear@6
|
16 static int capturing;
|
nuclear@6
|
17
|
nuclear@6
|
18 int cam_init(void *platform_data)
|
nuclear@6
|
19 {
|
nuclear@6
|
20 int glerr;
|
nuclear@6
|
21 struct cam_android_platform_data *pdata = platform_data;
|
nuclear@6
|
22
|
nuclear@6
|
23 jvm = pdata->vm;
|
nuclear@6
|
24 jni = pdata->jni;
|
nuclear@6
|
25 activity_class = pdata->activity_class;
|
nuclear@6
|
26
|
nuclear@9
|
27 jtex_matrix = (*jni)->NewFloatArray(jni, 16);
|
nuclear@9
|
28
|
nuclear@6
|
29 // create the camera texture
|
nuclear@6
|
30 assert(glGetError() == GL_NO_ERROR);
|
nuclear@6
|
31 glGenTextures(1, &tex);
|
nuclear@6
|
32 glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
|
nuclear@6
|
33 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
nuclear@6
|
34 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
nuclear@6
|
35
|
nuclear@6
|
36 glerr = glGetError();
|
nuclear@6
|
37 assert(glerr == GL_NO_ERROR);
|
nuclear@6
|
38 return glerr == GL_NO_ERROR ? 0 : -1;
|
nuclear@6
|
39 }
|
nuclear@6
|
40
|
nuclear@6
|
41 void cam_shutdown(void)
|
nuclear@6
|
42 {
|
nuclear@6
|
43 cam_stop_video();
|
nuclear@6
|
44 glDeleteTextures(1, &tex);
|
nuclear@6
|
45 tex = 0;
|
nuclear@9
|
46
|
nuclear@9
|
47 if(jni) {
|
nuclear@9
|
48 (*jni)->DeleteGlobalRef(jni, jtex_matrix);
|
nuclear@9
|
49 }
|
nuclear@6
|
50 }
|
nuclear@6
|
51
|
nuclear@6
|
52 unsigned int cam_texture(void)
|
nuclear@6
|
53 {
|
nuclear@6
|
54 return tex;
|
nuclear@6
|
55 }
|
nuclear@6
|
56
|
nuclear@9
|
57 const float *cam_texture_matrix(void)
|
nuclear@6
|
58 {
|
nuclear@9
|
59 return tex_matrix;
|
nuclear@6
|
60 }
|
nuclear@6
|
61
|
nuclear@6
|
62 int cam_start_video(void)
|
nuclear@6
|
63 {
|
nuclear@6
|
64 jmethodID method;
|
nuclear@6
|
65
|
nuclear@6
|
66 if(!jvm) {
|
nuclear@6
|
67 fprintf(stderr, "failed to start video, camera not initialized\n");
|
nuclear@6
|
68 return -1;
|
nuclear@6
|
69 }
|
nuclear@6
|
70 if(cam_is_capturing()) {
|
nuclear@6
|
71 return 0;
|
nuclear@6
|
72 }
|
nuclear@6
|
73
|
nuclear@6
|
74 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "start_video", "(I)I"))) {
|
nuclear@6
|
75 fprintf(stderr, "failed to find static method: start_video\n");
|
nuclear@6
|
76 return -1;
|
nuclear@6
|
77 }
|
nuclear@6
|
78 if((*jni)->CallStaticIntMethod(jni, activity_class, method, tex) == -1) {
|
nuclear@6
|
79 fprintf(stderr, "failed to start video capture\n");
|
nuclear@6
|
80 capturing = 0;
|
nuclear@6
|
81 return -1;
|
nuclear@6
|
82 }
|
nuclear@6
|
83 capturing = 1;
|
nuclear@6
|
84
|
nuclear@6
|
85 printf("video started\n");
|
nuclear@6
|
86
|
nuclear@6
|
87 return 1;
|
nuclear@6
|
88 }
|
nuclear@6
|
89
|
nuclear@6
|
90 int cam_stop_video(void)
|
nuclear@6
|
91 {
|
nuclear@6
|
92 jmethodID method;
|
nuclear@6
|
93
|
nuclear@6
|
94 if(!jvm) {
|
nuclear@6
|
95 fprintf(stderr, "failed to stop video, camera not initialized\n");
|
nuclear@6
|
96 return -1;
|
nuclear@6
|
97 }
|
nuclear@6
|
98
|
nuclear@6
|
99 if(!cam_is_capturing()) {
|
nuclear@6
|
100 return 0;
|
nuclear@6
|
101 }
|
nuclear@6
|
102
|
nuclear@6
|
103 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "stop_video", "()V"))) {
|
nuclear@6
|
104 fprintf(stderr, "failed to find static method: stop_video\n");
|
nuclear@6
|
105 return -1;
|
nuclear@6
|
106 }
|
nuclear@6
|
107 (*jni)->CallStaticVoidMethod(jni, activity_class, method);
|
nuclear@6
|
108 capturing = 0;
|
nuclear@6
|
109
|
nuclear@6
|
110 printf("video stopped\n");
|
nuclear@6
|
111
|
nuclear@6
|
112 return 0;
|
nuclear@6
|
113 }
|
nuclear@6
|
114
|
nuclear@8
|
115 int cam_update(void)
|
nuclear@7
|
116 {
|
nuclear@9
|
117 static int texmat_fail_warned;
|
nuclear@7
|
118 jmethodID method;
|
nuclear@9
|
119 float *ptr;
|
nuclear@7
|
120
|
nuclear@7
|
121 if(!jvm) {
|
nuclear@7
|
122 fprintf(stderr, "failed to update camera\n");
|
nuclear@7
|
123 return -1;
|
nuclear@7
|
124 }
|
nuclear@7
|
125 if(!cam_is_capturing()) {
|
nuclear@7
|
126 return 0;
|
nuclear@7
|
127 }
|
nuclear@7
|
128
|
nuclear@9
|
129 if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "update", "([F)V"))) {
|
nuclear@7
|
130 fprintf(stderr, "failed to find static method: update\n");
|
nuclear@7
|
131 return -1;
|
nuclear@7
|
132 }
|
nuclear@9
|
133 (*jni)->CallStaticVoidMethod(jni, activity_class, method, jtex_matrix);
|
nuclear@9
|
134
|
nuclear@9
|
135 if(!(ptr = (*jni)->GetFloatArrayElements(jni, jtex_matrix, 0))) {
|
nuclear@9
|
136 if(!texmat_fail_warned) {
|
nuclear@9
|
137 fprintf(stderr, "failed to get texture matrix\n");
|
nuclear@9
|
138 texmat_fail_warned = 1;
|
nuclear@9
|
139 }
|
nuclear@9
|
140 memcpy(tex_matrix, identity_matrix, sizeof identity_matrix);
|
nuclear@9
|
141 } else {
|
nuclear@9
|
142 memcpy(tex_matrix, ptr, 16 * sizeof *ptr);
|
nuclear@9
|
143 (*jni)->ReleaseFloatArrayElements(jni, jtex_matrix, ptr, JNI_ABORT);
|
nuclear@9
|
144 }
|
nuclear@9
|
145
|
nuclear@8
|
146 return 0;
|
nuclear@7
|
147 }
|
nuclear@7
|
148
|
nuclear@6
|
149 int cam_is_capturing(void)
|
nuclear@6
|
150 {
|
nuclear@6
|
151 return capturing; // XXX is it better to do this properly through JNI?
|
nuclear@6
|
152 }
|
nuclear@6
|
153
|
nuclear@9
|
154 int cam_video_size(int *xsz, int *ysz)
|
nuclear@9
|
155 {
|
nuclear@9
|
156 jfieldID jwidth, jheight;
|
nuclear@9
|
157
|
nuclear@9
|
158 if(!(jwidth = (*jni)->GetStaticFieldID(jni, activity_class, "preview_width", "I")) ||
|
nuclear@9
|
159 !(jheight = (*jni)->GetStaticFieldID(jni, activity_class, "preview_height", "I"))) {
|
nuclear@9
|
160 fprintf(stderr, "failed to retrieve preview width/height fields\n");
|
nuclear@9
|
161 *xsz = *ysz = 0;
|
nuclear@9
|
162 return -1;
|
nuclear@9
|
163 }
|
nuclear@9
|
164
|
nuclear@9
|
165 *xsz = (*jni)->GetStaticIntField(jni, activity_class, jwidth);
|
nuclear@9
|
166 *ysz = (*jni)->GetStaticIntField(jni, activity_class, jheight);
|
nuclear@9
|
167 return 0;
|
nuclear@9
|
168 }
|
nuclear@9
|
169
|
nuclear@6
|
170 int cam_take_picture(void)
|
nuclear@6
|
171 {
|
nuclear@6
|
172 return -1; // TODO
|
nuclear@6
|
173 }
|