FFMPEG-摄像头采集保存YUV

版权声明:引用请注明出处 https://blog.csdn.net/quange_style/article/details/90082114

ffmpeg-摄像头采集保存

//-------------------------------------------------------------------------------------------------
参考链接1、https://blog.csdn.net/leixiaohua1020/article/details/39702113
参考链接2、https://blog.csdn.net/li_wen01/article/details/67631687

//-------------------------------------------------------------------------------------------------
音视频同步录制相关文章
//-------------------------------------------------------------------------------------------------
1、 ffmpeg-摄像头采集保存
2、 ffmpeg-摄像头采集编码封装
3、 ffmpeg-音频正弦产生并编码封装
4、 ffmpeg-音频实时采集保存
5、 ffmpeg-音频实时采集编码封装
//---------------------------------------------------------------

系统环境:
系统版本:lubuntu 16.04
Ffmpge版本:ffmpeg version N-93527-g1125277
摄像头:1.3M HD WebCan
虚拟机:Oracle VM VirtualBox 5.2.22

1. 简介

FFmpeg中有一个和多媒体设备交互的类库:Libavdevice。使用这个库可以读取电脑(或者其他设备上)的多媒体设备的数据,或者输出数据到指定的多媒体设备上

2.源码

最简单的基于Libavdevice的摄像头数据读取一帧YUV数据,并保存成output.yuv文件:

1.	int main(int argc, char* argv[])  
2.	{  
3.	   
4.	    AVFormatContext *pFormatCtx;  
5.	    int             i, videoindex;  
6.	    AVCodecContext  *pCodecCtx;  
7.	    AVCodec         *pCodec;  
8.	      
9.	    av_register_all();  
10.	    avformat_network_init();  
11.	    pFormatCtx = avformat_alloc_context();  
12.	      
13.	    //Open File  
14.	    //char filepath[]="src01_480x272_22.h265";  
15.	    //avformat_open_input(&pFormatCtx,filepath,NULL,NULL)  
16.	   
17.	    //Register Device  
18.	    avdevice_register_all();  
19.	      
20.	  
21.	    //Linux  
22.	    AVInputFormat *ifmt=av_find_input_format("video4linux2");  
23.	    if(avformat_open_input(&pFormatCtx,"/dev/video0",ifmt,NULL)!=0){  
24.	        printf("Couldn't open input stream./dev/video0\n");  
25.	        return -1;  
26.	    }  
27.	   
28.	   
29.	    if(avformat_find_stream_info(pFormatCtx,NULL)<0)  
30.	    {  
31.	        printf("Couldn't find stream information.\n");  
32.	        return -1;  
33.	    }  
34.	    videoindex=-1;  
35.	    for(i=0; i<pFormatCtx->nb_streams; i++)   
36.	        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)  
37.	        {  
38.	            videoindex=i;  
39.	            break;  
40.	        }  
41.	    if(videoindex==-1)  
42.	    {  
43.	        printf("Couldn't find a video stream.\n");  
44.	        return -1;  
45.	    }  
46.	    pCodecCtx=pFormatCtx->streams[videoindex]->codec;  
47.	    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
48.	    if(pCodec==NULL)  
49.	    {  
50.	        printf("Codec not found.\n");  
51.	        return -1;  
52.	    }  
53.	    if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)  
54.	    {  
55.	        printf("Could not open codec.\n");  
56.	        return -1;  
57.	    }  
58.	    AVFrame *pFrame,*pFrameYUV;  
59.	    pFrame=av_frame_alloc();  
60.	    pFrameYUV=av_frame_alloc();  
61.	    unsigned char *out_buffer=(unsigned char *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));  
62.	    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);  
63.	  //根据获取摄像头的宽高和指定的像素格式420,分配空间
64.	  
65.	    printf("camera width=%d height=%d \n",pCodecCtx->width, pCodecCtx->height);  
66.	    int screen_w=0,screen_h=0;  
67.	            
68.	    int ret, got_picture;  
69.	   
70.	    AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));  
71.	   
72.	#if OUTPUT_YUV420P   
73.	    FILE *fp_yuv=fopen("output.yuv","wb+");    
74.	#endif    
75.	   
76.	    struct SwsContext *img_convert_ctx;  
77.	    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);   
78.	    //配置图像格式转换以及缩放参数
79.	          
80.	    if(av_read_frame(pFormatCtx, packet)>=0){  
81.	    if(packet->stream_index==videoindex){  
82.	        ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);  //解码从摄像头获取的数据,pframe结构
83.	        if(ret < 0){  
84.	            printf("Decode Error.\n");  
85.	            return -1;  
86.	        }  
87.	        if(got_picture){  
88.	            sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);  //根据前面配置的缩放参数,进行图像格式转换以及缩放等操作
89.	
90.	  
91.	#if OUTPUT_YUV420P    
92.	            int y_size=pCodecCtx->width*pCodecCtx->height;      
93.	            fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y     
94.	            fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U    
95.	            fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V    
96.	#endif    
97.	  
98.	        }  
99.	    }  
100.	    av_free_packet(packet);  
101.	              
102.	    }  
103.	   
104.	    sws_freeContext(img_convert_ctx);  
105.	#if OUTPUT_YUV420P   
106.	    fclose(fp_yuv);  
107.	#endif   
108.	    
109.	    //av_free(out_buffer);  
110.	    av_free(pFrameYUV);  
111.	    avcodec_close(pCodecCtx);  
112.	    avformat_close_input(&pFormatCtx);  
113.	   
114.	    return 0;  
115.	}  

3.验证

3.1 编译

1.	#!/bin/sh  
2.	export PKG_CONFIG_PATH=/home/quange/ffmpeg_build/lib/pkgconfig/:$PKG_CONFIG_PATH  
3.	gcc ffmpeg_get_camera_frame.c -g -o ffmpeg_get_camera_frame.out  -lSDLmain -lSDL  `pkg-config "libavcodec" --cflags --libs` `pkg-config "libavformat" --cflags --libs` `pkg-config "libavutil" --cflags --libs` `pkg-config "libswscale" --cflags --libs` `pkg-config "libavdevice" --cflags --libs`

3.1 结果

使用软件7yuv打开output.yuv
保存的YUV数据

4.参考资料

[1] 雷霄骅最简单的基于FFmpeg的AVDevice例子(读取摄像头)
https://blog.csdn.net/leixiaohua1020/article/details/39702113

[2] https://blog.csdn.net/li_wen01/article/details/67631687

猜你喜欢

转载自blog.csdn.net/quange_style/article/details/90082114
今日推荐