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
113};
114
115#define OFFSET(x) offsetof(struct JNIAMediaFormatFields, x)
116static 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
142 .class_name = "amediaformat",
143 .item_name = av_default_item_name,
144 .version = LIBAVUTIL_VERSION_INT,
145};
146
153
155
208
209#define OFFSET(x) offsetof(struct JNIAMediaCodecFields, x)
210static 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
264 .class_name = "amediacodec",
265 .item_name = av_default_item_name,
266 .version = LIBAVUTIL_VERSION_INT,
267};
268
292
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
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) {
376 return AVCProfileBaseline;
378 return AVCProfileConstrainedBaseline;
380 return AVCProfileMain;
381 break;
383 return AVCProfileExtended;
385 return AVCProfileHigh;
388 return AVCProfileHigh10;
391 return AVCProfileHigh422;
395 return AVCProfileHigh444;
396 }
397 } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
398 switch (avctx->profile) {
400 return HEVCProfileMain;
402 return HEVCProfileMainStill;
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 {
421 return MPEG4ProfileSimple;
423 return MPEG4ProfileSimpleScalable;
425 return MPEG4ProfileCore;
427 return MPEG4ProfileMain;
429 return MPEG4ProfileNbit;
431 return MPEG4ProfileScalableTexture;
433 return MPEG4ProfileSimpleFBA;
435 return MPEG4ProfileBasicAnimated;
437 return MPEG4ProfileHybrid;
439 return MPEG4ProfileAdvancedRealTime;
441 return MPEG4ProfileCoreScalable;
443 return MPEG4ProfileAdvancedCoding;
445 return MPEG4ProfileAdvancedCore;
447 return MPEG4ProfileAdvancedScalable;
449 return MPEG4ProfileAdvancedSimple;
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 {
459 return AV1ProfileMain8;
462 default:
463 break;
464 }
465 }
466
467 return -1;
468}
469
470char *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
626done_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
643done_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
657done:
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
679{
680 JNIEnv *env = NULL;
682 jobject object = NULL;
683
684 format = av_mallocz(sizeof(*format));
685 if (!format) {
686 return NULL;
687 }
689
690 env = ff_jni_get_env(format);
691 if (!env) {
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
710fail:
711 (*env)->DeleteLocalRef(env, object);
712
713 if (!format->object) {
716 }
717
718 return (FFAMediaFormat *)format;
719}
720
722{
723 JNIEnv *env = NULL;
725
726 format = av_mallocz(sizeof(*format));
727 if (!format) {
728 return NULL;
729 }
731
732 env = ff_jni_get_env(format);
733 if (!env) {
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;
748fail:
750
752
753 return NULL;
754}
755
757{
758 int ret = 0;
760 JNIEnv *env = NULL;
761
762 if (!format) {
763 return 0;
764 }
765
767
768 (*env)->DeleteGlobalRef(env, format->object);
769 format->object = NULL;
770
772
774
775 return ret;
776}
777
779{
780 char *ret = NULL;
782 JNIEnv *env = NULL;
783 jstring description = NULL;
784
786
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);
795fail:
796 (*env)->DeleteLocalRef(env, description);
797
798 return ret;
799}
800
802{
803 int ret = 1;
805 JNIEnv *env = NULL;
806 jstring key = NULL;
807 jboolean contains_key;
808
810
812
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;
832fail:
833 (*env)->DeleteLocalRef(env, key);
834
835 return ret;
836}
837
839{
840 int ret = 1;
842 JNIEnv *env = NULL;
843 jstring key = NULL;
844 jboolean contains_key;
845
847
849
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;
869fail:
870 (*env)->DeleteLocalRef(env, key);
871
872 return ret;
873}
874
875static int mediaformat_jni_getFloat(FFAMediaFormat* ctx, const char *name, float *out)
876{
877 int ret = 1;
879 JNIEnv *env = NULL;
880 jstring key = NULL;
881 jboolean contains_key;
882
884
886
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;
906fail:
907 (*env)->DeleteLocalRef(env, key);
908
909 return ret;
910}
911
912static int mediaformat_jni_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size)
913{
914 int ret = 1;
916 JNIEnv *env = NULL;
917 jstring key = NULL;
918 jboolean contains_key;
919 jobject result = NULL;
920
922
924
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;
958fail:
959 (*env)->DeleteLocalRef(env, key);
960 (*env)->DeleteLocalRef(env, result);
961
962 return ret;
963}
964
965static int mediaformat_jni_getString(FFAMediaFormat* ctx, const char *name, const char **out)
966{
967 int ret = 1;
969 JNIEnv *env = NULL;
970 jstring key = NULL;
971 jboolean contains_key;
972 jstring result = NULL;
973
975
977
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;
1003fail:
1004 (*env)->DeleteLocalRef(env, key);
1005 (*env)->DeleteLocalRef(env, result);
1006
1007 return ret;
1008}
1009
1011{
1012 JNIEnv *env = NULL;
1013 jstring key = NULL;
1015
1017
1019
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
1030fail:
1031 (*env)->DeleteLocalRef(env, key);
1032}
1033
1035{
1036 JNIEnv *env = NULL;
1037 jstring key = NULL;
1039
1041
1043
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
1054fail:
1055 (*env)->DeleteLocalRef(env, key);
1056}
1057
1058static void mediaformat_jni_setFloat(FFAMediaFormat* ctx, const char* name, float value)
1059{
1060 JNIEnv *env = NULL;
1061 jstring key = NULL;
1063
1065
1067
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
1078fail:
1079 (*env)->DeleteLocalRef(env, key);
1080}
1081
1082static 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;
1088
1090
1092
1094 if (!key) {
1095 goto fail;
1096 }
1097
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
1108fail:
1109 (*env)->DeleteLocalRef(env, key);
1110 (*env)->DeleteLocalRef(env, string);
1111}
1112
1113static 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;
1120
1122
1124
1126 if (!key) {
1127 goto fail;
1128 }
1129
1130 if (!data || !size) {
1131 goto fail;
1132 }
1133
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
1151fail:
1152 (*env)->DeleteLocalRef(env, key);
1153 (*env)->DeleteLocalRef(env, buffer);
1154}
1155
1157{
1158 int ret = 0;
1159 JNIEnv *env = NULL;
1160
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
1205fail:
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
1214static 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,
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
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;
1285fail:
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) \
1302static FFAMediaCodec *mediacodec_jni_##name(const char *arg) \
1303{ \
1304 return codec_create(method, arg); \
1305} \
1306
1310
1312{
1313 int ret = 0;
1315 JNIEnv *env = NULL;
1316
1317 if (!codec) {
1318 return 0;
1319 }
1320
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
1348{
1349 char *ret = NULL;
1350 JNIEnv *env = NULL;
1351 jobject *name = NULL;
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
1363fail:
1364 if (name) {
1365 (*env)->DeleteLocalRef(env, name);
1366 }
1367
1368 return ret;
1369}
1370
1372 const FFAMediaFormat* format_ctx,
1374 void *crypto,
1375 uint32_t flags)
1376{
1377 int ret = 0;
1378 JNIEnv *env = NULL;
1380 const FFAMediaFormatJni *format = (FFAMediaFormatJni *)format_ctx;
1381 jobject *surface = window ? window->surface : NULL;
1382
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
1410fail:
1411 return ret;
1412}
1413
1415{
1416 int ret = 0;
1417 JNIEnv *env = NULL;
1419
1421
1422 (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1423 if (ff_jni_exception_check(env, 1, codec) < 0) {
1424 ret = AVERROR_EXTERNAL;
1425 goto fail;
1426 }
1427
1428fail:
1429 return ret;
1430}
1431
1433{
1434 int ret = 0;
1435 JNIEnv *env = NULL;
1437
1439
1440 (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1441 if (ff_jni_exception_check(env, 1, codec) < 0) {
1442 ret = AVERROR_EXTERNAL;
1443 goto fail;
1444 }
1445
1446fail:
1447 return ret;
1448}
1449
1451{
1452 int ret = 0;
1453 JNIEnv *env = NULL;
1455
1457
1458 (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1459 if (ff_jni_exception_check(env, 1, codec) < 0) {
1460 ret = AVERROR_EXTERNAL;
1461 goto fail;
1462 }
1463
1464fail:
1465 return ret;
1466}
1467
1468static int mediacodec_jni_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render)
1469{
1470 int ret = 0;
1471 JNIEnv *env = NULL;
1473
1475
1476 (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render);
1477 if (ff_jni_exception_check(env, 1, codec) < 0) {
1478 ret = AVERROR_EXTERNAL;
1479 goto fail;
1480 }
1481
1482fail:
1483 return ret;
1484}
1485
1487{
1488 int ret = 0;
1489 JNIEnv *env = NULL;
1491
1493
1494 (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
1495 if (ff_jni_exception_check(env, 1, codec) < 0) {
1496 ret = AVERROR_EXTERNAL;
1497 goto fail;
1498 }
1499
1500fail:
1501 return ret;
1502}
1503
1505{
1506 int ret = 0;
1507 JNIEnv *env = NULL;
1509
1511
1512 ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1513 if (ff_jni_exception_check(env, 1, codec) < 0) {
1514 ret = AVERROR_EXTERNAL;
1515 goto fail;
1516 }
1517
1518fail:
1519 return ret;
1520}
1521
1522static int mediacodec_jni_queueInputBuffer(FFAMediaCodec* ctx, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1523{
1524 int ret = 0;
1525 JNIEnv *env = NULL;
1527
1529
1530 (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags);
1531 if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1532 ret = AVERROR_EXTERNAL;
1533 goto fail;
1534 }
1535
1536fail:
1537 return ret;
1538}
1539
1541{
1542 int ret = 0;
1543 JNIEnv *env = NULL;
1545
1547
1548 ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs);
1549 if (ff_jni_exception_check(env, 1, codec) < 0) {
1550 return AVERROR_EXTERNAL;
1551 }
1552
1553 info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id);
1554 if (ff_jni_exception_check(env, 1, codec) < 0) {
1555 return AVERROR_EXTERNAL;
1556 }
1557
1558 info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id);
1559 if (ff_jni_exception_check(env, 1, codec) < 0) {
1560 return AVERROR_EXTERNAL;
1561 }
1562
1563 info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id);
1564 if (ff_jni_exception_check(env, 1, codec) < 0) {
1565 return AVERROR_EXTERNAL;
1566 }
1567
1568 info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id);
1569 if (ff_jni_exception_check(env, 1, codec) < 0) {
1570 return AVERROR_EXTERNAL;
1571 }
1572
1573 return ret;
1574}
1575
1576static uint8_t* mediacodec_jni_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
1577{
1578 uint8_t *ret = NULL;
1579 JNIEnv *env = NULL;
1581 jobject buffer = NULL;
1582 jobject input_buffers = NULL;
1583
1584 JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1585
1586 if (codec->has_get_i_o_buffer) {
1587 buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx);
1588 if (ff_jni_exception_check(env, 1, codec) < 0) {
1589 goto fail;
1590 }
1591 } else {
1592 if (!codec->input_buffers) {
1593 input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1594 if (ff_jni_exception_check(env, 1, codec) < 0) {
1595 goto fail;
1596 }
1597
1598 codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers);
1599 if (ff_jni_exception_check(env, 1, codec) < 0) {
1600 goto fail;
1601 }
1602 }
1603
1604 buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1605 if (ff_jni_exception_check(env, 1, codec) < 0) {
1606 goto fail;
1607 }
1608 }
1609
1610 ret = (*env)->GetDirectBufferAddress(env, buffer);
1611 *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1612fail:
1613 (*env)->DeleteLocalRef(env, buffer);
1614 (*env)->DeleteLocalRef(env, input_buffers);
1615
1616 return ret;
1617}
1618
1619static uint8_t* mediacodec_jni_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
1620{
1621 uint8_t *ret = NULL;
1622 JNIEnv *env = NULL;
1624 jobject buffer = NULL;
1625 jobject output_buffers = NULL;
1626
1627 JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1628
1629 if (codec->has_get_i_o_buffer) {
1630 buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx);
1631 if (ff_jni_exception_check(env, 1, codec) < 0) {
1632 goto fail;
1633 }
1634 } else {
1635 if (!codec->output_buffers) {
1636 output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1637 if (ff_jni_exception_check(env, 1, codec) < 0) {
1638 goto fail;
1639 }
1640
1641 codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers);
1642 if (ff_jni_exception_check(env, 1, codec) < 0) {
1643 goto fail;
1644 }
1645 }
1646
1647 buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1648 if (ff_jni_exception_check(env, 1, codec) < 0) {
1649 goto fail;
1650 }
1651 }
1652
1653 ret = (*env)->GetDirectBufferAddress(env, buffer);
1654 *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1655fail:
1656 (*env)->DeleteLocalRef(env, buffer);
1657 (*env)->DeleteLocalRef(env, output_buffers);
1658
1659 return ret;
1660}
1661
1663{
1664 FFAMediaFormat *ret = NULL;
1665 JNIEnv *env = NULL;
1667
1668 jobject mediaformat = NULL;
1669
1670 JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1671
1672 mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1673 if (ff_jni_exception_check(env, 1, codec) < 0) {
1674 goto fail;
1675 }
1676
1677 ret = mediaformat_jni_newFromObject(mediaformat);
1678fail:
1679 (*env)->DeleteLocalRef(env, mediaformat);
1680
1681 return ret;
1682}
1683
1685{
1687 return idx == codec->INFO_TRY_AGAIN_LATER;
1688}
1689
1691{
1693 return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1694}
1695
1697{
1699 return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1700}
1701
1707
1713
1719
1725
1727{
1728 int ret = 0;
1730
1731 if (!codec->has_get_i_o_buffer) {
1732 if (codec->output_buffers) {
1733 JNIEnv *env = NULL;
1734
1735 env = ff_jni_get_env(codec);
1736 if (!env) {
1737 ret = AVERROR_EXTERNAL;
1738 goto fail;
1739 }
1740
1741 (*env)->DeleteGlobalRef(env, codec->output_buffers);
1742 codec->output_buffers = NULL;
1743 }
1744 }
1745
1746fail:
1747 return ret;
1748}
1749
1751{
1752 JNIEnv *env = NULL;
1754
1756
1757 (*env)->CallVoidMethod(env, codec->object, codec->jfields.signal_end_of_input_stream_id);
1758 if (ff_jni_exception_check(env, 1, codec) < 0) {
1759 return AVERROR_EXTERNAL;
1760 }
1761
1762 return 0;
1763}
1764
1767 void *userdata)
1768{
1769 av_log(codec, AV_LOG_ERROR, "Doesn't support aync mode with JNI, please try ndk_codec=1\n");
1770 return AVERROR(ENOSYS);
1771}
1772
1773static const FFAMediaFormat media_format_jni = {
1774 .class = &amediaformat_class,
1775
1776 .create = mediaformat_jni_new,
1777 .delete = mediaformat_jni_delete,
1778
1779 .toString = mediaformat_jni_toString,
1780
1781 .getInt32 = mediaformat_jni_getInt32,
1782 .getInt64 = mediaformat_jni_getInt64,
1783 .getFloat = mediaformat_jni_getFloat,
1784 .getBuffer = mediaformat_jni_getBuffer,
1785 .getString = mediaformat_jni_getString,
1786
1787 .setInt32 = mediaformat_jni_setInt32,
1788 .setInt64 = mediaformat_jni_setInt64,
1789 .setFloat = mediaformat_jni_setFloat,
1790 .setString = mediaformat_jni_setString,
1791 .setBuffer = mediaformat_jni_setBuffer,
1792};
1793
1794static const FFAMediaCodec media_codec_jni = {
1795 .class = &amediacodec_class,
1796
1797 .getName = mediacodec_jni_getName,
1798
1799 .createCodecByName = mediacodec_jni_createCodecByName,
1800 .createDecoderByType = mediacodec_jni_createDecoderByType,
1801 .createEncoderByType = mediacodec_jni_createEncoderByType,
1802 .delete = mediacodec_jni_delete,
1803
1804 .configure = mediacodec_jni_configure,
1805 .start = mediacodec_jni_start,
1806 .stop = mediacodec_jni_stop,
1807 .flush = mediacodec_jni_flush,
1808
1809 .getInputBuffer = mediacodec_jni_getInputBuffer,
1810 .getOutputBuffer = mediacodec_jni_getOutputBuffer,
1811
1812 .dequeueInputBuffer = mediacodec_jni_dequeueInputBuffer,
1813 .queueInputBuffer = mediacodec_jni_queueInputBuffer,
1814
1815 .dequeueOutputBuffer = mediacodec_jni_dequeueOutputBuffer,
1816 .getOutputFormat = mediacodec_jni_getOutputFormat,
1817
1818 .releaseOutputBuffer = mediacodec_jni_releaseOutputBuffer,
1819 .releaseOutputBufferAtTime = mediacodec_jni_releaseOutputBufferAtTime,
1820
1821 .infoTryAgainLater = mediacodec_jni_infoTryAgainLater,
1822 .infoOutputBuffersChanged = mediacodec_jni_infoOutputBuffersChanged,
1823 .infoOutputFormatChanged = mediacodec_jni_infoOutputFormatChanged,
1824
1825 .getBufferFlagCodecConfig = mediacodec_jni_getBufferFlagCodecConfig,
1826 .getBufferFlagEndOfStream = mediacodec_jni_getBufferFlagEndOfStream,
1827 .getBufferFlagKeyFrame = mediacodec_jni_getBufferFlagKeyFrame,
1828
1829 .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
1830 .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
1831 .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
1832 .setAsyncNotifyCallback = mediacodec_jni_setAsyncNotifyCallback,
1833};
1834
1835typedef struct FFAMediaFormatNdk {
1837
1839 AMediaFormat *impl;
1840
1841 bool (*getRect)(AMediaFormat *, const char *name,
1842 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom);
1843 void (*setRect)(AMediaFormat *, const char *name,
1844 int32_t left, int32_t top, int32_t right, int32_t bottom);
1846
1847typedef struct FFAMediaCodecNdk {
1849
1851 AMediaCodec *impl;
1852 ANativeWindow *window;
1853
1856
1857 // Available since API level 28.
1858 media_status_t (*getName)(AMediaCodec*, char** out_name);
1859 void (*releaseName)(AMediaCodec*, char* name);
1860
1861 // Available since API level 26.
1862 media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *);
1863 media_status_t (*signalEndOfInputStream)(AMediaCodec *);
1864 media_status_t (*setAsyncNotifyCallback)(AMediaCodec *,
1865 struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata);
1867
1870
1872 .class_name = "amediaformat_ndk",
1873 .item_name = av_default_item_name,
1874 .version = LIBAVUTIL_VERSION_INT,
1875};
1876
1878 .class_name = "amediacodec_ndk",
1879 .item_name = av_default_item_name,
1880 .version = LIBAVUTIL_VERSION_INT,
1881};
1882
1883static int media_status_to_error(media_status_t status)
1884{
1885 switch (status) {
1886 case AMEDIA_OK:
1887 return 0;
1888 case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE:
1889 return AVERROR(ENOMEM);
1890 case AMEDIA_ERROR_MALFORMED:
1891 return AVERROR_INVALIDDATA;
1892 case AMEDIA_ERROR_UNSUPPORTED:
1893 return AVERROR(ENOTSUP);
1894 case AMEDIA_ERROR_INVALID_PARAMETER:
1895 return AVERROR(EINVAL);
1896 case AMEDIA_ERROR_INVALID_OPERATION:
1897 return AVERROR(EOPNOTSUPP);
1898 case AMEDIA_ERROR_END_OF_STREAM:
1899 return AVERROR_EOF;
1900 case AMEDIA_ERROR_IO:
1901 return AVERROR(EIO);
1902 case AMEDIA_ERROR_WOULD_BLOCK:
1903 return AVERROR(EWOULDBLOCK);
1904 default:
1905 return AVERROR_EXTERNAL;
1906 }
1907}
1908
1909static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl)
1910{
1912 if (!format)
1913 return NULL;
1914
1915 format->api = media_format_ndk;
1916
1917 format->libmedia = dlopen("libmediandk.so", RTLD_NOW);
1918 if (!format->libmedia)
1919 goto error;
1920
1921#define GET_OPTIONAL_SYMBOL(sym) \
1922 format->sym = dlsym(format->libmedia, "AMediaFormat_" #sym);
1923
1924 GET_OPTIONAL_SYMBOL(getRect)
1925 GET_OPTIONAL_SYMBOL(setRect)
1926
1927#undef GET_OPTIONAL_SYMBOL
1928
1929 if (impl) {
1930 format->impl = impl;
1931 } else {
1932 format->impl = AMediaFormat_new();
1933 if (!format->impl)
1934 goto error;
1935 }
1936
1937 return (FFAMediaFormat *)format;
1938
1939error:
1940 if (format->libmedia)
1941 dlclose(format->libmedia);
1942 av_freep(&format);
1943 return NULL;
1944}
1945
1947{
1949}
1950
1952{
1954 int ret = 0;
1955 if (!format)
1956 return 0;
1957
1959
1960 if (format->impl && (AMediaFormat_delete(format->impl) != AMEDIA_OK))
1961 ret = AVERROR_EXTERNAL;
1962 if (format->libmedia)
1963 dlclose(format->libmedia);
1964 av_free(format);
1965
1966 return ret;
1967}
1968
1970{
1972 const char *str = AMediaFormat_toString(format->impl);
1973 return av_strdup(str);
1974}
1975
1977{
1979 return AMediaFormat_getInt32(format->impl, name, out);
1980}
1981
1983{
1985 return AMediaFormat_getInt64(format->impl, name, out);
1986}
1987
1988static int mediaformat_ndk_getFloat(FFAMediaFormat* ctx, const char *name, float *out)
1989{
1991 return AMediaFormat_getFloat(format->impl, name, out);
1992}
1993
1994static int mediaformat_ndk_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size)
1995{
1997 return AMediaFormat_getBuffer(format->impl, name, data, size);
1998}
1999
2000static int mediaformat_ndk_getString(FFAMediaFormat* ctx, const char *name, const char **out)
2001{
2003 const char *tmp = NULL;
2004 int ret = AMediaFormat_getString(format->impl, name, &tmp);
2005
2006 if (tmp)
2007 *out = av_strdup(tmp);
2008 return ret;
2009}
2010
2012 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom)
2013{
2015 if (!format->getRect)
2016 return AVERROR_EXTERNAL;
2017 return format->getRect(format->impl, name, left, top, right, bottom);
2018}
2019
2021{
2023 AMediaFormat_setInt32(format->impl, name, value);
2024}
2025
2027{
2029 AMediaFormat_setInt64(format->impl, name, value);
2030}
2031
2032static void mediaformat_ndk_setFloat(FFAMediaFormat* ctx, const char* name, float value)
2033{
2035 AMediaFormat_setFloat(format->impl, name, value);
2036}
2037
2038static void mediaformat_ndk_setString(FFAMediaFormat* ctx, const char* name, const char* value)
2039{
2041 AMediaFormat_setString(format->impl, name, value);
2042}
2043
2044static void mediaformat_ndk_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size)
2045{
2047 AMediaFormat_setBuffer(format->impl, name, data, size);
2048}
2049
2051 int32_t left, int32_t top, int32_t right, int32_t bottom)
2052{
2054 if (!format->setRect) {
2055 av_log(ctx, AV_LOG_WARNING, "Doesn't support setRect\n");
2056 return;
2057 }
2058 format->setRect(format->impl, name, left, top, right, bottom);
2059}
2060
2062{
2064 char *ret = NULL;
2065 char *name = NULL;
2066
2067 if (!codec->getName || !codec->releaseName) {
2068 av_log(ctx, AV_LOG_DEBUG, "getName() unavailable\n");
2069 return ret;
2070 }
2071
2072 codec->getName(codec->impl, &name);
2073 if (name) {
2074 ret = av_strdup(name);
2075 codec->releaseName(codec->impl, name);
2076 }
2077
2078 return ret;
2079}
2080
2081static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) {
2082 FFAMediaCodecNdk *codec = av_mallocz(sizeof(*codec));
2083 const char *lib_name = "libmediandk.so";
2084
2085 if (!codec)
2086 return NULL;
2087
2088 codec->api = media_codec_ndk;
2089 codec->libmedia = dlopen(lib_name, RTLD_NOW);
2090 if (!codec->libmedia)
2091 goto error;
2092
2093#define GET_SYMBOL(sym) \
2094 codec->sym = dlsym(codec->libmedia, "AMediaCodec_" #sym); \
2095 if (!codec->sym) \
2096 av_log(codec, AV_LOG_INFO, #sym "() unavailable from %s\n", lib_name);
2097
2098 GET_SYMBOL(getName)
2099 GET_SYMBOL(releaseName)
2100
2101 GET_SYMBOL(setInputSurface)
2102 GET_SYMBOL(signalEndOfInputStream)
2103 GET_SYMBOL(setAsyncNotifyCallback)
2104
2105#undef GET_SYMBOL
2106
2107 switch (method) {
2109 codec->impl = AMediaCodec_createCodecByName(arg);
2110 break;
2112 codec->impl = AMediaCodec_createDecoderByType(arg);
2113 break;
2115 codec->impl = AMediaCodec_createEncoderByType(arg);
2116 break;
2117 default:
2118 av_assert0(0);
2119 }
2120 if (!codec->impl)
2121 goto error;
2122
2123 return (FFAMediaCodec *)codec;
2124
2125error:
2126 if (codec->libmedia)
2127 dlclose(codec->libmedia);
2128 av_freep(&codec);
2129 return NULL;
2130}
2131
2132#define DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(name, method) \
2133static FFAMediaCodec *mediacodec_ndk_##name(const char *arg) \
2134{ \
2135 return ndk_codec_create(method, arg); \
2136} \
2137
2141
2143{
2145 int ret = 0;
2146
2147 if (!codec)
2148 return 0;
2149
2151
2152 if (codec->impl && (AMediaCodec_delete(codec->impl) != AMEDIA_OK))
2153 ret = AVERROR_EXTERNAL;
2154 if (codec->window)
2155 ANativeWindow_release(codec->window);
2156 if (codec->libmedia)
2157 dlclose(codec->libmedia);
2158 av_free(codec);
2159
2160 return ret;
2161}
2162
2164 const FFAMediaFormat* format_ctx,
2166 void *crypto,
2167 uint32_t flags)
2168{
2171 media_status_t status;
2172 ANativeWindow *native_window = NULL;
2173
2174 if (window) {
2175 if (window->surface) {
2176 JNIEnv *env = NULL;
2177 JNI_GET_ENV_OR_RETURN(env, ctx, -1);
2178 native_window = ANativeWindow_fromSurface(env, window->surface);
2179 // Save for release
2180 codec->window = native_window;
2181 } else if (window->native_window) {
2182 native_window = window->native_window;
2183 }
2184 }
2185
2186 if (format_ctx->class != &amediaformat_ndk_class) {
2187 av_log(ctx, AV_LOG_ERROR, "invalid media format\n");
2188 return AVERROR(EINVAL);
2189 }
2190
2191 if (flags & AMEDIACODEC_CONFIGURE_FLAG_ENCODE) {
2192 if (native_window && !codec->setInputSurface) {
2193 av_log(ctx, AV_LOG_ERROR, "System doesn't support setInputSurface\n");
2194 return AVERROR_EXTERNAL;
2195 }
2196
2197 status = AMediaCodec_configure(codec->impl, format->impl, NULL, NULL, flags);
2198 if (status != AMEDIA_OK) {
2199 av_log(codec, AV_LOG_ERROR, "Encoder configure failed, %d\n", status);
2200 return AVERROR_EXTERNAL;
2201 }
2202
2203 if (!native_window)
2204 return 0;
2205
2206 status = codec->setInputSurface(codec->impl, native_window);
2207 if (status != AMEDIA_OK) {
2208 av_log(codec, AV_LOG_ERROR, "Encoder set input surface failed, %d\n", status);
2209 return AVERROR_EXTERNAL;
2210 }
2211 } else {
2212 status = AMediaCodec_configure(codec->impl, format->impl, native_window, NULL, flags);
2213 if (status != AMEDIA_OK) {
2214 av_log(codec, AV_LOG_ERROR, "Decoder configure failed, %d\n", status);
2215 return AVERROR_EXTERNAL;
2216 }
2217 }
2218
2219 return 0;
2220}
2221
2222#define MEDIACODEC_NDK_WRAPPER(method) \
2223static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx) \
2224{ \
2225 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; \
2226 media_status_t status = AMediaCodec_ ## method (codec->impl); \
2227 \
2228 if (status != AMEDIA_OK) { \
2229 av_log(codec, AV_LOG_ERROR, #method " failed, %d\n", status); \
2230 return AVERROR_EXTERNAL; \
2231 } \
2232 \
2233 return 0; \
2234} \
2235
2239
2240static uint8_t* mediacodec_ndk_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
2241{
2243 return AMediaCodec_getInputBuffer(codec->impl, idx, out_size);
2244}
2245
2246static uint8_t* mediacodec_ndk_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
2247{
2249 return AMediaCodec_getOutputBuffer(codec->impl, idx, out_size);
2250}
2251
2253{
2255 return AMediaCodec_dequeueInputBuffer(codec->impl, timeoutUs);
2256}
2257
2259 off_t offset, size_t size,
2260 uint64_t time, uint32_t flags)
2261{
2263 return AMediaCodec_queueInputBuffer(codec->impl, idx, offset, size, time, flags);
2264}
2265
2267{
2269 AMediaCodecBufferInfo buf_info = {0};
2270 ssize_t ret;
2271
2272 ret = AMediaCodec_dequeueOutputBuffer(codec->impl, &buf_info, timeoutUs);
2273 info->offset = buf_info.offset;
2274 info->size = buf_info.size;
2275 info->presentationTimeUs = buf_info.presentationTimeUs;
2276 info->flags = buf_info.flags;
2277
2278 return ret;
2279}
2280
2282{
2284 AMediaFormat *format = AMediaCodec_getOutputFormat(codec->impl);
2285
2286 if (!format)
2287 return NULL;
2289}
2290
2291static int mediacodec_ndk_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render)
2292{
2294 media_status_t status;
2295
2296 status = AMediaCodec_releaseOutputBuffer(codec->impl, idx, render);
2297 if (status != AMEDIA_OK) {
2298 av_log(codec, AV_LOG_ERROR, "release output buffer failed, %d\n", status);
2299 return AVERROR_EXTERNAL;
2300 }
2301
2302 return 0;
2303}
2304
2306{
2308 media_status_t status;
2309
2310 status = AMediaCodec_releaseOutputBufferAtTime(codec->impl, idx, timestampNs);
2311 if (status != AMEDIA_OK) {
2312 av_log(codec, AV_LOG_ERROR, "releaseOutputBufferAtTime failed, %d\n", status);
2313 return AVERROR_EXTERNAL;
2314 }
2315
2316 return 0;
2317}
2318
2320{
2321 return idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER;
2322}
2323
2325{
2326 return idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
2327}
2328
2330{
2331 return idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
2332}
2333
2335{
2336 return AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
2337}
2338
2340{
2341 return AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
2342}
2343
2345{
2346 return 1;
2347}
2348
2350{
2351 return AMEDIACODEC_CONFIGURE_FLAG_ENCODE;
2352}
2353
2355{
2356 return 0;
2357}
2358
2360{
2362 media_status_t status;
2363
2364 if (!codec->signalEndOfInputStream) {
2365 av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream unavailable\n");
2366 return AVERROR_EXTERNAL;
2367 }
2368
2369 status = codec->signalEndOfInputStream(codec->impl);
2370 if (status != AMEDIA_OK) {
2371 av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream failed, %d\n", status);
2372 return AVERROR_EXTERNAL;
2373 }
2374 av_log(codec, AV_LOG_DEBUG, "signalEndOfInputStream success\n");
2375
2376 return 0;
2377}
2378
2379static void mediacodec_ndk_onInputAvailable(AMediaCodec *impl, void *userdata,
2380 int32_t index)
2381{
2382 FFAMediaCodecNdk *codec = userdata;
2384 codec->async_userdata, index);
2385}
2386
2387static void mediacodec_ndk_onOutputAvailable(AMediaCodec *impl,
2388 void *userdata,
2389 int32_t index,
2390 AMediaCodecBufferInfo *buffer_info)
2391{
2392 FFAMediaCodecNdk *codec = userdata;
2394 .offset = buffer_info->offset,
2395 .size = buffer_info->size,
2396 .presentationTimeUs = buffer_info->presentationTimeUs,
2397 .flags = buffer_info->flags,
2398 };
2399
2400 codec->async_cb.onAsyncOutputAvailable(&codec->api, codec->async_userdata,
2401 index, &info);
2402}
2403
2404static void mediacodec_ndk_onFormatChanged(AMediaCodec *impl, void *userdata,
2405 AMediaFormat *format)
2406{
2407 FFAMediaCodecNdk *codec = userdata;
2409 if (!media_format)
2410 return;
2411
2412 codec->async_cb.onAsyncFormatChanged(&codec->api, codec->async_userdata,
2413 media_format);
2414 ff_AMediaFormat_delete(media_format);
2415}
2416
2417static void mediacodec_ndk_onError(AMediaCodec *impl, void *userdata,
2418 media_status_t status,
2419 int32_t actionCode,
2420 const char *detail)
2421{
2422 FFAMediaCodecNdk *codec = userdata;
2423 int error = media_status_to_error(status);
2424
2425 codec->async_cb.onAsyncError(&codec->api, codec->async_userdata, error,
2426 detail);
2427}
2428
2431 void *userdata)
2432{
2434 struct AMediaCodecOnAsyncNotifyCallback cb = {
2435 .onAsyncInputAvailable = mediacodec_ndk_onInputAvailable,
2436 .onAsyncOutputAvailable = mediacodec_ndk_onOutputAvailable,
2437 .onAsyncFormatChanged = mediacodec_ndk_onFormatChanged,
2438 .onAsyncError = mediacodec_ndk_onError,
2439 };
2440 media_status_t status;
2441
2442 if (!codec->setAsyncNotifyCallback) {
2443 av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback unavailable\n");
2444 return AVERROR(ENOSYS);
2445 }
2446
2447 if (!callback ||
2448 !callback->onAsyncInputAvailable ||
2449 !callback->onAsyncOutputAvailable ||
2450 !callback->onAsyncFormatChanged ||
2451 !callback->onAsyncError)
2452 return AVERROR(EINVAL);
2453
2454 codec->async_cb = *callback;
2455 codec->async_userdata = userdata;
2456
2457 status = codec->setAsyncNotifyCallback(codec->impl, cb, codec);
2458 if (status != AMEDIA_OK) {
2459 av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback failed, %d\n",
2460 status);
2461 return AVERROR_EXTERNAL;
2462 }
2463
2464 return 0;
2465}
2466
2467static const FFAMediaFormat media_format_ndk = {
2468 .class = &amediaformat_ndk_class,
2469
2470 .create = mediaformat_ndk_new,
2471 .delete = mediaformat_ndk_delete,
2472
2473 .toString = mediaformat_ndk_toString,
2474
2475 .getInt32 = mediaformat_ndk_getInt32,
2476 .getInt64 = mediaformat_ndk_getInt64,
2477 .getFloat = mediaformat_ndk_getFloat,
2478 .getBuffer = mediaformat_ndk_getBuffer,
2479 .getString = mediaformat_ndk_getString,
2480 .getRect = mediaformat_ndk_getRect,
2481
2482 .setInt32 = mediaformat_ndk_setInt32,
2483 .setInt64 = mediaformat_ndk_setInt64,
2484 .setFloat = mediaformat_ndk_setFloat,
2485 .setString = mediaformat_ndk_setString,
2486 .setBuffer = mediaformat_ndk_setBuffer,
2487 .setRect = mediaformat_ndk_setRect,
2488};
2489
2490static const FFAMediaCodec media_codec_ndk = {
2491 .class = &amediacodec_ndk_class,
2492
2493 .getName = mediacodec_ndk_getName,
2494
2495 .createCodecByName = mediacodec_ndk_createCodecByName,
2496 .createDecoderByType = mediacodec_ndk_createDecoderByType,
2497 .createEncoderByType = mediacodec_ndk_createEncoderByType,
2498 .delete = mediacodec_ndk_delete,
2499
2500 .configure = mediacodec_ndk_configure,
2501 .start = mediacodec_ndk_start,
2502 .stop = mediacodec_ndk_stop,
2503 .flush = mediacodec_ndk_flush,
2504
2505 .getInputBuffer = mediacodec_ndk_getInputBuffer,
2506 .getOutputBuffer = mediacodec_ndk_getOutputBuffer,
2507
2508 .dequeueInputBuffer = mediacodec_ndk_dequeueInputBuffer,
2509 .queueInputBuffer = mediacodec_ndk_queueInputBuffer,
2510
2511 .dequeueOutputBuffer = mediacodec_ndk_dequeueOutputBuffer,
2512 .getOutputFormat = mediacodec_ndk_getOutputFormat,
2513
2514 .releaseOutputBuffer = mediacodec_ndk_releaseOutputBuffer,
2515 .releaseOutputBufferAtTime = mediacodec_ndk_releaseOutputBufferAtTime,
2516
2517 .infoTryAgainLater = mediacodec_ndk_infoTryAgainLater,
2518 .infoOutputBuffersChanged = mediacodec_ndk_infoOutputBuffersChanged,
2519 .infoOutputFormatChanged = mediacodec_ndk_infoOutputFormatChanged,
2520
2521 .getBufferFlagCodecConfig = mediacodec_ndk_getBufferFlagCodecConfig,
2522 .getBufferFlagEndOfStream = mediacodec_ndk_getBufferFlagEndOfStream,
2523 .getBufferFlagKeyFrame = mediacodec_ndk_getBufferFlagKeyFrame,
2524
2525 .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
2526 .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
2527 .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
2528 .setAsyncNotifyCallback = mediacodec_ndk_setAsyncNotifyCallback,
2529};
2530
2532{
2533 if (ndk)
2534 return media_format_ndk.create();
2535 return media_format_jni.create();
2536}
2537
2539{
2540 if (ndk)
2541 return media_codec_ndk.createCodecByName(name);
2542 return media_codec_jni.createCodecByName(name);
2543}
2544
2546{
2547 if (ndk)
2548 return media_codec_ndk.createDecoderByType(mime_type);
2549 return media_codec_jni.createDecoderByType(mime_type);
2550}
2551
2553{
2554 if (ndk)
2555 return media_codec_ndk.createEncoderByType(mime_type);
2556 return media_codec_jni.createEncoderByType(mime_type);
2557}
2558
2560{
2561 int ret = -1;
2562
2563#if __ANDROID_API__ >= 24
2564 // android_get_device_api_level() is a static inline before API level 29.
2565 // dlsym() might doesn't work.
2566 //
2567 // We can implement android_get_device_api_level() by
2568 // __system_property_get(), but __system_property_get() has created a lot of
2569 // troubles and is deprecated. So avoid using __system_property_get() for
2570 // now.
2571 //
2572 // Hopy we can remove the conditional compilation finally by bumping the
2573 // required API level.
2574 //
2575 ret = android_get_device_api_level();
2576#else
2577 JNIEnv *env = NULL;
2578 jclass versionClass;
2579 jfieldID sdkIntFieldID;
2580 JNI_GET_ENV_OR_RETURN(env, avctx, -1);
2581
2582 versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
2583 sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
2584 ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
2585 (*env)->DeleteLocalRef(env, versionClass);
2586#endif
2587 av_log(avctx, AV_LOG_DEBUG, "device api level %d\n", ret);
2588
2589 return ret;
2590}
2591
2592static struct {
2595} color_range_map[] = {
2599
2600static struct {
2603} color_space_map[] = {
2609
2610static struct {
2613} color_primaries_map[] = {
2619
2620static struct {
2623} color_transfer_map[] = {
2629
2638
2646
2648{
2649 for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++)
2650 if (color_space_map[i].mf_standard == color_standard)
2651 return color_space_map[i].space;
2652
2653 return AVCOL_SPC_UNSPECIFIED;
2654}
2655
2657{
2658 for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++)
2659 if (color_space_map[i].space == color_space)
2660 return color_space_map[i].mf_standard;
2661
2663}
2664
2666{
2667 for (int i = 0; i < FF_ARRAY_ELEMS(color_primaries_map); i++)
2668 if (color_primaries_map[i].mf_standard == color_standard)
2669 return color_primaries_map[i].primaries;
2670
2671 return AVCOL_PRI_UNSPECIFIED;
2672}
2673
2676{
2677 for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++)
2678 if (color_transfer_map[i].mf_transfer == color_transfer)
2679 return color_transfer_map[i].transfer;
2680
2681 return AVCOL_TRC_UNSPECIFIED;
2682}
2683
2685 enum AVColorTransferCharacteristic color_transfer)
2686{
2687 for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++)
2688 if (color_transfer_map[i].transfer == color_transfer)
2689 return color_transfer_map[i].mf_transfer;
2690
2692}
static const char *const format[]
Definition af_aiir.c:444
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:1636
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 FILE * out
Definition movenc.c:55
static int out_size
Definition movenc.c:56
static AVFormatContext * ctx
Definition movenc.c:49
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