基于ffmpeg的音频转码

首先引入音频帧的概念:

 

正常人听觉的频率范围大约在20Hz~20kHz之间。

 

采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。

根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。

常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,

如果采用更高的采样频率,还可以达到DVD的音质。

 

对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。

通常是按1024个采样点一帧

 

分析:

1. AAC

一个AAC原始帧包含某段时间内1024个采样点相关数据。

用1024主要是因为AAC是用的1024点的mdct。

 

音频帧的播放时间 = 一个AAC帧对应的采样样本的个数 / 采样频率(单位为s)。

 

采样率(samplerate)为 44100Hz,表示每秒 44100个采样点, 

所以,根据公式,   

音频帧的播放时长 = 一个AAC帧对应的采样点个数 / 采样频率

则,当前一帧的播放时间 = 1024 * 1000000/44100= 23.22ms(单位为ms)

 

48kHz采样率,

则,当前一帧的播放时间 = 1024 * 1000000/48000= 21.32ms(单位为ms)

 

22.05kHz采样率,

则,当前一帧的播放时间 = 1024 * 1000000/22050= 46.44ms(单位为ms)

 

2.MP3 

mp3 每帧均为1152个字节, 

则:

每帧播放时长 = 1152 * 1000000 / sample_rate

例如:sample_rate = 44100HZ时, 

计算出的时长为26.122ms,

这就是经常听到的mp3每帧播放时间固定为26ms的由来。
 

 

ffmpeg音频转码:

由于不同格式音频帧数的不同,在使用ffmpeg作音频转码时需要作音频fifo来缓存解码数据,依据编码音频帧需要给对应的大小。

音频fifo可使用ffmpeg中已写好的fifo,定义在libavutil/audio_fifo.h下。

 

AVAudioFifo,SwrContext定义及初始化:

 

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片

  1.     AVAudioFifo *af = NULL;  
  2.     SwrContext *resample_context = NULL;  
  3.     long long pts = 0;  
  4.     for(int i=0; i<1; i++){  
  5.         printf(" samplerate input = %d , samplerate output = %d\n",pAudioCodecCtx[i]->sample_rate, AudioEncodeCtx[i]->sample_rate);  
  6.         resample_context = swr_alloc_set_opts(NULL, av_get_default_channel_layout(AudioEncodeCtx[i]->channels),  
  7.                                                           AudioEncodeCtx[i]->sample_fmt,  
  8.                                                           AudioEncodeCtx[i]->sample_rate,  
  9.                                                           av_get_default_channel_layout(pAudioCodecCtx[i]->channels),  
  10.                                                           pAudioCodecCtx[i]->sample_fmt,  
  11.                                                           pAudioCodecCtx[i]->sample_rate,  
  12.                                                           0, NULL);  
  13.         swr_init(resample_context);  
  14.     }  
  15.     af = av_audio_fifo_alloc(AudioEncodeCtx[0]->sample_fmt, AudioEncodeCtx[0]->channels, 1);  
  16.     if(af == NULL)  
  17.     {  
  18.         printf("error af \n");  
  19.         return -1;  
  20.     }  


转码过程:

 

 

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片

  1. if (avcodec_decode_audio4(pAudioCodecCtx[i], pAudioframe[i], &frame_size, &pkt) >= 0) {  
  2.                         if (i == 0){  
  3.                             uint8_t *converted_input_samples = NULL;  
  4.                             converted_input_samples = (uint8_t *)calloc(AudioEncodeCtx[i]->channels, sizeof(*converted_input_samples));  
  5.                             av_samples_alloc(&converted_input_samples, NULL, AudioEncodeCtx[i]->channels, pAudioframe[i]->nb_samples, AudioEncodeCtx[i]->sample_fmt, 0);  
  6.                             int error = 0;  
  7.                             if((error = swr_convert(resample_context, &converted_input_samples, pAudioframe[i]->nb_samples,  
  8.                                                    (const uint8_t**)pAudioframe[i]->extended_data, pAudioframe[i]->nb_samples))<0){  
  9.                                 printf("error  : %d\n",error);  
  10.                             }  
  11.                             av_audio_fifo_write(af, (void **)&converted_input_samples, pAudioframe[i]->nb_samples);  
  12.   
  13.                             int got_frame=0;  
  14.                             //Encode  
  15.                             while(av_audio_fifo_size(af) >= AudioEncodeCtx[i]->frame_size){  
  16.                                 int frame_size = FFMIN(av_audio_fifo_size(af),AudioEncodeCtx[i]->frame_size);  
  17.                                 pOutAudioframe[i]->nb_samples =  frame_size;  
  18.                                 pOutAudioframe[i]->channel_layout = AudioEncodeCtx[i]->channel_layout;  
  19.                                 pOutAudioframe[i]->sample_rate = AudioEncodeCtx[i]->sample_rate;  
  20.                                 pOutAudioframe[i]->format = AudioEncodeCtx[i]->sample_fmt;  
  21.   
  22.                                 av_frame_get_buffer(pOutAudioframe[i], 0);  
  23.                                 av_audio_fifo_read(af, (void **)&pOutAudioframe[i]->data, frame_size);  
  24.   
  25.                                 pOutAudioframe[i]->pts=pts;  
  26.                                 pts += pOutAudioframe[i]->nb_samples;  
  27.   
  28.                                 audio_pkt.data = NULL;  
  29.                                 audio_pkt.size = 0;  
  30.                                 av_init_packet(&audio_pkt);  
  31.                                 avcodec_encode_audio2(AudioEncodeCtx[i], &audio_pkt, pOutAudioframe[i], &got_frame);  
  32.                             }  
  33.                         }  
  34.                         break;  
  35.                     }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值