ao_audiotrack: make audiotrack jni multi-instance and multi-thread safe

The detailed issue is here:
#15212

problem: Since The AudioTrack is not an mpv instance level but a global object, it cannot support multiple mpv instances at the same time. For example, if you create two instances and then destroy one of them, the other instance may crash.

Add jni usage count to fix this.
This commit is contained in:
davince 2024-10-29 20:22:39 +08:00 committed by sfan5
parent f8db474090
commit 46fe3cded0
1 changed files with 26 additions and 9 deletions

View File

@ -30,6 +30,9 @@
#include "osdep/timer.h" #include "osdep/timer.h"
#include "misc/jni.h" #include "misc/jni.h"
static mp_static_mutex jni_static_lock = MP_STATIC_MUTEX_INITIALIZER;
static int jni_static_use_count = 0;
struct priv { struct priv {
jobject audiotrack; jobject audiotrack;
jint samplerate; jint samplerate;
@ -524,26 +527,40 @@ static int AudioTrack_write(struct ao *ao, int len)
static void uninit_jni(struct ao *ao) static void uninit_jni(struct ao *ao)
{ {
mp_mutex_lock(&jni_static_lock);
jni_static_use_count--;
if (jni_static_use_count == 0) {
JNIEnv *env = MP_JNI_GET_ENV(ao); JNIEnv *env = MP_JNI_GET_ENV(ao);
for (int i = 0; i < MP_ARRAY_SIZE(jclass_list); i++) { for (int i = 0; i < MP_ARRAY_SIZE(jclass_list); i++) {
mp_jni_reset_jfields(env, jclass_list[i].fields, mp_jni_reset_jfields(env, jclass_list[i].fields,
jclass_list[i].mapping, 1, ao->log); jclass_list[i].mapping, 1, ao->log);
} }
} }
mp_mutex_unlock(&jni_static_lock);
}
static int init_jni(struct ao *ao) static int init_jni(struct ao *ao)
{ {
mp_mutex_lock(&jni_static_lock);
JNIEnv *env = MP_JNI_GET_ENV(ao); JNIEnv *env = MP_JNI_GET_ENV(ao);
if (jni_static_use_count == 0) {
for (int i = 0; i < MP_ARRAY_SIZE(jclass_list); i++) { for (int i = 0; i < MP_ARRAY_SIZE(jclass_list); i++) {
if (mp_jni_init_jfields(env, jclass_list[i].fields, if (mp_jni_init_jfields(env, jclass_list[i].fields,
jclass_list[i].mapping, 1, ao->log) < 0) { jclass_list[i].mapping, 1, ao->log) < 0) {
goto error; goto error;
} }
} }
}
jni_static_use_count++;
mp_mutex_unlock(&jni_static_lock);
return 0; return 0;
error: error:
uninit_jni(ao); for (int i = 0; i < MP_ARRAY_SIZE(jclass_list); i++) {
mp_jni_reset_jfields(env, jclass_list[i].fields,
jclass_list[i].mapping, 1, ao->log);
}
mp_mutex_unlock(&jni_static_lock);
return -1; return -1;
} }