開發者文件

目錄

1 簡介

本文與 FFmpeg 本身的開發有關。關於在其他程式中使用 FFmpeg 函式庫的資訊,可以在其他地方找到,例如在

如需關於在外部程式中使用 FFmpeg 的更詳細法律資訊,請閱讀原始碼樹中的 LICENSE 檔案,並參考 https://ffmpeg.dev.org.tw/legal.html

如果您為了自己的使用案例修改了 FFmpeg 程式碼,我們強烈建議您將您的變更回饋給我們,並以本文檔作為指南。這樣做既有務實的理由,也有理念上的理由

  • 維護外部變更以跟上上游開發進度既耗時又容易出錯。如果您的程式碼在主樹中,它將由 FFmpeg 開發人員維護。
  • FFmpeg 開發人員包括該領域的領先專家,他們可以找出您程式碼中的錯誤或設計缺陷。
  • 透過支持您認為有用的專案,您可以確保它持續得到維護和開發。

所有擬議的程式碼變更都應提交給 開發郵件列表 進行審核,詳情請參閱 提交補丁 章節。程式碼應符合 開發政策 並遵循 編碼規則。提交變更的開發人員和作者應對其變更負責,並應盡力修復其提交造成的任何問題。

2 編碼規則

2.1 語言

FFmpeg 主要以 ISO C11 語言編寫,但公共標頭檔必須保持與 C99 相容。

出於充分理由可以使用編譯器特定的擴充功能,但不應依賴它們,也就是說,程式碼仍然必須能夠在使用缺少擴充功能的編譯器時編譯和運作。

以下 C99 功能絕不能在程式碼庫中的任何地方使用

  • 可變長度陣列;
  • 複數;
  • 混合語句和宣告。

2.1.1 SIMD/DSP

由於現代編譯器無法從純 C 產生高效的 SIMD 或其他效能關鍵的 DSP 程式碼,因此使用了手寫組語。通常,此類程式碼會隔離在單獨的函式中。然後,標準方法是編寫此函式的多個版本 - 一個可在任何地方運作的純 C 版本,也可用於除錯,以及潛在的多個特定架構的最佳化實作。然後,初始化程式碼會在執行階段選擇最佳可用版本,並將其載入到函式指標中;然後始終透過此指標呼叫相關函式。

用於編寫組語的特定語法是

  • x86 上的 NASM;
  • ARM 和 RISC-V 上的 GAS。

用於組語的單元測試框架稱為 checkasm,位於 tests/checkasm 下。所有新的組語都應附帶 checkasm 測試;也強烈建議為缺少測試的現有組語新增測試。

2.1.2 其他語言

在特殊情況下可以使用 C 以外的其他語言

  • 當相關程式碼無法以 SIMD/DSP 區段中描述的標準方式編寫時,可以使用編譯器內建函式或內聯組語。這通常適用於需要內聯的程式碼。
  • 在需要與 macOS 特定介面互動時,可以使用 Objective-C。

2.2 程式碼格式慣例

以下是有關檔案中程式碼樣式的準則

  • 縮排大小為 4。
  • 在 Makefile 之外禁止使用 TAB 字元,以及任何形式的尾隨空格。包含任何一種情況的提交將被 git 儲存庫拒絕。
  • 您應該盡量將程式碼行限制在 80 個字元以內;但是,只有在這樣做可以提高可讀性的情況下才應如此。
  • 使用 K&R 編碼風格。

呈現方式受到 'indent -i4 -kr -nut' 的啟發。

2.2.1 範例

一些值得注意的範例,說明 FFmpeg 中常見的程式碼樣式

  • 在賦值運算符周圍以及 if/do/while/for 關鍵字後加空格
    // Good
    if (condition)
        av_foo();
    
    // Good
    for (size_t i = 0; i < len; i++)
        av_bar(i);
    
    // Good
    size_t size = 0;
    

    但是,括號和條件之間沒有空格,除非它可以幫助複雜條件的可讀性,因此不應執行以下操作

    // Bad style
    if ( condition )
        av_foo();
    
  • 沒有不必要的括號,除非它可以提高可讀性
    // Good
    int fields = ilace ? 2 : 1;
    
  • 單行區塊周圍沒有大括號
    // Good
    if (bits_pixel == 24)
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
    else if (bits_pixel == 8)
        avctx->pix_fmt = AV_PIX_FMT_GRAY8;
    else {
        av_log(avctx, AV_LOG_ERROR, "Invalid pixel format.\n");
        return AVERROR_INVALIDDATA;
    }
    
  • 在條件允許的情況下,避免在條件中賦值
    // Good
    video_enc->chroma_intra_matrix = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64)
    if (!video_enc->chroma_intra_matrix)
        return AVERROR(ENOMEM);
    
    // Bad style
    if (!(video_enc->chroma_intra_matrix = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64)))
        return AVERROR(ENOMEM);
    
    // Ok
    while ((entry = av_dict_iterate(options, entry)))
        av_log(ctx, AV_LOG_INFO, "Item '%s': '%s'\n", entry->key, entry->value);
    
  • 宣告指標變數時,* 與變數而不是類型相關聯
    // Good
    AVStream *stream;
    
    // Bad style
    AVStream* stream;
    

如果您處理的檔案未始終如一地遵循這些準則,請變更您正在編輯的部分以遵循這些準則,但不要對檔案進行不相關的變更以使其符合這些準則。

2.2.2 Vim 設定

為了設定 Vim 以遵循 FFmpeg 格式慣例,請將以下程式碼片段貼到您的 .vimrc

" indentation rules for FFmpeg: 4 spaces, no tabs
set expandtab
set shiftwidth=4
set softtabstop=4
set cindent
set cinoptions=(0
" Allow tabs in Makefiles.
autocmd FileType make,automake set noexpandtab shiftwidth=8 softtabstop=8
" Trailing whitespace and tabs are forbidden, so highlight them.
highlight ForbiddenWhitespace ctermbg=red guibg=red
match ForbiddenWhitespace /\s\+$\|\t/
" Do not highlight spaces at the end of line while typing on that line.
autocmd InsertEnter * match ForbiddenWhitespace /\t\|\s\+\%#\@<!$/

2.2.3 Emacs 設定

對於 Emacs,將以下大致等效的行新增到您的 .emacs.d/init.el

(c-add-style "ffmpeg"
             '("k&r"
               (c-basic-offset . 4)
               (indent-tabs-mode . nil)
               (show-trailing-whitespace . t)
               (c-offsets-alist
                (statement-cont . (c-lineup-assignments +)))
               )
             )
(setq c-default-style "ffmpeg")

2.3 註解

使用 JavaDoc/Doxygen 格式(請參閱以下範例),以便可以自動產生程式碼文件。所有重要的函式都應在其上方加上註解,說明該函式的作用,即使只是一句話。所有結構及其成員變數也應記錄在案。

避免使用 Qt 樣式和類似的 Doxygen 語法,其中包含 !,即將 //! 替換為 ///,依此類推。此外,標記命令應使用 @ 語法,即使用 @param 而不是 \param

/**
 * @file
 * MPEG codec.
 * @author ...
 */

/**
 * Summary sentence.
 * more text ...
 * ...
 */
typedef struct Foobar {
    int var1; /**< var1 description */
    int var2; ///< var2 description
    /** var3 description */
    int var3;
} Foobar;

/**
 * Summary sentence.
 * more text ...
 * ...
 * @param my_parameter description of my_parameter
 * @return return value description
 */
int myfunc(int my_parameter)
...

2.4 命名慣例

函式、變數和結構成員的名稱必須為小寫,並使用底線 (_) 分隔單字。例如,'avfilter_get_video_buffer' 是可接受的函式名稱,而 'AVFilterGetVideo' 則不是。

結構、聯合、列舉和 typedef 類型名稱必須使用 CamelCase。所有結構和聯合都應 typedef 為與結構/聯合標籤相同的名稱,例如 typedef struct AVFoo { ... } AVFoo;。列舉通常不進行 typedef。

列舉常數和巨集必須為大寫,但偽裝成函式的巨集除外,後者應使用函式命名慣例。

函式庫中的所有識別碼都應按如下方式命名空間

  • 對於檔案和較低範圍(例如,區域變數、靜態函式)以及結構和聯合成員的識別碼,不使用命名空間,
  • ff_ 前綴必須用於檔案範圍之外可見的變數和函式,但僅在單個函式庫內內部使用,例如 'ff_w64_demuxer'。這可以防止在靜態連結 FFmpeg 時發生名稱衝突。
  • 對於檔案範圍之外可見、在多個函式庫之間內部使用的變數和函式,請使用 avpriv_ 作為前綴,例如 'avpriv_report_missing_feature'。
  • 所有其他內部識別碼,例如私有類型或巨集名稱,都應僅進行命名空間化,以避免可能的內部衝突。例如,H264_NAL_SPSHEVC_NAL_SPS
  • 除了常用的 av_ 之外(libavformat 為 avformat_,libavcodec 為 avcodec_,libswresample 為 swr_ 等),每個函式庫都有其自己的公共符號前綴。檢查現有程式碼並相應地選擇名稱。
  • 其他公共識別碼(結構、聯合、列舉、巨集、類型名稱)必須使用其函式庫的公共前綴(AVSwsSwr)。

此外,不應侵犯系統保留的命名空間。以 _t 結尾的識別碼由 POSIX 保留。同時避免使用以 ___ 開頭後跟大寫字母的名稱,因為它們由 C 標準保留。以 _ 開頭的名稱在檔案層級保留,不得用於外部可見的符號。如有疑問,請避免使用以 _ 開頭的名稱。

2.5 其他慣例

  • 僅在必要時才應使用類型轉換。如果不使程式碼更容易理解,也應避免使用不必要的括號。

3 開發政策

3.1 程式碼行為

正確性

程式碼必須有效。它絕不能崩潰、中止、存取無效指標、洩漏記憶體、導致資料競爭或帶符號整數溢位,或以其他方式導致未定義的行為。應檢查錯誤碼,並在適用時轉發給呼叫者。

執行緒和函式庫安全性

我們的函式庫可能會被同一程序中的多個獨立呼叫者呼叫。這些呼叫可能來自任意數量的執行緒,並且不同的呼叫站點可能彼此不知道 - 例如,使用者程式可能直接呼叫我們的函式庫,並使用一個或多個也呼叫我們函式庫的函式庫。程式碼在這種情況下必須表現正確。

穩健性

程式碼必須將從呼叫者接收或從檔案、網路等讀取的任何位元組串流視為不受信任。當任意資料傳送給它時,它絕不能表現異常 - 通常,它應該在遇到無效輸入資料時列印錯誤訊息並傳回 AVERROR_INVALIDDATA

記憶體配置

程式碼必須使用 libavutil/mem.h 中的 av_malloc() 函式族來執行所有記憶體配置,除非在特殊情況下(例如,當與需要使用特定配置器的外部函式庫互動時)。

應檢查所有配置,並在失敗時傳回 AVERROR(ENOMEM)。一個常見的錯誤是錯誤路徑洩漏記憶體 - 確保不會發生這種情況。

stdio

我們的函式庫絕不能直接存取 stdio 串流 stdin/stdout/stderr(例如,透過 printf() 函式族),因為這不是函式庫安全的。對於記錄,請使用 av_log()

3.2 補丁/提交

補丁的授權必須與 FFmpeg 相容。

貢獻應根據 LGPL 2.1(包括「或任何更高版本」條款)或,如果您喜歡贈與式授權,則根據 ISCMIT 授權。包含「或任何更高版本」條款的 GPL 2 也可以接受,但首選 LGPL。如果您新增新檔案,請為其提供適當的授權標頭。不要從隨機位置複製並貼上它,請使用現有檔案作為範本。

您絕不能提交會破壞 FFmpeg 的程式碼!

這表示已啟用且會破壞編譯、或編譯但無法運作/破壞回歸測試的未完成程式碼。在某些情況下,可能會允許未完成但已停用的程式碼,例如缺少範例或功能子集較小的實作。在推送之前,始終檢查郵件列表以尋找任何有問題的審核者,並測試 FATE。

提交訊息

提交訊息是非常重要的工具,用於告知其他開發人員給定的變更的作用和原因。每個提交都必須始終具有正確填寫的提交訊息,格式如下

area changed: short 1 line description

details describing what and why and giving references.

如果提交解決了我們錯誤追蹤器或其他外部問題(例如 CVE)上的已知錯誤,則提交訊息應包含相關的錯誤 ID 或其他外部識別碼。請注意,這應該是除了適當的解釋之外完成的,而不是取代它。諸如「已修復!」或「已變更。」之類的註解是不可接受的。

在套用已在郵件列表上經過長時間討論的補丁時,請在提交訊息中參考該執行緒。

測試必須充分但不應過度。

如果它對您和其他人有效,並且通過了 FATE,那麼提交它應該可以,前提是它符合其他提交標準。您不必擔心過度測試。如果您的程式碼有問題(可移植性、觸發編譯器錯誤、異常環境等),它們將被報告並最終修復。

不要將不相關的變更一起提交。

應將它們分成獨立的部分。另外,不要忘記,如果 B 部分依賴於 A 部分,但 A 部分不依賴於 B 部分,那麼 A 部分可以並且應該先於 B 部分提交,並與 B 部分分開。將變更良好地分成獨立的部分,可以更輕鬆地在提交記錄郵件列表上審核和理解它們。這也有助於以後的除錯。此外,如果您對是否拆分有疑問,請隨時在開發人員郵件列表上詢問/討論。

外觀變更應保留在單獨的補丁中。

如果原始碼縮排和其他外觀變更與功能變更混合在一起,我們將拒絕,此類提交將被拒絕和移除。每個開發人員都有自己的縮排樣式,您不應變更它。當然,如果您(重新)編寫某些內容,您可以使用自己的樣式,即使我們希望整個 FFmpeg 的縮排風格保持一致(許多專案強制執行給定的縮排風格 - 我們沒有。)。如果您確實需要進行縮排變更(盡量避免這種情況),請將它們與實際變更嚴格分開。

注意:如果您必須在大型(> 5 行)程式碼區塊上放置 if(){ .. },那麼請勿變更內部部分的縮排(不要將其向右移動)!或在單獨的提交中執行此操作

歸功於補丁的作者。

確保正確設定提交的作者。(請參閱 git commit –author)如果您套用補丁,請回覆 ffmpeg-devel(或您從哪裡獲得補丁)說您已套用補丁。

歸功於任何研究人員

如果提交/補丁修復了某些研究人員發現的問題,請始終在提交訊息中歸功於研究人員發現/報告問題。

始終等待足夠長的時間再推送變更

未經許可,請勿提交給其他人積極維護的程式碼。將補丁發送到 ffmpeg-devel。如果在合理的時間範圍內(建置失敗和安全性修復為 12 小時,小變更為 3 天,大型補丁為 1 週)沒有人回覆,如果您認為可以,則提交您的補丁。另請注意,維護者可以簡單地要求更多時間進行審核!

3.3 程式碼

如果沒有其他選擇,可以停用正確程式碼的警告。

編譯器警告指示潛在的錯誤或樣式不良的程式碼。如果某種類型的警告始終指向正確且整潔的程式碼,則應停用該警告,而不是變更程式碼。因此,剩餘的警告可能是錯誤或正確的程式碼。如果是錯誤,則必須修復錯誤。如果不是,則應變更程式碼以不產生警告,除非這會導致速度減慢或程式碼變得難以理解。

3.4 函式庫公共介面

FFmpeg 中的每個函式庫都在其已安裝的標頭中提供一組公共 API,這些標頭在該函式庫的 Makefile 中的變數 HEADERS 中列出。這些標頭中定義的所有識別碼(除非另有明確說明)以及從編譯後的共享或靜態函式庫匯出的對應符號都被視為公共介面,並且必須符合本節中描述的 API 和 ABI 相容性規則。

公共 API 必須在給定的主要版本內向後相容。也就是說,任何有效的用戶程式碼,只要它使用給定的函式庫版本編譯和運作,就必須仍然能夠使用任何更高版本編譯和運作,只要主要版本號保持不變。「有效的用戶程式碼」在這裡是指以文件化和/或預期的方式呼叫我們的 API,並且不依賴於任何未定義行為的程式碼。增加主要版本可能會破壞向後相容性,但僅限於 主要版本號提升 中描述的範圍。

我們還保證共享和靜態函式庫的向後 ABI 相容性。也就是說,應該可以將我們的函式庫的共享或靜態建置版本替換為任何更高版本的建置版本(在靜態情況下重新連結用戶二進位檔),而不會破壞任何有效的用戶二進位檔,只要主要版本號保持不變。

3.4.1 新增介面

已安裝標頭中的任何新公共識別碼都被視為新的 API - 這包括新函式、結構、巨集、列舉值、typedef、現有結構中的新欄位、新的已安裝標頭等。新增新 API 時,請考慮以下準則。

動機

雖然可以相對輕鬆地新增新的 API,但由於上述相容性要求,變更或移除它們要困難得多。那麼,您應該仔細考慮您新增的功能是否真的需要作為新的公共 API 向我們的呼叫者公開。

您的新 API 應至少有一個在函式庫外部的完善使用案例,而這些案例無法透過現有 API 輕鬆實現。FFmpeg 中的每個函式庫也有一個定義的範圍 - 您的新 API 必須符合該範圍。

取代現有 API

如果您的新 API 正在取代現有的 API,則它應該嚴格優於現有的 API,以便使用新 API 的優勢超過呼叫者變更其程式碼的成本。新增新 API 後,您應該淘汰舊 API 並安排移除它,如 移除介面 中所述。

如果您認為現有的 API 有缺陷並想修復它,則在大多數情況下,首選方法是新增一個名稱不同的替代品,並淘汰現有的 API,而不是修改它。重要的是讓我們的呼叫者看到變更(例如,透過編譯或執行階段淘汰警告),並清楚說明如何轉換到新的 API(例如,在 Doxygen 文件中或在 wiki 上)。

API 設計

FFmpeg 函式庫被各種呼叫者用於執行各種多媒體相關的處理任務。因此,您應該在合理的範圍內,盡力為最廣泛的可行使用案例設計新的 API,並避免不必要地將其限制為特定類型的呼叫者(例如,僅限媒體播放或僅限轉碼)。

一致性

檢查 FFmpeg 中是否已存在類似的 API。如果存在,請嘗試根據它們對您的新增內容進行建模,以實現更好的整體一致性。

您的新識別碼的命名應遵循 命名慣例,並與其他類似的 API 對齊(如果適用)。

可擴充性

您還應該考慮如何在未來以向後相容的方式擴充您的 API。如果您要新增新的結構 AVFoo,標準方法是要求呼叫者始終透過建構函式(通常命名為 av_foo_alloc())配置它。這樣,新的欄位可以新增到結構的末尾,而不會破壞 ABI 相容性。通常,您還需要一個解構函式 - av_foo_free(AVFoo**),它會釋放間接提供的物件(及其內容,如果適用),並將 NULL 寫入提供的指標,從而消除呼叫者記憶體中潛在的懸空指標。

如果您要新增新的函式,請考慮是否可能需要在未來調整其行為 - 您可能想要新增一個標誌引數,即使它最初未被使用。

文件

所有新的 API 都必須記錄為 Doxygen 格式的註解,位於您新增到公共標頭的識別碼上方。您還應該在 doc/APIchanges 中簡要提及變更。

提升版本號

向後不相容的 API 或 ABI 變更需要增加(提升)主要版本號,如 主要版本號提升 中所述。主要版本號提升是重要的事件,會按計畫發生 - 因此,如果您的變更嚴格要求進行主要版本號提升,您應該將其新增到 #if 預處理器防護下,以在下一次主要版本號提升發生之前停用它。

可以在不破壞 API 或 ABI 相容性的情況下新增的新 API 需要提升次要版本號。

增加第三個(微型)版本元件表示值得注意的二進位相容變更(例如,對解碼器很重要的編碼器錯誤修復)。第三個元件始終從 100 開始,以區分 FFmpeg 和 Libav。

3.4.2 移除介面

由於上述相容性保證,移除 API 是一個複雜的過程,僅應在有充分理由的情況下進行。通常,有缺陷、限制性或以其他方式不足的 API 會被更優越的 API 取代,儘管有時我們會在沒有任何替代品的情況下移除 API(例如,當它提供的功能被認為不值得維護工作、超出專案範圍、從根本上存在缺陷等時)。

移除分為兩個步驟 - 首先,API 被淘汰並安排移除,但仍然存在且功能正常。第二步是實際移除 API - 這在 主要版本號提升 中描述。

要淘汰 API,您應該向我們的用戶發出訊號,表明他們應該停止使用它。例如,如果您打算移除結構成員或函式,則應使用 attribute_deprecated 標記它們。當無法做到這一點時,可能會在執行階段偵測到已淘汰 API 的使用情況並列印警告(但請注意不要太頻繁地列印它)。您還應該在相關的 Doxygen 文件區塊中記錄淘汰(以及替代品,如果適用)。

最後,您應該定義一個淘汰防護,類似於 libavbar/version_major.hlibavutil 的情況下為 version.h)中的 #define FF_API_<FOO> (LIBAVBAR_VERSION_MAJOR < XX)(其中 XX 是將移除 API 的主要版本)。然後將所有已淘汰 API 的使用都包裝在 #if FF_API_<FOO> .... #endif 中,以便程式碼在主要版本達到 XX 後自動停用。您也可以使用 FF_DISABLE_DEPRECATION_WARNINGSFF_ENABLE_DEPRECATION_WARNINGS 來抑制這些防護內部的編譯器淘汰警告。您應該測試程式碼在防護巨集評估為 true 和 false 時都能編譯和運作。

3.4.3 主要版本號提升

主要版本號提升表示 API 和/或 ABI 相容性中斷。為了減少對需要調整其程式碼的呼叫者的負面影響,主要版本號提升期間的向後不相容變更應限制為

  • 移除先前淘汰的 API。
  • 執行 ABI 而非 API 破壞性變更,例如重新排序結構內容。

3.5 文件/其他

訂閱 ffmpeg-devel 郵件列表。

訂閱 ffmpeg-devel 郵件列表非常重要。幾乎任何重要的補丁都應發送到那裡進行審核。其他開發人員可能會對您的貢獻發表評論。我們希望您看到這些評論,並在要求時改進它。(注意:經驗豐富的提交者有其他管道,有時可能會跳過對瑣碎修復的審核。)此外,其他開發人員在此處關於錯誤修復和 FFmpeg 改進的討論可能對您有所幫助。最後,透過成為列表訂閱者,您的貢獻將立即發布到列表,而無需非訂閱者訊息所經歷的審核保留。

但是,對於專案而言,我們收到您的補丁比您訂閱 ffmpeg-devel 列表更重要。如果您有補丁,並且不想訂閱和討論補丁,那麼無論如何請將其發送到列表。

訂閱 ffmpeg-cvslog 郵件列表。

所有提交的差異都會發送到 ffmpeg-cvslog 郵件列表。一些開發人員閱讀此列表以審核來自所有來源的所有程式碼庫變更。訂閱此列表不是強制性的。

保持文件為最新狀態。

如果您變更行為或新增功能,請更新文件。如果您不確定如何最好地執行此操作,請將補丁發送到 ffmpeg-devel,文件維護者將審核並提交您的內容。

重要的討論應可供所有人存取。

盡量將重要的討論和請求(也)保留在公共開發人員郵件列表上,以便所有開發人員都能從中受益。

檢查您在 MAINTAINERS 中的條目。

確保您維護的程式碼庫的任何部分都沒有從 MAINTAINERS 檔案中遺失。如果缺少您想要維護的內容,請在其後新增您的姓名。如果在某個時候您不再想維護某些程式碼,請幫助尋找新的維護者,並且不要忘記更新 MAINTAINERS 檔案。

我們認為我們的規則不太難。如果您有任何意見,請與我們聯絡。

4 提交補丁

首先,如果您尚未閱讀,請閱讀上面的 編碼規則,尤其是關於補丁提交的規則。

當您提交補丁時,請使用 git format-patchgit send-email。我們無法讀取其他差異 :-)。

另請不要提交包含多個不相關變更的補丁。將其分成單獨的、獨立的部分。這並不意味著逐個檔案拆分。相反,在盡可能保持補丁小的同時,使其保持為包含單個變更的邏輯單元,即使它跨越多個檔案。這使我們更容易審核您的補丁,並大大提高您的補丁被套用的機會。

使用 FFmpeg 的 patcheck 工具檢查您的補丁。該工具位於 tools 目錄中。

在提交補丁之前執行 回歸測試,以驗證它是否不會導致意外問題。

如果您告訴我們補丁的作用(例如「將 lrint 替換為 lrintf」)以及原因(例如「*BSD 不符合 C99 標準,並且沒有 lrint()」),也會有很大幫助

此外,如果您發送多個補丁,請將每個補丁作為單獨的郵件發送,不要將多個不相關的補丁附加到同一封郵件。

補丁應發佈到 ffmpeg-devel 郵件列表。盡可能使用 git send-email,因為它可以正確發送補丁,而無需額外注意。如果您無法使用,則將補丁作為 base64 編碼的附件發送,這樣您的補丁就不會在傳輸過程中被損壞。另請確保使用正確的 mime 類型(text/x-diff 或 text/x-patch 或至少 text/plain),並且每封郵件僅內聯或附加一個補丁。您可以檢查 https://patchwork.ffmpeg.org,如果您的補丁未顯示,則可能是其 mime 類型錯誤。

如何設定 git send-email?

請參閱 https://git-send-email.io/。對於 gmail,另請參閱 https://shallowsky.com/blog/tech/email/gmail-app-passwds.html

從電子郵件用戶端發送補丁

並非所有人可能都希望使用 git send-email。以下技巧允許以安全的方式透過電子郵件用戶端發送補丁。它已在 Outlook 和 Thunderbird(使用 X-Unsent 擴充功能)中測試過,並且可能適用於其他應用程式。

像這樣建立您的補丁

git format-patch -s -o "outputfolder" --add-header "X-Unsent: 1" --suffix .eml --to ffmpeg-devel@ffmpeg.org -1 1a2b3c4d

現在您只需要使用電子郵件應用程式開啟 eml 檔案並執行「發送」。

審核

您的補丁將在郵件列表上進行審核。您可能會被要求進行一些變更,並期望您提交一個改進的版本,其中包含審核中的請求。此過程可能會經歷多次迭代。一旦您的補丁被認為足夠好,一些開發人員將會選擇它並將其提交到官方 FFmpeg 樹。

給我們幾天時間做出反應。但如果經過一段時間沒有反應,請發送電子郵件提醒。您的補丁最終應該會得到處理。

5 新編解碼器或格式檢查清單

  1. 您是否為編解碼器初始化和關閉函式使用了 av_cold?
  2. 您是否在 AVCodec 或 AVInputFormat/AVOutputFormat 結構中為 NULL_IF_CONFIG_SMALL 新增了 long_name?
  3. 您是否在 libavcodec/version.hlibavformat/version.h 中提升了次要版本號(並重設了微型版本號)?
  4. 您是否已在 allcodecs.callformats.c 中註冊它?
  5. 您是否已將 AVCodecID 新增到 codec_id.h?新增新的編解碼器 ID 時,也請在 libavcodec/codec_desc.c 中的編解碼器描述符列表中新增條目。
  6. 如果它有 FourCC,您是否已將其新增到 libavformat/riff.c,即使它只是解碼器?
  7. 您是否已在 Makefile 中新增規則以編譯適當的檔案?即使您只是將格式新增到已由其他某些規則編譯的檔案(例如原始解多工器),也請記住執行此操作。
  8. 您是否已在 doc/general_contents.texi 中支援的格式或編解碼器表格中新增條目?
  9. 您是否已在 Changelog 中新增條目?
  10. 如果它依賴於剖析器或函式庫,您是否已在 configure 中新增該依賴項?
  11. 您是否在提交之前 git add 了適當的檔案?
  12. 您是否確保它可以獨立編譯,即使用 configure --disable-everything --enable-decoder=foo(或 --enable-demuxer 或您的元件是什麼)?

6 補丁提交檢查清單

  1. 套用補丁後,make fate 是否通過?
  2. 補丁是否使用 git format-patch 或 send-email 產生?
  3. 您是否簽署了您的補丁? (git commit -s) 有關簽署的含義,請參閱 簽署您的工作
  4. 您是否提供了清晰的 git 提交記錄訊息?
  5. 補丁是否針對最新的 FFmpeg git master 分支?
  6. 您是否訂閱了 ffmpeg-devel?(由於垃圾郵件,該列表僅限訂閱者)
  7. 您是否已檢查變更是否為最小,以便無法透過更小的補丁和/或更簡單的最終程式碼實現相同的目的?
  8. 如果變更是為了加速關鍵程式碼,您是否對其進行了基準測試?
  9. 如果您進行了任何基準測試,您是否在郵件中提供了它們?
  10. 您是否已檢查補丁是否不會引入緩衝區溢位或其他安全性問題?
  11. 您是否針對損壞的資料測試了您的解碼器或解多工器?如果沒有,請參閱 tools/trasher、noise 位元串流篩選器和 zzuf。當饋送損壞的資料時,您的解碼器或解多工器不應崩潰、陷入(接近)無限迴圈或配置過多的記憶體。
  12. 您是否已針對範例檔案測試了您的解碼器或解多工器?範例可以在 https://samples.ffmpeg.org 取得。
  13. 補丁是否未混合功能性變更和外觀變更?
  14. 您是否在程式碼中新增了 Tab 或尾隨空格?這兩者都是禁止的。
  15. 補丁是否附加到您發送的電子郵件?
  16. 補丁的 mime 類型是否正確?它應該是 text/x-diff 或 text/x-patch 或至少 text/plain,而不是 application/octet-stream。
  17. 如果補丁修復了錯誤,您是否提供了錯誤的詳細分析?
  18. 如果補丁修復了錯誤,您是否提供了足夠的資訊,包括範例,以便可以重現錯誤並驗證修復?請注意,請勿將 >100k 的範例附加到郵件,而是提供 URL,您可以上傳到 https://streams.videolan.org/upload/
  19. 您是否提供了關於補丁變更內容的詳細摘要?
  20. 您是否提供了關於它為何如此變更的詳細解釋?
  21. 您是否提供了關於如果套用補丁,用戶可見的優缺點的詳細摘要?
  22. 您是否提供了一個範例,以便我們可以輕鬆驗證補丁新增的新功能?
  23. 如果您新增了新檔案,您是否插入了授權標頭?它應該從 FFmpeg 中取得,而不是隨機複製並從其他地方貼上。
  24. 只要這樣做不會破壞 API/ABI 相容性,您就應該在按字母順序排列的列表中保持字母順序。
  25. 當垂直對齊具有相似內容的行可以提高可讀性時,應垂直對齊它們。
  26. 考慮為您的程式碼新增回歸測試。所有新模組都應經過測試涵蓋。這包括解多工器、多工器、解碼器、編碼器、濾波器、位元串流濾波器、剖析器。如果無法做到這一點,請在您的補丁集中新增一個解釋原因,如果有原因則可以不進行測試。
  27. 如果您新增了 NASM 程式碼,請檢查在使用 –disable-x86asm 的情況下,程式碼是否仍然有效。
  28. 使用 valgrind 和或 Address Sanitizer 測試您的程式碼,以確保它沒有洩漏、陣列越界存取等問題。

7 補丁審核流程

發佈到 ffmpeg-devel 的所有補丁都將被審核,除非它們包含明確的註解,說明該補丁不適用於 git master 分支。審核和評論將作為對郵件列表上補丁的回覆發佈。然後,補丁提交者必須處理每個評論,這可以透過重新提交變更後的補丁或透過討論來完成。重新提交的補丁本身將像任何其他補丁一樣被審核。如果在某個時候補丁通過審核且沒有任何評論,則表示已批准,對於簡單且小的補丁,可能會立即發生這種情況,而對於大型補丁,通常必須變更和審核多次才能獲得批准。補丁獲得批准後,將提交到儲存庫。

我們將審核所有提交的補丁,但有時我們非常忙,因此對於大型補丁,這可能需要幾週時間。

如果您覺得審核過程太慢,並且您願意嘗試接管您變更的程式碼區域的維護責任,那麼只需複製 git master 並在那裡維護程式碼區域即可。我們將從維護最佳的每個區域合併。

重新提交補丁時,請勿進行任何與審核期間收到的評論無關的重大變更。此類補丁將被拒絕。相反,請將重大變更或新功能作為單獨的補丁提交。

歡迎所有人審核補丁。此外,如果您正在等待審核您的補丁,請考慮幫助審核其他補丁,這是讓每個人的補丁更快獲得審核的好方法。

8 回歸測試

在提交補丁(或提交到儲存庫)之前,您至少應測試一下您是否沒有破壞任何內容。

執行 'make fate' 可以完成此操作,請參閱 fate.html 以取得詳細資訊。

[當然,某些補丁可能會變更回歸測試的結果。在這種情況下,應相應地修改回歸測試的參考結果]。

8.1 將檔案新增至 fate-suite 資料集

如果您需要上傳範例,請發送郵件至 samples-request。

當沒有可用的多工器或編碼器來產生特定測試的測試媒體時,媒體必須包含在 fate-suite 中。首先,請確保範例檔案盡可能小,以便充分測試各自的解碼器或解多工器。大型檔案會增加網路頻寬和磁碟空間需求。一旦您有了可運作的 fate 測試和 fate 範例,請在提交訊息或您發佈到 ffmpeg-devel 郵件列表的補丁系列的介紹訊息中,提供下載範例媒體的直接連結。

8.2 可視化測試覆蓋率

FFmpeg 建置系統允許使用覆蓋率工具 gcov/lcov 以簡單的方式可視化測試覆蓋率。這涉及以下步驟

  1. 配置為啟用檢測編譯:configure --toolchain=gcov
  2. 手動或透過 FATE 執行您的測試案例。這可以是完整的 FATE 回歸套件,也可以是 FFmpeg 提供的任何前端工具的任何任意調用,以任何組合形式。
  3. 執行 make lcov 以產生 HTML 格式的覆蓋率資料。
  4. 在您偏好的 HTML 檢視器中檢視 lcov/index.html

您可以使用命令 make lcov-reset 來重設覆蓋率測量。您需要在執行新測試後重新執行 make lcov

8.3 使用 Valgrind

configure 指令碼提供了一個使用 valgrind 來發現與記憶體處理相關的錯誤的快捷方式。只需將選項 --toolchain=valgrind-memcheck--toolchain=valgrind-massif 新增到您的 configure 行,並且將為在 valgrind 套件的 memcheckmassif 工具的監督下執行 FATE 設定合理的預設值。

如果您需要更精細地控制 valgrind 的調用方式,請在您的 configure 行中使用 --target-exec='valgrind <your_custom_valgrind_options> 選項。

9 維護流程

9.1 維護者 (MAINTAINERS)

維護程式碼庫每個部分的開發人員都列在 MAINTAINERS 中。列在 MAINTAINERS 中,使某人有權對特定儲存庫具有 git 寫入權限。

9.2 成為維護者

人們透過像任何其他程式碼變更一樣發送補丁將自己新增到 MAINTAINERS 中。這些像任何其他補丁一樣接受社群審核。預計如果有人反對新的維護者,她願意公開以全名反對,並願意接管該區域的維護責任。

10 發布流程

FFmpeg 維護一組發布分支,這些分支是系統整合商和發行商(例如 Linux 發行版等)的建議交付物。發布管理員定期準備、測試並在 https://ffmpeg.dev.org.tw 網站上發布 tarball。

有兩種發布類型

  1. 主要版本始終包含最新和最棒的功能。
  2. 次要版本是從發布分支中剪切出來的,發布分支的名稱為 release/X,其中 X 是發布版本號。

請注意,我們向用戶承諾,來自任何 FFmpeg 發行版本的共享函式庫絕不會破壞針對同一發行系列的先前版本編譯的程式!

但是,我們不時會進行 API 變更,這些變更需要在應用程式中進行調整。此類變更僅允許在(新的)主要版本中進行,並且需要進一步的步驟,例如提升函式庫版本號和/或調整符號版本控制檔案。請及時在 ffmpeg-devel 郵件列表上討論此類變更,以便進行提前規劃。

10.1 次要版本發布標準

符合以下標準的變更是有資格納入次要版本的候選者

  1. 修復安全性問題,最好由 http://cve.mitre.org/ 發布的 CVE 編號識別。
  2. 修復 https://trac.ffmpeg.org 中記錄的錯誤。
  3. 改進包含的文件。
  4. 與同一發布分支的先前次要版本保持原始碼和二進位相容性。

檢查規則的順序為 (1 或 2 或 3) 且 4。

10.2 發布檢查清單

發布流程涉及以下步驟

  1. 確保 RELEASE 檔案包含即將發布的版本號。
  2. https://trac.ffmpeg.org/admin/ticket/versions 新增發布版本。
  3. 向郵件列表宣告發布意圖。
  4. 確保所有相關的安全性修復都已向後移植。請參閱 https://ffmpeg.dev.org.tw/security.html
  5. 確保 FATE 回歸套件仍然在發布分支中通過,至少在 i386amd64 上(參見 回歸測試)。
  6. 準備 bz2gz 格式的發布 tarball,以及包含 gpg 簽名的補充檔案
  7. https://ffmpeg.dev.org.tw/releases 發布 tarball。建立並推送形式為 nX 的帶註釋標籤,其中 X 包含版本號。
  8. 提出並向 ffmpeg-devel 郵件列表發送一個包含網站新聞條目的補丁。
  9. 發布新聞條目。
  10. 向郵件列表發送公告。

本文件於 2025 年 1 月 21 日使用 makeinfo 產生。

託管由 telepoint.bg 提供