ffmpeg音频转码,采用swr_convert重取样

来源:互联网 发布:windows 10菜单栏隐藏 编辑:程序博客网 时间:2024/05/17 12:24

1、概述:

和上一篇音频转码流程一样,只是把filter重取样改为了swr_convert重取样,理解本例子对AVFrame中data如何存储音频数据有更好的理解。

2、代码:

[cpp] view plain copy
  1. /* 
  2. *最简单的音频转码器(只处理音频) 
  3. *缪国凯 Mickel 
  4. *821486004@qq.com 
  5. *本程序实现从一个视频格式转码到另一个视频格式,只处理音频,视频忽略,若有多个音频流,只处理第一个,采用swr_convert重取样 
  6. *2015-5-8 
  7. */  
  8.   
  9.   
  10. #include "stdafx.h"  
  11.   
  12. #ifdef __cplusplus  
  13. extern"C"  
  14. {  
  15. #endif  
  16. #include <libavformat/avformat.h>  
  17. #include "libavcodec/avcodec.h"  
  18. #include "libavfilter/avfiltergraph.h"  
  19. #include "libavfilter/buffersink.h"  
  20. #include "libavfilter/buffersrc.h"  
  21. #include "libavutil/avutil.h"  
  22. #include "libavutil/opt.h"  
  23. #include "libavutil/pixdesc.h"  
  24. #include "libswresample\swresample.h"  
  25. #include "libavutil\fifo.h"  
  26.   
  27.   
  28. #pragma comment(lib, "avcodec.lib")  
  29. #pragma comment(lib, "avformat.lib")  
  30. #pragma comment(lib, "avutil.lib")  
  31. //#pragma comment(lib, "avdevice.lib")  
  32. #pragma comment(lib, "avfilter.lib")  
  33. //#pragma comment(lib, "postproc.lib")  
  34. #pragma comment(lib, "swresample.lib")  
  35. //#pragma comment(lib, "swscale.lib")  
  36. #ifdef __cplusplus  
  37. };  
  38. #endif  
  39.   
  40. #define BUF_SIZE_20K 2048000  
  41. #define BUF_SIZE_1K 1024000  
  42.   
  43. SwrContext* pSwrCtx = NULL;  
  44. AVStream *out_stream = NULL;  
  45. AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;  
  46. int audio_index = -1;  
  47.   
  48. void initSwr()  
  49. {  
  50.     if (out_fmt_ctx->streams[0]->codec->channels != in_fmt_ctx->streams[audio_index]->codec->channels  
  51.         || out_fmt_ctx->streams[0]->codec->sample_rate != in_fmt_ctx->streams[audio_index]->codec->sample_rate  
  52.         || out_fmt_ctx->streams[0]->codec->sample_fmt != in_fmt_ctx->streams[audio_index]->codec->sample_fmt)  
  53.     {  
  54.         if ( NULL == pSwrCtx )   
  55.         {  
  56.             pSwrCtx = swr_alloc();  
  57.         }  
  58. #if LIBSWRESAMPLE_VERSION_MINOR >= 17    // 根据版本不同,选用适当函数  
  59.         av_opt_set_int(pSwrCtx, "ich", in_fmt_ctx->streams[audio_index]->codec->channels, 0);  
  60.         av_opt_set_int(pSwrCtx, "och", out_fmt_ctx->streams[0]->codec->channels, 0);  
  61.         av_opt_set_int(pSwrCtx, "in_sample_rate",  in_fmt_ctx->streams[audio_index]->codec->sample_rate, 0);  
  62.         av_opt_set_int(pSwrCtx, "out_sample_rate",  out_fmt_ctx->streams[0]->codec->sample_rate, 0);  
  63.         av_opt_set_sample_fmt(pSwrCtx, "in_sample_fmt", in_fmt_ctx->streams[audio_index]->codec->sample_fmt, 0);  
  64.         av_opt_set_sample_fmt(pSwrCtx, "out_sample_fmt", out_fmt_ctx->streams[0]->codec->sample_fmt, 0);  
  65.   
  66. #else  
  67.         pSwrCtx = swr_alloc_set_opts(pSwrCtx,  
  68.             in_fmt_ctx->streams[audio_index]->codec->channel_layout,   
  69.             AV_SAMPLE_FMT_S16,   
  70.             in_fmt_ctx->streams[audio_index]->codec->sample_rate,  
  71.             in_fmt_ctx->streams[audio_index]->codec->channel_layout,   
  72.             in_fmt_ctx->streams[audio_index]->codec->sample_fmt,   
  73.             in_fmt_ctx->streams[audio_index]->codec->sample_rate,  
  74.             0, NULL);  
  75. #endif  
  76.         swr_init(pSwrCtx);  
  77.     }  
  78. }  
  79.   
  80. //setup_array函数摘自ffmpeg例程  
  81. static void setup_array(uint8_t* out[SWR_CH_MAX], AVFrame* in_frame, int format, int samples)  
  82. {  
  83.     if (av_sample_fmt_is_planar((AVSampleFormat)format))   
  84.     {  
  85.         int i;  
  86.         int plane_size = av_get_bytes_per_sample((AVSampleFormat)(format & 0xFF)) * samples;  
  87.         format &= 0xFF;  
  88.         //从decoder出来的frame中的data数据不是连续分布的,所以不能这样写:in_frame->data[0]+i*plane_size;  
  89.         for (i = 0; i < in_frame->channels; i++)   
  90.         {  
  91.             out[i] = in_frame->data[i];  
  92.         }  
  93.     }   
  94.     else   
  95.     {  
  96.         out[0] = in_frame->data[0];  
  97.     }  
  98. }  
  99.   
  100. int TransSample(AVFrame *in_frame, AVFrame *out_frame)  
  101. {  
  102.     int ret;  
  103.       
  104.       
  105.     int max_dst_nb_samples = 4096;  
  106.     //int64_t dst_nb_samples;  
  107.     int64_t src_nb_samples = in_frame->nb_samples;  
  108.     out_frame->pts = in_frame->pts;  
  109.     uint8_t* paudiobuf;  
  110.     int decode_size, input_size, len;  
  111.     if (pSwrCtx != NULL)   
  112.     {  
  113.         out_frame->nb_samples = av_rescale_rnd(swr_get_delay(pSwrCtx, out_fmt_ctx->streams[0]->codec->sample_rate) + src_nb_samples,  
  114.             out_fmt_ctx->streams[0]->codec->sample_rate, out_fmt_ctx->streams[0]->codec->sample_rate, AV_ROUND_UP);  
  115.           
  116.         ret = av_samples_alloc(out_frame->data, &out_frame->linesize[0],   
  117.             out_fmt_ctx->streams[0]->codec->channels, out_frame->nb_samples, out_fmt_ctx->streams[0]->codec->sample_fmt, 0);  
  118.         if (ret < 0)  
  119.         {  
  120.             av_log(NULL, AV_LOG_WARNING, "[%s.%d %s() Could not allocate samples Buffer\n", __FILE__, __LINE__, __FUNCTION__);  
  121.             return -1;  
  122.         }  
  123.         max_dst_nb_samples = out_frame->nb_samples;  
  124.   
  125.         //输入也可能是分平面的,所以要做如下处理  
  126.         uint8_t* m_ain[SWR_CH_MAX];  
  127.         setup_array(m_ain, in_frame, in_fmt_ctx->streams[audio_index]->codec->sample_fmt, src_nb_samples);  
  128.   
  129.         //注意这里,out_count和in_count是samples单位,不是byte  
  130.         //所以这样av_get_bytes_per_sample(in_fmt_ctx->streams[audio_index]->codec->sample_fmt) * src_nb_samples是错的  
  131.         len = swr_convert(pSwrCtx, out_frame->data, out_frame->nb_samples,   
  132.             (const uint8_t**)m_ain, src_nb_samples);  
  133.   
  134.         if (len < 0)   
  135.         {  
  136.             char errmsg[BUF_SIZE_1K];  
  137.             av_strerror(len, errmsg, sizeof(errmsg));  
  138.             av_log(NULL, AV_LOG_WARNING, "[%s:%d] swr_convert!(%d)(%s)", __FILE__, __LINE__, len, errmsg);  
  139.             return -1;  
  140.         }  
  141.     }  
  142.     else  
  143.     {  
  144.         printf("pSwrCtx with out init!\n");  
  145.         return -1;  
  146.     }  
  147.     return 0;  
  148. }  
  149.   
  150. int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)  
  151. {  
  152.     int ret;  
  153.     int got_frame;  
  154.     AVPacket enc_pkt;  
  155.     if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &  
  156.         CODEC_CAP_DELAY))  
  157.     {  
  158.         return 0;  
  159.     }  
  160.     int i = 0;  
  161.     while(1)  
  162.     {  
  163.         enc_pkt.data = NULL;  
  164.         enc_pkt.size = 0;  
  165.         av_init_packet(&enc_pkt);  
  166.         ret = avcodec_encode_audio2(out_fmt_ctx->streams[stream_index]->codec, &enc_pkt,  
  167.             NULL, &got_frame);  
  168.           
  169.         if (ret < 0)  
  170.             break;  
  171.         if (!got_frame)  
  172.             break;  
  173.         /* prepare packet for muxing */  
  174.         enc_pkt.stream_index = stream_index;  
  175.         enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  
  176.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  177.             out_fmt_ctx->streams[stream_index]->time_base,  
  178.             (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  179.         enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  
  180.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  181.             out_fmt_ctx->streams[stream_index]->time_base,  
  182.             (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  183.         enc_pkt.duration = av_rescale_q(enc_pkt.duration,  
  184.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  185.             out_fmt_ctx->streams[stream_index]->time_base);  
  186.   
  187.         /* mux encoded frame */  
  188.         ret = av_interleaved_write_frame(out_fmt_ctx, &enc_pkt);  
  189.         av_free_packet(&enc_pkt);  
  190.         if (ret < 0)  
  191.         {  
  192.             break;  
  193.         }  
  194.         i++;  
  195.     }  
  196.     printf("flusher write %d frame", i);  
  197.     return ret;  
  198. }  
  199.   
  200. int _tmain(int argc, _TCHAR* argv[])  
  201. {  
  202.     AVFrame *frame, *frame_out;  
  203.     AVPacket pkt_in, pkt_out;  
  204.       
  205.     int ret;  
  206.   
  207.     if (argc < 3)  
  208.     {  
  209.         printf("error in input param");  
  210.         getchar();  
  211.         return -1;  
  212.     }  
  213.   
  214.     av_register_all();  
  215.     avfilter_register_all();  
  216.     //input  
  217.     if (avformat_open_input(&in_fmt_ctx, argv[1], NULL, NULL) < 0)  
  218.     {  
  219.         printf("can not open input file context");  
  220.         goto end;  
  221.     }  
  222.     if (avformat_find_stream_info(in_fmt_ctx, NULL) < 0)  
  223.     {  
  224.         printf("can not find input stream info!\n");  
  225.         goto end;  
  226.     }  
  227.   
  228.     //output  
  229.     avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL, argv[2]);  
  230.     if (!out_fmt_ctx)  
  231.     {  
  232.         printf("can not alloc output context!\n");  
  233.         goto end;  
  234.     }  
  235.     //open decoder & new out stream & open encoder  
  236.     for (int i = 0; i < in_fmt_ctx->nb_streams; i++)  
  237.     {  
  238.         if (in_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)  
  239.         {  
  240.             //open decoder  
  241.             if(0 > avcodec_open2(in_fmt_ctx->streams[i]->codec, avcodec_find_decoder(in_fmt_ctx->streams[i]->codec->codec_id), NULL))  
  242.             {  
  243.                 printf("can not find or open decoder!\n");  
  244.                 goto end;  
  245.             }  
  246.   
  247.             audio_index = i;  
  248.   
  249.             //new stream  
  250.             out_stream = avformat_new_stream(out_fmt_ctx, NULL);  
  251.             if (!out_stream)  
  252.             {  
  253.                 printf("can not new stream for output!\n");  
  254.                 goto end;  
  255.             }  
  256.   
  257.             //set codec context param             
  258.             //use default audio encoder  
  259.             out_stream->codec->codec = avcodec_find_encoder(out_fmt_ctx->oformat->audio_codec);  
  260.             //use the input audio encoder  
  261.             //out_stream->codec->codec = avcodec_find_encoder(ifmt_ctx->streams[i]->codec->codec_id);  
  262.   
  263.             out_stream->codec->sample_rate = in_fmt_ctx->streams[i]->codec->sample_rate;  
  264.             out_stream->codec->channel_layout = in_fmt_ctx->streams[i]->codec->channel_layout;  
  265.             out_stream->codec->channels = av_get_channel_layout_nb_channels(out_stream->codec->channel_layout);  
  266.             // take first format from list of supported formats  
  267.             out_stream->codec->sample_fmt = out_stream->codec->codec->sample_fmts[0];  
  268.             AVRational time_base={1, out_stream->codec->sample_rate};  
  269.             out_stream->codec->time_base = time_base;  
  270.   
  271.             //open encoder  
  272.             if (!out_stream->codec->codec)  
  273.             {  
  274.                 printf("can not find the encoder!\n");  
  275.                 goto end;  
  276.             }  
  277.             if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0)  
  278.             {  
  279.                 printf("can not open the encoder\n");  
  280.                 goto end;  
  281.             }  
  282.   
  283.             if (out_fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
  284.                 out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  285.   
  286.             break;  
  287.         }  
  288.     }  
  289.   
  290.     //dump input info  
  291.     av_dump_format(in_fmt_ctx, 0, argv[1], 0);  
  292.     //dump output info  
  293.     av_dump_format(out_fmt_ctx, 0, argv[2], 1);  
  294.   
  295.     if (-1 == audio_index)  
  296.     {  
  297.         printf("found no audio stream in input file!\n");  
  298.         goto end;  
  299.     }  
  300.   
  301.     if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  302.     {  
  303.         if(avio_open(&out_fmt_ctx->pb, argv[2], AVIO_FLAG_WRITE) < 0)  
  304.         {  
  305.             printf("can not open output file handle!\n");  
  306.             goto end;  
  307.         }  
  308.     }  
  309.   
  310.     if(avformat_write_header(out_fmt_ctx, NULL) < 0)  
  311.     {  
  312.         printf("can not write the header of the output file!\n");  
  313.         goto end;  
  314.     }  
  315.       
  316.     //  
  317.     initSwr();  
  318.       
  319.     int got_frame, got_picture;  
  320.     int frame_index = 0;  
  321.     int i = 0;  
  322.     for(int i = 0; ;i++)  
  323.     {         
  324.         pkt_in.data = NULL;  
  325.         pkt_in.size = 0;  
  326.   
  327.         got_frame = -1;  
  328.         got_picture = -1;  
  329.           
  330.         if (av_read_frame(in_fmt_ctx, &pkt_in) < 0)  
  331.         {  
  332.             break;  
  333.         }  
  334.         if (pkt_in.stream_index != audio_index)  
  335.         {  
  336.             continue;  
  337.         }  
  338.         frame = av_frame_alloc();  
  339.         if ((ret = avcodec_decode_audio4(in_fmt_ctx->streams[audio_index]->codec, frame, &got_frame, &pkt_in)) < 0)  
  340.         {  
  341.             av_frame_free(&frame);  
  342.             printf("can not decoder a frame");  
  343.             break;  
  344.         }  
  345.         av_free_packet(&pkt_in);  
  346.   
  347.         if (got_frame)  
  348.         {  
  349.             frame->pts = av_frame_get_best_effort_timestamp(frame);  
  350.   
  351.             frame_out = av_frame_alloc();  
  352.   
  353.             if (0 != TransSample(frame, frame_out))  
  354.             {  
  355.                 printf("can not swr the audio data!\n");  
  356.                 break;  
  357.             }  
  358.               
  359.             av_init_packet(&pkt_out);  
  360.             int ret = avcodec_encode_audio2(out_fmt_ctx->streams[0]->codec, &pkt_out, frame_out, &got_picture);  
  361.             av_free(frame_out->data[0]);  
  362.             av_frame_free(&frame_out);  
  363.             if (got_picture )   
  364.             {  
  365.                 pkt_out.stream_index = out_stream->index;  
  366.                 pkt_out.dts = av_rescale_q_rnd(pkt_out.dts,  
  367.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  368.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  369.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  370.   
  371.                 pkt_out.pts = av_rescale_q_rnd(pkt_out.pts,  
  372.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  373.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  374.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  375.   
  376.                 pkt_out.duration = av_rescale_q(pkt_out.duration,  
  377.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  378.                     out_fmt_ctx->streams[out_stream->index]->time_base);  
  379.   
  380.                 av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
  381.                 /* mux encoded frame */  
  382.                 ret = av_interleaved_write_frame(out_fmt_ctx, &pkt_out);  
  383.                 av_free_packet(&pkt_out);  
  384.                 if (ret < 0)  
  385.                 {  
  386.                     printf("write a frame failed!\n");  
  387.                     break;  
  388.                 }  
  389.                 printf("success write a frame:index %d\n", frame_index++);  
  390.             }  
  391.   
  392.         }  
  393.     }  
  394.     ret = flush_encoder(out_fmt_ctx, out_stream->index);  
  395.   
  396.     if (ret < 0)  
  397.     {  
  398.         printf("Flushing encoder failed");  
  399.         return -1;  
  400.     }  
  401.   
  402.     //write file trailer  
  403.     av_write_trailer(out_fmt_ctx);  
  404.   
  405.     //clean  
  406.     avcodec_close(out_stream->codec);  
  407.     avcodec_close(in_fmt_ctx->streams[audio_index]->codec);  
  408.   
  409. end:  
  410.     avformat_close_input(&in_fmt_ctx);  
  411.   
  412.     if (out_fmt_ctx && !(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  413.     {  
  414.         avio_close(out_fmt_ctx->pb);  
  415.     }  
  416.     avformat_free_context(out_fmt_ctx);  
  417.     getchar();  
  418.     return 0;  
  419. }  


3、工程下载地址:

http://download.csdn.net/detail/dancing_night/8685669

目录(?)[+]

1、概述:

和上一篇音频转码流程一样,只是把filter重取样改为了swr_convert重取样,理解本例子对AVFrame中data如何存储音频数据有更好的理解。

2、代码:

[cpp] view plain copy
  1. /* 
  2. *最简单的音频转码器(只处理音频) 
  3. *缪国凯 Mickel 
  4. *821486004@qq.com 
  5. *本程序实现从一个视频格式转码到另一个视频格式,只处理音频,视频忽略,若有多个音频流,只处理第一个,采用swr_convert重取样 
  6. *2015-5-8 
  7. */  
  8.   
  9.   
  10. #include "stdafx.h"  
  11.   
  12. #ifdef __cplusplus  
  13. extern"C"  
  14. {  
  15. #endif  
  16. #include <libavformat/avformat.h>  
  17. #include "libavcodec/avcodec.h"  
  18. #include "libavfilter/avfiltergraph.h"  
  19. #include "libavfilter/buffersink.h"  
  20. #include "libavfilter/buffersrc.h"  
  21. #include "libavutil/avutil.h"  
  22. #include "libavutil/opt.h"  
  23. #include "libavutil/pixdesc.h"  
  24. #include "libswresample\swresample.h"  
  25. #include "libavutil\fifo.h"  
  26.   
  27.   
  28. #pragma comment(lib, "avcodec.lib")  
  29. #pragma comment(lib, "avformat.lib")  
  30. #pragma comment(lib, "avutil.lib")  
  31. //#pragma comment(lib, "avdevice.lib")  
  32. #pragma comment(lib, "avfilter.lib")  
  33. //#pragma comment(lib, "postproc.lib")  
  34. #pragma comment(lib, "swresample.lib")  
  35. //#pragma comment(lib, "swscale.lib")  
  36. #ifdef __cplusplus  
  37. };  
  38. #endif  
  39.   
  40. #define BUF_SIZE_20K 2048000  
  41. #define BUF_SIZE_1K 1024000  
  42.   
  43. SwrContext* pSwrCtx = NULL;  
  44. AVStream *out_stream = NULL;  
  45. AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;  
  46. int audio_index = -1;  
  47.   
  48. void initSwr()  
  49. {  
  50.     if (out_fmt_ctx->streams[0]->codec->channels != in_fmt_ctx->streams[audio_index]->codec->channels  
  51.         || out_fmt_ctx->streams[0]->codec->sample_rate != in_fmt_ctx->streams[audio_index]->codec->sample_rate  
  52.         || out_fmt_ctx->streams[0]->codec->sample_fmt != in_fmt_ctx->streams[audio_index]->codec->sample_fmt)  
  53.     {  
  54.         if ( NULL == pSwrCtx )   
  55.         {  
  56.             pSwrCtx = swr_alloc();  
  57.         }  
  58. #if LIBSWRESAMPLE_VERSION_MINOR >= 17    // 根据版本不同,选用适当函数  
  59.         av_opt_set_int(pSwrCtx, "ich", in_fmt_ctx->streams[audio_index]->codec->channels, 0);  
  60.         av_opt_set_int(pSwrCtx, "och", out_fmt_ctx->streams[0]->codec->channels, 0);  
  61.         av_opt_set_int(pSwrCtx, "in_sample_rate",  in_fmt_ctx->streams[audio_index]->codec->sample_rate, 0);  
  62.         av_opt_set_int(pSwrCtx, "out_sample_rate",  out_fmt_ctx->streams[0]->codec->sample_rate, 0);  
  63.         av_opt_set_sample_fmt(pSwrCtx, "in_sample_fmt", in_fmt_ctx->streams[audio_index]->codec->sample_fmt, 0);  
  64.         av_opt_set_sample_fmt(pSwrCtx, "out_sample_fmt", out_fmt_ctx->streams[0]->codec->sample_fmt, 0);  
  65.   
  66. #else  
  67.         pSwrCtx = swr_alloc_set_opts(pSwrCtx,  
  68.             in_fmt_ctx->streams[audio_index]->codec->channel_layout,   
  69.             AV_SAMPLE_FMT_S16,   
  70.             in_fmt_ctx->streams[audio_index]->codec->sample_rate,  
  71.             in_fmt_ctx->streams[audio_index]->codec->channel_layout,   
  72.             in_fmt_ctx->streams[audio_index]->codec->sample_fmt,   
  73.             in_fmt_ctx->streams[audio_index]->codec->sample_rate,  
  74.             0, NULL);  
  75. #endif  
  76.         swr_init(pSwrCtx);  
  77.     }  
  78. }  
  79.   
  80. //setup_array函数摘自ffmpeg例程  
  81. static void setup_array(uint8_t* out[SWR_CH_MAX], AVFrame* in_frame, int format, int samples)  
  82. {  
  83.     if (av_sample_fmt_is_planar((AVSampleFormat)format))   
  84.     {  
  85.         int i;  
  86.         int plane_size = av_get_bytes_per_sample((AVSampleFormat)(format & 0xFF)) * samples;  
  87.         format &= 0xFF;  
  88.         //从decoder出来的frame中的data数据不是连续分布的,所以不能这样写:in_frame->data[0]+i*plane_size;  
  89.         for (i = 0; i < in_frame->channels; i++)   
  90.         {  
  91.             out[i] = in_frame->data[i];  
  92.         }  
  93.     }   
  94.     else   
  95.     {  
  96.         out[0] = in_frame->data[0];  
  97.     }  
  98. }  
  99.   
  100. int TransSample(AVFrame *in_frame, AVFrame *out_frame)  
  101. {  
  102.     int ret;  
  103.       
  104.       
  105.     int max_dst_nb_samples = 4096;  
  106.     //int64_t dst_nb_samples;  
  107.     int64_t src_nb_samples = in_frame->nb_samples;  
  108.     out_frame->pts = in_frame->pts;  
  109.     uint8_t* paudiobuf;  
  110.     int decode_size, input_size, len;  
  111.     if (pSwrCtx != NULL)   
  112.     {  
  113.         out_frame->nb_samples = av_rescale_rnd(swr_get_delay(pSwrCtx, out_fmt_ctx->streams[0]->codec->sample_rate) + src_nb_samples,  
  114.             out_fmt_ctx->streams[0]->codec->sample_rate, out_fmt_ctx->streams[0]->codec->sample_rate, AV_ROUND_UP);  
  115.           
  116.         ret = av_samples_alloc(out_frame->data, &out_frame->linesize[0],   
  117.             out_fmt_ctx->streams[0]->codec->channels, out_frame->nb_samples, out_fmt_ctx->streams[0]->codec->sample_fmt, 0);  
  118.         if (ret < 0)  
  119.         {  
  120.             av_log(NULL, AV_LOG_WARNING, "[%s.%d %s() Could not allocate samples Buffer\n", __FILE__, __LINE__, __FUNCTION__);  
  121.             return -1;  
  122.         }  
  123.         max_dst_nb_samples = out_frame->nb_samples;  
  124.   
  125.         //输入也可能是分平面的,所以要做如下处理  
  126.         uint8_t* m_ain[SWR_CH_MAX];  
  127.         setup_array(m_ain, in_frame, in_fmt_ctx->streams[audio_index]->codec->sample_fmt, src_nb_samples);  
  128.   
  129.         //注意这里,out_count和in_count是samples单位,不是byte  
  130.         //所以这样av_get_bytes_per_sample(in_fmt_ctx->streams[audio_index]->codec->sample_fmt) * src_nb_samples是错的  
  131.         len = swr_convert(pSwrCtx, out_frame->data, out_frame->nb_samples,   
  132.             (const uint8_t**)m_ain, src_nb_samples);  
  133.   
  134.         if (len < 0)   
  135.         {  
  136.             char errmsg[BUF_SIZE_1K];  
  137.             av_strerror(len, errmsg, sizeof(errmsg));  
  138.             av_log(NULL, AV_LOG_WARNING, "[%s:%d] swr_convert!(%d)(%s)", __FILE__, __LINE__, len, errmsg);  
  139.             return -1;  
  140.         }  
  141.     }  
  142.     else  
  143.     {  
  144.         printf("pSwrCtx with out init!\n");  
  145.         return -1;  
  146.     }  
  147.     return 0;  
  148. }  
  149.   
  150. int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)  
  151. {  
  152.     int ret;  
  153.     int got_frame;  
  154.     AVPacket enc_pkt;  
  155.     if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &  
  156.         CODEC_CAP_DELAY))  
  157.     {  
  158.         return 0;  
  159.     }  
  160.     int i = 0;  
  161.     while(1)  
  162.     {  
  163.         enc_pkt.data = NULL;  
  164.         enc_pkt.size = 0;  
  165.         av_init_packet(&enc_pkt);  
  166.         ret = avcodec_encode_audio2(out_fmt_ctx->streams[stream_index]->codec, &enc_pkt,  
  167.             NULL, &got_frame);  
  168.           
  169.         if (ret < 0)  
  170.             break;  
  171.         if (!got_frame)  
  172.             break;  
  173.         /* prepare packet for muxing */  
  174.         enc_pkt.stream_index = stream_index;  
  175.         enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  
  176.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  177.             out_fmt_ctx->streams[stream_index]->time_base,  
  178.             (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  179.         enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  
  180.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  181.             out_fmt_ctx->streams[stream_index]->time_base,  
  182.             (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  183.         enc_pkt.duration = av_rescale_q(enc_pkt.duration,  
  184.             out_fmt_ctx->streams[stream_index]->codec->time_base,  
  185.             out_fmt_ctx->streams[stream_index]->time_base);  
  186.   
  187.         /* mux encoded frame */  
  188.         ret = av_interleaved_write_frame(out_fmt_ctx, &enc_pkt);  
  189.         av_free_packet(&enc_pkt);  
  190.         if (ret < 0)  
  191.         {  
  192.             break;  
  193.         }  
  194.         i++;  
  195.     }  
  196.     printf("flusher write %d frame", i);  
  197.     return ret;  
  198. }  
  199.   
  200. int _tmain(int argc, _TCHAR* argv[])  
  201. {  
  202.     AVFrame *frame, *frame_out;  
  203.     AVPacket pkt_in, pkt_out;  
  204.       
  205.     int ret;  
  206.   
  207.     if (argc < 3)  
  208.     {  
  209.         printf("error in input param");  
  210.         getchar();  
  211.         return -1;  
  212.     }  
  213.   
  214.     av_register_all();  
  215.     avfilter_register_all();  
  216.     //input  
  217.     if (avformat_open_input(&in_fmt_ctx, argv[1], NULL, NULL) < 0)  
  218.     {  
  219.         printf("can not open input file context");  
  220.         goto end;  
  221.     }  
  222.     if (avformat_find_stream_info(in_fmt_ctx, NULL) < 0)  
  223.     {  
  224.         printf("can not find input stream info!\n");  
  225.         goto end;  
  226.     }  
  227.   
  228.     //output  
  229.     avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL, argv[2]);  
  230.     if (!out_fmt_ctx)  
  231.     {  
  232.         printf("can not alloc output context!\n");  
  233.         goto end;  
  234.     }  
  235.     //open decoder & new out stream & open encoder  
  236.     for (int i = 0; i < in_fmt_ctx->nb_streams; i++)  
  237.     {  
  238.         if (in_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)  
  239.         {  
  240.             //open decoder  
  241.             if(0 > avcodec_open2(in_fmt_ctx->streams[i]->codec, avcodec_find_decoder(in_fmt_ctx->streams[i]->codec->codec_id), NULL))  
  242.             {  
  243.                 printf("can not find or open decoder!\n");  
  244.                 goto end;  
  245.             }  
  246.   
  247.             audio_index = i;  
  248.   
  249.             //new stream  
  250.             out_stream = avformat_new_stream(out_fmt_ctx, NULL);  
  251.             if (!out_stream)  
  252.             {  
  253.                 printf("can not new stream for output!\n");  
  254.                 goto end;  
  255.             }  
  256.   
  257.             //set codec context param             
  258.             //use default audio encoder  
  259.             out_stream->codec->codec = avcodec_find_encoder(out_fmt_ctx->oformat->audio_codec);  
  260.             //use the input audio encoder  
  261.             //out_stream->codec->codec = avcodec_find_encoder(ifmt_ctx->streams[i]->codec->codec_id);  
  262.   
  263.             out_stream->codec->sample_rate = in_fmt_ctx->streams[i]->codec->sample_rate;  
  264.             out_stream->codec->channel_layout = in_fmt_ctx->streams[i]->codec->channel_layout;  
  265.             out_stream->codec->channels = av_get_channel_layout_nb_channels(out_stream->codec->channel_layout);  
  266.             // take first format from list of supported formats  
  267.             out_stream->codec->sample_fmt = out_stream->codec->codec->sample_fmts[0];  
  268.             AVRational time_base={1, out_stream->codec->sample_rate};  
  269.             out_stream->codec->time_base = time_base;  
  270.   
  271.             //open encoder  
  272.             if (!out_stream->codec->codec)  
  273.             {  
  274.                 printf("can not find the encoder!\n");  
  275.                 goto end;  
  276.             }  
  277.             if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0)  
  278.             {  
  279.                 printf("can not open the encoder\n");  
  280.                 goto end;  
  281.             }  
  282.   
  283.             if (out_fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
  284.                 out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  285.   
  286.             break;  
  287.         }  
  288.     }  
  289.   
  290.     //dump input info  
  291.     av_dump_format(in_fmt_ctx, 0, argv[1], 0);  
  292.     //dump output info  
  293.     av_dump_format(out_fmt_ctx, 0, argv[2], 1);  
  294.   
  295.     if (-1 == audio_index)  
  296.     {  
  297.         printf("found no audio stream in input file!\n");  
  298.         goto end;  
  299.     }  
  300.   
  301.     if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  302.     {  
  303.         if(avio_open(&out_fmt_ctx->pb, argv[2], AVIO_FLAG_WRITE) < 0)  
  304.         {  
  305.             printf("can not open output file handle!\n");  
  306.             goto end;  
  307.         }  
  308.     }  
  309.   
  310.     if(avformat_write_header(out_fmt_ctx, NULL) < 0)  
  311.     {  
  312.         printf("can not write the header of the output file!\n");  
  313.         goto end;  
  314.     }  
  315.       
  316.     //  
  317.     initSwr();  
  318.       
  319.     int got_frame, got_picture;  
  320.     int frame_index = 0;  
  321.     int i = 0;  
  322.     for(int i = 0; ;i++)  
  323.     {         
  324.         pkt_in.data = NULL;  
  325.         pkt_in.size = 0;  
  326.   
  327.         got_frame = -1;  
  328.         got_picture = -1;  
  329.           
  330.         if (av_read_frame(in_fmt_ctx, &pkt_in) < 0)  
  331.         {  
  332.             break;  
  333.         }  
  334.         if (pkt_in.stream_index != audio_index)  
  335.         {  
  336.             continue;  
  337.         }  
  338.         frame = av_frame_alloc();  
  339.         if ((ret = avcodec_decode_audio4(in_fmt_ctx->streams[audio_index]->codec, frame, &got_frame, &pkt_in)) < 0)  
  340.         {  
  341.             av_frame_free(&frame);  
  342.             printf("can not decoder a frame");  
  343.             break;  
  344.         }  
  345.         av_free_packet(&pkt_in);  
  346.   
  347.         if (got_frame)  
  348.         {  
  349.             frame->pts = av_frame_get_best_effort_timestamp(frame);  
  350.   
  351.             frame_out = av_frame_alloc();  
  352.   
  353.             if (0 != TransSample(frame, frame_out))  
  354.             {  
  355.                 printf("can not swr the audio data!\n");  
  356.                 break;  
  357.             }  
  358.               
  359.             av_init_packet(&pkt_out);  
  360.             int ret = avcodec_encode_audio2(out_fmt_ctx->streams[0]->codec, &pkt_out, frame_out, &got_picture);  
  361.             av_free(frame_out->data[0]);  
  362.             av_frame_free(&frame_out);  
  363.             if (got_picture )   
  364.             {  
  365.                 pkt_out.stream_index = out_stream->index;  
  366.                 pkt_out.dts = av_rescale_q_rnd(pkt_out.dts,  
  367.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  368.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  369.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  370.   
  371.                 pkt_out.pts = av_rescale_q_rnd(pkt_out.pts,  
  372.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  373.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  374.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  375.   
  376.                 pkt_out.duration = av_rescale_q(pkt_out.duration,  
  377.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  378.                     out_fmt_ctx->streams[out_stream->index]->time_base);  
  379.   
  380.                 av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
  381.                 /* mux encoded frame */  
  382.                 ret = av_interleaved_write_frame(out_fmt_ctx, &pkt_out);  
  383.                 av_free_packet(&pkt_out);  
  384.                 if (ret < 0)  
  385.                 {  
  386.                     printf("write a frame failed!\n");  
  387.                     break;  
  388.                 }  
  389.                 printf("success write a frame:index %d\n", frame_index++);  
  390.             }  
  391.   
  392.         }  
  393.     }  
  394.     ret = flush_encoder(out_fmt_ctx, out_stream->index);  
  395.   
  396.     if (ret < 0)  
  397.     {  
  398.         printf("Flushing encoder failed");  
  399.         return -1;  
  400.     }  
  401.   
  402.     //write file trailer  
  403.     av_write_trailer(out_fmt_ctx);  
  404.   
  405.     //clean  
  406.     avcodec_close(out_stream->codec);  
  407.     avcodec_close(in_fmt_ctx->streams[audio_index]->codec);  
  408.   
  409. end:  
  410.     avformat_close_input(&in_fmt_ctx);  
  411.   
  412.     if (out_fmt_ctx && !(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  413.     {  
  414.         avio_close(out_fmt_ctx->pb);  
  415.     }  
  416.     avformat_free_context(out_fmt_ctx);  
  417.     getchar();  
  418.     return 0;  
  419. }  


3、工程下载地址:

http://download.csdn.net/detail/dancing_night/8685669

0 0
原创粉丝点击