#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#ifdef __cplusplus
extern "C" {
#endif
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
#ifdef __cplusplus
}
#endif
void ffmpeg_video_capture();
int main(void)
{
ffmpeg_video_capture();
return 0;
}
void ffmpeg_video_capture()
{
char* video_dir="rtsp://admin:yltx8888@192.168.37.210:554/h264/ch1/main/av_stream";
// char* video_dir="rtmp://58.200.131.2:1935/livetv/cctv6";
av_register_all(); //注册库中所有的文件格式和编码器
avformat_network_init();
AVCodec *pCodec=NULL; //解码器指针
AVCodecContext* pCodecCtx=NULL; //ffmpeg 解码类的类成员
AVFormatContext* pFormatCtx=NULL; //保存视频流的信息
// pFormatCtx=avformat_alloc_context();
AVDictionary* options=NULL;
av_dict_set(&options,"buffer_size","1024000",0);
av_dict_set(&options,"max_delay","500000",0);
av_dict_set(&options,"rtsp_transport","tcp",0);
av_dict_set(&options,"stimeout","2000000",0);//如果没有设置stimeout,那么流地址错误,av_read_frame会阻塞(时间单位是微妙)
if(avformat_open_input(&pFormatCtx,video_dir,NULL,&options)!=0){ //检查文件头部
printf("can't find the stream\n");
}
if(avformat_find_stream_info(pFormatCtx,NULL)<0){ //查找流信息
printf("can't find the stream infomation!\n");
}
printf("--------输出文件信息-------\n");
av_dump_format(pFormatCtx,0,video_dir,0);
int video_index=-1;
for(int i=0;i<pFormatCtx->nb_streams;i++){
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
video_index=i;
break;
}
}
if(video_index==-1){
printf("can't find a video stream!");
}
pCodecCtx=pFormatCtx->streams[video_index]->codec; //得到一个指向视频流的上下文指针
int frame_rate=pFormatCtx->streams[video_index]->avg_frame_rate.num / pFormatCtx->streams[video_index]->avg_frame_rate.den;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id); //得到该格式的解码器
if(pCodec==NULL){
printf("can't find the decoder!\n");
}
if(avcodec_open2(pCodecCtx,pCodec,NULL)<0){ // 打开解码器
printf("can't open the decoder\n");
}
AVFrame* pAvFrame=NULL; //多媒体帧,保存解码后的数据帧
pAvFrame=av_frame_alloc();//分配视频帧存储空间
AVFrame* pFrameBGR=NULL;
pFrameBGR=av_frame_alloc();//存储解码后转换的BGR数据
if(pAvFrame==NULL || pFrameBGR==NULL){
printf("视频帧为空或者解码数据为空!\n");
}
//保存BGR
int size=avpicture_get_size(AV_PIX_FMT_BGR24,pCodecCtx->width,pCodecCtx->height);
uint8_t* out_buffer=(uint8_t*)av_malloc(size*sizeof(uint8_t));
avpicture_fill((AVPicture*)pFrameBGR,out_buffer,AV_PIX_FMT_BGR24,pCodecCtx->width,pCodecCtx->height);
AVPacket packet;
SwsContext *img_convert_ctx;
img_convert_ctx=sws_getContext(pCodecCtx->width,pCodecCtx->height,
pCodecCtx->pix_fmt,pCodecCtx->width,
pCodecCtx->height,AV_PIX_FMT_BGR24,
SWS_BILINEAR,NULL,NULL,NULL);
int ret;
int got_picture=0;
cv::Mat frame(pCodecCtx->height, pCodecCtx->width, CV_8UC3);
cv::namedWindow("frame",cv::WINDOW_AUTOSIZE);
for( ; ; ){
if(av_read_frame(pFormatCtx,&packet)>=0){
std::cout<<"*********1111********\n";
if(packet.stream_index==video_index){
std::cout<<"*********2222********\n";
ret=avcodec_decode_video2(pCodecCtx,pAvFrame,&got_picture,&packet);
if(ret<0){
printf("decodec error!(解码错误!)\n");
}
std::cout<<"*********3333********\n";
if(got_picture){
sws_scale(img_convert_ctx,pAvFrame->data,pAvFrame->linesize,0,
pCodecCtx->height,pFrameBGR->data,pFrameBGR->linesize);
std::cout<<"*********4444********\n";
memcpy(frame.data,pFrameBGR->data[0],size);
std::cout<<"*********5555********\n";
cv::imshow("RGB",frame);
cv::waitKey(25);
}
}
av_free_packet(&packet);
}
}
av_free(out_buffer);
av_free(pFrameBGR);
av_free(pAvFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
sws_freeContext(img_convert_ctx);
cv::destroyWindow("RGB");
}
ffmpeg 获取rtsp视频流
于 2020-12-31 09:19:35 首次发布