1. 程式人生 > >FFmpeg libswscale原始碼分析2-轉碼命令列與濾鏡圖

FFmpeg libswscale原始碼分析2-轉碼命令列與濾鏡圖

本文為作者原創,轉載請註明出處: libswscale 原始碼分析系列文章: [1]. [FFmpeg libswscale原始碼分析1-API介紹](https://www.cnblogs.com/leisure_chn/p/14349382.html) [2]. [FFmpeg libswscale原始碼分析2-轉碼命令列與濾鏡圖](https://www.cnblogs.com/leisure_chn/p/14355015.html) [3]. [FFmpeg libswscale原始碼分析3-scale濾鏡原始碼分析](https://www.cnblogs.com/leisure_chn/p/14355017.html) [4]. [FFmpeg libswscale原始碼分析4-libswscale原始碼分析](https://www.cnblogs.com/leisure_chn/p/14355019.html) 原始碼分析基於 FFmpeg 4.1 版本。 ## 2. 轉碼命令列與濾鏡圖 本節從 ffmpeg 轉碼命令開始,引入一個完整的示例:hevc yuv422p10le 源軟解硬編為 hevc yuv420p10le 視訊。 第 2 節、第 3 節、第 4 節是由上到下分層的關係。第 2 節介紹命令列,通過命令列呼叫 ffmpeg 程序。第 3 節介紹 scale 濾鏡,ffmpeg 程序使用了 scale 濾鏡,scale 濾鏡中會呼叫 libswscale 庫。第 4 節介紹 libswscale 庫。 檢視 ffmpeg 中 hevc_nvenc 支援的畫素格式: ``` [root@node0 ~]# ffmpeg -hide_banner -h encoder=hevc_nvenc | grep "pixel formats" Supported pixel formats: yuv420p nv12 p010le yuv444p p016le yuv444p16le bgr0 rgb0 cuda ``` 在如下程式碼 for 迴圈處打斷點,分析濾鏡圖中的各個濾鏡輸入輸出畫素格式: ``` static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx) { AVFilterContext *filt; int i, ret; for (i = 0; i < graph->nb_filters; i++) { filt = graph->filters[i]; if (!filt->nb_outputs) { if ((ret = avfilter_config_links(filt))) return ret; } } return 0; } ``` 不顯式指定濾鏡的轉碼命令: ``` ffmpeg -hide_banner -y -re -i ./hevc_4k_422_10b_5994_60m_vibe.ts -c:v hevc_nvenc -preset fast -profile:v main10 -c:a aac -f mpegts /dev/null ``` 濾鏡圖如下: ``` yuv422p10le yuv422p10le yuv444p16le yuv444p16le [buffer] -----> [null] -----> [scale] -----> [format] -----> [buffersink] ``` ffmpeg 自動插入濾鏡,協商濾鏡格式。buffer 濾鏡輸出的格式是 ffmpeg hevc 解碼器解碼輸出的影象畫素格式,是 yuv422p10le。buffersink 濾鏡的輸入格式,是 ffmpeg 在 buffersink 濾鏡前插入 format 濾鏡,在執行 format 濾鏡初始化時,從 hevc_nvenc 編碼器支援的畫素格式列表中,選定了 yuv444p16le,作為編碼器的輸入格式。由 scale 濾鏡執行畫素格式轉換操作:yuv422p10le 轉為 yuv444p16le。 通過濾鏡指定格式 yuv420p10le: ``` ffmpeg -hide_banner -y -re -i ./hevc_4k_422_10b_5994_60m_vibe.ts -vf format=yuv420p10le -c:v hevc_nvenc -preset fast -profile:v main10 -c:a aac -f mpegts /dev/null ``` 濾鏡圖如下: ``` yuv422p10le yuv420p10le yuv420p10le p010le p010le [buffer] ------> [scale] ------> [format] ------> [scale] ------> [format] ------> [buffersink] ``` 第三個濾鏡 format 是我們在命令列中給出的濾鏡。第五個濾鏡 format 是編碼器輸入格式濾鏡,是 ffmpeg 在濾鏡圖與編碼器間進行畫素格式協商時,在 hevc_nvenc 編碼器支援的畫素格式列表中,選擇了 p010le 畫素格式作為編碼器的輸入格式,並在此 format 濾鏡前自動插入一個 scale 濾鏡執行畫素格式轉換。 可以看到,一個畫素格式轉換,在命令列中是由一個 scale 濾鏡緊跟一個 format 濾鏡實現的,scale + format 濾鏡可由使用者在命令中顯式給出,ffmpeg 也會根據實際情況按需插入。 通過濾鏡指定格式 p010le: ``` ffmpeg -hide_banner -y -re -i ./hevc_4k_422_10b_5994_60m_vibe.ts -vf format=p010le -c:v hevc_nvenc -preset fast -profile:v main10 -c:a aac -f mpegts /dev/null ``` 濾鏡圖如下: ``` yuv422p10le p010le p010le p010le [buffer] ------> [scale] ------> [format] ------> [format] ------> [buffersink] ``` 第三個濾鏡 format 是我們在命令列中給出的濾鏡。第四個濾鏡 format 是編碼器輸入格式濾鏡,是 ffmpeg 在濾鏡圖與編碼器間進行畫素格式協商時,在 hevc_nvenc 編碼器支援的畫素格式列表中,選擇了 p010le 畫素格式作為編碼器的輸入格式。第二個濾鏡 scale 執行實際的畫素格式轉換操作:yuv422p10le 轉 p0