本文為作者原創,轉載請註明出處:https://www.cnblogs.com/leisure_chn/p/14355015.html
libswscale 原始碼分析系列文章:
[1]. FFmpeg libswscale原始碼分析1-API介紹
[2]. FFmpeg libswscale原始碼分析2-轉碼命令列與濾鏡圖
[3]. FFmpeg libswscale原始碼分析3-scale濾鏡原始碼分析
[4]. FFmpeg libswscale原始碼分析4-libswscale原始碼分析
原始碼分析基於 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 轉 p010le。