ffmpeg获取rtsp视频流(qt)

文章描述了一个QT应用程序如何使用FFmpeg库处理RTSP流,包括初始化解码器、获取视频流信息、解码视频帧并显示到QImage中。
摘要由CSDN通过智能技术生成

connect(this,SIGNAL(GetImage(QImage)),this,SLOT(SetImageSlots(QImage)));
 

void MainWindow::startStream()
{
    videoStreamIndex=-1;
    av_register_all();
    avformat_network_init();
    pAVFormatContext = avformat_alloc_context();
    pAVFrame=av_frame_alloc();
    if (this->Init())
    {
        m_timerPlay->start();
    }
}

bool MainWindow::Init()
{
    if(m_str_url.isEmpty())
        return false;
    qDebug()<<"m_str_url="<<m_str_url;

    //加了下面一句后不丢包
    av_dict_set(&pAVDict, "rtsp_transport", "tcp", 0);
    av_dict_set(&pAVDict, "strict", "1", 0);

    int result=avformat_open_input(&pAVFormatContext,m_str_url.toStdString().c_str(),nullptr,&pAVDict;
    if (result<0){
        return false;
    }

    //获取视频流信息
    result=avformat_find_stream_info(pAVFormatContext,nullptr);
    if (result<0){
        return false;
    }
    qDebug()<<"avformat_find_stream_info result="<<result;
    //获取视频流索引
    videoStreamIndex = -1;
    for (uint i = 0; i < pAVFormatContext->nb_streams; i++) {
        if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }/*else if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            videoStreamIndex = i;
        }*/
    }
    qDebug()<<"videoStreamIndex="<<videoStreamIndex;
    if (videoStreamIndex==-1){
        qDebug()<<"获取视频流索引失败";
        return false;
    }

    //获取视频流的分辨率大小
    pAVCodecContext = pAVFormatContext->streams[videoStreamIndex]->codec;
    videoWidth=pAVCodecContext->width;
    videoHeight=pAVCodecContext->height;

    m_i_w = videoWidth;
    m_i_h = videoHeight;

    qDebug()<<"videoWidth="<<videoWidth<<",videoHeight="<<videoHeight;

    avpicture_alloc(&pAVPicture,AV_PIX_FMT_RGB24,videoWidth,videoHeight);

    AVCodec *pAVCodec;

    //获取视频流解码器
    pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
    pSwsContext = sws_getContext(videoWidth,videoHeight,AV_PIX_FMT_YUV420P,videoWidth,videoHeight,AV_PIX_FMT_RGB24,SWS_BICUBIC,0,0,0);


    //打开对应解码器
    //result=avcodec_open2(pAVCodecContext,pAVCodec,NULL);
    result = avcodec_open2(pAVCodecContext,pAVCodec,&pAVDict);
    if (result<0)
    {
        qDebug()<<"打开解码器失败";
        return false;
    }

    qDebug()<<"初始化视频流成功";
    return true;
}

void MainWindow::playSlots()
{
    static ulong frame_num = 0;
    //一帧一帧读取视频
    if (av_read_frame(pAVFormatContext, &pAVPacket) >= 0)
    {
        if(pAVPacket.stream_index==videoStreamIndex)
        {
            int ret = avcodec_decode_video2(pAVCodecContext, pAVFrame, &m_i_frameFinished, &pAVPacket);
            if(ret < 0)
            {
                qDebug()<<"Decode Error.";
            }
            if (m_i_frameFinished)
            {

                mutex.lock();

                sws_scale(pSwsContext,(const uint8_t* const *)pAVFrame->data,pAVFrame->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);
                //发送获取一帧图像信号
                QImage image(pAVPicture.data[0],videoWidth,videoHeight,QImage::Format_RGB888);
                emit GetImage(image);
                qDebug()<<"one frame time"<<QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss zzz")<<pAVFrame->pts<<frame_num<<","<<pAVFrame->key_frame;
                frame_num++;
                mutex.unlock();
            }

        }
        //av_usleep(1000);
    }
    av_free_packet(&pAVPacket);//释放资源,否则内存会一直上升
}

void MainWindow::SetImageSlots(const QImage &image)
{
    if (image.height()>0)
    {
        QPixmap pix = QPixmap::fromImage(image.scaled(ui->label_video->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->label_video->setPixmap(pix);
    }
}

qt的pro文件引用ffmpeg(4.4.2)

INCLUDEPATH += C:\ffmpeg_build\include
LIBS+= -LC:\ffmpeg_build\bin -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale

  • 34
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Qt中使用FFmpeg播放RTSP H264视频流的方法如下[^1][^2]: 1. 首先,确保你已经安装了QtFFmpeg,并且已经将FFmpeg的库文件添加到Qt项目中。 2. 创建一个Qt项目,并在项目文件中添加FFmpeg的头文件和库文件的路径。 3. 在Qt的代码中,使用FFmpeg的API来实现视频流的播放。以下是一个简单的示例代码: ```cpp #include <QCoreApplication> #include <QDebug> #include <QThread> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 初始化FFmpeg av_register_all(); // 创建AVFormatContext对象 AVFormatContext *formatContext = avformat_alloc_context(); // 打开视频流 if (avformat_open_input(&formatContext, "rtsp://your_rtsp_url", nullptr, nullptr) != 0) { qDebug() << "无法打开视频流"; return -1; } // 查找视频流信息 if (avformat_find_stream_info(formatContext, nullptr) < 0) { qDebug() << "无法获取视频流信息"; return -1; } // 查找视频流索引 int videoStreamIndex = -1; for (int i = 0; i < formatContext->nb_streams; i++) { if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } } // 如果找不到视频流索引,退出程序 if (videoStreamIndex == -1) { qDebug() << "找不到视频流"; return -1; } // 获取视频解码器参数 AVCodecParameters *codecParameters = formatContext->streams[videoStreamIndex]->codecpar; // 查找视频解码器 AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id); if (codec == nullptr) { qDebug() << "找不到视频解码器"; return -1; } // 创建解码器上下文 AVCodecContext *codecContext = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) { qDebug() << "无法创建解码器上下文"; return -1; } // 打开解码器 if (avcodec_open2(codecContext, codec, nullptr) < 0) { qDebug() << "无法打开解码器"; return -1; } // 创建帧对象 AVFrame *frame = av_frame_alloc(); // 创建解码后的帧对象 AVFrame *decodedFrame = av_frame_alloc(); // 创建解码后的帧的缓冲区 uint8_t *buffer = nullptr; int bufferSize = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1); buffer = (uint8_t *)av_malloc(bufferSize * sizeof(uint8_t)); av_image_fill_arrays(decodedFrame->data, decodedFrame->linesize, buffer, AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1); // 创建视频转换上下文 SwsContext *swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt, codecContext->width, codecContext->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr); // 读取视频帧 AVPacket packet; while (av_read_frame(formatContext, &packet) >= 0) { if (packet.stream_index == videoStreamIndex) { // 解码视频帧 avcodec_send_packet(codecContext, &packet); avcodec_receive_frame(codecContext, frame); // 转换视频帧格式 sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, decodedFrame->data, decodedFrame->linesize); // 在这里可以将解码后的帧显示到界面上 // 延时一段时间,模拟视频播放 QThread::msleep(40); } av_packet_unref(&packet); } // 释放资源 av_frame_free(&frame); av_frame_free(&decodedFrame); avcodec_free_context(&codecContext); avformat_close_input(&formatContext); avformat_free_context(formatContext); return a.exec(); } ``` 请注意,上述代码只是一个简单的示例,实际的视频播放功能可能需要更多的处理和错误处理。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值