ffmpeg 音频转换

音频转换主要API
swr_alloc_set_opts 设置转换的参数


  /**
         如果需要,分配SwrContext并设置/重置公共参数。
          此函数不需要使用swr_alloc()分配。 另一方面,swr_alloc()可以使用swr_alloc_set_opts()在分配的上下文上设置参数。
          
         * 初始化resampler
         * @param s               现有的Swr上下文(如果可用),否则为NULL
         * @param out_ch_layout   输出通道布局(AV_CH_LAYOUT_ *)
         * @param out_sample_fmt  输出样本格式(AV_SAMPLE_FMT_ *)
         * @param out_sample_rate 输出采样率(频率,单位:Hz)
         * @param in_ch_layout    输入通道布局(AV_CH_LAYOUT_ *)
         * @param in_sample_fmt   输入样本格式(AV_SAMPLE_FMT_ *)
         * @param in_sample_rate  输入采样率(频率,Hz)
         * @param log_offset      logging level offset
         * @param log_ctx          父日志记录上下文,可以为NULL
          返回 错误时为NULL,否则分配上下文
          
         */


truct SwrContext * swr_alloc_set_opts(
    struct SwrContext *s,
    int64_t out_ch_layout, 
    enum AVSampleFormat out_sample_fmt, 
    int out_sample_rate,
     int64_t  in_ch_layout, 
    enum AVSampleFormat  in_sample_fmt,
     int  in_sample_rate,
     int log_offset, void *log_ctx);

swr_convert 在上面转换参数设置后,进行音频转换

  /**
     swr_convert 音频数据转换 (使用avcodec_decode_audio4函数来解码音频,但解码得到的数据类型为float 4bit,而播放器播放的格式一般为S16(signed 16bit),就需要对解码得到的数据进行转换)     in和in_count可以设置为0,以清除最后几个样本
如果提供的输入多于输出空间,则将缓冲输入。 您可以通过使用swr_get_out_samples()检索给定数量的输入样本的所需数量的输出样本的上限来避免这种缓冲。 转换将直接运行而无需复制。
        参数1 s: 分配的Swr上下文,并设置了参数
        参数2 out: 输出缓冲区,如果打包了音频,则仅需要设置第一个
        参数3 out_count: 每通道样本中可用于输出的空间量
        参数4 in: 输入缓冲区,在打包音频的情况下仅需要设置第一个
        参数5 in_count: 一个通道中可用的输入样本数
        返回每个通道输出的样本数,错误时为负值
 */
 int swr_convert(
        struct SwrContext *s, 
        uint8_t **out, 
        int out_count,
        const uint8_t **in ,
        int in_count);

音频转换的原则是时长不变,不管转换成何种格式,音频总时长一样

影响音频播放时长的因素是每帧的采样数和采样率。
现在有mp3 每帧1152, 采样率48000
aac 每帧1024, 采样率44100
44100的aac每帧的播放时长=1024/44100.每秒有44100/1024帧,每个aac采样的播放时长是1/44100秒
48000的mp3,每帧的播放时长=1152/48000,每秒有48000/1152帧。每个mp3采样的播放时长是1/48000秒
这里我们就能看出,不可能一个aac帧转出一个mp3帧,比例不可能1:1 。具体能转多少,需要计算。这就是上面的转换在干的事,到底在转换什么,实质就是转换一个每帧aac里面有1024个采样,看能转出多个mp3性质的采样。

把一帧aac变成一帧mp3,能从每帧aac的1024个采样身上重采样出多少个mp3帧的采样,这个值记作K,就是上面的dst_nb_samples
根据我们的音频总时长不变原则,
(44100/1024) * K * (1/48000)=1秒 (src_rate/src_nb_samples =dst_rate/K)

即1秒钟的aac总帧数每个aac帧能转换的mp3采样数 每个mp3采样的播放时长=转换出来的mp3也是1s
计算得K=1114.57

1114.57是不够一帧mp3帧的,这个数也是一个计算出来的理论值,实际采样个数肯定也不可能是一个小数,实际到底转了多少,sws_convert函数的返回值告诉你,实际编码过程中,我们也是通过累计的方式,够了1152个采样,我们才组装出一个mp3帧

swr_convert 返回的输出样本数,可以根据输入样本数计算出来

条件1: 首先需要满足: out_count(输出通道可以接收的样本空间)> in_count (输入样本数)

否则输入的数据过大,输出接收空间不足以接收所有的输入数据

满足条件1后,可计算swr_convert 返回的输出样本数。
例如
1帧数据,
采样数 pAudioFrame->nb_samples = 1024
输入采样率为 in_sample_rate = 44100
输出采样率 out_sample_rate = 44100 * 2
那么经过swr_convert转换出来的结果就近似 2048 (具体数值以swr_convert返回值为准)
也满足上面的公式

(44100/1024) * K * (1/44100 * 2)=1秒 

swr_alloc_set_opts设置的输出采样频率越高,swr_convert转换的采样数越大,才能保证时间一致

你可能感兴趣的:(ffmpeg 音频转换)