On Mon, 30 Oct 2017, Mironov, Mikhail wrote:

[...]

I still think this would be much better off using the
send_frame()/receive_packet() API.  Even if your API doesn't expose
any information about the queue length, you only need to hold a
single input frame transiently to get around that (the user is not
allowed to call
send_frame() twice in a row without calling receive_packet()).


So to implement this I would have to:
- in the send_frame() if AMF_INPUT_FULL is returned - store input
frame (or copy?)
- In the next receive_frame() check if frame is stored
- Wait till some output is produced
- resubmit stored frame

Sounds about right.

Issues I see:
- Isn't this logic defeat the purpose of independent send()/receive()?
- How can I report a error if receive() produced a compressed frame but
the delayed submission failed?

Since this is asynchronous anyway, just report it at the next available
opportunity.

- This logic depends on the particular logic in the calling code.

The API requires this behaviour of the caller.  See the documentation in
avcodec.h.

- This logic depends on the particular HW behaviour.

How so?

- In the future, we would like to output individual slices of a compressed
frame.
When this added receive_frame() must be called several times to clear
space in the HW queue.
Granted, current implementation also does not cover this case but
truly independent send/receive implementation would.

Note that the user is required to call receive_packet() repeatedly until it
returns EAGAIN, and only then are they allowed to call send_frame() again.

The implementation will be cumbersome at least. Note that calling Drain()
may also return AMF_INPUT_FULL and therefore will have to be remembered and
called again in receive(). But I will implement as you suggests. It is not a 
huge change.


I see some confusion. The user can call send_frame/receive_packet in any order, and you can implement send_frame and receive_packet any way you want, the only thing you have to guarantee is that you cannot return EAGAIN for both send_frame and receive_packet. Not even temporarily.

If you returned EAGAIN in send_frame, you must return success or a normal error in receive_packet. If you returned EAGAIN in receive_packet, you must return success or a normal error in send_frame.

By returning EAGAIN in receive_packet you make sure that the API user submits as many frames as needed to fill your pipeline.

The simplest solution really seems to me what Mark proposed:

send_frame:

if (have_stored_frame)
  return EAGAIN;
if (amd_send_frame() == INPUT_FULL)
  store_frame;
return 0;

receive_packet:

if (have_stored_frame) {
  if (amd_send_frame() == OK)
     unstore_frame;
  block_until_have_packet
  return packet
} else {
  return EAGAIN
}

I hope I did not mess it up, proper draining and error handling obviously needs some minor changes.

Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to