[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