[vlc-commits] [Git][videolan/vlc][master] 6 commits: modules: split android_env from android_utils

Thomas Guillem (@tguillem) gitlab at videolan.org
Wed Mar 15 14:47:57 UTC 2023



Thomas Guillem pushed to branch master at VideoLAN / VLC


Commits:
c65493d6 by Alexandre Janniaux at 2023-03-15T15:30:09+01:00
modules: split android_env from android_utils

android_utils depends on GLES2_LIBS and EGL_LIBS, but it isn't forwarded
correctly from the convenience library. In particlar, it contains mostly
video-related code, and some helpers for the android environment state,
which is why the non-video code is using the utils library.

Move the code in a separate convenience library so that it can be
imported without constraints.

- - - - -
ddb540cb by Alexandre Janniaux at 2023-03-15T15:30:09+01:00
audio_output: android: link android_env

The convenience library libandroid_env is needed in particular for the
function android_GetEnv.

There's no functional changes for the current way we distribute android,
ie. in static builds, since link options are ignored, but it's needed to
compile a dynamic build.

- - - - -
189d4353 by Alexandre Janniaux at 2023-03-15T15:30:09+01:00
audio_output: android: move AudioFormat vtable

Move the AudioFormat vtable to a separate file and convenience library
so as to use the AudioFormat vtable from device.c.

The choice of a convenience library here is to compile the code only
once but be able to use it from different locations, especially since it
needs the vtable filled before using the associated function.

The commit doesn't change audiotrack yet, as the goal is mostly to fix
the dynamic build on Android, and thus duplicates part of the code from
there. Some more changes would be needed to potentially supply the
vtable as parameter and provides what's missing for audiotrack.c to use
this convenience library instead.

- - - - -
ec94c477 by Thomas Guillem at 2023-03-15T15:30:09+01:00
audio_output: android: remove AudioTrack_HasEncoding()

The encoding is previously checked in device.c

- - - - -
352a3cd3 by Thomas Guillem at 2023-03-15T15:30:09+01:00
audio_output: android: add vlc_android_AudioFormat_FourCCToEncoding()

Finish the transition to the new audioformat_jni helper.

- - - - -
38d17118 by Alexandre Janniaux at 2023-03-15T15:30:09+01:00
audio_output: android: split DynamicsProcessing

DynamicsProcessing is used by android/device.c, by audiotrack and by
aaudio and a common vtable is needed as well as the matching JNI helpers
to use the vtable.

The vtable is currently stored in the audiotrack vtable, which is
available in the other plugins in static build. But it leads to
undefined reference errors when compiling a dynamic build of libvlc for
android.

Split the code handling this vtable in a separate convenience library to
address this, which is then linked to every other targets.

Since convenience libraries are playing a different role than static
libraries, and are not linked but merged into the final objects that
will be part of the library output (shared or archive), the symbols are
then available to each of the plugins.

Fixes #27726

- - - - -


20 changed files:

- modules/audio_output/Makefile.am
- modules/audio_output/android/aaudio.c
- + modules/audio_output/android/audioformat_jni.c
- + modules/audio_output/android/audioformat_jni.h
- modules/audio_output/android/audiotrack.c
- modules/audio_output/android/device.c
- modules/audio_output/android/device.h
- + modules/audio_output/android/dynamicsprocessing_jni.c
- + modules/audio_output/android/dynamicsprocessing_jni.h
- modules/audio_output/android/opensles.c
- modules/codec/Makefile.am
- modules/codec/omxil/mediacodec_jni.c
- modules/keystore/Makefile.am
- modules/keystore/file_crypt_android.c
- modules/video_output/Makefile.am
- + modules/video_output/android/env.c
- + modules/video_output/android/env.h
- modules/video_output/android/utils.c
- modules/video_output/android/utils.h
- modules/video_output/opengl/Makefile.am


Changes:

=====================================
modules/audio_output/Makefile.am
=====================================
@@ -1,16 +1,35 @@
 aoutdir = $(pluginsdir)/audio_output
 aout_LTLIBRARIES =
 
+libvlc_android_audioformat_jni_la_SOURCES = \
+	audio_output/android/audioformat_jni.c \
+	audio_output/android/audioformat_jni.h
+
+libvlc_android_dynamicsprocessing_jni_la_SOURCES = \
+	audio_output/android/dynamicsprocessing_jni.c \
+	audio_output/android/dynamicsprocessing_jni.h
+
+if HAVE_ANDROID
+noinst_LTLIBRARIES += \
+	libvlc_android_audioformat_jni.la \
+	libvlc_android_dynamicsprocessing_jni.la
+endif
+
 libopensles_android_plugin_la_SOURCES = audio_output/android/opensles.c
-libopensles_android_plugin_la_LIBADD = libandroid_utils.la $(LIBDL) $(LIBM)
+libopensles_android_plugin_la_LIBADD = libandroid_env.la $(LIBDL) $(LIBM)
 
 libandroid_audiotrack_plugin_la_SOURCES = audio_output/android/audiotrack.c audio_output/android/device.h
-libandroid_audiotrack_plugin_la_LIBADD = libandroid_utils.la
+libandroid_audiotrack_plugin_la_LIBADD = libandroid_env.la \
+	libvlc_android_audioformat_jni.la \
+	libvlc_android_dynamicsprocessing_jni.la
 
 libandroid_aaudio_plugin_la_SOURCES = audio_output/android/aaudio.c audio_output/android/device.h
-libandroid_aaudio_plugin_la_LIBADD = libandroid_utils.la $(LIBDL)
+libandroid_aaudio_plugin_la_LIBADD = libandroid_env.la libvlc_android_dynamicsprocessing_jni.la $(LIBDL)
 
 libandroid_audiodevice_plugin_la_SOURCES = audio_output/android/device.c audio_output/android/device.h
+libandroid_audiodevice_plugin_la_LIBADD = libandroid_env.la \
+	libvlc_android_audioformat_jni.la \
+	libvlc_android_dynamicsprocessing_jni.la
 
 if HAVE_ANDROID
 aout_LTLIBRARIES += libandroid_audiodevice_plugin.la libopensles_android_plugin.la \


=====================================
modules/audio_output/android/aaudio.c
=====================================
@@ -32,6 +32,8 @@
 #include <dlfcn.h>
 
 #include "device.h"
+#include "dynamicsprocessing_jni.h"
+#include "../../video_output/android/env.h"
 
 #include <aaudio/AAudio.h>
 


=====================================
modules/audio_output/android/audioformat_jni.c
=====================================
@@ -0,0 +1,175 @@
+/*****************************************************************************
+ * android/audioformat_jni.c: Android AudioFormat JNI implementation
+ *****************************************************************************
+ * Copyright © 2012-2022 VLC authors and VideoLAN, VideoLabs
+ *
+ * Authors: Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <vlc_common.h>
+#include <vlc_modules.h>
+#include <vlc_fourcc.h>
+#include "../video_output/android/env.h"
+#include "audioformat_jni.h"
+
+#define THREAD_NAME "android_audio"
+#define GET_ENV() android_getEnv(VLC_OBJECT(stream), THREAD_NAME)
+#define JNI_CALL(what, obj, method, ...) (*env)->what(env, obj, method, ##__VA_ARGS__)
+#define JNI_CALL_INT(obj, method, ...) JNI_CALL(CallIntMethod, obj, method, ##__VA_ARGS__)
+#define JNI_CALL_VOID(obj, method, ...) JNI_CALL(CallVoidMethod, obj, method, ##__VA_ARGS__)
+
+static struct {
+    struct {
+        jint ENCODING_AC3;
+        bool has_ENCODING_AC3;
+        jint ENCODING_E_AC3;
+        bool has_ENCODING_E_AC3;
+        jint ENCODING_DOLBY_TRUEHD;
+        bool has_ENCODING_DOLBY_TRUEHD;
+        jint ENCODING_DTS;
+        bool has_ENCODING_DTS;
+        jint ENCODING_DTS_HD;
+        bool has_ENCODING_DTS_HD;
+    } AudioFormat;
+} jfields;
+
+bool vlc_android_AudioFormat_HasEncoding(long long encoding_flags,
+                                         vlc_fourcc_t i_format)
+{
+#define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
+    (encoding_flags == 0 || encoding_flags & (1 << jfields.AudioFormat.x))
+
+    switch(i_format)
+    {
+        case VLC_CODEC_DTSHD:
+            return MATCH_ENCODING_FLAG(ENCODING_DTS_HD);
+        case VLC_CODEC_DTS:
+            return MATCH_ENCODING_FLAG(ENCODING_DTS);
+        case VLC_CODEC_A52:
+            return MATCH_ENCODING_FLAG(ENCODING_AC3);
+        case VLC_CODEC_EAC3:
+            return MATCH_ENCODING_FLAG(ENCODING_E_AC3);
+        case VLC_CODEC_TRUEHD:
+        case VLC_CODEC_MLP:
+            return MATCH_ENCODING_FLAG(ENCODING_DOLBY_TRUEHD);
+        default:
+            return true;
+    }
+}
+
+int vlc_android_AudioFormat_FourCCToEncoding(vlc_fourcc_t format, int *encoding)
+{
+    switch(format)
+    {
+        case VLC_CODEC_A52:
+            if( !jfields.AudioFormat.has_ENCODING_AC3 )
+                return VLC_EGENERIC;
+            *encoding = jfields.AudioFormat.ENCODING_AC3;
+            return VLC_SUCCESS;
+        case VLC_CODEC_EAC3:
+            if( !jfields.AudioFormat.has_ENCODING_E_AC3 )
+                return VLC_EGENERIC;
+            *encoding = jfields.AudioFormat.ENCODING_E_AC3;
+            return VLC_SUCCESS;
+        case VLC_CODEC_DTS:
+            if( !jfields.AudioFormat.has_ENCODING_DTS )
+                return VLC_EGENERIC;
+            *encoding = jfields.AudioFormat.ENCODING_DTS;
+            return VLC_SUCCESS;
+        default:
+            return VLC_EGENERIC;
+    }
+
+    vlc_assert_unreachable();
+}
+
+/* init all jni fields.
+ * Done only one time during the first initialisation */
+int vlc_android_AudioFormat_InitJNI(vlc_object_t *p_aout)
+{
+    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
+    static int i_init_state = -1;
+    jclass clazz;
+    jfieldID field;
+    JNIEnv *env = android_getEnv(p_aout, THREAD_NAME);
+
+    if(env == NULL)
+        return VLC_EGENERIC;
+
+    vlc_mutex_lock(&lock);
+
+    if(i_init_state != -1)
+        goto end;
+
+#define CHECK_EXCEPTION(what, critical) do { \
+    if((*env)->ExceptionCheck(env)) \
+    { \
+        msg_Err(p_aout, "%s failed", what); \
+        (*env)->ExceptionClear(env); \
+        if((critical)) \
+        { \
+            i_init_state = 0; \
+            goto end; \
+        } \
+    } \
+} while(0)
+#define GET_CLASS(str, critical) do { \
+    clazz = (*env)->FindClass(env, (str)); \
+    CHECK_EXCEPTION("FindClass(" str ")", critical); \
+} while(0)
+#define GET_ID(get, id, str, args, critical) do { \
+    jfields.id = (*env)->get(env, clazz, (str), (args)); \
+    CHECK_EXCEPTION(#get "(" #id ")", critical); \
+} while(0)
+#define GET_CONST_INT(id, str, critical) do { \
+    field = NULL; \
+    field = (*env)->GetStaticFieldID(env, clazz, (str), "I"); \
+    CHECK_EXCEPTION("GetStaticFieldID(" #id ")", critical); \
+    if(field) \
+    { \
+        jfields.id = (*env)->GetStaticIntField(env, clazz, field); \
+        CHECK_EXCEPTION(#id, critical); \
+    } \
+} while(0)
+
+
+    /* AudioFormat class init */
+    GET_CLASS("android/media/AudioFormat", true);
+    GET_CONST_INT(AudioFormat.ENCODING_AC3, "ENCODING_AC3", false);
+    jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
+    GET_CONST_INT(AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false);
+    jfields.AudioFormat.has_ENCODING_E_AC3 = field != NULL;
+
+    GET_CONST_INT(AudioFormat.ENCODING_DTS, "ENCODING_DTS", false);
+    jfields.AudioFormat.has_ENCODING_DTS = field != NULL;
+    GET_CONST_INT(AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD", false);
+    jfields.AudioFormat.has_ENCODING_DTS_HD = field != NULL;
+
+    GET_CONST_INT(AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD",
+                  false);
+    jfields.AudioFormat.has_ENCODING_DOLBY_TRUEHD = field != NULL;
+
+    i_init_state = 1;
+end:
+    vlc_mutex_unlock(&lock);
+    return i_init_state == 1 ? VLC_SUCCESS : VLC_EGENERIC;
+}


=====================================
modules/audio_output/android/audioformat_jni.h
=====================================
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * android/audioformat_jni.h: Android AudioFormat JNI vtable
+ *****************************************************************************
+ * Copyright © 2012-2022 VLC authors and VideoLAN, VideoLabs
+ *
+ * Authors: Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+bool vlc_android_AudioFormat_HasEncoding(long long encoding_flags,
+                                         vlc_fourcc_t i_format);
+
+int vlc_android_AudioFormat_FourCCToEncoding(vlc_fourcc_t format, int *encoding);
+
+/* init all jni fields.
+ * Done only one time during the first initialisation */
+int vlc_android_AudioFormat_InitJNI(vlc_object_t *p_aout);


=====================================
modules/audio_output/android/audiotrack.c
=====================================
@@ -33,8 +33,10 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_aout.h>
-#include "../video_output/android/utils.h"
+#include "../video_output/android/env.h"
 #include "device.h"
+#include "audioformat_jni.h"
+#include "dynamicsprocessing_jni.h"
 
 #define SMOOTHPOS_SAMPLE_COUNT 10
 #define SMOOTHPOS_INTERVAL_US VLC_TICK_FROM_MS(30) // 30ms
@@ -187,20 +189,8 @@ static struct
     struct {
         jint ENCODING_PCM_8BIT;
         jint ENCODING_PCM_16BIT;
-        jint ENCODING_PCM_32BIT;
-        bool has_ENCODING_PCM_32BIT;
         jint ENCODING_PCM_FLOAT;
         bool has_ENCODING_PCM_FLOAT;
-        jint ENCODING_AC3;
-        bool has_ENCODING_AC3;
-        jint ENCODING_E_AC3;
-        bool has_ENCODING_E_AC3;
-        jint ENCODING_DOLBY_TRUEHD;
-        bool has_ENCODING_DOLBY_TRUEHD;
-        jint ENCODING_DTS;
-        bool has_ENCODING_DTS;
-        jint ENCODING_DTS_HD;
-        bool has_ENCODING_DTS_HD;
         jint ENCODING_IEC61937;
         bool has_ENCODING_IEC61937;
         jint CHANNEL_OUT_MONO;
@@ -236,20 +226,19 @@ static struct
         jfieldID framePosition;
         jfieldID nanoTime;
     } AudioTimestamp;
-    struct DynamicsProcessing_fields DynamicsProcessing;
+
 } jfields;
 
 /* init all jni fields.
  * Done only one time during the first initialisation */
-int
-AudioTrack_InitJNI( audio_output_t *p_aout,
-                    struct DynamicsProcessing_fields *dp_fields )
+static int
+AudioTrack_InitJNI( vlc_object_t *p_aout)
 {
     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
     static int i_init_state = -1;
     jclass clazz;
     jfieldID field;
-    JNIEnv *env = android_getEnv( VLC_OBJECT(p_aout), THREAD_NAME );
+    JNIEnv *env = android_getEnv( p_aout, THREAD_NAME );
 
     if( env == NULL )
         return VLC_EGENERIC;
@@ -402,8 +391,6 @@ AudioTrack_InitJNI( audio_output_t *p_aout,
     GET_CLASS( "android/media/AudioFormat", true );
     GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true );
     GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true );
-    GET_CONST_INT( AudioFormat.ENCODING_PCM_32BIT, "ENCODING_PCM_32BIT", false );
-    jfields.AudioFormat.has_ENCODING_PCM_32BIT = field != NULL;
 
 #ifdef AUDIOTRACK_USE_FLOAT
     GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT",
@@ -422,20 +409,6 @@ AudioTrack_InitJNI( audio_output_t *p_aout,
     else
         jfields.AudioFormat.has_ENCODING_IEC61937 = false;
 
-    GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false );
-    jfields.AudioFormat.has_ENCODING_AC3 = field != NULL;
-    GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false );
-    jfields.AudioFormat.has_ENCODING_E_AC3 = field != NULL;
-
-    GET_CONST_INT( AudioFormat.ENCODING_DTS, "ENCODING_DTS", false );
-    jfields.AudioFormat.has_ENCODING_DTS = field != NULL;
-    GET_CONST_INT( AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD", false );
-    jfields.AudioFormat.has_ENCODING_DTS_HD = field != NULL;
-
-    GET_CONST_INT( AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD",
-                   false );
-    jfields.AudioFormat.has_ENCODING_DOLBY_TRUEHD = field != NULL;
-
     GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true );
     GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true );
     GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true );
@@ -460,27 +433,6 @@ AudioTrack_InitJNI( audio_output_t *p_aout,
     jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL;
     GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true );
 
-    /* Don't use DynamicsProcessing before Android 12 since it may crash
-     * randomly, cf. videolan/vlc-android#2221.
-     *
-     * ENCODING_PCM_32BIT is available on API 31, so test its availability to
-     * check if we are running Android 12 */
-    if( jfields.AudioFormat.has_ENCODING_PCM_32BIT )
-    {
-        GET_CLASS( "android/media/audiofx/DynamicsProcessing", false );
-        if( clazz )
-        {
-            jfields.DynamicsProcessing.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
-            CHECK_EXCEPTION( "NewGlobalRef", true );
-            GET_ID( GetMethodID, DynamicsProcessing.ctor, "<init>", "(I)V", true );
-            GET_ID( GetMethodID, DynamicsProcessing.setInputGainAllChannelsTo,
-                    "setInputGainAllChannelsTo", "(F)V", true );
-            GET_ID( GetMethodID, DynamicsProcessing.setEnabled,
-                    "setEnabled", "(Z)I", true );
-        }
-    }
-    *dp_fields = jfields.DynamicsProcessing;
-
 #undef CHECK_EXCEPTION
 #undef GET_CLASS
 #undef GET_ID
@@ -1106,30 +1058,6 @@ AudioTrack_Create( JNIEnv *env, aout_stream_t *stream,
     return 0;
 }
 
-bool
-AudioTrack_HasEncoding( long long encoding_flags, vlc_fourcc_t i_format )
-{
-#define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
-    (encoding_flags == 0 || encoding_flags & (1 << jfields.AudioFormat.x) )
-
-    switch( i_format )
-    {
-        case VLC_CODEC_DTSHD:
-            return MATCH_ENCODING_FLAG( ENCODING_DTS_HD );
-        case VLC_CODEC_DTS:
-            return MATCH_ENCODING_FLAG( ENCODING_DTS );
-        case VLC_CODEC_A52:
-            return MATCH_ENCODING_FLAG( ENCODING_AC3 );
-        case VLC_CODEC_EAC3:
-            return MATCH_ENCODING_FLAG( ENCODING_E_AC3 );
-        case VLC_CODEC_TRUEHD:
-        case VLC_CODEC_MLP:
-            return MATCH_ENCODING_FLAG( ENCODING_DOLBY_TRUEHD );
-        default:
-            return true;
-    }
-}
-
 static int GetPassthroughFmt( bool compat, audio_sample_format_t *fmt, int *at_format )
 {
     if( !compat && jfields.AudioFormat.has_ENCODING_IEC61937 )
@@ -1172,26 +1100,9 @@ static int GetPassthroughFmt( bool compat, audio_sample_format_t *fmt, int *at_f
     }
     else
     {
-        switch( fmt->i_format )
-        {
-            case VLC_CODEC_A52:
-                if( !jfields.AudioFormat.has_ENCODING_AC3 )
-                    return VLC_EGENERIC;
-                *at_format = jfields.AudioFormat.ENCODING_AC3;
-                break;
-            case VLC_CODEC_EAC3:
-                if( !jfields.AudioFormat.has_ENCODING_E_AC3 )
-                    return VLC_EGENERIC;
-                *at_format = jfields.AudioFormat.ENCODING_E_AC3;
-                break;
-            case VLC_CODEC_DTS:
-                if( !jfields.AudioFormat.has_ENCODING_DTS )
-                    return VLC_EGENERIC;
-                *at_format = jfields.AudioFormat.ENCODING_DTS;
-                break;
-            default:
-                return VLC_EGENERIC;
-        }
+        if( vlc_android_AudioFormat_FourCCToEncoding( fmt->i_format, at_format )
+                != VLC_SUCCESS )
+            return VLC_EGENERIC;
         fmt->i_bytes_per_frame = 4;
         fmt->i_frame_length = 1;
         fmt->i_physical_channels = AOUT_CHANS_STEREO;
@@ -1207,9 +1118,6 @@ StartPassthrough( JNIEnv *env, aout_stream_t *stream )
 {
     aout_sys_t *p_sys = stream->sys;
 
-    if( !AudioTrack_HasEncoding( p_sys->i_encoding_flags, p_sys->fmt.i_format ) )
-        return VLC_EGENERIC;
-
     /* Try ENCODING_IEC61937 first, then fallback to ENCODING_[AC3|DTS|...] */
     unsigned nb_fmt = jfields.AudioFormat.has_ENCODING_IEC61937 ? 2 : 1;
     int i_ret;
@@ -1366,6 +1274,8 @@ Start( aout_stream_t *stream, audio_sample_format_t *restrict p_fmt,
     if( !( env = GET_ENV() ) )
         return VLC_EGENERIC;
 
+    AudioTrack_InitJNI(VLC_OBJECT(stream));
+
     aout_sys_t *p_sys = stream->sys = calloc( 1, sizeof (aout_sys_t) );
 
     if( unlikely( p_sys == NULL ) )


=====================================
modules/audio_output/android/device.c
=====================================
@@ -29,7 +29,8 @@
 #include <vlc_modules.h>
 #include <vlc_aout.h>
 #include "device.h"
-#include "../video_output/android/utils.h"
+#include "audioformat_jni.h"
+#include "../video_output/android/env.h"
 
 /* There is an undefined behavior when configuring AudioTrack with SPDIF or
  * more than 2 channels when there is no HDMI out. It may succeed and the
@@ -58,8 +59,6 @@ static const struct {
     {  NULL, NULL, ANDROID_AUDIO_DEVICE_DEFAULT },
 };
 
-static struct DynamicsProcessing_fields dp_fields;
-
 struct sys {
     aout_stream_t *stream;
 
@@ -94,7 +93,7 @@ Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
     struct sys *sys = aout->sys;
 
-    if (!AudioTrack_HasEncoding(sys->encoding_flags, fmt->i_format))
+    if (!vlc_android_AudioFormat_HasEncoding(sys->encoding_flags, fmt->i_format))
         return VLC_EGENERIC;
 
     aout_stream_t *s = vlc_object_create(aout, sizeof (*s));
@@ -249,7 +248,7 @@ static int DeviceSelect(audio_output_t *aout, const char *id)
             for (size_t i = 0;
                  i < sizeof(enc_fourccs)/ sizeof(enc_fourccs[0]); ++i)
             {
-                if (AudioTrack_HasEncoding(sys->encoding_flags, enc_fourccs[i]))
+                if (vlc_android_AudioFormat_HasEncoding(sys->encoding_flags, enc_fourccs[i]))
                     msg_Dbg(aout, "device has %4.4s passthrough support",
                              (const char *)&enc_fourccs[i]);
             }
@@ -264,9 +263,8 @@ Open(vlc_object_t *obj)
 {
     audio_output_t *aout = (audio_output_t *)obj;
 
-    int ret = AudioTrack_InitJNI(aout, &dp_fields);
-    if (ret != VLC_SUCCESS)
-        return ret;
+    if (vlc_android_AudioFormat_InitJNI(obj) != VLC_SUCCESS)
+        return VLC_EGENERIC;
 
     struct sys *sys = aout->sys = vlc_obj_malloc(obj, sizeof(*sys));
     if (sys == NULL)
@@ -297,90 +295,6 @@ Open(vlc_object_t *obj)
     return VLC_SUCCESS;
 }
 
-#define THREAD_NAME "android_audio"
-#define GET_ENV() android_getEnv( VLC_OBJECT(stream), THREAD_NAME )
-#define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
-#define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
-#define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
-static inline bool
-check_exception( JNIEnv *env, aout_stream_t *stream,
-                 const char *class, const char *method )
-{
-    if( (*env)->ExceptionCheck( env ) )
-    {
-        (*env)->ExceptionDescribe( env );
-        (*env)->ExceptionClear( env );
-        msg_Err( stream, "%s.%s triggered an exception !", class, method );
-        return true;
-    } else
-        return false;
-}
-#define CHECK_EXCEPTION( class, method ) check_exception( env, stream, class, method )
-
-jobject
-DynamicsProcessing_New( aout_stream_t *stream, int session_id )
-{
-    JNIEnv *env;
-    if( !( env = GET_ENV() ) )
-        return NULL;
-
-    if( !dp_fields.clazz )
-        return NULL;
-
-    jobject dp = JNI_CALL( NewObject, dp_fields.clazz,
-                           dp_fields.ctor, session_id );
-
-    if( CHECK_EXCEPTION( "DynamicsProcessing", "ctor" ) )
-        return NULL;
-
-    jobject global_dp = (*env)->NewGlobalRef( env, dp );
-    (*env)->DeleteLocalRef( env, dp );
-
-    return global_dp;
-}
-
-void
-DynamicsProcessing_Disable( aout_stream_t *stream, jobject dp )
-{
-    JNIEnv *env;
-    if( !( env = GET_ENV() ) )
-        return;
-
-    JNI_CALL_INT( dp, dp_fields.setEnabled, false );
-    CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" );
-}
-
-int
-DynamicsProcessing_SetVolume( aout_stream_t *stream, jobject dp, float volume )
-{
-    JNIEnv *env;
-    if( !( env = GET_ENV() ) )
-        return VLC_EGENERIC;
-
-    /* convert linear gain to dB */
-    float dB = volume == 0.0f ? -144 : 20.0f * log10f( volume );
-
-    JNI_CALL_VOID( dp, dp_fields.setInputGainAllChannelsTo, dB );
-    int ret = JNI_CALL_INT( dp, dp_fields.setEnabled, volume != 1.0f );
-
-    if( CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" ) || ret != 0 )
-        return VLC_EGENERIC;
-
-    return VLC_SUCCESS;
-}
-
-void
-DynamicsProcessing_Delete( aout_stream_t *stream, jobject dp )
-{
-    JNIEnv *env;
-    if( !( env = GET_ENV() ) )
-        return;
-
-    JNI_CALL_INT( dp, dp_fields.setEnabled, false );
-    CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" );
-
-    (*env)->DeleteGlobalRef( env, dp );
-}
 
 #define add_aout(shortcut, name, desc) \
     add_submodule() \


=====================================
modules/audio_output/android/device.h
=====================================
@@ -32,33 +32,6 @@ enum android_audio_device_type
 };
 #define ANDROID_AUDIO_DEVICE_MAX_CHANNELS 8
 
-struct DynamicsProcessing_fields
-{
-    jclass clazz;
-    jmethodID ctor;
-    jmethodID setInputGainAllChannelsTo;
-    jmethodID setEnabled;
-};
-
-int
-AudioTrack_InitJNI(audio_output_t *aout,
-                   struct DynamicsProcessing_fields *dp_fields);
-
-bool
-AudioTrack_HasEncoding(long long encoding_flags, vlc_fourcc_t format);
-
-jobject
-DynamicsProcessing_New(aout_stream_t *stream, int32_t session_id);
-
-int
-DynamicsProcessing_SetVolume(aout_stream_t *stream, jobject dp, float volume);
-
-void
-DynamicsProcessing_Disable(aout_stream_t *stream, jobject dp);
-
-void
-DynamicsProcessing_Delete(aout_stream_t *stream, jobject dp);
-
 struct aout_stream
 {
     struct vlc_object_t obj;


=====================================
modules/audio_output/android/dynamicsprocessing_jni.c
=====================================
@@ -0,0 +1,212 @@
+/*****************************************************************************
+ * android/dynamicsprocessing_jni.c: Android DynamicsProcessing
+ *****************************************************************************
+ * Copyright © 2012-2023 VLC authors and VideoLAN, VideoLabs
+ *
+ * Authors: Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_fourcc.h>
+
+#include <jni.h>
+#include <math.h>
+
+#include "dynamicsprocessing_jni.h"
+#include "../../video_output/android/env.h"
+
+#define THREAD_NAME "android_audio"
+#define GET_ENV() android_getEnv( obj, THREAD_NAME )
+#define JNI_CALL( what, obj, method, ... ) (*env)->what( env, obj, method, ##__VA_ARGS__ )
+#define JNI_CALL_INT( obj, method, ... ) JNI_CALL( CallIntMethod, obj, method, ##__VA_ARGS__ )
+#define JNI_CALL_VOID( obj, method, ... ) JNI_CALL( CallVoidMethod, obj, method, ##__VA_ARGS__ )
+
+struct DynamicsProcessing_fields
+{
+    /* Needed to probe for PCM 32bit support */
+    struct {
+        jclass clazz;
+        jint ENCODING_PCM_32BIT;
+    } AudioFormat;
+
+    struct {
+        jclass clazz;
+        jmethodID ctor;
+        jmethodID setInputGainAllChannelsTo;
+        jmethodID setEnabled;
+    } DynamicsProcessing;
+};
+static struct DynamicsProcessing_fields jfields;
+
+int DynamicsProcessing_InitJNI( vlc_object_t *obj )
+{
+    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
+    static int i_init_state = -1;
+
+    jclass clazz;
+    jfieldID field;
+    JNIEnv *env = android_getEnv( obj, THREAD_NAME );
+
+    if( env == NULL )
+        return VLC_EGENERIC;
+
+    vlc_mutex_lock(&lock);
+    if( i_init_state != -1 )
+        goto end;
+
+#define CHECK_EXCEPTION( what, critical ) do { \
+    if( (*env)->ExceptionCheck( env ) ) \
+    { \
+        msg_Err( obj, "%s failed", what ); \
+        (*env)->ExceptionClear( env ); \
+        if( (critical) ) \
+        { \
+            i_init_state = 0; \
+            goto end; \
+        } \
+    } \
+} while( 0 )
+#define GET_CLASS( str, critical ) do { \
+    clazz = (*env)->FindClass( env, (str) ); \
+    CHECK_EXCEPTION( "FindClass(" str ")", critical ); \
+} while( 0 )
+#define GET_ID( get, id, str, args, critical ) do { \
+    jfields.id = (*env)->get( env, clazz, (str), (args) ); \
+    CHECK_EXCEPTION( #get "(" #id ")", critical ); \
+} while( 0 )
+#define GET_CONST_INT( id, str, critical ) do { \
+    field = NULL; \
+    field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \
+    CHECK_EXCEPTION( "GetStaticFieldID(" #id ")", critical ); \
+    if( field ) \
+    { \
+        jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \
+        CHECK_EXCEPTION( #id, critical ); \
+    } \
+} while( 0 )
+
+    /* Don't use DynamicsProcessing before Android 12 since it may crash
+     * randomly, cf. videolan/vlc-android#2221.
+     *
+     * ENCODING_PCM_32BIT is available on API 31, so test its availability to
+     * check if we are running Android 12 */
+    GET_CLASS( "android/media/AudioFormat", true );
+    GET_CONST_INT( AudioFormat.ENCODING_PCM_32BIT, "ENCODING_PCM_32BIT", true );
+
+    GET_CLASS( "android/media/audiofx/DynamicsProcessing", true );
+
+    jfields.DynamicsProcessing.clazz = (jclass) (*env)->NewGlobalRef( env, clazz );
+    CHECK_EXCEPTION( "NewGlobalRef", true );
+    GET_ID( GetMethodID, DynamicsProcessing.ctor, "<init>", "(I)V", true );
+    GET_ID( GetMethodID, DynamicsProcessing.setInputGainAllChannelsTo,
+            "setInputGainAllChannelsTo", "(F)V", true );
+    GET_ID( GetMethodID, DynamicsProcessing.setEnabled,
+            "setEnabled", "(Z)I", true );
+
+#undef CHECK_EXCEPTION
+
+    i_init_state = 1;
+end:
+    vlc_mutex_unlock(&lock);
+    return i_init_state == 1 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
+static inline bool
+check_exception( JNIEnv *env, vlc_object_t *obj,
+                 const char *class, const char *method )
+{
+    if( (*env)->ExceptionCheck( env ) )
+    {
+        (*env)->ExceptionDescribe( env );
+        (*env)->ExceptionClear( env );
+        msg_Err( obj, "%s.%s triggered an exception !", class, method );
+        return true;
+    } else
+        return false;
+}
+#define CHECK_EXCEPTION( class, method ) check_exception( env, obj, class, method )
+
+
+jobject
+(DynamicsProcessing_New)( vlc_object_t *obj, int session_id )
+{
+    JNIEnv *env;
+    if( !( env = GET_ENV() ) )
+        return NULL;
+
+    int ret = DynamicsProcessing_InitJNI( obj );
+    if (ret == VLC_EGENERIC)
+        return NULL;
+
+    jobject dp = JNI_CALL( NewObject, jfields.DynamicsProcessing.clazz,
+                           jfields.DynamicsProcessing.ctor, session_id );
+
+    if( CHECK_EXCEPTION( "DynamicsProcessing", "ctor" ) )
+        return NULL;
+
+    jobject global_dp = (*env)->NewGlobalRef( env, dp );
+    (*env)->DeleteLocalRef( env, dp );
+
+    return global_dp;
+}
+
+void
+(DynamicsProcessing_Disable)( vlc_object_t *obj, jobject dp )
+{
+    JNIEnv *env;
+    if( !( env = GET_ENV() ) )
+        return;
+
+    JNI_CALL_INT( dp, jfields.DynamicsProcessing.setEnabled, false );
+    CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" );
+}
+
+int
+(DynamicsProcessing_SetVolume)( vlc_object_t *obj, jobject dp, float volume )
+{
+    JNIEnv *env;
+    if( !( env = GET_ENV() ) )
+        return VLC_EGENERIC;
+
+    /* convert linear gain to dB */
+    float dB = volume == 0.0f ? -144 : 20.0f * log10f( volume );
+
+    JNI_CALL_VOID( dp, jfields.DynamicsProcessing.setInputGainAllChannelsTo, dB );
+    int ret = JNI_CALL_INT( dp, jfields.DynamicsProcessing.setEnabled, volume != 1.0f );
+
+    if( CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" ) || ret != 0 )
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+}
+
+void
+(DynamicsProcessing_Delete)( vlc_object_t *obj, jobject dp )
+{
+    JNIEnv *env;
+    if( !( env = GET_ENV() ) )
+        return;
+
+    JNI_CALL_INT( dp, jfields.DynamicsProcessing.setEnabled, false );
+    CHECK_EXCEPTION( "DynamicsProcessing", "setEnabled" );
+
+    (*env)->DeleteGlobalRef( env, dp );
+}


=====================================
modules/audio_output/android/dynamicsprocessing_jni.h
=====================================
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * android/dynamicsprocessing_jni.h: Android DynamicsProcessing
+ *****************************************************************************
+ * Copyright © 2012-2023 VLC authors and VideoLAN, VideoLabs
+ *
+ * Authors: Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+int
+DynamicsProcessing_InitJNI(vlc_object_t *obj);
+
+jobject
+DynamicsProcessing_New(vlc_object_t *obj, int32_t session_id);
+#define DynamicsProcessing_New(o, s) \
+    (DynamicsProcessing_New)(VLC_OBJECT(o), s)
+
+int
+DynamicsProcessing_SetVolume(vlc_object_t *obj, jobject dp, float volume);
+#define DynamicsProcessing_SetVolume(o, dp, v) \
+    (DynamicsProcessing_SetVolume)(VLC_OBJECT(o), dp, v)
+
+void
+DynamicsProcessing_Disable(vlc_object_t *obj, jobject dp);
+#define DynamicsProcessing_Disable(o, dp) \
+    (DynamicsProcessing_Disable)(VLC_OBJECT(o), dp)
+
+void
+DynamicsProcessing_Delete(vlc_object_t *obj, jobject dp);
+#define DynamicsProcessing_Delete(o, dp) \
+    (DynamicsProcessing_Delete)(VLC_OBJECT(o), dp)
+
+


=====================================
modules/audio_output/android/opensles.c
=====================================
@@ -33,12 +33,13 @@
 #include <dlfcn.h>
 #include <math.h>
 
+#include "../../video_output/android/env.h"
+
 // For native audio
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES_Android.h>
 
 #include <jni.h>
-JNIEnv *android_getEnv(vlc_object_t *p_obj, const char *psz_thread_name);
 
 #define OPENSLES_BUFFERS 255 /* maximum number of buffers */
 #define OPENSLES_BUFLEN  VLC_TICK_FROM_MS(10)


=====================================
modules/codec/Makefile.am
=====================================
@@ -487,7 +487,8 @@ libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
 libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacodec.h \
 	codec/omxil/mediacodec_jni.c codec/omxil/mediacodec_ndk.c codec/omxil/utils.c \
 	codec/omxil/omxil_utils.h codec/omxil/qcom.c codec/omxil/qcom.h
-libmediacodec_plugin_la_LIBADD = libchroma_copy.la libvlc_hxxxhelper.la libandroid_utils.la $(LIBDL)
+libmediacodec_plugin_la_LIBADD = libchroma_copy.la libvlc_hxxxhelper.la \
+	libandroid_env.la libandroid_utils.la $(LIBDL) $(GLES2_LIBS) $(EGL_LIBS)
 codec_LTLIBRARIES += $(LTLIBomxil)
 EXTRA_LTLIBRARIES += libomxil_plugin.la
 if HAVE_ANDROID


=====================================
modules/codec/omxil/mediacodec_jni.c
=====================================
@@ -37,6 +37,7 @@
 #include "../../packetizer/hevc_nal.h"
 
 #include "mediacodec.h"
+#include "../../video_output/android/env.h"
 
 char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
                          int profile, int *p_quirks);


=====================================
modules/keystore/Makefile.am
=====================================
@@ -9,7 +9,7 @@ libfile_keystore_plugin_la_SOURCES = keystore/file.c \
 	keystore/list_util.c keystore/list_util.h
 if HAVE_ANDROID
 libfile_keystore_plugin_la_SOURCES += keystore/file_crypt_android.c
-libfile_keystore_plugin_la_LIBADD = libandroid_utils.la
+libfile_keystore_plugin_la_LIBADD = libandroid_env.la
 endif
 if HAVE_WIN32
 libfile_keystore_plugin_la_SOURCES += keystore/file_crypt_win32.c


=====================================
modules/keystore/file_crypt_android.c
=====================================
@@ -32,7 +32,7 @@
 
 #include <jni.h>
 
-JNIEnv * android_getEnv(vlc_object_t *, const char *);
+#include "../video_output/android/env.h"
 #define GET_ENV() android_getEnv(VLC_OBJECT(p_keystore), "android keystore")
 
 static struct


=====================================
modules/video_output/Makefile.am
=====================================
@@ -291,26 +291,34 @@ endif
 libandroid_utils_la_SOURCES = video_output/android/utils.c video_output/android/utils.h
 libandroid_utils_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) $(EGL_CFLAGS)
 libandroid_utils_la_LIBADD = $(GLES2_LIBS) $(EGL_LIBS)
+
+libandroid_env_la_SOURCES = \
+	video_output/android/env.c \
+	video_output/android/env.h
 if HAVE_ANDROID
-noinst_LTLIBRARIES += libandroid_utils.la
+noinst_LTLIBRARIES += \
+	libandroid_utils.la \
+	libandroid_env.la
 endif
 
 libegl_android_plugin_la_SOURCES = video_output/opengl/egl.c
 libegl_android_plugin_la_CFLAGS = $(AM_CFLAGS) $(EGL_CFLAGS) -DUSE_PLATFORM_ANDROID=1
-libegl_android_plugin_la_LIBADD = $(EGL_LIBS) libandroid_utils.la
+libegl_android_plugin_la_LIBADD = libandroid_env.la $(EGL_LIBS) libandroid_utils.la
 
 libandroid_window_plugin_la_SOURCES = video_output/android/window.c \
 	video_output/wasync_resize_compressor.h
-libandroid_window_plugin_la_LIBADD = libandroid_utils.la $(LIBDL)
+libandroid_window_plugin_la_LIBADD = \
+	libandroid_env.la libandroid_utils.la $(LIBDL) $(EGL_LIBS) $(GLES2_LIBS)
 
 libandroid_display_plugin_la_SOURCES = video_output/android/display.c
 libandroid_display_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES2
-libandroid_display_plugin_la_LIBADD = libvlc_opengles.la
+libandroid_display_plugin_la_LIBADD = libvlc_opengles.la $(EGL_LIBS) $(GLES2_LIBS)
 
 libglinterop_android_plugin_la_SOURCES = video_output/opengl/interop_android.c \
 	video_output/opengl/interop.h
 libglinterop_android_plugin_la_CFLAGS = $(AM_CFLAGS) -DUSE_OPENGL_ES2
-libglinterop_android_plugin_la_LIBADD = libandroid_utils.la
+libglinterop_android_plugin_la_LIBADD = libandroid_env.la libandroid_utils.la \
+	$(EGL_LIBS) $(GLES2_LIBS)
 
 if HAVE_ANDROID
 vout_LTLIBRARIES += libandroid_window_plugin.la libandroid_display_plugin.la


=====================================
modules/video_output/android/env.c
=====================================
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * env.c: shared code between Android modules.
+ *****************************************************************************
+ * Copyright (C) 2014-2015 VLC authors and VideoLAN
+ *
+ * Authors: Felix Abecassis <felix.abecassis at gmail.com>
+ *          Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "utils.h"
+#include <dlfcn.h>
+#include <jni.h>
+#include <pthread.h>
+#include <assert.h>
+
+/*
+ * Android JNIEnv helper
+ */
+
+static pthread_key_t jni_env_key;
+static pthread_once_t jni_env_key_once = PTHREAD_ONCE_INIT;
+
+/* This function is called when a thread attached to the Java VM is canceled or
+ * exited */
+static void
+jni_detach_thread(void *data)
+{
+    JNIEnv *env = data;
+    JavaVM *jvm;
+
+    (*env)->GetJavaVM(env, &jvm);
+    assert(jvm);
+    (*jvm)->DetachCurrentThread(jvm);
+}
+
+static void jni_env_key_create()
+{
+    /* Create a TSD area and setup a destroy callback when a thread that
+     * previously set the jni_env_key is canceled or exited */
+    pthread_key_create(&jni_env_key, jni_detach_thread);
+}
+
+JNIEnv *
+android_getEnvCommon(vlc_object_t *p_obj, JavaVM *jvm, const char *psz_name)
+{
+    assert((p_obj && !jvm) || (!p_obj && jvm));
+
+    JNIEnv *env;
+
+    pthread_once(&jni_env_key_once, jni_env_key_create);
+    env = pthread_getspecific(jni_env_key);
+    if (env == NULL)
+    {
+        if (!jvm)
+            jvm = var_InheritAddress(p_obj, "android-jvm");
+
+        if (!jvm)
+            return NULL;
+
+        /* if GetEnv returns JNI_OK, the thread is already attached to the
+         * JavaVM, so we are already in a java thread, and we don't have to
+         * setup any destroy callbacks */
+        if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2) != JNI_OK)
+        {
+            /* attach the thread to the Java VM */
+            JavaVMAttachArgs args;
+
+            args.version = JNI_VERSION_1_2;
+            args.name = psz_name;
+            args.group = NULL;
+
+            if ((*jvm)->AttachCurrentThread(jvm, &env, &args) != JNI_OK)
+                return NULL;
+
+            /* Set the attached env to the thread-specific data area (TSD) */
+            if (pthread_setspecific(jni_env_key, env) != 0)
+            {
+                (*jvm)->DetachCurrentThread(jvm);
+                return NULL;
+            }
+        }
+    }
+
+    return env;
+}


=====================================
modules/video_output/android/env.h
=====================================
@@ -0,0 +1,33 @@
+/*****************************************************************************
+ * env.h: shared code between Android modules
+ *****************************************************************************
+ * Copyright (C) 2014-2015 VLC authors and VideoLAN
+ *
+ * Authors: Felix Abecassis <felix.abecassis at gmail.com>
+ *          Thomas Guillem <thomas at gllm.fr>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include <jni.h>
+
+JNIEnv *
+android_getEnvCommon(vlc_object_t *p_obj, JavaVM *jvm, const char *psz_name);
+
+static inline JNIEnv *
+android_getEnv(vlc_object_t *p_obj, const char *psz_name)
+{
+    return android_getEnvCommon(p_obj, NULL, psz_name);
+}


=====================================
modules/video_output/android/utils.c
=====================================
@@ -26,6 +26,8 @@
 #endif
 
 #include "utils.h"
+#include "env.h"
+
 #include <dlfcn.h>
 #include <jni.h>
 #include <pthread.h>
@@ -150,84 +152,6 @@ struct AWindowHandler
 #define JNI_STEXCALL(what, method, ...) \
     (*p_env)->what(p_env, p_awh->jobj, p_awh->jfields.AWindow.method, ##__VA_ARGS__)
 
-/*
- * Android JNIEnv helper
- */
-
-static pthread_key_t jni_env_key;
-static pthread_once_t jni_env_key_once = PTHREAD_ONCE_INIT;
-
-/* This function is called when a thread attached to the Java VM is canceled or
- * exited */
-static void
-jni_detach_thread(void *data)
-{
-    JNIEnv *env = data;
-    JavaVM *jvm;
-
-    (*env)->GetJavaVM(env, &jvm);
-    assert(jvm);
-    (*jvm)->DetachCurrentThread(jvm);
-}
-
-static void jni_env_key_create()
-{
-    /* Create a TSD area and setup a destroy callback when a thread that
-     * previously set the jni_env_key is canceled or exited */
-    pthread_key_create(&jni_env_key, jni_detach_thread);
-}
-
-static JNIEnv *
-android_getEnvCommon(vlc_object_t *p_obj, JavaVM *jvm, const char *psz_name)
-{
-    assert((p_obj && !jvm) || (!p_obj && jvm));
-
-    JNIEnv *env;
-
-    pthread_once(&jni_env_key_once, jni_env_key_create);
-    env = pthread_getspecific(jni_env_key);
-    if (env == NULL)
-    {
-        if (!jvm)
-            jvm = var_InheritAddress(p_obj, "android-jvm");
-
-        if (!jvm)
-            return NULL;
-
-        /* if GetEnv returns JNI_OK, the thread is already attached to the
-         * JavaVM, so we are already in a java thread, and we don't have to
-         * setup any destroy callbacks */
-        if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2) != JNI_OK)
-        {
-            /* attach the thread to the Java VM */
-            JavaVMAttachArgs args;
-
-            args.version = JNI_VERSION_1_2;
-            args.name = psz_name;
-            args.group = NULL;
-
-            if ((*jvm)->AttachCurrentThread(jvm, &env, &args) != JNI_OK)
-                return NULL;
-
-            /* Set the attached env to the thread-specific data area (TSD) */
-            if (pthread_setspecific(jni_env_key, env) != 0)
-            {
-                (*jvm)->DetachCurrentThread(jvm);
-                return NULL;
-            }
-        }
-    }
-
-    return env;
-}
-
-JNIEnv *
-android_getEnv(vlc_object_t *p_obj, const char *psz_name)
-{
-    return android_getEnvCommon(p_obj, NULL, psz_name);
-}
-
-
 /*
  * Android Surface (pre android 2.3)
  */


=====================================
modules/video_output/android/utils.h
=====================================
@@ -114,15 +114,6 @@ struct vlc_asurfacetexture_operations
             struct vlc_asurfacetexture *surface);
 };
 
-/**
- * Attach or get a JNIEnv*
- *
- * The returned JNIEnv* is created from the android JavaVM attached to the VLC
- * object var.
- * \return a valid JNIEnv * or NULL. It doesn't need to be released.
- */
-JNIEnv *android_getEnv(vlc_object_t *p_obj, const char *psz_thread_name);
-
 /**
  * Create new AWindowHandler
  *


=====================================
modules/video_output/opengl/Makefile.am
=====================================
@@ -223,7 +223,8 @@ endif
 
 libegl_surfacetexture_plugin_la_SOURCES = video_filter/egl_surfacetexture.c
 libegl_surfacetexture_plugin_la_CFLAGS = $(AM_CFLAGS) $(EGL_CFLAGS) -DUSE_OPENGL_ES2
-libegl_surfacetexture_plugin_la_LIBADD = $(EGL_LIBS) libandroid_utils.la libvlc_opengles.la
+libegl_surfacetexture_plugin_la_LIBADD = $(EGL_LIBS) \
+	libandroid_env.la libandroid_utils.la libvlc_opengles.la
 
 if HAVE_ANDROID
 if HAVE_EGL



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e6785a0f4545b216b4e157dfd1c7d92fbc5b8a6c...38d17118c45ac5df1fee375823ac98d341af8723

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e6785a0f4545b216b4e157dfd1c7d92fbc5b8a6c...38d17118c45ac5df1fee375823ac98d341af8723
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list