]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mediacodec_wrapper.c
avcodec/Makefile: Fix mlpenc dependencies
[ffmpeg] / libavcodec / mediacodec_wrapper.c
index 546768f47737ec52c9979cbb9bc68851ab9131be..97e3a296466de44354d60a2a1cccb759f1767e68 100644 (file)
@@ -62,6 +62,10 @@ struct JNIAMediaCodecListFields {
     jfieldID avc_profile_high422_id;
     jfieldID avc_profile_high444_id;
 
+    jfieldID hevc_profile_main_id;
+    jfieldID hevc_profile_main10_id;
+    jfieldID hevc_profile_main10_hdr10_id;
+
 } JNIAMediaCodecListFields;
 
 static const struct FFJniField jni_amediacodeclist_mapping[] = {
@@ -94,6 +98,10 @@ static const struct FFJniField jni_amediacodeclist_mapping[] = {
         { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh422", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high422_id), 1 },
         { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh444", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high444_id), 1 },
 
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main_id), 0 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main10_id), 0 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain10HDR10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main10_hdr10_id), 0 },
+
     { NULL }
 };
 
@@ -283,44 +291,35 @@ struct FFAMediaCodec {
     int has_get_i_o_buffer;
 };
 
-#define JNI_ATTACH_ENV_OR_RETURN(env, attached, log_ctx, ret) do { \
-    (env) = ff_jni_attach_env(attached, log_ctx);                  \
+#define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do {              \
+    (env) = ff_jni_get_env(log_ctx);                               \
     if (!(env)) {                                                  \
         return ret;                                                \
     }                                                              \
 } while (0)
 
-#define JNI_ATTACH_ENV_OR_RETURN_VOID(env, attached, log_ctx) do { \
-    (env) = ff_jni_attach_env(attached, log_ctx);              \
+#define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do {              \
+    (env) = ff_jni_get_env(log_ctx);                               \
     if (!(env)) {                                                  \
         return;                                                    \
     }                                                              \
 } while (0)
 
-#define JNI_DETACH_ENV(attached, log_ctx) do { \
-    if (attached)                              \
-        ff_jni_detach_env(log_ctx);            \
-} while (0)
-
-
-
 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
 {
     int ret = -1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     struct JNIAMediaCodecListFields jfields = { 0 };
+    jfieldID field_id = 0;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, avctx, -1);
+    JNI_GET_ENV_OR_RETURN(env, avctx, -1);
 
     if (ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx) < 0) {
         goto done;
     }
 
     if (avctx->codec_id == AV_CODEC_ID_H264) {
-        jfieldID field_id = 0;
-
         switch(avctx->profile) {
         case FF_PROFILE_H264_BASELINE:
         case FF_PROFILE_H264_CONSTRAINED_BASELINE:
@@ -349,6 +348,17 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
             field_id = jfields.avc_profile_high444_id;
             break;
         }
+    } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
+        switch (avctx->profile) {
+        case FF_PROFILE_HEVC_MAIN:
+        case FF_PROFILE_HEVC_MAIN_STILL_PICTURE:
+            field_id = jfields.hevc_profile_main_id;
+            break;
+        case FF_PROFILE_HEVC_MAIN_10:
+            field_id = jfields.hevc_profile_main10_id;
+            break;
+        }
+    }
 
         if (field_id) {
             ret = (*env)->GetStaticIntField(env, jfields.codec_profile_level_class, field_id);
@@ -357,13 +367,10 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
                 goto done;
             }
         }
-    }
 
 done:
     ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx);
 
-    JNI_DETACH_ENV(attached, avctx);
-
     return ret;
 }
 
@@ -376,7 +383,6 @@ char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int e
     char *name = NULL;
     char *supported_type = NULL;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     struct JNIAMediaCodecListFields jfields = { 0 };
     struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
@@ -393,7 +399,7 @@ char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int e
     jobject profile_level = NULL;
     jobjectArray profile_levels = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, log_ctx, NULL);
+    JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL);
 
     if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
         goto done;
@@ -588,8 +594,6 @@ done:
     ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
     ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
 
-    JNI_DETACH_ENV(attached, log_ctx);
-
     if (!found_codec) {
         av_freep(&name);
     }
@@ -599,7 +603,6 @@ done:
 
 FFAMediaFormat *ff_AMediaFormat_new(void)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     FFAMediaFormat *format = NULL;
 
@@ -609,7 +612,7 @@ FFAMediaFormat *ff_AMediaFormat_new(void)
     }
     format->class = &amediaformat_class;
 
-    env = ff_jni_attach_env(&attached, format);
+    env = ff_jni_get_env(format);
     if (!env) {
         av_freep(&format);
         return NULL;
@@ -629,14 +632,10 @@ FFAMediaFormat *ff_AMediaFormat_new(void)
         goto fail;
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return format;
 fail:
     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
 
-    JNI_DETACH_ENV(attached, format);
-
     av_freep(&format);
 
     return NULL;
@@ -644,7 +643,6 @@ fail:
 
 static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     FFAMediaFormat *format = NULL;
 
@@ -654,7 +652,7 @@ static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
     }
     format->class = &amediaformat_class;
 
-    env = ff_jni_attach_env(&attached, format);
+    env = ff_jni_get_env(format);
     if (!env) {
         av_freep(&format);
         return NULL;
@@ -669,14 +667,10 @@ static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
         goto fail;
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return format;
 fail:
     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
 
-    JNI_DETACH_ENV(attached, format);
-
     av_freep(&format);
 
     return NULL;
@@ -686,22 +680,19 @@ int ff_AMediaFormat_delete(FFAMediaFormat* format)
 {
     int ret = 0;
 
-    int attached = 0;
     JNIEnv *env = NULL;
 
     if (!format) {
         return 0;
     }
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, format, AVERROR_EXTERNAL);
 
     (*env)->DeleteGlobalRef(env, format->object);
     format->object = NULL;
 
     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
 
-    JNI_DETACH_ENV(attached, format);
-
     av_freep(&format);
 
     return ret;
@@ -711,13 +702,12 @@ char* ff_AMediaFormat_toString(FFAMediaFormat* format)
 {
     char *ret = NULL;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring description = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, NULL);
+    JNI_GET_ENV_OR_RETURN(env, format, NULL);
 
     description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
     if (ff_jni_exception_check(env, 1, NULL) < 0) {
@@ -726,13 +716,10 @@ char* ff_AMediaFormat_toString(FFAMediaFormat* format)
 
     ret = ff_jni_jstring_to_utf_chars(env, description, format);
 fail:
-
     if (description) {
         (*env)->DeleteLocalRef(env, description);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
@@ -740,13 +727,12 @@ int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t *
 {
     int ret = 1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+    JNI_GET_ENV_OR_RETURN(env, format, 0);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -766,8 +752,6 @@ fail:
         (*env)->DeleteLocalRef(env, key);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
@@ -775,13 +759,12 @@ int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t *
 {
     int ret = 1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+    JNI_GET_ENV_OR_RETURN(env, format, 0);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -801,8 +784,6 @@ fail:
         (*env)->DeleteLocalRef(env, key);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
@@ -810,13 +791,12 @@ int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *ou
 {
     int ret = 1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+    JNI_GET_ENV_OR_RETURN(env, format, 0);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -836,8 +816,6 @@ fail:
         (*env)->DeleteLocalRef(env, key);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
@@ -845,14 +823,13 @@ int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** d
 {
     int ret = 1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
     jobject result = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+    JNI_GET_ENV_OR_RETURN(env, format, 0);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -890,8 +867,6 @@ fail:
         (*env)->DeleteLocalRef(env, result);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
@@ -899,14 +874,13 @@ int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const ch
 {
     int ret = 1;
 
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
     jstring result = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+    JNI_GET_ENV_OR_RETURN(env, format, 0);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -936,20 +910,17 @@ fail:
         (*env)->DeleteLocalRef(env, result);
     }
 
-    JNI_DETACH_ENV(attached, format);
-
     return ret;
 }
 
 void ff_AMediaFormat_setInt32(FFAMediaFormat* format, const char* name, int32_t value)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+    JNI_GET_ENV_OR_RETURN_VOID(env, format);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -965,19 +936,16 @@ fail:
     if (key) {
         (*env)->DeleteLocalRef(env, key);
     }
-
-    JNI_DETACH_ENV(attached, format);
 }
 
 void ff_AMediaFormat_setInt64(FFAMediaFormat* format, const char* name, int64_t value)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+    JNI_GET_ENV_OR_RETURN_VOID(env, format);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -993,19 +961,16 @@ fail:
     if (key) {
         (*env)->DeleteLocalRef(env, key);
     }
-
-    JNI_DETACH_ENV(attached, NULL);
 }
 
 void ff_AMediaFormat_setFloat(FFAMediaFormat* format, const char* name, float value)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+    JNI_GET_ENV_OR_RETURN_VOID(env, format);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -1021,20 +986,17 @@ fail:
     if (key) {
         (*env)->DeleteLocalRef(env, key);
     }
-
-    JNI_DETACH_ENV(attached, NULL);
 }
 
 void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
     jstring string = NULL;
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+    JNI_GET_ENV_OR_RETURN_VOID(env, format);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -1059,13 +1021,10 @@ fail:
     if (string) {
         (*env)->DeleteLocalRef(env, string);
     }
-
-    JNI_DETACH_ENV(attached, format);
 }
 
 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     jstring key = NULL;
     jobject buffer = NULL;
@@ -1073,7 +1032,7 @@ void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* d
 
     av_assert0(format != NULL);
 
-    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+    JNI_GET_ENV_OR_RETURN_VOID(env, format);
 
     key = ff_jni_utf_chars_to_jstring(env, name, format);
     if (!key) {
@@ -1109,17 +1068,14 @@ fail:
     if (buffer) {
         (*env)->DeleteLocalRef(env, buffer);
     }
-
-    JNI_DETACH_ENV(attached, format);
 }
 
 static int codec_init_static_fields(FFAMediaCodec *codec)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
@@ -1164,14 +1120,12 @@ static int codec_init_static_fields(FFAMediaCodec *codec)
     }
 
 fail:
-    JNI_DETACH_ENV(attached, NULL);
 
     return ret;
 }
 
 FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     FFAMediaCodec *codec = NULL;
     jstring codec_name = NULL;
@@ -1182,7 +1136,7 @@ FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
     }
     codec->class = &amediacodec_class;
 
-    env = ff_jni_attach_env(&attached, codec);
+    env = ff_jni_get_env(codec);
     if (!env) {
         av_freep(&codec);
         return NULL;
@@ -1215,8 +1169,6 @@ FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
         codec->has_get_i_o_buffer = 1;
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     return codec;
 fail:
     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
@@ -1225,8 +1177,6 @@ fail:
         (*env)->DeleteLocalRef(env, codec_name);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     av_freep(&codec);
 
     return NULL;
@@ -1234,7 +1184,6 @@ fail:
 
 FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     FFAMediaCodec *codec = NULL;
     jstring mime_type = NULL;
@@ -1245,7 +1194,7 @@ FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
     }
     codec->class = &amediacodec_class;
 
-    env = ff_jni_attach_env(&attached, codec);
+    env = ff_jni_get_env(codec);
     if (!env) {
         av_freep(&codec);
         return NULL;
@@ -1278,8 +1227,6 @@ FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
         codec->has_get_i_o_buffer = 1;
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     return codec;
 fail:
     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
@@ -1288,8 +1235,6 @@ fail:
         (*env)->DeleteLocalRef(env, mime_type);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     av_freep(&codec);
 
     return NULL;
@@ -1297,7 +1242,6 @@ fail:
 
 FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
 {
-    int attached = 0;
     JNIEnv *env = NULL;
     FFAMediaCodec *codec = NULL;
     jstring mime_type = NULL;
@@ -1308,7 +1252,7 @@ FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
     }
     codec->class = &amediacodec_class;
 
-    env = ff_jni_attach_env(&attached, codec);
+    env = ff_jni_get_env(codec);
     if (!env) {
         av_freep(&codec);
         return NULL;
@@ -1341,8 +1285,6 @@ FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
         codec->has_get_i_o_buffer = 1;
     }
 
-    JNI_DETACH_ENV(attached, NULL);
-
     return codec;
 fail:
     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
@@ -1351,8 +1293,6 @@ fail:
         (*env)->DeleteLocalRef(env, mime_type);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     av_freep(&codec);
 
     return NULL;
@@ -1362,14 +1302,13 @@ int ff_AMediaCodec_delete(FFAMediaCodec* codec)
 {
     int ret = 0;
 
-    int attached = 0;
     JNIEnv *env = NULL;
 
     if (!codec) {
         return 0;
     }
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1381,8 +1320,6 @@ int ff_AMediaCodec_delete(FFAMediaCodec* codec)
 
     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
 
-    JNI_DETACH_ENV(attached, codec);
-
     av_freep(&codec);
 
     return ret;
@@ -1391,11 +1328,10 @@ int ff_AMediaCodec_delete(FFAMediaCodec* codec)
 char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
 {
     char *ret = NULL;
-    int attached = 0;
     JNIEnv *env = NULL;
     jobject *name = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+    JNI_GET_ENV_OR_RETURN(env, codec, NULL);
 
     name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1405,41 +1341,32 @@ char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
     ret = ff_jni_jstring_to_utf_chars(env, name, codec);
 
 fail:
-    JNI_DETACH_ENV(attached, NULL);
-
     return ret;
 }
 
 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    /* TODO: implement surface handling */
-    av_assert0(surface == NULL);
-
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
-    (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags);
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
         ret = AVERROR_EXTERNAL;
         goto fail;
     }
 
 fail:
-    JNI_DETACH_ENV(attached, NULL);
-
     return ret;
 }
 
 int ff_AMediaCodec_start(FFAMediaCodec* codec)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1448,18 +1375,15 @@ int ff_AMediaCodec_start(FFAMediaCodec* codec)
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 int ff_AMediaCodec_stop(FFAMediaCodec* codec)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1468,18 +1392,15 @@ int ff_AMediaCodec_stop(FFAMediaCodec* codec)
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 int ff_AMediaCodec_flush(FFAMediaCodec* codec)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1488,18 +1409,15 @@ int ff_AMediaCodec_flush(FFAMediaCodec* codec)
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1508,18 +1426,15 @@ int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int ren
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1528,18 +1443,15 @@ int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, i
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1548,18 +1460,15 @@ ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutU
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
@@ -1568,20 +1477,17 @@ int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offs
     }
 
 fail:
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
 {
     int ret = 0;
-    int attached = 0;
     JNIEnv *env = NULL;
 
     jobject mediainfo = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+    JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
     mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1623,20 +1529,17 @@ fail:
         (*env)->DeleteLocalRef(env, mediainfo);
     }
 
-    JNI_DETACH_ENV(attached, NULL);
-
     return ret;
 }
 
 uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
 {
     uint8_t *ret = NULL;
-    int attached = 0;
     JNIEnv *env = NULL;
 
     jobject buffer = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+    JNI_GET_ENV_OR_RETURN(env, codec, NULL);
 
     if (codec->has_get_i_o_buffer) {
         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
@@ -1669,20 +1572,17 @@ fail:
         (*env)->DeleteLocalRef(env, buffer);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
 {
     uint8_t *ret = NULL;
-    int attached = 0;
     JNIEnv *env = NULL;
 
     jobject buffer = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+    JNI_GET_ENV_OR_RETURN(env, codec, NULL);
 
     if (codec->has_get_i_o_buffer) {
         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
@@ -1715,20 +1615,17 @@ fail:
         (*env)->DeleteLocalRef(env, buffer);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
 FFAMediaFormat* ff_AMediaCodec_getOutputFormat(FFAMediaCodec* codec)
 {
     FFAMediaFormat *ret = NULL;
-    int attached = 0;
     JNIEnv *env = NULL;
 
     jobject mediaformat = NULL;
 
-    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+    JNI_GET_ENV_OR_RETURN(env, codec, NULL);
 
     mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
@@ -1741,8 +1638,6 @@ fail:
         (*env)->DeleteLocalRef(env, mediaformat);
     }
 
-    JNI_DETACH_ENV(attached, codec);
-
     return ret;
 }
 
@@ -1787,10 +1682,9 @@ int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
 
     if (!codec->has_get_i_o_buffer) {
         if (codec->output_buffers) {
-            int attached = 0;
             JNIEnv *env = NULL;
 
-            env = ff_jni_attach_env(&attached, codec);
+            env = ff_jni_get_env(codec);
             if (!env) {
                 ret = AVERROR_EXTERNAL;
                 goto fail;
@@ -1798,8 +1692,6 @@ int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
 
             (*env)->DeleteGlobalRef(env, codec->output_buffers);
             codec->output_buffers = NULL;
-
-            JNI_DETACH_ENV(attached, codec);
         }
     }