FFplay音频滤镜分析
音频流的 滤镜是通过 configure_audio_filters() 函数来创建的,因为 ffplay 为了代码的通用性,即便命令行参数不使用滤镜, AVFrame 也会过一遍 空滤镜做下样子。
configure_audio_filters() 函数的流程图如下:
configure_audio_filters() 函数的定义如下: static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format){....}
下面讲解一下这个函数的参数。
VideoState *is ,是 ffplay 播放器的全局管理器。
char *afilters ,是滤镜字符串,例如 下面的命令: ffplay -af "atempo=2.0" -i juren-5s.mp4
"atempo=2.0" 这个字符串就会赋值给 afilters 。
int force_output_format ,代表是否强制把 buffersink 出口滤镜的音频帧采样等信息 设置为 跟 is->audio_tgt 一样。
之前说过 is->audio_tgt 是音响硬件设备打开的信息。 is->audio_tgt 是 最终 要传递给 SDL 的音频格式。所有的采样率,声道数等等最后都要转成 is->audio_tgt 。
下面来分析一下 configure_audio_filters() 函数里面的重点代码,如下:
这个函数一开始就定义了 一些只有 2 个元素的数组,这其实是 ffmpeg 项目传递参数的方式,传递一个数组进去函数,主要有两种方式。
1, 传递数组的大小。就是有多少个元素。
2, 传递数组的结尾,只要读到结尾元素 (-1),就算结束了。
ffmpeg 大部分函数采用的是第二种方式。
然后他会调 avfilter_graph_free() 释放 滤镜容器 (FilterGraph),有些同学可能会疑惑, is->agraph 一开始不是 NULL 吗? 为什么需要释放?
is->agraph 一开始确实是 NULL,但是 configure_audio_filters() 这个函数可能会调用 第二次 ,第二次的时候 is->agraph 就不是 NULL了。
configure_audio_filters() 第一次调用 是在 stream_component_open() 里面,如下:
第二次调用 是在 audio_thread() 里面,如下:
【腾讯文档】FFmpegWebRTCRTMPRTSPHLSRTP播放器-音视频流媒体高级开发-资料领取FFmpegWebRTCRTMPRTSPHLSRTP鎾 斁鍣 -闊宠 棰戞祦濯掍綋楂樼骇寮 鍙 -璧勬枡棰嗗彇
第二次调用 configure_audio_filters() 是因为实际解码出来的 AVFrame 的采样率,声道等,跟容器里面记录的不一致,之前 is->audio_filter_src 是直接从容器,封装层取的数据。封装层记录的音频采样率等, 可能是错的 ,需要以实际解码出来的 AVFrame 为准。
而且,注意,第二次的时候, force_output_format 参数会置为 1,这样会强制 buffersink 出口滤镜的采样信息等 设置为 is->audio_tgt 一样。
其实 configure_audio_filters() 必然会调第二次的 ,因为 is->auddec.pkt_serial != last_serial 这个条件肯定是真。
接着就是设置 滤镜使用的线程数量,0 为自动选择线程数量,如下: is->agraph->nb_threads = filter_nbthreads;
第三个重点是,设置重采样选项(aresample_swr_opts),如下:
什么样的命令行参数才是重采样选项的,在 libswresample/options.c 里面可以找到,如下:
举个例子,如下: ffpaly -ich 1 -i juren-5s.mp4
ich 1 就会被解析拷贝进去 ffplay.c 里面的 swr_opts 变量里面。
这里还用到了一个新的函数 av_opt_set() ,这个函数其实不只可以设置 滤镜的属性字段 ,还可以设置大多数 数据结构 的属性字段,例如解码器,封装器 等等,只要内部有 AVClass 的数据结构,都能用 av_opt_set() 来设置属性,详情请阅读《opt.h文件函数分析》
接下来的重点是设置入口跟出口滤镜,如下:
出口滤镜 还设置了 sample_fmts 为 AV_SAMPLE_FMT_S16 ,这是 ffpaly 播放器自己的特性,就是说无论MP4文件里面的音频格式是怎样的,他都会转成 AV_SAMPLE_FMT_S16 格式丢给 SDL 播放,而且它在用 SDL_OpenAudioDevice 打开音频设备的时候,就是用的 S16 格式, 这是写死的 。
force_output_format 的逻辑主要是 强制 buffersink 出口滤镜的采样信息等 设置为跟 is->audio_tgt 一样。 audio_tgt 是 SDL 接受音频帧的最终格式。
第一次调用 configure_audio_filters() 函数, force_output_format 为 0,不会跑进去这块逻辑。
最后就是调 configure_filtergraph() 函数来 链接入口跟出口滤镜 ,同时创建滤镜容器(FilterGraph),如下:
上图最重要的是,入口滤镜 跟 出口滤镜 被赋值到全局管理器 is 了。后面只要把解码器输出的 AVFrame 往入口滤镜丢,然后往出口滤镜读就行了。
官方森保一继续担任日本队主帅,率队冲击2026年世界杯直播吧12月28日讯日本足协宣布,森保一继续担任日本队主帅,率队冲击2026年的美国加拿大墨西哥世界杯。在刚结束不久的卡塔尔世界杯上,森保一率队在死亡之组中战胜德国和西班牙,闯入1
(经济)全球最大规模沙戈荒风电光伏基地项目在库布其沙漠开工建设新华社北京12月28日电(记者侯雪静)记者28日从三峡集团了解到,由三峡集团联合内蒙古能源集团建设的库布其沙漠鄂尔多斯中北部新能源基地项目在内蒙古鄂尔多斯市达拉特旗开工建设。该项目
不是只有芯片,才叫核心竞争力精亦诚刘欣(本文来自原创作者刘欣卓越运营实战公号,订阅公号,一起实现卓越运营。)持续近两年的芯片短缺,让芯片似乎快成了核心竞争力的代名词。特别是在数字化时代的今天,能生产芯片,几乎
重磅!安徽宝镁年产30万吨高性能镁基轻合金项目获银团贷款!安徽宝镁年产30万吨高性能镁基轻合金项目银团贷款签约仪式举行方能斌出席12月28日下午,安徽宝镁轻合金有限公司年产30万吨高性能镁基轻合金项目银团贷款签约仪式举行。宝钢金属党委书记
为人处事要公平公正,但也要有决绝的一面为人处世要公平公正,但面对他人求助不想帮助的时候,也必须要学会狠心拒绝。相信很多人都经历过,别人求你办事的时候,不好意思拒绝的这种经历。说到这个问题,那就要说人性这个问题了,相信很
饱经沧桑过三朝与人为善心肠好缅怀我的外爷饱经沧桑过三朝与人为善心肠好深切缅怀我的外爷萧贞祥张耀宇文头顶一个天,脚踏一方土,风雨中你昂起头,冰雪压不服题记人是感情动物,无论亲情友情,都弥足珍贵。茫茫人海,多少人相遇又再见缘
写在2022年尾的话三年来,那个叫新冠的病毒,一次次打乱了每个人的生活节奏。可我们阻止不了它的到来。在2022年这个冬天,猝不及防地它直击我们的身心,每个人几乎都与之正面交锋。别无选择。唯一能做的,就
洛克菲勒家族留给子孙的忠告洛克菲勒是谁?比尔盖茨曾经这样说过洛克菲勒在我心目中,只有一个真正的赚钱英雄。他就是洛克菲勒。洛克菲勒是世界石油大王,世界上第一位亿万富翁。不仅如此,洛克菲勒将家族的富裕传承了下去
散文老屋童年和大黑那大概是一个夏秋交际的早晨,天才蒙蒙亮,整个乡村在烟雾的笼罩之下,太阳还没出来,虽然公鸡已经开始打鸣了,偶尔也会有伴随着几声狗叫,但是整个山村基本上还处于睡眠状态。母亲夹着一个包裹
张晴散文回忆慈父我的严师我的慈父文张晴又一次走进向往已久的校园感到一切非常新鲜,当年一排排平房已被一幢幢教学大楼取代,校园里绿树成荫鲜花锦簇,母校的变化太大了唯一没改变的就是我的情怀,三十多年前的
被保护了三年,已经足够网图侵删不得不说,这三年,在生命历程中,是特殊的三年。从当初的恐慌不安,到现在的欣然接受,从病毒的毒性强,到逐渐减弱,从一无所知,到铺天盖地解说,从心理接受到主动预防,我们已走过很