ffmpeg--yuv数据采集
程序员文章站
2022-03-04 23:41:17
...
1.打开视频设备
static AVFormatContext* open_dev()
{
int ret = 0;
char errors[1024] ={0,};
AVFormatContext *fmt_ctx = NULL;
AVDictionary *options= NULL;
//0:0 前面的0是视频设备,后面的0是音频设备,这里只采集视频
//0 是机器摄像头
//1 是桌面
char * devicename = "0";
//av_register_all();
// 1.注册所有的编解码器和音视频格式
avdevice_register_all();
//2.选取mac对应的avfoundation库
//mac 上使用avfoundation,windows上面使用directshow,linux使用alsa
AVInputFormat *iformat = av_find_input_format("avfoundation");
//video_size 指定分辨率的大小
av_dict_set(&options,"video_size","640x480", 0);
av_dict_set(&options,"framerate","30", 0);
av_dict_set(&options,"pixel_format","nv12", 0);
//av_dict_set(&options,"list_devices","true",0);
//打开设备上下文
ret = avformat_open_input(&fmt_ctx, devicename, iformat,&options);
if(ret < 0)
{
av_strerror(ret, errors, 1024);
fprintf(stderr, "Failed to open device,[%d]%s\n",ret,errors);
return NULL;
}
return fmt_ctx;
}`在这里插入代码片`
2.yuv数据采集
void rec_video()
{
int ret = 0;
AVFormatContext *fmt_ctx = NULL;
AVPacket pkt;
av_log_set_level(AV_LOG_DEBUG);
rec_status = 1;
char *out ="/users/test/Downloads/video.yuv";
FILE * outfile = fopen(out,"wb+");
fmt_ctx = open_dev();
if(NULL == fmt_ctx)
{
av_log(NULL, AV_LOG_DEBUG, "=====ERROR======!\n");
goto __ERROR;
}
av_log(NULL, AV_LOG_DEBUG, "test 11111111!\n");
while(rec_status)
{
ret = av_read_frame(fmt_ctx, &pkt);
if (ret == 0)
{ // 读取成功
// 将数据写入文件
//(宽x高)x(yuv420=1.5/yuv422=2/yuv444=3)字节
//fwrite的第三个形参长度是以为字节为单位的
//nv12是yuv420的一种存储格式
fwrite(pkt.data,1,460800, outfile);
// 释放资源,此处必须释放,每次av_read_frame都会增加引用计数,av_packet_unref释放引用计数,等到引用计数为0的时候,资源被释放
av_packet_unref(&pkt);
}
else if (ret == AVERROR(EAGAIN))
{ // 资源临时不可用
//此处会引起cpu占用率过高
continue;
}
else
{ // 其他错误
//errbuf[1024];
//av_strerror(ret, errbuf, sizeof (errbuf));
//av_log(NULL, AV_LOG_INFO, "errbuf is %s \n",errbuf);
break;
}
// 必须要加,释放pkt内部的资源
av_packet_unref(&pkt);
}
__ERROR:
if(outfile)
{
fclose(outfile);
}
if(fmt_ctx)
{
avformat_close_input(&fmt_ctx);
}
av_log(NULL, AV_LOG_DEBUG, "finish!\n");
return;
}