基于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的依赖在此不做赘述
- 打开项目的属性管理器,在“包含目录”和“库目录”中加入解压得到的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弹出窗口