生成的MP4文件,用播放器看见的视频如下,同时你可以听到一种呼叫的音频声音

生成的MP4文件音频为(aac)、视频为H264
由于生成的H264需要依赖x264开源库【因为需要将普通的原始数据编码成H264,而ffmpeg默认是按x264进行编码】,在生产x264库过程中,一般我们默认生成静态库即可。

编译ffmpeg并安装

代码如下:

[cpp] view plaincopy
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include "libavutil/mathematics.h"
  6. #include "libavformat/avformat.h"
  7. #include "libswscale/swscale.h"
  8. #undef exit
  9. /* 5 seconds stream duration */
  10. #define STREAM_DURATION   200.0
  11. #define STREAM_FRAME_RATE 25 /* 25 images/s */
  12. #define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
  13. #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
  14. static int sws_flags = SWS_BICUBIC;
  15. /**************************************************************/
  16. /* audio output */
  17. static float t, tincr, tincr2;
  18. static int16_t *samples;
  19. static uint8_t *audio_outbuf;
  20. static int audio_outbuf_size;
  21. static int audio_input_frame_size;
  22. /*
  23. * add an audio output stream
  24. */
  25. static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id)
  26. {
  27. AVCodecContext *c;
  28. AVStream *st;
  29. st = avformat_new_stream(oc, NULL);
  30. if (!st) {
  31. fprintf(stderr, "Could not alloc stream\n");
  32. exit(1);
  33. }
  34. st->id = 1;
  35. c = st->codec;
  36. c->codec_id = codec_id;
  37. c->codec_type = AVMEDIA_TYPE_AUDIO;
  38. /* put sample parameters */
  39. c->sample_fmt = AV_SAMPLE_FMT_S16;
  40. c->bit_rate = 64000;
  41. c->sample_rate = 44100;
  42. c->channels = 2;
  43. // some formats want stream headers to be separate
  44. if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  45. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  46. return st;
  47. }
  48. static void open_audio(AVFormatContext *oc, AVStream *st)
  49. {
  50. AVCodecContext *c;
  51. AVCodec *codec;
  52. c = st->codec;
  53. /* find the audio encoder */
  54. codec = avcodec_find_encoder(c->codec_id);
  55. if (!codec) {
  56. fprintf(stderr, "codec not found\n");
  57. exit(1);
  58. }
  59. /* open it */
  60. if (avcodec_open(c, codec) < 0) {
  61. fprintf(stderr, "could not open codec\n");
  62. exit(1);
  63. }
  64. /* init signal generator */
  65. t = 0;
  66. tincr = 2 * M_PI * 110.0 / c->sample_rate;
  67. /* increment frequency by 110 Hz per second */
  68. tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
  69. audio_outbuf_size = 10000;
  70. audio_outbuf = av_malloc(audio_outbuf_size);
  71. if (c->frame_size <= 1) {
  72. audio_input_frame_size = audio_outbuf_size / c->channels;
  73. switch(st->codec->codec_id) {
  74. case CODEC_ID_PCM_S16LE:
  75. case CODEC_ID_PCM_S16BE:
  76. case CODEC_ID_PCM_U16LE:
  77. case CODEC_ID_PCM_U16BE:
  78. audio_input_frame_size >>= 1;
  79. break;
  80. default:
  81. break;
  82. }
  83. } else {
  84. audio_input_frame_size = c->frame_size;
  85. }
  86. samples = av_malloc(audio_input_frame_size * 2 * c->channels);
  87. }
  88. static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
  89. {
  90. int j, i, v;
  91. int16_t *q;
  92. q = samples;
  93. for (j = 0; j < frame_size; j++) {
  94. v = (int)(sin(t) * 10000);
  95. for(i = 0; i < nb_channels; i++)
  96. *q++ = v;
  97. t += tincr;
  98. tincr += tincr2;
  99. }
  100. }
  101. static void write_audio_frame(AVFormatContext *oc, AVStream *st)
  102. {
  103. AVCodecContext *c;
  104. AVPacket pkt;
  105. av_init_packet(&pkt);
  106. c = st->codec;
  107. get_audio_frame(samples, audio_input_frame_size, c->channels);
  108. pkt.size = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
  109. if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
  110. pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
  111. pkt.flags |= AV_PKT_FLAG_KEY;
  112. pkt.stream_index = st->index;
  113. pkt.data = audio_outbuf;
  114. /* write the compressed frame in the media file */
  115. if (av_interleaved_write_frame(oc, &pkt) != 0) {
  116. fprintf(stderr, "Error while writing audio frame\n");
  117. exit(1);
  118. }
  119. }
  120. static void close_audio(AVFormatContext *oc, AVStream *st)
  121. {
  122. avcodec_close(st->codec);
  123. av_free(samples);
  124. av_free(audio_outbuf);
  125. }
  126. /**************************************************************/
  127. /* video output */
  128. static AVFrame *picture, *tmp_picture;
  129. static uint8_t *video_outbuf;
  130. static int frame_count, video_outbuf_size;
  131. /* add a video output stream */
  132. static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id)
  133. {
  134. AVCodecContext *c;
  135. AVStream *st;
  136. AVCodec *codec;
  137. st = avformat_new_stream(oc, NULL);
  138. if (!st) {
  139. fprintf(stderr, "Could not alloc stream\n");
  140. exit(1);
  141. }
  142. c = st->codec;
  143. /* find the video encoder */
  144. codec = avcodec_find_encoder(codec_id);
  145. if (!codec) {
  146. fprintf(stderr, "codec not found\n");
  147. exit(1);
  148. }
  149. avcodec_get_context_defaults3(c, codec);
  150. c->codec_id = codec_id;
  151. /* put sample parameters */
  152. c->bit_rate = 400000;
  153. /* resolution must be a multiple of two */
  154. c->width = 352;
  155. c->height = 288;
  156. /* time base: this is the fundamental unit of time (in seconds) in terms
  157. of which frame timestamps are represented. for fixed-fps content,
  158. timebase should be 1/framerate and timestamp increments should be
  159. identically 1. */
  160. c->time_base.den = STREAM_FRAME_RATE;
  161. c->time_base.num = 1;
  162. c->gop_size = 12; /* emit one intra frame every twelve frames at most */
  163. c->pix_fmt = STREAM_PIX_FMT;
  164. if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
  165. /* just for testing, we also add B frames */
  166. c->max_b_frames = 2;
  167. }
  168. if (c->codec_id == CODEC_ID_MPEG1VIDEO){
  169. /* Needed to avoid using macroblocks in which some coeffs overflow.
  170. This does not happen with normal video, it just happens here as
  171. the motion of the chroma plane does not match the luma plane. */
  172. c->mb_decision=2;
  173. }
  174. // some formats want stream headers to be separate
  175. if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  176. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  177. return st;
  178. }
  179. static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height)
  180. {
  181. AVFrame *picture;
  182. uint8_t *picture_buf;
  183. int size;
  184. picture = avcodec_alloc_frame();
  185. if (!picture)
  186. return NULL;
  187. size = avpicture_get_size(pix_fmt, width, height);
  188. picture_buf = av_malloc(size);
  189. if (!picture_buf) {
  190. av_free(picture);
  191. return NULL;
  192. }
  193. avpicture_fill((AVPicture *)picture, picture_buf,
  194. pix_fmt, width, height);
  195. return picture;
  196. }
  197. static void open_video(AVFormatContext *oc, AVStream *st)
  198. {
  199. AVCodec *codec;
  200. AVCodecContext *c;
  201. c = st->codec;
  202. /* find the video encoder */
  203. codec = avcodec_find_encoder(c->codec_id);
  204. if (!codec) {
  205. fprintf(stderr, "codec not found\n");
  206. exit(1);
  207. }
  208. /* open the codec */
  209. if (avcodec_open(c, codec) < 0) {
  210. fprintf(stderr, "could not open codec\n");
  211. exit(1);
  212. }
  213. video_outbuf = NULL;
  214. if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
  215. video_outbuf_size = 200000;
  216. video_outbuf = av_malloc(video_outbuf_size);
  217. }
  218. /* allocate the encoded raw picture */
  219. picture = alloc_picture(c->pix_fmt, c->width, c->height);
  220. if (!picture) {
  221. fprintf(stderr, "Could not allocate picture\n");
  222. exit(1);
  223. }
  224. /* if the output format is not YUV420P, then a temporary YUV420P
  225. picture is needed too. It is then converted to the required
  226. output format */
  227. tmp_picture = NULL;
  228. if (c->pix_fmt != PIX_FMT_YUV420P) {
  229. tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
  230. if (!tmp_picture) {
  231. fprintf(stderr, "Could not allocate temporary picture\n");
  232. exit(1);
  233. }
  234. }
  235. }
  236. /* prepare a dummy image */
  237. static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
  238. {
  239. int x, y, i;
  240. i = frame_index;
  241. /* Y */
  242. for (y = 0; y < height; y++) {
  243. for (x = 0; x < width; x++) {
  244. pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
  245. }
  246. }
  247. /* Cb and Cr */
  248. for (y = 0; y < height/2; y++) {
  249. for (x = 0; x < width/2; x++) {
  250. pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
  251. pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
  252. }
  253. }
  254. }
  255. static void write_video_frame(AVFormatContext *oc, AVStream *st)
  256. {
  257. int out_size, ret;
  258. AVCodecContext *c;
  259. static struct SwsContext *img_convert_ctx;
  260. c = st->codec;
  261. if (frame_count >= STREAM_NB_FRAMES) {
  262. /* no more frame to compress. The codec has a latency of a few
  263. frames if using B frames, so we get the last frames by
  264. passing the same picture again */
  265. } else {
  266. if (c->pix_fmt != PIX_FMT_YUV420P) {
  267. /* as we only generate a YUV420P picture, we must convert it
  268. to the codec pixel format if needed */
  269. if (img_convert_ctx == NULL) {
  270. img_convert_ctx = sws_getContext(c->width, c->height,
  271. PIX_FMT_YUV420P,
  272. c->width, c->height,
  273. c->pix_fmt,
  274. sws_flags, NULL, NULL, NULL);
  275. if (img_convert_ctx == NULL) {
  276. fprintf(stderr, "Cannot initialize the conversion context\n");
  277. exit(1);
  278. }
  279. }
  280. fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
  281. sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
  282. 0, c->height, picture->data, picture->linesize);
  283. } else {
  284. fill_yuv_image(picture, frame_count, c->width, c->height);
  285. }
  286. }
  287. if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  288. /* raw video case. The API will change slightly in the near
  289. future for that. */
  290. AVPacket pkt;
  291. av_init_packet(&pkt);
  292. pkt.flags |= AV_PKT_FLAG_KEY;
  293. pkt.stream_index = st->index;
  294. pkt.data = (uint8_t *)picture;
  295. pkt.size = sizeof(AVPicture);
  296. ret = av_interleaved_write_frame(oc, &pkt);
  297. } else {
  298. /* encode the image */
  299. out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
  300. /* if zero size, it means the image was buffered */
  301. if (out_size > 0) {
  302. AVPacket pkt;
  303. av_init_packet(&pkt);
  304. if (c->coded_frame->pts != AV_NOPTS_VALUE)
  305. pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
  306. if(c->coded_frame->key_frame)
  307. pkt.flags |= AV_PKT_FLAG_KEY;
  308. pkt.stream_index = st->index;
  309. pkt.data = video_outbuf;
  310. pkt.size = out_size;
  311. /* write the compressed frame in the media file */
  312. ret = av_interleaved_write_frame(oc, &pkt);
  313. } else {
  314. ret = 0;
  315. }
  316. }
  317. if (ret != 0) {
  318. fprintf(stderr, "Error while writing video frame\n");
  319. exit(1);
  320. }
  321. frame_count++;
  322. }
  323. static void close_video(AVFormatContext *oc, AVStream *st)
  324. {
  325. avcodec_close(st->codec);
  326. av_free(picture->data[0]);
  327. av_free(picture);
  328. if (tmp_picture) {
  329. av_free(tmp_picture->data[0]);
  330. av_free(tmp_picture);
  331. }
  332. av_free(video_outbuf);
  333. }
  334. /**************************************************************/
  335. /* media file output */
  336. int main(int argc, char **argv)
  337. {
  338. const char *filename;
  339. AVOutputFormat *fmt;
  340. AVFormatContext *oc;
  341. AVStream *audio_st, *video_st;
  342. double audio_pts, video_pts;
  343. int i;
  344. /* initialize libavcodec, and register all codecs and formats */
  345. av_register_all();
  346. if (argc != 2) {
  347. printf("usage: %s output_file\n"
  348. "API example program to output a media file with libavformat.\n"
  349. "The output format is automatically guessed according to the file extension.\n"
  350. "Raw images can also be output by using '%%d' in the filename\n"
  351. "\n", argv[0]);
  352. return 1;
  353. }
  354. filename = argv[1];
  355. /* allocate the output media context */
  356. avformat_alloc_output_context2(&oc, NULL, NULL, filename);
  357. if (!oc) {
  358. printf("Could not deduce output format from file extension: using MPEG.\n");
  359. avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
  360. }
  361. if (!oc) {
  362. return 1;
  363. }
  364. fmt = oc->oformat;
  365. /* add the audio and video streams using the default format codecs
  366. and initialize the codecs */
  367. video_st = NULL;
  368. audio_st = NULL;
  369. if (fmt->video_codec != CODEC_ID_NONE) {
  370. video_st = add_video_stream(oc, fmt->video_codec);
  371. }
  372. if (fmt->audio_codec != CODEC_ID_NONE) {
  373. audio_st = add_audio_stream(oc, fmt->audio_codec);
  374. }
  375. av_dump_format(oc, 0, filename, 1);
  376. /* now that all the parameters are set, we can open the audio and
  377. video codecs and allocate the necessary encode buffers */
  378. if (video_st)
  379. open_video(oc, video_st);
  380. if (audio_st)
  381. open_audio(oc, audio_st);
  382. /* open the output file, if needed */
  383. if (!(fmt->flags & AVFMT_NOFILE)) {
  384. if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
  385. fprintf(stderr, "Could not open '%s'\n", filename);
  386. return 1;
  387. }
  388. }
  389. /* write the stream header, if any */
  390. av_write_header(oc);
  391. picture->pts = 0;
  392. for(;;) {
  393. /* compute current audio and video time */
  394. if (audio_st)
  395. audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
  396. else
  397. audio_pts = 0.0;
  398. if (video_st)
  399. video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
  400. else
  401. video_pts = 0.0;
  402. if ((!audio_st || audio_pts >= STREAM_DURATION) &&
  403. (!video_st || video_pts >= STREAM_DURATION))
  404. break;
  405. /* write interleaved audio and video frames */
  406. if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
  407. write_audio_frame(oc, audio_st);
  408. } else {
  409. write_video_frame(oc, video_st);
  410. picture->pts++;
  411. }
  412. }
  413. av_write_trailer(oc);
  414. /* close each codec */
  415. if (video_st)
  416. close_video(oc, video_st);
  417. if (audio_st)
  418. close_audio(oc, audio_st);
  419. /* free the streams */
  420. for(i = 0; i < oc->nb_streams; i++) {
  421. av_freep(&oc->streams[i]->codec);
  422. av_freep(&oc->streams[i]);
  423. }
  424. if (!(fmt->flags & AVFMT_NOFILE)) {
  425. /* close the output file */
  426. avio_close(oc->pb);
  427. }
  428. /* free the stream */
  429. av_free(oc);
  430. return 0;
  431. }

参考:http://www.ylmf.net/ubuntu/tips/2010122919090_3.html

http://hi.baidu.com/ccqi0000/blog/item/d39fb21f1d5157a84aedbcb1.html

运用ffmpeg生成MP4文件相关推荐

  1. 解决ffmpeg生成mp4文件不能正常预览的问题

    框架的使用极大的提高了开发效率,让我们能够有更多的精力去关注系统的整体架构和业务需求,而不需要过多的关注一些具体的实现细节,但任何事情都有两面性,如果某个细节出了问题,由于对具体的实现不了解,那么会给 ...

  2. 利用FFmpeg转码生成MP4文件

    利用FFmpeg转码生成MP4文件 2017年06月24日 14:42:53 阅读数:2401 项目中,需要把一路音频流及一路视频流分别转码,生成指定格式(MP4)文件.在使用ffmpeg转码生成mp ...

  3. FFMpeg写MP4文件例子分析

    这段时间看了FFMpeg提供的例子muxing.c,我略微修改了下源代码,使其生成一个MP4文件,音频使用AAC编码,视频使用H.264编码.代码很简单,我就不做说明了,代码如下.以后我们继续写如何将 ...

  4. 转: FFMpeg 封装MP4 文件

    FFmpeg 封装MP4文件的一个例子    项目中用到FFmpeg 将IP摄像头的视频流的保存MP4文件的.之前的大哥将它先存成了H264文件,然后又调用FFMpeg的命令行去实现转码为MP4.感觉 ...

  5. 服务器php将视频转为m3u8,php应用ffmpeg对mp4文件转换并生成m3u8视频流文件

    生成m3u8视频流,如果没有做视频流文件,播放视频的时候,一个大视频直接加载,会增加服务器巨大压力,并且视频太大加载慢,显示视频也慢,都不利于观看.那么视频流的好处是,将大视频分成一小段一小段的ts分 ...

  6. 使用ffmpeg从mp4文件中提取视频流到h264文件中

    注释: -i 2018.mp4:  是输入的MP4文件 -codec copy: 从mp4中拷贝 -bsf: h264_mp4toannexb: 从mp4拷贝到annexB封装 -f h264: 采用 ...

  7. 照做就完事了:Mac下编译ffmpeg生成so文件

    下载ffmpeg源码 下载地址:www.ffmpeg.org/download.ht- 下载NDK 下载地址:user-gold-cdn.xitu.io/2019/4/10/1- 编写Android脚 ...

  8. 安卓采集摄像头画面生成MP4文件

    主要用的安卓类有MediaCodec和MediaMuxer,MediaCodec负责视频数据编解码,MediaMuxer负责将编码后的数据封装成MP4文件,采集摄像头用的是camera,并且用surf ...

  9. windows使用ffmpeg将mp4文件转变成h264视频文件

    我是直接使用ffmpeg的安装包,win10下 首先下载ffmpeg http://www.ffmpeg.org/download.htmlhttp://www.ffmpeg.org/download ...

  10. Android中如何提取和生成mp4文件

    1. MediaExtractor 该类主要用于音视频混合数据的分离,接口比较简单,首先要通过setDataSource(String path)函数设置数据源,数据源可以是本地文件地址,也可以使用H ...

最新文章

  1. [Vue warn]: Failed to mount component: template or render function not defined. 错误解决方法
  2. Harvard's CS50
  3. 交叉编译和交叉调试环境的搭建及使用
  4. OpenGL indexedCube索引多维数据集的实例
  5. 编辑器js获取浏览器高度和宽度值(转)
  6. 计算机系统结构 期末复习
  7. php函数声明提前,php的日期处理函数及uchome的function_coomon中日期处理函数的研究...
  8. redis的bitmap操作
  9. Dart入门—开发环境
  10. bash: test1: command not found
  11. flex mx:TabNavigator进行选项卡切换,需要进行交互时。发生Error #1009错误
  12. LeaRun.Java可视化拖拽编辑的BI大屏
  13. js中的经典题Foo.getName
  14. 新浪开发者平台(Sina App Engine)初探
  15. python 保存网页图片到本地
  16. tp5.1 EasyTask Windows本地测试和centos系统服务器安装
  17. [ArcGIS] 空间分析(五) 网络分析
  18. js如何实现拆分字符串并依次输出
  19. 一文搞懂各种架构(业务架构、应用架构、数据架构...
  20. QUECTEL上海移远4G通讯CAT4模组EC20CEFAG模块串口调试指南之【05EC20模组TCP/IP模块AT指令说明】

热门文章

  1. 内存图片IOS app启动动画的实现
  2. titanium开发教程-04-05从rows打开window
  3. maven 加入第三方库_项目pom里引入第三方库的四个方法
  4. 3.JUC线程高级-同步容器 ConcurrentHashMap
  5. struts标签logic:iterate的用法
  6. MyBatis映射表问题
  7. Go 性能优化技巧 4/10
  8. internet与Internet的区别
  9. wamp环境单独安装(windows下apache2.4、mysql5.5、php5.5的版本)
  10. 为什么用preparedStatement 而不是statement