Configure FFmpeg MediaCodec Encoding on Android
This article provides a practical guide on how to configure and enable hardware-accelerated video encoding in FFmpeg on Android using the MediaCodec API. By leveraging the device’s system-on-chip (SoC) hardware encoder, you can drastically reduce CPU usage, lower battery consumption, and increase video processing speeds in your Android applications.
1. Build FFmpeg with MediaCodec and JNI Support
To use MediaCodec hardware acceleration, you must compile FFmpeg with JNI (Java Native Interface) and MediaCodec modules enabled. During the configuration step of your FFmpeg build script, ensure the following flags are included:
./configure \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-encoder=h264_mediacodec \
--enable-hwaccel=h264_mediacodec \
--enable-parser=h264Note: You can swap or add hevc_mediacodec (H.265) or
vp9_mediacodec depending on your target format and device
support.
2. Initialize the JVM in Your Native Code
Because MediaCodec is a Java-based API on Android, native C/C++ FFmpeg code must access the Java Virtual Machine (JVM). You must register the JVM pointer when your native library loads.
In your JNI initialization code (typically JNI_OnLoad),
call av_jni_set_java_vm:
#include <libavcodec/jni.h>
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
av_jni_set_java_vm(vm, NULL);
return JNI_VERSION_1_6;
}Without this initialization step, FFmpeg will fail to instantiate the MediaCodec instance and will fallback to software encoding.
3. Configure the Encoder in Your Application
When setting up your FFmpeg encoding pipeline in C/C++, you must explicitly request the MediaCodec encoder by name.
Locating the Encoder
Instead of using avcodec_find_encoder(AV_CODEC_ID_H264),
lookup the encoder by name:
const AVCodec *codec = avcodec_find_encoder_by_name("h264_mediacodec");
if (!codec) {
// Fallback or handle error (hardware encoding not supported)
}Setting Codec Context Parameters
MediaCodec requires specific pixel formats and parameters. Standard Android devices typically expect NV12 or YUV420P color formats.
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
codec_ctx->width = 1920;
codec_ctx->height = 1080;
codec_ctx->time_base = (AVRational){1, 30};
codec_ctx->framerate = (AVRational){30, 1};
codec_ctx->pix_fmt = AV_PIX_FMT_NV12; // Standard for MediaCodec
codec_ctx->bit_rate = 4000000; // 4 Mbps
// Open the encoder
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
// Handle initialization failure
}4. Run via Command Line (FFmpeg CLI)
If you are executing FFmpeg command-line arguments using a mobile
wrapper (such as FFmpeg-Kit), specify the codec using the
-c:v flag:
ffmpeg -i input.yuv -pix_fmt nv12 -s 1920x1080 -c:v h264_mediacodec output.mp4To verify that the hardware encoder is being utilized, check the
console output log. You should see references to
h264_mediacodec and system logcat messages from
OMX or Codec2 initiating the hardware
codec.