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

基于FFmpeg与C++的AC3音频编码方法纠错求助:AV_SAMPLE_FMT_FLT转AV_SAMPLE_FMT_FLTP

Fixing Audio Sample Conversion & AC3 Encoding Issues

Let’s break down the problems in your code and fix them one by one—there are several critical issues with frame setup, resampling, packet handling, and resource management that are preventing proper AC3 output.

1. Incorrect Output Frame Buffer & Metadata Setup

Your ProcessData function has two major flaws:

  • You’re forcing the planar FLTP frame to use a pre-allocated pAudioEncodeBuffer, which doesn’t account for FLTP’s channel-separated buffer structure.
  • The pkt_size calculation is wrong (it uses packed FLT’s block align instead of planar FLTP’s requirements).
  • You’re missing the channel_layout metadata, which FFmpeg needs for proper resampling and encoding.

Fixed ProcessData Function:

void ProcessData(AVFrame *inputframe, AVFrame *outputFrame, uint8_t* data, uint32_t sample_count, uint64_t device_ts) {
    // Configure input FLT frame (packed format)
    inputframe->nb_samples = sample_count;
    inputframe->format = AV_SAMPLE_FMT_FLT;
    inputframe->sample_rate = mWFX->nSamplesPerSec;
    inputframe->channels = mWFX->nChannels;
    inputframe->channel_layout = av_get_default_channel_layout(mWFX->nChannels);
    // Convert device timestamp to sample-based PTS (FFmpeg's preferred audio PTS format)
    inputframe->pts = av_rescale_q(device_ts, AV_TIME_BASE_Q, av_make_q(1, inputframe->sample_rate));

    // Fill input frame with external audio data (no allocation needed)
    int ret = av_samples_fill_arrays(inputframe->data, inputframe->linesize, data,
                                   mWFX->nChannels, sample_count, AV_SAMPLE_FMT_FLT, 0);
    if (ret < 0) {
        fprintf(stderr, "Failed to populate input frame: %s\n", av_err2str(ret));
        exit(1);
    }

    // Configure output FLTP frame (planar format)
    outputFrame->nb_samples = sample_count;
    outputFrame->format = AV_SAMPLE_FMT_FLTP;
    outputFrame->sample_rate = inputframe->sample_rate;
    outputFrame->channels = inputframe->channels;
    outputFrame->channel_layout = inputframe->channel_layout;
    outputFrame->pts = inputframe->pts; // Pass through PTS to output frame

    // Let FFmpeg allocate the correct planar buffers automatically
    ret = av_frame_get_buffer(outputFrame, 0);
    if (ret < 0) {
        fprintf(stderr, "Failed to allocate output frame buffer: %s\n", av_err2str(ret));
        exit(1);
    }
}

2. Resampling Context & swr_convert Improvements

Your resampler setup is missing channel layout configuration, which can cause channel mapping errors. Also, you should check the return value of swr_convert to ensure conversion succeeded.

Fixed Resampler Initialization:

// Replace your existing swr_alloc setup with this
pSmplConvertCtx = swr_alloc_set_opts(NULL,
                                   av_get_default_channel_layout(pCodecCxt->channels),
                                   pCodecCxt->sample_fmt,
                                   pCodecCxt->sample_rate,
                                   av_get_default_channel_layout(pCodecCxt->channels),
                                   AV_SAMPLE_FMT_FLT,
                                   pCodecCxt->sample_rate,
                                   0, NULL);
if (!pSmplConvertCtx) {
    fprintf(stderr, "Could not allocate resampler context\n");
    exit(1);
}
if (swr_init(pSmplConvertCtx) < 0) {
    fprintf(stderr, "Failed to initialize resampling context\n");
    swr_free(&pSmplConvertCtx);
    exit(1);
}

Fixed swr_convert Call:

int converted_samples = swr_convert(pSmplConvertCtx,
                                 pFLTPAudioFrame->data, pFLTPAudioFrame->nb_samples,
                                 (const uint8_t **)pFLTAudioFrame->data, pFLTAudioFrame->nb_samples);
if (converted_samples < 0) {
    fprintf(stderr, "Resampling failed: %s\n", av_err2str(converted_samples));
    exit(1);
}
// Update output frame to reflect actual converted samples (matches input here since sample rate is unchanged)
pFLTPAudioFrame->nb_samples = converted_samples;

3. Encoding Packet Handling & PTS Correction

Your packet setup has multiple issues:

  • Manually setting AV_PKT_FLAG_KEY is incorrect (AC3 keyframes are determined by the encoder, not you).
  • Hardcoding pkt.data to pAudioEncodeBuffer overrides FFmpeg’s internal packet management.
  • Using pCodecCxt->coded_frame->pts is deprecated; use the packet’s PTS directly.

Fixed Encoding Section:

AVPacket pkt = {0};
av_init_packet(&pkt);
pkt.stream_index = pStream->index;

int gotOutput = 0;
auto ret = avcodec_encode_audio2(pCodecCxt, &pkt, pFLTPAudioFrame, &gotOutput);
if (ret < 0) {
    fprintf(stderr, "Audio encoding failed: %s\n", av_err2str(ret));
    exit(1);
}
if (gotOutput) {
    // Rescale PTS from codec time base to stream time base
    pkt.pts = av_rescale_q(pkt.pts, pCodecCxt->time_base, pStream->time_base);
    pkt.dts = pkt.pts; // Audio DTS typically equals PTS
    pkt.duration = av_rescale_q(pkt.duration, pCodecCxt->time_base, pStream->time_base);

    ret = av_interleaved_write_frame(pFormatContext, &pkt);
    if (ret < 0) {
        fprintf(stderr, "Failed to write audio packet: %s\n", av_err2str(ret));
        exit(1);
    }
    av_packet_unref(&pkt); // Critical: Free packet resources after writing
}

4. Memory Leak Fixes

You’re allocating frames with av_frame_alloc but never freeing them. Add these lines at the end of AddAudioSample:

av_frame_free(&pFLTAudioFrame);
av_frame_free(&pFLTPAudioFrame);

Also, since we’re now using av_frame_get_buffer for the output frame, you can remove the pAudioEncodeBuffer allocation (it’s no longer needed). Don’t forget to free the resampler context when you’re done with it:

swr_free(&pSmplConvertCtx);

5. Critical Pre-Checks

Before calling AddAudioSample, ensure:

  • Your codec context’s time_base is set correctly: pCodecCxt->time_base = av_make_q(1, pCodecCxt->sample_rate);
  • The AC3 encoder is properly opened with avcodec_open2(pCodecCxt, pCodec, NULL);
  • mWFX parameters are valid (e.g., sample rate 48000/44100, channel count 1/2, which are supported by AC3).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:03:12