mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 08:01:20 +02:00
Add experimental MPV player backend (#161)
Experimental MPV player backend Related to #14, #22, & #85 You can switch to MPV in advanced settings and toggle using hardware decoding or not. This uses code and buildscripts from https://github.com/mpv-android/mpv-android, plus other third party libraries to build MPV
This commit is contained in:
parent
d7b333e519
commit
6be2662d4e
84 changed files with 3987 additions and 289 deletions
108
app/src/main/jni/main.cpp
Normal file
108
app/src/main/jni/main.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <locale.h>
|
||||
#include <atomic>
|
||||
|
||||
#include <mpv/client.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/jni.h>
|
||||
}
|
||||
|
||||
#include "log.h"
|
||||
#include "jni_utils.h"
|
||||
#include "event.h"
|
||||
|
||||
#define ARRAYLEN(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
extern "C" {
|
||||
jni_func(void, create, jobject appctx);
|
||||
jni_func(void, init);
|
||||
jni_func(void, destroy);
|
||||
|
||||
jni_func(void, command, jobjectArray jarray);
|
||||
};
|
||||
|
||||
JavaVM *g_vm;
|
||||
mpv_handle *g_mpv;
|
||||
std::atomic<bool> g_event_thread_request_exit(false);
|
||||
|
||||
static pthread_t event_thread_id;
|
||||
|
||||
static void prepare_environment(JNIEnv *env, jobject appctx) {
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
if (!env->GetJavaVM(&g_vm) && g_vm)
|
||||
av_jni_set_java_vm(g_vm, NULL);
|
||||
|
||||
jobject global_appctx = env->NewGlobalRef(appctx);
|
||||
if (global_appctx)
|
||||
av_jni_set_android_app_ctx(global_appctx, NULL);
|
||||
|
||||
init_methods_cache(env);
|
||||
}
|
||||
|
||||
jni_func(void, create, jobject appctx) {
|
||||
prepare_environment(env, appctx);
|
||||
|
||||
if (g_mpv)
|
||||
die("mpv is already initialized");
|
||||
|
||||
g_mpv = mpv_create();
|
||||
if (!g_mpv)
|
||||
die("context init failed");
|
||||
|
||||
// use terminal log level but request verbose messages
|
||||
// this way --msg-level can be used to adjust later
|
||||
mpv_request_log_messages(g_mpv, "terminal-default");
|
||||
mpv_set_option_string(g_mpv, "msg-level", "all=v");
|
||||
}
|
||||
|
||||
jni_func(void, init) {
|
||||
if (!g_mpv)
|
||||
die("mpv is not created");
|
||||
|
||||
if (mpv_initialize(g_mpv) < 0)
|
||||
die("mpv init failed");
|
||||
|
||||
g_event_thread_request_exit = false;
|
||||
if (pthread_create(&event_thread_id, NULL, event_thread, NULL) != 0)
|
||||
die("thread create failed");
|
||||
pthread_setname_np(event_thread_id, "event_thread");
|
||||
}
|
||||
|
||||
jni_func(void, destroy) {
|
||||
if (!g_mpv) {
|
||||
ALOGV("mpv destroy called but it's already destroyed");
|
||||
return;
|
||||
}
|
||||
|
||||
// poke event thread and wait for it to exit
|
||||
g_event_thread_request_exit = true;
|
||||
mpv_wakeup(g_mpv);
|
||||
pthread_join(event_thread_id, NULL);
|
||||
|
||||
mpv_terminate_destroy(g_mpv);
|
||||
g_mpv = NULL;
|
||||
}
|
||||
|
||||
jni_func(void, command, jobjectArray jarray) {
|
||||
CHECK_MPV_INIT();
|
||||
|
||||
const char *arguments[128] = {0};
|
||||
int len = env->GetArrayLength(jarray);
|
||||
if (len >= ARRAYLEN(arguments))
|
||||
die("too many command arguments");
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
arguments[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(jarray, i), NULL);
|
||||
|
||||
mpv_command(g_mpv, arguments);
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(jarray, i), arguments[i]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue