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