系统环境:
系统版本:lubuntu 16.04
Ffmpge版本:ffmpeg version N-93527-g1125277
摄像头:1.3M HD WebCan
虚拟机:Oracle VM VirtualBox 5.2.22
指令查看设备 ffmpeg -devices
本章文档基于《ffmpeg-摄像头采集编码封装》和《ffmpeg-音频实时采集编码封装》。在同一进程中,判断其产生的time=pts*time_base,根据其视频的帧率,以及音频产生的采样率等,来比较当前帧时间time,来写入音视频。
1.简介
FFmpeg中有一个和多媒体设备交互的类库:Libavdevice。使用这个库可以读取电脑(或者其他设备上)的多媒体设备的数据,或者输出数据到指定的多媒体设备上。
1.1数据流程图
![](https://i-blog.csdnimg.cn/blog_migrate/9eb8f7d10c0aeb269b3fa869d0945f5c.png)
1.2 代码流程图
![](https://i-blog.csdnimg.cn/blog_migrate/fd028f94bb6a519177baa2427b02cd61.png)
1.3 队列传输流程图
2.源码
最简单的基于Libavdevice的音频采集口数据读取一帧帧pcm数据,经过音频重采样获取目标AAC的音频源数据参数,同时基于Libavdevice的视频采集口,获取yuv420数据,再经过编码,封装等,保存成FLV文件。
程序主要是参考/doc/example/muxing.c源码的音视频同步方法。
2.1音频初始化
1. int open_audio_capture()
2. {
3.
4. printf("open_audio_capture\n");
5.
6. //********add alsa read***********//
7. AVCodecContext *pCodecCtx;
8. AVCodec *pCodec;
9. AVFormatContext *a_ifmtCtx;
10. int i,ret;
11. //Register Device
12. avdevice_register_all();
13.
14. a_ifmtCtx = avformat_alloc_context();
15.
16.
17. //Linux
18. AVInputFormat *ifmt=av_find_input_format("alsa");
19. if(avformat_open_input(&a_ifmtCtx,"default",ifmt,NULL)!=0){
20. printf("Couldn't open input stream.default\n");
21. return -1;
22. }
23.
24.
25. if(avformat_find_stream_info(a_ifmtCtx,NULL)<0)
26. {
27. printf("Couldn't find stream information.\n");
28. return -1;
29. }
30.
31. int audioindex=-1;
32. for(i=0; i<a_ifmtCtx->nb_streams; i++)
33. if(a_ifmtCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
34. {
35. audioindex=i;
36. break;
37. }
38. if(audioindex==-1)
39. {
40. printf("Couldn't find a video stream.\n");
41. return -1;
42. }
43.
44. pCodecCtx=a_ifmtCtx->streams[audioindex]->codec;
45. pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
46. if(pCodec==NULL)
47. {
48. printf("Codec not found.\n");
49. return -1;
50. }
51. if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
52. {
53. printf("Could not open codec.\n");
54. return -1;
55. }
56.
57. AVPacket *in_packet=(AVPacket *)av_malloc(sizeof(AVPacket));
58.
59. AVFrame *pAudioFrame=av_frame_alloc();
60. if(NULL==pAudioFrame)
61. {
62. printf("could not alloc pAudioFrame\n");
63. return -1;
64. }
65.
66. //audio output paramter //resample
67. uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
68. int out_sample_fmt = AV_SAMPLE_FMT_S16;
69. int out_nb_samples =1024; //pCodecCtx->frame_size;
70. int out_sample_rate = 48000;
71. int out_nb_channels = av_get_channel_layout_nb_channels(out_channel_layout);
72. int out_buffer_size = av_samples_get_buffer_size(NULL, out_nb_channels, out_nb_samples, out_sample_fmt, 1);
73. uint8_t *dst_buffer=NULL;
74. dst_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE);
75. int64_t in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);
76.
77.
78. printf("audio sample_fmt=%d size=%d channel=%d sample_rate=%d in_channel_layout=%s\n",
79. pCodecCtx->sample_fmt, pCodecCtx->frame_size,
80. pCodecCtx->channels,pCodecCtx->sample_rate,av_ts2str(in_channel_layout));
81.
82. struct SwrContext *audio_convert_ctx = NULL;
83. audio_convert_ctx = swr_alloc();
84. if (audio_convert_ctx == NULL)
85. {
86. printf("Could not allocate SwrContext\n");
87. return -1;
88. }
89.
90. /* set options */
91. av_opt_set_int