三.ffmpeg对yuv的操作
一.windows
1.使用ffmpeg录制mp4视频
#获取音视频设备
ffmpeg -list_devices true -f dshow -i dummy
#录制视频
ffmpeg -f dshow -i video="xxxx" -c"v libx264 -pix_fmt yuv420p output.mp4
2.将mp4转换为yuv数据
//-i:输入文件选项;-an:不处理音频流;
//-c:v rawvideo 视频编码器的选项,使用原始视频格式进行编码(不进行压缩);
//-pix_fmt yuv420p:输出视频的像素格式
ffmpeg -i output.mp4 -an -c:v rawvideo -pix_fmt yuv420p out.yuv
//播放
ffplay -f rawvideo -pixel_format yuv420p -video_size 1280x720 out1.yuv
3.也可以单独播放单独分量
//播放yuv数据
ffplay -s 1280x720 -vf extractplanes='y' out.yuv
//提取yuv三个分量为三个文件
ffmpeg -s 1280x720 -pix_fmt yuv420p -i out.yuv -filter_complex "extractplanes=y+u+v[y][u][v]" -map "[y]" y.yuv -map "[u]" u.yuv -map "[v]" v.yuv
//播放单个分量 格式为gray
ffplay -s 1280x720 -pix_fmt gray y.yuv
播放出来y、u、v都是没有颜色的,为什么u和v表示蓝色和红色的差分量也没有颜色呢?
因为u和v分量的值是相对于y分量的,没有y分量它们都无法提供完整的颜色信息。
4.api调用
#可以查看摄像头输出的视频数据的编码格式和像素格式
ffmpeg -list_options true -f dshow -i video="Integrated Camera"
5.整体代码
//打开摄像头直接获取原始数据
int read_video()
{int ret = 0;char errors[1024];AVFormatContext *fmt_ctx = NULL;AVDictionary *options = NULL;AVAudioFifo *fifo = nullptr;// FILE *outfile = fopen("./out.yuv", "wb+");FILE *outfile_yuv = fopen("./out1.yuv", "wb+");if (outfile_yuv == nullptr){printf("filed open out file\n");}AVPacket pkt;av_init_packet(&pkt);int frame_count = 0;// 找到采集工具const AVInputFormat *iformat = av_find_input_format("dshow");if (iformat == NULL){printf("AVInputFormat find failed \n");return -1;}// 打开视频设备av_dict_set(&options, "video_size", "1280x720", 0);av_dict_set(&options, "framerate", "10", 0);av_dict_set(&options, "pixel_format", "yuyv422", 0);ret = open_dev(&fmt_ctx, "video=Integrated Camera", iformat, &options);int count = 0;while (av_read_frame(fmt_ctx, &pkt) >= 0){printf("pkt-size:%d\n", pkt.size);fwrite(pkt.data, 1, pkt.size, outfile_yuv);fflush(outfile_yuv);av_packet_unref(&pkt);if (count++ > 50)break;}avformat_close_input(&fmt_ctx);fclose(outfile_yuv);av_log(NULL, AV_LOG_DEBUG, "end");return 0;
}
6.遇到问题
1.通过av_read_frame获取到的视频数据不是yuv420p的原始数据,而是通过mjpeg编码的yuv422p的数据。
7.解决问题
注意:打开使用设备时要注意自己摄像头支持的参数,我之前设置的1280x720 30fps yuyv422和1280x720 30fps yuv420p都不支持设置pixel_format,所以我没写pixel_format,导致1280x720 30fps默认使用vcodec=mjpeg编码器来进行编码。
解决办法:使用上面的这个指令来查看本机设备支持的格式和参数
ffmpeg -list_options true -f dshow -i video="Integrated Camera"