前言:
当前兄弟们对“ffmpeg录制rtsp”可能比较关注,兄弟们都想要知道一些“ffmpeg录制rtsp”的相关内容。那么小编同时在网络上网罗了一些对于“ffmpeg录制rtsp””的相关内容,希望你们能喜欢,姐妹们一起来了解一下吧!实现一个基于ffmpeg的rtsp抓屏服务一、服务实现图1、整体图2、 采集图3、 编码图4、 传输二、各个模块简要说明1、模块讲解
上面图1
在上面的1、中,主要是整个程序的主要流程走向,使用ffmpeg **gdigrab**进行采集,ffmpeg中的libx264进行编码,
由于直接使用ES流进行传输。所以,封装这层先不做过多的处理。传输,是网络上找的一个rtsp服务,最终会使用**vlc**进行验证。
上面图2、
图2中,有几个函数avdevice_register_all,是需要使用到采集的gdi设备,所以需要该函数进行注册。使用av_dict_set_int来设
置编码参数,
图2中av_dict_set_int,设置抓屏参数
小编整理了一些学习资料、教学视频和学习路线图共享在群文件,资料包括《Andoird音视频开发必备手册+音视频最新学习视频+大厂面试真题+2022最新学习路线图+项目实战源码》等等(C/C++,Linux,FFmpeg ,webRTC, rtmp, hls, rtsp, ffplay, srs)
部分采集编码:
AVDictionary *options = nullptr; av_dict_set_int(&options, "framerate", 25, 1); av_dict_set_int(&options, "draw_mouse", 1, 1); av_dict_set_int(&options, "offset_x", 0, 1); av_dict_set_int(&options, "offset_y", 0, 1); av_dict_set(&options, "video_size", video_size, 1); AVInputFormat* pInputFmt = av_find_input_format("gdigrab"); AVFormatContext* pFmtCtx = avformat_alloc_context(); avformat_open_input(&pFmtCtx , "desktop", pInputFmt, &options); if (avformat_find_stream_info(pFmtCtx , nullptr) < 0) { printf("Couldn't find stream info.\n"); avformat_close_input(&pFmtCtx); pFmtCtx = nullptr; return false; } int video_index = -1; for (unsigned int i = 0; i < pFmtCtx ->nb_streams; i++) { if (pFmtCtx ->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_index = i; } } if (video_index < 0) { printf("Couldn't find video stream.\n"); avformat_close_input(&pFmtCtx ); pFmtCtx = nullptr; return false; } AVCodec* codec = avcodec_find_decoder(pFmtCtx->streams[video_index]->codecpar->codec_id); if (!codec) { avformat_close_input(&pFmtCtx ); pFmtCtx = nullptr; return false; } m_pCodecCtx = avcodec_alloc_context3(codec); if (!m_pCodecCtx ) { return false; } avcodec_parameters_to_context(m_pCodecCtx , pFmtCtx->streams[video_index]->codecpar); if (avcodec_open2(m_pCodecCtx , codec, nullptr) != 0) { avcodec_close(m_pCodecCtx ); codec_context_ = nullptr; avformat_close_input(&pFmtCtx); pFmtCtx= nullptr; return false; }
部分编码
AVCodec *codec = nullptr; //codec = avcodec_find_encoder(AV_CODEC_ID_H264); codec = avcodec_find_encoder_by_name("libx264"); if (!codec) { std::cout << "H.264 Encoder not found.\n" << std::endl; return false; } codec_context_ = avcodec_alloc_context3(codec); if (!codec_context_) { std::cout << "avcodec_alloc_context3() failed." << std::endl; return false; } codec_context_->width = av_config_.video.width; codec_context_->height = av_config_.video.height; codec_context_->time_base = { 1, (int)av_config_.video.framerate }; codec_context_->framerate = { (int)av_config_.video.framerate, 1 }; codec_context_->gop_size = av_config_.video.gop; codec_context_->max_b_frames = 0; codec_context_->pix_fmt = AV_PIX_FMT_YUV420P; // rc control mode: abr codec_context_->bit_rate = av_config_.video.bitrate; // cbr mode config codec_context_->rc_min_rate = av_config_.video.bitrate; codec_context_->rc_max_rate = av_config_.video.bitrate; codec_context_->rc_buffer_size = (int)av_config_.video.bitrate; codec_context_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; if (codec->id == AV_CODEC_ID_H264) { av_opt_set(codec_context_->priv_data, "preset", "ultrafast", 0); //ultrafast } av_opt_set(codec_context_->priv_data, "tune", "zerolatency", 0); av_opt_set_int(codec_context_->priv_data, "forced-idr", 1, 0); av_opt_set_int(codec_context_->priv_data, "avcintra-class", -1, 0); if (avcodec_open2(codec_context_, codec, NULL) != 0) { std::cout << "avcodec_open2() failed." << std::endl; return false; }
部分代码如上
① 采集流程
上面主要是获取设备信息,并打开解码器
后面通过av_read_frame读取流,avcodec_send_packet/avcodec_receive_frame来进行解码流
同时,将获取到的数据进行编码成h264,
② 编码流程
编码流程中需要注意,数据是通过采集中获取到的数据,AVframe,需要先将AVFrame转为yuvAVFrame,然后通过接口avcodec_send_frame/avcodec_receive_packet,avcodec_receive_packet中的数据,得到的是AVPacket的数据,需要去掉其中h264中的起始码,传给rtsp服务,rtsp服务就能将数据传输给用户端。
③ 封装
由于此处直接使用ES流,不做封装,直接将编码器中的数据进行传输。
④ 传输
传输参考下面的3.rtsp服务
总结
本章节只讲述整个服务器相关的流程
标签: #ffmpeg录制rtsp