[FFmpeg-devel] [PATCH] lavd/alsa: implement get_device_list callbacks
Nicolas George
george at nsup.org
Wed Oct 22 11:53:22 CEST 2014
Le septidi 27 vendémiaire, an CCXXIII, Lukasz Marek a écrit :
> ---
> libavdevice/alsa-audio-common.c | 60 +++++++++++++++++++++++++++++++++++++++++
> libavdevice/alsa-audio-dec.c | 6 +++++
> libavdevice/alsa-audio-enc.c | 6 +++++
> libavdevice/alsa-audio.h | 2 ++
> 4 files changed, 74 insertions(+)
>
> diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c
> index 4e63397..1061917 100644
> --- a/libavdevice/alsa-audio-common.c
> +++ b/libavdevice/alsa-audio-common.c
> @@ -343,3 +343,63 @@ int ff_alsa_extend_reorder_buf(AlsaData *s, int min_size)
> s->reorder_buf_size = size;
> return 0;
> }
> +
> +/* ported from alsa-utils/aplay.c */
> +int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type)
> +{
> + int ret;
> + void **hints, **n;
> + char *name = NULL, *descr = NULL, *io = NULL, *tmp;
> + AVDeviceInfo *new_device = NULL;
> + const char *filter = stream_type == SND_PCM_STREAM_PLAYBACK ? "Output" : "Input";
> +
> + av_log(NULL, AV_LOG_INFO, "%s\n", filter);
Stray?
> +
> + if (snd_device_name_hint(-1, "pcm", &hints) < 0)
> + return AVERROR_EXTERNAL;
> + n = hints;
> + while (*n) {
Can hints be NULL here? If so, you need to init "ret = 0", otherwise you are
using it uninitialized at the end.
> + name = snd_device_name_get_hint(*n, "NAME");
> + descr = snd_device_name_get_hint(*n, "DESC");
> + io = snd_device_name_get_hint(*n, "IOID");
I suspect you need to av_strdup() all these strings, as av_free() may not be
compatible with the plain free() needed for the strings returned by ALSA
(for example with CONFIG_MEMALIGN_HACK).
> + if (!io || !strcmp(io, filter)) {
> + new_device = av_mallocz(sizeof(AVDeviceInfo));
> + if (!new_device) {
> + ret = AVERROR(ENOMEM);
> + goto fail;
> + }
> + new_device->device_name = name;
> + name = NULL;
> + if ((tmp = strrchr(descr, '\n')) && tmp[1]) {
> + new_device->device_description = av_strdup(&tmp[1]);
> + if (!new_device->device_description) {
> + ret = AVERROR(ENOMEM);
> + goto fail;
> + }
> + } else {
> + new_device->device_description = descr;
> + descr = NULL;
> + }
> + if ((ret = av_dynarray_add_nofree(&device_list->devices,
> + &device_list->nb_devices, new_device)) < 0) {
> + goto fail;
> + }
> + new_device = NULL;
> + }
> + av_freep(&io);
> + av_freep(&name);
> + av_freep(&descr);
> + n++;
> + }
> + fail:
> + av_free(io);
> + av_free(name);
> + av_free(descr);
> + if (new_device) {
> + av_free(new_device->device_description);
> + av_free(new_device->device_name);
> + av_free(new_device);
> + }
> + snd_device_name_free_hint(hints);
> + return ret;
> +}
> diff --git a/libavdevice/alsa-audio-dec.c b/libavdevice/alsa-audio-dec.c
> index 2cdf356..7f8f8cd 100644
> --- a/libavdevice/alsa-audio-dec.c
> +++ b/libavdevice/alsa-audio-dec.c
> @@ -132,6 +132,11 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
> return 0;
> }
>
> +static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
> +{
> + return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_CAPTURE);
> +}
> +
> 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 },
> @@ -153,6 +158,7 @@ AVInputFormat ff_alsa_demuxer = {
> .read_header = audio_read_header,
> .read_packet = audio_read_packet,
> .read_close = ff_alsa_close,
> + .get_device_list = audio_get_device_list,
> .flags = AVFMT_NOFILE,
> .priv_class = &alsa_demuxer_class,
> };
> diff --git a/libavdevice/alsa-audio-enc.c b/libavdevice/alsa-audio-enc.c
> index e42cc8f..43d097d 100644
> --- a/libavdevice/alsa-audio-enc.c
> +++ b/libavdevice/alsa-audio-enc.c
> @@ -142,6 +142,11 @@ audio_get_output_timestamp(AVFormatContext *s1, int stream,
> *dts = s->timestamp - delay;
> }
>
> +static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
> +{
> + return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_PLAYBACK);
> +}
> +
> static const AVClass alsa_muxer_class = {
> .class_name = "ALSA muxer",
> .item_name = av_default_item_name,
> @@ -159,6 +164,7 @@ AVOutputFormat ff_alsa_muxer = {
> .write_packet = audio_write_packet,
> .write_trailer = ff_alsa_close,
> .write_uncoded_frame = audio_write_frame,
> + .get_device_list = audio_get_device_list,
> .get_output_timestamp = audio_get_output_timestamp,
> .flags = AVFMT_NOFILE,
> .priv_class = &alsa_muxer_class,
> diff --git a/libavdevice/alsa-audio.h b/libavdevice/alsa-audio.h
> index 583c911..cf0e942 100644
> --- a/libavdevice/alsa-audio.h
> +++ b/libavdevice/alsa-audio.h
> @@ -99,4 +99,6 @@ int ff_alsa_xrun_recover(AVFormatContext *s1, int err);
>
> int ff_alsa_extend_reorder_buf(AlsaData *s, int size);
>
> +int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type);
> +
> #endif /* AVDEVICE_ALSA_AUDIO_H */
The rest looks good to me, but I have not checked the actual output. If you
have a working test tree, can you show the output on a typical system?
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20141022/5715e28b/attachment.asc>
More information about the ffmpeg-devel
mailing list