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

双摄像头场景下FFmpeg推流失效问题排查及实现咨询

双摄像头FFmpeg推流问题排查思路

核心问题分析

单摄像头逻辑复用双摄像头场景失效,大概率是线程安全问题或资源共享冲突导致,以下是具体排查方向:

1. 激活标记的线程竞争

  • 你用active_cam指定推送摄像头,若这个变量是全局且未加锁保护,两个线程可能同时读写导致值混乱——比如线程A刚判断active_cam指向自身,线程B就修改了标记,导致推流逻辑执行错误。
  • 解决:给active_cam的读写操作加互斥锁(std::mutex),确保同一时间只有一个线程能访问该变量。

2. FFmpeg推流资源的复用冲突

  • 若initRemoteStream()中创建的FFmpeg上下文(比如AVFormatContext*、AVCodecContext*)是全局变量,两个线程会同时操作同一资源,导致初始化或推流崩溃。
  • 解决:为每个摄像头线程维护独立的FFmpeg推流上下文,不要共享全局的FFmpeg资源。

3. 线程启动与资源初始化的时序问题

  • 可能两个线程同时调用initRemoteStream(),导致推流管道被重复创建或覆盖,其中一个线程的管道被破坏。
  • 解决:确保只有当前激活的摄像头线程才会初始化推流管道,非激活线程只做捕获,不执行推流初始化;或者在切换激活摄像头时,先销毁旧的推流资源,再初始化新的。

4. YUV数据写入的线程安全问题

  • 若decodePacket()中使用的缓冲区是全局共享的,两个线程同时写入会导致数据错乱,FFmpeg无法正确编码。
  • 解决:每个线程使用独立的YUV数据缓冲区,或者在写入时加锁保护。

5. 线程退出与资源释放的问题

  • 切换激活摄像头时,旧的摄像头线程若未正确释放资源(比如FFmpeg上下文、捕获设备句柄),会导致资源泄漏或新线程无法获取资源。
  • 解决:实现线程的优雅退出机制,切换时通知旧线程停止并释放所有资源,再启动新线程的推流逻辑。

代码修改建议示例

// 为每个摄像头定义独立的上下文结构体
struct CamContext {
    int cam_id;
    bool is_active;
    std::mutex mtx;
    AVFormatContext* fmt_ctx;
    // 其他FFmpeg资源、捕获设备句柄等
};

// 线程函数
void cameraThread(CamContext* ctx) {
    while (true) {
        std::lock_guard<std::mutex> lock(ctx->mtx);
        if (!ctx->is_active) {
            // 非激活状态只捕获不推流
            captureYUV(ctx);
            continue;
        }
        // 激活状态初始化推流并写入数据
        if (!ctx->fmt_ctx) {
            initRemoteStream(ctx); // 用ctx内的资源初始化
        }
        decodePacket(ctx); // 写入当前线程的YUV数据
    }
}

// 在main中创建上下文并启动线程
int main() {
    CamContext cam1{0, false, {}, nullptr};
    CamContext cam2{1, true, {}, nullptr}; // 默认激活cam2

    std::thread t1(cameraThread, &cam1);
    std::thread t2(cameraThread, &cam2);

    // 切换激活摄像头的逻辑(示例)
    std::this_thread::sleep_for(std::chrono::seconds(10));
    {
        std::lock_guard<std::mutex> lock1(cam1.mtx);
        std::lock_guard<std::mutex> lock2(cam2.mtx);
        cam1.is_active = true;
        cam2.is_active = false;
        // 销毁cam2的推流资源
        if (cam2.fmt_ctx) {
            avformat_close_input(&cam2.fmt_ctx);
            cam2.fmt_ctx = nullptr;
        }
    }

    t1.join();
    t2.join();
    return 0;
}

注意:所有FFmpeg资源的创建、操作、释放都要绑定到对应摄像头的上下文,避免跨线程共享。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:42:37