FFmpeg Encapsulation Format processing: video/audio multiplexing (muxer)

Source: Internet
Author: User
Tags file url
I plan to record examples of FFmpeg-based Encapsulation Format processing. Including separation, reuse, and Encapsulation Format Conversion of audio and video. This is Article 3rd. This document records an FFmpeg-based audio and video multiplexing (SimplestFFmpegmuxer ). The Muxer combines the compressed video data (for example, H.264) with the compressed audio data (for example, AAC ).

I plan to record examples of FFmpeg-based Encapsulation Format processing. Including separation, reuse, and Encapsulation Format Conversion of audio and video. This is Article 3rd. This document records an FFmpeg-based video/audio multiplexing (Simplest FFmpeg muxer ). The Muxer combines the compressed video data (for example, H.264) with the compressed audio data (for example, AAC ).

I plan to record examples of FFmpeg-based Encapsulation Format processing. Including separation, reuse, and Encapsulation Format Conversion of audio and video. This is Article 3rd.

This document records an FFmpeg-based video/audio multiplexing (Simplest FFmpeg muxer ). The Muxer combines the compressed video data (such as H.264) and compressed audio data (such as AAC) into an encapsulated format data (such as MKV .. Encoding and decoding are not involved in this process.



The program recorded in this article combines an H.264 encoded video code stream file and an MP3 encoded audio code stream file into an MP4 encapsulated file.
Three AVFormatContext are initialized, two of which are used for input and one for output. After the three AVFormatContext initialization, you can use the avcodec_copy_context () function to copy the input video/audio parameters to the AVCodecContext structure of the output video/audio. Then, av_read_frame () of the video input stream and the audio input stream are called respectively to retrieve the AVPacket of the video from the video input stream and the AVPacket of the audio input stream, write the retrieved AVPacket to the output file. In this case, av_compare_ts (), a very common function, is used to compare timestamps. You can use this function to determine whether to write the video or audio.

In this article, the input video is not necessarily a H.264 bare stream file, and the audio is not necessarily a pure audio file. You can select two encapsulated audio and video files as the input. The program will "pick" the video stream from the video input file, "pick" the audio stream in the audio input file, and then reuse the "Selected" audio stream. PS1: for H.264 in certain encapsulation formats (for example, MP4/FLV/MKV), bitstream filter named "h1__mp4to1_ B" must be used.
PS2: bitstream filter named "aac_adtstoasc" is required for AAC in certain encapsulation formats (such as MP4/FLV/MKV.

Briefly introduce the significance of each important function in the process:

Avformat_open_input (): Open the input file.
Avcodec_copy_context (): assign a value to the AVCodecContext parameter.
Avformat_alloc_output_context2 (): Initialize the output file.
Avio_open (): Open the output file.
Avformat_write_header (): Write the file header.
Av_compare_ts (): Compares the timestamp to determine whether to write the video or audio. This function is relatively rare.
Av_read_frame (): read an AVPacket from the input file.
Av_interleaved_write_frame (): Write an AVPacket to the output file.
Av_write_trailer (): The end of the written file.

Code
Paste the code below:[Cpp]View plaincopy
  1. /**
  2. * The simplest FFmpeg-based audio and video multiplexing
  3. * Simplest FFmpeg Muxer
  4. *
  5. * Lei Xiaohua
  6. * leixiaohua1020@126.com
  7. * China Media University/Digital TV technology
  8. * Communication University of China / Digital TV Technology
  9. * http://blog.csdn.net/leixiaohua1020
  10. *
  11. * This program can package the video and audio streams into one Encapsulation Format.
  12. * In the program, package the MP3-encoded audio streams and H.264-encoded video streams (in MPEG2TS encapsulation)
  13. * MP4 encapsulated files.
  14. * Note that this program does not change the audio/video encoding format.
  15. *
  16. * This software mux a video bitstream and a audio bitstream
  17. * together into a file.
  18. * In this example, it mux a H.264 bitstream (in MPEG2TS) and
  19. * a MP3 bitstream file together into MP4 format file.
  20. *
  21. */
  22. #include 
       
  23. extern "C"
  24. {
  25. #include "libavformat/avformat.h"
  26. };
  27. /*
  28. FIX: H.264 in some container format (FLV, MP4, MKV etc.) need
  29. "h264_mp4toannexb" bitstream filter (BSF)
  30. *Add SPS,PPS in front of IDR frame
  31. *Add start code ("0,0,0,1") in front of NALU
  32. H.264 in some container (MPEG2TS) don't need this BSF.
  33. */
  34. //'1': Use H.264 Bitstream Filter
  35. #define USE_H264BSF 0
  36. /*
  37. FIX:AAC in some container format (FLV, MP4, MKV etc.) need
  38. "aac_adtstoasc" bitstream filter (BSF)
  39. */
  40. //'1': Use AAC Bitstream Filter
  41. #define USE_AACBSF 0
  42. int main(int argc, char* argv[])
  43. {
  44. AVOutputFormat *ofmt = NULL;
  45. // The input corresponds to an AVFormatContext, and the output corresponds to an AVFormatContext.
  46. //(Input AVFormatContext and Output AVFormatContext)
  47. AVFormatContext *ifmt_ctx_v = NULL, *ifmt_ctx_a = NULL,*ofmt_ctx = NULL;
  48. AVPacket pkt;
  49. int ret, i;
  50. Char * in_filename_v = "cuc_ieschool.ts"; // Input file URL)
  51. //char *in_filename_v = "cuc_ieschool.h264";
  52. //char *in_filename_a = "cuc_ieschool.mp3";
  53. //char *in_filename_a = "gowest.m4a";
  54. //char *in_filename_a = "gowest.aac";
  55. char *in_filename_a = "huoyuanjia.mp3";
  56. Char * out_filename = "cuc_ieschool.mp4"; // Output file URL)
  57. av_register_all();
  58. // Input)
  59. if ((ret = avformat_open_input(&ifmt_ctx_v, in_filename_v, 0, 0)) < 0) {
  60. printf( "Could not open input file.");
  61. goto end;
  62. }
  63. if ((ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) {
  64. printf( "Failed to retrieve input stream information");
  65. goto end;
  66. }
  67. if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0)) < 0) {
  68. printf( "Could not open input file.");
  69. goto end;
  70. }
  71. if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) {
  72. printf( "Failed to retrieve input stream information");
  73. goto end;
  74. }
  75. printf("Input Information=====================\n");
  76. av_dump_format(ifmt_ctx_v, 0, in_filename_v, 0);
  77. av_dump_format(ifmt_ctx_a, 0, in_filename_a, 0);
  78. printf("======================================\n");
  79. // Output)
  80. avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
  81. if (!ofmt_ctx) {
  82. printf( "Could not create output context\n");
  83. ret = AVERROR_UNKNOWN;
  84. goto end;
  85. }
  86. ofmt = ofmt_ctx->oformat;
  87. int videoindex_v=-1,videoindex_out=-1;
  88. for (i = 0; i < ifmt_ctx_v->nb_streams; i++) {
  89. // Create output AVStream (according to input AVStream)
  90. if(ifmt_ctx_v->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
  91. videoindex_v=i;
  92. AVStream *in_stream = ifmt_ctx_v->streams[i];
  93. AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
  94. if (!out_stream) {
  95. printf( "Failed allocating output stream\n");
  96. ret = AVERROR_UNKNOWN;
  97. goto end;
  98. }
  99. videoindex_out=out_stream->index;
  100. // Copy the settings of AVCodecContext)
  101. if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
  102. printf( "Failed to copy context from input to output stream codec context\n");
  103. goto end;
  104. }
  105. out_stream->codec->codec_tag = 0;
  106. if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
  107. out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  108. break;
  109. }
  110. }
  111. int audioindex_a=-1,audioindex_out=-1;
  112. for (i = 0; i < ifmt_ctx_a->nb_streams; i++) {
  113. // Create output AVStream (according to input AVStream)
  114. if(ifmt_ctx_a->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
  115. audioindex_a=i;
  116. AVStream *in_stream = ifmt_ctx_a->streams[i];
  117. AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
  118. if (!out_stream) {
  119. printf( "Failed allocating output stream\n");
  120. ret = AVERROR_UNKNOWN;
  121. goto end;
  122. }
  123. audioindex_out=out_stream->index;
  124. // Copy the settings of AVCodecContext)
  125. if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
  126. printf( "Failed to copy context from input to output stream codec context\n");
  127. goto end;
  128. }
  129. out_stream->codec->codec_tag = 0;
  130. if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
  131. out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  132. break;
  133. }
  134. }
  135. // Output the following format ------------------
  136. printf("Output Information====================\n");
  137. av_dump_format(ofmt_ctx, 0, out_filename, 1);
  138. printf("======================================\n");
  139. // Open output file)
  140. if (!(ofmt->flags & AVFMT_NOFILE)) {
  141. if (avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) {
  142. printf( "Could not open output file '%s'", out_filename);
  143. goto end;
  144. }
  145. }
  146. // Write file header)
  147. if (avformat_write_header(ofmt_ctx, NULL) < 0) {
  148. printf( "Error occurred when opening output file\n");
  149. goto end;
  150. }
  151. int frame_index=0;
  152. int64_t cur_pts_v=0,cur_pts_a=0;
  153. //FIX
  154. #if USE_H264BSF
  155. AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
  156. #endif
  157. #if USE_AACBSF
  158. AVBitStreamFilterContext* aacbsfc = av_bitstream_filter_init("aac_adtstoasc");
  159. #endif
  160. while (1) {
  161. AVFormatContext *ifmt_ctx;
  162. int stream_index=0;
  163. AVStream *in_stream, *out_stream;
  164. // Obtain an AVPacket (Get an AVPacket)
  165. if(av_compare_ts(cur_pts_v,ifmt_ctx_v->streams[videoindex_v]->time_base,cur_pts_a,ifmt_ctx_a->streams[audioindex_a]->time_base) <= 0){
  166. ifmt_ctx=ifmt_ctx_v;
  167. stream_index=videoindex_out;
  168. if(av_read_frame(ifmt_ctx, &pkt) >= 0){
  169. do{
  170. if(pkt.stream_index==videoindex_v){
  171. cur_pts_v=pkt.pts;
  172. break;
  173. }
  174. }while(av_read_frame(ifmt_ctx, &pkt) >= 0);
  175. }else{
  176. break;
  177. }
  178. }else{
  179. ifmt_ctx=ifmt_ctx_a;
  180. stream_index=audioindex_out;
  181. if(av_read_frame(ifmt_ctx, &pkt) >= 0){
  182. do{
  183. if(pkt.stream_index==audioindex_a){
  184. cur_pts_a=pkt.pts;
  185. break;
  186. }
  187. }while(av_read_frame(ifmt_ctx, &pkt) >= 0);
  188. }else{
  189. break;
  190. }
  191. }
  192. in_stream = ifmt_ctx->streams[pkt.stream_index];
  193. out_stream = ofmt_ctx->streams[stream_index];
  194. //FIX
  195. #if USE_H264BSF
  196. av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
  197. #endif
  198. #if USE_AACBSF
  199. av_bitstream_filter_filter(aacbsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
  200. #endif
  201. //FIX:No PTS (Example: Raw H.264)
  202. //Simple Write PTS
  203. if(pkt.pts==AV_NOPTS_VALUE){
  204. //Write PTS
  205. AVRational time_base1=in_stream->time_base;
  206. //Duration between 2 frames (us)
  207. int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(in_stream->r_frame_rate);
  208. //Parameters
  209. pkt.pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);
  210. pkt.dts=pkt.pts;
  211. pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
  212. frame_index++;
  213. }
  214. /* copy packet */
  215. // Convert PTS/DTS (Convert PTS/DTS)
  216. pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
  217. pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
  218. pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
  219. pkt.pos = -1;
  220. pkt.stream_index=stream_index;
  221. printf("Write 1 Packet. size:%5d\tpts:%8d\n",pkt.size,pkt.pts);
  222. // Write)
  223. if (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {
  224. printf( "Error muxing packet\n");
  225. break;
  226. }
  227. av_free_packet(&pkt);
  228. }
  229. // Write file trailer)
  230. av_write_trailer(ofmt_ctx);
  231. #if USE_H264BSF
  232. av_bitstream_filter_close(h264bsfc);
  233. #endif
  234. #if USE_AACBSF
  235. av_bitstream_filter_close(aacbsfc);
  236. #endif
  237. end:
  238. avformat_close_input(&ifmt_ctx_v);
  239. avformat_close_input(&ifmt_ctx_a);
  240. /* close output */
  241. if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
  242. avio_close(ofmt_ctx->pb);
  243. avformat_free_context(ofmt_ctx);
  244. if (ret < 0 && ret != AVERROR_EOF) {
  245. printf( "Error occurred.\n");
  246. return -1;
  247. }
  248. return 0;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.