FFmpeg音频重采样(复杂版)

代码框架
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值