[FFmpeg-devel] [PATCH] lavd/alsa: implement get_device_list callbacks

Lukasz Marek lukasz.m.luki2 at gmail.com
Sat Oct 18 20:36:22 CEST 2014


---
 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);
+
+    if (snd_device_name_hint(-1, "pcm", &hints) < 0)
+        return AVERROR_EXTERNAL;
+    n = hints;
+    while (*n) {
+        name = snd_device_name_get_hint(*n, "NAME");
+        descr = snd_device_name_get_hint(*n, "DESC");
+        io = snd_device_name_get_hint(*n, "IOID");
+        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 */
-- 
1.9.1



More information about the ffmpeg-devel mailing list