You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台FFmpeg 4.4无法初始化h264_mediacodec硬件解码

解决Android平台FFmpeg 4.4 MediaCodec硬件解码初始化失败问题

一、修复编译参数问题

  • 立即移除--enable-hwaccel=h264_mediacodec参数,FFmpeg中h264_mediacodec是独立解码器,不属于hwaccel模块,该参数完全无效,这就是编译警告的根源。
  • 保留正确的编译参数:
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
  • 检查ffmpeg-android-maker脚本,确保自定义参数被正确传递到FFmpeg的configure流程,避免脚本覆盖或忽略这些配置。

二、代码层面修正

1. 手动指定MediaCodec解码器

当前用av_find_best_stream自动选解码器时,大概率会优先选择软件解码器(如h264),而非硬件解码器。需要主动尝试获取h264_mediacodec:

void Decoder::initDecoder() {
    AVCodecParameters* videoStreamCodecParams = m_videoStream->codecpar;

    // 优先尝试硬件解码器
    m_decoder = avcodec_find_decoder_by_name("h264_mediacodec");
    if (!m_decoder) {
        spdlog::warn("h264_mediacodec not found, falling back to software decoder");
        //  fallback到自动选择逻辑
        int ret = av_find_best_stream(m_inputFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, &m_decoder, 0);
        if (ret < 0 || !m_decoder) {
            throw FFmpegException("Decoder: No available video decoder");
        }
    }

    // 遍历硬件配置逻辑保留,后续补充设备初始化
    for (size_t i = 0;; i++) {
        const AVCodecHWConfig* config = avcodec_get_hw_config(m_decoder, i);
        if (!config) {
            spdlog::error(
                "Decoder {} doesn't support device type {}. Use SW decoder...",
                m_decoder->name,
                av_hwdevice_get_type_name(m_deviceType)
            );
            m_hwDecoderSupported = false;
            break;
        }

        if (
            config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
            config->device_type == m_deviceType
        ) {
            g_hwPixFmt = config->pix_fmt;
            m_hwDecoderSupported = true;
            break;
        }
    }

    // 补充硬件设备上下文初始化(关键步骤)
    if (m_hwDecoderSupported) {
        AVBufferRef* hw_device_ctx = nullptr;
        int ret = av_hwdevice_ctx_create(&hw_device_ctx, m_deviceType, nullptr, nullptr, 0);
        if (ret < 0) {
            spdlog::error("Failed to create MediaCodec device: {}", av_err2str(ret));
            m_hwDecoderSupported = false;
            return;
        }

        // 分配并初始化解码器上下文
        m_codecContext = avcodec_alloc_context3(m_decoder);
        if (!m_codecContext) {
            av_buffer_unref(&hw_device_ctx);
            throw FFmpegException("Failed to allocate codec context");
        }

        // 复制流参数到解码器上下文
        ret = avcodec_parameters_to_context(m_codecContext, videoStreamCodecParams);
        if (ret < 0) {
            avcodec_free_context(&m_codecContext);
            av_buffer_unref(&hw_device_ctx);
            throw FFmpegException(fmt::format("Copy codec params failed: {}", av_err2str(ret)));
        }

        // 关联硬件设备上下文到解码器
        m_codecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
        av_buffer_unref(&hw_device_ctx);

        // 打开解码器
        ret = avcodec_open2(m_codecContext, m_decoder, nullptr);
        if (ret < 0) {
            spdlog::error("Open MediaCodec decoder failed: {}", av_err2str(ret));
            m_hwDecoderSupported = false;
            avcodec_free_context(&m_codecContext);
        }
    }

    // 软件解码器的初始化逻辑(如果需要)
    if (!m_hwDecoderSupported) {
        m_codecContext = avcodec_alloc_context3(m_decoder);
        if (!m_codecContext) {
            throw FFmpegException("Failed to allocate codec context");
        }
        int ret = avcodec_parameters_to_context(m_codecContext, videoStreamCodecParams);
        if (ret < 0) {
            avcodec_free_context(&m_codecContext);
            throw FFmpegException(fmt::format("Copy codec params failed: {}", av_err2str(ret)));
        }
        ret = avcodec_open2(m_codecContext, m_decoder, nullptr);
        if (ret < 0) {
            avcodec_free_context(&m_codecContext);
            throw FFmpegException(fmt::format("Open SW decoder failed: {}", av_err2str(ret)));
        }
    }
}

2. 关键缺失点说明

原代码缺少AVCodecContext的创建和硬件设备上下文的关联逻辑,这是FFmpeg硬件解码的核心步骤——必须将MediaCodec设备上下文绑定到解码器上下文,才能启用硬件加速。

三、验证步骤

  • 编译后,用输出的ffmpeg二进制执行ffmpeg -decoders,确认列表中存在h264_mediacodec,验证编译是否生效。
  • 在JNI代码中添加日志,打印avcodec_find_decoder_by_name("h264_mediacodec")的地址,以及遍历avcodec_get_hw_config时的所有config->device_type和config->pix_fmt,排查硬件配置是否被正确识别。

内容的提问来源于stack exchange,提问作者Ramil Galin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 13:35:55