Blame view

ffmpeg-4.2.2/doc/filter_design.txt 11.2 KB
aac5773f   hucm   功能基本完成,接口待打磨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  Filter design
  =============
  
  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 AVFrame structure.
  
  
  Format negotiation
  ==================
  
    The query_formats method should set, for each input and each output links,
    the list of supported formats.
  
    For video links, that means pixel format. For audio links, that means
    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 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 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.
  
  
  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
  ================
  
    The purpose of these rules is to ensure that frames flow in the filter
    graph without getting stuck and accumulating somewhere.
  
    Simple filters that output one frame for each input frame should not have
    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
    ------------
  
      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.
  
      As an exception to the previous rule, if the input frame is enough to
      produce several output frames, then the filter needs output only at
      least one per link. The additional frames can be left buffered in the
      filter; these buffered frames must be flushed immediately if a new input
      produces new output.
  
      (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
      it. The task of requesting more frames is left to the filter's
      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 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.
  
    request_frame
    -------------
  
      For filters that do not use the activate() callback, this method is
      called when a frame is wanted on an 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 inputs, repeatedly until at least one frame has been pushed.
  
      Return values:
      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 should return
      AVERROR_EOF.
  
      The typical implementation of request_frame for a filter with several
      inputs will look like that:
  
          if (frames_queued) {
              push_one_frame();
              return 0;
          }
          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 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.