[FFmpeg-devel] v4l2: bug #1570 and possible solution

Giorgio Vazzana mywing81 at gmail.com
Tue Feb 12 19:53:29 CET 2013


2013/2/12 Michael Niedermayer <michaelni at gmx.at>:
> On Tue, Feb 12, 2013 at 06:01:10PM +0100, Giorgio Vazzana wrote:
>> 2013/2/12 Michael Niedermayer <michaelni at gmx.at>:
>> > On Tue, Feb 12, 2013 at 12:40:21PM +0100, Giorgio Vazzana wrote:
>> >> 2013/2/12 Michael Niedermayer <michaelni at gmx.at>:
>> >> +static void mmap_release_buffer(AVPacket *pkt)
>> >> +{
>> >> +    struct buff_data *buf_descriptor = pkt->priv;
>> >> +
>> >> +    if (pkt->data == NULL)
>> >> +        return;
>> >> +
>> >> +    if (buf_descriptor->buffer_copied) {
>> >> +        av_free(pkt->data);
>> >> +    } else {
>> >> +        if (!enqueue_buffer(buf_descriptor->fd, buf_descriptor->index))
>> >
>> >> +            (*buf_descriptor->buffers_dequeued)--;
>> >
>> > the deallocation of packets could happen from different thread(s)
>> > so i think this needs either a mutex, an atomic decrement or some
>> > lockless algorithm to achive the same
>>
>> Ok, I've tried to implement the solution using the mutex. Please comment.
>>
>> We can use this approach, or the easiest (and slightly slower?)
>> solution would be copying every frame/buffer to the memory allocated
>> for the corresponding packet.
>
> if you want to avoid the dependancy on pthreads, one way that should
> work is to use an array which size matches the maximum number of
> buffers, inited to 0 each time a buffer is allocated its entry is set
> to 1, when its freed its set to 0. to find out how many buffers are
> left the whole array would need to be scanned and remaining 0 elements
> counted.

I will have to think about this in the following days, but for now I
do not see how this can work: suppose we consider the following
example:

Initialization:
// let's suppose the number of buffers allocated by the v4l2
// driver is 10. This is also the lenght of the incoming and
// outgoing queues, which are organized as FIFO
buffers_obtained = 10;

// allocate and clear array
int *array = calloc(buffers_obtained, sizeof(*array));

// enqueue all the buffers to the incoming FIFO and start capturing
start_streaming();


Thread0 will do this:
// when we want to read a frame, we dequeue a buffer from the
// outgoing FIFO
dequeue_buffer(&buf);
// signal that a particular buffer has been dequeued
array[buf.index] = 1;


Thread1 will do this:
// count the numbers of buffers still in the incoming FIFO
int i, count = 0;
for (i = 0; i < buffers_obtained; i++)
    if (array[i] == 0)
        count++;

// when we're done with a frame, we need to enqueue the
// corrisponding buffer again
enqueue_buffer(index);
// signal that the buffer has been enqueued
array[index] = 0;


If Thread1 is suspended while it's executing the for loop, then
Thread0 starts executing, and then the control passes to Thread1
again, the value of count could be wrong... we would need to use a
mutex to protect array, unless I'm missing something.


More information about the ffmpeg-devel mailing list