網(wǎng)站首頁 編程語言 正文
new_video_stream()?函數(shù)流程
new_video_stream()
?函數(shù)的流程相對來說比較簡單,主要的邏輯如下:
1, 調(diào)?new_output_stream()
?函數(shù)來創(chuàng)建?OutputStream
?輸出流,以及?AVCodecContext
?編碼器上下文。
new_output_stream()
?是一個公共函數(shù),創(chuàng)建 音頻流,數(shù)據(jù)流,字幕流都用了它。
new_output_stream()
?會把命令行的一些公共參數(shù)賦值給?OutputStream
?跟?AVCodecContext
。
這些公共參數(shù)是指音頻,視頻,字幕都可能會有的參數(shù)。因為?new_output_stream()
?是一個公共函數(shù)。
2, 調(diào)?MATCH_PER_STREAM_OPT()
?宏函數(shù),把?OptionsContext
?里面視頻相關(guān)的參數(shù),賦值給 給?OutputStream
?跟?AVCodecContext
。
流程圖
可以看到,實(shí)際上就兩步,new_video_stream()
?肯定會創(chuàng)建視頻的輸出流,還有視頻的編碼器實(shí)例。
公共參數(shù),就在?new_output_stream()
?函數(shù) 里面賦值了。
視頻相關(guān)的參數(shù),就在?new_video_stream()
?函數(shù)再賦值。
new_video_stream()
?跟?new_output_stream()
?函數(shù)都調(diào)用了多次?MATCH_PER_STREAM_OPT()
?宏函數(shù)來提取?OptionsContext
?的內(nèi)容,
MATCH_PER_STREAM_OPT()
?其實(shí)是?MATCH_PER_TYPE_OPT()
?的兄弟函數(shù),
#define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\ {\ int i;\ for (i = 0; i < o->nb_ ## name; i++) {\ char *spec = o->name[i].specifier;\ if (!strcmp(spec, mediatype))\ outvar = o->name[i].u.type;\ }\ }
#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);\ }
這兩個函數(shù),只有最后一個參數(shù),第四個參數(shù)是不一樣的。
mediatype 通常是 a 或者 v,也就是根據(jù) a 還是 v 字符來提取?OptionsContext
?里面音頻或者視頻的選項。
st 是 AVStream,所以如果?AVStream
?是音頻,就提取?OptionsContext
?里面的音頻選項,如果是視頻就提取視頻。
這兩個函數(shù)的宏實(shí)現(xiàn)看起來有點(diǎn)復(fù)雜,但他們的區(qū)別就是這么一點(diǎn)區(qū)別。
至此,new_video_stream()
?函數(shù)分析完畢。new_audio_stream()
?跟?new_video_stream()
?類似,里面都調(diào)了?new_output_stream()
?。
new_audio_stream()
?主要是提取OptionsContext
?里面音頻選項,對?OutputStream
?輸出流,以及?AVCodecContext
?編碼器 進(jìn)行賦值操作。
補(bǔ)充一點(diǎn):雖然?new_video_stream()
?里創(chuàng)建了 編碼器實(shí)例,但是還沒真正打開編碼器的。打開編碼器,需要等到解碼出第一幀 AVFrame。才會打開編碼器。
原因解析
因為 ffmpeg.exe 的邏輯,是只有在解碼出第一幀AVFrame的時候,才去用?avfilter_graph_config()
?打開 FilterGragh ,這樣才能從出口濾鏡讀取到 輸出的寬高是多少。
ffmpeg.exe
?比較謹(jǐn)慎,他可能不太相信容器層記錄的寬度,也有可能有些容器根本沒記錄寬高,所以他必須等到解碼出 AVFrame,才能確定輸入的寬高,確定了輸入的寬高,才能創(chuàng)建 buffer入口濾鏡,創(chuàng)建了入口濾鏡,才能打開?FilterGragh
?。
TODO:這個邏輯非常重要,在本章結(jié)尾的時候再重復(fù)講一次。
濾鏡出口里面獲取寬高
最后是在?init_output_stream_encode()
?里面,從濾鏡出口里面獲取的寬高,如下:
enc_ctx->width = av_buffersink_get_w(ost->filter->filter); enc_ctx->height = av_buffersink_get_h(ost->filter->filter); enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio
最后,推薦一下 clion 的 Call Hierarchy 功能,可以看到函數(shù)的調(diào)用流程,如下:
大部分的 集成開發(fā)環(huán)境都有這個功能,你只需用 “工具名稱” + Call Hierarchy 關(guān)鍵詞,即可搜索到相關(guān)教程。
原文鏈接:https://juejin.cn/post/7159423852345294861
相關(guān)推薦
- 2022-04-07 你知道怎么基于?React?封裝一個組件嗎_React
- 2022-06-18 python使用Random隨機(jī)生成列表的方法實(shí)例_python
- 2022-11-19 springboot整合使用云服務(wù)器上的Redis方法_Redis
- 2023-03-27 基于Unity3D實(shí)現(xiàn)仿真時鐘詳解_C#教程
- 2022-06-01 python中使用正則表達(dá)式的方法詳解_python
- 2023-07-07 React中useState的setState方法請求了好多次
- 2022-09-20 react-redux?action傳參及多個state處理的實(shí)現(xiàn)_React
- 2022-04-05 解決IDEA .properties文件中文亂碼的問題
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支