It appears that Gstreamer-1.0 can't access raw uaudio(4) devices (rsnd/n).
I'm struggling to debug further so wanted to ask if this is expected to
work or a known limitation of OpenBSD's sndio(7) implementation for
gstreamer?
This is where I've got to so far:
Gstreamer-1.0 works fine with uaudio(4) devices exposed by sndiod(8) (e.g.
snd/n) but fails with the raw (rsnd/n) device. Once gstreamer has attempted
to use the raw device, the uaudio(4) device is left in an unuseable state
until it is hard reset (unplug / replug).
I've tested several uaudio(4) USB-2 class-compliant devices (Focusrite,
Tascam, M-Audio) on different amd64 -current hosts and the problem appears
to be reproducible on all of them. So it looks like a
gstreamer+sndio+uaudio specific issue?
A simple test to demonstrate would be:
Terminate any running sndiod(8).
env AUDIODEVICE=rsnd/1 gst-launch-1.0 -v sndiosrc ! fakesink
--gst-debug=sndio:9
0:00:00.103475000 21585 0x37af4e42210 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
0:00:00.103918000 21585 0x37af4e42210 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
Setting pipeline to PAUSED ...
0:00:00.105188000 21585 0x37af4e42210 DEBUG sndio gstsndio.c:111:gboolean
gst_sndio_open(struct gstsndio *, gint):<sndiosrc0> open
0:00:00.105580000 21585 0x37af4e42210 WARN sndio gstsndio.c:123:gboolean
gst_sndio_open(struct gstsndio *, gint):0x37b29982c00 error: Couldn't get
device capabilities
(gst-launch-1.0:21585): GStreamer-CRITICAL **:
gst_element_message_full_with_details: assertion 'GST_IS_ELEMENT (element)'
failed
ERROR: Pipeline doesn't want to pause.
Setting pipeline to NULL ...
Freeing pipeline ...
Now, nothing but a hard reset will get the uaudio device working correctly
again. Any further attempts to access the uaudio(4) device returns a
'failed to open device' error. (examples below with both gstreamer and
sndiod)
Other, non gstreamer-1.0 code seems to be unaffected e.g. Audacity will
happily open and use the raw (rsnd/n) device without any apparent error.
The gstreamer code is a bit odd as sndio(7) support is 'patched in' by the
OpenBSD port's Makefile. It fails at gst_sndio_open->sio_getcap in
gstsndio.c:
gboolean
gst_sndio_open (struct gstsndio *sio, gint mode)
{
GValue list = G_VALUE_INIT, item = G_VALUE_INIT;
GstStructure *s;
GstCaps *caps;
struct sio_enc *enc;
struct sio_cap cap;
char fmt[16];
int i, chan;
GST_DEBUG_OBJECT (sio->obj, "open");
sio->hdl = sio_open (sio->device, mode, 0);
if (sio->hdl == NULL) {
GST_ELEMENT_ERROR (sio->obj, RESOURCE, OPEN_READ_WRITE,
("Couldn't open sndio device"), (NULL));
return FALSE;
}
sio->mode = mode;
if (!sio_getcap(sio->hdl, &cap)) { /* Fails here */
GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE,
("Couldn't get device capabilities"), (NULL));
sio_close(sio->hdl);
sio->hdl = NULL;
return FALSE;
}
All further attempts to open the audio(4) device fail, with either
gstreamer or sndiod(8):
env AUDIODEVICE=rsnd/1 gst-launch-1.0 -v sndiosrc ! fakesink
--gst-debug=sndio:9
0:00:00.100955000 86224 0x122e996b8810 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
0:00:00.101160000 86224 0x122e996b8810 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
Setting pipeline to PAUSED ...
0:00:00.101781000 86224 0x122e996b8810 DEBUG sndio gstsndio.c:111:gboolean
gst_sndio_open(struct gstsndio *, gint):<sndiosrc0> open
0:00:00.103892000 86224 0x122e996b8810 WARN sndio gstsndio.c:116:gboolean
gst_sndio_open(struct gstsndio *, gint):<sndiosrc0> error: Couldn't open
sndio device
ERROR: Pipeline doesn't want to pause.
ERROR: from element /GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: Couldn't
open sndio device
Additional debug info:
gstsndio.c(116): gboolean gst_sndio_open(struct gstsndio *, gint) ():
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0
Setting pipeline to NULL ...
Freeing pipeline ...
# sndiod -ddd -f rsnd/1
snd0 pst=cfg.default: rec=0:1 dup
helper(helper|ini): created
worker(worker|ini): created
listen(/tmp/aucat/aucat0|ini): created
sock(sock|ini): created
sock,rmsg,widl: AUTH message
sock,rmsg,widl: HELLO message
sock,rmsg,widl: hello from <gst-launch->, mode = 2, ver 7
sock,rmsg,widl: using snd0 pst=cfg.default, mode = 2
gstlaun0: overwritten slot 0
snd0 pst=cfg: device requested
worker: send: cmd = 0, num = 0, mode = 2, fd = -1
worker: recv: cmd = 3, num = 0, mode = 0, fd = -1
snd0 pst=cfg: rsnd/1: failed to open audio device
sock,rmsg,widl: closing
sock(sock|zom): destroyed
helper: recv: cmd = 0, num = 0, mode = 2, fd = -1
helper: send: cmd = 3, num = 0, mode = 0, fd = -1
^Cworker(worker|zom): destroyed
listen(/tmp/aucat/aucat0|zom): destroyed
snd0 pst=cfg: draining
nothing to do...
snd0 pst=cfg: deleting
helper: hup
helper(helper|zom): destroyed
nothing to do...
If you unplug and re-plug the uaudio(4), start sndiod(8) and set gstreamer
to use the snd/n device, all is good again:
# sndiod -ddd -f rsnd/1
snd0 pst=cfg.default: rec=0:1 dup
helper(helper|ini): created
worker(worker|ini): created
listen(/tmp/aucat/aucat0|ini): created
sock(sock|ini): created
sock,rmsg,widl: AUTH message
helper: recv: cmd = 0, num = 0, mode = 2, fd = -1
helper: send: cmd = 3, num = 0, mode = 0, fd = 3
sock,rmsg,widl: HELLO message
sock,rmsg,widl: hello from <gst-launch->, mode = 2, ver 7
sock,rmsg,widl: using snd0 pst=cfg.default, mode = 2
gstlaun0: overwritten slot 0
snd0 pst=cfg: device requested
worker: send: cmd = 0, num = 0, mode = 2, fd = -1
worker: recv: cmd = 3, num = 0, mode = 0, fd = 6
sio(rsnd/1|ini): created
dec: s24le3, 2 channels
snd0 pst=ini: 48000Hz, s24le3, rec 0:1, 8 blocks of 960 frames
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: SETPAR message
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: recording channels 0:1 -> 0:1
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: 44100Hz sample rate, 882 frame
blocks
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: 8820 frame buffer
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: GETPAR message
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: GETPAR message
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: START message
gstlaun0 vol=127,pst=ini,mmc=off: recording s16le <- s24le3
gstlaun0 vol=127,pst=ini,mmc=off: allocated 8820/15876 fr buffers
snd0 pst=ini: device started
snd0 pst=run: started
gstlaun0 vol=127,pst=run,mmc=off: attached at 0, delta = 0
cmap: nch = 2, ostart = 0, onext = 0, istart = 0, inext = 0
resamp: 960/882
gstlaun0 vol=127,pst=run,mmc=off: 44100Hz, s16le, rec 0:1, 10 blocks of 882
frames
sock(sock|ini): processed in 6309us
gstlaun0 vol=127,pst=run,mmc=off,rmsg,widl: building SETVOL message, vol =
127
gstlaun0 vol=127,pst=run,mmc=off,rmsg,widl: STOP message
gstlaun0 vol=127,pst=run,mmc=off: stopping
gstlaun0 vol=127,pst=run,mmc=off: detaching
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: stopped
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: building STOP message
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: BYE message
gstlaun0 vol=127,pst=ini,mmc=off,rmsg,widl: closing
snd0 pst=run: device released
sock(sock|zom): destroyed
snd0 pst=run: device stopped
snd0 pst=run: stopped, load avg = 6957 / 162320
snd0 pst=ini: closing
snd0 pst=cfg: closed
sio(rsnd/1|zom): destroyed
sio(rsnd/1|zom): processed in 23004us
^Cworker(worker|zom): destroyed
listen(/tmp/aucat/aucat0|zom): destroyed
snd0 pst=cfg: draining
nothing to do...
snd0 pst=cfg: deleting
helper: hup
helper(helper|zom): destroyed
nothing to do...
$ env AUDIODEVICE=snd/0 gst-launch-1.0 -v sndiosrc ! fakesink
--gst-debug=sndio:9
0:00:00.099699000 94966 0x15a533946c10 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
0:00:00.099898000 94966 0x15a533946c10 LOG sndio gstsndio.c:77:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> getcaps
called, returning template caps
Setting pipeline to PAUSED ...
0:00:00.100517000 94966 0x15a533946c10 DEBUG sndio gstsndio.c:111:gboolean
gst_sndio_open(struct gstsndio *, gint):<sndiosrc0> open
0:00:00.101631000 94966 0x15a533946c10 DEBUG sndio gstsndio.c:213:gboolean
gst_sndio_open(struct gstsndio *, gint): caps are audio/x-raw, rate=(int){
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200,
96000, 128000, 176400, 192000 }, channels=(int){ 1, 2, 4, 6, 8, 10, 12, 16
}, format=(string){ S8, U8, S16BE, S16LE, S24BE, S24LE },
layout=(string)interleaved
Pipeline is live and does not need PREROLL ...
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: mute = false
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: volume = 1
Setting pipeline to PLAYING ...
New clock: GstAudioSrcClock
0:00:00.105053000 94966 0x15a5da9bb630 LOG sndio gstsndio.c:81:GstCaps
*gst_sndio_getcaps(struct gstsndio *, GstCaps *):<sndiosrc0> returning
audio/x-raw, rate=(int){ 8000, 11025, 12000, 16000, 22050, 24000, 32000,
44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 },
channels=(int){ 1, 2, 4, 6, 8, 10, 12, 16 }, format=(string){ S8, U8,
S16BE, S16LE, S24BE, S24LE }, layout=(string)interleaved
0:00:00.105411000 94966 0x15a5da9bb630 DEBUG sndio gstsndio.c:246:gboolean
gst_sndio_prepare(struct gstsndio *, GstAudioRingBufferSpec
*):0x15a5f8656400 prepare
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: actual-buffer-time = 360000
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: actual-latency-time = 20000
Redistribute latency...
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0.GstPad:src: caps =
audio/x-raw, rate=(int)44100, channels=(int)2, format=(string)S16LE,
layout=(string)interleaved
/GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps =
audio/x-raw, rate=(int)44100, channels=(int)2, format=(string)S16LE,
layout=(string)interleaved
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: mute = false
/GstPipeline:pipeline0/GstSndioSrc:sndiosrc0: volume = 1
Got EOS from element "pipeline0".
Execution ended after 0:00:00.139063000
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
0:00:00.259600000 94966 0x15a533946c10 DEBUG sndio gstsndio.c:220:gboolean
gst_sndio_close(struct gstsndio *):<sndiosrc0> close
Freeing pipeline ...