[FFmpeg-devel] Added HW H.264 and HEVC encoding for AMD GPUs based on AMF SDK
Marton Balint
cus at passwd.hu
Tue Oct 31 03:26:24 EET 2017
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
More information about the ffmpeg-devel
mailing list