AVFilterLink的channels设置

下面这样一条命令

ffmpeg -i /Users/user/video/mp4/output.wav  -ac 1 /Users/user/video/mp4/output1.wav 

我们会形成下面这样的图

图1

现在有个问题link4的channel怎么设置的?

static int pick_format(AVFilterLink *link, AVFilterLink *ref){link->channel_layout = link->incfg.channel_layouts->channel_layouts[0];if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout)))link->channel_layout = 0;elselink->channels = av_get_channel_layout_nb_channels(link->channel_layout);}

我们通过上面代码可以知道link的channel来自于link->incfg.channel_layouts->channel_layouts[0]的转化。

那么下一个问题incfg是什么。我们知道link的输入是link->src对应filter,那么这个配置也应该是src对应的filter进行配置。

通过图1我们知道link4的src是afromat。

我们进入afromat的filter我们发现了下面的代码

 static int query_formats(AVFilterContext *ctx){AFormatContext *s = ctx->priv;ret = ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts :ff_all_channel_counts());}

我们知道了s->channel_layouts 从ctx->priv

也就是下面结构体重的channel_layouts


typedef struct AFormatContext {const AVClass   *class;AVFilterFormats *formats;AVFilterFormats *sample_rates;AVFilterChannelLayouts *channel_layouts;char *formats_str;char *sample_rates_str;char *channel_layouts_str;
} AFormatContext;

那么aformat的参数又来自于下面的设置

 static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
{sample_fmts     = choose_sample_fmts(ofilter);sample_rates    = choose_sample_rates(ofilter);channel_layouts = choose_channel_layouts(ofilter);args[0] = 0;if (sample_fmts)av_strlcatf(args, sizeof(args), "sample_fmts=%s:",sample_fmts);if (sample_rates)av_strlcatf(args, sizeof(args), "sample_rates=%s:",sample_rates);if (channel_layouts)av_strlcatf(args, sizeof(args), "channel_layouts=%s:",channel_layouts);ret = avfilter_graph_create_filter(&format,avfilter_get_by_name("aformat"),name, args, NULL, fg->graph);                  }

可以看到来自于choose_channel_layouts

choose_channel_layouts是个宏定义,理解起来比较费劲

DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0,GET_CH_LAYOUT_NAME)
#define DEF_CHOOSE_FORMAT(suffix, type, var, supported_list, none, get_name)   \
static char *choose_ ## suffix (OutputFilter *ofilter)                         \
{                                                                              \if (ofilter->var != none) {                                                \get_name(ofilter->var);                                                \return av_strdup(name);                                                \} else if (ofilter->supported_list) {                                      \const type *p;                                                         \AVIOContext *s = NULL;                                                 \uint8_t *ret;                                                          \int len;                                                               \\if (avio_open_dyn_buf(&s) < 0)                                         \exit_program(1);                                                           \\for (p = ofilter->supported_list; *p != none; p++) {                   \get_name(*p);                                                      \avio_printf(s, "%s|", name);                                       \}                                                                      \len = avio_close_dyn_buf(s, &ret);                                     \ret[len - 1] = 0;                                                      \return ret;                                                            \} else                                                                     \return NULL;                                                           \
}

将相应的占位符进行替换后会发现channel_layouts取的是OutputFilter的是channel_layout字段。

接下来我们开始寻找OutputFilter->channel_layout怎么设置的?

static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter,AVFilterInOut *out){case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);}int configure_filtergraph(FilterGraph *fg) {const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :fg->graph_desc;  if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)goto fail;for (cur = outputs, i = 0; cur; cur = cur->next, i++)configure_output_filter(fg, fg->outputs[i], cur);
}

我们发现来自于FilterGraph的output

static int open_output_file(OptionsContext *o, const char *filename){OutputFilter *f = ost->filter;switch (ist->st->codecpar->codec_type) {case AVMEDIA_TYPE_VIDEO:      ost = new_video_stream     (o, oc, src_idx); break;case AVMEDIA_TYPE_AUDIO:      ost = new_audio_stream     (o, oc, src_idx); break;}if (ost->enc_ctx->channels) {f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels);}}

现在的问题就成了ost->enc_ctx->channels怎么来的?

static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
{audio_enc = ost->enc_ctx;if (!ost->stream_copy) {char *sample_fmt = NULL;MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);}
}

MATCH_PER_STREAM_OPT的定义如下

#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
{\int i, ret, matches = 0;\SpecifierOpt *so;\for (i = 0; i < o->nb_ ## name; i++) {\char *spec = o->name[i].specifier;\if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0) {\outvar = o->name[i].u.type;\so = &o->name[i];\matches++;\} else if (ret < 0)\exit_program(1);\}\if (matches > 1)\WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\
}

我们将相应占位符带入后发现其实找的是

OptionsContext->audio_channels

typedef struct OptionsContext {OptionGroup *g;/* input/output options */int64_t start_time;int64_t start_time_eof;int seek_timestamp;const char *format;SpecifierOpt *codec_names;int        nb_codec_names;SpecifierOpt *audio_channels;
}

下面的问题来了audio_channels怎么设置的?

在ffmpeg_opt.c

#define OFFSET(x) offsetof(OptionsContext, x)
const OptionDef options[] = { { "ac",             OPT_AUDIO | HAS_ARG  | OPT_INT | OPT_SPEC |OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(audio_channels) },"set number of audio channels", "channels" },
}static int open_files(OptionGroupList *l, const char *inout,int (*open_file)(OptionsContext*, const char*))
{int i, ret;for (i = 0; i < l->nb_groups; i++) {OptionGroup *g = &l->groups[i];OptionsContext o;init_options(&o);o.g = g;ret = parse_optgroup(&o, g);
}
}int parse_optgroup(void *optctx, OptionGroup *g)
{for (i = 0; i < g->nb_opts; i++) {Option *o = &g->opts[i];ret = write_option(optctx, o->opt, o->key, o->val);if (ret < 0)return ret;}
}

这样就option_context进行了设置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/8809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

猫头虎分享已解决Bug || Node.js安装失败Error: unable to connect to https://nodejs.org/猫头虎

猫头虎分享已解决Bug || Node.js安装失败Error: unable to connect to https://nodejs.org/猫头虎 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — …

JVM的垃圾回收

JVM简介 JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java虚拟机。 虚拟机:是指通过软件模拟的具有完整硬件功能、运行在一个完全隔离的环境中完整计算机系统 1.JVM的内存区域划分 jvm是一个java进程 每一个java进程就是一个jvm实例 一个进程运行过程中 就要从操作系…

VscodeC/C++环境配置

引言 vscode是一款非常好用的编辑器&#xff0c;集成了大量的插件&#xff0c;具有很高的自由度&#xff0c;因此广受大家的喜爱。但是他本身是不带编译器的&#xff0c;因此如果要使用vscode来编译C/C程序的话&#xff0c;我们需要额外安装编译器并且为vscode配上环境。 编译…

一文教会你lambda表达式

引言 在现代编程中&#xff0c;Lambda表达式&#xff08;也称为匿名函数或闭包&#xff09;已经成为了一种非常流行的编程范式。它允许我们定义简短、一次性的函数对象&#xff0c;而无需显式地定义它们。在C11及之后的版本中&#xff0c;Lambda表达式得到了官方的支持&#x…

梦幻西游12门派复古怀旧 单机版 安装简单,云盘下载哦

做游戏开发的朋友&#xff0c;可以多参考里面的设计思想&#xff0c;真的不错。 梦幻西游12门派复古怀旧 单机版 安装简单&#xff0c;云盘下载哦 游戏大小&#xff1a; 支持系统&#xff1a;win7、win10 64位 特色&#xff1a;简化安装&#xff0c;非常容易。 重新整盒高…

Ubuntu下halcon软件的下载安装

由于工作需求&#xff0c;点云配准需要使用halcon进行实现&#xff0c;并且将该功能放入QT界面中 1.下载halcon 进入halcon官网进行下载 官网链接&#xff1a;https://www.mvtec.com/products/halcon/ 注意&#xff1a;要注册登陆之后才能进行下载 接着点击Downloads->H…

MouseBoost PRO mac中文激活版:专业鼠标助手

MouseBoost PRO mac鼠标性能优化软件&#xff0c;以其强大的功能和智能化的操作&#xff0c;助您轻松驾驭鼠标&#xff0c;提高工作效率。 MouseBoost PRO支持自定义快捷键设置&#xff0c;让您轻松实现快速切换应用程序、打开特定文件、调节音量大小等操作。自动识别窗口功能则…

240多道!Go开发岗位面试题合集(含答案)

随着今年互联网寒潮环境的影响&#xff0c;找工作的人也将达到顶峰&#xff0c;今天给大家分享一份《Go开发工程师超高频面试真题》&#xff0c;一共有240多道面试真题&#xff0c;希望能够帮助大家在面试中&#xff0c;少走一些弯路、更快拿到offer&#xff01; 内容展示 GO 基…

Dreamweaver 2021 for Mac 激活版:网页设计工具

在追求卓越的网页设计道路上&#xff0c;Dreamweaver 2021 for Mac无疑是您的梦幻之选。这款专为Mac用户打造的网页设计工具&#xff0c;集强大的功能与出色的用户体验于一身。 Dreamweaver 2021支持多种网页标准和技术&#xff0c;让您能够轻松创建符合现代网页设计的作品。其…

[Algorithm][BFS][拓扑排序][课程表][课程表Ⅱ][火星词典] + BFS解决拓扑排序原理 详细讲解

目录 0.原理讲解1.有向无环图2.AOV网3.拓扑排序4.实现拓扑排序5.如何建图&#xff1f; 1.课程表1.题目链接2.算法原理详解3.代码实现 2.课程表 II1.题目链接2.算法原理详解3.代码实现 3.火星词典1.题目链接2.算法原理详解3.代码实现 0.原理讲解 1.有向无环图 有向无环图&#…

基于Django图像识别系统毕业设计(付源码)

前言&#xff1a;Django是一个由Python编写的具有完整架站能力的开源Web框架&#xff0c;Django本身基于MVC模型&#xff0c;即Model&#xff08;模型&#xff09;View&#xff08;视图&#xff09; Controller&#xff08;控制器&#xff09;设计模式&#xff0c;因此天然具有…

【抽样调查】分层抽样上

碎碎念&#xff1a;在大一大二时听课有的时候会发现听不太懂&#xff0c;那时候只觉得是我自己的基础不好的原因&#xff0c;但现在我发现“听不懂”是能够针对性解决的。比如抽样调查这门课&#xff0c;分析过后我发现我听不懂的原因之一是“没有框架”&#xff0c;一大堆知识…

【使用ChatGPT的API之前】OpenAI API提供的可用模型

文章目录 一. ChatGPT基本概念二. OpenAI API提供的可用模型1. InstructGPT2. ChatGPT3. GPT-4 三. 在OpenAI Playground中使用GPT模型-ing 在使用GPT-4和ChatGPT的API集成到Python应用程序之前&#xff0c;我们先了解ChatGPT的基本概念&#xff0c;与OpenAI API提供的可用模型…

情感分类学习笔记(1)

文本情感分类&#xff08;二&#xff09;&#xff1a;深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…

FTTR介绍

概念 FTTR&#xff08;Fiber to The Room&#xff09;是一种新型的光纤接入技术&#xff0c;它将光纤信号传输到室内的一个通信网络方案。在FTTR网络中&#xff0c;光纤到达建筑物内的分配盒后&#xff0c;通过铜缆或其他传输介质进入室内各个房间&#xff0c;为用户提供网络服…

Java面试八股文(SpringCloud篇)

****************************************************

前端双语实现方案(VUE版)

一、封装一个lib包 结构如下 en.js use strict;exports.__esModule true; exports.default {sp: {input: {amountError: Incorrect amount format},table: {total: Total:,selected: Selected:,tableNoData: No data,tableNoDataSubtext: Tip: Suggest to recheck your fil…

使用css的box-reflect属性制作倒影效果

box-reflect 是一个在 CSS 中创建元素倒影效果的非标准属性。尽管它在过去的一些 WebKit 浏览器中&#xff08;如旧版的 Safari 和 Chrome&#xff09;得到了支持&#xff0c;但由于它并未成为 CSS 标准的一部分&#xff0c;因此在现代浏览器中的兼容性较差。以下是对 box-refl…

瑞麦德机电设备有限公司将莅临2024第13届生物发酵展

参展企业介绍 河南瑞麦德机电设备有限公司是专业从事机械输送气力输送、称重配料、筛分、磁选设备研发和制造于一体的企业&#xff0c;公司采用国内外同行业产品的先进技术&#xff0c;经专业团队设计、研发、生产&#xff0c;产品满足“ISO9001”&#xff0c;“GMP”等标准要求…

【BST】Behavior Sequence Transformer for E-commerceRecommendation in Alibaba

一、提出背景 传统的Embedding&MLP模型结构将原始特征嵌入到低维向量中&#xff0c;然后将其concat后输入MLP进行最终推荐。DIN提出使用注意力机制来捕获候选项与用户先前点击的项之间的相似性。 然而&#xff0c;大多数这些工作只是连接不同的特征&#xff0c;而没有捕获用…