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:
damontecres 2025-11-16 18:46:25 -05:00 • committed by GitHub
parent d7b333e519
commit 6be2662d4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
84 changed files with 3987 additions and 289 deletions

View file

@ -0,0 +1,125 @@
#include <jni.h>
#include <stdlib.h>
#include <mpv/client.h>
#include "jni_utils.h"
#include "log.h"
#include "globals.h"
extern "C" {
jni_func(jint, setOptionString, jstring option, jstring value);
jni_func(jobject, getPropertyInt, jstring property);
jni_func(void, setPropertyInt, jstring property, jint value);
jni_func(jobject, getPropertyDouble, jstring property);
jni_func(void, setPropertyDouble, jstring property, jdouble value);
jni_func(jobject, getPropertyBoolean, jstring property);
jni_func(void, setPropertyBoolean, jstring property, jboolean value);
jni_func(jstring, getPropertyString, jstring jproperty);
jni_func(void, setPropertyString, jstring jproperty, jstring jvalue);
jni_func(void, observeProperty, jstring property, jint format);
}
jni_func(jint, setOptionString, jstring joption, jstring jvalue) {
CHECK_MPV_INIT();
const char *option = env->GetStringUTFChars(joption, NULL);
const char *value = env->GetStringUTFChars(jvalue, NULL);
int result = mpv_set_option_string(g_mpv, option, value);
env->ReleaseStringUTFChars(joption, option);
env->ReleaseStringUTFChars(jvalue, value);
return result;
}
static int common_get_property(JNIEnv *env, jstring jproperty, mpv_format format, void *output)
{
CHECK_MPV_INIT();
const char *prop = env->GetStringUTFChars(jproperty, NULL);
int result = mpv_get_property(g_mpv, prop, format, output);
if (result == MPV_ERROR_PROPERTY_UNAVAILABLE)
ALOGV("mpv_get_property(%s) format %d was unavailable", prop, format);
else if (result < 0)
ALOGE("mpv_get_property(%s) format %d returned error %s", prop, format, mpv_error_string(result));
env->ReleaseStringUTFChars(jproperty, prop);
return result;
}
static int common_set_property(JNIEnv *env, jstring jproperty, mpv_format format, void *value)
{
CHECK_MPV_INIT();
const char *prop = env->GetStringUTFChars(jproperty, NULL);
int result = mpv_set_property(g_mpv, prop, format, value);
if (result < 0)
ALOGE("mpv_set_property(%s, %p) format %d returned error %s", prop, value, format, mpv_error_string(result));
env->ReleaseStringUTFChars(jproperty, prop);
return result;
}
jni_func(jobject, getPropertyInt, jstring jproperty) {
int64_t value = 0;
if (common_get_property(env, jproperty, MPV_FORMAT_INT64, &value) < 0)
return NULL;
return env->NewObject(java_Integer, java_Integer_init, (jint)value);
}
jni_func(jobject, getPropertyDouble, jstring jproperty) {
double value = 0;
if (common_get_property(env, jproperty, MPV_FORMAT_DOUBLE, &value) < 0)
return NULL;
return env->NewObject(java_Double, java_Double_init, (jdouble)value);
}
jni_func(jobject, getPropertyBoolean, jstring jproperty) {
int value = 0;
if (common_get_property(env, jproperty, MPV_FORMAT_FLAG, &value) < 0)
return NULL;
return env->NewObject(java_Boolean, java_Boolean_init, (jboolean)value);
}
jni_func(jstring, getPropertyString, jstring jproperty) {
char *value;
if (common_get_property(env, jproperty, MPV_FORMAT_STRING, &value) < 0)
return NULL;
jstring jvalue = env->NewStringUTF(value);
mpv_free(value);
return jvalue;
}
jni_func(void, setPropertyInt, jstring jproperty, jint jvalue) {
int64_t value = static_cast<int64_t>(jvalue);
common_set_property(env, jproperty, MPV_FORMAT_INT64, &value);
}
jni_func(void, setPropertyDouble, jstring jproperty, jdouble jvalue) {
double value = static_cast<double>(jvalue);
common_set_property(env, jproperty, MPV_FORMAT_DOUBLE, &value);
}
jni_func(void, setPropertyBoolean, jstring jproperty, jboolean jvalue) {
int value = jvalue == JNI_TRUE ? 1 : 0;
common_set_property(env, jproperty, MPV_FORMAT_FLAG, &value);
}
jni_func(void, setPropertyString, jstring jproperty, jstring jvalue) {
const char *value = env->GetStringUTFChars(jvalue, NULL);
common_set_property(env, jproperty, MPV_FORMAT_STRING, &value);
env->ReleaseStringUTFChars(jvalue, value);
}
jni_func(void, observeProperty, jstring property, jint format) {
CHECK_MPV_INIT();
const char *prop = env->GetStringUTFChars(property, NULL);
int result = mpv_observe_property(g_mpv, 0, prop, (mpv_format)format);
if (result < 0)
ALOGE("mpv_observe_property(%s) format %d returned error %s", prop, format, mpv_error_string(result));
env->ReleaseStringUTFChars(property, prop);
}