avfilter/vf_atadenoise: do not abort if user specified invalid size
[ffmpeg.git] / doc / filter_design.txt
index a19f316..885b19b 100644 (file)
@@ -5,34 +5,117 @@ This document explains guidelines that should be observed (or ignored with
 good reason) when writing filters for libavfilter.
 
 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 negociation
+Format negotiation
 ==================
 
   The query_formats method should set, for each input and each output links,
-  the list supported formats.
+  the list of supported formats.
 
   For video links, that means pixel format. For audio links, that means
-  channel layout, sample format and sample packing.
+  channel layout, sample format (the sample packing is implied by the sample
+  format) and sample rate.
 
   The lists are not just lists, they are references to shared objects. When
-  the negociation mechanism computes the intersection of the formats
-  supported at each ends of a link, all references to both lists are
-  replaced with a reference to the intersection. And when a single format is
+  the negotiation mechanism computes the intersection of the formats
+  supported at each end of a link, all references to both lists are replaced
+  with a reference to the intersection. And when a single format is
   eventually chosen for a link amongst the remaining list, again, all
   references to the list are updated.
 
   That means that if a filter requires that its input and output have the
-  same format amongst a supported list, all it have to do is use a reference
+  same format amongst a supported list, all it has to do is use a reference
   to the same list of formats.
 
+  query_formats can leave some formats unset and return AVERROR(EAGAIN) to
+  cause the negotiation mechanism to try again later. That can be used by
+  filters with complex requirements to use the format negotiated on one link
+  to set the formats supported on another.
 
-Buffer references ownership and permissions
-===========================================
 
-  TODO
+Frame references ownership and permissions
+==========================================
+
+  Principle
+  ---------
+
+    Audio and video data are voluminous; the frame and frame reference
+    mechanism is intended to avoid, as much as possible, expensive copies of
+    that data while still allowing the filters to produce correct results.
+
+    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
+    stored in the reference; different references for the same buffer can
+    show different characteristics. In particular, a video reference can
+    point to only a part of a video buffer.
+
+    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
+  -------------------
+
+    At any time, a reference “belongs” to a particular piece of code,
+    usually a filter. With a few caveats that will be explained below, only
+    that piece of code is allowed to access it. It is also responsible for
+    destroying it, although this is sometimes done automatically (see the
+    section on link reference fields).
+
+    Here are the (fairly obvious) rules for reference ownership:
+
+    * A reference received by the filter_frame method belongs to the
+      corresponding filter.
+
+    * A reference passed to ff_filter_frame is given away and must no longer
+      be used.
+
+    * A reference created with av_frame_ref() belongs to the code that
+      created it.
+
+    * A reference obtained with ff_get_video_buffer or ff_get_audio_buffer
+      belongs to the code that requested it.
+
+    * A reference given as return value by the get_video_buffer or
+      get_audio_buffer method is given away and must no longer be used.
+
+  Link reference fields
+  ---------------------
+
+    The AVFilterLink structure has a few AVFrame fields.
+
+    partial_buf is used by libavfilter internally and must not be accessed
+    by filters.
+
+    fifo contains frames queued in the filter's input. They belong to the
+    framework until they are taken by the filter.
+
+  Reference permissions
+  ---------------------
+
+    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.
+
+    A filter can check if a frame is writable by using the
+    av_frame_is_writable() function.
+
+    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.
+
+    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
@@ -44,11 +127,100 @@ Frame scheduling
   Simple filters that output one frame for each input frame should not have
   to worry about it.
 
-  start_frame / filter_samples
-  ----------------------------
+  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
+  ------------
 
-    These methods are called when a frame is pushed to the filter's input.
-    They 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
     push the output frames on the output link immediately.
@@ -59,9 +231,9 @@ Frame scheduling
     filter; these buffered frames must be flushed immediately if a new input
     produces new output.
 
-    ( Example: framerate-doubling filter: start_frame must (1) flush the
-    second copy of the previous frame, it it is stille there, (2) push the
-    first copy of the incoming frame, (3) keep the second copy for later. )
+    (Example: frame rate-doubling filter: filter_frame must (1) flush the
+    second copy of the previous frame, if it is still there, (2) push the
+    first copy of the incoming frame, (3) keep the second copy for later.)
 
     If the input frame is not enough to produce output, the filter must not
     call request_frame to get more. It must just process the frame or queue
@@ -69,7 +241,7 @@ Frame scheduling
     request_frame method or the application.
 
     If a filter has several inputs, the filter must be ready for frames
-    arriving randomly on any input. Therefore, any filter with several input
+    arriving randomly on any input. Therefore, any filter with several inputs
     will most likely require some kind of queuing mechanism. It is perfectly
     acceptable to have a limited queue and to drop frames when the inputs
     are too unbalanced.
@@ -77,19 +249,21 @@ Frame scheduling
   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 start_frame or filter_samples on
-    the corresponding output.
+    For a source, it should directly call filter_frame on the corresponding
+    output.
 
     For a filter, if there are queued frames already ready, one of these
     frames should be pushed. If not, the filter should request a frame on
-    one of its input, repeatedly until at least one frame has been pushed.
+    one of its inputs, repeatedly until at least one frame has been pushed.
 
     Return values:
-    if request_frame could produce a frame, it should return 0;
+    if request_frame could produce a frame, or at least make progress
+    towards producing a frame, it should return 0;
     if it could not for temporary reasons, it should return AVERROR(EAGAIN);
-    if it could not because there are no more frames, it shous return
+    if it could not because there are no more frames, it should return
     AVERROR_EOF.
 
     The typical implementation of request_frame for a filter with several
@@ -99,17 +273,16 @@ Frame scheduling
             push_one_frame();
             return 0;
         }
-        while (!frame_pushed) {
-            input = input_where_a_frame_is_most_needed();
-            ret = avfilter_request_frame(input);
-            if (ret == AVERROR_EOF) {
-                process_eof_on_input();
-            } else if (ret < 0) {
-                return ret;
-            }
+        input = input_where_a_frame_is_most_needed();
+        ret = ff_request_frame(input);
+        if (ret == AVERROR_EOF) {
+            process_eof_on_input();
+        } else if (ret < 0) {
+            return ret;
         }
         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 start_frame / filter_samples method will be called and do the work.
+    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.