[FFmpeg-devel] lavfi: request_frame() return value.

Nicolas George nicolas.george at normalesup.org
Sat Mar 16 00:25:32 CET 2013


Hi. A few words about the API contract of request_frame().

Here is the current situation:

* If request_frame() succeeds, it returns 0; it happens if and only if
  request_frame() pushed (successfully) at least a frame on the same link.

* If request_frame() can not succeed for temporary external reasons (e.g. a
  source needs input), it returns AVERROR(EAGAIN).

* It can always return an error code for other reasons (including EOF, which
  is not an error); I will omit this case in the rest of this message.

The problem with these rules is this: if a filter does not produce always at
least one output frame for each input frame (for example: select can skip
frames, fps too if the output frame rate is lower than the input, tile needs
n input frames to produce one output frame), then it needs to implement some
kind of communication so that filter_frame() can inform request_frame() it
is done. Something like this:

    int filter_frame(inlink, frame) {
	...
	if (can_produce_output) {
	    ff_filter_frame(outlink, out_frame);
	    self->request_fulfilled = 1;
	}
	return 0;
    }

    int request_frame(outlink) {
	self->request_fulfilled = 0;
	while (!self->request_fulfilled)
	    ff_request_frame(inlink);
	return 0;
    }

Add to that all error checks and EOF handling, and it can become somewhat
messy.

A special case of this is filters that use the min/max_samples feature: in
that case, the filter before the link thinks it has successfully pushed a
frame, and therefore returns 0, but the filter after the link did not
receive it yet.

I see several solutions for this:

0. Leave things as it is. The problem of the min/max_samples can be solved
   by making it the responsibility of the filter: if a filter sets
   min/max_samples on its input, it must implement a non-trivial
   request_frame() as above to make sure a frame was actually received.

It works, but all in all that makes a lot of code, and there is room for
simplification. I see two main options that could make things easier:

1. Change the semantic of the return value 0: instead of "success, at least
   one frame has been sent", it can become "success, some progress has been
   made (a frame has been pushed, or I have accumulated more data to push a
   frame later, or filters before me did)".

   This is a change of API, but since all these functions are internal, it
   only concerns the sinks and people maintaining private trees and forks
   with additional filters.

2. Move the "while (!request_fulfilled) ff_request_frame(inlink);" logic to
   the framework, namely ff_request_frame(). The request_fulfilled would
   then be just a private field of AVFilterLink.

I see small pros and cons for each solution, but I do not see a real problem
with either. I wonder if people have an advice before considering
implementing one of them.

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130316/486bd3e4/attachment.asc>


More information about the ffmpeg-devel mailing list