代码框架
1 首先初始化好 重采样的源和目标三大项!
ch_layout 通道数也可以说是什么模式吧
AVSampleFormat 数据format格式 就像 是lllllrrrr 还是lrlrlrl
rate 采样频率
这里是一个二维数组 所以用耳机指针存储数据
比如planer 时候 data[0] 是一堆lrlrlrl 也只有0
交叉的时候 data[0]是llllllllll data[1]rrrrrrrrr
linsize 是缓存区长度 对齐以后的
比如src linesize 计算就是 281024 = 16384
int64_t src_ch_layout = AV_CH_LAYOUT_STEREO;
int src_rate = 48000;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL;
int src_nb_channels = 0;
uint8_t **src_data = NULL; // 二级指针
int src_linesize;
int src_nb_samples = 1024;
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
int dst_rate = 44100;
enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;
int dst_nb_channels = 0;
uint8_t **dst_data = NULL; //二级指针
int dst_linesize;
int dst_nb_samples;
int max_dst_nb_samples;
然后是定义初始化重采样需要的结构体
常用方式!
struct SwrContext *swrContext;
swrContext = swr_alloc();
// 输入参数
av_opt_set_int(swrContext, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swrContext, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swrContext, "in_sample_fmt", src_sample_fmt, 0);
//输出参数
av_opt_set_int(swrContext, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swrContext, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0);
ret = swr_init(swrContext)
得到src的通道数量 就是通过名字去查数字 和查编码器类型
通过把得到的结果传入av_samples_alloc_array_and_samples 初始化
&src_data &src_linesize 这两个参数具体和前面三大项有关 主要和前两个有关
总体 作用就是 输入源所需要的空间
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels,
src_nb_samples, src_sample_fmt, 0);
因为 不同是rate 会导致不同的播放时间戳 比如 1024除以41000和48000s不同的结果 如果sample 不改变会导致重采样后pts错误 播放时间错误 所以重采样的时候需要对 计算一下实际的输出采用sample
最后一个参数向上取整
后面同上
然后就说转码数据
首先 先不说为啥 swr_get_delay av_rescale_rnd
ret = swr_convert()这里就是转码 返回值是转码成功的结果可能缓存区里还有一部分
根据传入值计算缓冲区大小 ret 乘以dst_nb_channels乘以dst_sample_fmt
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, dst_sample_fmt, 1);
ret = swr_convert(swrContext, dst_data, dst_nb_samples, NULL, 0);
然后是冲刷缓冲区
对于 swr_get_delay av_rescale_rnd 作用就是
swr_convert(dst_nb_samples )这里的samples 小了不足以保存重采样后缓存中的数据 那就改变他的大小 要不然缓存会越来越大!
max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples,dst_rate,src_rate,AV_ROUND_UP);
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
// 分配输出缓存内存
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 0);
int64_t delay = swr_get_delay(swrContext,src_rate);
dst_nb_samples = av_rescale_rnd(delay+src_nb_samples,dst_rate,src_rate,AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples) {
av_freep(&dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 1);
if (ret < 0)
break;
max_dst_nb_samples = dst_nb_samples;
}
ret = swr_convert(swrContext, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
goto end;
}
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, dst_sample_fmt, 1);
if (dst_bufsize < 0) {
fprintf(stderr, "Could not get sample buffer size\n");
goto end;
}
printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
fwrite(dst_data[0], 1, dst_bufsize, dst_file);
} while (t<10);
完整代码 https://github.com/zycccer/aac_mp3_pcm