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
4.参考资料
[1] 雷霄骅最简单的基于FFmpeg的AVDevice例子(读取摄像头)
https://blog.csdn.net/leixiaohua1020/article/details/39702113