linux下 使用FFmpeg 采集摄像头YUV数据

alt
采集摄像头数据

从一个多媒体文件提取YUV数据

a)FFmpeg命令行

要得到原始YUV数据,需要解码操作,也就是编码的反向操作。

ffmpeg -i ./test.mp4 -an -c:v rawvideo -pix_fmt yuv420p out.yuv

-i:要提取的多媒体文件

-an:audio not 过滤掉音频,只要视频数据

-c:v:选择解码器

-pix_fmt:输出YUV数据格式

alt

比对文件大小,观察下解码后的原始数据大小。

alt

多媒体文件大小是1.8M,解码得到的YUV原始数据是538M,为什么会相差那么多?因为得到MP4多媒体文件,引用了H264压缩技术。可以想象到H264编码能力十分强。关于H264知识,我下期会介绍。

b)ffplay播放YUV文件。

在播放YUV文件时,我们要知道这个视频的分辨率以及YUV格式。

查看多媒体文件的大小

ffprobe ./test.mp4
alt

分辨率是1280x720,YUV格式是yuv420p

播放YUV

ffplay -pix_fmt yuv420p -s 1280x720 out.yuv
alt

2、C语言实现从外部设备中获取到YUV数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#include <libavutil/avutil.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#define WIDTH 640
#define HEIGHT 480

/*

*/

static AVFormatContext* open_dev()
{
    int ret = 0;
    char errors[1024] = {0,};
    char *devicename = "/dev/video0"//0机子的摄像头
    //ctx
    AVFormatContext *fmt_ctx = NULL;
    AVDictionary *options = NULL;

    avdevice_register_all();

    //get format
    AVInputFormat *iformat = av_find_input_format("video4linux2");

    //option 视频需要参数
    char video_size[10];
    sprintf(video_size, "%dx%d", WIDTH, HEIGHT);
    av_dict_set(&options,"video_size",video_size,0);
    
    //av_dict_set(&options,"pixel_format","yuyv422",0);
    
    if((ret = avformat_open_input(&fmt_ctx,devicename,iformat,&options)) < 0)
    {
        av_strerror(ret,errors,1024);
        fprintf(stderr,"Failed to open video device ,[%d]%s\n",ret,errors);
        return NULL;
    }
    return fmt_ctx;
}
void rec_video(){
    int ret = 0;
    int flag=-1;
    char input_command[128];
    AVFormatContext *fmt_ctx = NULL;
    AVPacket pkt;//数据存放
    flag=fcntl(0,F_GETFL); //获取当前flag
    av_log_set_level(AV_LOG_DEBUG);

    char *out = "./out.yuv";

    FILE *outfile = fopen(out,"wb+");

    //打开设备
    fmt_ctx = open_dev();
    
    flag |=O_NONBLOCK; //设置新falg
    fcntl(0,F_SETFL,flag); //更新flag

    av_init_packet(&pkt);//数据初始化 干净的空间;
    while((ret = av_read_frame(fmt_ctx,&pkt)) == 0)
    {
        av_log(NULL,AV_LOG_DEBUG,
                    "packet size is %d(%p)\n",
                    pkt.size,pkt.data);

        fwrite(pkt.data,1,pkt.size,outfile);
        fflush(outfile);

        av_packet_unref(&pkt);

        if((ret=read(0,input_command,sizeof(input_command))) > 0)
        {
            if(strncmp(input_command, "over",2) == 0)
            {
                av_log(NULL,AV_LOG_DEBUG,"over\n");
                break;
            }
            else
            {
                av_log(NULL,AV_LOG_DEBUG,"请重新输入\n");
            }
            memset(input_command, 0sizeof(input_command));
        }
    }

    fclose(outfile);
    avformat_close_input(&fmt_ctx);

    av_log(NULL, AV_LOG_DEBUG,"finish\n");
}
int main(int argc, char** argv)
{
    rec_video();
    return 0;
}

gcc编译:

gcc av_video.c -I/usr/ffmpeg4.1/include -L/usr/ffmpeg4.1/lib -o av_video -lavutil -lavdevice -lavformat -lavcodec

a)执行av_video文件

alt

此时摄像头录像,获取YUV数据,程序默认使用yuv420p格式采集,从提示可以看到,最后采用yuyv422格式采集yuv数据。因为摄像头输出的yuv数据格式是yuyv422格式,怎样修改程序默认采集YUV格式? 取消av_dict_set(&options,"pixel_format","yuyv422",0);注释,指定YUV数据输入格式。

b)文件播放

yuv420p格式播放

ffplay -pix_fmt yuv420p -s 640x480 ./out.yuv
alt

因为文件格式是YUYV422,与FFplay制定的播放格式不一致,导致显示效果有差异。

yuyv422格式播放

ffplay -pix_fmt yuyv422 -s 640x480 ./out.yuv

此时显示就正常了啦。

alt

想了解更多,可以关注 小昭debug 公众号,交个朋友,交流下。

alt

本文由 mdnice 多平台发布

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用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 ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小昭dedug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值