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

Olivier Guilyardi list
Mon Mar 23 20:17:57 CET 2009


Attached: jack demuxer 0.13 "The Lucky One" (hopefully ;)

Michael Niedermayer wrote:

> [...]
>> +/**
>> + * Size of the internal FIFO buffers as a number of audio packets
>> + */
>> +#define FIFO_PACKETS_NUM 16
>> +
>> +typedef struct {
>> +    jack_client_t *     client;
>> +    int                 activated;
>> +    sem_t               packet_count;
>> +    jack_nframes_t      sample_rate;
>> +    jack_nframes_t      buffer_size;
>> +    jack_port_t **      ports;
>> +    int                 nports;
>> +    TimeFilter *        timefilter;
>> +    AVFifoBuffer *      new_pkts;
> 
>> +    unsigned int        new_pkts_size;
>> +    AVFifoBuffer *      filled_pkts;
> 
>> +    unsigned int        filled_pkts_size;
> 
> maybe ive been too tired (yes i suggested it) but these make no sense
> FIFO_PACKETS_NUM should be used

This is quite ugly IMO:
FIFO_PACKETS_NUM * sizeof(AVPacket) - av_fifo_size(my_fifo)

Plus one of my ringbuffers contains FIFO_PACKETS_NUM + 1 packets, making the
above statement even worse.

All ringbuffers implementations I know of have two functions, read_space() and
write_space(). The later, which misses in fifo.*, is very often needed and
allows to avoid ugly operations as above.

So my patch include a new function, av_fifo_space(), which completes
av_fifo_size() and sounds semantically great to me.

>> +    /* Timestamp the packet with the cycle start time minus the average latency */
>> +    pkt.pts = (cycle_time - (latency / self->nports) / self->sample_rate) * 1000000.0;
> 
> isnt
> (latency / self->nports) / self->sample_rate
> an integer in seconds aka pretty inaccurate?

Right, that was a bug. Thanks!

> also (nitpick), id write
> latency / (self->nports * self->sample_rate)
> avoiding a slow division

Done

> 
> [...]
>> +static int supply_new_packets(JackData *self, AVFormatContext *context)
>> +{
>> +    AVPacket pkt;
>> +    int pkt_size = self->buffer_size * self->nports * sizeof(float);
>> +
>> +    /* Supply the process callback with new empty packets, by filling the new
>> +     * packets FIFO buffer with as many packets as possible. process_callback()
>> +     * can't do this by itself, because it can't allocate memory in realtime. */
>> +    while (self->new_pkts_size - av_fifo_size(self->new_pkts) >= sizeof(pkt)) {
>> +        if (av_new_packet(&pkt, pkt_size) < 0) {
>> +            av_log(context, AV_LOG_ERROR, "Could not create packet of size %d\n", pkt_size);
>> +            return AVERROR(EIO);
> 
> the error should be either the one returned by av_new_packet() or ENOMEM
> which is what the error would be

I now return the error reported by av_new_packet()

> 
> 
>> +        }
>> +        av_fifo_generic_write(self->new_pkts, &pkt, sizeof(pkt), NULL);
>> +    }
>> +    return 0;
>> +}
>> +
>> +static int start_jack(AVFormatContext *context, AVFormatParameters *params)
>> +{
>> +    JackData *self = context->priv_data;
>> +    jack_status_t status;
>> +    int i, test;
>> +    double o, period;
>> +
>> +    /* Register as a JACK client, using the context filename as client name. */
>> +    self->client = jack_client_open(context->filename, 0, &status);
>> +    if (!self->client) {
>> +        av_log(context, AV_LOG_ERROR, "Unable to register as a JACK client\n");
>> +        return AVERROR(EIO);
>> +    }
>> +
>> +    sem_init(&self->packet_count, 0, 0);
>> +
> 
>> +    self->overrun     = 0;
>> +    self->xrun        = 0;
>> +    self->activated   = 0;
> 
> redundant

Not sure what you mean here.

> 
> [...]
>> +    self->timefilter  = ff_timefilter_new (1 / self->sample_rate, sqrt(2 * o), o * o);
> 
> is the division not missing a float or doubl cast?

Indeed ! Corrected..

> [...]
>> +static int activate_jack(JackData *self, AVFormatContext *context)
>> +{
>> +    if (!jack_activate(self->client)) {
>> +        self->activated = 1;
>> +    } else {
>> +        av_log(context, AV_LOG_ERROR, "Unable to activate JACK client\n");
>> +        return -1;
>> +    }
>> +
>> +    av_log(context, AV_LOG_INFO, "JACK client registered and activated (rate=%dHz, buffer_size=%d frames)\n",
>> +           self->sample_rate, self->buffer_size);
>> +
>> +    return 0;
> 
> that stuff would fit nicer in the if() so both sides end in return
> 
> anyway, id this function really needed?
> simply calling jack_activate() and setting activated seems simpler

Function removed and "pasted" into audio_read_packet()

> [...]
>> +    if (self->overrun) {
>> +        av_log(context, AV_LOG_WARNING, "Audio packet overrun\n");
>> +        self->overrun = 0;
>> +    }
>> +
>> +    if (self->underrun) {
>> +        av_log(context, AV_LOG_WARNING, "Audio packet underrun\n");
>> +        self->underrun = 0;
>> +    }
>> +
>> +    if (self->xrun) {
>> +        av_log(context, AV_LOG_WARNING, "JACK xrun\n");
>> +        self->xrun = 0;
>> +    }
> 
> can xrun be != overrun || underrun ?

Yes

> if not it is redundant

I reckon these three variables were too many. I've merged overrun and underrun
into pkt_xrun, and renamed xrun to jack_xrun.

There are many possible reasons for JACK xruns. They happen when jack fails to
read/write some data from/to the audio hardware. This may be caused by low
level/operating system overhead. But the most usual reasons are that the user
has not enabled realtime scheduling, or that he has set a jack buffer size which
is too low for his system to support it.

Whereas the pkt_xrun (formerly underrun || overrun) may happen when the non
realtime thread where audio_read_packet() gets called doesn't run fast enough to
follow the realtime thread. Apart from overhead situations, this could also
happen because the application blocks, etc...

So, IMO, it is important to make a difference between pkt_xrun and jack_xrun log
messages, to help debugging and ease user support. pkt_xrun may come from cpu
overhead or a bug in the application. jack_xrun is likely to be caused by a
wrong (or too cpu intensive) jack or kernel setup.

--
  Olivier



-------------- next part --------------
A non-text attachment was scrubbed...
Name: ffmpeg-r18171-jack-0.13.patch
Type: text/x-patch
Size: 15214 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090323/86c543c2/attachment.bin>



More information about the ffmpeg-devel mailing list