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

葉餘發表於2021-02-02

本文為作者原創,轉載請註明出處: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。

相關文章