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

1、概述:

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

2、代码:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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.             out_fmt_ctx->streams[0]->codec->channel_layout,   
  69.             out_fmt_ctx->streams[0]->codec->sample_fmt,   
  70.             out_fmt_ctx->streams[0]->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;int plane_size = av_get_bytes_per_sample((AVSampleFormat)(format & 0xFF)) * samples;format &= 0xFF;  
  86.           
  87.         //从decoder出来的frame中的data数据不是连续分布的,所以不能这样写:  
  88.         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.     int max_dst_nb_samples = 4096;  
  104.     //int64_t dst_nb_samples;  
  105.     int64_t src_nb_samples = in_frame->nb_samples;  
  106.     out_frame->pts = in_frame->pts;  
  107.     uint8_t* paudiobuf;  
  108.     int decode_size, input_size, len;  
  109.     if (pSwrCtx != NULL)   
  110.     {  
  111.         out_frame->nb_samples = av_rescale_rnd(swr_get_delay(pSwrCtx, out_fmt_ctx->streams[0]->codec->sample_rate) + src_nb_samples,  
  112.             out_fmt_ctx->streams[0]->codec->sample_rate, in_fmt_ctx->streams[audio_index]->codec->sample_rate, AV_ROUND_UP);  
  113.   
  114.         ret = av_samples_alloc(out_frame->data,   
  115.             &out_frame->linesize[0],   
  116.             out_fmt_ctx->streams[0]->codec->channels,   
  117.             out_frame->nb_samples,   
  118.             out_fmt_ctx->streams[0]->codec->sample_fmt, 0);  
  119.           
  120.         if (ret < 0)  
  121.         {  
  122.             av_log(NULL, AV_LOG_WARNING, "[%s.%d %s() Could not allocate samples Buffer\n", __FILE__, __LINE__, __FUNCTION__);  
  123.             return -1;  
  124.         }  
  125.           
  126.         max_dst_nb_samples = out_frame->nb_samples;  
  127.         //输入也可能是分平面的,所以要做如下处理  
  128.         uint8_t* m_ain[SWR_CH_MAX];  
  129.         setup_array(m_ain, in_frame, in_fmt_ctx->streams[audio_index]->codec->sample_fmt, src_nb_samples);  
  130.           
  131.         //注意这里,out_count和in_count是samples单位,不是byte  
  132.         //所以这样av_get_bytes_per_sample(in_fmt_ctx->streams[audio_index]->codec->sample_fmt) * src_nb_samples是错的  
  133.         len = swr_convert(pSwrCtx, out_frame->data, out_frame->nb_samples, (const uint8_t**)m_ain, src_nb_samples);  
  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 &CODEC_CAP_DELAY))  
  156.     {  
  157.         return 0;  
  158.     }  
  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,NULL, &got_frame);  
  167.         if (ret < 0)  
  168.             break;  
  169.           
  170.         if (!got_frame)  
  171.             break;  
  172.           
  173.         /* prepare packet for muxing */  
  174.         enc_pkt.stream_index = stream_index;  
  175.           
  176.         enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,out_fmt_ctx->streams[stream_index]->codec->time_base,  
  177.             out_fmt_ctx->streams[stream_index]->time_base,(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  178.           
  179.         enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,out_fmt_ctx->streams[stream_index]->codec->time_base,  
  180.             out_fmt_ctx->streams[stream_index]->time_base,(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  181.           
  182.         enc_pkt.duration = av_rescale_q(enc_pkt.duration,out_fmt_ctx->streams[stream_index]->codec->time_base,  
  183.             out_fmt_ctx->streams[stream_index]->time_base);  
  184.           
  185.         /* mux encoded frame */  
  186.         ret = av_interleaved_write_frame(out_fmt_ctx, &enc_pkt);  
  187.           
  188.         av_free_packet(&enc_pkt);  
  189.           
  190.         if (ret < 0)  
  191.         {  
  192.             break;  
  193.         }  
  194.         i++;  
  195.     }  
  196.       
  197.     printf("flusher write %d frame", i);  
  198.       
  199.     return ret;  
  200. }  
  201.   
  202. int _tmain(int argc, _TCHAR* argv[])  
  203. {  
  204.     AVFrame *frame, *frame_out;  
  205.     AVPacket pkt_in, pkt_out;  
  206.     int ret;  
  207.       
  208.     if (argc < 3)  
  209.     {  
  210.         printf("error in input param");  
  211.         getchar();  
  212.         return -1;  
  213.     }  
  214.       
  215.     av_register_all();  
  216.     avfilter_register_all();  
  217.       
  218.     //input  
  219.     if (avformat_open_input(&in_fmt_ctx, argv[1], NULL, NULL) < 0)  
  220.     {  
  221.         printf("can not open input file context");  
  222.         goto end;  
  223.     }  
  224.       
  225.     if (avformat_find_stream_info(in_fmt_ctx, NULL) < 0)  
  226.     {  
  227.         printf("can not find input stream info!\n");  
  228.         goto end;  
  229.     }  
  230.       
  231.     //output  
  232.     avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL, argv[2]);  
  233.     if (!out_fmt_ctx)  
  234.     {  
  235.         printf("can not alloc output context!\n");  
  236.         goto end;  
  237.     }  
  238.       
  239.     //open decoder & new out stream & open encoder  
  240.     for (int i = 0; i < in_fmt_ctx->nb_streams; i++)  
  241.     {  
  242.         if (in_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)  
  243.         {  
  244.             //open decoder  
  245.             if(0 > avcodec_open2(in_fmt_ctx->streams[i]->codec, avcodec_find_decoder(in_fmt_ctx->streams[i]->codec->codec_id), NULL))  
  246.             {  
  247.                 printf("can not find or open decoder!\n");  
  248.                 goto end;  
  249.             }  
  250.             audio_index = i;  
  251.               
  252.             //new stream  
  253.             out_stream = avformat_new_stream(out_fmt_ctx, NULL);  
  254.             if (!out_stream)  
  255.             {  
  256.                 printf("can not new stream for output!\n");  
  257.                 goto end;  
  258.             }  
  259.             //set codec context param  
  260.             //use default audio encoder  
  261.             out_stream->codec->codec = avcodec_find_encoder(out_fmt_ctx->oformat->audio_codec);  
  262.             //use the input audio encoder  
  263.             //  
  264.             out_stream->codec->codec = avcodec_find_encoder(in_fmt_ctx->streams[i]->codec->codec_id);  
  265.             out_stream->codec->sample_rate = in_fmt_ctx->streams[i]->codec->sample_rate;  
  266.             out_stream->codec->channel_layout = in_fmt_ctx->streams[i]->codec->channel_layout;  
  267.             out_stream->codec->channels = av_get_channel_layout_nb_channels(out_stream->codec->channel_layout);  
  268.               
  269.             // take first format from list of supported formats  
  270.             out_stream->codec->sample_fmt = out_stream->codec->codec->sample_fmts[0];  
  271.             AVRational time_base={1, out_stream->codec->sample_rate};  
  272.             out_stream->codec->time_base = time_base;  
  273.               
  274.             //open encoder  
  275.             if (!out_stream->codec->codec)  
  276.             {  
  277.                 printf("can not find the encoder!\n");  
  278.                 goto end;  
  279.             }  
  280.             if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0)  
  281.             {  
  282.                 printf("can not open the encoder\n");  
  283.                 goto end;  
  284.             }  
  285.             if (out_fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
  286.                 out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  287.             break;  
  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.     if (-1 == audio_index)  
  295.     {  
  296.         printf("found no audio stream in input file!\n");  
  297.         goto end;  
  298.     }  
  299.     if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  300.     {  
  301.         if(avio_open(&out_fmt_ctx->pb, argv[2], AVIO_FLAG_WRITE) < 0)  
  302.         {  
  303.             printf("can not open output file handle!\n");  
  304.             goto end;  
  305.         }  
  306.     }  
  307.       
  308.     if(avformat_write_header(out_fmt_ctx, NULL) < 0)  
  309.     {  
  310.         printf("can not write the header of the output file!\n");  
  311.         goto end;  
  312.     }  
  313.     //  
  314.     initSwr();  
  315.     int got_frame, got_picture;  
  316.     int frame_index = 0;  
  317.     int i = 0;  
  318.       
  319.     for(int i = 0; ;i++)  
  320.     {  
  321.         pkt_in.data = NULL;  
  322.         pkt_in.size = 0;  
  323.         got_frame = -1;  
  324.         got_picture = -1;  
  325.         if (av_read_frame(in_fmt_ctx, &pkt_in) < 0)  
  326.         {  
  327.             break;  
  328.         }  
  329.   
  330.         if (pkt_in.stream_index != audio_index)  
  331.         {  
  332.             continue;  
  333.         }  
  334.           
  335.         frame = av_frame_alloc();  
  336.           
  337.         if ((ret = avcodec_decode_audio4(in_fmt_ctx->streams[audio_index]->codec, frame, &got_frame, &pkt_in)) < 0)  
  338.         {  
  339.             av_frame_free(&frame);  
  340.             printf("can not decoder a frame");  
  341.             break;  
  342.         }  
  343.           
  344.         av_free_packet(&pkt_in);  
  345.           
  346.         if (got_frame)  
  347.         {  
  348.             frame->pts = av_frame_get_best_effort_timestamp(frame);  
  349.             frame_out = av_frame_alloc();  
  350.             if (0 != TransSample(frame, frame_out))  
  351.             {  
  352.                 printf("can not swr the audio data!\n");  
  353.                 break;  
  354.             }  
  355.               
  356.             av_init_packet(&pkt_out);  
  357.             int ret = avcodec_encode_audio2(out_fmt_ctx->streams[0]->codec, &pkt_out, frame_out, &got_picture);  
  358.               
  359.             av_free(frame_out->data[0]);  
  360.             av_frame_free(&frame_out);  
  361.               
  362.             if (got_picture )   
  363.             {  
  364.                 pkt_out.stream_index = out_stream->index;  
  365.                 pkt_out.dts = av_rescale_q_rnd(pkt_out.dts,  
  366.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  367.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  368.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  369.                 pkt_out.pts = av_rescale_q_rnd(pkt_out.pts,  
  370.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  371.                     out_fmt_ctx->streams[out_stream->index]->time_base,  
  372.                     (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
  373.                 pkt_out.duration = av_rescale_q(pkt_out.duration,  
  374.                     out_fmt_ctx->streams[out_stream->index]->codec->time_base,  
  375.                     out_fmt_ctx->streams[out_stream->index]->time_base);  
  376.                   
  377.                 av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
  378.                   
  379.                 /* mux encoded frame */  
  380.                 ret = av_interleaved_write_frame(out_fmt_ctx, &pkt_out);  
  381.                 av_free_packet(&pkt_out);  
  382.                   
  383.                 if (ret < 0)  
  384.                 {  
  385.                     printf("write a frame failed!\n");  
  386.                     break;  
  387.                 }  
  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.     if (ret < 0)  
  396.     {  
  397.         printf("Flushing encoder failed");  
  398.         return -1;  
  399.     }  
  400.       
  401.     //write file trailer      
  402.     av_write_trailer(out_fmt_ctx);  
  403.       
  404.     //clean  
  405.     avcodec_close(out_stream->codec);  
  406.     avcodec_close(in_fmt_ctx->streams[audio_index]->codec);  
  407.   
  408. end:  
  409.     avformat_close_input(&in_fmt_ctx);  
  410.     if (out_fmt_ctx && !(out_fmt_ctx->oformat->flags & AVFMT_NOFILE))  
  411.     {  
  412.         avio_close(out_fmt_ctx->pb);  
  413.     }  
  414.     avformat_free_context(out_fmt_ctx);  
  415.     getchar();  
  416.     return 0;  
  417. }  




http://blog.csdn.net/dancing_night/article/details/45642107

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值