網站首頁 編程語言 正文
new_video_stream()?函數流程
new_video_stream()
?函數的流程相對來說比較簡單,主要的邏輯如下:
1, 調?new_output_stream()
?函數來創建?OutputStream
?輸出流,以及?AVCodecContext
?編碼器上下文。
new_output_stream()
?是一個公共函數,創建 音頻流,數據流,字幕流都用了它。
new_output_stream()
?會把命令行的一些公共參數賦值給?OutputStream
?跟?AVCodecContext
。
這些公共參數是指音頻,視頻,字幕都可能會有的參數。因為?new_output_stream()
?是一個公共函數。
2, 調?MATCH_PER_STREAM_OPT()
?宏函數,把?OptionsContext
?里面視頻相關的參數,賦值給 給?OutputStream
?跟?AVCodecContext
。
流程圖
可以看到,實際上就兩步,new_video_stream()
?肯定會創建視頻的輸出流,還有視頻的編碼器實例。
公共參數,就在?new_output_stream()
?函數 里面賦值了。
視頻相關的參數,就在?new_video_stream()
?函數再賦值。
new_video_stream()
?跟?new_output_stream()
?函數都調用了多次?MATCH_PER_STREAM_OPT()
?宏函數來提取?OptionsContext
?的內容,
MATCH_PER_STREAM_OPT()
?其實是?MATCH_PER_TYPE_OPT()
?的兄弟函數,
#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);\ }
這兩個函數,只有最后一個參數,第四個參數是不一樣的。
mediatype 通常是 a 或者 v,也就是根據 a 還是 v 字符來提取?OptionsContext
?里面音頻或者視頻的選項。
st 是 AVStream,所以如果?AVStream
?是音頻,就提取?OptionsContext
?里面的音頻選項,如果是視頻就提取視頻。
這兩個函數的宏實現看起來有點復雜,但他們的區別就是這么一點區別。
至此,new_video_stream()
?函數分析完畢。new_audio_stream()
?跟?new_video_stream()
?類似,里面都調了?new_output_stream()
?。
new_audio_stream()
?主要是提取OptionsContext
?里面音頻選項,對?OutputStream
?輸出流,以及?AVCodecContext
?編碼器 進行賦值操作。
補充一點:雖然?new_video_stream()
?里創建了 編碼器實例,但是還沒真正打開編碼器的。打開編碼器,需要等到解碼出第一幀 AVFrame。才會打開編碼器。
原因解析
因為 ffmpeg.exe 的邏輯,是只有在解碼出第一幀AVFrame的時候,才去用?avfilter_graph_config()
?打開 FilterGragh ,這樣才能從出口濾鏡讀取到 輸出的寬高是多少。
ffmpeg.exe
?比較謹慎,他可能不太相信容器層記錄的寬度,也有可能有些容器根本沒記錄寬高,所以他必須等到解碼出 AVFrame,才能確定輸入的寬高,確定了輸入的寬高,才能創建 buffer入口濾鏡,創建了入口濾鏡,才能打開?FilterGragh
?。
TODO:這個邏輯非常重要,在本章結尾的時候再重復講一次。
濾鏡出口里面獲取寬高
最后是在?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 功能,可以看到函數的調用流程,如下:
大部分的 集成開發環境都有這個功能,你只需用 “工具名稱” + Call Hierarchy 關鍵詞,即可搜索到相關教程。
原文鏈接:https://juejin.cn/post/7159423852345294861
相關推薦
- 2022-06-11 嵌入式C語言二級指針在鏈表中的應用_C 語言
- 2023-10-11 lambda Collectors類的靜態工廠方法
- 2022-01-27 插入數據庫某個字段之前判斷是否重復
- 2022-05-06 Python學習之模塊化程序設計示例詳解_python
- 2022-07-30 jQuery?UI組件介紹_jquery
- 2023-01-13 python中的txt文件轉換為XML_python
- 2022-07-03 詳解Flutter中Dart集合使用教程_Android
- 2022-04-22 C#基于WinForm實現串口通訊_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支