亭台六七座 2025-07-15 05:46 采纳率: 26.1%
浏览 13

在线程0中停止如何解决如图(语言-qt)(相关搜索:convert函数)

在使用Qt调用FFMPEG库时,swr_convert函数报错:异常被触发在线程0中停止如何解决
如图

img

img

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-07-15 05:47
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 Qt 调用 FFMPEG 库(如 swr_convert 函数)时,如果出现“异常被触发在线程0中停止”的错误,通常意味着程序在执行过程中遇到了未处理的异常或错误,导致线程崩溃。


    一、问题分析

    1. 常见原因

    • 内存越界访问:例如传入了无效的 AVFrameSwrContext
    • 未正确初始化 FFmpeg 相关结构体:如 SwrContext 没有通过 swr_alloc_set_opts 正确初始化。
    • 多线程问题:FFmpeg 的某些函数不是线程安全的,或者在 Qt 线程中使用不当。
    • 资源释放顺序错误:如先释放了 SwrContext,却仍然调用 swr_convert
    • 输入数据格式不匹配:如音频格式、采样率、通道布局等不一致。

    二、解决方案(详细步骤)

    1. 检查 swr_convert 参数是否正确

    确保你传递给 swr_convert 的参数是合法的:

    int swr_convert(
        SwrContext *s,
        uint8_t *out_samples[],
        int out_count,
        const uint8_t *in_samples[],
        int in_count
    );
    

    重点:必须确保 s 不为 NULL,且 out_samplesin_samples 是有效的缓冲区。


    2. 确保 SwrContext 已正确初始化

    使用 swr_alloc_set_opts 创建并初始化 SwrContext

    SwrContext *swr_ctx = swr_alloc_set_opts(
        nullptr,
        output_channel_layout,
        output_sample_format,
        output_sample_rate,
        input_channel_layout,
        input_sample_format,
        input_sample_rate,
        0,
        nullptr
    );
    
    if (!swr_ctx) {
        qWarning() << "Failed to allocate SwrContext";
        return;
    }
    
    if (swr_init(swr_ctx) < 0) {
        qWarning() << "Failed to initialize SwrContext";
        swr_free(&swr_ctx);
        return;
    }
    

    重点: 必须调用 swr_init() 初始化上下文。


    3. 检查音频格式是否兼容

    确保输入和输出格式匹配,比如:

    • 采样格式:AV_SAMPLE_FMT_FLTP vs AV_SAMPLE_FMT_S16
    • 通道数:AV_CH_LAYOUT_STEREO vs AV_CH_LAYOUT_MONO
    • 采样率:44100 vs 48000

    4. 避免在主线程中进行耗时操作

    如果你在 主线程(线程0) 中直接调用 swr_convert,可能会导致 UI 停止响应甚至崩溃。

    建议:将耗时操作放到子线程中运行。

    示例代码(使用 Qt 线程):

    class AudioWorker : public QObject {
        Q_OBJECT
    public:
        void processAudio() {
            // 在这里调用 swr_convert
            int ret = swr_convert(swr_ctx, out_buffer, out_channels, in_buffer, in_channels);
            if (ret < 0) {
                qWarning() << "swr_convert failed";
            }
        }
    };
    
    // 在主窗口中启动线程
    QThread* thread = new QThread(this);
    AudioWorker* worker = new AudioWorker();
    worker->moveToThread(thread);
    connect(thread, &QThread::started, worker, &AudioWorker::processAudio);
    thread->start();
    

    5. 确保资源正确释放

    在不再需要 SwrContext 时,务必释放它:

    swr_free(&swr_ctx);
    

    注意: 如果 swr_convert 被调用前已经释放了 swr_ctx,就会导致崩溃。


    三、完整示例代码(修改版)

    #include <QDebug>
    extern "C" {
    #include <libavutil/opt.h>
    #include <libswresample/swresample.h>
    }
    
    void convertAudio() {
        SwrContext *swr_ctx = swr_alloc_set_opts(
            nullptr,
            AV_CH_LAYOUT_STEREO,
            AV_SAMPLE_FMT_FLTP,
            44100,
            AV_CH_LAYOUT_MONO,
            AV_SAMPLE_FMT_S16,
            48000,
            0,
            nullptr
        );
    
        if (!swr_ctx) {
            qDebug() << "Failed to allocate SwrContext";
            return;
        }
    
        if (swr_init(swr_ctx) < 0) {
            qDebug() << "Failed to initialize SwrContext";
            swr_free(&swr_ctx);
            return;
        }
    
        // 假设我们有一个输入音频帧
        AVFrame *in_frame = av_frame_alloc();
        in_frame->sample_rate = 48000;
        in_frame->channel_layout = AV_CH_LAYOUT_MONO;
        in_frame->format = AV_SAMPLE_FMT_S16;
    
        // 分配输出缓冲区
        int out_channels = 2;
        int out_samples = 1024;
        uint8_t *out_buffer[2];
        for (int i = 0; i < out_channels; ++i) {
            out_buffer[i] = (uint8_t *)malloc(out_samples * sizeof(float));
        }
    
        // 执行转换
        int ret = swr_convert(swr_ctx, out_buffer, out_samples, (const uint8_t **)in_frame->data, in_frame->nb_samples);
        if (ret < 0) {
            qDebug() << "swr_convert failed";
        }
    
        // 释放资源
        for (int i = 0; i < out_channels; ++i) {
            free(out_buffer[i]);
        }
        swr_free(&swr_ctx);
        av_frame_free(&in_frame);
    }
    

    四、调试建议

    1. 使用 GDBVisual Studio Debugger 查看崩溃点。
    2. 添加日志输出,确认每一步是否成功。
    3. 检查 FFmpeg 是否编译为静态库,避免动态链接问题。
    4. 确保你的 FFmpeg 版本与 Qt 兼容。

    五、总结

    | 问题 | 解决方案 | |------|----------| | swr_convert 报错 | 检查 SwrContext 是否初始化正确 | | 线程0崩溃 | 避免在主线程中执行耗时操作,使用子线程 | | 内存越界 | 确保 out_bufferin_buffer 有效 | | 格式不匹配 | 确认输入输出格式一致 |


    如你有具体的错误信息或代码片段,可以提供更多细节,我可以进一步帮助你定位问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 7月15日