* Copyright (c) 2009 Samalyse
* Author: Olivier Guilyardi <olivier samalyse com>
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/log.h"
#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/time.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
-#include "libavformat/timefilter.h"
+#include "libavformat/internal.h"
+#include "timefilter.h"
/**
* Size of the internal FIFO buffers as a number of audio packets
#define FIFO_PACKETS_NUM 16
typedef struct {
+ AVClass *class;
jack_client_t * client;
int activated;
sem_t packet_count;
/* Copy and interleave audio data from the JACK buffer into the packet */
for (i = 0; i < self->nports; i++) {
+ #if HAVE_JACK_PORT_GET_LATENCY_RANGE
+ jack_latency_range_t range;
+ jack_port_get_latency_range(self->ports[i], JackCaptureLatency, &range);
+ latency += range.max;
+ #else
latency += jack_port_get_total_latency(self->client, self->ports[i]);
+ #endif
buffer = jack_port_get_buffer(self->ports[i], self->buffer_size);
for (j = 0; j < self->buffer_size; j++)
pkt_data[j * self->nports + i] = buffer[j];
return 0;
}
-static int start_jack(AVFormatContext *context, AVFormatParameters *params)
+static int start_jack(AVFormatContext *context)
{
JackData *self = context->priv_data;
jack_status_t status;
sem_init(&self->packet_count, 0, 0);
self->sample_rate = jack_get_sample_rate(self->client);
- self->nports = params->channels;
self->ports = av_malloc(self->nports * sizeof(*self->ports));
self->buffer_size = jack_get_buffer_size(self->client);
period = (double) self->buffer_size / self->sample_rate;
o = 2 * M_PI * 1.5 * period; /// bandwidth: 1.5Hz
self->timefilter = ff_timefilter_new (1.0 / self->sample_rate, sqrt(2 * o), o * o);
+ if (!self->timefilter) {
+ jack_client_close(self->client);
+ return AVERROR(ENOMEM);
+ }
/* Create FIFO buffers */
self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket));
ff_timefilter_destroy(self->timefilter);
}
-static int audio_read_header(AVFormatContext *context, AVFormatParameters *params)
+static int audio_read_header(AVFormatContext *context)
{
JackData *self = context->priv_data;
AVStream *stream;
int test;
- if (params->sample_rate <= 0 || params->channels <= 0)
- return -1;
-
- if ((test = start_jack(context, params)))
+ if ((test = start_jack(context)))
return test;
- stream = av_new_stream(context, 0);
+ stream = avformat_new_stream(context, NULL);
if (!stream) {
stop_jack(self);
return AVERROR(ENOMEM);
stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
#if HAVE_BIGENDIAN
- stream->codec->codec_id = CODEC_ID_PCM_F32BE;
+ stream->codec->codec_id = AV_CODEC_ID_PCM_F32BE;
#else
- stream->codec->codec_id = CODEC_ID_PCM_F32LE;
+ stream->codec->codec_id = AV_CODEC_ID_PCM_F32LE;
#endif
stream->codec->sample_rate = self->sample_rate;
stream->codec->channels = self->nports;
- av_set_pts_info(stream, 64, 1, 1000000); /* 64 bits pts in us */
+ avpriv_set_pts_info(stream, 64, 1, 1000000); /* 64 bits pts in us */
return 0;
}
}
}
- /* Wait for a packet comming back from process_callback(), if one isn't available yet */
+ /* Wait for a packet coming back from process_callback(), if one isn't available yet */
timeout.tv_sec = av_gettime() / 1000000 + 2;
if (sem_timedwait(&self->packet_count, &timeout)) {
if (errno == ETIMEDOUT) {
return 0;
}
-AVInputFormat jack_demuxer = {
- "jack",
- NULL_IF_CONFIG_SMALL("JACK Audio Connection Kit"),
- sizeof(JackData),
- NULL,
- audio_read_header,
- audio_read_packet,
- audio_read_close,
- .flags = AVFMT_NOFILE,
+#define OFFSET(x) offsetof(JackData, x)
+static const AVOption options[] = {
+ { "channels", "Number of audio channels.", OFFSET(nports), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+ { NULL },
+};
+
+static const AVClass jack_indev_class = {
+ .class_name = "JACK indev",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_jack_demuxer = {
+ .name = "jack",
+ .long_name = NULL_IF_CONFIG_SMALL("JACK Audio Connection Kit"),
+ .priv_data_size = sizeof(JackData),
+ .read_header = audio_read_header,
+ .read_packet = audio_read_packet,
+ .read_close = audio_read_close,
+ .flags = AVFMT_NOFILE,
+ .priv_class = &jack_indev_class,
};