ffmpeg的使用举例

1. 实时获取rtsp流数据

功能描述

CamerPicUtil 类主要用于从 RTSP 流中读取视频帧,并将其转换为 QImage 格式,然后通过信号 signal_sendPic 发送出去。该类可以通过调用 doWork 方法开始工作,并且可以通过调用 stopRun 方法停止工作。

camerpicutil.h

// camerpicutil.h 文件

#ifndef CAMERPICUTIL_H
#define CAMERPICUTIL_H

#include <QObject>
#include <QCoreApplication>

// CamerPicUtil 类,继承自 QObject,用于处理摄像头图片的获取和处理
class CamerPicUtil : public QObject
{
    Q_OBJECT
public:
    // 构造函数,接收 RTSP 地址、组索引、摄像头索引和父对象指针
    // url: RTSP 流的地址
    // group_index: 组索引,用于标识不同的组
    // camer_index: 摄像头索引,用于标识同一组内的不同摄像头
    // parent: 父对象指针,默认为 nullptr
    explicit CamerPicUtil(QString url, int group_index, int camer_index, QObject *parent = nullptr);
    // 析构函数
    ~CamerPicUtil();
    // 开始工作的方法,用于读取 RTSP 流并处理视频帧
    void doWork();

public slots:
    // 停止运行的槽函数,用于停止视频帧的读取和处理
    void stopRun();

signals:
    // 发送图片的信号,当处理完一帧视频后,通过该信号发送处理后的 QImage 以及组索引和摄像头索引
    // image: 处理后的 QImage 指针
    // group_index: 组索引
    // camer_index: 摄像头索引
    void signal_sendPic(QImage *image, int group_index, int camer_index);

private:
    // RTSP 流的地址
    QString m_rspturl;
    // 控制是否继续运行的标志位
    bool m_isRun = true;
    // 组索引
    int m_group_index = 1;
    // 摄像头索引
    int m_camer_index = 1;
};

#endif // CAMERPICUTIL_H

camerpicutil.cpp

// camerpicutil.cpp 文件

#include "camerpicutil.h"
#include "qthread.h"
#include <QDebug>
#include <QDateTime>
#include <QImage>

// 引入 FFmpeg 相关的 C 库
extern "C" {
    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    #include <libswscale/swscale.h>
    #include <libavutil/opt.h>
    #include <libavutil/channel_layout.h>
    #include <libavutil/common.h>
    #include <libavutil/imgutils.h>
    #include <libavutil/mathematics.h>
    #include <libavutil/samplefmt.h>
}

// 构造函数的实现
CamerPicUtil::CamerPicUtil(QString url, int group_index, int camer_index, QObject *parent)
    : QObject{parent}
{
    // 保存 RTSP 流的地址
    m_rspturl = url;
    // 打印 RTSP 地址,用于调试
    qDebug() << "**********" << url;
    // 保存组索引
    m_group_index = group_index;
    // 保存摄像头索引
    m_camer_index = camer_index;
}

// 析构函数的实现
CamerPicUtil::~CamerPicUtil()
{
    // 打印析构信息,用于调试
    qDebug() << "~CamerPicUtil";
}

// 开始工作的方法实现
void CamerPicUtil::doWork()
{
    // 视频流所在流序列中的索引,初始化为 -1 表示未找到
    int  videoStreamIndex = -1;
    // 默认返回值,用于存储 FFmpeg 函数的返回结果
    int ret = 0;

    // 需要的 FFmpeg 相关变量并初始化
    // AVFormatContext 用于存储输入或输出的格式信息
    AVFormatContext *fmtCtx = NULL;
    // AVPacket 用于存储压缩的音视频数据
    AVPacket *pkt = NULL;
    // AVCodecContext 用于存储解码器的上下文信息
    AVCodecContext *codecCtx = NULL;
    // AVCodecParameters 用于存储编解码器的参数信息
    AVCodecParameters *avCodecPara = NULL;

    // 分配一个 AVFrame 用于存储 YUV 格式的视频帧
    AVFrame *yuvFrame = av_frame_alloc();
    // 分配一个 AVFrame 用于存储 RGB 格式的视频帧
    AVFrame *rgbFrame = av_frame_alloc();

    // 用于设置 FFmpeg 的选项
    AVDictionary* options = NULL;
    // 设置 RTSP 传输方式为 TCP
    av_dict_set(&options, "rtsp_transport", "tcp", 0);
    // 设置超时断开链接时间,单位为微秒
    av_dict_set(&options, "stimeout", "5000000", 0);

    // 使用 do-while(0) 结构确保资源的正确释放
    do {
        // 分配一个 AVFormatContext,FFMPEG 所有的操作都要通过这个 AVFormatContext 来进行
        fmtCtx = avformat_alloc_context();
        // 打开 RTSP 流
        if (avformat_open_input(&fmtCtx, m_rspturl.toLatin1().data(), NULL, &options) != 0) {
            // 打开失败,打印错误信息并跳出循环
            printf("cannot open video file\n");
            break;
        }

        // 获取视频流信息
        if ((ret = avformat_find_stream_info(fmtCtx, NULL)) < 0) {
            // 获取失败,打印错误信息并跳出循环
            printf("cannot retrive video info\n");
            break;
        }

        // 循环查
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值