PR #22870 opened by padenot URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22870 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22870.patch
When the encoder receives a frame with pict_type == AV_PICTURE_TYPE_I, use AMediaCodec_setParameters with "request-sync" to request a sync frame from the Android MediaCodec encoder. Implement setParameters for both the JNI and NDK codec wrappers (JNI stub returns AVERROR_PATCHWELCOME as the JNI path does not support it). The NDK setParameters function pointer is loaded via dlsym (matching the pattern for other API 26 symbols in FFAMediaCodecNdk) so that the code degrades gracefully on older devices. No tests, but this has been tested both on CI (emulators) and real devices, when compiled in Firefox. Signed-off-by: Paul Adenot <[email protected]> >From fa6d161751fdec99d7a378cae38cf944de9b995d Mon Sep 17 00:00:00 2001 From: Andrew Osmond <[email protected]> Date: Mon, 20 Apr 2026 16:32:01 +0000 Subject: [PATCH] avcodec/mediacodecenc: allow forcing key frames via AMediaCodec_setParameters When the encoder receives a frame with pict_type == AV_PICTURE_TYPE_I, use AMediaCodec_setParameters with "request-sync" to request a sync frame from the Android MediaCodec encoder. Implement setParameters for both the JNI and NDK codec wrappers (JNI stub returns AVERROR_PATCHWELCOME as the JNI path does not support it). The NDK setParameters function pointer is loaded via dlsym (matching the pattern for other API 26 symbols in FFAMediaCodecNdk) so that the code degrades gracefully on older devices. Signed-off-by: Paul Adenot <[email protected]> --- libavcodec/mediacodec_wrapper.c | 36 +++++++++++++++++++++++++++++++++ libavcodec/mediacodec_wrapper.h | 7 +++++++ libavcodec/mediacodecenc.c | 13 ++++++++++++ 3 files changed, 56 insertions(+) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 283bbe72d6..68054c6be5 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -1411,6 +1411,12 @@ fail: return ret; } +static int mediacodec_jni_setParameters(FFAMediaCodec *ctx, + const FFAMediaFormat* format_ctx) +{ + return AVERROR_PATCHWELCOME; +} + static int mediacodec_jni_start(FFAMediaCodec* ctx) { int ret = 0; @@ -1802,6 +1808,7 @@ static const FFAMediaCodec media_codec_jni = { .delete = mediacodec_jni_delete, .configure = mediacodec_jni_configure, + .setParameters = mediacodec_jni_setParameters, .start = mediacodec_jni_start, .stop = mediacodec_jni_stop, .flush = mediacodec_jni_flush, @@ -1863,6 +1870,7 @@ typedef struct FFAMediaCodecNdk { media_status_t (*signalEndOfInputStream)(AMediaCodec *); media_status_t (*setAsyncNotifyCallback)(AMediaCodec *, struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata); + media_status_t (*setParameters)(AMediaCodec*, const AMediaFormat *); } FFAMediaCodecNdk; static const FFAMediaFormat media_format_ndk; @@ -2101,6 +2109,7 @@ static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) { GET_SYMBOL(setInputSurface) GET_SYMBOL(signalEndOfInputStream) GET_SYMBOL(setAsyncNotifyCallback) + GET_SYMBOL(setParameters) #undef GET_SYMBOL @@ -2219,6 +2228,32 @@ static int mediacodec_ndk_configure(FFAMediaCodec* ctx, return 0; } +static int mediacodec_ndk_setParameters(FFAMediaCodec *ctx, + const FFAMediaFormat* format_ctx) +{ + FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; + FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)format_ctx; + media_status_t status; + + if (format_ctx->class != &amediaformat_ndk_class) { + av_log(ctx, AV_LOG_ERROR, "invalid media format\n"); + return AVERROR(EINVAL); + } + + if (!codec->setParameters) { + av_log(ctx, AV_LOG_ERROR, "setParameters() unavailable\n"); + return AVERROR_EXTERNAL; + } + + status = codec->setParameters(codec->impl, format->impl); + if (status != AMEDIA_OK) { + av_log(codec, AV_LOG_ERROR, "setParameters failed, %d\n", status); + return AVERROR_EXTERNAL; + } + + return 0; +} + #define MEDIACODEC_NDK_WRAPPER(method) \ static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx) \ { \ @@ -2498,6 +2533,7 @@ static const FFAMediaCodec media_codec_ndk = { .delete = mediacodec_ndk_delete, .configure = mediacodec_ndk_configure, + .setParameters = mediacodec_ndk_setParameters, .start = mediacodec_ndk_start, .stop = mediacodec_ndk_stop, .flush = mediacodec_ndk_flush, diff --git a/libavcodec/mediacodec_wrapper.h b/libavcodec/mediacodec_wrapper.h index 18d0796445..3b3975a3b2 100644 --- a/libavcodec/mediacodec_wrapper.h +++ b/libavcodec/mediacodec_wrapper.h @@ -205,6 +205,7 @@ struct FFAMediaCodec { int (*delete)(FFAMediaCodec* codec); int (*configure)(FFAMediaCodec* codec, const FFAMediaFormat* format, FFANativeWindow* surface, void *crypto, uint32_t flags); + int (*setParameters)(FFAMediaCodec* codec, const FFAMediaFormat* format); int (*start)(FFAMediaCodec* codec); int (*stop)(FFAMediaCodec* codec); int (*flush)(FFAMediaCodec* codec); @@ -259,6 +260,12 @@ static inline int ff_AMediaCodec_configure(FFAMediaCodec *codec, return codec->configure(codec, format, surface, crypto, flags); } +static inline int ff_AMediaCodec_setParameters(FFAMediaCodec *codec, + const FFAMediaFormat *format) +{ + return codec->setParameters(codec, format); +} + static inline int ff_AMediaCodec_start(FFAMediaCodec* codec) { return codec->start(codec); diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index 507c48df9c..d76c56cf1c 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -827,6 +827,19 @@ static int mediacodec_send(AVCodecContext *avctx, copy_frame_to_buffer(avctx, frame, input_buf, input_size); pts = av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q); + + if (frame->pict_type == AV_PICTURE_TYPE_I) { + FFAMediaFormat *format = ff_AMediaFormat_new(s->use_ndk_codec); + if (format) { + int set_ret; + ff_AMediaFormat_setInt32(format, "request-sync", 0); + set_ret = ff_AMediaCodec_setParameters(codec, format); + if (set_ret < 0) + av_log(avctx, AV_LOG_WARNING, + "Failed to request key frame: %d\n", set_ret); + ff_AMediaFormat_delete(format); + } + } } else { flags |= ff_AMediaCodec_getBufferFlagEndOfStream(codec); s->eof_sent = 1; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
