From 8d3db95f201fba2e22611f9a5f8eced76f8e89ed Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:12:41 +0200 Subject: [PATCH 1/5] sndio: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/sndio.c | 108 ++++++++++++++++++++++++++++++++++-- libavdevice/sndio.h | 48 ---------------- libavdevice/sndio_dec.c | 120 ---------------------------------------- 4 files changed, 104 insertions(+), 174 deletions(-) delete mode 100644 libavdevice/sndio.h delete mode 100644 libavdevice/sndio_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 69542020d3..18228f590f 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -18,7 +18,7 @@ OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o -OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o +OBJS-$(CONFIG_SNDIO_INDEV) += sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o diff --git a/libavdevice/sndio.c b/libavdevice/sndio.c index 739551b841..ae14453bce 100644 --- a/libavdevice/sndio.c +++ b/libavdevice/sndio.c @@ -1,5 +1,5 @@ /* - * sndio play and grab interface + * sndio grab interface * Copyright (c) 2010 Jacob Meuser * * This file is part of Libav. @@ -22,9 +22,26 @@ #include #include +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" + #include "libavformat/avformat.h" +#include "libavformat/internal.h" -#include "libavdevice/sndio.h" +typedef struct SndioData { + AVClass *class; + struct sio_hdl *hdl; + enum AVCodecID codec_id; + int64_t hwpos; + int64_t softpos; + uint8_t *buffer; + int bps; + int buffer_size; + int buffer_offset; + int channels; + int sample_rate; +} SndioData; static inline void movecb(void *addr, int delta) { @@ -33,8 +50,8 @@ static inline void movecb(void *addr, int delta) s->hwpos += delta * s->channels * s->bps; } -av_cold int ff_sndio_open(AVFormatContext *s1, int is_output, - const char *audio_device) +static av_cold int sndio_open(AVFormatContext *s1, int is_output, + const char *audio_device) { SndioData *s = s1->priv_data; struct sio_hdl *hdl; @@ -109,8 +126,65 @@ fail: return AVERROR(EIO); } -int ff_sndio_close(SndioData *s) +static av_cold int audio_read_header(AVFormatContext *s1) +{ + SndioData *s = s1->priv_data; + AVStream *st; + int ret; + + st = avformat_new_stream(s1, NULL); + if (!st) + return AVERROR(ENOMEM); + + ret = sndio_open(s1, 0, s1->filename); + if (ret < 0) + return ret; + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + + return 0; +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + SndioData *s = s1->priv_data; + int64_t bdelay, cur_time; + int ret; + + if ((ret = av_new_packet(pkt, s->buffer_size)) < 0) + return ret; + + ret = sio_read(s->hdl, pkt->data, pkt->size); + if (ret == 0 || sio_eof(s->hdl)) { + av_packet_unref(pkt); + return AVERROR_EOF; + } + + pkt->size = ret; + s->softpos += ret; + + /* compute pts of the start of the packet */ + cur_time = av_gettime(); + + bdelay = ret + s->hwpos - s->softpos; + + /* convert to pts */ + pkt->pts = cur_time - ((bdelay * 1000000) / + (s->bps * s->channels * s->sample_rate)); + + return 0; +} + +static av_cold int audio_read_close(AVFormatContext *s1) { + SndioData *s = s1->priv_data; + av_freep(&s->buffer); if (s->hdl) @@ -118,3 +192,27 @@ int ff_sndio_close(SndioData *s) return 0; } + +static const AVOption options[] = { + { "sample_rate", "", offsetof(SndioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(SndioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass sndio_demuxer_class = { + .class_name = "sndio indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_sndio_demuxer = { + .name = "sndio", + .long_name = NULL_IF_CONFIG_SMALL("sndio audio capture"), + .priv_data_size = sizeof(SndioData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = audio_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &sndio_demuxer_class, +}; diff --git a/libavdevice/sndio.h b/libavdevice/sndio.h deleted file mode 100644 index cd5c55ecc5..0000000000 --- a/libavdevice/sndio.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * sndio play and grab interface - * Copyright (c) 2010 Jacob Meuser - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_SNDIO_H -#define AVDEVICE_SNDIO_H - -#include -#include - -#include "libavformat/avformat.h" -#include "libavutil/log.h" - -typedef struct SndioData { - AVClass *class; - struct sio_hdl *hdl; - enum AVCodecID codec_id; - int64_t hwpos; - int64_t softpos; - uint8_t *buffer; - int bps; - int buffer_size; - int buffer_offset; - int channels; - int sample_rate; -} SndioData; - -int ff_sndio_open(AVFormatContext *s1, int is_output, const char *audio_device); -int ff_sndio_close(SndioData *s); - -#endif /* AVDEVICE_SNDIO_H */ diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c deleted file mode 100644 index a839a6fab2..0000000000 --- a/libavdevice/sndio_dec.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * sndio play and grab interface - * Copyright (c) 2010 Jacob Meuser - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/time.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "libavdevice/sndio.h" - -static av_cold int audio_read_header(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(s1, NULL); - if (!st) - return AVERROR(ENOMEM); - - ret = ff_sndio_open(s1, 0, s1->filename); - if (ret < 0) - return ret; - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = s->codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - return 0; -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - SndioData *s = s1->priv_data; - int64_t bdelay, cur_time; - int ret; - - if ((ret = av_new_packet(pkt, s->buffer_size)) < 0) - return ret; - - ret = sio_read(s->hdl, pkt->data, pkt->size); - if (ret == 0 || sio_eof(s->hdl)) { - av_packet_unref(pkt); - return AVERROR_EOF; - } - - pkt->size = ret; - s->softpos += ret; - - /* compute pts of the start of the packet */ - cur_time = av_gettime(); - - bdelay = ret + s->hwpos - s->softpos; - - /* convert to pts */ - pkt->pts = cur_time - ((bdelay * 1000000) / - (s->bps * s->channels * s->sample_rate)); - - return 0; -} - -static av_cold int audio_read_close(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - - ff_sndio_close(s); - - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(SndioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(SndioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass sndio_demuxer_class = { - .class_name = "sndio indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_sndio_demuxer = { - .name = "sndio", - .long_name = NULL_IF_CONFIG_SMALL("sndio audio capture"), - .priv_data_size = sizeof(SndioData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = audio_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &sndio_demuxer_class, -}; From 6ce13070bddeb78fb2974ed94d28ef9424631817 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:18:58 +0200 Subject: [PATCH 2/5] oss: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/oss.c | 122 +++++++++++++++++++++++++++++++++-- libavdevice/oss.h | 45 ------------- libavdevice/oss_dec.c | 146 ------------------------------------------ 4 files changed, 117 insertions(+), 198 deletions(-) delete mode 100644 libavdevice/oss.h delete mode 100644 libavdevice/oss_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 18228f590f..c7c5a319ee 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -16,7 +16,7 @@ OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o -OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o +OBJS-$(CONFIG_OSS_INDEV) += oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o diff --git a/libavdevice/oss.c b/libavdevice/oss.c index e504438124..e2f0e87eac 100644 --- a/libavdevice/oss.c +++ b/libavdevice/oss.c @@ -28,15 +28,30 @@ #include #include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" - -#include "oss.h" - -int ff_oss_audio_open(AVFormatContext *s1, int is_output, - const char *audio_device) +#include "libavformat/internal.h" + +#define OSS_AUDIO_BLOCK_SIZE 4096 + +typedef struct OSSAudioData { + AVClass *class; + int fd; + int sample_rate; + int channels; + int frame_size; /* in bytes ! */ + enum AVCodecID codec_id; + unsigned int flip_left : 1; + uint8_t buffer[OSS_AUDIO_BLOCK_SIZE]; + int buffer_ptr; +} OSSAudioData; + +static int oss_audio_open(AVFormatContext *s1, int is_output, + const char *audio_device) { OSSAudioData *s = s1->priv_data; int audio_fd; @@ -126,8 +141,103 @@ int ff_oss_audio_open(AVFormatContext *s1, int is_output, #undef CHECK_IOCTL_ERROR } -int ff_oss_audio_close(OSSAudioData *s) +static int audio_read_header(AVFormatContext *s1) { + OSSAudioData *s = s1->priv_data; + AVStream *st; + int ret; + + st = avformat_new_stream(s1, NULL); + if (!st) { + return AVERROR(ENOMEM); + } + + ret = oss_audio_open(s1, 0, s1->filename); + if (ret < 0) { + return AVERROR(EIO); + } + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + return 0; +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + OSSAudioData *s = s1->priv_data; + int ret, bdelay; + int64_t cur_time; + struct audio_buf_info abufi; + + if ((ret=av_new_packet(pkt, s->frame_size)) < 0) + return ret; + + ret = read(s->fd, pkt->data, pkt->size); + if (ret <= 0){ + av_packet_unref(pkt); + pkt->size = 0; + if (ret<0) return AVERROR(errno); + else return AVERROR_EOF; + } + pkt->size = ret; + + /* compute pts of the start of the packet */ + cur_time = av_gettime(); + bdelay = ret; + if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) { + bdelay += abufi.bytes; + } + /* subtract time represented by the number of bytes in the audio fifo */ + cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); + + /* convert to wanted units */ + pkt->pts = cur_time; + + if (s->flip_left && s->channels == 2) { + int i; + short *p = (short *) pkt->data; + + for (i = 0; i < ret; i += 4) { + *p = ~*p; + p += 2; + } + } + return 0; +} + +static int audio_read_close(AVFormatContext *s1) +{ + OSSAudioData *s = s1->priv_data; + close(s->fd); return 0; } + +static const AVOption options[] = { + { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(OSSAudioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass oss_demuxer_class = { + .class_name = "OSS demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_oss_demuxer = { + .name = "oss", + .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"), + .priv_data_size = sizeof(OSSAudioData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = audio_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &oss_demuxer_class, +}; diff --git a/libavdevice/oss.h b/libavdevice/oss.h deleted file mode 100644 index 0fbe14b3ec..0000000000 --- a/libavdevice/oss.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_OSS_H -#define AVDEVICE_OSS_H - -#include "libavcodec/avcodec.h" - -#include "libavformat/avformat.h" - -#define OSS_AUDIO_BLOCK_SIZE 4096 - -typedef struct OSSAudioData { - AVClass *class; - int fd; - int sample_rate; - int channels; - int frame_size; /* in bytes ! */ - enum AVCodecID codec_id; - unsigned int flip_left : 1; - uint8_t buffer[OSS_AUDIO_BLOCK_SIZE]; - int buffer_ptr; -} OSSAudioData; - -int ff_oss_audio_open(AVFormatContext *s1, int is_output, - const char *audio_device); - -int ff_oss_audio_close(OSSAudioData *s); - -#endif /* AVDEVICE_OSS_H */ diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c deleted file mode 100644 index 6f51a30662..0000000000 --- a/libavdevice/oss_dec.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Linux audio play interface - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include - -#if HAVE_SOUNDCARD_H -#include -#else -#include -#endif - -#include -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/time.h" - -#include "libavcodec/avcodec.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "oss.h" - -static int audio_read_header(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(s1, NULL); - if (!st) { - return AVERROR(ENOMEM); - } - - ret = ff_oss_audio_open(s1, 0, s1->filename); - if (ret < 0) { - return AVERROR(EIO); - } - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = s->codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - return 0; -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - OSSAudioData *s = s1->priv_data; - int ret, bdelay; - int64_t cur_time; - struct audio_buf_info abufi; - - if ((ret=av_new_packet(pkt, s->frame_size)) < 0) - return ret; - - ret = read(s->fd, pkt->data, pkt->size); - if (ret <= 0){ - av_packet_unref(pkt); - pkt->size = 0; - if (ret<0) return AVERROR(errno); - else return AVERROR_EOF; - } - pkt->size = ret; - - /* compute pts of the start of the packet */ - cur_time = av_gettime(); - bdelay = ret; - if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) { - bdelay += abufi.bytes; - } - /* subtract time represented by the number of bytes in the audio fifo */ - cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); - - /* convert to wanted units */ - pkt->pts = cur_time; - - if (s->flip_left && s->channels == 2) { - int i; - short *p = (short *) pkt->data; - - for (i = 0; i < ret; i += 4) { - *p = ~*p; - p += 2; - } - } - return 0; -} - -static int audio_read_close(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - - ff_oss_audio_close(s); - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(OSSAudioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass oss_demuxer_class = { - .class_name = "OSS demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_oss_demuxer = { - .name = "oss", - .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"), - .priv_data_size = sizeof(OSSAudioData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = audio_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &oss_demuxer_class, -}; From d46cd2498614ae770f6c93e89f7665239b947e1c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:24:58 +0200 Subject: [PATCH 3/5] alsa: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/alsa.c | 190 +++++++++++++++++++++++++++++++++++++++-- libavdevice/alsa.h | 94 -------------------- libavdevice/alsa_dec.c | 178 -------------------------------------- 4 files changed, 182 insertions(+), 282 deletions(-) delete mode 100644 libavdevice/alsa.h delete mode 100644 libavdevice/alsa_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index c7c5a319ee..1160088c32 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -10,7 +10,7 @@ OBJS = alldevices.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # input devices -OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o +OBJS-$(CONFIG_ALSA_INDEV) += alsa.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index 81c94049cb..276a6c84cf 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -1,5 +1,5 @@ /* - * ALSA input and output + * ALSA input * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) * @@ -22,18 +22,39 @@ /** * @file - * ALSA input and output: common code + * ALSA input * @author Luca Abeni ( lucabe72 email it ) * @author Benoit Fouet ( benoit fouet free fr ) * @author Nicolas George ( nicolas george normalesup org ) */ #include -#include "libavformat/avformat.h" + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" +#include "libavutil/opt.h" + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" -#include "alsa.h" +/* XXX: we make the assumption that the soundcard accepts this format */ +/* XXX: find better solution with "preinit" method, needed also in + other formats */ +#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) + +#define ALSA_BUFFER_SIZE_MAX 32768 + +typedef struct AlsaData { + AVClass *class; + snd_pcm_t *h; + int frame_size; ///< preferred size for reads and writes + int period_size; ///< bytes per sample * channels + int sample_rate; ///< sample rate set by user + int channels; ///< number of channels set by user + void (*reorder_func)(const void *, void *, int); + void *reorder_buf; + int reorder_buf_size; ///< in frames +} AlsaData; static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id) { @@ -183,9 +204,23 @@ static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, return s->reorder_func ? 0 : AVERROR(ENOSYS); } -av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, - unsigned int *sample_rate, - int channels, enum AVCodecID *codec_id) +/** + * Open an ALSA PCM. + * + * @param s media file handle + * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK + * @param sample_rate in: requested sample rate; + * out: actually selected sample rate + * @param channels number of channels + * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE; + * out: actually selected AVCodecID, changed only if + * AV_CODEC_ID_NONE was requested + * + * @return 0 if OK, AVERROR_xxx on error + */ +static av_cold int alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, + unsigned int *sample_rate, + int channels, enum AVCodecID *codec_id) { AlsaData *s = ctx->priv_data; const char *audio_device; @@ -315,7 +350,14 @@ fail1: return AVERROR(EIO); } -av_cold int ff_alsa_close(AVFormatContext *s1) +/** + * Close the ALSA PCM. + * + * @param s1 media file handle + * + * @return 0 + */ +static av_cold int alsa_close(AVFormatContext *s1) { AlsaData *s = s1->priv_data; @@ -324,7 +366,15 @@ av_cold int ff_alsa_close(AVFormatContext *s1) return 0; } -int ff_alsa_xrun_recover(AVFormatContext *s1, int err) +/** + * Try to recover from ALSA buffer underrun. + * + * @param s1 media file handle + * @param err error code reported by the previous ALSA call + * + * @return 0 if OK, AVERROR_xxx on error + */ +static int alsa_xrun_recover(AVFormatContext *s1, int err) { AlsaData *s = s1->priv_data; snd_pcm_t *handle = s->h; @@ -344,3 +394,125 @@ int ff_alsa_xrun_recover(AVFormatContext *s1, int err) } return err; } + +static av_cold int audio_read_header(AVFormatContext *s1) +{ + AlsaData *s = s1->priv_data; + AVStream *st; + int ret; + enum AVCodecID codec_id; + snd_pcm_sw_params_t *sw_params; + + st = avformat_new_stream(s1, NULL); + if (!st) { + av_log(s1, AV_LOG_ERROR, "Cannot add stream\n"); + + return AVERROR(ENOMEM); + } + codec_id = s1->audio_codec_id; + + ret = alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels, + &codec_id); + if (ret < 0) { + return AVERROR(EIO); + } + + if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW) + av_log(s1, AV_LOG_WARNING, + "capture with some ALSA plugins, especially dsnoop, " + "may hang.\n"); + + ret = snd_pcm_sw_params_malloc(&sw_params); + if (ret < 0) { + av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n", + snd_strerror(ret)); + goto fail; + } + + snd_pcm_sw_params_current(s->h, sw_params); + snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE); + + ret = snd_pcm_sw_params(s->h, sw_params); + snd_pcm_sw_params_free(sw_params); + if (ret < 0) { + av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n", + snd_strerror(ret)); + goto fail; + } + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + + return 0; + +fail: + snd_pcm_close(s->h); + return AVERROR(EIO); +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + AlsaData *s = s1->priv_data; + AVStream *st = s1->streams[0]; + int res; + snd_htimestamp_t timestamp; + snd_pcm_uframes_t ts_delay; + + if (av_new_packet(pkt, s->period_size) < 0) { + return AVERROR(EIO); + } + + while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) { + if (res == -EAGAIN) { + av_packet_unref(pkt); + + return AVERROR(EAGAIN); + } + if (alsa_xrun_recover(s1, res) < 0) { + av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", + snd_strerror(res)); + av_packet_unref(pkt); + + return AVERROR(EIO); + } + } + + snd_pcm_htimestamp(s->h, &ts_delay, ×tamp); + ts_delay += res; + pkt->pts = timestamp.tv_sec * 1000000LL + + (timestamp.tv_nsec * st->codecpar->sample_rate + - (int64_t)ts_delay * 1000000000LL + st->codecpar->sample_rate * 500LL) + / (st->codecpar->sample_rate * 1000LL); + + pkt->size = res * s->frame_size; + + return 0; +} + +static const AVOption options[] = { + { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(AlsaData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass alsa_demuxer_class = { + .class_name = "ALSA demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_alsa_demuxer = { + .name = "alsa", + .long_name = NULL_IF_CONFIG_SMALL("ALSA audio input"), + .priv_data_size = sizeof(AlsaData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = alsa_close, + .flags = AVFMT_NOFILE, + .priv_class = &alsa_demuxer_class, +}; diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h deleted file mode 100644 index 773cd2faf8..0000000000 --- a/libavdevice/alsa.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ALSA input and output - * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) - * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * ALSA input and output: definitions and structures - * @author Luca Abeni ( lucabe72 email it ) - * @author Benoit Fouet ( benoit fouet free fr ) - */ - -#ifndef AVDEVICE_ALSA_H -#define AVDEVICE_ALSA_H - -#include -#include "config.h" -#include "libavformat/avformat.h" -#include "libavutil/log.h" - -/* XXX: we make the assumption that the soundcard accepts this format */ -/* XXX: find better solution with "preinit" method, needed also in - other formats */ -#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) - -#define ALSA_BUFFER_SIZE_MAX 32768 - -typedef struct AlsaData { - AVClass *class; - snd_pcm_t *h; - int frame_size; ///< preferred size for reads and writes - int period_size; ///< bytes per sample * channels - int sample_rate; ///< sample rate set by user - int channels; ///< number of channels set by user - void (*reorder_func)(const void *, void *, int); - void *reorder_buf; - int reorder_buf_size; ///< in frames -} AlsaData; - -/** - * Open an ALSA PCM. - * - * @param s media file handle - * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK - * @param sample_rate in: requested sample rate; - * out: actually selected sample rate - * @param channels number of channels - * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE; - * out: actually selected AVCodecID, changed only if - * AV_CODEC_ID_NONE was requested - * - * @return 0 if OK, AVERROR_xxx on error - */ -int ff_alsa_open(AVFormatContext *s, snd_pcm_stream_t mode, - unsigned int *sample_rate, - int channels, enum AVCodecID *codec_id); - -/** - * Close the ALSA PCM. - * - * @param s1 media file handle - * - * @return 0 - */ -int ff_alsa_close(AVFormatContext *s1); - -/** - * Try to recover from ALSA buffer underrun. - * - * @param s1 media file handle - * @param err error code reported by the previous ALSA call - * - * @return 0 if OK, AVERROR_xxx on error - */ -int ff_alsa_xrun_recover(AVFormatContext *s1, int err); - -#endif /* AVDEVICE_ALSA_H */ diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c deleted file mode 100644 index 58bf1dd6a1..0000000000 --- a/libavdevice/alsa_dec.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * ALSA input and output - * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) - * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * ALSA input and output: input - * @author Luca Abeni ( lucabe72 email it ) - * @author Benoit Fouet ( benoit fouet free fr ) - * @author Nicolas George ( nicolas george normalesup org ) - * - * This avdevice decoder allows to capture audio from an ALSA (Advanced - * Linux Sound Architecture) device. - * - * The filename parameter is the name of an ALSA PCM device capable of - * capture, for example "default" or "plughw:1"; see the ALSA documentation - * for naming conventions. The empty string is equivalent to "default". - * - * The capture period is set to the lower value available for the device, - * which gives a low latency suitable for real-time capture. - * - * The PTS are an Unix time in microsecond. - * - * Due to a bug in the ALSA library - * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4308), this - * decoder does not work with certain ALSA plugins, especially the dsnoop - * plugin. - */ - -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "alsa.h" - -static av_cold int audio_read_header(AVFormatContext *s1) -{ - AlsaData *s = s1->priv_data; - AVStream *st; - int ret; - enum AVCodecID codec_id; - snd_pcm_sw_params_t *sw_params; - - st = avformat_new_stream(s1, NULL); - if (!st) { - av_log(s1, AV_LOG_ERROR, "Cannot add stream\n"); - - return AVERROR(ENOMEM); - } - codec_id = s1->audio_codec_id; - - ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels, - &codec_id); - if (ret < 0) { - return AVERROR(EIO); - } - - if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW) - av_log(s1, AV_LOG_WARNING, - "capture with some ALSA plugins, especially dsnoop, " - "may hang.\n"); - - ret = snd_pcm_sw_params_malloc(&sw_params); - if (ret < 0) { - av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n", - snd_strerror(ret)); - goto fail; - } - - snd_pcm_sw_params_current(s->h, sw_params); - snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE); - - ret = snd_pcm_sw_params(s->h, sw_params); - snd_pcm_sw_params_free(sw_params); - if (ret < 0) { - av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n", - snd_strerror(ret)); - goto fail; - } - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - return 0; - -fail: - snd_pcm_close(s->h); - return AVERROR(EIO); -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - AlsaData *s = s1->priv_data; - AVStream *st = s1->streams[0]; - int res; - snd_htimestamp_t timestamp; - snd_pcm_uframes_t ts_delay; - - if (av_new_packet(pkt, s->period_size) < 0) { - return AVERROR(EIO); - } - - while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) { - if (res == -EAGAIN) { - av_packet_unref(pkt); - - return AVERROR(EAGAIN); - } - if (ff_alsa_xrun_recover(s1, res) < 0) { - av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", - snd_strerror(res)); - av_packet_unref(pkt); - - return AVERROR(EIO); - } - } - - snd_pcm_htimestamp(s->h, &ts_delay, ×tamp); - ts_delay += res; - pkt->pts = timestamp.tv_sec * 1000000LL - + (timestamp.tv_nsec * st->codecpar->sample_rate - - (int64_t)ts_delay * 1000000000LL + st->codecpar->sample_rate * 500LL) - / (st->codecpar->sample_rate * 1000LL); - - pkt->size = res * s->frame_size; - - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(AlsaData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass alsa_demuxer_class = { - .class_name = "ALSA demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_alsa_demuxer = { - .name = "alsa", - .long_name = NULL_IF_CONFIG_SMALL("ALSA audio input"), - .priv_data_size = sizeof(AlsaData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = ff_alsa_close, - .flags = AVFMT_NOFILE, - .priv_class = &alsa_demuxer_class, -}; From 543f00c78e6dc9fbb1ad83bfd8d57b5127cb4bac Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:28:33 +0200 Subject: [PATCH 4/5] avfoundation: Drop silly _dec suffix from filename --- libavdevice/Makefile | 2 +- libavdevice/{avfoundation_dec.m => avfoundation.m} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename libavdevice/{avfoundation_dec.m => avfoundation.m} (100%) diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 1160088c32..420fb065d2 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -11,7 +11,7 @@ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # input devices OBJS-$(CONFIG_ALSA_INDEV) += alsa.o -OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o +OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation.m similarity index 100% rename from libavdevice/avfoundation_dec.m rename to libavdevice/avfoundation.m From 762ab2de6ead68cfe6617d1960921878ddece9e1 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 26 Sep 2017 15:49:18 +0100 Subject: [PATCH 5/5] Remove dv1394 input device Support for this device has been removed in the Linux kernel since v2.6.37. dv1394 has been superseded by libiec61883 which is functionally equivalent. Signed-off-by: Josh de Kock Signed-off-by: Diego Biurrun --- configure | 3 - doc/general.texi | 1 - doc/indevs.texi | 4 - libavdevice/Makefile | 1 - libavdevice/alldevices.c | 1 - libavdevice/dv1394.c | 238 -------------------------- libavdevice/dv1394.h | 357 --------------------------------------- libavdevice/version.h | 2 +- 8 files changed, 1 insertion(+), 606 deletions(-) delete mode 100644 libavdevice/dv1394.c delete mode 100644 libavdevice/dv1394.h diff --git a/configure b/configure index 67354dc6a7..e45b3201fc 100755 --- a/configure +++ b/configure @@ -2433,8 +2433,6 @@ alsa_indev_deps="alsa" avfoundation_indev_deps="AVFoundation_AVFoundation_h objc_arc pthreads" avfoundation_indev_extralibs="-framework Foundation -framework AVFoundation -framework CoreVideo -framework CoreMedia" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" -dv1394_indev_deps="dv1394" -dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" jack_indev_deps="libjack" jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" @@ -4008,7 +4006,6 @@ case $target_os in add_cppflags -U__STRICT_ANSI__ ;; linux) - enable dv1394 enable section_data_rel_ro ;; irix*) diff --git a/doc/general.texi b/doc/general.texi index adf5b4eabf..6e39d5c1a0 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1067,7 +1067,6 @@ performance on systems without hardware floating point support). @item Name @tab Input @tab Output @item ALSA @tab X @tab X @item BKTR @tab X @tab -@item DV1394 @tab X @tab @item Linux framebuffer @tab X @tab @item JACK @tab X @tab @item LIBCDIO @tab X diff --git a/doc/indevs.texi b/doc/indevs.texi index a08c7a5f6b..7acdd8f3cc 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -55,10 +55,6 @@ For more information see: BSD video input device. -@section dv1394 - -Linux DV 1394 input device. - @section fbdev Linux framebuffer input device. diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 420fb065d2..8e533012d8 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -13,7 +13,6 @@ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o OBJS-$(CONFIG_ALSA_INDEV) += alsa.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o -OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o OBJS-$(CONFIG_OSS_INDEV) += oss.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 47d7421a06..151e977b85 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -41,7 +41,6 @@ void avdevice_register_all(void) REGISTER_INDEV(ALSA, alsa); REGISTER_INDEV(AVFOUNDATION, avfoundation); REGISTER_INDEV(BKTR, bktr); - REGISTER_INDEV(DV1394, dv1394); REGISTER_INDEV(FBDEV, fbdev); REGISTER_INDEV(JACK, jack); REGISTER_INDEV(OSS, oss); diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c deleted file mode 100644 index addf1ade67..0000000000 --- a/libavdevice/dv1394.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Linux DV1394 interface - * Copyright (c) 2003 Max Krasnyansky - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/log.h" -#include "libavutil/opt.h" -#include "libavformat/avformat.h" -#include "libavformat/dv.h" -#include "dv1394.h" - -struct dv1394_data { - AVClass *class; - int fd; - int channel; - int format; - - uint8_t *ring; /* Ring buffer */ - int index; /* Current frame index */ - int avail; /* Number of frames available for reading */ - int done; /* Number of completed frames */ - - DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */ -}; - -/* - * The trick here is to kludge around well known problem with kernel Ooopsing - * when you try to capture PAL on a device node configure for NTSC. That's - * why we have to configure the device node for PAL, and then read only NTSC - * amount of data. - */ -static int dv1394_reset(struct dv1394_data *dv) -{ - struct dv1394_init init; - - init.channel = dv->channel; - init.api_version = DV1394_API_VERSION; - init.n_frames = DV1394_RING_FRAMES; - init.format = DV1394_PAL; - - if (ioctl(dv->fd, DV1394_INIT, &init) < 0) - return -1; - - dv->avail = dv->done = 0; - return 0; -} - -static int dv1394_start(struct dv1394_data *dv) -{ - /* Tell DV1394 driver to enable receiver */ - if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to start receiver: %s\n", strerror(errno)); - return -1; - } - return 0; -} - -static int dv1394_read_header(AVFormatContext * context) -{ - struct dv1394_data *dv = context->priv_data; - - dv->dv_demux = avpriv_dv_init_demux(context); - if (!dv->dv_demux) - goto failed; - - /* Open and initialize DV1394 device */ - dv->fd = avpriv_open(context->filename, O_RDONLY); - if (dv->fd < 0) { - av_log(context, AV_LOG_ERROR, "Failed to open DV interface: %s\n", strerror(errno)); - goto failed; - } - - if (dv1394_reset(dv) < 0) { - av_log(context, AV_LOG_ERROR, "Failed to initialize DV interface: %s\n", strerror(errno)); - goto failed; - } - - dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES, - PROT_READ, MAP_PRIVATE, dv->fd, 0); - if (dv->ring == MAP_FAILED) { - av_log(context, AV_LOG_ERROR, "Failed to mmap DV ring buffer: %s\n", strerror(errno)); - goto failed; - } - - if (dv1394_start(dv) < 0) - goto failed; - - return 0; - -failed: - close(dv->fd); - return AVERROR(EIO); -} - -static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt) -{ - struct dv1394_data *dv = context->priv_data; - int size; - - size = avpriv_dv_get_packet(dv->dv_demux, pkt); - if (size > 0) - return size; - - if (!dv->avail) { - struct dv1394_status s; - struct pollfd p; - - if (dv->done) { - /* Request more frames */ - if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) { - /* This usually means that ring buffer overflowed. - * We have to reset :(. - */ - - av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n"); - - dv1394_reset(dv); - dv1394_start(dv); - } - dv->done = 0; - } - - /* Wait until more frames are available */ -restart_poll: - p.fd = dv->fd; - p.events = POLLIN | POLLERR | POLLHUP; - if (poll(&p, 1, -1) < 0) { - if (errno == EAGAIN || errno == EINTR) - goto restart_poll; - av_log(context, AV_LOG_ERROR, "Poll failed: %s\n", strerror(errno)); - return AVERROR(EIO); - } - - if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) { - av_log(context, AV_LOG_ERROR, "Failed to get status: %s\n", strerror(errno)); - return AVERROR(EIO); - } - av_log(context, AV_LOG_TRACE, "DV1394: status\n" - "\tactive_frame\t%d\n" - "\tfirst_clear_frame\t%d\n" - "\tn_clear_frames\t%d\n" - "\tdropped_frames\t%d\n", - s.active_frame, s.first_clear_frame, - s.n_clear_frames, s.dropped_frames); - - dv->avail = s.n_clear_frames; - dv->index = s.first_clear_frame; - dv->done = 0; - - if (s.dropped_frames) { - av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n", - s.dropped_frames); - - dv1394_reset(dv); - dv1394_start(dv); - } - } - - av_log(context, AV_LOG_TRACE, "index %d, avail %d, done %d\n", dv->index, dv->avail, - dv->done); - - size = avpriv_dv_produce_packet(dv->dv_demux, pkt, - dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE), - DV1394_PAL_FRAME_SIZE); - dv->index = (dv->index + 1) % DV1394_RING_FRAMES; - dv->done++; dv->avail--; - - return size; -} - -static int dv1394_close(AVFormatContext * context) -{ - struct dv1394_data *dv = context->priv_data; - - /* Shutdown DV1394 receiver */ - if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0) - av_log(context, AV_LOG_ERROR, "Failed to shutdown DV1394: %s\n", strerror(errno)); - - /* Unmap ring buffer */ - if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0) - av_log(context, AV_LOG_ERROR, "Failed to munmap DV1394 ring buffer: %s\n", strerror(errno)); - - close(dv->fd); - av_free(dv->dv_demux); - - return 0; -} - -static const AVOption options[] = { - { "standard", "", offsetof(struct dv1394_data, format), AV_OPT_TYPE_INT, {.i64 = DV1394_NTSC}, DV1394_NTSC, DV1394_PAL, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "PAL", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_PAL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "NTSC", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_NTSC}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "channel", "", offsetof(struct dv1394_data, channel), AV_OPT_TYPE_INT, {.i64 = DV1394_DEFAULT_CHANNEL}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass dv1394_class = { - .class_name = "DV1394 indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_dv1394_demuxer = { - .name = "dv1394", - .long_name = NULL_IF_CONFIG_SMALL("DV1394 A/V grab"), - .priv_data_size = sizeof(struct dv1394_data), - .read_header = dv1394_read_header, - .read_packet = dv1394_read_packet, - .read_close = dv1394_close, - .flags = AVFMT_NOFILE, - .priv_class = &dv1394_class, -}; diff --git a/libavdevice/dv1394.h b/libavdevice/dv1394.h deleted file mode 100644 index 9710ff56ea..0000000000 --- a/libavdevice/dv1394.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * DV input/output over IEEE 1394 on OHCI chips - * Copyright (C)2001 Daniel Maas - * receive, proc_fs by Dan Dennedy - * - * based on: - * video1394.h - driver for OHCI 1394 boards - * Copyright (C)1999,2000 Sebastien Rougeaux - * Peter Schlaile - * - * This file is part of Libav. - * - * 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. - * - * 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_DV1394_H -#define AVDEVICE_DV1394_H - -#define DV1394_DEFAULT_CHANNEL 63 -#define DV1394_DEFAULT_CARD 0 -#define DV1394_RING_FRAMES 20 - -#define DV1394_WIDTH 720 -#define DV1394_NTSC_HEIGHT 480 -#define DV1394_PAL_HEIGHT 576 - -/* This is the public user-space interface. Try not to break it. */ - -#define DV1394_API_VERSION 0x20011127 - -/* ******************** - ** ** - ** DV1394 API ** - ** ** - ******************** - - There are two methods of operating the DV1394 DV output device. - - 1) - - The simplest is an interface based on write(): simply write - full DV frames of data to the device, and they will be transmitted - as quickly as possible. The FD may be set for non-blocking I/O, - in which case you can use select() or poll() to wait for output - buffer space. - - To set the DV output parameters (e.g. whether you want NTSC or PAL - video), use the DV1394_INIT ioctl, passing in the parameters you - want in a struct dv1394_init. - - Example 1: - To play a raw .DV file: cat foo.DV > /dev/dv1394 - (cat will use write() internally) - - Example 2: - static struct dv1394_init init = { - 0x63, (broadcast channel) - 4, (four-frame ringbuffer) - DV1394_NTSC, (send NTSC video) - 0, 0 (default empty packet rate) - } - - ioctl(fd, DV1394_INIT, &init); - - while(1) { - read( , buf, DV1394_NTSC_FRAME_SIZE ); - write( , buf, DV1394_NTSC_FRAME_SIZE ); - } - - 2) - - For more control over buffering, and to avoid unnecessary copies - of the DV data, you can use the more sophisticated the mmap() interface. - First, call the DV1394_INIT ioctl to specify your parameters, - including the number of frames in the ringbuffer. Then, calling mmap() - on the dv1394 device will give you direct access to the ringbuffer - from which the DV card reads your frame data. - - The ringbuffer is simply one large, contiguous region of memory - containing two or more frames of packed DV data. Each frame of DV data - is 120000 bytes (NTSC) or 144000 bytes (PAL). - - Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES - ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl - or select()/poll() to wait until the frames are transmitted. Next, you'll - need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer - frames are clear (ready to be filled with new DV data). Finally, use - DV1394_SUBMIT_FRAMES again to send the new data to the DV output. - - - Example: here is what a four-frame ringbuffer might look like - during DV transmission: - - - frame 0 frame 1 frame 2 frame 3 - - *--------------------------------------* - | CLEAR | DV data | DV data | CLEAR | - *--------------------------------------* - - - transmission goes in this direction --->>> - - - The DV hardware is currently transmitting the data in frame 1. - Once frame 1 is finished, it will automatically transmit frame 2. - (if frame 2 finishes before frame 3 is submitted, the device - will continue to transmit frame 2, and will increase the dropped_frames - counter each time it repeats the transmission). - - - If you called DV1394_GET_STATUS at this instant, you would - receive the following values: - - n_frames = 4 - active_frame = 1 - first_clear_frame = 3 - n_clear_frames = 2 - - At this point, you should write new DV data into frame 3 and optionally - frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that - it may transmit the new frames. - - ERROR HANDLING - - An error (buffer underflow/overflow or a break in the DV stream due - to a 1394 bus reset) can be detected by checking the dropped_frames - field of struct dv1394_status (obtained through the - DV1394_GET_STATUS ioctl). - - The best way to recover from such an error is to re-initialize - dv1394, either by using the DV1394_INIT ioctl call, or closing the - file descriptor and opening it again. (note that you must unmap all - ringbuffer mappings when closing the file descriptor, or else - dv1394 will still be considered 'in use'). - - MAIN LOOP - - For maximum efficiency and robustness against bus errors, you are - advised to model the main loop of your application after the - following pseudo-code example: - - (checks of system call return values omitted for brevity; always - check return values in your code!) - - while( frames left ) { - - struct pollfd *pfd = ...; - - pfd->fd = dv1394_fd; - pfd->revents = 0; - pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive) - - (add other sources of I/O here) - - poll(pfd, 1, -1); (or select(); add a timeout if you want) - - if(pfd->revents) { - struct dv1394_status status; - - ioctl(dv1394_fd, DV1394_GET_STATUS, &status); - - if(status.dropped_frames > 0) { - reset_dv1394(); - } else { - int i; - for (i = 0; i < status.n_clear_frames; i++) { - copy_DV_frame(); - } - } - } - } - - where copy_DV_frame() reads or writes on the dv1394 file descriptor - (read/write mode) or copies data to/from the mmap ringbuffer and - then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new - frames are available (mmap mode). - - reset_dv1394() is called in the event of a buffer - underflow/overflow or a halt in the DV stream (e.g. due to a 1394 - bus reset). To guarantee recovery from the error, this function - should close the dv1394 file descriptor (and munmap() all - ringbuffer mappings, if you are using them), then re-open the - dv1394 device (and re-map the ringbuffer). - -*/ - - -/* maximum number of frames in the ringbuffer */ -#define DV1394_MAX_FRAMES 32 - -/* number of *full* isochronous packets per DV frame */ -#define DV1394_NTSC_PACKETS_PER_FRAME 250 -#define DV1394_PAL_PACKETS_PER_FRAME 300 - -/* size of one frame's worth of DV data, in bytes */ -#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME) -#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME) - - -/* ioctl() commands */ - -enum { - /* I don't like using 0 as a valid ioctl() */ - DV1394_INVALID = 0, - - - /* get the driver ready to transmit video. - pass a struct dv1394_init* as the parameter (see below), - or NULL to get default parameters */ - DV1394_INIT, - - - /* stop transmitting video and free the ringbuffer */ - DV1394_SHUTDOWN, - - - /* submit N new frames to be transmitted, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_SUBMIT_FRAMES, - - - /* block until N buffers are clear (pass N as the parameter) - Because we re-transmit the last frame on underrun, there - will at most be n_frames - 1 clear frames at any time */ - DV1394_WAIT_FRAMES, - - /* capture new frames that have been received, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_RECEIVE_FRAMES, - - - DV1394_START_RECEIVE, - - - /* pass a struct dv1394_status* as the parameter (see below) */ - DV1394_GET_STATUS, -}; - - - -enum pal_or_ntsc { - DV1394_NTSC = 0, - DV1394_PAL -}; - - - - -/* this is the argument to DV1394_INIT */ -struct dv1394_init { - /* DV1394_API_VERSION */ - unsigned int api_version; - - /* isochronous transmission channel to use */ - unsigned int channel; - - /* number of frames in the ringbuffer. Must be at least 2 - and at most DV1394_MAX_FRAMES. */ - unsigned int n_frames; - - /* send/receive PAL or NTSC video format */ - enum pal_or_ntsc format; - - /* the following are used only for transmission */ - - /* set these to zero unless you want a - non-default empty packet rate (see below) */ - unsigned long cip_n; - unsigned long cip_d; - - /* set this to zero unless you want a - non-default SYT cycle offset (default = 3 cycles) */ - unsigned int syt_offset; -}; - -/* NOTE: you may only allocate the DV frame ringbuffer once each time - you open the dv1394 device. DV1394_INIT will fail if you call it a - second time with different 'n_frames' or 'format' arguments (which - would imply a different size for the ringbuffer). If you need a - different buffer size, simply close and re-open the device, then - initialize it with your new settings. */ - -/* Q: What are cip_n and cip_d? */ - -/* - A: DV video streams do not utilize 100% of the potential bandwidth offered - by IEEE 1394 (FireWire). To achieve the correct rate of data transmission, - DV devices must periodically insert empty packets into the 1394 data stream. - Typically there is one empty packet per 14-16 data-carrying packets. - - Some DV devices will accept a wide range of empty packet rates, while others - require a precise rate. If the dv1394 driver produces empty packets at - a rate that your device does not accept, you may see ugly patterns on the - DV output, or even no output at all. - - The default empty packet insertion rate seems to work for many people; if - your DV output is stable, you can simply ignore this discussion. However, - we have exposed the empty packet rate as a parameter to support devices that - do not work with the default rate. - - The decision to insert an empty packet is made with a numerator/denominator - algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D. - You can alter the empty packet rate by passing non-zero values for cip_n - and cip_d to the INIT ioctl. - - */ - - - -struct dv1394_status { - /* this embedded init struct returns the current dv1394 - parameters in use */ - struct dv1394_init init; - - /* the ringbuffer frame that is currently being - displayed. (-1 if the device is not transmitting anything) */ - int active_frame; - - /* index of the first buffer (ahead of active_frame) that - is ready to be filled with data */ - unsigned int first_clear_frame; - - /* how many buffers, including first_clear_buffer, are - ready to be filled with data */ - unsigned int n_clear_frames; - - /* how many times the DV stream has underflowed, overflowed, - or otherwise encountered an error, since the previous call - to DV1394_GET_STATUS */ - unsigned int dropped_frames; - - /* N.B. The dropped_frames counter is only a lower bound on the actual - number of dropped frames, with the special case that if dropped_frames - is zero, then it is guaranteed that NO frames have been dropped - since the last call to DV1394_GET_STATUS. - */ -}; - - -#endif /* AVDEVICE_DV1394_H */ diff --git a/libavdevice/version.h b/libavdevice/version.h index e09a23cf67..3427d206cd 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 57 #define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 1 +#define LIBAVDEVICE_VERSION_MICRO 2 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \