# HG changeset patch # User John Tsiombikas # Date 1432520846 -10800 # Node ID d1b456d087131e05bbcf6fabc424ed4e486aa786 # Parent 9fc7d52f578d8a27fe84fbfc77c9b8dbd87e12e2 texture matrix and video size from JNI diff -r 9fc7d52f578d -r d1b456d08713 android/manifest.xml.in --- a/android/manifest.xml.in Mon May 25 04:14:38 2015 +0300 +++ b/android/manifest.xml.in Mon May 25 05:27:26 2015 +0300 @@ -10,7 +10,7 @@ - + diff -r 9fc7d52f578d -r d1b456d08713 src/android/MainActivity.java --- a/src/android/MainActivity.java Mon May 25 04:14:38 2015 +0300 +++ b/src/android/MainActivity.java Mon May 25 05:27:26 2015 +0300 @@ -24,6 +24,8 @@ // old camera api (fallback) private static Camera cam; + private static Camera.Parameters params; + private static int preview_width, preview_height; private static SurfaceTexture surftex; public static int start_video(int texid) @@ -49,10 +51,13 @@ cam = Camera.open(0); - Camera.Parameters params = cam.getParameters(); + params = cam.getParameters(); params.set("orientation", "landscape"); cam.setParameters(params); + preview_width = params.getPreviewSize().width; + preview_height = params.getPreviewSize().height; + try { cam.setPreviewTexture(surftex); } @@ -70,14 +75,18 @@ { cam.stopPreview(); cam = null; + params = null; surftex = null; } - public static synchronized void update() + public static synchronized void update(float [] matrix) { - if(cam != null && surftex != null && frame_pending) { - surftex.updateTexImage(); - frame_pending = false; + if(cam != null && surftex != null) { + if(frame_pending) { + surftex.updateTexImage(); + frame_pending = false; + } + surftex.getTransformMatrix(matrix); } } } diff -r 9fc7d52f578d -r d1b456d08713 src/android/camera.c --- a/src/android/camera.c Mon May 25 04:14:38 2015 +0300 +++ b/src/android/camera.c Mon May 25 05:27:26 2015 +0300 @@ -1,4 +1,5 @@ #include +#include #include #include #include "opengl.h" @@ -9,6 +10,9 @@ static JNIEnv *jni; static jclass activity_class; static unsigned int tex; +static float tex_matrix[16]; +static const float identity_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; +static jfloatArray jtex_matrix; static int capturing; int cam_init(void *platform_data) @@ -20,6 +24,8 @@ jni = pdata->jni; activity_class = pdata->activity_class; + jtex_matrix = (*jni)->NewFloatArray(jni, 16); + // create the camera texture assert(glGetError() == GL_NO_ERROR); glGenTextures(1, &tex); @@ -37,6 +43,10 @@ cam_stop_video(); glDeleteTextures(1, &tex); tex = 0; + + if(jni) { + (*jni)->DeleteGlobalRef(jni, jtex_matrix); + } } unsigned int cam_texture(void) @@ -44,9 +54,9 @@ return tex; } -void cam_texture_size(int *w, int *h) +const float *cam_texture_matrix(void) { - /* TODO */ + return tex_matrix; } int cam_start_video(void) @@ -104,7 +114,9 @@ int cam_update(void) { + static int texmat_fail_warned; jmethodID method; + float *ptr; if(!jvm) { fprintf(stderr, "failed to update camera\n"); @@ -114,11 +126,23 @@ return 0; } - if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "update", "()V"))) { + if(!(method = (*jni)->GetStaticMethodID(jni, activity_class, "update", "([F)V"))) { fprintf(stderr, "failed to find static method: update\n"); return -1; } - (*jni)->CallStaticVoidMethod(jni, activity_class, method); + (*jni)->CallStaticVoidMethod(jni, activity_class, method, jtex_matrix); + + if(!(ptr = (*jni)->GetFloatArrayElements(jni, jtex_matrix, 0))) { + if(!texmat_fail_warned) { + fprintf(stderr, "failed to get texture matrix\n"); + texmat_fail_warned = 1; + } + memcpy(tex_matrix, identity_matrix, sizeof identity_matrix); + } else { + memcpy(tex_matrix, ptr, 16 * sizeof *ptr); + (*jni)->ReleaseFloatArrayElements(jni, jtex_matrix, ptr, JNI_ABORT); + } + return 0; } @@ -127,6 +151,22 @@ return capturing; // XXX is it better to do this properly through JNI? } +int cam_video_size(int *xsz, int *ysz) +{ + jfieldID jwidth, jheight; + + if(!(jwidth = (*jni)->GetStaticFieldID(jni, activity_class, "preview_width", "I")) || + !(jheight = (*jni)->GetStaticFieldID(jni, activity_class, "preview_height", "I"))) { + fprintf(stderr, "failed to retrieve preview width/height fields\n"); + *xsz = *ysz = 0; + return -1; + } + + *xsz = (*jni)->GetStaticIntField(jni, activity_class, jwidth); + *ysz = (*jni)->GetStaticIntField(jni, activity_class, jheight); + return 0; +} + int cam_take_picture(void) { return -1; // TODO diff -r 9fc7d52f578d -r d1b456d08713 src/camera.h --- a/src/camera.h Mon May 25 04:14:38 2015 +0300 +++ b/src/camera.h Mon May 25 05:27:26 2015 +0300 @@ -15,13 +15,15 @@ void cam_shutdown(void); unsigned int cam_texture(void); -void cam_texture_size(int *w, int *h); +const float *cam_texture_matrix(void); int cam_start_video(void); int cam_stop_video(void); int cam_update(void); int cam_is_capturing(void); +int cam_video_size(int *xsz, int *ysz); + int cam_take_picture(void); #endif /* CAMERA_H_ */ diff -r 9fc7d52f578d -r d1b456d08713 src/game.c --- a/src/game.c Mon May 25 04:14:38 2015 +0300 +++ b/src/game.c Mon May 25 05:27:26 2015 +0300 @@ -8,6 +8,9 @@ static void draw_quad(float hsz, float vsz); static int win_width, win_height; +static float win_aspect; +static int video_width, video_height; +static float video_aspect; int game_init(void) @@ -19,6 +22,14 @@ glClearColor(0.4, 0.4, 0.4, 1); cam_start_video(); + cam_video_size(&video_width, &video_height); + if(video_height) { + video_aspect = (float)video_width / (float)video_height; + } else { + video_aspect = 1.0; + } + + printf("started video %dx%d (aspect: %g)\n", video_width, video_height, video_aspect); return 0; } @@ -29,8 +40,13 @@ void game_display(unsigned long msec) { - unsigned int tex = cam_texture(); + unsigned int tex; + const float *tex_matrix; + float xscale, yscale; + cam_update(); + tex = cam_texture(); + tex_matrix = cam_texture_matrix(); //float tsec = (float)msec / 1000.0f; @@ -43,19 +59,34 @@ if(tex) { glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); glEnable(GL_TEXTURE_EXTERNAL_OES); + + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(tex_matrix); + glMatrixMode(GL_MODELVIEW); } - draw_quad(0.5 * 1.33333, 0.5); + if(video_aspect > win_aspect) { + xscale = 1.0; + yscale = 1.0 / video_aspect; + } else { + xscale = video_aspect; + yscale = 1.0; + } + draw_quad(xscale, yscale); if(tex) { glDisable(GL_TEXTURE_EXTERNAL_OES); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } } static void draw_quad(float hsz, float vsz) { static const float varr[] = {-1, -1, 1, -1, 1, 1, -1, 1}; - static const float tcarr[] = {0, 1, 1, 1, 1, 0, 0, 0}; + static const float tcarr[] = {0, 0, 1, 0, 1, 1, 0, 1}; static const float colarr[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; glPushMatrix(); @@ -82,6 +113,7 @@ { win_width = x; win_height = y; + win_aspect = y ? (float)x / (float)y : 1.0; glViewport(0, 0, x, y); glMatrixMode(GL_PROJECTION);