Last active
October 9, 2017 19:09
-
-
Save tmm1/b64245184b24fd57e9a9a3e3ab0a6a28 to your computer and use it in GitHub Desktop.
mpv --vo=opengl --opengl-backend=android --wid=(int64_t)(intptr_t)(android.view.Surface *)surface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c | |
index 72311e11fa..dab32d122a 100644 | |
--- a/video/out/opengl/context.c | |
+++ b/video/out/opengl/context.c | |
@@ -46,10 +46,14 @@ extern const struct mpgl_driver mpgl_driver_angle; | |
extern const struct mpgl_driver mpgl_driver_angle_es2; | |
extern const struct mpgl_driver mpgl_driver_dxinterop; | |
extern const struct mpgl_driver mpgl_driver_rpi; | |
+extern const struct mpgl_driver mpgl_driver_android; | |
extern const struct mpgl_driver mpgl_driver_mali; | |
extern const struct mpgl_driver mpgl_driver_vdpauglx; | |
static const struct mpgl_driver *const backends[] = { | |
+#if HAVE_ANDROID | |
+ &mpgl_driver_android, | |
+#endif | |
#if HAVE_RPI | |
&mpgl_driver_rpi, | |
#endif | |
diff --git a/video/out/opengl/context_android.c b/video/out/opengl/context_android.c | |
new file mode 100644 | |
index 0000000000..6a53461ec2 | |
--- /dev/null | |
+++ b/video/out/opengl/context_android.c | |
@@ -0,0 +1,148 @@ | |
+/* | |
+ * This file is part of mpv. | |
+ * | |
+ * mpv is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Lesser General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2.1 of the License, or (at your option) any later version. | |
+ * | |
+ * mpv is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ * GNU Lesser General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Lesser General Public | |
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. | |
+ */ | |
+ | |
+#include <EGL/egl.h> | |
+#include <EGL/eglext.h> | |
+#include <libavcodec/jni.h> | |
+#include <android/native_window_jni.h> | |
+ | |
+#include "egl_helpers.h" | |
+ | |
+#include "common/common.h" | |
+#include "options/m_config.h" | |
+#include "context.h" | |
+ | |
+struct priv { | |
+ struct mp_log *log; | |
+ struct GL *gl; | |
+ EGLDisplay egl_display; | |
+ EGLConfig egl_config; | |
+ EGLContext egl_context; | |
+ EGLSurface egl_surface; | |
+ ANativeWindow *native_window; | |
+ int w, h; | |
+}; | |
+ | |
+static void android_uninit(struct MPGLContext *ctx) | |
+{ | |
+ struct priv *p = ctx->priv; | |
+ | |
+ if (p->egl_surface) { | |
+ eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, | |
+ EGL_NO_CONTEXT); | |
+ eglDestroySurface(p->egl_display, p->egl_surface); | |
+ } | |
+ if (p->egl_context) | |
+ eglDestroyContext(p->egl_display, p->egl_context); | |
+ | |
+ if (p->native_window) { | |
+ ANativeWindow_release(p->native_window); | |
+ p->native_window = NULL; | |
+ } | |
+} | |
+ | |
+static int android_init(struct MPGLContext *ctx, int flags) | |
+{ | |
+ struct priv *p = ctx->priv; | |
+ p->log = ctx->vo->log; | |
+ | |
+ jobject surface = (jobject)(intptr_t)ctx->vo->opts->WinID; | |
+ JavaVM *vm = (JavaVM *)av_jni_get_java_vm(NULL); | |
+ JNIEnv *env; | |
+ int ret = (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6); | |
+ if (ret == JNI_EDETACHED) { | |
+ if ((*vm)->AttachCurrentThread(vm, &env, NULL) != 0) { | |
+ MP_FATAL(p, "Could not attach java VM.\n"); | |
+ goto fail; | |
+ } | |
+ } | |
+ p->native_window = ANativeWindow_fromSurface(env, surface); | |
+ (*vm)->DetachCurrentThread(vm); | |
+ | |
+ p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
+ if (!eglInitialize(p->egl_display, NULL, NULL)) { | |
+ MP_FATAL(p, "EGL failed to initialize.\n"); | |
+ goto fail; | |
+ } | |
+ | |
+ EGLConfig config; | |
+ if (!mpegl_create_context(p->egl_display, p->log, flags, &p->egl_context, | |
+ &config)) | |
+ goto fail; | |
+ | |
+ EGLint format; | |
+ eglGetConfigAttrib(p->egl_display, config, EGL_NATIVE_VISUAL_ID, &format); | |
+ ANativeWindow_setBuffersGeometry(p->native_window, 0, 0, format); | |
+ | |
+ p->egl_surface = eglCreateWindowSurface(p->egl_display, config, | |
+ (EGLNativeWindowType)p->native_window, NULL); | |
+ | |
+ if (p->egl_surface == EGL_NO_SURFACE) { | |
+ MP_FATAL(p, "Could not create EGL surface!\n"); | |
+ goto fail; | |
+ } | |
+ | |
+ if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, | |
+ p->egl_context)) { | |
+ MP_FATAL(p, "Failed to set context!\n"); | |
+ goto fail; | |
+ } | |
+ | |
+ if (!eglQuerySurface(p->egl_display, p->egl_surface, EGL_WIDTH, &p->w) || | |
+ !eglQuerySurface(p->egl_display, p->egl_surface, EGL_HEIGHT, &p->h)) { | |
+ MP_FATAL(p, "Failed to get height and width!\n"); | |
+ goto fail; | |
+ } | |
+ | |
+ ctx->gl = talloc_zero(ctx, GL); | |
+ | |
+ mpegl_load_functions(ctx->gl, p->log); | |
+ | |
+ return 0; | |
+fail: | |
+ android_uninit(ctx); | |
+ return -1; | |
+} | |
+ | |
+static int android_reconfig(struct MPGLContext *ctx) | |
+{ | |
+ struct priv *p = ctx->priv; | |
+ ctx->vo->dwidth = p->w; | |
+ ctx->vo->dheight = p->h; | |
+ return 0; | |
+} | |
+ | |
+static int android_control(MPGLContext *ctx, int *events, int request, void *arg) | |
+{ | |
+ return VO_NOTIMPL; | |
+} | |
+ | |
+static void android_swap_buffers(MPGLContext *ctx) | |
+{ | |
+ struct priv *p = ctx->priv; | |
+ eglSwapBuffers(p->egl_display, p->egl_surface); | |
+} | |
+ | |
+const struct mpgl_driver mpgl_driver_android = { | |
+ .name = "android", | |
+ .priv_size = sizeof(struct priv), | |
+ .init = android_init, | |
+ .reconfig = android_reconfig, | |
+ .swap_buffers = android_swap_buffers, | |
+ .control = android_control, | |
+ .uninit = android_uninit, | |
+}; | |
diff --git a/wscript b/wscript | |
index 3a60c9c6a0..e3f0bb7ceb 100644 | |
--- a/wscript | |
+++ b/wscript | |
@@ -685,7 +685,10 @@ video_output_features = [ | |
}, { | |
'name': '--android', | |
'desc': 'Android support', | |
- 'func': check_statement('android/api-level.h', '(void)__ANDROID__'), # arbitrary android-specific header | |
+ 'func': compose_checks( | |
+ check_statement('android/api-level.h', '(void)__ANDROID__'), # arbitrary android-specific header | |
+ check_cc(lib="android"), | |
+ ) | |
}, { | |
'name': '--rpi', | |
'desc': 'Raspberry Pi support', | |
@@ -732,7 +735,7 @@ video_output_features = [ | |
'name': 'egl-helpers', | |
'desc': 'EGL helper functions', | |
'deps_any': [ 'egl-x11', 'mali-fbdev', 'rpi', 'gl-wayland', 'egl-drm', | |
- 'egl-angle' ], | |
+ 'egl-angle', 'android' ], | |
'func': check_true | |
} | |
] | |
diff --git a/wscript_build.py b/wscript_build.py | |
index 7a21d5f6e7..77daeec3c4 100644 | |
--- a/wscript_build.py | |
+++ b/wscript_build.py | |
@@ -359,6 +359,7 @@ def build(ctx): | |
( "video/out/opengl/context_drm_egl.c", "egl-drm" ), | |
( "video/out/opengl/context_dxinterop.c","gl-dxinterop" ), | |
( "video/out/opengl/context_mali_fbdev.c","mali-fbdev" ), | |
+ ( "video/out/opengl/context_android.c", "android" ), | |
( "video/out/opengl/context_rpi.c", "rpi" ), | |
( "video/out/opengl/context_vdpau.c", "vdpau-gl-x11" ), | |
( "video/out/opengl/context_wayland.c", "gl-wayland" ), |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment