//-------------------------------------------------------------------------------------------------
参考链接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-音频实时采集编码封装
6、 ffmpeg-音视频实时采集编码封装
//---------------------------------------------------------------
系统环境:
系统版本:lubuntu 16.04
Ffmpge版本:ffmpeg version N-93527-g1125277
摄像头:1.3M HD WebCan
虚拟机:Oracle VM VirtualBox 5.2.22
本章文档基于源码/doc/example/muxing.c例子,仅仅是使用了其音频产生功能。
FFmpeg中有一个和多媒体设备交互的类库:Libavdevice。使用这个库可以读取电脑(或者其他设备上)的多媒体设备的数据,或者输出数据到指定的多媒体设备上
程序产生正弦音频pcm数据,使用44100采样率,经过AAC编码,封装成并保存成test.mp4文件:
1. #include <stdlib.h>
2. #include <stdio.h>
3. #include <string.h>
4. #include <math.h>
5.
6. #include <libavutil/avassert.h>
7. #include <libavutil/channel_layout.h>
8. #include <libavutil/opt.h>
9. #include <libavutil/mathematics.h>
10. #include <libavutil/timestamp.h>
11. #include <libavformat/avformat.h>
12. #include <libswscale/swscale.h>
13. #include <libswresample/swresample.h>
14.
15. #define STREAM_DURATION 10.0
16. #define STREAM_FRAME_RATE 25 /* 25 images/s */
17. #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
18.
19. #define SCALE_FLAGS SWS_BICUBIC
20.
21. // a wrapper around a single output AVStream
22. typedef struct OutputStream {
23. AVStream *st;
24. AVCodecContext *enc;
25.
26. /* pts of the next frame that will be generated */
27. int64_t next_pts;
28. int samples_count;
29.
30. AVFrame *frame;
31. AVFrame *tmp_frame;
32.
33. float t, tincr, tincr2;
34.
35. struct SwsContext *sws_ctx;
36. struct SwrContext *swr_ctx;
37. } OutputStream;
38.
39. static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
40. {
41. AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
42.
43. printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
44. av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
45. av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
46. av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
47. pkt->stream_index);
48. }
49.
50. static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
51. {
52. /* rescale output packet timestamp values from codec to stream timebase */
53. av_packet_rescale_ts(pkt, *time_base, st->time_base);
54. pkt->stream_index = st->index;
55.
56. /* Write the compressed frame to the media file. */
57. log_packet(fmt_ctx, pkt);
58. return av_interleaved_write_frame(fmt_ctx, pkt);
59. }
60.
61. /* Add an output stream. */
62. static void add_stream(OutputStream *ost, AVFormatContext *oc,
63. AVCodec **codec,
64. enum AVCodecID codec_id)
65. {
66. AVCodecContext *c;
67. int i;
68.
69. /* find the encoder */
70. *codec = avcodec_find_encoder(codec_id);
71. if (!(*codec)) {
72. fprintf(stderr, "Could not find encoder for '%s'\n",
73. avcodec_get_name(codec_id));
74. exit(1);
75. }
76.
77. ost->st = avformat_new_stream(oc, NULL);
78. if (!ost->st) {
79. fprintf(stderr, "Could not allocate stream\n");
80. exit(1);
81. }
82. ost->st->id = oc->nb_streams-1;
83. c = avcodec_alloc_context3(*codec);
84. if (!c) {
85. fprintf(stderr, "Could not alloc an encoding context\n");
86. exit(1);
87. }
88. ost->enc = c;
89.
90. switch ((*codec)->type) {
91. case AVMEDIA_TYPE_AUDIO:
92. c->sample_fmt = (*codec)->sample_fmts ?
93. (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
94. c->bit_rate = 64000;
95. c->sample_rate = 44100;
96. if ((*codec)->supported_samplerates) {
97. c->sample_rate = (*codec)->supported_samplerates[0];
98. for (i = 0; (*codec)->supported_samplerates[i]; i++) {
99. if ((*codec)->supported_samplerates[i] == 44100)
100. c->sample_rate = 44100;
101. }
102. }
103. c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
104. c->channel_layout = AV_CH_LAYOUT_STEREO;
105. if ((*codec)->channel_layouts) {
106. c->channel_layout = (*codec)->channel_layouts[0];
107. for (i = 0; (*codec)->channel_layouts[i]; i++) {
108. if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
109. c->channel_layout = AV_CH_LAYOUT_STEREO;
110. }
111. }
112. c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
113. ost->st->time_base = (AVRational){
1, c->sample_rate };
114. break;
115.
116. case AVMEDIA_TYPE_VIDEO:
117. c->codec_id = codec_id;
118.
119. c->bit_rate = 400000;
120. /* Resolution must be a multiple of two. */
121. c->width = 352;
122. c->height = 288;
123. /* timebase: This is the fundamental unit of time (in seconds) in terms
124. * of which frame timestamps are represented. For fixed-fps content,
125. * timebase should be 1/framerate and timestamp increments should be
126. * identical to 1. */
127. ost->st->time_base = (AVRational){
1, STREAM_FRAME_RATE };
128. c->time_base = ost->st->time_base;
129.
130. c->gop_size = 12; /* emit one intra frame every twelve frames at most */
131. c->pix_fmt = STREAM_PIX_FMT;
132. if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
133. /* just for testing, we also add B-frames */
134. c->max_b_frames = 2;
135. }
136. if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
137. /* Needed to avoid using macroblocks in which some coeffs overflow.
138. * This does not happen with normal video, it just happens here as
139. * the motion of the chroma plane does not match the luma plane. */
140. c->mb_decision = 2;
141. }
142. break;
143.
144. default:
145. break;
146. }
147.
148. /* Some formats want stream headers to be separate. */
149. if (oc->oformat->flags & AVFMT_GLOBALHEADER)
150. c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
151. }
152.
153. /**************************************************************/
154. /* audio output */
155.
156. static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
157. uint64_t channel_layout,
158. int sample_rate, int nb_samples)
159. {
160. AVFrame *frame = av_frame_alloc();
161. int ret;
162.
163. if (!frame) {
164. fprintf(stderr, "Error allocating an audio frame\n");
165. exit(1);
166. }
167.
168. frame->format = sample_fmt;
169. frame->channel_layout = channel_layout;
170. frame->sample_rate = sample_rate;
171. frame->nb_samples = nb_samples;
172.
173. if (nb_samples) {
174. ret = av_frame_get_buffer(frame, 0);
175. if (ret < 0) {
176. fprintf(stderr, "Error allocating an audio buffer\n");
177. exit(1);
178. }
179. }
180.
181. return frame;
182. }
183.
184. static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
185. {
186. AVCodecContext *c;
187. int nb_samples;
188. int ret;
189. AVDictionary *opt = NULL;
190.
191. c = ost->enc;
192.
193. /* open it */
194. av_dict_copy(&opt, opt_arg, 0);
195. ret = avcodec_open2(c, codec, &opt);
196. av_dict_free(&opt);
197. if (ret < 0) {
198. fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
199. exit(1);
200. }
201.
202. /* init signal generator */
203. ost->t = 0;
204. ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
205. /* increment frequency by 110 Hz per second */
206. ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
207.
208. if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
209. nb_samples = 10000;
210. else
211. nb_samples = c->frame_size;
212.
213. ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout,
214. c->sample_rate, nb_samples);
215. ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
216. c->sample_rate, nb_samples);
217.
218. /* copy the stream parameters to the muxer */
219. ret = avcodec_parameters_from_context(ost->st->codecpar, c);
220. if (ret < 0) {
221. fprintf(stderr, "Could not copy the stream parameters\n");
222. exit(1);
223. }
224.
225. /* create resampler context */
226. ost->swr_ctx = swr_alloc();
227. if (!ost->swr_ctx) {
228. fprintf(stderr, "Could not allocate resampler context\n");
229. exit(1);
230. }
231.
232. /* set options */
233. av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0);
234. av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0);
235. av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
236. av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0);
237. av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0);
238. av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0);
239.
240. /* initialize the resampling context */
241. if ((ret = swr_init(ost->swr_ctx)) < 0) {
242. fprintf(stderr, "Failed to initialize the resampling context\n");
243. exit(1);
244. }
245. }
246.
247. /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
248. * 'nb_channels' channels. */
249. static AVFrame *get_audio_frame(OutputStream *ost)
250. {
251. AVFrame *frame = ost->tmp_frame;
252. int j, i, v;
253. int16_t *q = (int16_t*)frame->data[0];
254.
255. /* check if we want to generate more frames */
256. if (av_compare_ts(ost->next_pts, ost->enc->time_base,
257. STREAM_DURATION, (AVRational){
1, 1 }) >= 0)
258. return NULL;
259.
260. for (j = 0; j <frame->nb_samples; j++) {
261. v = (int)(sin(ost->t) * 10000);
262. for (i = 0; i < ost->enc->channels; i++)
263. *q++ = v;
264. ost->t += ost->tincr;
265. ost->tincr += ost->tincr2;
266. }
267.
268. frame->pts = ost->next_pts;
269. ost->next_pts += frame->nb_samples;
270.
271. return frame;
272. }
273.
274. /*
275. * encode one audio frame and send it to the muxer
276. * return 1 when encoding is finished, 0 otherwise
277. */
278. static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
279. {
280. AVCodecContext *c;
281. AVPacket pkt = {
0 }; // data and size must be 0;
282. AVFrame *frame;
283. int ret;
284. int got_packet;
285. int dst_nb_samples;
286.
287. av_init_packet(&pkt);
288. c = ost->enc;
289.
290. frame = get_audio_frame(ost);
291.
292. if (frame) {
293. /* convert samples from native format to destination codec format, using the resampler */
294. /* compute destination number of samples */
295. dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
296. c->sample_rate, c->sample_rate, AV_ROUND_UP);
297. av_assert0(dst_nb_samples == frame->nb_samples);
298.
299. /* when we pass a frame to the encoder, it may keep a reference to it
300. * internally;
301. * make sure we do not overwrite it here
302. */
303. ret = av_frame_make_writable(ost->frame);
304. if (ret < 0)
305. exit(1);
306.
307. /* convert to destination format */
308. ret = swr_convert(ost->swr_ctx,
309. ost->frame->data, dst_nb_samples,
310. (const uint8_t **)frame->data, frame->nb_samples);
311. if (ret < 0) {
312. fprintf(stderr, "Error while converting\n");
313. exit(1);
314. }
315. frame = ost->frame;
316.
317. frame->pts = av_rescale_q(ost->samples_count, (AVRational){
1, c->sample_rate}, c->time_base);
318. ost->samples_count += dst_nb_samples;
319. }
320.
321. ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
322. if (ret < 0) {
323. fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
324. exit(1);
325. }
326.
327. if (got_packet) {
328. ret = write_frame(oc, &c->time_base, ost->st, &pkt);
329. if (ret < 0) {
330. fprintf(stderr, "Error while writing audio frame: %s\n",
331. av_err2str(ret));
332. exit(1);
333. }
334. }
335.
336. return (frame || got_packet) ? 0 : 1;
337. }
338.
339. /**************************************************************/
340.
341.
342. static void close_stream(AVFormatContext *oc, OutputStream *ost)
343. {
344. avcodec_free_context(&ost->enc);
345. av_frame_free(&ost->frame);
346. av_frame_free(&ost->tmp_frame);
347. sws_freeContext(ost->sws_ctx);
348. swr_free(&ost->swr_ctx);
349. }
350.
351. /**************************************************************/
352. /* media file output */
353.
354. int main(int argc, char **argv)
355. {
356. OutputStream video_st = {
0 }, audio_st = {
0 };
357. const char *filename;
358. AVOutputFormat *fmt;
359. AVFormatContext *oc;
360. AVCodec *audio_codec, *video_codec;
361. int ret;
362. int have_video = 0, have_audio = 0;
363. int encode_video = 0, encode_audio = 0;
364. AVDictionary *opt = NULL;
365. int i;
366.
367. if (argc < 2) {
368. printf("usage: %s output_file\n"
369. "API example program to output a media file with libavformat.\n"
370. "This program generates a synthetic audio and video stream, encodes and\n"
371. "muxes them into a file named output_file.\n"
372. "The output format is automatically guessed according to the file extension.\n"
373. "Raw images can also be output by using '%%d' in the filename.\n"
374. "\n", argv[0]);
375. return 1;
376. }
377.
378. filename = argv[1];
379. for (i = 2; i+1 < argc; i+=2) {
380. if (!strcmp(argv[i], "-flags") || !strcmp(argv[i], "-fflags"))
381. av_dict_set(&opt, argv[i]+1, argv[i+1], 0);
382. }
383.
384. /* allocate the output media context */
385. avformat_alloc_output_context2(&oc, NULL, NULL, filename);
386. if (!oc) {
387. printf("Could not deduce output format from file extension: using MPEG.\n");
388. avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
389. }
390. if (!oc)
391. return 1;
392.
393. fmt = oc->oformat;
394.
395. /* Add the audio and video streams using the default format codecs
396. * and initialize the codecs. */
397.
398. if (fmt->audio_codec != AV_CODEC_ID_NONE) {
399. add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
400. have_audio = 1;
401. encode_audio = 1;
402. }
403.
404. /* Now that all the parameters are set, we can open the audio and
405. * video codecs and allocate the necessary encode buffers. */
406.
407. if (have_audio)
408. open_audio(oc, audio_codec, &audio_st, opt);
409.
410. av_dump_format(oc, 0, filename, 1);
411.
412. /* open the output file, if needed */
413. if (!(fmt->flags & AVFMT_NOFILE)) {
414. ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
415. if (ret < 0) {
416. fprintf(stderr, "Could not open '%s': %s\n", filename,
417. av_err2str(ret));
418. return 1;
419. }
420. }
421.
422. /* Write the stream header, if any. */
423. ret = avformat_write_header(oc, &opt);
424. if (ret < 0) {
425. fprintf(stderr, "Error occurred when opening output file: %s\n",
426. av_err2str(ret));
427. return 1;
428. }
429.
430. while (encode_video || encode_audio) {
431. /* select the stream to encode */
432. encode_audio = !write_audio_frame(oc, &audio_st);
433. }
434.
435. /* Write the trailer, if any. The trailer must be written before you
436. * close the CodecContexts open when you wrote the header; otherwise
437. * av_write_trailer() may try to use memory that was freed on
438. * av_codec_close(). */
439. av_write_trailer(oc);
440.
441. /* Close each codec. */
442. if (have_audio)
443. close_stream(oc, &audio_st);
444.
445. if (!(fmt->flags & AVFMT_NOFILE))
446. /* Close the output file. */
447. avio_closep(&oc->pb);
448.
449. /* free the stream */
450. avformat_free_context(oc);
451.
452. return 0;
453. }
1. #!/bin/sh
2. export PKG_CONFIG_PATH=/home/quange/ffmpeg_build/lib/pkgconfig/:$PKG_CONFIG_PATH
3. gcc ffmpeg_get_pcm_muxing.c -g -o ffmpeg_get_pcm_muxing.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`
ffmpeg_get_pcm_muxing.out test.mp4
使用ffplay打开test.mp4,可以听到音调从小到大的音频数据
无
[1] 雷霄骅最简单的基于FFmpeg的AVDevice例子(读取摄像头)
https://blog.csdn.net/leixiaohua1020/article/details/39702113
[2] https://blog.csdn.net/li_wen01/article/details/67631687
[3]https://blog.csdn.net/boonya/article/details/80649018
[4] https://blog.csdn.net/luoyouren/article/details/48464809
[5] https://www.jianshu.com/p/514707091c83