企业网站建设网,建小网站多少钱,即墨网站制作,建设银行信用卡中心网站auto convert的创建
在FFmpeg/libavfilter/formats.c中定义了negotiate_video和negotiate_audio#xff0c;在格式协商#xff0c;对于video如果需要scale#xff0c;那么就会自动创建scale作为convert#xff0c;对于audio#xff0c;如果需要重采样#xff0c;则会创建…auto convert的创建
在FFmpeg/libavfilter/formats.c中定义了negotiate_video和negotiate_audio在格式协商对于video如果需要scale那么就会自动创建scale作为convert对于audio如果需要重采样则会创建aresample。
static const AVFilterNegotiation negotiate_video {.nb_mergers FF_ARRAY_ELEMS(mergers_video),.mergers mergers_video,.conversion_filter scale,.conversion_opts_offset offsetof(AVFilterGraph, scale_sws_opts),
};static const AVFilterNegotiation negotiate_audio {.nb_mergers FF_ARRAY_ELEMS(mergers_audio),.mergers mergers_audio,.conversion_filter aresample,.conversion_opts_offset offsetof(AVFilterGraph, aresample_swr_opts),
};merge相关
格式协商merge的时候video有merge_pix_fmtsaudio有merge_channel_layoutsmerge_sampleratesmerge_sample_fmts。
static const AVFilterFormatsMerger mergers_video[] {{.offset offsetof(AVFilterFormatsConfig, formats),.merge merge_pix_fmts,.can_merge can_merge_pix_fmts,},
};static const AVFilterFormatsMerger mergers_audio[] {{.offset offsetof(AVFilterFormatsConfig, channel_layouts),.merge merge_channel_layouts,.can_merge NULL,},{.offset offsetof(AVFilterFormatsConfig, samplerates),.merge merge_samplerates,.can_merge can_merge_samplerates,},{.offset offsetof(AVFilterFormatsConfig, formats),.merge merge_sample_fmts,.can_merge can_merge_sample_fmts,},
};ffmpeg的auto conversion开关
在ffmpeg_opt.c中有这个定义
int auto_conversion_filters 1;如果是0那么audio conversion是都可以关掉的这段代码在configure_filtergraph()函数中flag设置为AVFILTER_AUTO_CONVERT_NONE所有的自动转换会被禁用。
if (!auto_conversion_filters)avfilter_graph_set_auto_convert(fg-graph, AVFILTER_AUTO_CONVERT_NONE);ffmpeg使用soxr
-af aresampleresamplersoxr
ffmpeg -i chd-44100.wav -af aresampleresamplersoxr -ar 48000 chd-48000.wav -v 56FFmpeg命令中默认不指定aresample的时候是swr采样使用soxr就需要手动指定-af aresampleresamplersoxr。
ffmpeg resample函数中的buf_set
ret s-resampler-multiple_resample(s-resample, out, out_count, in, FFMAX(in_count-padless, 0), consumed);
out_count - ret;
ret_sum ret;
buf_set(out, out, ret);
in_count - consumed;
buf_set(in, in, consumed);s-resampler-multiple_resample返回实际resample的sample数consumed返回实际消耗的input sample数。
然后buf_set(out, out, ret)对out数据进行有效的长度设置同时也重新计算了out_count和in_countbuf_set(in, in, consumed)设置了输入数据的有效长度。
internal format的选择
首先要看下internal format的来历
struct SwrContext {const AVClass *av_class; /// AVClass used for AVOption and av_log()int log_level_offset; /// logging level offsetvoid *log_ctx; /// parent logging contextenum AVSampleFormat in_sample_fmt; /// input sample formatenum AVSampleFormat int_sample_fmt; /// internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)enum AVSampleFormat out_sample_fmt; /// output sample formatSwrContext中定义了in_sample_fmtint_sample_fmtout_sample_fmt其中int_sample_fmt就表示internal format顾名思义就是用于swresample内部的sample format格式。并且有四种取值
AV_SAMPLE_FMT_S16P
AV_SAMPLE_FMT_S32P
AV_SAMPLE_FMT_FLTP
AV_SAMPLE_FMT_DBLP实际的代码是 if(s-int_sample_fmt AV_SAMPLE_FMT_NONE){if( av_get_bytes_per_sample(s- in_sample_fmt) 2 av_get_bytes_per_sample(s-out_sample_fmt) 2){s-int_sample_fmt AV_SAMPLE_FMT_S16P;}else if( av_get_bytes_per_sample(s- in_sample_fmt) 2 !s-rematrix s-out_sample_rates-in_sample_rate !(s-flags SWR_FLAG_RESAMPLE)){s-int_sample_fmt AV_SAMPLE_FMT_S16P;}else if( av_get_planar_sample_fmt(s- in_sample_fmt) AV_SAMPLE_FMT_S32P av_get_planar_sample_fmt(s-out_sample_fmt) AV_SAMPLE_FMT_S32P !s-rematrix s-out_sample_rate s-in_sample_rate !(s-flags SWR_FLAG_RESAMPLE) s-engine ! SWR_ENGINE_SOXR){s-int_sample_fmt AV_SAMPLE_FMT_S32P;}else if(av_get_bytes_per_sample(s-in_sample_fmt) 4){s-int_sample_fmt AV_SAMPLE_FMT_FLTP;}else{s-int_sample_fmt AV_SAMPLE_FMT_DBLP;}}这段代码检查int_sample_fmt是否指定如果未指定则根据一些规则来选择一个合适的内部采样格式为 第一个if语句块中如果输入和输出采样格式的每个采样点的字节数都小于等于2则选择AV_SAMPLE_FMT_S16P作为内部采样格式。第二个else if语句块中如果输入采样格式的每个采样点的字节数小于等于2且不需要重新混音rematrix为false、输出采样率等于输入采样率、不需要重新采样SWR_FLAG_RESAMPLE为false则选择AV_SAMPLE_FMT_S16P作为内部采样格式。第三个else if语句块中如果输入和输出采样格式都是32位平面格式AV_SAMPLE_FMT_S32P且不需要重新混音、输出采样率等于输入采样率、不需要重新采样、使用的引擎不是SOXR则选择AV_SAMPLE_FMT_S32P作为内部采样格式。第四个else if语句块中如果输入采样格式的每个采样点的字节数小于等于4则选择AV_SAMPLE_FMT_FLTP作为内部采样格式。最后一个else语句块中如果以上条件都不满足则选择AV_SAMPLE_FMT_DBLP作为内部采样格式。
resample输入输出convert s-in_convert swri_audio_convert_alloc(s-int_sample_fmt,s- in_sample_fmt, s-used_ch_count, s-channel_map, 0);s-out_convert swri_audio_convert_alloc(s-out_sample_fmt,s-int_sample_fmt, s-out.ch_count, NULL, 0);比如internal sample fmt是fltp输入输出sample fmt没有指定输入文件是s16那么输入输出默认就是s16那么in_convert和out_convert的conv_f值如下
s-in_convert
conv_f: conv_AV_SAMPLE_FMT_S16_to_AV_SAMPLE_FMT_FLT
s-out_convert
conv_f: conv_AV_SAMPLE_FMT_FLT_to_AV_SAMPLE_FMT_S16
convert初始化不同的平台对应不同的版本
#if ARCH_X86 HAVE_X86ASM HAVE_MMXswri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);
#elif ARCH_ARMswri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);
#elif ARCH_AARCH64swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);
#endifffmpeg swreample命令
resamplerswr ffmpeg -y -i 2ch-16k.wav -af aresampleresamplerswr -ac 2 -ar 48000 -f f32le out.pcm不写aresample默认会走swr
ffmpeg -y -i 2ch-16k.wav -ac 2 -ar 48000 -f f32le out.pcm-f f32le指定了保存的文件格式是PCM不是wav所以保存出来的文件按wav来解析是不对的即使文件名为out.wav也不行。
resamplersoxr
ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersoxr -ac 2 -ar 48000 -f f32le out.pcmresamplersrc
ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc -filter_type sinc_best \
-ac 2 -ar 48000 -acodec pcm_f32le out.wavffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc -ac 2 -ar 48000 -f f32le out.pcm -v 56
-acodec pcm_f32le指定输出的格式是pcm_f32le没有显示指定-f wav实际上会根据输出文件名使用wav muxer.
-f f32lef32le参数指定了输出的格式的同时也保证了src重采样使用的内部数据格式是fltp。
指定-acodec pcm_f32le输出的格式codec格式是pcm_f32le所以aresample的输出格式会设置为f32le:
./ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typesinc_best -ac 2 -ar 48000 -acodec pcm_f32le out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typesinc_fast -ac 2 -ar 48000 -acodec pcm_f32le out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typesinc_fast:internal_sample_fmtfltp -ac 2 -ar 48000 out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typelinear:internal_sample_fmtfltp -ac 2 -ar 48000 out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typezoh:internal_sample_fmtfltp -ac 2 -ar 48000 out.wav -v 56
如果没有指定-acodec pcm_f32le而是通过aresample的option指定out_sample_fmtflt这时候flt只是一个中间格式最后会转换和输入格式一样的s16le
ffmpeg -y -i 2ch-16k.wav -af aresampleresamplersrc:filter_typesinc_best:out_sample_fmtflt \
-ac 2 -ar 48000 out.wav -v 56可以看到如下log
[ap] ch:2 chl:stereo fmt:s16 r:16000Hz - ch:2 chl:stereo fmt:flt r:48000Hz
[ap] Using fltp internally between filters
[ap] ch:2 chl:stereo fmt:flt r:48000Hz - ch:2 chl:stereo fmt:s16 r:48000Hz