Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / tests / test_camera.c
1 /*
2 * Copyright (C) 2012 Canonical Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <hybris/camera/camera_compatibility_layer.h>
19 #include <hybris/camera/camera_compatibility_layer_capabilities.h>
20
21 #include <hybris/input/input_stack_compatibility_layer.h>
22 #include <hybris/input/input_stack_compatibility_layer_codes_key.h>
23 #include <hybris/input/input_stack_compatibility_layer_flags_key.h>
24 #include <hybris/input/input_stack_compatibility_layer_flags_motion.h>
25
26 #include <EGL/egl.h>
27 #include <GLES2/gl2.h>
28 #include <GLES2/gl2ext.h>
29
30 #include <assert.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39
40 int shot_counter = 1;
41 int32_t current_zoom_level = 1;
42 bool new_camera_frame_available = true;
43
44 static GLuint gProgram;
45 static GLuint gaPositionHandle, gaTexHandle, gsTextureHandle, gmTexMatrix;
46
47 EffectMode next_effect()
48 {
49 static EffectMode current_effect = EFFECT_MODE_NONE;
50
51 EffectMode next = current_effect;
52
53 switch (current_effect) {
54 case EFFECT_MODE_NONE:
55 next = EFFECT_MODE_MONO;
56 break;
57 case EFFECT_MODE_MONO:
58 next = EFFECT_MODE_NEGATIVE;
59 break;
60 case EFFECT_MODE_NEGATIVE:
61 next = EFFECT_MODE_SOLARIZE;
62 break;
63 case EFFECT_MODE_SOLARIZE:
64 next = EFFECT_MODE_SEPIA;
65 break;
66 case EFFECT_MODE_SEPIA:
67 next = EFFECT_MODE_POSTERIZE;
68 break;
69 case EFFECT_MODE_POSTERIZE:
70 next = EFFECT_MODE_WHITEBOARD;
71 break;
72 case EFFECT_MODE_WHITEBOARD:
73 next = EFFECT_MODE_BLACKBOARD;
74 break;
75 case EFFECT_MODE_BLACKBOARD:
76 next = EFFECT_MODE_AQUA;
77 break;
78 case EFFECT_MODE_AQUA:
79 next = EFFECT_MODE_NONE;
80 break;
81 }
82
83 current_effect = next;
84 return next;
85 }
86
87 void error_msg_cb(void* context)
88 {
89 printf("%s \n", __PRETTY_FUNCTION__);
90 }
91
92 void shutter_msg_cb(void* context)
93 {
94 printf("%s \n", __PRETTY_FUNCTION__);
95 }
96
97 void zoom_msg_cb(void* context, int32_t new_zoom_level)
98 {
99 printf("%s \n", __PRETTY_FUNCTION__);
100
101 struct CameraControl* cc = (struct CameraControl*) context;
102 static int zoom;
103 current_zoom_level = new_zoom_level;
104 }
105
106 void autofocus_msg_cb(void* context)
107 {
108 printf("%s \n", __PRETTY_FUNCTION__);
109 }
110
111 void raw_data_cb(void* data, uint32_t data_size, void* context)
112 {
113 printf("%s: %d \n", __PRETTY_FUNCTION__, data_size);
114 }
115
116 void jpeg_data_cb(void* data, uint32_t data_size, void* context)
117 {
118 printf("%s: %d \n", __PRETTY_FUNCTION__, data_size);
119
120 char fn[256];
121 sprintf(fn, "/tmp/shot_%d.jpeg", shot_counter);
122 int fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
123 ssize_t ret = write(fd, data, data_size);
124 close(fd);
125 shot_counter++;
126
127 struct CameraControl* cc = (struct CameraControl*) context;
128 android_camera_start_preview(cc);
129 }
130
131 void size_cb(void* ctx, int width, int height)
132 {
133 printf("Supported size: [%d,%d]\n", width, height);
134 }
135
136 void preview_texture_needs_update_cb(void* ctx)
137 {
138 new_camera_frame_available = true;
139 }
140
141 void on_new_input_event(struct Event* event, void* context)
142 {
143 assert(context);
144
145 if (event->type == KEY_EVENT_TYPE && event->action == ISCL_KEY_EVENT_ACTION_UP) {
146 printf("We have got a key event: %d \n", event->details.key.key_code);
147
148 struct CameraControl* cc = (struct CameraControl*) context;
149
150 switch(event->details.key.key_code) {
151 case ISCL_KEYCODE_VOLUME_UP:
152 printf("\tZooming in now.\n");
153 android_camera_start_zoom(cc, current_zoom_level+1);
154 break;
155 case ISCL_KEYCODE_VOLUME_DOWN:
156 printf("\tZooming out now.\n");
157 android_camera_start_zoom(cc, current_zoom_level-1);
158 break;
159 case ISCL_KEYCODE_POWER:
160 printf("\tTaking a photo now.\n");
161 android_camera_take_snapshot(cc);
162 break;
163 case ISCL_KEYCODE_HEADSETHOOK:
164 printf("\tSwitching effect.\n");
165 android_camera_set_effect_mode(cc, next_effect());
166
167 }
168 } else if (event->type == MOTION_EVENT_TYPE &&
169 event->details.motion.pointer_count == 1) {
170 if ((event->action & ISCL_MOTION_EVENT_ACTION_MASK) == ISCL_MOTION_EVENT_ACTION_UP) {
171 printf("\tMotion event(Action up): (%f, %f) \n",
172 event->details.motion.pointer_coordinates[0].x,
173 event->details.motion.pointer_coordinates[0].y);
174 }
175
176 if ((event->action & ISCL_MOTION_EVENT_ACTION_MASK) == ISCL_MOTION_EVENT_ACTION_DOWN) {
177 printf("\tMotion event(Action down): (%f, %f) \n",
178 event->details.motion.pointer_coordinates[0].x,
179 event->details.motion.pointer_coordinates[0].y);
180 }
181 }
182 }
183
184 static const char* vertex_shader()
185 {
186 return
187 "#extension GL_OES_EGL_image_external : require \n"
188 "attribute vec4 a_position; \n"
189 "attribute vec2 a_texCoord; \n"
190 "uniform mat4 m_texMatrix; \n"
191 "varying vec2 v_texCoord; \n"
192 "varying float topDown; \n"
193 "void main() \n"
194 "{ \n"
195 " gl_Position = a_position; \n"
196 " v_texCoord = a_texCoord; \n"
197 // " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n"
198 // " topDown = v_texCoord.y; \n"
199 "} \n";
200 }
201
202 static const char* fragment_shader()
203 {
204 return
205 "#extension GL_OES_EGL_image_external : require \n"
206 "precision mediump float; \n"
207 "varying vec2 v_texCoord; \n"
208 "uniform samplerExternalOES s_texture; \n"
209 "void main() \n"
210 "{ \n"
211 " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
212 "} \n";
213 }
214
215 static GLuint loadShader(GLenum shaderType, const char* pSource) {
216 GLuint shader = glCreateShader(shaderType);
217
218 if (shader) {
219 glShaderSource(shader, 1, &pSource, NULL);
220 glCompileShader(shader);
221 GLint compiled = 0;
222 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
223
224 if (!compiled) {
225 GLint infoLen = 0;
226 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
227 if (infoLen) {
228 char* buf = (char*) malloc(infoLen);
229 if (buf) {
230 glGetShaderInfoLog(shader, infoLen, NULL, buf);
231 fprintf(stderr, "Could not compile shader %d:\n%s\n",
232 shaderType, buf);
233 free(buf);
234 }
235 glDeleteShader(shader);
236 shader = 0;
237 }
238 }
239 } else {
240 printf("Error, during shader creation: %i\n", glGetError());
241 }
242
243 return shader;
244 }
245
246 static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) {
247 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
248 if (!vertexShader) {
249 printf("vertex shader not compiled\n");
250 return 0;
251 }
252
253 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
254 if (!pixelShader) {
255 printf("frag shader not compiled\n");
256 return 0;
257 }
258
259 GLuint program = glCreateProgram();
260 if (program) {
261 glAttachShader(program, vertexShader);
262 glAttachShader(program, pixelShader);
263 glLinkProgram(program);
264 GLint linkStatus = GL_FALSE;
265 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
266
267 if (linkStatus != GL_TRUE) {
268 GLint bufLength = 0;
269 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
270 if (bufLength) {
271 char* buf = (char*) malloc(bufLength);
272 if (buf) {
273 glGetProgramInfoLog(program, bufLength, NULL, buf);
274 fprintf(stderr, "Could not link program:\n%s\n", buf);
275 free(buf);
276 }
277 }
278 glDeleteProgram(program);
279 program = 0;
280 }
281
282 }
283 return program;
284 }
285
286 int main(int argc, char** argv)
287 {
288 struct CameraControlListener listener;
289 memset(&listener, 0, sizeof(listener));
290 listener.on_msg_error_cb = error_msg_cb;
291 listener.on_msg_shutter_cb = shutter_msg_cb;
292 listener.on_msg_focus_cb = autofocus_msg_cb;
293 listener.on_msg_zoom_cb = zoom_msg_cb;
294
295 listener.on_data_raw_image_cb = raw_data_cb;
296 listener.on_data_compressed_image_cb = jpeg_data_cb;
297 listener.on_preview_texture_needs_update_cb = preview_texture_needs_update_cb;
298 struct CameraControl* cc = android_camera_connect_to(FRONT_FACING_CAMERA_TYPE,
299 &listener);
300 if (cc == NULL) {
301 printf("Problem connecting to camera");
302 return 1;
303 }
304
305 listener.context = cc;
306
307 struct AndroidEventListener event_listener;
308 event_listener.on_new_event = on_new_input_event;
309 event_listener.context = cc;
310
311 struct InputStackConfiguration input_configuration = { false, 25000, 1024, 1024 };
312
313 android_input_stack_initialize(&event_listener, &input_configuration);
314 android_input_stack_start();
315
316 android_camera_dump_parameters(cc);
317 android_camera_enumerate_supported_picture_sizes(cc, size_cb, NULL);
318 android_camera_enumerate_supported_preview_sizes(cc, size_cb, NULL);
319
320 int min_fps, max_fps, current_fps;
321 android_camera_get_preview_fps_range(cc, &min_fps, &max_fps);
322 printf("Preview fps range: [%d,%d]\n", min_fps, max_fps);
323 android_camera_get_preview_fps(cc, &current_fps);
324 printf("Current preview fps range: %d\n", current_fps);
325
326 android_camera_set_preview_size(cc, 960, 720);
327
328 int width, height;
329 android_camera_get_preview_size(cc, &width, &height);
330 printf("Current preview size: [%d,%d]\n", width, height);
331 android_camera_get_picture_size(cc, &width, &height);
332 printf("Current picture size: [%d,%d]\n", width, height);
333 int zoom;
334 android_camera_get_max_zoom(cc, &zoom);
335 printf("Max zoom: %d \n", zoom);
336 android_camera_set_zoom(cc, 10);
337
338 EffectMode effect_mode;
339 FlashMode flash_mode;
340 WhiteBalanceMode wb_mode;
341 SceneMode scene_mode;
342 AutoFocusMode af_mode;
343 android_camera_get_effect_mode(cc, &effect_mode);
344 android_camera_get_flash_mode(cc, &flash_mode);
345 android_camera_get_white_balance_mode(cc, &wb_mode);
346 android_camera_get_scene_mode(cc, &scene_mode);
347 android_camera_get_auto_focus_mode(cc, &af_mode);
348 printf("Current effect mode: %d \n", effect_mode);
349 printf("Current flash mode: %d \n", flash_mode);
350 printf("Current wb mode: %d \n", wb_mode);
351 printf("Current scene mode: %d \n", scene_mode);
352 printf("Current af mode: %d \n", af_mode);
353 FocusRegion fr = { top: -200, left: -200, bottom: 200, right: 200, weight: 300};
354 android_camera_set_focus_region(cc, &fr);
355
356 /* EGL Setup */
357 EGLConfig ecfg;
358 EGLBoolean rv;
359 EGLint num_config;
360 EGLContext context;
361 EGLint attr[] = {
362 EGL_BUFFER_SIZE, 32,
363 EGL_RENDERABLE_TYPE,
364 EGL_OPENGL_ES2_BIT,
365 EGL_NONE
366 };
367 EGLint ctxattr[] = {
368 EGL_CONTEXT_CLIENT_VERSION, 2,
369 EGL_NONE
370 };
371
372 EGLDisplay disp = eglGetDisplay(NULL);
373 assert(eglGetError() == EGL_SUCCESS);
374 assert(disp != EGL_NO_DISPLAY);
375
376 rv = eglInitialize(disp, 0, 0);
377 assert(eglGetError() == EGL_SUCCESS);
378 assert(rv == EGL_TRUE);
379
380 eglChooseConfig((EGLDisplay) disp, attr, &ecfg, 1, &num_config);
381 assert(eglGetError() == EGL_SUCCESS);
382 assert(rv == EGL_TRUE);
383
384 EGLSurface surface = eglCreateWindowSurface((EGLDisplay) disp, ecfg,
385 (EGLNativeWindowType) NULL, NULL);
386 assert(eglGetError() == EGL_SUCCESS);
387 assert(surface != EGL_NO_SURFACE);
388
389 context = eglCreateContext((EGLDisplay) disp, ecfg, EGL_NO_CONTEXT, ctxattr);
390 assert(eglGetError() == EGL_SUCCESS);
391 assert(context != EGL_NO_CONTEXT);
392
393 assert(eglMakeCurrent((EGLDisplay) disp, surface, surface, context) == EGL_TRUE);
394
395 gProgram = create_program(vertex_shader(), fragment_shader());
396 gaPositionHandle = glGetAttribLocation(gProgram, "a_position");
397 gaTexHandle = glGetAttribLocation(gProgram, "a_texCoord");
398 gsTextureHandle = glGetUniformLocation(gProgram, "s_texture");
399 gmTexMatrix = glGetUniformLocation(gProgram, "m_texMatrix");
400
401 GLuint preview_texture_id;
402 glGenTextures(1, &preview_texture_id);
403 glClearColor(1.0, 0., 0.5, 1.);
404 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
405 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
406 glTexParameteri(
407 GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
408 glTexParameteri(
409 GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
410 android_camera_set_preview_texture(cc, preview_texture_id);
411 android_camera_set_effect_mode(cc, EFFECT_MODE_SEPIA);
412 android_camera_set_flash_mode(cc, FLASH_MODE_AUTO);
413 android_camera_set_auto_focus_mode(cc, AUTO_FOCUS_MODE_CONTINUOUS_PICTURE);
414 android_camera_start_preview(cc);
415
416 GLfloat transformation_matrix[16];
417 android_camera_get_preview_texture_transformation(cc, transformation_matrix);
418 glUniformMatrix4fv(gmTexMatrix, 1, GL_FALSE, transformation_matrix);
419
420 printf("Started camera preview.\n");
421
422 while(true) {
423 /*if (new_camera_frame_available)
424 {
425 printf("Updating texture");
426 new_camera_frame_available = false;
427 }*/
428 static GLfloat vVertices[] = { 0.0f, 0.0f, 0.0f, // Position 0
429 0.0f, 0.0f, // TexCoord 0
430 0.0f, 1.0f, 0.0f, // Position 1
431 0.0f, 1.0f, // TexCoord 1
432 1.0f, 1.0f, 0.0f, // Position 2
433 1.0f, 1.0f, // TexCoord 2
434 1.0f, 0.0f, 0.0f, // Position 3
435 1.0f, 0.0f // TexCoord 3
436 };
437
438 GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
439
440 // Set the viewport
441 // Clear the color buffer
442 glClear(GL_COLOR_BUFFER_BIT);
443 // Use the program object
444 glUseProgram(gProgram);
445 // Enable attributes
446 glEnableVertexAttribArray(gaPositionHandle);
447 glEnableVertexAttribArray(gaTexHandle);
448 // Load the vertex position
449 glVertexAttribPointer(gaPositionHandle,
450 3,
451 GL_FLOAT,
452 GL_FALSE,
453 5 * sizeof(GLfloat),
454 vVertices);
455 // Load the texture coordinate
456 glVertexAttribPointer(gaTexHandle,
457 2,
458 GL_FLOAT,
459 GL_FALSE,
460 5 * sizeof(GLfloat),
461 vVertices+3);
462
463 glActiveTexture(GL_TEXTURE0);
464 // Set the sampler texture unit to 0
465 glUniform1i(gsTextureHandle, 0);
466 glUniform1i(gmTexMatrix, 0);
467 android_camera_update_preview_texture(cc);
468 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
469 glDisableVertexAttribArray(gaPositionHandle);
470 glDisableVertexAttribArray(gaTexHandle);
471
472 eglSwapBuffers((EGLDisplay) disp, surface);
473 }
474 }