FFmpeg-4.0 的filter機制的架構與實現.之二 結構體關係與定義
4. Filter的結構體關係圖與定義
4.1 結構體間的關係圖
filter涉及的結構體,主要包括:
> FilterGraph, AVFilterGraph
> InputFilter, InputStream, OutputFilter, OutputStream
> AVFilter, AVFilterContext
> AVFilterLink
> AVFilterPad;
它們之間的類關係如下圖所示:
圖5:濾鏡結構體關係圖
從上圖可以看到,FFmpeg的濾鏡相關的結構體三層組成:
1) filtergraph層
由結構體 FilterGraph, AVFilterGraph組成;
其中,
FilterGraph, 包含一個InputFilter, 它指示了整個Graph的第一個濾鏡,並指示了InputStream, 從而作為整個Graph的輸入;
包含一個OutputFilter, 它指示了整個Graph的最後一個濾鏡,並指示了OutputStream,從而作為整個Graph的輸出;
包含一個AVFilterGraph的例項,它指示的是組成本graph的filter;
2) filterchain層
它由AVFilter, AVFilterContext, AVFilterLink, AVFilterPad組成;
其中,AVFilterContext是AVFilter的例項;
而filter之間是用 AVFilterLink進行連線,意思是,濾鏡之間並不是直接相連的,是通過AVFilterLink進行連線;
AVFilterContext 通過AVFilterLink進行連線後,就組成了Filterchain。
而AVFilterContext與AVFilterLink之間的AVFilterPad是直接相連的,對應的關係是
AVFilterContext的output_pad 連線它下游AVFilterLink的 srcpad;
AVFilterContext的input_pad 連線它上游AVFilterLink的 dstpad;
3) filter層
由AVFilterContext, AVFilterPad組成;
其中AVFilterContext是真正進行資料處理的濾鏡實體;
AVFilterPad用於AVFilterContext之間的callback(回撥):
第一個AVFilterContext的outputs[0]指標,指向第一個AVFilterLink,這個AVFilterLink的dst指標,指向第二個AVFilterContext。
如果在前一個AVFilterContext呼叫 outputs[0]->dstpad->filter_frame(Frame* input_frame1),
那其實就意味著,第一個過濾器,可以把處理好的一個frame(名字為input_frame1),可以通過這個呼叫,傳遞給第二個過濾器的input_pads的filter_frame函式。
而第二個過濾器,裡面就是使用者自己實現的filter_frame(),以對資料進行處理;
以 ./ffmpeg_g -i INPUT.mp4 -vn -acodec libfdk_aac -filter_complex "aresample=osf=s16,denoise" -ar 16000 -ac 1 -y OUTPUT.mp4 為例:
它們的實際資料流程如下圖所示:
圖6:-filter_complex "aresample=osf=s16,denoise"的濾鏡例項圖
從上圖可以看到,雖然我們只使用了兩個濾鏡,但構建出來的filterchain實際上包含有:五個filter, 和四個link;
是因為ffmpeg系統會自動為使用者設定的濾鏡新增上必要的輸入、輸出濾鏡,並將它們連線起來,組成一個完整的filterchain;
其中,ffmpeg預設是有3個filter的!分別是 "graph_0_in_0_0","format_out_0_0", "out_0_0"
它們對應的濾鏡型別是: “buffersrc”, “format”, “buffersink”。
它們對應的原始碼位於: libavfilter/buffersrc.c libavfilter/vf_format.c(對應視訊格式) libavfilter/format.c(對應音訊格式) , libavfilter/buffersink.c
上圖中:
藍色和綠色連線 是 AVFilterContext 與 AVFilterLink的連線關係 ;
紅色連線 是 AVFilterPad的連線關係;
灰色連線 是 組成AVFilterGraph的AVFilterContext;
上圖中,上半部分是filtergraph層:
左邊連線的是InputFilter,用來引入filtergraph的輸入流;
右邊連線的是OutputFilter,用來匯出filtergraph的輸出流;
並且指示了組成本filtergraph的所有filter;
上圖中,下半部分是filterchain層:
AVFilterContext與AVFilterLink是一種雙向連結串列指標的關係,見圖左的藍色和綠色連線所示;
即 AVFilterContext的 outputs 指向 它的下游 AVFilterLink;
而 下游的AVFilterLink的 src 批向它上游的 AVFilterContext;
4.2 FilterGraph 濾鏡圖結構體定義
typedef struct FilterGraph {
int index;
const char *graph_desc;
AVFilterGraph *graph; // 指向它的例項
int reconfiguration;
InputFilter **inputs;
int nb_inputs;
OutputFilter **outputs;
int nb_outputs;
} FilterGraph;
4.3 AVFilterGraph 濾鏡圖結構體定義
typedef struct AVFilterGraph {
const AVClass *av_class;
AVFilterContext **filters; // 本 濾鏡圖 包含的所有 filter, 包括系統自生成的
unsigned nb_filters;
char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters
#if FF_API_LAVR_OPTS
attribute_deprecated char *resample_lavr_opts; ///< libavresample options to use for the auto-inserted resample filters
#endif
/**
* Type of multithreading allowed for filters in this graph. A combination
* of AVFILTER_THREAD_* flags.
*
* May be set by the caller at any point, the setting will apply to all
* filters initialized after that. The default is allowing everything.
*
* When a filter in this graph is initialized, this field is combined using
* bit AND with AVFilterContext.thread_type to get the final mask used for
* determining allowed threading types. I.e. a threading type needs to be
* set in both to be allowed.
*/
int thread_type;
/**
* Maximum number of threads used by filters in this graph. May be set by
* the caller before adding any filters to the filtergraph. Zero (the
* default) means that the number of threads is determined automatically.
*/
int nb_threads;
/**
* Opaque object for libavfilter internal use.
*/
AVFilterGraphInternal *internal;
/**
* Opaque user data. May be set by the caller to an arbitrary value, e.g. to
* be used from callbacks like @ref AVFilterGraph.execute.
* Libavfilter will not touch this field in any way.
*/
void *opaque;
/**
* This callback may be set by the caller immediately after allocating the
* graph and before adding any filters to it, to provide a custom
* multithreading implementation.
*
* If set, filters with slice threading capability will call this callback
* to execute multiple jobs in parallel.
*
* If this field is left unset, libavfilter will use its internal
* implementation, which may or may not be multithreaded depending on the
* platform and build options.
*/
avfilter_execute_func *execute;
char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions
/**
* Private fields
*
* The following fields are for internal use only.
* Their type, offset, number and semantic can change without notice.
*/
AVFilterLink **sink_links;
int sink_links_count;
unsigned disable_auto_convert;
} AVFilterGraph;
4.4. 視訊濾鏡型別的巨集定義
/**
* 濾鏡輸入源的個數不能單由成員變數 AVFilter.inputs 來確定。
* 即依賴於 options 的支援與否,這個濾鏡在初始化時可以新增額外的輸入源;
*/
#define AVFILTER_FLAG_DYNAMIC_INPUTS (1 << 0)
/**
* 濾鏡輸出目的的個數不能單由成員變數 AVFilter.outputs來確定。
* 即依賴於 options 的支援與否,這個濾鏡在初始化時可以新增額外的輸出目的
*/
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
/**
* 這個濾鏡通過將一幀劃分成多個部分,然後使用多執行緒來並行處理它們;
*/
#define AVFILTER_FLAG_SLICE_THREADS (1 << 2)
/**
* 有些濾鏡支援一個一般意義上的"enable"表示式選項。它可以用來在時間軸上開啟或關閉濾鏡。
* 如果濾鏡支援這個選項就是設定這個標誌。
* 當 enable 表示式為假時,預設的無操作的 filter_frame()函式將被呼叫,它會替換掉在每個輸入pad上定義的回撥函式 filter_frame();
* 因此,這一幀不做任何處理地透傳到下一個濾鏡;
*/
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC (1 << 16)
/**
* 和 AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC一樣,
* 有些濾鏡希望在 enable表示式為假時,呼叫自己的 filter_frame()回撥函式。
* 例如,依據AVFilterCOntext->is_disable值,這個濾鏡會使用它自己的filter_frame()回撥來關閉它的處理。
*/
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17)
/**
* 用來測試濾鏡是否支援時間軸功能(internally or generically)的掩碼
*/
#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL)
4.5. AVFilter 結構體定義詳解
/**
* 濾鏡定義。
* 它定義了濾鏡與外部進行互動的pad(管腳,這個概念來自整合電腦,表示濾鏡和外部互動的介面),
* 以及和本濾鏡進行互動的所有回撥函式;
*/
typedef struct AVFilter {
/* 濾鏡名。必須是非空且唯一的; */
const char *name;
/* 濾鏡的描述,可以為空。 */
const char *description;
/**
* Pad : 輸入Pad列表,以零元素結束, 它是和它的上一個AVFilterLink的 dstpad 相連的;
* 如果沒有(靜態的)輸入,則將其設定為空。
* 如果濾鏡是 AVFILTER_FLAG_DYNAMIC_INPUTS 型別的例項,則在這個列表中可能有多個輸入
*/
const AVFilterPad *inputs;
/**
* Pad : 輸出Pad列表,以零元素結束, 它是和它的下一個AVFilterLink的 srcpad 相連的;
* 如果沒有(靜態的)輸出,則將其設定為空。
* 如果濾鏡是 AVFILTER_FLAG_DYNAMIC_OUTPUTS 型別的例項,則在這個列表中可能有多個輸出
*/
const AVFilterPad *outputs;
/**
* 私有資料類,用於宣告濾鏡私有的 AVoptions 結構體;
* 如果濾鏡沒有任何可選項則將這個值初始化為NULL;
* 如果這個值不為空,那麼濾鏡私有資料的第一個成員變數必須是 AVClass指標;
*/
const AVClass *priv_class;
/**
* 濾鏡型別標誌 , 其值為 AVFILTER_FLAG_* 巨集定義
*/
int flags;
/*****************************************************************
* 下面的變數不是公開的API,它們不能被libavfilter的外部使用
*****************************************************************/
/**
* 回撥函式: 濾鏡預初始化函式
* 當濾鏡的 context 被分配後,將立即呼叫這個回撥函式,來分配空間和初始化子物件。
* 如果 這個回撥函式不為空, 當遇到空間分配失敗時將呼叫 uninit 回撥函式;
* 返回值: 0, 表示成功
* AVERROR,表示失敗,但是這個錯誤碼會被刪除,並被呼叫程式碼視為 ENOMEM 。
*/
int (*preinit)(AVFilterContext *ctx);
/**
* 回撥函式: 濾鏡初始化函式
* 在濾鏡的整個生命週期中,這個回撥函式只會在 所有可選項被設定後,濾鏡鏈建立及格式協調之前 被呼叫 一次。
* 濾鏡本身的基本初始化可以放在這裡,
* ----- 意思是隻是初始化濾鏡本身的狀態,結構體,及本濾鏡專用的引數(如輸入引數再計算得到的引數)可以放在這裡;
* 如果 這些初始化需要使用到本濾鏡外的(如上下游濾鏡,系統)引數,則需要把這樣的初始化放在 config_input()中;
* NOTE:輸入引數的預設值是在 static const AVOption xxxx_options[] 中設定的,不需要再單獨設定;
*
* 如果濾鏡是多輸入/輸出型別的,那麼應該在這裡基於提供的可選項建立這些 inputs/outputs。
* 對於濾鏡來說,當這個回撥被呼叫後,就不能再有濾鏡的inputs/outputs的改變了。
*
* 這個回撥函式它假設濾鏡鏈是有效的,或者幀引數是有效的
* AVFilter.uninit 指標指向的 uninit 函式 保證了即使初始化失敗時 ,這個函式將會被呼叫 , 因此失敗時這個回撥函式不需要清空
*
* 返回值: 0, 表示成功; 負數AVERROR, 表示失敗。
*/
int (*init)(AVFilterContext *ctx);
/**
* Should be set instead of @ref AVFilter.init "init" by the filters that
* want to pass a dictionary of AVOptions to nested contexts that are
* allocated during init.
*
* On return, the options dict should be freed and replaced with one that
* contains all the options which could not be processed by this filter (or
* with NULL if all the options were processed).
*
* Otherwise the semantics is the same as for @ref AVFilter.init "init".
* 回撥函式: 這個變數是被濾鏡設定,用來代替 AVFilter.init "init" 回撥函式,
* 它會傳遞一個 AVOptions的字典 給 巢狀的 context (它是在初始化進分配的)
* 返回時,這個字典選項應當被釋放,且被一個包含所有選項的
*/
int (*init_dict)(AVFilterContext *ctx, AVDictionary **options);
/**
* 回撥函式: 濾鏡釋放函式 , 它必須在濾鏡釋放前僅呼叫一次。
* 在這個回撥函式中,應當釋放濾鏡的所有申請的記憶體,指標引用等。
* 但它不需要去釋放 AVFilterContext.priv 記憶體空間本身;
* 即便 AVFilter.init "init" 函式沒有被呼叫或呼叫失敗,這個函式也可能會被呼叫。
* 因此,它必須能處理這種情況
*/
void (*uninit)(AVFilterContext *ctx);
/**
* 回撥函式: 檢查本濾鏡輸入列表和輸出列表支援的格式。
* 它是在濾鏡初始化後(這時輸入列表和輸出列表都固定了),格式協商之前被呼叫。它可以被呼叫多次。
*
* 在這個回撥函式中, 必須對每一個輸入link 設定 AVFilterLink.out_formats, 對每一個輸出link 設定 AVFilterLink.in_formats,
* 列出這個濾鏡的link 支援的 畫素/樣本格式列表。
* 對於音訊 link, 這個濾鏡還需要設定的引數有:
* @ref AVFilterLink.in_samplerates "in_samplerates" /
* @ref AVFilterLink.out_samplerates "out_samplerates" and
* @ref AVFilterLink.in_channel_layouts "in_channel_layouts" /
* @ref AVFilterLink.out_channel_layouts "out_channel_layouts"
*
* 如果濾鏡只有一個輸入,那這個回撥函式可以設定為空,
* 在這種情況下, libavfilter假設它支援所有的輸入格式,並在輸出時保留它們
*
* 返回值: 0, 表示成功; 負數,對應為AVERROR 碼
*/
int (*query_formats)(AVFilterContext *);
int priv_size; ///< 濾鏡分配的私有資料的大小
int flags_internal; ///< avfilter內部使用的額外的標誌
/**
* 它是被濾鏡註冊系統使用的,任何其它程式碼都不需要去操作它
*/
struct AVFilter *next;
/**
* 讓濾鏡例項執行一個命令;
* 引數: cmd , 要執行的命令,為簡化處理,所有命令必須僅為字母數字;
* arg , 命令的引數
* res , 大小為 res_size的buffer, 用於存放濾鏡的返回。當命令不支援時,不需要改變它。
* flags , 如果設定為 AVFILTER_CMD_FLAG_FAST, 且這個命令是有時間消耗的時,這個濾鏡將會不執行命令
* 返回值: >=0, 表示成功。 否則為錯誤碼,其中,AVERROR(ENOSYS) 為濾鏡不支援這個命令
*/
int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);
/**
* 回撥函式: 濾鏡初始化函式,它用來替代 init()回撥函式。
* 引數中可以包含使用者提供的引數 : opaque是用於傳輸二進位制資料
*/
int (*init_opaque)(AVFilterContext *ctx, void *opaque);
/**
* Filter activation function.
*
* Called when any processing is needed from the filter, instead of any
* filter_frame and request_frame on pads.
*
* The function must examine inlinks and outlinks and perform a single
* step of processing. If there is nothing to do, the function must do
* nothing and not return an error. If more steps are or may be
* possible, it must use ff_filter_set_ready() to schedule another
* activation.
* 回撥函式: 濾鏡啟用函式
* 當有處理需要這個濾鏡時,就會呼叫這個函式。
*/
int (*activate)(AVFilterContext *ctx);
} AVFilter;
4.6 AVFilterContext 濾鏡例項的結構體
/** An instance of a filter */
struct AVFilterContext {
const AVClass *av_class; ///< needed for av_log() and filters common options
const AVFilter *filter; ///< 指明本例項是哪個AVFilter的例項
char *name; ///< 當前濾鏡例項的名稱
AVFilterPad *input_pads; ///< 輸入Pad的陣列 array of input pads
AVFilterLink **inputs; ///< 輸入link的指標陣列 array of pointers to input links
unsigned nb_inputs; ///< 輸入Pad的個數 number of input pads
AVFilterPad *output_pads; ///< 輸出Pad的陣列 array of output pads
AVFilterLink **outputs; ///< 輸出link的指標陣列 array of pointers to output links
unsigned nb_outputs; ///< 輸出Pad的個數 number of output pads
void *priv; ///< 本濾鏡使用的私有資料 private data for use by the filter
struct AVFilterGraph *graph; ///< 指明本濾鏡是屬於哪個filtergraph
/**
* Type of multithreading being allowed/used. A combination of
* AVFILTER_THREAD_* flags.
*
* May be set by the caller before initializing the filter to forbid some
* or all kinds of multithreading for this filter. The default is allowing
* everything.
*
* When the filter is initialized, this field is combined using bit AND with
* AVFilterGraph.thread_type to get the final mask used for determining
* allowed threading types. I.e. a threading type needs to be set in both
* to be allowed.
*
* After the filter is initialized, libavfilter sets this field to the
* threading type that is actually used (0 for no multithreading).
*/
int thread_type;
/**
* An opaque struct for libavfilter internal use.
*/
AVFilterInternal *internal;
struct AVFilterCommand *command_queue;
char *enable_str; ///< enable expression string
void *enable; ///< parsed expression (AVExpr*)
double *var_values; ///< variable values for the enable expression
int is_disabled; ///< the enabled state from the last expression evaluation
/**
* For filters which will create hardware frames, sets the device the
* filter should create them in. All other filters will ignore this field:
* in particular, a filter which consumes or processes hardware frames will
* instead use the hw_frames_ctx field in AVFilterLink to carry the
* hardware context information.
*/
AVBufferRef *hw_device_ctx;
/**
* Max number of threads allowed in this filter instance.
* If <= 0, its value is ignored.
* Overrides global number of threads set per filter graph.
*/
int nb_threads;
/**
* Ready status of the filter.
* A non-0 value means that the filter needs activating;
* a higher value suggests a more urgent activation.
*/
unsigned ready;
/**
* Sets the number of extra hardware frames which the filter will
* allocate on its output links for use in following filters or by
* the caller.
*
* Some hardware filters require all frames that they will use for
* output to be defined in advance before filtering starts. For such
* filters, any hardware frame pools used for output must therefore be
* of fixed size. The extra frames set here are on top of any number
* that the filter needs internally in order to operate normally.
*
* This field must be set before the graph containing this filter is
* configured.
*/
int extra_hw_frames;
};
4.7 AVFilterLink : 連結結構體定義
libavfilter/avfilter.h
/**
* 兩個濾鏡之間的連結;
* 如果兩個濾鏡是有連結的,則這個連結結構體包含有指向源濾鏡與目的濾鏡的指標,
* 及 源濾鏡的輸出Pad, 和 目的濾鏡的輸入Pad 指標;
* 另外,這個連結還包含有這個兩個濾鏡經過協商並匹配成功的引數,如影象的解析度,格式等;
*
* 應用程式不能直接去訪問連結結構體,而是使用 buffersrc 和 buffersink API 來訪問,如:
*
*/
struct AVFilterLink {
AVFilterContext *src; ///< 指向和它相連的上游的源濾鏡
AVFilterPad *srcpad; ///< 源Pad , 和上游源濾鏡的 output_pad 相連
AVFilterContext *dst; ///< 指向和它相連的下游的目的濾鏡
AVFilterPad *dstpad; ///< 目的Pad, 和下游目目的濾鏡的 innput_pad 相連
enum AVMediaType type; ///< Link的媒體型別
/* 視訊相關引數 */
int w; ///< agreed upon image width
int h; ///< agreed upon image height
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
/* 音訊相關引數 */
uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
int sample_rate; ///< samples per second
int format; ///< 協商後並匹配成功的媒體格式 ID
/**
* 定義將通過此連結的 幀/樣本的PTS表示用的 時鐘基,
* 在配置階段,每個濾鏡應當只能改變輸出的時鐘基,而輸入的時鐘基是不可以更改的
*/
AVRational time_base;
/*****************************************************************
* 下面的所有成員屬性與函式都不是公開API,它們不能被 libavfilter的外部使用
*****************************************************************
*/
/**
* 輸入濾鏡與輸出濾鏡支援的格式、通道佈局、取樣率列表,這些列表用是用於實際的格式協商。
* 當協商成功後,匹配的格式與通道佈局將會更新上面的 format 、channel_layout 、sample_rate 成員屬性;
*/
AVFilterFormats *in_formats;
AVFilterFormats *out_formats;
AVFilterFormats *in_samplerates;
AVFilterFormats *out_samplerates;
struct AVFilterChannelLayouts *in_channel_layouts;
struct AVFilterChannelLayouts *out_channel_layouts;
/**
* 僅用於音訊;
* 輸出濾鏡會設定它為一個非零值,用於請求將有設定數量的樣本緩衝區傳送給它。
* 此時,對應輸入Pad的 AVFilterPad.needs_fifo 也要做設定;
* EOF之前的最後一個buffer將會使用靜音資料填充;
*/
int request_samples;
/** stage of the initialization of the link properties (dimensions, etc) */
enum {
AVLINK_UNINIT = 0, ///< not started
AVLINK_STARTINIT, ///< started, but incomplete
AVLINK_INIT ///< complete
} init_state;
/**
* 濾鏡所屬的濾鏡圖;
*/
struct AVFilterGraph *graph;
/**
* 本連結的當前時間戳,由最近的幀定義,單位是 上面的 time_base;
*/
int64_t current_pts;
/**
* 本連結的當前時間戳,由最近的幀定義,單位是 AV_TIME_BASE (即ffmpeg內部使用的時鐘基)
*/
int64_t current_pts_us;
/**
* Index in the age array.
*/
int age_index;
/**
* 本濾鏡鏈的流的幀率,當幀率是未知或可變時,設為 {1/0};
* 如果設定為 {0/0}, 將會自動從源濾鏡的輸入複製得到;
*
* 源濾鏡應當將其設定為實際幀率的最佳估值。
* 如果源濾鏡幀率是未知或是可變的,則將其設定為 {1/0}.
* 如果有必要,濾鏡應當在它的處理函式中更新這個值;
* Sink型濾鏡可以用它來設定預設的輸出幀率;
* 它和 AVStream中 的 r_frame_rate 類似;
*/
AVRational frame_rate;
/**
* Buffer partially filled with samples to achieve a fixed/minimum size.
*
*/
AVFrame *partial_buf;
/**
* Size of the partial buffer to allocate.Must be between min_samples and max_samples.
*
*/
int partial_buf_size;
/**
* 濾鏡一次能處理的最小樣本數。
* 如果呼叫 filter_frame() 函式 時 的樣本數小於這個值時,那這個函式將會在 partial_buf中將這些樣本累積起來。
* 這個屬性值 及 相關的屬性在濾鏡初始化完成後就不能再更改了;
* 如果設定為零,則所有相關的屬性都被忽略;
*/
int min_samples;
/**
* 濾鏡一次能處理的最大樣本數。
* 如果呼叫 filter_frame() 函式時的 樣本數大於這個值時,那這個函式要將樣本切分後再處理;
*/
int max_samples;
/**
* 音訊通道的個數
*/
int channels;
/**
* Link processing flags. 連結處理標誌
*/
unsigned flags;
/**
* 通過連結的輸入的幀數,輸出的幀數;
*/
int64_t frame_count_in, frame_count_out;
/**
* A pointer to a FFFramePool struct.
*/
void *frame_pool;
/**
* True if a frame is currently wanted on the output of this filter.
* Set when ff_request_frame() is called by the output,
* cleared when a frame is filtered.
* 如果當前幀希望從濾鏡輸出,則此值為真。
*/
int frame_wanted_out;
/**
* For hwaccel pixel formats, this should be a reference to the
* AVHWFramesContext describing the frames.
*/
AVBufferRef *hw_frames_ctx;
#ifndef FF_INTERNAL_FIELDS
/**
* Internal structure members.
* The fields below this limit are internal for libavfilter's use
* and must in no way be accessed by applications.
*/
char reserved[0xF000];
#else /* FF_INTERNAL_FIELDS */
/**
* Queue of frames waiting to be filtered.
*/
FFFrameQueue fifo;
/**
* If set, the source filter can not generate a frame as is.
* The goal is to avoid repeatedly calling the request_frame() method on
* the same link.
*/
int frame_blocked_in;
/**
* Link input status.
* If not zero, all attempts of filter_frame will fail with the
* corresponding code.
*/
int status_in;
/**
* Timestamp of the input status change.
*/
int64_t status_in_pts;
/**
* Link output status.
* If not zero, all attempts of request_frame will fail with the
* corresponding code.
*/
int status_out;
#endif /* FF_INTERNAL_FIELDS */
};
4.8. AVFilterPad結構體定義
/**
* @addtogroup lavu_media Media Type
* @brief Media Type
*/
enum AVMediaType {
AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA
AVMEDIA_TYPE_VIDEO,
AVMEDIA_TYPE_AUDIO,
AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous
AVMEDIA_TYPE_SUBTITLE,
AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse
AVMEDIA_TYPE_NB
};
/**
* 一個 filter pad 就是一個濾鏡的輸入/輸出埠
*/
struct AVFilterPad {
/**
* Pad名稱, 在輸入列表,或輸出列表內部必須是唯一的,但輸入列表,輸出列表之間可以重名。
* 如果 這個 Pad 不會被以名稱引用,則其值可以為NULL。
*/
const char *name;
/**
* AVFilterPad 型別
*/
enum AVMediaType type;
/**
* 獲得一個視訊 buffer的回撥函式,如果為空,則濾鏡系統會使用預設的 ff_default_get_video_buffer();
* 只對輸入的視訊 Pad 有效
*/
AVFrame *(*get_video_buffer)(AVFilterLink *link, int w, int h);
/**
* 獲得一個音訊 buffer的回撥函式,如果為空,則濾鏡系統會使用預設的 ff_default_get_audio_buffer();
* 只對輸入的 音訊 Pad 有效
*/
AVFrame *(*get_audio_buffer)(AVFilterLink *link, int nb_samples);
/**
* 呼叫濾鏡進行處理的回撥函式:當濾鏡收到一幀 音訊/視訊 資料時,就要呼叫它進行處理。
* 它是濾鏡處理的真正入口 , 只在輸入 pad中使用;
*
* 返回值: >=0, 表示成功,負數,為AVERROR的錯誤。
* 這個函式必須確保 當濾鏡的處理出現錯誤時未被不合適地引用,且不會將錯誤傳遞到下一個濾鏡
*/
int (*filter_frame)(AVFilterLink *link, AVFrame *frame);
/**
* Frame poll callback. This returns the number of immediately available
* samples. It should return a positive value if the next request_frame()
* is guaranteed to return one frame (with no delay).
*
* Defaults to just calling the source poll_frame() method.
*
* Output pads only.
* 回撥函式: 幀輪詢的回撥函式, 它返回當前有效的樣本個數; 只對輸出Pad有效;
* 如果下一個 request_frame()函式是有幀資料返回,則它應該返回一個正數值;
*/
int (*poll_frame)(AVFilterLink *link);
/**
* Frame request callback. A call to this should result in some progress
* towards producing output over the given link. This should return zero
* on success, and another value on error.
*
* Output pads only.
* 回撥函式: 幀請求回撥函式。只對輸出Pad有效;
* 如果呼叫 了這個回撥函式,應當在給定的link上生成經過處理後的輸出資料;
* 返回值: 0,表示成功;否則為錯誤值;
*/
int (*request_frame)(AVFilterLink *link);
/**
* 回撥函式: 用於link的配置的回撥函式
* 對於 輸出 Pad, 它應當設定 link的屬性,如 width/height等。
* 不要在這裡設定 格式 屬性;
* 因為格式屬性是由濾鏡系統呼叫這個回撥函式之前,呼叫query_formats() 回撥函式在濾鏡間進行協調得到的。
* 對於輸入 pad, 這個回撥函式是用檢查 link的屬性,並由此更新濾鏡內部的相關狀態;
*
* 對於既有輸入,又有輸出的濾鏡,這個回撥函式在成功時返回零,其它返回值為出錯。
*/
int (*config_props)(AVFilterLink *link);
/**
* 這個濾鏡需要有一個 FIFO插入它的輸入link,通常是因為這個濾鏡會有一個延遲的動作。
* 只在輸入pad中使用
*/
int needs_fifo;
/**
* 這個濾鏡需要從它的輸入 link中得到一個可寫的幀,如果有需要,會複製資料buffer
* 只在輸入pad中使用
*/
int needs_writable;
};