Linux下使用FFmpeg实现采集摄像头数据

FFmpeg采集摄像头数据


前言

博主对音视频蛮感兴趣的,学习了一段时间的FFmpeg。前几天,在逛博客的时候发现在Linux下使用FFmpeg采集摄像头的数据,由于这采集摄像头的数据没写过代码,于是复现了下人家的代码,是一个比较简单的demo程序,仅供参考。

一、查看Linux系统下的摄像头设备

前排提示:在看此博客的之前,需要在自己的Ubuntu环境中安装FFmpeg,若没安装FFmpeg,可以在网上搜教程(网上的教程还是蛮详细的)。
在Linux系统中,使用的是v4l2框架来驱动摄像头设备的。
使用FFmpeg的ffprobe命令来查看连接到Ubuntu系统中的摄像头设备,如下图。
在这里插入图片描述
从图中可以看到,所使用摄像头的参数,从图中可以看出摄像头输出的原始参数是yuyv422的形式,一般我们使用的是yuv420p的数据,因此在保存摄像头数据的时候,先对yuyu422的格式进行变化,将其变换为yuv420p的格式,然后再进行编码保存为h264的文件。

二、代码

1.在main函数中,所需要用到的参数的声明

    int ret = 0;
    
    // 注册所有的设备
    avdevice_register_all();

    // 输入设备的相关参数
    AVFormatContext *inFmtCtx = avformat_alloc_context();
    AVCodec *inCodec = NULL;
    AVCodecContext *inCodecCtx = NULL;
    int inVideoSteamIndex = -1;
    struct SwsContext *img_ctx = NULL;
    AVFrame *yuvFrame = NULL;
    AVFrame *srcFrame = NULL;
    AVPacket *inPkt = av_packet_alloc();


    // 输出文件的相关参数
    AVFormatContext *outFmtCtx = avformat_alloc_context();
    AVOutputFormat *outFmt = NULL;
    AVStream *outStream = NULL;
    AVCodecContext *outCodecCtx=NULL;
    AVCodec *outCodec = NULL;
    AVPacket *outPkt = av_packet_alloc();

2.解码摄像头原始参数设置

        // 解码部分
        // 打开v4l2的相机输入
        AVInputFormat *inFmt = av_find_input_format("v4l2");
        if(avformat_open_input(&inFmtCtx,"/dev/video0",inFmt,NULL) < 0){
   
            fprintf(stderr,"Cannot open camera.\n");
            return -1;
        }

        // 查找流
        if(avformat_find_stream_info(inFmtCtx,NULL) < 0){
   
            fprintf(stderr,"Cannot find any stream in file.\n");
            return -1;
        }

        // 寻找视频流
        for(size_t i = 0;i < inFmtCtx->nb_streams;i++){
   
            if(inFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
   
                inVideoSteamIndex = i;
                break;
            }
        }

        // 没找到视频流
        if(inVideoSteamIndex == -1){
   
            fprintf(stderr,"Cannot find video stream in file.\n");
            return -1;
        }

        // 创建解码器的参数集
        AVCodecParameters* inVideoCodecPara = inFmtCtx->streams[inVideoSteamIndex]->codecpar;
        // 查找解码器
        if(!(inCodec = avcodec_find_decoder(inVideoCodecPara->codec_id))){
   
            fprintf(stderr,"Cannot find valid video decoder.\n");
            return -1;
        }

        if(!(inCodecCtx = avcodec_alloc_context3(inCodec))){
   
            fprintf(stderr,"Cannot alloc valid decode codec context.\n");
            return -1;
        }

        if(avcodec_parameters_to_context(inCodecCtx,inVideoCodecPara) < 0){
   
            fprintf(stderr,"Cannot initialize parameters.\n");
            return -1;
        }

        // 打开编解码器
        if(avcodec_open2(inCodecCtx,inCodec,NULL) < 0){
   
            fprintf(stderr,"Cannot open codec.\n");
            return -1;
        }

        img_ctx = sws_getContext(inCodecCtx->width,inCodecCtx->height,inCodecCtx->pix_fmt,
                                    inCodecCtx->width,inCodecCtx->height,AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);
        
        // 获取图像的大小
        int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,inCodecCtx->width,inCodecCtx->height,1);

        // 创建out_buffer缓冲区
        uint8_t *out_buffer = (unsigned char *)av_malloc(num_bytes*sizeof(unsigned char));
        yuvFrame = av_frame_alloc();
        srcFrame = av_frame_alloc();

        // 将yuvframe和out_buffer进行关联
        int ret = av_image_fill_arrays(yuvFrame->data,yuvFrame->linesize,out_buffer,AV_PIX_FMT_YUV420P,inCodecCtx->width,inCodecCtx->height,1);
        if(ret < 0){
   
            fprintf(stderr,"Fill arrays failed.\n");
            return -1;
        }

3.输出H264文件部分

// 输出文件,编码器部分
        const char* out_file = "output.h264";
        if(avformat_alloc_output_context2(&outFmtCtx,NULL,NULL,out_file)  < 0){
   
            fprintf(stderr,"Cannot alloc output file context.\n");
            return -1;
        }
        outFmt = outFmtCtx->oformat;

        // 打开输出文件
        if(avio_open(&outFmtCtx->pb,out_file,AVIO_FLAG_READ_WRITE) < 0){
   
            fprintf(stderr,"output file open failed.\n");
            return -1;
        }

        // 创建保存的H264流,并设置参数
        outStream = avformat_new_stream(outFmtCtx,outCodec
  • 7
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
敬告:该系列的课程在抓紧录制更新中,敬请大家关注。敬告:本课程项目仅供学习参考,请不要直接商用,概不负责任何法律责任。 该系列的课程涉及:FFmpeg,WebRTC,SRS,Nginx,Darwin,Live555,等。包括:音视频、流媒体、直播、Android、视频监控28181、等。 我将带领大家一起来学习使用FFmpeg开发视频监控项目,并动手操练。具体内容包括: 一、视频监控的架构和流程二、FFmpeg4.3+SDL2+Qt5开发环境的搭建三、FFmpeg的SDK编程回顾总结并操练四、SDL2.0的编程回顾总结并操练五、颜色空间转换RGB和YUV的原理与实战六、Qt5+FFmpeg本地摄像头采集预览实战七、代码封装:摄像头h264/5编码并存储八、Qt5+FFmpeg单路网络摄像头采集预览九、Qt5+FFmpeg单路网络摄像头采集预览录制会看十、onvif与GB/T-28181的简介  音视频与流媒体是一门很复杂的技术,涉及的概念、原理、理论非常多,很多初学者不学 基础理论,而是直接做项目,往往会看到c/c++的代码时一头雾水,不知道代码到底是什么意思,这是为什么呢?   因为没有学习音视频和流媒体的基础理论,就比如学习英语,不学习基本单词,而是天天听英语新闻,总也听不懂。 所以呢,一定要认真学习基础理论,然后再学习播放器、转码器、非编、流媒体直播、视频监控、等等。   梅老师从事音视频与流媒体行业18年;曾在永新视博、中科大洋、百度、美国Harris广播事业部等公司就职,经验丰富;曾亲手主导广电直播全套项目,精通h.264/h.265/aac,曾亲自参与百度app上的网页播放器等实战产品。  目前全身心自主创业,主要聚焦音视频+流媒体行业,精通音视频加密、流媒体在线转码快编等热门产品。  
使用ffmpeg采集摄像头数据并进行推流,你可以使用以下命令: 1. 首先,使用命令`ffmpeg -list_devices true -f dshow -i dummy`获取摄像头的名称\[1\]。 2. 然后,使用以下命令来获取视频流并推流: ``` ffmpeg -f dshow -i video="摄像头名称" -vcodec libx264 -acodec copy -preset:v ultrafast -tune:v zerolatency -f flv <推流地址> ``` 这个命令将会获取摄像头视频流,并使用libx264编码器进行视频编码,音频则直接复制。推流地址是你要推送到的目标地址\[1\]。 另外,如果你使用的是Linux系统,可以使用以下命令来采集摄像头数据并推流: ``` ./ffmpeg -f video4linux2 -r 12 -s 640x480 -i /dev/video0 -vcodec libx264 -f flv rtmp://127.0.0.1:1935/live/live ``` 这个命令将会采集/dev/video0设备的视频流,并使用libx264编码器进行视频编码,然后将视频流推送到rtmp://127.0.0.1:1935/live/live地址\[2\]。 希望以上信息对你有帮助! #### 引用[.reference_title] - *1* [FFMPEG采集摄像头推流方法说明](https://blog.csdn.net/az44yao/article/details/98104615)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [linux FFMPEG 摄像头采集数据推流](https://blog.csdn.net/hanhui22/article/details/109842044)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值