首页 > 其他分享 >使用ffmpeg将opencv捕获的摄像头数据推流到本地rtsp器上

使用ffmpeg将opencv捕获的摄像头数据推流到本地rtsp器上

时间:2023-10-18 12:45:13浏览次数:32  
标签:编码器 ffmpeg int frame rtsp 器上 codec outputVc size

首先,为什么使用opencv?答:方便对视频进行处理,各种深度学习网络就有了用物之地。

具体流程参考的FFmpeg/opencv + C++ 实现直播拉流和直播推流(对视频帧进行处理)_c++ ffmpeg拉流_酒神无忧的博客-CSDN博客,但是细节不同。

简述一下流程:

使用opencv从摄像头中读取数据。

将cv::Mat转换为AVFrame。

打开编码器(这里用的是H264)。

设置视频的详细参数,以及编码参数。

编码并进行写入输出文件。

从cv::Mat到AVFrame的转化如下:

AVFrame *PushOpencv::CVMatToAVFrame(cv::Mat &inMat, int YUV_TYPE) {
    //得到Mat信息
    AVPixelFormat dstFormat = AV_PIX_FMT_YUV420P;
    int width = inMat.cols;
    int height = inMat.rows;
    //创建AVFrame填充参数 注:调用者释放该frame
    AVFrame *frame = av_frame_alloc();
    frame->width = width;
    frame->height = height;
    frame->format = dstFormat;

    //初始化AVFrame内部空间
    int ret = av_frame_get_buffer(frame, 64);
    if (ret < 0)
    {
        return nullptr;
    }
    ret = av_frame_make_writable(frame);
    if (ret < 0)
    {
        return nullptr;
    }

    //转换颜色空间为YUV420
    cv::cvtColor(inMat, inMat, cv::COLOR_BGR2YUV_I420);

    //按YUV420格式,设置数据地址
    int frame_size = width * height;
    unsigned char *data = inMat.data;

    memcpy(frame->data[0], data, frame_size);
    memcpy(frame->data[1], data + frame_size, frame_size/4);
    memcpy(frame->data[2], data + frame_size * 5/4, frame_size/4);

    return frame;
}

这里默认用的是yuv420,你当然可以转换到yuv422或YUV444。注意422的数据分布是(frame_size, frame_size/2, frame_size/2),yuv444的数据分布是(frame_size, frame_size, frame_size)。

编码器参数设置如下:

int PushOpencv::open_codec(int width, int height, int den) {
    int ret = 0;
    avformat_network_init();
    const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (!codec)
    {
        throw std::logic_error("Can`t find h264 encoder!"); // 找不到264编码器
    }
    // b 创建编码器上下文
    outputVc = avcodec_alloc_context3(codec);
    if (!outputVc)
    {
        throw std::logic_error("avcodec_alloc_context3 failed!"); // 创建编码器失败
    }
    // c 配置编码器参数
    outputVc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // 全局参数
    outputVc->codec_id = codec->id;
    outputVc->codec_type = AVMEDIA_TYPE_VIDEO;
    outputVc->thread_count = 8;

    outputVc->bit_rate = 50 * 1024 * 8; // 压缩后每秒视频的bit位大小为50kb
    outputVc->width = width;
    outputVc->height = height;
    outputVc->time_base = {1, den};
    outputVc->framerate = {den, 1};

    outputVc->gop_size = 30;
    outputVc->max_b_frames = 1;
    outputVc->qmax = 51;
    outputVc->qmin = 10;
    outputVc->pix_fmt = AV_PIX_FMT_YUV420P;

    // d 打开编码器上下文
    ret = avcodec_open2(outputVc, codec, 0);
    std::cout << "avcodec_open2 success!" << std::endl;

    ret = avformat_alloc_output_context2(&output, nullptr, "rtsp", url.c_str());

    vs = avformat_new_stream(output, outputVc->codec);
    vs->codecpar->codec_tag = 0;
    // 从编码器复制参数
    avcodec_parameters_from_context(vs->codecpar, outputVc);
    av_dump_format(output, 0, url.c_str(), 1);

//    ret = avio_open(&output->pb, url.c_str(), AVIO_FLAG_WRITE);
    return ret;
}

解释一下控制画面清晰地参数:

outputVc->gop_size = 30;

h264的为了控制错误传递,以一个gop_size为一个编码组。在close gop模式下,同一组的只能参考同一组的帧进行帧间预测。gop总是以一个idr帧开头(注意不是I帧)且只有一个idr帧。由于I帧是全帧压缩,gop_size越小,被压缩数据越少,视频质量越高,数据量越大。

outputVc->max_b_frames = 1; 顾名思义,最大连续B帧数量。B帧是双向预测帧,一般认为,相较于I帧和P帧,B帧的压缩量大。因此B帧数量越多,压缩率越大,清晰地越低,数据量越小。
outputVc->qmax = 51;
outputVc->qmin = 10; 量化参数的范围:h264编码过程中,经过DCT变换后的数据需要进一步进行量化。可以简单认为,量化系数越大,数据之间的细节越少,进而导致压缩率变大。
outputVc->pix_fmt = AV_PIX_FMT_YUV420P; 像素格式,不在赘言。 rtsp服务器的本地部署:https://github.com/bluenviron/mediamtx/releases/tag/v0.19.1 直接在控制台运行。 具体的代码放在:https://gitee.com/Lai_Wang/PushOpencvToRtsp.git  请君自取。

 

标签:编码器,ffmpeg,int,frame,rtsp,器上,codec,outputVc,size
From: https://www.cnblogs.com/wensi-eric/p/17771807.html

相关文章

  • FFMPEG+SDL简单视频播放器——人脸检测
    前言最近突发奇想,给播放器加上一个人脸检测的功能(事情似乎朝着奇怪的方向发展了,谁家的播放器会需要去检测人脸啊......
  • RTSP/Onvi安防视频平台LiteNVR一站式视频监控解决方案
    随着我国计算机网络技术的发展和基础设施建设的不断完善,网络带来的便捷性已经开始改变我们的生活。网络设施的高速发展,视频监控行业也有了新的需求。1)高清监控系统需要满足管理者能够灵活的部署系统与分配责任;2)需要满足用户能够以最快速和最方便的方式使用监控录像。在很多项目......
  • LINUX FFMPEG安装全过程记录
    LINUXFFMPEG安装全过程记录环境是Ubuntu(也在mint上测试过),不要用包管理器安装,因为有太多的坑。如果你只是使用基础功能,可以直接使用包管理器下载。我是从源码编译安装的,下面是安装过程。参考资料:https://blog.csdn.net/Z_zzzD/article/details/106070491https://blog.csdn.n......
  • 使用fluent-ffmpeg将完整视频文件转码切片为.ts .m3u8文件以实现hls流媒体传输
    使用fluent-ffmpeg将完整视频文件转码切片为.ts.m3u8文件以实现hls流媒体传输安装项目内安装:npmiffmpegnpmifluent-ffmpeg外部环境安装:官网下载ffmpeg,将文件bin目录添加为Path系统环境变量C:\Users\lenovo\Desktop\ffmpeg-6.0-essentials_build\ffmpeg-6.0-essential......
  • 海康摄像机&大华摄像机&DSS平台的RTSP流地址格式
    实时流海康: rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username:用户名。例如admin。password:密码。例如12345。ip:为设备IP。例如192.0.0.64。port:端口号默认为554,若为默认可不填写。codec:有h264、MPEG-4、mpeg4这几......
  • ffmpeg
    参考:https://zhuanlan.zhihu.com/p/455572544ffmpeg介绍ffmpeg是一个处理媒体文件的命令行工具(commandlinebased)。它是一个拥有非常多功能的框架,并且因为他是开源的,很多知名的工具如VLC,YouTube,iTunes等等,都是再其之上开发出来的。ffmpeg最吸引我的地方就是它可以用非......
  • 服务器上清理Docker容器运行日志的正确姿势
    文章目录@[toc]1.为啥要清理服务器上docker容器的日志?2.docker容器日志限制2.1容器范围内2.2全局范围内3.删除Docker容器日志的正确姿势3.1方式一:3.2方式二:1.为啥要清理服务器上docker容器的日志?  因为是服务器的磁盘空间资源法律有限,由于d......
  • FFMPEG+SDL简单视频播放器——视频快进
    之前写过一篇关于视频播放器的文章。播放器只简单实现了视频播放的功能,在此功能的基础上,给它加上一个视频快进的功能。实现添加参数//videoplaycontrolbooldo_seek=false;//播放状态int64_tseek_length=5;//快进秒数int64_tseek_pos;//视频跳转......
  • Carthage的framework不能在模拟器上工作
    RTld:warning:ignoringfile/Users/kimoji/project/NativeFlutterCordova/iOSNative/Carthage/Build/iOS/Cordova.framework/Cordova,buildingforiOSSimulator-x86_64butattemptingtolinkwithfilebuiltforiOS-arm64Undefinedsymbolsforarchitecturex86_......
  • BOSHIDA DC电源模块在电容滤波器上的设计
    BOSHIDADC电源模块在电容滤波器上的设计DC电源模块在电容滤波器上的设计是电源管理系统中非常重要的一部分,其目的是为了确保电源输出电压的稳定性和纹波尽可能小。在设计中,需要考虑到电源负载的变化和变压器等电源配件的电磁干扰等因素。下面我们详细介绍一下电容滤波器设计中的......