| @@ -5,7 +5,7 @@ This document explains guidelines that should be observed (or ignored with | |||||
| good reason) when writing filters for libavfilter. | good reason) when writing filters for libavfilter. | ||||
| In this document, the word “frame” indicates either a video frame or a group | In this document, the word “frame” indicates either a video frame or a group | ||||
| of audio samples, as stored in an AVFilterBuffer structure. | |||||
| of audio samples, as stored in an AVFrame structure. | |||||
| Format negotiation | Format negotiation | ||||
| @@ -35,32 +35,31 @@ Format negotiation | |||||
| to set the formats supported on another. | to set the formats supported on another. | ||||
| Buffer references ownership and permissions | |||||
| =========================================== | |||||
| Frame references ownership and permissions | |||||
| ========================================== | |||||
| Principle | Principle | ||||
| --------- | --------- | ||||
| Audio and video data are voluminous; the buffer and buffer reference | |||||
| Audio and video data are voluminous; the frame and frame reference | |||||
| mechanism is intended to avoid, as much as possible, expensive copies of | mechanism is intended to avoid, as much as possible, expensive copies of | ||||
| that data while still allowing the filters to produce correct results. | that data while still allowing the filters to produce correct results. | ||||
| The data is stored in buffers represented by AVFilterBuffer structures. | |||||
| They must not be accessed directly, but through references stored in | |||||
| AVFilterBufferRef structures. Several references can point to the | |||||
| same buffer; the buffer is automatically deallocated once all | |||||
| corresponding references have been destroyed. | |||||
| The data is stored in buffers represented by AVFrame structures. | |||||
| Several references can point to the same frame buffer; the buffer is | |||||
| automatically deallocated once all corresponding references have been | |||||
| destroyed. | |||||
| The characteristics of the data (resolution, sample rate, etc.) are | The characteristics of the data (resolution, sample rate, etc.) are | ||||
| stored in the reference; different references for the same buffer can | stored in the reference; different references for the same buffer can | ||||
| show different characteristics. In particular, a video reference can | show different characteristics. In particular, a video reference can | ||||
| point to only a part of a video buffer. | point to only a part of a video buffer. | ||||
| A reference is usually obtained as input to the start_frame or | |||||
| filter_frame method or requested using the ff_get_video_buffer or | |||||
| ff_get_audio_buffer functions. A new reference on an existing buffer can | |||||
| be created with the avfilter_ref_buffer. A reference is destroyed using | |||||
| the avfilter_unref_bufferp function. | |||||
| A reference is usually obtained as input to the filter_frame method or | |||||
| requested using the ff_get_video_buffer or ff_get_audio_buffer | |||||
| functions. A new reference on an existing buffer can be created with | |||||
| av_frame_ref(). A reference is destroyed using | |||||
| the av_frame_free() function. | |||||
| Reference ownership | Reference ownership | ||||
| ------------------- | ------------------- | ||||
| @@ -73,17 +72,13 @@ Buffer references ownership and permissions | |||||
| Here are the (fairly obvious) rules for reference ownership: | Here are the (fairly obvious) rules for reference ownership: | ||||
| * A reference received by the filter_frame method (or its start_frame | |||||
| deprecated version) belongs to the corresponding filter. | |||||
| * A reference received by the filter_frame method belongs to the | |||||
| corresponding filter. | |||||
| Special exception: for video references: the reference may be used | |||||
| internally for automatic copying and must not be destroyed before | |||||
| end_frame; it can be given away to ff_start_frame. | |||||
| * A reference passed to ff_filter_frame is given away and must no longer | |||||
| be used. | |||||
| * A reference passed to ff_filter_frame (or the deprecated | |||||
| ff_start_frame) is given away and must no longer be used. | |||||
| * A reference created with avfilter_ref_buffer belongs to the code that | |||||
| * A reference created with av_frame_ref() belongs to the code that | |||||
| created it. | created it. | ||||
| * A reference obtained with ff_get_video_buffer or ff_get_audio_buffer | * A reference obtained with ff_get_video_buffer or ff_get_audio_buffer | ||||
| @@ -95,89 +90,32 @@ Buffer references ownership and permissions | |||||
| Link reference fields | Link reference fields | ||||
| --------------------- | --------------------- | ||||
| The AVFilterLink structure has a few AVFilterBufferRef fields. The | |||||
| cur_buf and out_buf were used with the deprecated | |||||
| start_frame/draw_slice/end_frame API and should no longer be used. | |||||
| src_buf and partial_buf are used by libavfilter internally | |||||
| and must not be accessed by filters. | |||||
| Reference permissions | |||||
| --------------------- | |||||
| The AVFilterBufferRef structure has a perms field that describes what | |||||
| the code that owns the reference is allowed to do to the buffer data. | |||||
| Different references for the same buffer can have different permissions. | |||||
| For video filters that implement the deprecated | |||||
| start_frame/draw_slice/end_frame API, the permissions only apply to the | |||||
| parts of the buffer that have already been covered by the draw_slice | |||||
| method. | |||||
| The value is a binary OR of the following constants: | |||||
| * AV_PERM_READ: the owner can read the buffer data; this is essentially | |||||
| always true and is there for self-documentation. | |||||
| * AV_PERM_WRITE: the owner can modify the buffer data. | |||||
| * AV_PERM_PRESERVE: the owner can rely on the fact that the buffer data | |||||
| will not be modified by previous filters. | |||||
| * AV_PERM_REUSE: the owner can output the buffer several times, without | |||||
| modifying the data in between. | |||||
| * AV_PERM_REUSE2: the owner can output the buffer several times and | |||||
| modify the data in between (useless without the WRITE permissions). | |||||
| * AV_PERM_ALIGN: the owner can access the data using fast operations | |||||
| that require data alignment. | |||||
| The READ, WRITE and PRESERVE permissions are about sharing the same | |||||
| buffer between several filters to avoid expensive copies without them | |||||
| doing conflicting changes on the data. | |||||
| The REUSE and REUSE2 permissions are about special memory for direct | |||||
| rendering. For example a buffer directly allocated in video memory must | |||||
| not modified once it is displayed on screen, or it will cause tearing; | |||||
| it will therefore not have the REUSE2 permission. | |||||
| The ALIGN permission is about extracting part of the buffer, for | |||||
| copy-less padding or cropping for example. | |||||
| The AVFilterLink structure has a few AVFrame fields. | |||||
| References received on input pads are guaranteed to have all the | |||||
| permissions stated in the min_perms field and none of the permissions | |||||
| stated in the rej_perms. | |||||
| partial_buf is used by libavfilter internally and must not be accessed | |||||
| by filters. | |||||
| References obtained by ff_get_video_buffer and ff_get_audio_buffer are | |||||
| guaranteed to have at least all the permissions requested as argument. | |||||
| fifo contains frames queued in the filter's input. They belong to the | |||||
| framework until they are taken by the filter. | |||||
| References created by avfilter_ref_buffer have the same permissions as | |||||
| the original reference minus the ones explicitly masked; the mask is | |||||
| usually ~0 to keep the same permissions. | |||||
| Filters should remove permissions on reference they give to output | |||||
| whenever necessary. It can be automatically done by setting the | |||||
| rej_perms field on the output pad. | |||||
| Here are a few guidelines corresponding to common situations: | |||||
| Reference permissions | |||||
| --------------------- | |||||
| * Filters that modify and forward their frame (like drawtext) need the | |||||
| WRITE permission. | |||||
| Since the same frame data can be shared by several frames, modifying may | |||||
| have unintended consequences. A frame is considered writable if only one | |||||
| reference to it exists. The code owning that reference it then allowed | |||||
| to modify the data. | |||||
| * Filters that read their input to produce a new frame on output (like | |||||
| scale) need the READ permission on input and must request a buffer | |||||
| with the WRITE permission. | |||||
| A filter can check if a frame is writable by using the | |||||
| av_frame_is_writable() function. | |||||
| * Filters that intend to keep a reference after the filtering process | |||||
| is finished (after filter_frame returns) must have the PRESERVE | |||||
| permission on it and remove the WRITE permission if they create a new | |||||
| reference to give it away. | |||||
| A filter can ensure that a frame is writable at some point of the code | |||||
| by using the ff_inlink_make_frame_writable() function. It will duplicate | |||||
| the frame if needed. | |||||
| * Filters that intend to modify a reference they have kept after the end | |||||
| of the filtering process need the REUSE2 permission and must remove | |||||
| the PRESERVE permission if they create a new reference to give it | |||||
| away. | |||||
| A filter can ensure that the frame passed to the filter_frame() callback | |||||
| is writable by setting the needs_writable flag on the corresponding | |||||
| input pad. It does not apply to the activate() callback. | |||||
| Frame scheduling | Frame scheduling | ||||
| @@ -189,11 +127,100 @@ Frame scheduling | |||||
| Simple filters that output one frame for each input frame should not have | Simple filters that output one frame for each input frame should not have | ||||
| to worry about it. | to worry about it. | ||||
| There are two design for filters: one using the filter_frame() and | |||||
| request_frame() callbacks and the other using the activate() callback. | |||||
| The design using filter_frame() and request_frame() is legacy, but it is | |||||
| suitable for filters that have a single input and process one frame at a | |||||
| time. New filters with several inputs, that treat several frames at a time | |||||
| or that require a special treatment at EOF should probably use the design | |||||
| using activate(). | |||||
| activate | |||||
| -------- | |||||
| This method is called when something must be done in a filter; the | |||||
| definition of that "something" depends on the semantic of the filter. | |||||
| The callback must examine the status of the filter's links and proceed | |||||
| accordingly. | |||||
| The status of output links is stored in the frame_wanted_out, status_in | |||||
| and status_out fields and tested by the ff_outlink_frame_wanted() | |||||
| function. If this function returns true, then the processing requires a | |||||
| frame on this link and the filter is expected to make efforts in that | |||||
| direction. | |||||
| The status of input links is stored by the status_in, fifo and | |||||
| status_out fields; they must not be accessed directly. The fifo field | |||||
| contains the frames that are queued in the input for processing by the | |||||
| filter. The status_in and status_out fields contains the queued status | |||||
| (EOF or error) of the link; status_in is a status change that must be | |||||
| taken into account after all frames in fifo have been processed; | |||||
| status_out is the status that have been taken into account, it is final | |||||
| when it is not 0. | |||||
| The typical task of an activate callback is to first check the backward | |||||
| status of output links, and if relevant forward it to the corresponding | |||||
| input. Then, if relevant, for each input link: test the availability of | |||||
| frames in fifo and process them; if no frame is available, test and | |||||
| acknowledge a change of status using ff_inlink_acknowledge_status(); and | |||||
| forward the result (frame or status change) to the corresponding input. | |||||
| If nothing is possible, test the status of outputs and forward it to the | |||||
| corresponding input(s). If still not possible, return FFERROR_NOT_READY. | |||||
| If the filters stores internally one or a few frame for some input, it | |||||
| can consider them to be part of the FIFO and delay acknowledging a | |||||
| status change accordingly. | |||||
| Example code: | |||||
| ret = ff_outlink_get_status(outlink); | |||||
| if (ret) { | |||||
| ff_inlink_set_status(inlink, ret); | |||||
| return 0; | |||||
| } | |||||
| if (priv->next_frame) { | |||||
| /* use it */ | |||||
| return 0; | |||||
| } | |||||
| ret = ff_inlink_consume_frame(inlink, &frame); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| if (ret) { | |||||
| /* use it */ | |||||
| return 0; | |||||
| } | |||||
| ret = ff_inlink_acknowledge_status(inlink, &status, &pts); | |||||
| if (ret) { | |||||
| /* flush */ | |||||
| ff_outlink_set_status(outlink, status, pts); | |||||
| return 0; | |||||
| } | |||||
| if (ff_outlink_frame_wanted(outlink)) { | |||||
| ff_inlink_request_frame(inlink); | |||||
| return 0; | |||||
| } | |||||
| return FFERROR_NOT_READY; | |||||
| The exact code depends on how similar the /* use it */ blocks are and | |||||
| how related they are to the /* flush */ block, and needs to apply these | |||||
| operations to the correct inlink or outlink if there are several. | |||||
| Macros are available to factor that when no extra processing is needed: | |||||
| FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); | |||||
| FF_FILTER_FORWARD_STATUS_ALL(outlink, filter); | |||||
| FF_FILTER_FORWARD_STATUS(inlink, outlink); | |||||
| FF_FILTER_FORWARD_STATUS_ALL(inlink, filter); | |||||
| FF_FILTER_FORWARD_WANTED(outlink, inlink); | |||||
| filter_frame | filter_frame | ||||
| ------------ | ------------ | ||||
| This method is called when a frame is pushed to the filter's input. It | |||||
| can be called at any time except in a reentrant way. | |||||
| For filters that do not use the activate() callback, this method is | |||||
| called when a frame is pushed to the filter's input. It can be called at | |||||
| any time except in a reentrant way. | |||||
| If the input frame is enough to produce output, then the filter should | If the input frame is enough to produce output, then the filter should | ||||
| push the output frames on the output link immediately. | push the output frames on the output link immediately. | ||||
| @@ -222,9 +249,10 @@ Frame scheduling | |||||
| request_frame | request_frame | ||||
| ------------- | ------------- | ||||
| This method is called when a frame is wanted on an output. | |||||
| For filters that do not use the activate() callback, this method is | |||||
| called when a frame is wanted on an output. | |||||
| For an input, it should directly call filter_frame on the corresponding | |||||
| For a source, it should directly call filter_frame on the corresponding | |||||
| output. | output. | ||||
| For a filter, if there are queued frames already ready, one of these | For a filter, if there are queued frames already ready, one of these | ||||
| @@ -254,16 +282,7 @@ Frame scheduling | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| Note that, except for filters that can have queued frames, request_frame | |||||
| does not push frames: it requests them to its input, and as a reaction, | |||||
| the filter_frame method possibly will be called and do the work. | |||||
| Legacy API | |||||
| ========== | |||||
| Until libavfilter 3.23, the filter_frame method was split: | |||||
| - for video filters, it was made of start_frame, draw_slice (that could be | |||||
| called several times on distinct parts of the frame) and end_frame; | |||||
| - for audio filters, it was called filter_samples. | |||||
| Note that, except for filters that can have queued frames and sources, | |||||
| request_frame does not push frames: it requests them to its input, and | |||||
| as a reaction, the filter_frame method possibly will be called and do | |||||
| the work. | |||||