【ffmpeg】音频重采样

【ffmpeg】音频重采样

  • 前言
  • 什么是音频重采样
  • 实现音频重采样
    • 创建重采样上下文
    • 初始化重采样
    • 进行重采样
    • ffplay播放
  • 参考资料

个人简介

个人主页:一二三o-0-O的博客
技术方向:C/C++客户端资深工程师(直播+音视频剪辑)
‍作者简介:数据结构算法与音视频领域创作者
系列专栏:ffmpeg入门
专栏目标:务实的掌握FFmpeg相关专业知识
如果对您有帮助的话,欢迎点赞收藏,关注不迷路

前言

如果是刚刚开始学习音视频的伙伴,可以先看看音视频基 础专栏系列的内容,掌握音视频相关的一些基础理论

音视频基础专栏系列

(一)【音视频基础】音频基础理论
(二)【音视频基础】视频基础理论
(三)【音视频基础】封装格式与编码数据

如果觉得理论学习枯燥的伙伴,可以先通过以下四篇文章使用ffmpeg实现一个播放器,可以获得些许成就感,为持续在音视频领域扎根打好兴趣基础。

ffmpeg专栏系列

(一)【ffmpeg】ffmpeg命令工具的使用
(二)【ffmpeg】视频解码器
(三)【ffmpeg】SDL视频显示
(四)【ffmpeg】ffmpeg+SDL实现播放器

本节主要阐述音频重采样

什么是音频重采样

  • 音频重采样就是将音频三元组(采样率,采样大小和通道数)的值转换成另外一组值
    • 例如:将44100/16/2转成48000/16/2
  • 为什么要重采样?
    • 从设备采集的音频数据与编码器要求的数据不一致
    • 扬声器要求的音频数据与要播放的音频数据不一致
    • 更方便运算
  • 如何知道是否需要进行重采样
    • 要了解音频设备
    • 查看ffmpeg源码
  • 重采样的步骤
    • 创建重采样上下文
    • 设置参数
    • 初始化重采样
    • 进行重采样

实现音频重采样

本节代码在【ffmpeg】音频采集的基础上进行开发。

创建重采样上下文

使用swr_alloc_set_opts分配采样上下文

SwrContext *swrCtx = swr_alloc_set_opts(NULL,       // ctx
                                AV_CH_LAYOUT_STEREO,// 输出channel布局
                                AV_SAMPLE_FMT_FLT,  // 输出的采样格式
                                44100,              // 采样率
                                AV_CH_LAYOUT_STEREO,// 输入channel布局
                                AV_SAMPLE_FMT_S16,  // 输入的采样格式
                                44100,              // 输入的采样率
                                0,
                                NULL);

初始化重采样

1.初始化重采样缓冲区
uint8_t **src_data {};
uint8_t **dst_data {};
2.使用av_samples_alloc_array_and_samples分配缓冲区

// 创建输入缓冲区
av_samples_alloc_array_and_samples(&srcData,            // 输出缓冲区地址
                                   &srcLineSize,        // 缓冲区的大小
                                   2,                   // 通道个数
                                   22050,               // 单通道采样个数
                                   AV_SAMPLE_FMT_S16,   // 采样格式
                                   0);

进行重采样

1.将采集到的AVPacket音频包拷贝到输入缓冲区中
2.使用swr_convert进行重采样

// 进行内存拷贝
memcpy((void *)srcData[0], (void *)pkt.data, pkt.size);
// 重采样
swr_convert(swrCtx,                     // 重采样的上下文
            dstData,                    // 输出结果缓冲区
            22050,                      // 每个通道的采样数
            (const uint8_t **)srcData,  // 输入缓冲区
            22050);                     // 输入单个通道的采样数

重点注意:
av_samples_alloc_array_and_samples的nb_samples参数
以及swr_convert的out_count与in_count两个参数表示的都是单通道的采样个数,切记是单通道的采样个数,而不是大小(字节)
计算规则:
因为我的音频采集设备每次采集到的AVPacket大小是88200个字节,采样大小是16位,即每采集一次是两个字节;所以一个Packet是采集了44100次,而一个通道就采集了22050次

ffplay播放

  • 播放采样格式为AV_SAMPLE_FMT_S16的音频
    【ffmpeg】音频重采样_第1张图片
  • 播放将采样格式为AV_SAMPLE_FMT_S16重采样为AV_SAMPLE_FMT_FLT的音频
    【ffmpeg】音频重采样_第2张图片

参考资料

【1】雷神博客
【2】ffmpeg官方文档
【3】李超:音视频基础+ffmpeg原理

你可能感兴趣的:(#,FFmpeg入门,音视频,重采样,ffmpeg,SwrContext,swr_convert)