[FFmpeg-devel] [PATCHv8] libavcodec: v4l2: add support for v4l2 mem2mem codecs

Mark Thompson sw at jkqxz.net
Mon Sep 4 21:58:36 EEST 2017

On 04/09/17 18:01, Jorge Ramirez wrote:
> On 09/04/2017 06:31 PM, Mark Thompson wrote:
>> On 04/09/17 17:00, Jorge Ramirez wrote:
>>> On 09/03/2017 08:23 PM, Mark Thompson wrote:
>>>> On 03/09/17 17:54, Jorge Ramirez wrote:
>>>>> On 09/03/2017 02:27 AM, Mark Thompson wrote:
>>>>>>> +/* in ffmpeg there is a single thread could be queueing/dequeuing buffers so a
>>>>>>> + * timeout is * required when retrieving a frame in case the driver has not received
>>>>>>> + * enough input * to start generating output.
>>>>>>> + *
>>>>>>> + * once decoding starts, the timeout should not be hit.
>>>>>> This seems like it could introduce a significant delay on startup for no good reason.  Can you instead just queue packets until either you run out of input buffers or a nonblocking dequeue succeeds?
>>>>>> (I might need to think more about how the semantics of this work.)
>>>>> if the decoder needs 4 blocks, the delay is 200ms, if it is 10 blocks, that is 500ms which doesn't seem too significant? when I test I barely notice the difference with respect to using the h264 codec (or any of the others in fact)
>>>>> the best solution would be to be able to block until the capture queue has frames ready but for that we would need another thread inputting independently on the other queue...does ffmpeg allow for this? separate threads for input and output?
>>>> Since the API is nonblocking, you can just return EAGAIN from receive_frame if there are any free buffers (to request more input).  You would then only block waiting for output if there is no more input (end of stream) or there aren't any free buffers (so no more input could be accepted).  Ideally there would then be no timeouts at all except in error cases.
>>> sure, can do that as well, not a problem.
>>> the encoding API doesnt seem to allow for this though: once it retrieves a valid frame it appears to keep on reading them without inputing others (this causes teh capture queue to block for ever)
>>> is this intentional or is it a bug?
>> The encode API should be identical to the decode API with frames/packets swapped (see docs in avcodec.h).
>> If you have an lavc-using program which calls receive_packet() repeatedly after it has returned EAGAIN and never calls send_packet() then that program is wrong.
> thanks for the prompt answer.
> yes I am just using the ffmpeg binary to encode a stream; however once a valid encoded packet is returned,  send_frame is not ever called again unless I return EAGAIN from v4l2m2m_receive_packet.
> But I cant return EAGAIN on receive_packet while I am blocked waiting for data which will never arrive (since send_frame is not executing)
> ...
> so if I queue 20 frames in the output queue and the allow frames to be dequeued, all of them are dequeued at once and then the code just blocks waiting for more input...

I've thought about this a bit further and I just don't understand the case you are hitting here.

receive_packet() will only need to block if both the the packet queue is full (all buffers in the kernel) and the frame queue is empty (also all buffers in the kernel), right?  If the packet queue is not full then we can return EAGAIN to indicate that send_packet() should be called to add more input, and if the frame queue is not empty then we can immediately return a frame.

If we do get blocked in that state (polling for read on both queues), then one must become readable eventually.  If the packet queue becomes readable then we dequeue a free buffer and return EAGAIN, if the frame queue becomes readable then we dequeue a frame and return it.  If neither happens then something is very wrong - either we don't have enough input buffers to make a frame, or the decoder itself is somehow broken.

(Ignoring end-of-stream behaviour, but I don't think that's the case you are talking about.)

So, can you describe in more detail the problem case?


- Mark

More information about the ffmpeg-devel mailing list