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