FFMPEG学习【libswresample】

来源:互联网 发布:编程证书 编辑:程序博客网 时间:2024/06/13 22:55

音频重采样,采样格式转换和混合库。

与lswr的交互是通过SwrContext完成的,SwrContext被分配给swr_alloc()或swr_alloc_set_opts()。 它是不透明的,所以所有参数必须使用AVOptions API设置。

为了使用lswr,你需要做的第一件事就是分配SwrContext。 这可以使用swr_alloc()或swr_alloc_set_opts()来完成。 如果您使用前者,则必须通过AVOptions API设置选项。 后一个函数提供了相同的功能,但它允许您在同一语句中设置一些常用选项。

例如,以下代码将设置从平面浮动样本格式到交织的带符号16位整数的转换,从48kHz到44.1kHz的下采样,以及从5.1声道到立体声的下混合(使用默认混合矩阵)。 这是使用swr_alloc()函数。

SwrContext *swr = swr_alloc();av_opt_set_channel_layout(swr, "in_channel_layout",  AV_CH_LAYOUT_5POINT1, 0);av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO,  0);av_opt_set_int(swr, "in_sample_rate",     48000,                0);av_opt_set_int(swr, "out_sample_rate",    44100,                0);av_opt_set_sample_fmt(swr, "in_sample_fmt",  AV_SAMPLE_FMT_FLTP, 0);av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16,  0);

同样的工作也可以使用swr_alloc_set_opts():

SwrContext *swr = swr_alloc_set_opts(NULL,  // we're allocating a new context                      AV_CH_LAYOUT_STEREO,  // out_ch_layout                      AV_SAMPLE_FMT_S16,    // out_sample_fmt                      44100,                // out_sample_rate                      AV_CH_LAYOUT_5POINT1, // in_ch_layout                      AV_SAMPLE_FMT_FLTP,   // in_sample_fmt                      48000,                // in_sample_rate                      0,                    // log_offset                      NULL);                // log_ctx

一旦设置了所有值,它必须用swr_init()初始化。 如果需要更改转换参数,可以使用AVOptions来更改参数,如上面第一个例子所述; 或者使用swr_alloc_set_opts(),但是第一个参数是分配的上下文。 您必须再次调用swr_init()。

转换本身通过重复调用swr_convert()来完成。 请注意,如果提供的输出空间不足或采样率转换完成后,样本可能会在swr中缓冲,这需要“未来”样本。 可以随时通过使用swr_convert()(in_count可以设置为0)来检索不需要将来输入的样本。 在转换结束时,可以通过调用具有NULL in和in incount的swr_convert()来刷新重采样缓冲区。

在转换过程中使用的样本可以使用libavutil示例操作API进行管理,包括以下示例中使用的av_samples_alloc()函数。

输入和输出之间的延迟可以随时通过使用swr_get_delay()找到。

以下代码演示了假设上面的参数和调用者定义的函数get_input()和handle_output())的转换循环:

uint8_t **input;int in_samples;while (get_input(&input, &in_samples)) {    uint8_t *output;    int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) +                                     in_samples, 44100, 48000, AV_ROUND_UP);    av_samples_alloc(&output, NULL, 2, out_samples,                     AV_SAMPLE_FMT_S16, 0);    out_samples = swr_convert(swr, &output, out_samples,                                     input, in_samples);    handle_output(output, out_samples);    av_freep(&output);}

转换完成后,必须使用swr_free()释放转换上下文和与之相关的所有内容。 也可以使用swr_close()函数,但它主要是为了与libavresample兼容,不需要调用。

如果在swr_free()之前没有完全刷新数据,则不会有内存泄漏。


一、函数

const AVClass * swr_get_class (void)获取 SwrContext的AVClass。

它可以与AV_OPT_SEARCH_FAKE_OBJ结合使用来检查选项。

查看:av_opt_find().

返回:SwrContext的AVClass



二、选项常数

这些常量用于lswr的AVOptions接口。

enum  SwrDitherType { 
  SWR_DITHER_NONE = 0, SWR_DITHER_RECTANGULAR, SWR_DITHER_TRIANGULAR, SWR_DITHER_TRIANGULAR_HIGHPASS, 
  SWR_DITHER_NS = 64, SWR_DITHER_NS_LIPSHITZ, SWR_DITHER_NS_F_WEIGHTED, SWR_DITHER_NS_MODIFIED_E_WEIGHTED, 
  SWR_DITHER_NS_IMPROVED_E_WEIGHTED, SWR_DITHER_NS_SHIBATA, SWR_DITHER_NS_LOW_SHIBATA, SWR_DITHER_NS_HIGH_SHIBATA, 
  SWR_DITHER_NB 
}抖动算法。


enum  SwrEngine { SWR_ENGINE_SWR, SWR_ENGINE_SOXR, SWR_ENGINE_NB }重新采样发动机。


enum  SwrFilterType { SWR_FILTER_TYPE_CUBIC, SWR_FILTER_TYPE_BLACKMAN_NUTTALL, SWR_FILTER_TYPE_KAISER }重新采样过滤器类型。


#define SWR_FLAG_RESAMPLE   1强制重采样即使相等采样率。




三、SwrContext构造函数
struct SwrContext * swr_alloc (void)分配SwrContext
如果使用此函数,则需要在调用swr_init()之前设置参数(手动或使用swr_alloc_set_opts())。
参数:swr_alloc_set_opts()swr_init()swr_free()
返回:错误为NULL,否则分配上下文

int swr_init (struct SwrContext *s)用户参数设置后初始化上下文。
注意:必须使用AVOption API配置上下文。
查看:av_opt_set_int(),av_opt_set_dict()
参数:s:Swr上下文进行初始化
返回:发生故障时出现AVERROR错误代码。

int swr_is_initialized (struct SwrContext *s)检查swr上下文是否已初始化。
参数:s:Swr上下文检查
查看:swr_init()
返回:如果初始化为正,则为0,如果未初始化则为0

 struct 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)如果需要,分配SwrContext并设置/重置常见参数。
此函数不需要使用swr_alloc()分配s。 另一方面,swr_alloc()可以使用swr_alloc_set_opts()在分配的上下文上设置参数。
参数:s:现有Swr上下文(如果可用),如果不可用则为NULL
   out_ch_layout:输出通道布局(AV_CH_LAYOUT_ *)
   out_sample_fmt:输出采样格式(AV_SAMPLE_FMT_ *)。
   out_sample_rate:输出采样率(频率(Hz))
   in_ch_layout:输入通道布局(AV_CH_LAYOUT_ *)
   in_sample_fmt:输入样品格式(AV_SAMPLE_FMT_ *)。
   in_sample_rate:输入采样率(频率(Hz))
   log_offset:记录级别偏移
   log_ctx:父记录上下文,可以为NULL
查看:swr_init()swr_free()
返回:错误为NULL,否则分配上下文

四、SwrContext析构函数
void swr_free (struct SwrContext **s)释放给定的SwrContext并将指针设置为NULL。
参数:s:指向Swr上下文的指针的指针

void swr_close (struct SwrContext *s)关闭上下文以使swr_is_initialized()返回0。
可以通过运行swr_init()将上下文恢复使用,也可以在不使用swr_close()的情况下使用swr_init()。 此功能主要用于简化用户尝试支持libavresample和libswresample的用例。
参数:s:Swr上下文关闭



五、核心转换函数
int swr_convert (struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count)转换音频
in和in_count可以设置为0,以最后刷新最后几个样本。
如果提供比输出空间更多的输入,则输入将被缓冲。 您可以通过使用swr_get_out_samples()来检索给定数量的输入样本所需的输出样本数的上限来避免此缓冲。 转换将直接运行,无需复制即可。
参数:s:分配Swr上下文,并设置参数
   out:输出缓冲区,只有在打包音频的情况下才需要设置第一个
   out_count:每个通道样品中可用于输出的空间量
   in:输入缓冲区,只有在打包音频的情况下才需要设置第一个
   in_count:在一个通道中可用的输入样本数
返回:每个通道的采样数量,误差的负值


int64_t swr_next_pts (struct SwrContext *s, int64_t pts)将下一个时间戳从输入转换为输出时间戳为1 /(in_sample_rate * out_sample_rate)单位。
注意:有两种略有不同的行为模式。
1、当不使用自动时间戳补偿时,(min_compensation> = FLT_MAX)在这种情况下时间戳将通过延迟补偿
2、当使用自动时间戳补偿时,(min_compensation <FLT_MAX)在这种情况下,输出时间戳将匹配输出样本号。 有关两种补偿方式,请参阅ffmpeg-resampler(1)。
参数:s:初始化Swr上下文
   pts:时间戳为下一个输入样本,INT64_MIN如果未知
查看:swr_set_compensation(),swr_drop_output()和swr_inject_silence()是内部用于时间戳补偿的函数。
返回:下一个输出样本的输出时间戳



六、低级选项设置函数
这些功能提供了设置AVOption API无法实现的低级选项的方法。

int swr_set_compensation (struct SwrContext *s, int sample_delta, int compensation_distance)激活重采样补偿(“软”补偿)。
在swr_next_pts()中需要时,内部调用此函数。
参数:s:分配Swr上下文。 如果未初始化,或未设置SWR_FLAG_RESAMPLE,则会使用标志集调用swr_init()。
   sample_delta:每个样本PTS的delta
   compensation_distance:要补偿的样品数量
返回:> = 0成功,AVERROR错误代码如果:
1、s为null
2、compensation_distance小于0,
3、compensation_distance是0,但是sample_delta不是,
4、补偿不支持重采样器,或
5、调用时,swr_init()失败。


int swr_set_channel_mapping (struct SwrContext *s, const int *channel_map)设置一个定制的输入通道映射。
参数:s:分配的Swr上下文,尚未初始化
   channel_map:定制输入通道映射(通道索引数组,静音通道为-1)
返回:> = 0成功,否则AVERROR错误代码失败。

int swr_build_matrix (uint64_t in_layout, uint64_t out_layout, double center_mix_level, double surround_mix_level, double lfe_mix_level, double rematrix_maxval, double rematrix_volume, double *matrix, int stride, enum AVMatrixEncoding matrix_encoding, void *log_ctx)生成通道混合矩阵。
此函数是用于构建默认混合矩阵的libswresample内部使用的函数。 它被公开,作为构建自定义矩阵的效用函数。
参数:in_layout:输入通道布局
   out_layout:输出通道布局
   center_mix_level:混合水平为中心通道
   surround_mix_level:环绕声道的混合电平
   ife_mix_level:低频效果通道的混合电平
   rematrix_maxval:如果为1.0,系数将被归一化以防止溢出。 如果INT_MAX,系数将不会被归一化。
   matrix:混合系数; 矩阵[i + stride * o]是输出通道o中输入通道i的权重。
   stride:矩阵阵列中相邻输入通道之间的距离
   matrix_encoding:矩阵立体声下混模式(例如dplii)
   log_ctx:父记录上下文,可以为NULL
返回:0成功,否则ERROR代码失败
   

int swr_set_matrix (struct SwrContext *s, const double *matrix, int stride)设置一个定制的混音矩阵。
参数:s:分配的Swr上下文,尚未初始化
   matrix:混音系数; 矩阵[i + stride * o]是输出通道o中输入通道i的权重
   stride:在矩阵的行之间偏移
返回:> = 0成功,否则AVERROR错误代码失败。



七、样品处理函数
int swr_drop_output (struct SwrContext *s, int count)丢弃指定数量的输出样本。
如果需要“硬”补偿,则此函数与swr_inject_silence()一起由swr_next_pts()调用。
参数:s:分配Swr上下文
   count:要丢弃的样品数量
返回:> = 0,否则为ERROR代码

int swr_inject_silence (struct SwrContext *s, int count)注入指定数量的沉默样本。
如果需要“硬”补偿,此函数与swr_drop_output()一起被swr_next_pts()调用。
参数:s:分配Swr上下文
   count:要丢弃的样品数量
返回:> = 0,否则为ERROR代码

int64_t swr_get_delay (struct SwrContext *s, int64_t base)获取下一个输入样本相对于下一个输出样本将遇到的延迟。
如果提供了比可用的输出空间更多的输入,Swresample可以缓冲数据,而且采样率之间的转换也需要延迟。 此函数返回所有此类延迟的总和。 输入或输出采样率的精确延迟不一定是整数值。 特别是当以较大的值进行下采样时,输出采样率可能是用于表示延迟的不良选择,类似于上采样和输入采样率。
参数:s:swr上下文
   base:返回延迟的时基:
1、f设置为1,返回的延迟是以秒为单位
  2、如果设置为1000,返回的延迟是毫秒
3、如果设置为输入采样率,则返回的延迟在输入采样中
4、如果将其设置为输出采样率,则返回的延迟在输出采样中
5、如果它是in_sample_rate和out_sample_rate的最不常见的倍数,那么将返回一个确切的无舍弃的延迟
返回:延迟1 /基本单位。

int swr_get_out_samples (struct SwrContext *s, int in_samples)查找下一个swr_convert调用将输出的样本数的上限,如果使用in_samples的输入样本调用。
这取决于内部状态,任何改变内部状态(如进一步的swr_convert()调用)都可能会改变样本数swr_get_out_samples()返回相同数量的输入样本数。
参数:in_samples:输入样本数。
注意:任何调用swr_inject_silence(),swr_convert(),swr_next_pts()或swr_set_compensation()都会使此限制无效
   建议将正确的可用缓冲区大小传递给所有函数,如swr_convert(),即使swr_get_out_samples()表示较少使用。
返回:下一个swr_convert将输出的样本数量的上限或用于指示错误的负值



八、配置访问器
unsigned swresample_version (void)返回LIBSWRESAMPLE_VERSION_INT常量。
这对于检查构建时libswresample是否与运行时libswresample具有相同的版本是有用的。
返回:未签名的int型版本

const char * swresample_configuration (void)返回swr构建时配置。
返回:构建时间./configure标志

const char * swresample_license (void)返回swr许可证。
返回:libswresample的许可证在建立时确定




九、AVFrame基础API
int swr_convert_frame (SwrContext *swr, AVFrame *output, const AVFrame *input)转换输入AVFrame中的样本并将其写入输出AVFrame。
输入和输出AVFrames必须具有channel_layout,sample_rate和格式设置。
如果输出的AVFrame没有分配数据指针,那么将使用av_frame_get_buffer()来设置nb_samples字段来分配帧。
输出的AVFrame可以为空,或者比所需的分配样本少。 在这种情况下,未写入输出的任何剩余样本将被添加到内部FIFO缓冲区,以便在下次调用此函数或swr_convert()时返回。
如果转换采样率,内部重采样延迟缓冲器中可能存在数据。 swr_get_delay()告诉剩余样本的数量。 要将此数据作为输出,请调用此函数或使用NULL输入调用此函数或swr_convert()。
如果SwrContext配置与输出和输入AVFrame设置不匹配,转换不会发生,并且取决于哪个AVFrame不匹配AVERROR_OUTPUT_CHANGED,则返回AVERROR_INPUT_CHANGED或它们的按位OR的结果。
查看:swr_delay(),swr_convert(),swr_get_delay()
参数:swr:音频重新采样上下文
   output:输出AVFrame
   input:输入AVFrame
返回:0成功,失败或不匹配配置错误。

int swr_config_frame (SwrContext *swr, const AVFrame *out, const AVFrame *in)使用AVFrames提供的信息配置或重新配置SwrContext。
即使故障,原始重采样上下文也被重置。 如果上下文打开,该函数将在内部调用swr_close()。
查看:swr_close();
参数:swr:音频重新采样上下文
  out:输出AVFrame
  in:输入AVFrame
返回:0成功,失败时出错。