[FFmpeg-devel] [PATCH] libavdevice: JACK demuxer

Olivier Guilyardi list
Sat Mar 7 14:10:40 CET 2009


Michael Niedermayer a ?crit :
> On Wed, Mar 04, 2009 at 02:33:47PM +0100, Olivier Guilyardi wrote:
> [...]
>>>> +
>>>> +    timeout.tv_sec = av_gettime() / 1000000 + 2;
>>>> +    if (sem_timedwait(&self->packet_signal, &timeout)) {
>>>> +        if (errno == ETIMEDOUT) {
>>>> +            av_log(context, AV_LOG_ERROR,
>>>> +                   "Input error: timed out when waiting for JACK process callback output\n");
>>>> +        } else {
>>>> +            av_log(context, AV_LOG_ERROR, "Error while waiting for audio packet: %s\n",
>>>> +                   strerror(errno));
>>>> +        }
>>>> +        if (!self->client) {
>>>> +            av_log(context, AV_LOG_ERROR, "Input error: JACK server is gone\n");
>>>> +        }
>>>> +        return AVERROR(EIO);
>>>> +    }
>>>> +
>>>> +    if (self->overrun) {
>>>> +        av_log(context, AV_LOG_WARNING, "Packet ringbuffer overrun\n");
>>>> +        self->overrun = 0;
>>>> +    }
>>>> +
>>>> +    if (self->xrun) {
>>>> +        av_log(context, AV_LOG_WARNING, "JACK xrun\n");
>>>> +        self->xrun = 0;
>>>> +    }
>>>> +
>>>> +    self->reader_index = (self->reader_index + 1) % RING_NBUFFERS;
>>>> +
>>>> +    memcpy(pkt, self->ringbuffer + self->reader_index, sizeof(*pkt));
>>> *pkt= self->ringbuffer[self->reader_index];
>>>
>>> also it seems 1 entry in the ring buffer cant be used with your
>>> implementation
>>>
>>> maybe the following is better:
>>> process_callback(){
>>>     if((uint8_t)(writer_index - reader_index) < RING_SIZE){
>>>         write at buffer[writer_index & (RING_SIZE-1)];
>>>         writer_index++;
>>>     }
>>> }
>>>
>>> read_packet(){
>>>     if(writer_index == reader_index)
>>>         return AVERROR(EAGAIN);
>>>
>>>     take packet from buffer[reader_index & (RING_SIZE-1)];
>>>     buffer[reader_index & (RING_SIZE-1)]= av_new_packet();
>>>     reader_index++;
>>> }
>>>
>>> note, both writer_index and reader_index must be unsigned for above
>>> to work, and probably its best if they are uint8_t to exclude any issues
>>> with the writes to them not being done in one piece.
>> Okay, I've completely changed this. My experience with lock free ringbuffers
>> shows that it's hard to tell what is safe and what is not from a theoretical
>> point of view (and there are many such point of views...).
>>
>> As of JACK 0.116, the jack ringbuffer has been thoroughly unit tested and fixed
>> (see the dozens of posts on LAD, LAU and jack-devel), on single/multi cpu, and
>> especially on weakly memory ordered ones (such as PowerPC SMP).
>>
>> So I found a way to avoid superfluous copy operations, using 2 jack ringbuffers.
>> The idea is simple: audio_read_packet() sends newly allocated empty packets
>> through one ringbuffer. Then process_callback() retrieve one, directly copy and
>> interleave data into it, and send it back through another ringbuffer.
> 
> Iam sure this works but it is certainly not the simplest solution, that is i
> belive my suggestion needs less code also mine needs just one buffer not 2

It depends on what you call simple.

Coding such IPC mechanism using uint8_t and stuff is a subtle thing, with 
potential subtle bugs.

What you call simple IMO is smaller, and potentially faster, code, even if that 
implies much more complexity.

In this very case, I believe your approach is dangerous, because you drastically 
reduce maintainability. Your code may well be bug-free, but even a skilled 
developer might introduce a non-obvious bug, in a later change. Plus, it's hard 
to test because it might behave differently on different cpu architectures.

What is my approach then? I'm using a "brick", the jack ringbuffer, which I know 
to be well tested, just as I would use a semaphore or a mutex, (sort of) blindly 
trusting them. I'm dealing with complexity, but it is well encapsulated.

What is the expected result? Stability now, and because of maintainability: long 
term stability. Which is the top 1 in my priorities.

And I don't think the slight increase in performance (if any) of your solution 
has the same weight as that.

--
   Olivier




More information about the ffmpeg-devel mailing list