mediacodec_wrapper.c (89030B)
1 /* 2 * Android MediaCodec Wrapper 3 * 4 * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com> 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 #include <dlfcn.h> 24 #include <jni.h> 25 #include <stdbool.h> 26 #include <media/NdkMediaFormat.h> 27 #include <media/NdkMediaCodec.h> 28 #include <android/native_window_jni.h> 29 30 #include "libavutil/avassert.h" 31 #include "libavutil/mem.h" 32 #include "libavutil/avstring.h" 33 34 #include "avcodec.h" 35 #include "ffjni.h" 36 #include "mediacodec_wrapper.h" 37 38 struct JNIAMediaCodecListFields { 39 40 jclass mediacodec_list_class; 41 jmethodID init_id; 42 jmethodID find_decoder_for_format_id; 43 44 jmethodID get_codec_count_id; 45 jmethodID get_codec_info_at_id; 46 47 jclass mediacodec_info_class; 48 jmethodID get_name_id; 49 jmethodID get_codec_capabilities_id; 50 jmethodID get_supported_types_id; 51 jmethodID is_encoder_id; 52 jmethodID is_software_only_id; 53 54 jclass codec_capabilities_class; 55 jfieldID color_formats_id; 56 jfieldID profile_levels_id; 57 58 jclass codec_profile_level_class; 59 jfieldID profile_id; 60 jfieldID level_id; 61 }; 62 63 #define OFFSET(x) offsetof(struct JNIAMediaCodecListFields, x) 64 static const struct FFJniField jni_amediacodeclist_mapping[] = { 65 { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, OFFSET(mediacodec_list_class), 1 }, 66 { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, OFFSET(init_id), 0 }, 67 { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, OFFSET(find_decoder_for_format_id), 0 }, 68 69 { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, OFFSET(get_codec_count_id), 1 }, 70 { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, OFFSET(get_codec_info_at_id), 1 }, 71 72 { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, OFFSET(mediacodec_info_class), 1 }, 73 { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, OFFSET(get_name_id), 1 }, 74 { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, OFFSET(get_codec_capabilities_id), 1 }, 75 { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, OFFSET(get_supported_types_id), 1 }, 76 { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, OFFSET(is_encoder_id), 1 }, 77 { "android/media/MediaCodecInfo", "isSoftwareOnly", "()Z", FF_JNI_METHOD, OFFSET(is_software_only_id), 0 }, 78 79 { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, OFFSET(codec_capabilities_class), 1 }, 80 { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, OFFSET(color_formats_id), 1 }, 81 { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD, OFFSET(profile_levels_id), 1 }, 82 83 { "android/media/MediaCodecInfo$CodecProfileLevel", NULL, NULL, FF_JNI_CLASS, OFFSET(codec_profile_level_class), 1 }, 84 { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD, OFFSET(profile_id), 1 }, 85 { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD, OFFSET(level_id), 1 }, 86 87 { NULL } 88 }; 89 #undef OFFSET 90 91 struct JNIAMediaFormatFields { 92 93 jclass mediaformat_class; 94 95 jmethodID init_id; 96 97 jmethodID contains_key_id; 98 99 jmethodID get_integer_id; 100 jmethodID get_long_id; 101 jmethodID get_float_id; 102 jmethodID get_bytebuffer_id; 103 jmethodID get_string_id; 104 105 jmethodID set_integer_id; 106 jmethodID set_long_id; 107 jmethodID set_float_id; 108 jmethodID set_bytebuffer_id; 109 jmethodID set_string_id; 110 111 jmethodID to_string_id; 112 113 }; 114 115 #define OFFSET(x) offsetof(struct JNIAMediaFormatFields, x) 116 static const struct FFJniField jni_amediaformat_mapping[] = { 117 { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, OFFSET(mediaformat_class), 1 }, 118 119 { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, OFFSET(init_id), 1 }, 120 121 { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD, OFFSET(contains_key_id), 1 }, 122 123 { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, OFFSET(get_integer_id), 1 }, 124 { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, OFFSET(get_long_id), 1 }, 125 { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, OFFSET(get_float_id), 1 }, 126 { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, OFFSET(get_bytebuffer_id), 1 }, 127 { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, OFFSET(get_string_id), 1 }, 128 129 { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, OFFSET(set_integer_id), 1 }, 130 { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, OFFSET(set_long_id), 1 }, 131 { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, OFFSET(set_float_id), 1 }, 132 { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, OFFSET(set_bytebuffer_id), 1 }, 133 { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, OFFSET(set_string_id), 1 }, 134 135 { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, OFFSET(to_string_id), 1 }, 136 137 { NULL } 138 }; 139 #undef OFFSET 140 141 static const AVClass amediaformat_class = { 142 .class_name = "amediaformat", 143 .item_name = av_default_item_name, 144 .version = LIBAVUTIL_VERSION_INT, 145 }; 146 147 typedef struct FFAMediaFormatJni { 148 FFAMediaFormat api; 149 150 struct JNIAMediaFormatFields jfields; 151 jobject object; 152 } FFAMediaFormatJni; 153 154 static const FFAMediaFormat media_format_jni; 155 156 struct JNIAMediaCodecFields { 157 158 jclass mediacodec_class; 159 160 jfieldID info_try_again_later_id; 161 jfieldID info_output_buffers_changed_id; 162 jfieldID info_output_format_changed_id; 163 164 jfieldID buffer_flag_codec_config_id; 165 jfieldID buffer_flag_end_of_stream_id; 166 jfieldID buffer_flag_key_frame_id; 167 168 jfieldID configure_flag_encode_id; 169 170 jmethodID create_by_codec_name_id; 171 jmethodID create_decoder_by_type_id; 172 jmethodID create_encoder_by_type_id; 173 174 jmethodID get_name_id; 175 176 jmethodID configure_id; 177 jmethodID start_id; 178 jmethodID flush_id; 179 jmethodID stop_id; 180 jmethodID release_id; 181 182 jmethodID get_output_format_id; 183 184 jmethodID dequeue_input_buffer_id; 185 jmethodID queue_input_buffer_id; 186 jmethodID get_input_buffer_id; 187 jmethodID get_input_buffers_id; 188 189 jmethodID dequeue_output_buffer_id; 190 jmethodID get_output_buffer_id; 191 jmethodID get_output_buffers_id; 192 jmethodID release_output_buffer_id; 193 jmethodID release_output_buffer_at_time_id; 194 195 jmethodID set_input_surface_id; 196 jmethodID signal_end_of_input_stream_id; 197 198 jclass mediainfo_class; 199 200 jmethodID init_id; 201 202 jfieldID flags_id; 203 jfieldID offset_id; 204 jfieldID presentation_time_us_id; 205 jfieldID size_id; 206 207 }; 208 209 #define OFFSET(x) offsetof(struct JNIAMediaCodecFields, x) 210 static const struct FFJniField jni_amediacodec_mapping[] = { 211 { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, OFFSET(mediacodec_class), 1 }, 212 213 { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, OFFSET(info_try_again_later_id), 1 }, 214 { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, OFFSET(info_output_buffers_changed_id), 1 }, 215 { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, OFFSET(info_output_format_changed_id), 1 }, 216 217 { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, OFFSET(buffer_flag_codec_config_id), 1 }, 218 { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, OFFSET(buffer_flag_end_of_stream_id), 1 }, 219 { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, OFFSET(buffer_flag_key_frame_id), 0 }, 220 221 { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, OFFSET(configure_flag_encode_id), 1 }, 222 223 { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, OFFSET(create_by_codec_name_id), 1 }, 224 { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, OFFSET(create_decoder_by_type_id), 1 }, 225 { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, OFFSET(create_encoder_by_type_id), 1 }, 226 227 { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, OFFSET(get_name_id), 1 }, 228 229 { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, OFFSET(configure_id), 1 }, 230 { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, OFFSET(start_id), 1 }, 231 { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, OFFSET(flush_id), 1 }, 232 { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, OFFSET(stop_id), 1 }, 233 { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, OFFSET(release_id), 1 }, 234 235 { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, OFFSET(get_output_format_id), 1 }, 236 237 { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, OFFSET(dequeue_input_buffer_id), 1 }, 238 { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, OFFSET(queue_input_buffer_id), 1 }, 239 { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, OFFSET(get_input_buffer_id), 0 }, 240 { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, OFFSET(get_input_buffers_id), 1 }, 241 242 { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, OFFSET(dequeue_output_buffer_id), 1 }, 243 { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, OFFSET(get_output_buffer_id), 0 }, 244 { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, OFFSET(get_output_buffers_id), 1 }, 245 { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, OFFSET(release_output_buffer_id), 1 }, 246 { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, OFFSET(release_output_buffer_at_time_id), 0 }, 247 248 { "android/media/MediaCodec", "setInputSurface", "(Landroid/view/Surface;)V", FF_JNI_METHOD, OFFSET(set_input_surface_id), 0 }, 249 { "android/media/MediaCodec", "signalEndOfInputStream", "()V", FF_JNI_METHOD, OFFSET(signal_end_of_input_stream_id), 0 }, 250 251 { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, OFFSET(mediainfo_class), 1 }, 252 253 { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, OFFSET(init_id), 1 }, 254 { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, OFFSET(flags_id), 1 }, 255 { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, OFFSET(offset_id), 1 }, 256 { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, OFFSET(presentation_time_us_id), 1 }, 257 { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, OFFSET(size_id), 1 }, 258 259 { NULL } 260 }; 261 #undef OFFSET 262 263 static const AVClass amediacodec_class = { 264 .class_name = "amediacodec", 265 .item_name = av_default_item_name, 266 .version = LIBAVUTIL_VERSION_INT, 267 }; 268 269 typedef struct FFAMediaCodecJni { 270 FFAMediaCodec api; 271 272 struct JNIAMediaCodecFields jfields; 273 274 jobject object; 275 jobject buffer_info; 276 277 jobject input_buffers; 278 jobject output_buffers; 279 280 int INFO_TRY_AGAIN_LATER; 281 int INFO_OUTPUT_BUFFERS_CHANGED; 282 int INFO_OUTPUT_FORMAT_CHANGED; 283 284 int BUFFER_FLAG_CODEC_CONFIG; 285 int BUFFER_FLAG_END_OF_STREAM; 286 int BUFFER_FLAG_KEY_FRAME; 287 288 int CONFIGURE_FLAG_ENCODE; 289 290 int has_get_i_o_buffer; 291 } FFAMediaCodecJni; 292 293 static const FFAMediaCodec media_codec_jni; 294 295 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \ 296 (env) = ff_jni_get_env(log_ctx); \ 297 if (!(env)) { \ 298 return ret; \ 299 } \ 300 } while (0) 301 302 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do { \ 303 (env) = ff_jni_get_env(log_ctx); \ 304 if (!(env)) { \ 305 return; \ 306 } \ 307 } while (0) 308 309 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) 310 { 311 // Copy and modified from MediaCodecInfo.java 312 static const int AVCProfileBaseline = 0x01; 313 static const int AVCProfileMain = 0x02; 314 static const int AVCProfileExtended = 0x04; 315 static const int AVCProfileHigh = 0x08; 316 static const int AVCProfileHigh10 = 0x10; 317 static const int AVCProfileHigh422 = 0x20; 318 static const int AVCProfileHigh444 = 0x40; 319 static const int AVCProfileConstrainedBaseline = 0x10000; 320 static const int AVCProfileConstrainedHigh = 0x80000; 321 322 static const int HEVCProfileMain = 0x01; 323 static const int HEVCProfileMain10 = 0x02; 324 static const int HEVCProfileMainStill = 0x04; 325 static const int HEVCProfileMain10HDR10 = 0x1000; 326 static const int HEVCProfileMain10HDR10Plus = 0x2000; 327 328 static const int VP9Profile0 = 0x01; 329 static const int VP9Profile1 = 0x02; 330 static const int VP9Profile2 = 0x04; 331 static const int VP9Profile3 = 0x08; 332 static const int VP9Profile2HDR = 0x1000; 333 static const int VP9Profile3HDR = 0x2000; 334 static const int VP9Profile2HDR10Plus = 0x4000; 335 static const int VP9Profile3HDR10Plus = 0x8000; 336 337 static const int MPEG4ProfileSimple = 0x01; 338 static const int MPEG4ProfileSimpleScalable = 0x02; 339 static const int MPEG4ProfileCore = 0x04; 340 static const int MPEG4ProfileMain = 0x08; 341 static const int MPEG4ProfileNbit = 0x10; 342 static const int MPEG4ProfileScalableTexture = 0x20; 343 static const int MPEG4ProfileSimpleFBA = 0x80; 344 static const int MPEG4ProfileSimpleFace = 0x40; 345 static const int MPEG4ProfileBasicAnimated = 0x100; 346 static const int MPEG4ProfileHybrid = 0x200; 347 static const int MPEG4ProfileAdvancedRealTime = 0x400; 348 static const int MPEG4ProfileCoreScalable = 0x800; 349 static const int MPEG4ProfileAdvancedCoding = 0x1000; 350 static const int MPEG4ProfileAdvancedCore = 0x2000; 351 static const int MPEG4ProfileAdvancedScalable = 0x4000; 352 static const int MPEG4ProfileAdvancedSimple = 0x8000; 353 354 355 static const int AV1ProfileMain8 = 0x1; 356 static const int AV1ProfileMain10 = 0x2; 357 static const int AV1ProfileMain10HDR10 = 0x1000; 358 static const int AV1ProfileMain10HDR10Plus = 0x2000; 359 360 // Unused yet. 361 (void)AVCProfileConstrainedHigh; 362 (void)HEVCProfileMain10HDR10; 363 (void)HEVCProfileMain10HDR10Plus; 364 (void)VP9Profile2HDR; 365 (void)VP9Profile3HDR; 366 (void)VP9Profile2HDR10Plus; 367 (void)VP9Profile3HDR10Plus; 368 (void)MPEG4ProfileSimpleFace; 369 (void)AV1ProfileMain10; 370 (void)AV1ProfileMain10HDR10; 371 (void)AV1ProfileMain10HDR10Plus; 372 373 if (avctx->codec_id == AV_CODEC_ID_H264) { 374 switch(avctx->profile) { 375 case AV_PROFILE_H264_BASELINE: 376 return AVCProfileBaseline; 377 case AV_PROFILE_H264_CONSTRAINED_BASELINE: 378 return AVCProfileConstrainedBaseline; 379 case AV_PROFILE_H264_MAIN: 380 return AVCProfileMain; 381 break; 382 case AV_PROFILE_H264_EXTENDED: 383 return AVCProfileExtended; 384 case AV_PROFILE_H264_HIGH: 385 return AVCProfileHigh; 386 case AV_PROFILE_H264_HIGH_10: 387 case AV_PROFILE_H264_HIGH_10_INTRA: 388 return AVCProfileHigh10; 389 case AV_PROFILE_H264_HIGH_422: 390 case AV_PROFILE_H264_HIGH_422_INTRA: 391 return AVCProfileHigh422; 392 case AV_PROFILE_H264_HIGH_444: 393 case AV_PROFILE_H264_HIGH_444_INTRA: 394 case AV_PROFILE_H264_HIGH_444_PREDICTIVE: 395 return AVCProfileHigh444; 396 } 397 } else if (avctx->codec_id == AV_CODEC_ID_HEVC) { 398 switch (avctx->profile) { 399 case AV_PROFILE_HEVC_MAIN: 400 return HEVCProfileMain; 401 case AV_PROFILE_HEVC_MAIN_STILL_PICTURE: 402 return HEVCProfileMainStill; 403 case AV_PROFILE_HEVC_MAIN_10: 404 return HEVCProfileMain10; 405 } 406 } else if (avctx->codec_id == AV_CODEC_ID_VP9) { 407 switch (avctx->profile) { 408 case AV_PROFILE_VP9_0: 409 return VP9Profile0; 410 case AV_PROFILE_VP9_1: 411 return VP9Profile1; 412 case AV_PROFILE_VP9_2: 413 return VP9Profile2; 414 case AV_PROFILE_VP9_3: 415 return VP9Profile3; 416 } 417 } else if(avctx->codec_id == AV_CODEC_ID_MPEG4) { 418 switch (avctx->profile) 419 { 420 case AV_PROFILE_MPEG4_SIMPLE: 421 return MPEG4ProfileSimple; 422 case AV_PROFILE_MPEG4_SIMPLE_SCALABLE: 423 return MPEG4ProfileSimpleScalable; 424 case AV_PROFILE_MPEG4_CORE: 425 return MPEG4ProfileCore; 426 case AV_PROFILE_MPEG4_MAIN: 427 return MPEG4ProfileMain; 428 case AV_PROFILE_MPEG4_N_BIT: 429 return MPEG4ProfileNbit; 430 case AV_PROFILE_MPEG4_SCALABLE_TEXTURE: 431 return MPEG4ProfileScalableTexture; 432 case AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION: 433 return MPEG4ProfileSimpleFBA; 434 case AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE: 435 return MPEG4ProfileBasicAnimated; 436 case AV_PROFILE_MPEG4_HYBRID: 437 return MPEG4ProfileHybrid; 438 case AV_PROFILE_MPEG4_ADVANCED_REAL_TIME: 439 return MPEG4ProfileAdvancedRealTime; 440 case AV_PROFILE_MPEG4_CORE_SCALABLE: 441 return MPEG4ProfileCoreScalable; 442 case AV_PROFILE_MPEG4_ADVANCED_CODING: 443 return MPEG4ProfileAdvancedCoding; 444 case AV_PROFILE_MPEG4_ADVANCED_CORE: 445 return MPEG4ProfileAdvancedCore; 446 case AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE: 447 return MPEG4ProfileAdvancedScalable; 448 case AV_PROFILE_MPEG4_ADVANCED_SIMPLE: 449 return MPEG4ProfileAdvancedSimple; 450 case AV_PROFILE_MPEG4_SIMPLE_STUDIO: 451 // Studio profiles are not supported by mediacodec. 452 default: 453 break; 454 } 455 } else if(avctx->codec_id == AV_CODEC_ID_AV1) { 456 switch (avctx->profile) 457 { 458 case AV_PROFILE_AV1_MAIN: 459 return AV1ProfileMain8; 460 case AV_PROFILE_AV1_HIGH: 461 case AV_PROFILE_AV1_PROFESSIONAL: 462 default: 463 break; 464 } 465 } 466 467 return -1; 468 } 469 470 char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx) 471 { 472 int ret; 473 int i; 474 int codec_count; 475 int found_codec = 0; 476 char *name = NULL; 477 char *supported_type = NULL; 478 479 JNIEnv *env = NULL; 480 struct JNIAMediaCodecListFields jfields = { 0 }; 481 struct JNIAMediaFormatFields mediaformat_jfields = { 0 }; 482 483 jobject codec_name = NULL; 484 485 jobject info = NULL; 486 jobject type = NULL; 487 jobjectArray types = NULL; 488 489 jobject capabilities = NULL; 490 jobject profile_level = NULL; 491 jobjectArray profile_levels = NULL; 492 493 JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL); 494 495 if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) { 496 goto done; 497 } 498 499 if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) { 500 goto done; 501 } 502 503 codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id); 504 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 505 goto done; 506 } 507 508 for(i = 0; i < codec_count; i++) { 509 int j; 510 int type_count; 511 int is_encoder; 512 513 info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i); 514 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 515 goto done; 516 } 517 518 types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id); 519 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 520 goto done; 521 } 522 523 is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id); 524 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 525 goto done; 526 } 527 528 if (is_encoder != encoder) { 529 goto done_with_info; 530 } 531 532 if (jfields.is_software_only_id) { 533 int is_software_only = (*env)->CallBooleanMethod(env, info, jfields.is_software_only_id); 534 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 535 goto done; 536 } 537 538 if (is_software_only) { 539 goto done_with_info; 540 } 541 } 542 543 codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id); 544 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 545 goto done; 546 } 547 548 name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx); 549 if (!name) { 550 goto done; 551 } 552 553 (*env)->DeleteLocalRef(env, codec_name); 554 codec_name = NULL; 555 556 /* Skip software decoders */ 557 if ( 558 strstr(name, "OMX.google") || 559 strstr(name, "OMX.ffmpeg") || 560 (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) || 561 !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) { 562 goto done_with_info; 563 } 564 565 type_count = (*env)->GetArrayLength(env, types); 566 for (j = 0; j < type_count; j++) { 567 int k; 568 int profile_count; 569 570 type = (*env)->GetObjectArrayElement(env, types, j); 571 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 572 goto done; 573 } 574 575 supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx); 576 if (!supported_type) { 577 goto done; 578 } 579 580 if (av_strcasecmp(supported_type, mime)) { 581 goto done_with_type; 582 } 583 584 capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type); 585 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 586 goto done; 587 } 588 589 profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id); 590 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 591 goto done; 592 } 593 594 profile_count = (*env)->GetArrayLength(env, profile_levels); 595 if (!profile_count) { 596 found_codec = 1; 597 } 598 for (k = 0; k < profile_count; k++) { 599 int supported_profile = 0; 600 601 if (profile < 0) { 602 found_codec = 1; 603 break; 604 } 605 606 profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k); 607 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 608 goto done; 609 } 610 611 supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id); 612 if (ff_jni_exception_check(env, 1, log_ctx) < 0) { 613 goto done; 614 } 615 616 found_codec = profile == supported_profile; 617 618 (*env)->DeleteLocalRef(env, profile_level); 619 profile_level = NULL; 620 621 if (found_codec) { 622 break; 623 } 624 } 625 626 done_with_type: 627 (*env)->DeleteLocalRef(env, profile_levels); 628 profile_levels = NULL; 629 630 (*env)->DeleteLocalRef(env, capabilities); 631 capabilities = NULL; 632 633 (*env)->DeleteLocalRef(env, type); 634 type = NULL; 635 636 av_freep(&supported_type); 637 638 if (found_codec) { 639 break; 640 } 641 } 642 643 done_with_info: 644 (*env)->DeleteLocalRef(env, info); 645 info = NULL; 646 647 (*env)->DeleteLocalRef(env, types); 648 types = NULL; 649 650 if (found_codec) { 651 break; 652 } 653 654 av_freep(&name); 655 } 656 657 done: 658 (*env)->DeleteLocalRef(env, codec_name); 659 (*env)->DeleteLocalRef(env, info); 660 (*env)->DeleteLocalRef(env, type); 661 (*env)->DeleteLocalRef(env, types); 662 (*env)->DeleteLocalRef(env, capabilities); 663 (*env)->DeleteLocalRef(env, profile_level); 664 (*env)->DeleteLocalRef(env, profile_levels); 665 666 av_freep(&supported_type); 667 668 ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx); 669 ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx); 670 671 if (!found_codec) { 672 av_freep(&name); 673 } 674 675 return name; 676 } 677 678 static FFAMediaFormat *mediaformat_jni_new(void) 679 { 680 JNIEnv *env = NULL; 681 FFAMediaFormatJni *format = NULL; 682 jobject object = NULL; 683 684 format = av_mallocz(sizeof(*format)); 685 if (!format) { 686 return NULL; 687 } 688 format->api = media_format_jni; 689 690 env = ff_jni_get_env(format); 691 if (!env) { 692 av_freep(&format); 693 return NULL; 694 } 695 696 if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) { 697 goto fail; 698 } 699 700 object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id); 701 if (!object) { 702 goto fail; 703 } 704 705 format->object = (*env)->NewGlobalRef(env, object); 706 if (!format->object) { 707 goto fail; 708 } 709 710 fail: 711 (*env)->DeleteLocalRef(env, object); 712 713 if (!format->object) { 714 ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format); 715 av_freep(&format); 716 } 717 718 return (FFAMediaFormat *)format; 719 } 720 721 static FFAMediaFormat *mediaformat_jni_newFromObject(void *object) 722 { 723 JNIEnv *env = NULL; 724 FFAMediaFormatJni *format = NULL; 725 726 format = av_mallocz(sizeof(*format)); 727 if (!format) { 728 return NULL; 729 } 730 format->api = media_format_jni; 731 732 env = ff_jni_get_env(format); 733 if (!env) { 734 av_freep(&format); 735 return NULL; 736 } 737 738 if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) { 739 goto fail; 740 } 741 742 format->object = (*env)->NewGlobalRef(env, object); 743 if (!format->object) { 744 goto fail; 745 } 746 747 return (FFAMediaFormat *)format; 748 fail: 749 ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format); 750 751 av_freep(&format); 752 753 return NULL; 754 } 755 756 static int mediaformat_jni_delete(FFAMediaFormat* ctx) 757 { 758 int ret = 0; 759 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 760 JNIEnv *env = NULL; 761 762 if (!format) { 763 return 0; 764 } 765 766 JNI_GET_ENV_OR_RETURN(env, format, AVERROR_EXTERNAL); 767 768 (*env)->DeleteGlobalRef(env, format->object); 769 format->object = NULL; 770 771 ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format); 772 773 av_freep(&format); 774 775 return ret; 776 } 777 778 static char* mediaformat_jni_toString(FFAMediaFormat* ctx) 779 { 780 char *ret = NULL; 781 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 782 JNIEnv *env = NULL; 783 jstring description = NULL; 784 785 av_assert0(format != NULL); 786 787 JNI_GET_ENV_OR_RETURN(env, format, NULL); 788 789 description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id); 790 if (ff_jni_exception_check(env, 1, NULL) < 0) { 791 goto fail; 792 } 793 794 ret = ff_jni_jstring_to_utf_chars(env, description, format); 795 fail: 796 (*env)->DeleteLocalRef(env, description); 797 798 return ret; 799 } 800 801 static int mediaformat_jni_getInt32(FFAMediaFormat* ctx, const char *name, int32_t *out) 802 { 803 int ret = 1; 804 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 805 JNIEnv *env = NULL; 806 jstring key = NULL; 807 jboolean contains_key; 808 809 av_assert0(format != NULL); 810 811 JNI_GET_ENV_OR_RETURN(env, format, 0); 812 813 key = ff_jni_utf_chars_to_jstring(env, name, format); 814 if (!key) { 815 ret = 0; 816 goto fail; 817 } 818 819 contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); 820 if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { 821 ret = 0; 822 goto fail; 823 } 824 825 *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key); 826 if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { 827 ret = 0; 828 goto fail; 829 } 830 831 ret = 1; 832 fail: 833 (*env)->DeleteLocalRef(env, key); 834 835 return ret; 836 } 837 838 static int mediaformat_jni_getInt64(FFAMediaFormat* ctx, const char *name, int64_t *out) 839 { 840 int ret = 1; 841 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 842 JNIEnv *env = NULL; 843 jstring key = NULL; 844 jboolean contains_key; 845 846 av_assert0(format != NULL); 847 848 JNI_GET_ENV_OR_RETURN(env, format, 0); 849 850 key = ff_jni_utf_chars_to_jstring(env, name, format); 851 if (!key) { 852 ret = 0; 853 goto fail; 854 } 855 856 contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); 857 if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { 858 ret = 0; 859 goto fail; 860 } 861 862 *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key); 863 if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { 864 ret = 0; 865 goto fail; 866 } 867 868 ret = 1; 869 fail: 870 (*env)->DeleteLocalRef(env, key); 871 872 return ret; 873 } 874 875 static int mediaformat_jni_getFloat(FFAMediaFormat* ctx, const char *name, float *out) 876 { 877 int ret = 1; 878 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 879 JNIEnv *env = NULL; 880 jstring key = NULL; 881 jboolean contains_key; 882 883 av_assert0(format != NULL); 884 885 JNI_GET_ENV_OR_RETURN(env, format, 0); 886 887 key = ff_jni_utf_chars_to_jstring(env, name, format); 888 if (!key) { 889 ret = 0; 890 goto fail; 891 } 892 893 contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); 894 if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { 895 ret = 0; 896 goto fail; 897 } 898 899 *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key); 900 if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { 901 ret = 0; 902 goto fail; 903 } 904 905 ret = 1; 906 fail: 907 (*env)->DeleteLocalRef(env, key); 908 909 return ret; 910 } 911 912 static int mediaformat_jni_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size) 913 { 914 int ret = 1; 915 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 916 JNIEnv *env = NULL; 917 jstring key = NULL; 918 jboolean contains_key; 919 jobject result = NULL; 920 921 av_assert0(format != NULL); 922 923 JNI_GET_ENV_OR_RETURN(env, format, 0); 924 925 key = ff_jni_utf_chars_to_jstring(env, name, format); 926 if (!key) { 927 ret = 0; 928 goto fail; 929 } 930 931 contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); 932 if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { 933 ret = 0; 934 goto fail; 935 } 936 937 result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key); 938 if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { 939 ret = 0; 940 goto fail; 941 } 942 943 *data = (*env)->GetDirectBufferAddress(env, result); 944 *size = (*env)->GetDirectBufferCapacity(env, result); 945 946 if (*data && *size) { 947 void *src = *data; 948 *data = av_malloc(*size); 949 if (!*data) { 950 ret = 0; 951 goto fail; 952 } 953 954 memcpy(*data, src, *size); 955 } 956 957 ret = 1; 958 fail: 959 (*env)->DeleteLocalRef(env, key); 960 (*env)->DeleteLocalRef(env, result); 961 962 return ret; 963 } 964 965 static int mediaformat_jni_getString(FFAMediaFormat* ctx, const char *name, const char **out) 966 { 967 int ret = 1; 968 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 969 JNIEnv *env = NULL; 970 jstring key = NULL; 971 jboolean contains_key; 972 jstring result = NULL; 973 974 av_assert0(format != NULL); 975 976 JNI_GET_ENV_OR_RETURN(env, format, 0); 977 978 key = ff_jni_utf_chars_to_jstring(env, name, format); 979 if (!key) { 980 ret = 0; 981 goto fail; 982 } 983 984 contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); 985 if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { 986 ret = 0; 987 goto fail; 988 } 989 990 result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key); 991 if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { 992 ret = 0; 993 goto fail; 994 } 995 996 *out = ff_jni_jstring_to_utf_chars(env, result, format); 997 if (!*out) { 998 ret = 0; 999 goto fail; 1000 } 1001 1002 ret = 1; 1003 fail: 1004 (*env)->DeleteLocalRef(env, key); 1005 (*env)->DeleteLocalRef(env, result); 1006 1007 return ret; 1008 } 1009 1010 static void mediaformat_jni_setInt32(FFAMediaFormat* ctx, const char* name, int32_t value) 1011 { 1012 JNIEnv *env = NULL; 1013 jstring key = NULL; 1014 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 1015 1016 av_assert0(format != NULL); 1017 1018 JNI_GET_ENV_OR_RETURN_VOID(env, format); 1019 1020 key = ff_jni_utf_chars_to_jstring(env, name, format); 1021 if (!key) { 1022 goto fail; 1023 } 1024 1025 (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value); 1026 if (ff_jni_exception_check(env, 1, format) < 0) { 1027 goto fail; 1028 } 1029 1030 fail: 1031 (*env)->DeleteLocalRef(env, key); 1032 } 1033 1034 static void mediaformat_jni_setInt64(FFAMediaFormat* ctx, const char* name, int64_t value) 1035 { 1036 JNIEnv *env = NULL; 1037 jstring key = NULL; 1038 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 1039 1040 av_assert0(format != NULL); 1041 1042 JNI_GET_ENV_OR_RETURN_VOID(env, format); 1043 1044 key = ff_jni_utf_chars_to_jstring(env, name, format); 1045 if (!key) { 1046 goto fail; 1047 } 1048 1049 (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value); 1050 if (ff_jni_exception_check(env, 1, format) < 0) { 1051 goto fail; 1052 } 1053 1054 fail: 1055 (*env)->DeleteLocalRef(env, key); 1056 } 1057 1058 static void mediaformat_jni_setFloat(FFAMediaFormat* ctx, const char* name, float value) 1059 { 1060 JNIEnv *env = NULL; 1061 jstring key = NULL; 1062 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 1063 1064 av_assert0(format != NULL); 1065 1066 JNI_GET_ENV_OR_RETURN_VOID(env, format); 1067 1068 key = ff_jni_utf_chars_to_jstring(env, name, format); 1069 if (!key) { 1070 goto fail; 1071 } 1072 1073 (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value); 1074 if (ff_jni_exception_check(env, 1, format) < 0) { 1075 goto fail; 1076 } 1077 1078 fail: 1079 (*env)->DeleteLocalRef(env, key); 1080 } 1081 1082 static void mediaformat_jni_setString(FFAMediaFormat* ctx, const char* name, const char* value) 1083 { 1084 JNIEnv *env = NULL; 1085 jstring key = NULL; 1086 jstring string = NULL; 1087 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 1088 1089 av_assert0(format != NULL); 1090 1091 JNI_GET_ENV_OR_RETURN_VOID(env, format); 1092 1093 key = ff_jni_utf_chars_to_jstring(env, name, format); 1094 if (!key) { 1095 goto fail; 1096 } 1097 1098 string = ff_jni_utf_chars_to_jstring(env, value, format); 1099 if (!string) { 1100 goto fail; 1101 } 1102 1103 (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string); 1104 if (ff_jni_exception_check(env, 1, format) < 0) { 1105 goto fail; 1106 } 1107 1108 fail: 1109 (*env)->DeleteLocalRef(env, key); 1110 (*env)->DeleteLocalRef(env, string); 1111 } 1112 1113 static void mediaformat_jni_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size) 1114 { 1115 JNIEnv *env = NULL; 1116 jstring key = NULL; 1117 jobject buffer = NULL; 1118 void *buffer_data = NULL; 1119 FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx; 1120 1121 av_assert0(format != NULL); 1122 1123 JNI_GET_ENV_OR_RETURN_VOID(env, format); 1124 1125 key = ff_jni_utf_chars_to_jstring(env, name, format); 1126 if (!key) { 1127 goto fail; 1128 } 1129 1130 if (!data || !size) { 1131 goto fail; 1132 } 1133 1134 buffer_data = av_malloc(size); 1135 if (!buffer_data) { 1136 goto fail; 1137 } 1138 1139 memcpy(buffer_data, data, size); 1140 1141 buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size); 1142 if (!buffer) { 1143 goto fail; 1144 } 1145 1146 (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer); 1147 if (ff_jni_exception_check(env, 1, format) < 0) { 1148 goto fail; 1149 } 1150 1151 fail: 1152 (*env)->DeleteLocalRef(env, key); 1153 (*env)->DeleteLocalRef(env, buffer); 1154 } 1155 1156 static int codec_init_static_fields(FFAMediaCodecJni *codec) 1157 { 1158 int ret = 0; 1159 JNIEnv *env = NULL; 1160 1161 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1162 1163 codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id); 1164 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1165 goto fail; 1166 } 1167 1168 codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id); 1169 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1170 goto fail; 1171 } 1172 1173 codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id); 1174 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1175 goto fail; 1176 } 1177 1178 if (codec->jfields.buffer_flag_key_frame_id) { 1179 codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id); 1180 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1181 goto fail; 1182 } 1183 } 1184 1185 codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id); 1186 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1187 goto fail; 1188 } 1189 1190 codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id); 1191 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1192 goto fail; 1193 } 1194 1195 codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id); 1196 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1197 goto fail; 1198 } 1199 1200 codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id); 1201 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1202 goto fail; 1203 } 1204 1205 fail: 1206 1207 return ret; 1208 } 1209 1210 #define CREATE_CODEC_BY_NAME 0 1211 #define CREATE_DECODER_BY_TYPE 1 1212 #define CREATE_ENCODER_BY_TYPE 2 1213 1214 static inline FFAMediaCodec *codec_create(int method, const char *arg) 1215 { 1216 int ret = -1; 1217 JNIEnv *env = NULL; 1218 FFAMediaCodecJni *codec = NULL; 1219 jstring jarg = NULL; 1220 jobject object = NULL; 1221 jobject buffer_info = NULL; 1222 jmethodID create_id = NULL; 1223 1224 codec = av_mallocz(sizeof(*codec)); 1225 if (!codec) { 1226 return NULL; 1227 } 1228 codec->api = media_codec_jni; 1229 1230 env = ff_jni_get_env(codec); 1231 if (!env) { 1232 av_freep(&codec); 1233 return NULL; 1234 } 1235 1236 if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) { 1237 goto fail; 1238 } 1239 1240 jarg = ff_jni_utf_chars_to_jstring(env, arg, codec); 1241 if (!jarg) { 1242 goto fail; 1243 } 1244 1245 switch (method) { 1246 case CREATE_CODEC_BY_NAME: create_id = codec->jfields.create_by_codec_name_id; break; 1247 case CREATE_DECODER_BY_TYPE: create_id = codec->jfields.create_decoder_by_type_id; break; 1248 case CREATE_ENCODER_BY_TYPE: create_id = codec->jfields.create_encoder_by_type_id; break; 1249 default: 1250 av_assert0(0); 1251 } 1252 1253 object = (*env)->CallStaticObjectMethod(env, 1254 codec->jfields.mediacodec_class, 1255 create_id, 1256 jarg); 1257 if (ff_jni_exception_check(env, 1, codec) < 0) { 1258 goto fail; 1259 } 1260 1261 codec->object = (*env)->NewGlobalRef(env, object); 1262 if (!codec->object) { 1263 goto fail; 1264 } 1265 1266 if (codec_init_static_fields(codec) < 0) { 1267 goto fail; 1268 } 1269 1270 if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) { 1271 codec->has_get_i_o_buffer = 1; 1272 } 1273 1274 buffer_info = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id); 1275 if (ff_jni_exception_check(env, 1, codec) < 0) { 1276 goto fail; 1277 } 1278 1279 codec->buffer_info = (*env)->NewGlobalRef(env, buffer_info); 1280 if (!codec->buffer_info) { 1281 goto fail; 1282 } 1283 1284 ret = 0; 1285 fail: 1286 (*env)->DeleteLocalRef(env, jarg); 1287 (*env)->DeleteLocalRef(env, object); 1288 (*env)->DeleteLocalRef(env, buffer_info); 1289 1290 if (ret < 0) { 1291 (*env)->DeleteGlobalRef(env, codec->object); 1292 (*env)->DeleteGlobalRef(env, codec->buffer_info); 1293 1294 ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); 1295 av_freep(&codec); 1296 } 1297 1298 return (FFAMediaCodec *)codec; 1299 } 1300 1301 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \ 1302 static FFAMediaCodec *mediacodec_jni_##name(const char *arg) \ 1303 { \ 1304 return codec_create(method, arg); \ 1305 } \ 1306 1307 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME) 1308 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE) 1309 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE) 1310 1311 static int mediacodec_jni_delete(FFAMediaCodec* ctx) 1312 { 1313 int ret = 0; 1314 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1315 JNIEnv *env = NULL; 1316 1317 if (!codec) { 1318 return 0; 1319 } 1320 1321 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1322 1323 (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id); 1324 if (ff_jni_exception_check(env, 1, codec) < 0) { 1325 ret = AVERROR_EXTERNAL; 1326 } 1327 1328 (*env)->DeleteGlobalRef(env, codec->input_buffers); 1329 codec->input_buffers = NULL; 1330 1331 (*env)->DeleteGlobalRef(env, codec->output_buffers); 1332 codec->output_buffers = NULL; 1333 1334 (*env)->DeleteGlobalRef(env, codec->object); 1335 codec->object = NULL; 1336 1337 (*env)->DeleteGlobalRef(env, codec->buffer_info); 1338 codec->buffer_info = NULL; 1339 1340 ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); 1341 1342 av_freep(&codec); 1343 1344 return ret; 1345 } 1346 1347 static char *mediacodec_jni_getName(FFAMediaCodec *ctx) 1348 { 1349 char *ret = NULL; 1350 JNIEnv *env = NULL; 1351 jobject *name = NULL; 1352 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1353 1354 JNI_GET_ENV_OR_RETURN(env, codec, NULL); 1355 1356 name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id); 1357 if (ff_jni_exception_check(env, 1, codec) < 0) { 1358 goto fail; 1359 } 1360 1361 ret = ff_jni_jstring_to_utf_chars(env, name, codec); 1362 1363 fail: 1364 if (name) { 1365 (*env)->DeleteLocalRef(env, name); 1366 } 1367 1368 return ret; 1369 } 1370 1371 static int mediacodec_jni_configure(FFAMediaCodec *ctx, 1372 const FFAMediaFormat* format_ctx, 1373 FFANativeWindow* window, 1374 void *crypto, 1375 uint32_t flags) 1376 { 1377 int ret = 0; 1378 JNIEnv *env = NULL; 1379 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1380 const FFAMediaFormatJni *format = (FFAMediaFormatJni *)format_ctx; 1381 jobject *surface = window ? window->surface : NULL; 1382 1383 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1384 1385 if (flags & codec->CONFIGURE_FLAG_ENCODE) { 1386 if (surface && !codec->jfields.set_input_surface_id) { 1387 av_log(ctx, AV_LOG_ERROR, "System doesn't support setInputSurface\n"); 1388 return AVERROR_EXTERNAL; 1389 } 1390 1391 (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags); 1392 if (ff_jni_exception_check(env, 1, codec) < 0) 1393 return AVERROR_EXTERNAL; 1394 1395 if (!surface) 1396 return 0; 1397 1398 (*env)->CallVoidMethod(env, codec->object, codec->jfields.set_input_surface_id, surface); 1399 if (ff_jni_exception_check(env, 1, codec) < 0) 1400 return AVERROR_EXTERNAL; 1401 return 0; 1402 } else { 1403 (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags); 1404 } 1405 if (ff_jni_exception_check(env, 1, codec) < 0) { 1406 ret = AVERROR_EXTERNAL; 1407 goto fail; 1408 } 1409 1410 fail: 1411 return ret; 1412 } 1413 1414 static int mediacodec_jni_setParameters(FFAMediaCodec *ctx, 1415 const FFAMediaFormat* format_ctx) 1416 { 1417 return AVERROR_PATCHWELCOME; 1418 } 1419 1420 static int mediacodec_jni_start(FFAMediaCodec* ctx) 1421 { 1422 int ret = 0; 1423 JNIEnv *env = NULL; 1424 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1425 1426 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1427 1428 (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id); 1429 if (ff_jni_exception_check(env, 1, codec) < 0) { 1430 ret = AVERROR_EXTERNAL; 1431 goto fail; 1432 } 1433 1434 fail: 1435 return ret; 1436 } 1437 1438 static int mediacodec_jni_stop(FFAMediaCodec* ctx) 1439 { 1440 int ret = 0; 1441 JNIEnv *env = NULL; 1442 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1443 1444 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1445 1446 (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id); 1447 if (ff_jni_exception_check(env, 1, codec) < 0) { 1448 ret = AVERROR_EXTERNAL; 1449 goto fail; 1450 } 1451 1452 fail: 1453 return ret; 1454 } 1455 1456 static int mediacodec_jni_flush(FFAMediaCodec* ctx) 1457 { 1458 int ret = 0; 1459 JNIEnv *env = NULL; 1460 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1461 1462 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1463 1464 (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id); 1465 if (ff_jni_exception_check(env, 1, codec) < 0) { 1466 ret = AVERROR_EXTERNAL; 1467 goto fail; 1468 } 1469 1470 fail: 1471 return ret; 1472 } 1473 1474 static int mediacodec_jni_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render) 1475 { 1476 int ret = 0; 1477 JNIEnv *env = NULL; 1478 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1479 1480 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1481 1482 (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render); 1483 if (ff_jni_exception_check(env, 1, codec) < 0) { 1484 ret = AVERROR_EXTERNAL; 1485 goto fail; 1486 } 1487 1488 fail: 1489 return ret; 1490 } 1491 1492 static int mediacodec_jni_releaseOutputBufferAtTime(FFAMediaCodec *ctx, size_t idx, int64_t timestampNs) 1493 { 1494 int ret = 0; 1495 JNIEnv *env = NULL; 1496 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1497 1498 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1499 1500 (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs); 1501 if (ff_jni_exception_check(env, 1, codec) < 0) { 1502 ret = AVERROR_EXTERNAL; 1503 goto fail; 1504 } 1505 1506 fail: 1507 return ret; 1508 } 1509 1510 static ssize_t mediacodec_jni_dequeueInputBuffer(FFAMediaCodec* ctx, int64_t timeoutUs) 1511 { 1512 int ret = 0; 1513 JNIEnv *env = NULL; 1514 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1515 1516 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1517 1518 ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs); 1519 if (ff_jni_exception_check(env, 1, codec) < 0) { 1520 ret = AVERROR_EXTERNAL; 1521 goto fail; 1522 } 1523 1524 fail: 1525 return ret; 1526 } 1527 1528 static int mediacodec_jni_queueInputBuffer(FFAMediaCodec* ctx, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) 1529 { 1530 int ret = 0; 1531 JNIEnv *env = NULL; 1532 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1533 1534 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1535 1536 (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags); 1537 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) { 1538 ret = AVERROR_EXTERNAL; 1539 goto fail; 1540 } 1541 1542 fail: 1543 return ret; 1544 } 1545 1546 static int mediacodec_jni_queueSecureInputBuffer(FFAMediaCodec* ctx, size_t idx, off_t offset, void* cryptoInfo, uint64_t time, uint32_t flags) 1547 { 1548 return AVERROR_PATCHWELCOME; 1549 } 1550 1551 static ssize_t mediacodec_jni_dequeueOutputBuffer(FFAMediaCodec* ctx, FFAMediaCodecBufferInfo *info, int64_t timeoutUs) 1552 { 1553 int ret = 0; 1554 JNIEnv *env = NULL; 1555 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1556 1557 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1558 1559 ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs); 1560 if (ff_jni_exception_check(env, 1, codec) < 0) { 1561 return AVERROR_EXTERNAL; 1562 } 1563 1564 info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id); 1565 if (ff_jni_exception_check(env, 1, codec) < 0) { 1566 return AVERROR_EXTERNAL; 1567 } 1568 1569 info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id); 1570 if (ff_jni_exception_check(env, 1, codec) < 0) { 1571 return AVERROR_EXTERNAL; 1572 } 1573 1574 info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id); 1575 if (ff_jni_exception_check(env, 1, codec) < 0) { 1576 return AVERROR_EXTERNAL; 1577 } 1578 1579 info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id); 1580 if (ff_jni_exception_check(env, 1, codec) < 0) { 1581 return AVERROR_EXTERNAL; 1582 } 1583 1584 return ret; 1585 } 1586 1587 static uint8_t* mediacodec_jni_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) 1588 { 1589 uint8_t *ret = NULL; 1590 JNIEnv *env = NULL; 1591 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1592 jobject buffer = NULL; 1593 jobject input_buffers = NULL; 1594 1595 JNI_GET_ENV_OR_RETURN(env, codec, NULL); 1596 1597 if (codec->has_get_i_o_buffer) { 1598 buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx); 1599 if (ff_jni_exception_check(env, 1, codec) < 0) { 1600 goto fail; 1601 } 1602 } else { 1603 if (!codec->input_buffers) { 1604 input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id); 1605 if (ff_jni_exception_check(env, 1, codec) < 0) { 1606 goto fail; 1607 } 1608 1609 codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers); 1610 if (ff_jni_exception_check(env, 1, codec) < 0) { 1611 goto fail; 1612 } 1613 } 1614 1615 buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx); 1616 if (ff_jni_exception_check(env, 1, codec) < 0) { 1617 goto fail; 1618 } 1619 } 1620 1621 ret = (*env)->GetDirectBufferAddress(env, buffer); 1622 *out_size = (*env)->GetDirectBufferCapacity(env, buffer); 1623 fail: 1624 (*env)->DeleteLocalRef(env, buffer); 1625 (*env)->DeleteLocalRef(env, input_buffers); 1626 1627 return ret; 1628 } 1629 1630 static uint8_t* mediacodec_jni_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) 1631 { 1632 uint8_t *ret = NULL; 1633 JNIEnv *env = NULL; 1634 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1635 jobject buffer = NULL; 1636 jobject output_buffers = NULL; 1637 1638 JNI_GET_ENV_OR_RETURN(env, codec, NULL); 1639 1640 if (codec->has_get_i_o_buffer) { 1641 buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx); 1642 if (ff_jni_exception_check(env, 1, codec) < 0) { 1643 goto fail; 1644 } 1645 } else { 1646 if (!codec->output_buffers) { 1647 output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id); 1648 if (ff_jni_exception_check(env, 1, codec) < 0) { 1649 goto fail; 1650 } 1651 1652 codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers); 1653 if (ff_jni_exception_check(env, 1, codec) < 0) { 1654 goto fail; 1655 } 1656 } 1657 1658 buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx); 1659 if (ff_jni_exception_check(env, 1, codec) < 0) { 1660 goto fail; 1661 } 1662 } 1663 1664 ret = (*env)->GetDirectBufferAddress(env, buffer); 1665 *out_size = (*env)->GetDirectBufferCapacity(env, buffer); 1666 fail: 1667 (*env)->DeleteLocalRef(env, buffer); 1668 (*env)->DeleteLocalRef(env, output_buffers); 1669 1670 return ret; 1671 } 1672 1673 static FFAMediaFormat* mediacodec_jni_getOutputFormat(FFAMediaCodec* ctx) 1674 { 1675 FFAMediaFormat *ret = NULL; 1676 JNIEnv *env = NULL; 1677 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1678 1679 jobject mediaformat = NULL; 1680 1681 JNI_GET_ENV_OR_RETURN(env, codec, NULL); 1682 1683 mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id); 1684 if (ff_jni_exception_check(env, 1, codec) < 0) { 1685 goto fail; 1686 } 1687 1688 ret = mediaformat_jni_newFromObject(mediaformat); 1689 fail: 1690 (*env)->DeleteLocalRef(env, mediaformat); 1691 1692 return ret; 1693 } 1694 1695 static int mediacodec_jni_infoTryAgainLater(FFAMediaCodec *ctx, ssize_t idx) 1696 { 1697 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1698 return idx == codec->INFO_TRY_AGAIN_LATER; 1699 } 1700 1701 static int mediacodec_jni_infoOutputBuffersChanged(FFAMediaCodec *ctx, ssize_t idx) 1702 { 1703 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1704 return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED; 1705 } 1706 1707 static int mediacodec_jni_infoOutputFormatChanged(FFAMediaCodec *ctx, ssize_t idx) 1708 { 1709 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1710 return idx == codec->INFO_OUTPUT_FORMAT_CHANGED; 1711 } 1712 1713 static int mediacodec_jni_getBufferFlagCodecConfig(FFAMediaCodec *ctx) 1714 { 1715 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1716 return codec->BUFFER_FLAG_CODEC_CONFIG; 1717 } 1718 1719 static int mediacodec_jni_getBufferFlagEndOfStream(FFAMediaCodec *ctx) 1720 { 1721 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1722 return codec->BUFFER_FLAG_END_OF_STREAM; 1723 } 1724 1725 static int mediacodec_jni_getBufferFlagKeyFrame(FFAMediaCodec *ctx) 1726 { 1727 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1728 return codec->BUFFER_FLAG_KEY_FRAME; 1729 } 1730 1731 static int mediacodec_jni_getConfigureFlagEncode(FFAMediaCodec *ctx) 1732 { 1733 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1734 return codec->CONFIGURE_FLAG_ENCODE; 1735 } 1736 1737 static int mediacodec_jni_cleanOutputBuffers(FFAMediaCodec *ctx) 1738 { 1739 int ret = 0; 1740 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1741 1742 if (!codec->has_get_i_o_buffer) { 1743 if (codec->output_buffers) { 1744 JNIEnv *env = NULL; 1745 1746 env = ff_jni_get_env(codec); 1747 if (!env) { 1748 ret = AVERROR_EXTERNAL; 1749 goto fail; 1750 } 1751 1752 (*env)->DeleteGlobalRef(env, codec->output_buffers); 1753 codec->output_buffers = NULL; 1754 } 1755 } 1756 1757 fail: 1758 return ret; 1759 } 1760 1761 static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx) 1762 { 1763 JNIEnv *env = NULL; 1764 FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx; 1765 1766 JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); 1767 1768 (*env)->CallVoidMethod(env, codec->object, codec->jfields.signal_end_of_input_stream_id); 1769 if (ff_jni_exception_check(env, 1, codec) < 0) { 1770 return AVERROR_EXTERNAL; 1771 } 1772 1773 return 0; 1774 } 1775 1776 static int mediacodec_jni_setAsyncNotifyCallback(FFAMediaCodec *codec, 1777 const FFAMediaCodecOnAsyncNotifyCallback *callback, 1778 void *userdata) 1779 { 1780 av_log(codec, AV_LOG_ERROR, "Doesn't support aync mode with JNI, please try ndk_codec=1\n"); 1781 return AVERROR(ENOSYS); 1782 } 1783 1784 static const FFAMediaFormat media_format_jni = { 1785 .class = &amediaformat_class, 1786 1787 .create = mediaformat_jni_new, 1788 .delete = mediaformat_jni_delete, 1789 1790 .toString = mediaformat_jni_toString, 1791 1792 .getInt32 = mediaformat_jni_getInt32, 1793 .getInt64 = mediaformat_jni_getInt64, 1794 .getFloat = mediaformat_jni_getFloat, 1795 .getBuffer = mediaformat_jni_getBuffer, 1796 .getString = mediaformat_jni_getString, 1797 1798 .setInt32 = mediaformat_jni_setInt32, 1799 .setInt64 = mediaformat_jni_setInt64, 1800 .setFloat = mediaformat_jni_setFloat, 1801 .setString = mediaformat_jni_setString, 1802 .setBuffer = mediaformat_jni_setBuffer, 1803 }; 1804 1805 static const FFAMediaCodec media_codec_jni = { 1806 .class = &amediacodec_class, 1807 1808 .getName = mediacodec_jni_getName, 1809 1810 .createCodecByName = mediacodec_jni_createCodecByName, 1811 .createDecoderByType = mediacodec_jni_createDecoderByType, 1812 .createEncoderByType = mediacodec_jni_createEncoderByType, 1813 .delete = mediacodec_jni_delete, 1814 1815 .configure = mediacodec_jni_configure, 1816 .setParameters = mediacodec_jni_setParameters, 1817 .start = mediacodec_jni_start, 1818 .stop = mediacodec_jni_stop, 1819 .flush = mediacodec_jni_flush, 1820 1821 .getInputBuffer = mediacodec_jni_getInputBuffer, 1822 .getOutputBuffer = mediacodec_jni_getOutputBuffer, 1823 1824 .dequeueInputBuffer = mediacodec_jni_dequeueInputBuffer, 1825 .queueInputBuffer = mediacodec_jni_queueInputBuffer, 1826 .queueSecureInputBuffer = mediacodec_jni_queueSecureInputBuffer, 1827 1828 .dequeueOutputBuffer = mediacodec_jni_dequeueOutputBuffer, 1829 .getOutputFormat = mediacodec_jni_getOutputFormat, 1830 1831 .releaseOutputBuffer = mediacodec_jni_releaseOutputBuffer, 1832 .releaseOutputBufferAtTime = mediacodec_jni_releaseOutputBufferAtTime, 1833 1834 .infoTryAgainLater = mediacodec_jni_infoTryAgainLater, 1835 .infoOutputBuffersChanged = mediacodec_jni_infoOutputBuffersChanged, 1836 .infoOutputFormatChanged = mediacodec_jni_infoOutputFormatChanged, 1837 1838 .getBufferFlagCodecConfig = mediacodec_jni_getBufferFlagCodecConfig, 1839 .getBufferFlagEndOfStream = mediacodec_jni_getBufferFlagEndOfStream, 1840 .getBufferFlagKeyFrame = mediacodec_jni_getBufferFlagKeyFrame, 1841 1842 .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode, 1843 .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers, 1844 .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream, 1845 .setAsyncNotifyCallback = mediacodec_jni_setAsyncNotifyCallback, 1846 }; 1847 1848 typedef struct FFAMediaFormatNdk { 1849 FFAMediaFormat api; 1850 1851 void *libmedia; 1852 AMediaFormat *impl; 1853 1854 bool (*getRect)(AMediaFormat *, const char *name, 1855 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom); 1856 void (*setRect)(AMediaFormat *, const char *name, 1857 int32_t left, int32_t top, int32_t right, int32_t bottom); 1858 } FFAMediaFormatNdk; 1859 1860 typedef struct FFAMediaCodecNdk { 1861 FFAMediaCodec api; 1862 1863 void *libmedia; 1864 AMediaCodec *impl; 1865 ANativeWindow *window; 1866 1867 FFAMediaCodecOnAsyncNotifyCallback async_cb; 1868 void *async_userdata; 1869 1870 // Available since API level 28. 1871 media_status_t (*getName)(AMediaCodec*, char** out_name); 1872 void (*releaseName)(AMediaCodec*, char* name); 1873 1874 // Available since API level 26. 1875 media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *); 1876 media_status_t (*signalEndOfInputStream)(AMediaCodec *); 1877 media_status_t (*setAsyncNotifyCallback)(AMediaCodec *, 1878 struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata); 1879 } FFAMediaCodecNdk; 1880 1881 static const FFAMediaFormat media_format_ndk; 1882 static const FFAMediaCodec media_codec_ndk; 1883 1884 static const AVClass amediaformat_ndk_class = { 1885 .class_name = "amediaformat_ndk", 1886 .item_name = av_default_item_name, 1887 .version = LIBAVUTIL_VERSION_INT, 1888 }; 1889 1890 static const AVClass amediacodec_ndk_class = { 1891 .class_name = "amediacodec_ndk", 1892 .item_name = av_default_item_name, 1893 .version = LIBAVUTIL_VERSION_INT, 1894 }; 1895 1896 static int media_status_to_error(media_status_t status) 1897 { 1898 switch (status) { 1899 case AMEDIA_OK: 1900 return 0; 1901 case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE: 1902 return AVERROR(ENOMEM); 1903 case AMEDIA_ERROR_MALFORMED: 1904 return AVERROR_INVALIDDATA; 1905 case AMEDIA_ERROR_UNSUPPORTED: 1906 return AVERROR(ENOTSUP); 1907 case AMEDIA_ERROR_INVALID_PARAMETER: 1908 return AVERROR(EINVAL); 1909 case AMEDIA_ERROR_INVALID_OPERATION: 1910 return AVERROR(EOPNOTSUPP); 1911 case AMEDIA_ERROR_END_OF_STREAM: 1912 return AVERROR_EOF; 1913 case AMEDIA_ERROR_IO: 1914 return AVERROR(EIO); 1915 case AMEDIA_ERROR_WOULD_BLOCK: 1916 return AVERROR(EWOULDBLOCK); 1917 default: 1918 return AVERROR_EXTERNAL; 1919 } 1920 } 1921 1922 static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl) 1923 { 1924 FFAMediaFormatNdk *format = av_mallocz(sizeof(*format)); 1925 if (!format) 1926 return NULL; 1927 1928 format->api = media_format_ndk; 1929 1930 format->libmedia = dlopen("libmediandk.so", RTLD_NOW); 1931 if (!format->libmedia) 1932 goto error; 1933 1934 #define GET_OPTIONAL_SYMBOL(sym) \ 1935 format->sym = dlsym(format->libmedia, "AMediaFormat_" #sym); 1936 1937 GET_OPTIONAL_SYMBOL(getRect) 1938 GET_OPTIONAL_SYMBOL(setRect) 1939 1940 #undef GET_OPTIONAL_SYMBOL 1941 1942 if (impl) { 1943 format->impl = impl; 1944 } else { 1945 format->impl = AMediaFormat_new(); 1946 if (!format->impl) 1947 goto error; 1948 } 1949 1950 return (FFAMediaFormat *)format; 1951 1952 error: 1953 if (format->libmedia) 1954 dlclose(format->libmedia); 1955 av_freep(&format); 1956 return NULL; 1957 } 1958 1959 static FFAMediaFormat *mediaformat_ndk_new(void) 1960 { 1961 return mediaformat_ndk_create(NULL); 1962 } 1963 1964 static int mediaformat_ndk_delete(FFAMediaFormat* ctx) 1965 { 1966 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 1967 int ret = 0; 1968 if (!format) 1969 return 0; 1970 1971 av_assert0(format->api.class == &amediaformat_ndk_class); 1972 1973 if (format->impl && (AMediaFormat_delete(format->impl) != AMEDIA_OK)) 1974 ret = AVERROR_EXTERNAL; 1975 if (format->libmedia) 1976 dlclose(format->libmedia); 1977 av_free(format); 1978 1979 return ret; 1980 } 1981 1982 static char* mediaformat_ndk_toString(FFAMediaFormat* ctx) 1983 { 1984 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 1985 const char *str = AMediaFormat_toString(format->impl); 1986 return av_strdup(str); 1987 } 1988 1989 static int mediaformat_ndk_getInt32(FFAMediaFormat* ctx, const char *name, int32_t *out) 1990 { 1991 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 1992 return AMediaFormat_getInt32(format->impl, name, out); 1993 } 1994 1995 static int mediaformat_ndk_getInt64(FFAMediaFormat* ctx, const char *name, int64_t *out) 1996 { 1997 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 1998 return AMediaFormat_getInt64(format->impl, name, out); 1999 } 2000 2001 static int mediaformat_ndk_getFloat(FFAMediaFormat* ctx, const char *name, float *out) 2002 { 2003 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2004 return AMediaFormat_getFloat(format->impl, name, out); 2005 } 2006 2007 static int mediaformat_ndk_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size) 2008 { 2009 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2010 return AMediaFormat_getBuffer(format->impl, name, data, size); 2011 } 2012 2013 static int mediaformat_ndk_getString(FFAMediaFormat* ctx, const char *name, const char **out) 2014 { 2015 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2016 const char *tmp = NULL; 2017 int ret = AMediaFormat_getString(format->impl, name, &tmp); 2018 2019 if (tmp) 2020 *out = av_strdup(tmp); 2021 return ret; 2022 } 2023 2024 static int mediaformat_ndk_getRect(FFAMediaFormat *ctx, const char *name, 2025 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) 2026 { 2027 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2028 if (!format->getRect) 2029 return AVERROR_EXTERNAL; 2030 return format->getRect(format->impl, name, left, top, right, bottom); 2031 } 2032 2033 static void mediaformat_ndk_setInt32(FFAMediaFormat* ctx, const char* name, int32_t value) 2034 { 2035 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2036 AMediaFormat_setInt32(format->impl, name, value); 2037 } 2038 2039 static void mediaformat_ndk_setInt64(FFAMediaFormat* ctx, const char* name, int64_t value) 2040 { 2041 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2042 AMediaFormat_setInt64(format->impl, name, value); 2043 } 2044 2045 static void mediaformat_ndk_setFloat(FFAMediaFormat* ctx, const char* name, float value) 2046 { 2047 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2048 AMediaFormat_setFloat(format->impl, name, value); 2049 } 2050 2051 static void mediaformat_ndk_setString(FFAMediaFormat* ctx, const char* name, const char* value) 2052 { 2053 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2054 AMediaFormat_setString(format->impl, name, value); 2055 } 2056 2057 static void mediaformat_ndk_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size) 2058 { 2059 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2060 AMediaFormat_setBuffer(format->impl, name, data, size); 2061 } 2062 2063 static void mediaformat_ndk_setRect(FFAMediaFormat *ctx, const char *name, 2064 int32_t left, int32_t top, int32_t right, int32_t bottom) 2065 { 2066 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; 2067 if (!format->setRect) { 2068 av_log(ctx, AV_LOG_WARNING, "Doesn't support setRect\n"); 2069 return; 2070 } 2071 format->setRect(format->impl, name, left, top, right, bottom); 2072 } 2073 2074 static char *mediacodec_ndk_getName(FFAMediaCodec *ctx) 2075 { 2076 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2077 char *ret = NULL; 2078 char *name = NULL; 2079 2080 if (!codec->getName || !codec->releaseName) { 2081 av_log(ctx, AV_LOG_DEBUG, "getName() unavailable\n"); 2082 return ret; 2083 } 2084 2085 codec->getName(codec->impl, &name); 2086 if (name) { 2087 ret = av_strdup(name); 2088 codec->releaseName(codec->impl, name); 2089 } 2090 2091 return ret; 2092 } 2093 2094 static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) { 2095 FFAMediaCodecNdk *codec = av_mallocz(sizeof(*codec)); 2096 const char *lib_name = "libmediandk.so"; 2097 2098 if (!codec) 2099 return NULL; 2100 2101 codec->api = media_codec_ndk; 2102 codec->libmedia = dlopen(lib_name, RTLD_NOW); 2103 if (!codec->libmedia) 2104 goto error; 2105 2106 #define GET_SYMBOL(sym) \ 2107 codec->sym = dlsym(codec->libmedia, "AMediaCodec_" #sym); \ 2108 if (!codec->sym) \ 2109 av_log(codec, AV_LOG_INFO, #sym "() unavailable from %s\n", lib_name); 2110 2111 GET_SYMBOL(getName) 2112 GET_SYMBOL(releaseName) 2113 2114 GET_SYMBOL(setInputSurface) 2115 GET_SYMBOL(signalEndOfInputStream) 2116 GET_SYMBOL(setAsyncNotifyCallback) 2117 2118 #undef GET_SYMBOL 2119 2120 switch (method) { 2121 case CREATE_CODEC_BY_NAME: 2122 codec->impl = AMediaCodec_createCodecByName(arg); 2123 break; 2124 case CREATE_DECODER_BY_TYPE: 2125 codec->impl = AMediaCodec_createDecoderByType(arg); 2126 break; 2127 case CREATE_ENCODER_BY_TYPE: 2128 codec->impl = AMediaCodec_createEncoderByType(arg); 2129 break; 2130 default: 2131 av_assert0(0); 2132 } 2133 if (!codec->impl) 2134 goto error; 2135 2136 return (FFAMediaCodec *)codec; 2137 2138 error: 2139 if (codec->libmedia) 2140 dlclose(codec->libmedia); 2141 av_freep(&codec); 2142 return NULL; 2143 } 2144 2145 #define DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(name, method) \ 2146 static FFAMediaCodec *mediacodec_ndk_##name(const char *arg) \ 2147 { \ 2148 return ndk_codec_create(method, arg); \ 2149 } \ 2150 2151 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME) 2152 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE) 2153 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE) 2154 2155 static int mediacodec_ndk_delete(FFAMediaCodec* ctx) 2156 { 2157 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2158 int ret = 0; 2159 2160 if (!codec) 2161 return 0; 2162 2163 av_assert0(codec->api.class == &amediacodec_ndk_class); 2164 2165 if (codec->impl && (AMediaCodec_delete(codec->impl) != AMEDIA_OK)) 2166 ret = AVERROR_EXTERNAL; 2167 if (codec->window) 2168 ANativeWindow_release(codec->window); 2169 if (codec->libmedia) 2170 dlclose(codec->libmedia); 2171 av_free(codec); 2172 2173 return ret; 2174 } 2175 2176 static int mediacodec_ndk_configure(FFAMediaCodec* ctx, 2177 const FFAMediaFormat* format_ctx, 2178 FFANativeWindow* window, 2179 void *crypto, 2180 uint32_t flags) 2181 { 2182 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2183 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)format_ctx; 2184 media_status_t status; 2185 ANativeWindow *native_window = NULL; 2186 2187 if (window) { 2188 if (window->surface) { 2189 JNIEnv *env = NULL; 2190 JNI_GET_ENV_OR_RETURN(env, ctx, -1); 2191 native_window = ANativeWindow_fromSurface(env, window->surface); 2192 // Save for release 2193 codec->window = native_window; 2194 } else if (window->native_window) { 2195 native_window = window->native_window; 2196 } 2197 } 2198 2199 if (format_ctx->class != &amediaformat_ndk_class) { 2200 av_log(ctx, AV_LOG_ERROR, "invalid media format\n"); 2201 return AVERROR(EINVAL); 2202 } 2203 2204 if (flags & AMEDIACODEC_CONFIGURE_FLAG_ENCODE) { 2205 if (native_window && !codec->setInputSurface) { 2206 av_log(ctx, AV_LOG_ERROR, "System doesn't support setInputSurface\n"); 2207 return AVERROR_EXTERNAL; 2208 } 2209 2210 status = AMediaCodec_configure(codec->impl, format->impl, NULL, NULL, flags); 2211 if (status != AMEDIA_OK) { 2212 av_log(codec, AV_LOG_ERROR, "Encoder configure failed, %d\n", status); 2213 return AVERROR_EXTERNAL; 2214 } 2215 2216 if (!native_window) 2217 return 0; 2218 2219 status = codec->setInputSurface(codec->impl, native_window); 2220 if (status != AMEDIA_OK) { 2221 av_log(codec, AV_LOG_ERROR, "Encoder set input surface failed, %d\n", status); 2222 return AVERROR_EXTERNAL; 2223 } 2224 } else { 2225 status = AMediaCodec_configure(codec->impl, format->impl, native_window, (AMediaCrypto*)crypto, flags); 2226 if (status != AMEDIA_OK) { 2227 av_log(codec, AV_LOG_ERROR, "Decoder configure failed, %d\n", status); 2228 return AVERROR_EXTERNAL; 2229 } 2230 } 2231 2232 return 0; 2233 } 2234 2235 static int mediacodec_ndk_setParameters(FFAMediaCodec *ctx, 2236 const FFAMediaFormat* format_ctx) 2237 { 2238 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2239 FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)format_ctx; 2240 media_status_t status; 2241 2242 if (format_ctx->class != &amediaformat_ndk_class) { 2243 av_log(ctx, AV_LOG_ERROR, "invalid media format\n"); 2244 return AVERROR(EINVAL); 2245 } 2246 2247 status = AMediaCodec_setParameters(codec->impl, format->impl); 2248 if (status != AMEDIA_OK) { 2249 av_log(codec, AV_LOG_ERROR, "setParameters failed, %d\n", status); 2250 return AVERROR_EXTERNAL; 2251 } 2252 2253 return 0; 2254 } 2255 2256 #define MEDIACODEC_NDK_WRAPPER(method) \ 2257 static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx) \ 2258 { \ 2259 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; \ 2260 media_status_t status = AMediaCodec_ ## method (codec->impl); \ 2261 \ 2262 if (status != AMEDIA_OK) { \ 2263 av_log(codec, AV_LOG_ERROR, #method " failed, %d\n", status); \ 2264 return AVERROR_EXTERNAL; \ 2265 } \ 2266 \ 2267 return 0; \ 2268 } \ 2269 2270 MEDIACODEC_NDK_WRAPPER(start) 2271 MEDIACODEC_NDK_WRAPPER(stop) 2272 MEDIACODEC_NDK_WRAPPER(flush) 2273 2274 static uint8_t* mediacodec_ndk_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) 2275 { 2276 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2277 return AMediaCodec_getInputBuffer(codec->impl, idx, out_size); 2278 } 2279 2280 static uint8_t* mediacodec_ndk_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) 2281 { 2282 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2283 return AMediaCodec_getOutputBuffer(codec->impl, idx, out_size); 2284 } 2285 2286 static ssize_t mediacodec_ndk_dequeueInputBuffer(FFAMediaCodec* ctx, int64_t timeoutUs) 2287 { 2288 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2289 return AMediaCodec_dequeueInputBuffer(codec->impl, timeoutUs); 2290 } 2291 2292 static int mediacodec_ndk_queueInputBuffer(FFAMediaCodec *ctx, size_t idx, 2293 off_t offset, size_t size, 2294 uint64_t time, uint32_t flags) 2295 { 2296 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2297 return AMediaCodec_queueInputBuffer(codec->impl, idx, offset, size, time, flags); 2298 } 2299 2300 static int mediacodec_ndk_queueSecureInputBuffer(FFAMediaCodec *ctx, size_t idx, 2301 off_t offset, void* cryptoInfo, 2302 uint64_t time, uint32_t flags) 2303 { 2304 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2305 return AMediaCodec_queueSecureInputBuffer(codec->impl, idx, offset, (AMediaCodecCryptoInfo*)cryptoInfo, time, flags); 2306 } 2307 2308 static ssize_t mediacodec_ndk_dequeueOutputBuffer(FFAMediaCodec* ctx, FFAMediaCodecBufferInfo *info, int64_t timeoutUs) 2309 { 2310 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2311 AMediaCodecBufferInfo buf_info = {0}; 2312 ssize_t ret; 2313 2314 ret = AMediaCodec_dequeueOutputBuffer(codec->impl, &buf_info, timeoutUs); 2315 info->offset = buf_info.offset; 2316 info->size = buf_info.size; 2317 info->presentationTimeUs = buf_info.presentationTimeUs; 2318 info->flags = buf_info.flags; 2319 2320 return ret; 2321 } 2322 2323 static FFAMediaFormat* mediacodec_ndk_getOutputFormat(FFAMediaCodec* ctx) 2324 { 2325 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2326 AMediaFormat *format = AMediaCodec_getOutputFormat(codec->impl); 2327 2328 if (!format) 2329 return NULL; 2330 return mediaformat_ndk_create(format); 2331 } 2332 2333 static int mediacodec_ndk_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render) 2334 { 2335 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2336 media_status_t status; 2337 2338 status = AMediaCodec_releaseOutputBuffer(codec->impl, idx, render); 2339 if (status != AMEDIA_OK) { 2340 av_log(codec, AV_LOG_ERROR, "release output buffer failed, %d\n", status); 2341 return AVERROR_EXTERNAL; 2342 } 2343 2344 return 0; 2345 } 2346 2347 static int mediacodec_ndk_releaseOutputBufferAtTime(FFAMediaCodec *ctx, size_t idx, int64_t timestampNs) 2348 { 2349 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2350 media_status_t status; 2351 2352 status = AMediaCodec_releaseOutputBufferAtTime(codec->impl, idx, timestampNs); 2353 if (status != AMEDIA_OK) { 2354 av_log(codec, AV_LOG_ERROR, "releaseOutputBufferAtTime failed, %d\n", status); 2355 return AVERROR_EXTERNAL; 2356 } 2357 2358 return 0; 2359 } 2360 2361 static int mediacodec_ndk_infoTryAgainLater(FFAMediaCodec *ctx, ssize_t idx) 2362 { 2363 return idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER; 2364 } 2365 2366 static int mediacodec_ndk_infoOutputBuffersChanged(FFAMediaCodec *ctx, ssize_t idx) 2367 { 2368 return idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED; 2369 } 2370 2371 static int mediacodec_ndk_infoOutputFormatChanged(FFAMediaCodec *ctx, ssize_t idx) 2372 { 2373 return idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED; 2374 } 2375 2376 static int mediacodec_ndk_getBufferFlagCodecConfig(FFAMediaCodec *ctx) 2377 { 2378 return AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG; 2379 } 2380 2381 static int mediacodec_ndk_getBufferFlagEndOfStream(FFAMediaCodec *ctx) 2382 { 2383 return AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM; 2384 } 2385 2386 static int mediacodec_ndk_getBufferFlagKeyFrame(FFAMediaCodec *ctx) 2387 { 2388 return 1; 2389 } 2390 2391 static int mediacodec_ndk_getConfigureFlagEncode(FFAMediaCodec *ctx) 2392 { 2393 return AMEDIACODEC_CONFIGURE_FLAG_ENCODE; 2394 } 2395 2396 static int mediacodec_ndk_cleanOutputBuffers(FFAMediaCodec *ctx) 2397 { 2398 return 0; 2399 } 2400 2401 static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx) 2402 { 2403 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2404 media_status_t status; 2405 2406 if (!codec->signalEndOfInputStream) { 2407 av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream unavailable\n"); 2408 return AVERROR_EXTERNAL; 2409 } 2410 2411 status = codec->signalEndOfInputStream(codec->impl); 2412 if (status != AMEDIA_OK) { 2413 av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream failed, %d\n", status); 2414 return AVERROR_EXTERNAL; 2415 } 2416 av_log(codec, AV_LOG_DEBUG, "signalEndOfInputStream success\n"); 2417 2418 return 0; 2419 } 2420 2421 static void mediacodec_ndk_onInputAvailable(AMediaCodec *impl, void *userdata, 2422 int32_t index) 2423 { 2424 FFAMediaCodecNdk *codec = userdata; 2425 codec->async_cb.onAsyncInputAvailable((FFAMediaCodec *) codec, 2426 codec->async_userdata, index); 2427 } 2428 2429 static void mediacodec_ndk_onOutputAvailable(AMediaCodec *impl, 2430 void *userdata, 2431 int32_t index, 2432 AMediaCodecBufferInfo *buffer_info) 2433 { 2434 FFAMediaCodecNdk *codec = userdata; 2435 FFAMediaCodecBufferInfo info = { 2436 .offset = buffer_info->offset, 2437 .size = buffer_info->size, 2438 .presentationTimeUs = buffer_info->presentationTimeUs, 2439 .flags = buffer_info->flags, 2440 }; 2441 2442 codec->async_cb.onAsyncOutputAvailable(&codec->api, codec->async_userdata, 2443 index, &info); 2444 } 2445 2446 static void mediacodec_ndk_onFormatChanged(AMediaCodec *impl, void *userdata, 2447 AMediaFormat *format) 2448 { 2449 FFAMediaCodecNdk *codec = userdata; 2450 FFAMediaFormat *media_format = mediaformat_ndk_create(format); 2451 if (!media_format) 2452 return; 2453 2454 codec->async_cb.onAsyncFormatChanged(&codec->api, codec->async_userdata, 2455 media_format); 2456 ff_AMediaFormat_delete(media_format); 2457 } 2458 2459 static void mediacodec_ndk_onError(AMediaCodec *impl, void *userdata, 2460 media_status_t status, 2461 int32_t actionCode, 2462 const char *detail) 2463 { 2464 FFAMediaCodecNdk *codec = userdata; 2465 int error = media_status_to_error(status); 2466 2467 codec->async_cb.onAsyncError(&codec->api, codec->async_userdata, error, 2468 detail); 2469 } 2470 2471 static int mediacodec_ndk_setAsyncNotifyCallback(FFAMediaCodec *ctx, 2472 const FFAMediaCodecOnAsyncNotifyCallback *callback, 2473 void *userdata) 2474 { 2475 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; 2476 struct AMediaCodecOnAsyncNotifyCallback cb = { 2477 .onAsyncInputAvailable = mediacodec_ndk_onInputAvailable, 2478 .onAsyncOutputAvailable = mediacodec_ndk_onOutputAvailable, 2479 .onAsyncFormatChanged = mediacodec_ndk_onFormatChanged, 2480 .onAsyncError = mediacodec_ndk_onError, 2481 }; 2482 media_status_t status; 2483 2484 if (!codec->setAsyncNotifyCallback) { 2485 av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback unavailable\n"); 2486 return AVERROR(ENOSYS); 2487 } 2488 2489 if (!callback || 2490 !callback->onAsyncInputAvailable || 2491 !callback->onAsyncOutputAvailable || 2492 !callback->onAsyncFormatChanged || 2493 !callback->onAsyncError) 2494 return AVERROR(EINVAL); 2495 2496 codec->async_cb = *callback; 2497 codec->async_userdata = userdata; 2498 2499 status = codec->setAsyncNotifyCallback(codec->impl, cb, codec); 2500 if (status != AMEDIA_OK) { 2501 av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback failed, %d\n", 2502 status); 2503 return AVERROR_EXTERNAL; 2504 } 2505 2506 return 0; 2507 } 2508 2509 static const FFAMediaFormat media_format_ndk = { 2510 .class = &amediaformat_ndk_class, 2511 2512 .create = mediaformat_ndk_new, 2513 .delete = mediaformat_ndk_delete, 2514 2515 .toString = mediaformat_ndk_toString, 2516 2517 .getInt32 = mediaformat_ndk_getInt32, 2518 .getInt64 = mediaformat_ndk_getInt64, 2519 .getFloat = mediaformat_ndk_getFloat, 2520 .getBuffer = mediaformat_ndk_getBuffer, 2521 .getString = mediaformat_ndk_getString, 2522 .getRect = mediaformat_ndk_getRect, 2523 2524 .setInt32 = mediaformat_ndk_setInt32, 2525 .setInt64 = mediaformat_ndk_setInt64, 2526 .setFloat = mediaformat_ndk_setFloat, 2527 .setString = mediaformat_ndk_setString, 2528 .setBuffer = mediaformat_ndk_setBuffer, 2529 .setRect = mediaformat_ndk_setRect, 2530 }; 2531 2532 static const FFAMediaCodec media_codec_ndk = { 2533 .class = &amediacodec_ndk_class, 2534 2535 .getName = mediacodec_ndk_getName, 2536 2537 .createCodecByName = mediacodec_ndk_createCodecByName, 2538 .createDecoderByType = mediacodec_ndk_createDecoderByType, 2539 .createEncoderByType = mediacodec_ndk_createEncoderByType, 2540 .delete = mediacodec_ndk_delete, 2541 2542 .configure = mediacodec_ndk_configure, 2543 .setParameters = mediacodec_ndk_setParameters, 2544 .start = mediacodec_ndk_start, 2545 .stop = mediacodec_ndk_stop, 2546 .flush = mediacodec_ndk_flush, 2547 2548 .getInputBuffer = mediacodec_ndk_getInputBuffer, 2549 .getOutputBuffer = mediacodec_ndk_getOutputBuffer, 2550 2551 .dequeueInputBuffer = mediacodec_ndk_dequeueInputBuffer, 2552 .queueInputBuffer = mediacodec_ndk_queueInputBuffer, 2553 .queueSecureInputBuffer = mediacodec_ndk_queueSecureInputBuffer, 2554 2555 .dequeueOutputBuffer = mediacodec_ndk_dequeueOutputBuffer, 2556 .getOutputFormat = mediacodec_ndk_getOutputFormat, 2557 2558 .releaseOutputBuffer = mediacodec_ndk_releaseOutputBuffer, 2559 .releaseOutputBufferAtTime = mediacodec_ndk_releaseOutputBufferAtTime, 2560 2561 .infoTryAgainLater = mediacodec_ndk_infoTryAgainLater, 2562 .infoOutputBuffersChanged = mediacodec_ndk_infoOutputBuffersChanged, 2563 .infoOutputFormatChanged = mediacodec_ndk_infoOutputFormatChanged, 2564 2565 .getBufferFlagCodecConfig = mediacodec_ndk_getBufferFlagCodecConfig, 2566 .getBufferFlagEndOfStream = mediacodec_ndk_getBufferFlagEndOfStream, 2567 .getBufferFlagKeyFrame = mediacodec_ndk_getBufferFlagKeyFrame, 2568 2569 .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode, 2570 .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers, 2571 .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream, 2572 .setAsyncNotifyCallback = mediacodec_ndk_setAsyncNotifyCallback, 2573 }; 2574 2575 FFAMediaFormat *ff_AMediaFormat_new(int ndk) 2576 { 2577 if (ndk) 2578 return media_format_ndk.create(); 2579 return media_format_jni.create(); 2580 } 2581 2582 FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name, int ndk) 2583 { 2584 if (ndk) 2585 return media_codec_ndk.createCodecByName(name); 2586 return media_codec_jni.createCodecByName(name); 2587 } 2588 2589 FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type, int ndk) 2590 { 2591 if (ndk) 2592 return media_codec_ndk.createDecoderByType(mime_type); 2593 return media_codec_jni.createDecoderByType(mime_type); 2594 } 2595 2596 FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type, int ndk) 2597 { 2598 if (ndk) 2599 return media_codec_ndk.createEncoderByType(mime_type); 2600 return media_codec_jni.createEncoderByType(mime_type); 2601 } 2602 2603 int ff_Build_SDK_INT(AVCodecContext *avctx) 2604 { 2605 int ret = -1; 2606 2607 #if __ANDROID_API__ >= 24 2608 // android_get_device_api_level() is a static inline before API level 29. 2609 // dlsym() might doesn't work. 2610 // 2611 // We can implement android_get_device_api_level() by 2612 // __system_property_get(), but __system_property_get() has created a lot of 2613 // troubles and is deprecated. So avoid using __system_property_get() for 2614 // now. 2615 // 2616 // Hopy we can remove the conditional compilation finally by bumping the 2617 // required API level. 2618 // 2619 ret = android_get_device_api_level(); 2620 #else 2621 JNIEnv *env = NULL; 2622 jclass versionClass; 2623 jfieldID sdkIntFieldID; 2624 JNI_GET_ENV_OR_RETURN(env, avctx, -1); 2625 2626 versionClass = (*env)->FindClass(env, "android/os/Build$VERSION"); 2627 sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I"); 2628 ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID); 2629 (*env)->DeleteLocalRef(env, versionClass); 2630 #endif 2631 av_log(avctx, AV_LOG_DEBUG, "device api level %d\n", ret); 2632 2633 return ret; 2634 } 2635 2636 static struct { 2637 enum FFAMediaFormatColorRange mf_range; 2638 enum AVColorRange range; 2639 } color_range_map[] = { 2640 { COLOR_RANGE_FULL, AVCOL_RANGE_JPEG }, 2641 { COLOR_RANGE_LIMITED, AVCOL_RANGE_MPEG }, 2642 }; 2643 2644 static struct { 2645 enum FFAMediaFormatColorStandard mf_standard; 2646 enum AVColorSpace space; 2647 } color_space_map[] = { 2648 { COLOR_STANDARD_BT709, AVCOL_SPC_BT709 }, 2649 { COLOR_STANDARD_BT601_PAL, AVCOL_SPC_BT470BG }, 2650 { COLOR_STANDARD_BT601_NTSC, AVCOL_SPC_SMPTE170M }, 2651 { COLOR_STANDARD_BT2020, AVCOL_SPC_BT2020_NCL }, 2652 }; 2653 2654 static struct { 2655 enum FFAMediaFormatColorStandard mf_standard; 2656 enum AVColorPrimaries primaries; 2657 } color_primaries_map[] = { 2658 { COLOR_STANDARD_BT709, AVCOL_PRI_BT709 }, 2659 { COLOR_STANDARD_BT601_PAL, AVCOL_PRI_BT470BG }, 2660 { COLOR_STANDARD_BT601_NTSC, AVCOL_PRI_SMPTE170M }, 2661 { COLOR_STANDARD_BT2020, AVCOL_PRI_BT2020 }, 2662 }; 2663 2664 static struct { 2665 enum FFAMediaFormatColorTransfer mf_transfer; 2666 enum AVColorTransferCharacteristic transfer; 2667 } color_transfer_map[] = { 2668 { COLOR_TRANSFER_LINEAR, AVCOL_TRC_LINEAR }, 2669 { COLOR_TRANSFER_SDR_VIDEO, AVCOL_TRC_SMPTE170M }, 2670 { COLOR_TRANSFER_ST2084, AVCOL_TRC_SMPTEST2084 }, 2671 { COLOR_TRANSFER_HLG, AVCOL_TRC_ARIB_STD_B67 }, 2672 }; 2673 2674 enum AVColorRange ff_AMediaFormatColorRange_to_AVColorRange(int color_range) 2675 { 2676 for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++) 2677 if (color_range_map[i].mf_range == color_range) 2678 return color_range_map[i].range; 2679 2680 return AVCOL_RANGE_UNSPECIFIED; 2681 } 2682 2683 int ff_AMediaFormatColorRange_from_AVColorRange(enum AVColorRange color_range) 2684 { 2685 for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++) 2686 if (color_range_map[i].range == color_range) 2687 return color_range_map[i].mf_range; 2688 return COLOR_RANGE_UNSPECIFIED; 2689 } 2690 2691 enum AVColorSpace ff_AMediaFormatColorStandard_to_AVColorSpace(int color_standard) 2692 { 2693 for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++) 2694 if (color_space_map[i].mf_standard == color_standard) 2695 return color_space_map[i].space; 2696 2697 return AVCOL_SPC_UNSPECIFIED; 2698 } 2699 2700 int ff_AMediaFormatColorStandard_from_AVColorSpace(enum AVColorSpace color_space) 2701 { 2702 for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++) 2703 if (color_space_map[i].space == color_space) 2704 return color_space_map[i].mf_standard; 2705 2706 return COLOR_STANDARD_UNSPECIFIED; 2707 } 2708 2709 enum AVColorPrimaries ff_AMediaFormatColorStandard_to_AVColorPrimaries(int color_standard) 2710 { 2711 for (int i = 0; i < FF_ARRAY_ELEMS(color_primaries_map); i++) 2712 if (color_primaries_map[i].mf_standard == color_standard) 2713 return color_primaries_map[i].primaries; 2714 2715 return AVCOL_PRI_UNSPECIFIED; 2716 } 2717 2718 enum AVColorTransferCharacteristic 2719 ff_AMediaFormatColorTransfer_to_AVColorTransfer(int color_transfer) 2720 { 2721 for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++) 2722 if (color_transfer_map[i].mf_transfer == color_transfer) 2723 return color_transfer_map[i].transfer; 2724 2725 return AVCOL_TRC_UNSPECIFIED; 2726 } 2727 2728 int ff_AMediaFormatColorTransfer_from_AVColorTransfer( 2729 enum AVColorTransferCharacteristic color_transfer) 2730 { 2731 for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++) 2732 if (color_transfer_map[i].transfer == color_transfer) 2733 return color_transfer_map[i].mf_transfer; 2734 2735 return COLOR_TRANSFER_UNSPECIFIED; 2736 }