ffmpeg 获取rtsp视频流

#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");
}



  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值