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

使用FFmpeg C API提取MP4音频时发送解码包报错-1094995529

错误原因与修复方案

错误码解析

-1094995529 对应FFmpeg的AVERROR_INVALIDDATA,表示解码器收到了无法识别的无效数据包。核心问题是解码器上下文未正确初始化输入音频流的编码参数,导致解码器不知道如何解析输入的音频数据包。

关键错误点

你的代码在创建解码器上下文cd_ctx后,直接调用avcodec_open2打开解码器,但没有将输入音频流的codecpar参数复制到解码器上下文中。解码器缺少输入音频的编码格式、采样率、通道数等关键信息,无法处理数据包。

修复步骤

1. 正确初始化解码器上下文

在avcodec_alloc_context3之后,添加avcodec_parameters_to_context将输入流的编码参数复制到解码器上下文:

// allocate codec context
cd_ctx = avcodec_alloc_context3(codec);
if (!cd_ctx)
    return (printf("Could not allocate codec context\n"), 1);

// 新增:从输入流的codecpar复制参数到解码器上下文
if (avcodec_parameters_to_context(cd_ctx, fmt_ctx->streams[audio_stream_index]->codecpar) < 0)
    return (printf("Could not copy codec parameters to decoder context\n"), 1);

// open codec
if (avcodec_open2(cd_ctx, codec, NULL) < 0)
    return (printf("Could not open codec\n"), 1);

2. 完整处理解码流程

发送数据包到解码器后,必须循环调用avcodec_receive_frame获取解码后的原始音频帧,否则解码器内部缓冲区会溢出,导致后续错误:

// read packets
AVFrame *pframe = av_frame_alloc();
if (!pframe)
    return (printf("Could not allocate packet frame\n"), 1);
AVPacket pkt;
while (1)
{
    int ret = av_read_frame(fmt_ctx, &pkt);
    if (ret < 0)
        break;
    printf("packet stream index %d\n", pkt.stream_index);
    if (pkt.stream_index == audio_stream_index)
    {
        printf("packet size %d\n", pkt.size);
        ret = avcodec_send_packet(cd_ctx, &pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            printf("EAGAIN or EOF\n");
        else if (ret < 0)
        {
            char errbuf[AV_ERROR_MAX_STRING_SIZE];
            av_strerror(ret, errbuf, sizeof(errbuf));
            return (printf("Error sending packet to decoder: %s\n", errbuf), 1);
        }

        // 新增:循环获取解码后的帧
        while (ret >= 0)
        {
            ret = avcodec_receive_frame(cd_ctx, pframe);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                break;
            else if (ret < 0)
            {
                char errbuf[AV_ERROR_MAX_STRING_SIZE];
                av_strerror(ret, errbuf, sizeof(errbuf));
                return (printf("Error receiving frame from decoder: %s\n", errbuf), 1);
            }
            // 这里可以添加将解码后的帧发送到MP3编码器的逻辑
            printf("Decoded frame with %d samples\n", pframe->nb_samples);
            av_frame_unref(pframe); // 释放帧的引用
        }
    }
    av_packet_unref(&pkt); // 必须释放数据包,避免内存泄漏
}

3. 完善输出编码器配置

你的代码仅设置了输出流的codecpar,但未创建编码器上下文并打开,无法完成MP3编码。需要添加编码器上下文的初始化:

// 创建输出编码器上下文
AVCodecContext *out_cd_ctx = avcodec_alloc_context3(out_codec);
if (!out_cd_ctx)
    return (printf("Could not allocate output codec context\n"), 1);

// 设置编码器参数
out_cd_ctx->codec_id = AV_CODEC_ID_MP3;
out_cd_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
out_cd_ctx->sample_rate = 44100;
out_cd_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
out_cd_ctx->channels = 2;
out_cd_ctx->bit_rate = 128000; // MP3比特率

// 打开编码器
if (avcodec_open2(out_cd_ctx, out_codec, NULL) < 0)
    return (printf("Could not open output codec\n"), 1);

// 将编码器参数复制到输出流的codecpar
if (avcodec_parameters_from_context(out_codecpar, out_cd_ctx) < 0)
    return (printf("Could not copy output codec parameters\n"), 1);

4. 补充资源释放逻辑

程序结束前需要释放所有分配的资源:

// 释放资源
av_frame_free(&pframe);
avcodec_free_context(&cd_ctx);
avcodec_free_context(&out_cd_ctx);
avformat_close_input(&fmt_ctx);
avio_close(out_ctx->pb);
avformat_free_context(out_ctx);

FFmpeg C API数据包处理指导

输入解码流程

  1. 读取数据包:用av_read_frame从输入文件读取AVPacket,每个包对应一段压缩的音视频数据。
  2. 匹配流索引:根据包的stream_index判断是音频还是视频流,只处理目标流的包。
  3. 发送到解码器:调用avcodec_send_packet将数据包送入解码器,注意:
    • 若返回AVERROR(EAGAIN),表示解码器需要先读取已解码的帧才能继续接收新包。
    • 处理完所有数据包后,需要发送NULL包(avcodec_send_packet(cd_ctx, NULL))来flush解码器剩余的帧。
  4. 接收解码帧:循环调用avcodec_receive_frame获取解码后的原始帧,直到返回AVERROR(EAGAIN)或AVERROR_EOF。

输出编码流程

  1. 发送原始帧:将解码得到的AVFrame送入编码器(avcodec_send_frame)。
  2. 接收编码包:循环调用avcodec_receive_packet获取编码后的压缩数据包。
  3. 写入输出文件:设置数据包的stream_index为输出流的索引,用av_interleaved_write_frame写入输出文件(确保音视频同步)。
  4. Flush编码器:发送NULL帧(avcodec_send_frame(out_cd_ctx, NULL))来获取编码器剩余的数据包。

核心注意事项

  • 资源管理:所有AVPacket必须用av_packet_unref释放,AVFrame用av_frame_unref或av_frame_free释放,上下文用对应的avcodec_free_context、avformat_free_context释放。
  • 错误处理:所有FFmpeg API的返回值都要检查,用av_strerror将错误码转为可读字符串,方便调试。
  • 参数匹配:解码器/编码器的参数必须与输入/输出流的参数一致,否则会出现无效数据或编码失败。

内容的提问来源于stack exchange,提问作者Saad Out03

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:28:09