基于FFMPEG的视频拉流并传给OPENCV显示

基于FFMPEG的视频拉流并传给OPENCV显示

依赖文件解压

将ffmpeg-master-latest-win64-gpl-shared解压,得到如下所示文件夹:
在这里插入图片描述
将其中的bin目录下的.dll文件复制到C:\Windows\System32目录下。

代码编写

基于FFMPEG的拉流代码如下所示,修改添加拉流地址即可。

#include <iostream>
#include <opencv2/opencv.hpp>
extern "C"   //ffmpeg是采用c语言实现的 c++工程种 导入c语言
{
    
    
    //avcodec:编解码(最重要的库)
    #include <libavcodec/avcodec.h>
    //avformat:封装格式处理
    #include <libavformat/avformat.h>
    //swscale:视频像素数据格式转换
    #include <libswscale/swscale.h>
    //avdevice:各种设备的输入输出
    #include <libavdevice/avdevice.h>
    //avutil:工具库(大部分库都需要这个库的支持)
    #include <libavutil/avutil.h>

    #include <libavutil/imgutils.h>

}


int main() {
    
    
    // Initialize FFmpeg
    //av_register_all();//在新版本4.0以后,不需要调用该方法,可以直接使用所有模块。
    avformat_network_init();
    std::cout << "start work" << std::endl;

    // Open RTSP stream
    AVFormatContext* formatContext = nullptr;
    if (avformat_open_input(&formatContext, "rtsp://xxx", nullptr, nullptr) != 0) {
    
    //拉流地址
        std::cerr << "Failed to open RTSP stream." << std::endl;
        return -1;
    }

    // Find stream info
    if (avformat_find_stream_info(formatContext, nullptr) < 0) {
    
    
        std::cerr << "Failed to find stream info." << std::endl;
        return -1;
    }

    // Find video stream index
    int videoStreamIndex = -1;
    for (unsigned int i = 0; i < formatContext->nb_streams; ++i) {
    
    
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    
    
            videoStreamIndex = i;
            break;
        }
    }

    if (videoStreamIndex == -1) {
    
    
        std::cerr << "Failed to find video stream." << std::endl;
        return -1;
    }

    // Get codec parameters for the video stream
    AVCodecParameters* codecParameters = formatContext->streams[videoStreamIndex]->codecpar;

    // Find video decoder
    const AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);
    if (codec == nullptr) {
    
    
        std::cerr << "Failed to find video decoder." << std::endl;
        return -1;
    }

    // Allocate codec context
    AVCodecContext* codecContext = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {
    
    
        std::cerr << "Failed to allocate codec context." << std::endl;
        return -1;
    }

    // Open codec
    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
    
    
        std::cerr << "Failed to open codec." << std::endl;
        return -1;
    }
  
    // Prepare image conversion context
    //SwsContext* swsContext = sws_getContext(codecContext->width, codecContext->height,
    //    codecContext->pix_fmt,
    //    codecContext->width, codecContext->height,
    //    //AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
    //    AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr);


    // Create OpenCV window for displaying frames
    cv::namedWindow("RTSP Stream", cv::WINDOW_NORMAL);

    AVPacket packet;
    cv::Mat frame;

    frame = cv::Mat(codecContext->height, codecContext->width, CV_8UC3);

    AVFrame* pFrameRGB = av_frame_alloc();
    uint8_t* buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1));
    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1);

    struct SwsContext* sws_ctx = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
        codecContext->width, codecContext->height, AV_PIX_FMT_RGB24,
        SWS_BILINEAR, nullptr, nullptr, nullptr);

    while (av_read_frame(formatContext, &packet) >= 0) {
    
    
        if (packet.stream_index == videoStreamIndex) {
    
    
            // Decode video frame
            avcodec_send_packet(codecContext, &packet);
            AVFrame* avFrame = av_frame_alloc();
            int ret = avcodec_receive_frame(codecContext, avFrame);

            if (ret == 0) {
    
    
                // Convert frame to RGB
                sws_scale(sws_ctx, avFrame->data, avFrame->linesize, 0, codecContext->height, pFrameRGB->data, pFrameRGB->linesize);
                frame.data = pFrameRGB->data[0];
                // Display frame
                cv::imshow("RTSP Stream", frame);
                cv::waitKey(1);
            }

            av_frame_free(&avFrame);
        }

        av_packet_unref(&packet);
    }

    // Clean up
    avformat_close_input(&formatContext);
    avformat_network_deinit();
    avcodec_free_context(&codecContext);
    sws_freeContext(sws_ctx);

    return 0;
}

依赖配置

opencv的依赖在此不做赘述

  1. 打开项目的属性管理器,在“包含目录”和“库目录”中加入解压得到的ffmpeg的include和lib路径,如下所示:
    在这里插入图片描述

我这的包含目录路径是:E:\ffmpeg-master-latest-win64-gpl-shared\ffmpeg-master-latest-win64-gpl-shared\include
库目录路径是:E:\ffmpeg-master-latest-win64-gpl-shared\ffmpeg-master-latest-win64-gpl-shared\lib
2. 在属性页的链接器的输入部分的附加依赖项中添加库
在这里插入图片描述
添加如下库即可:

avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib

编译运行

设为启动项目,编译运行即可,会使用opencv弹出窗口

猜你喜欢

转载自blog.csdn.net/qq_40608730/article/details/131394183