Menu

#314 sndio output not working on FreeBSD

svn
closed-fixed
nobody
None
5
2021-07-12
2021-06-06
No

With mpg123 1.28.0 I noticed that sndio output is not working:

High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
        version 1.28.0; written and copyright by Michael Hipp and others
        free software (LGPL) without any warranty but with best wishes
Decoder: x86-64 (AVX)
Trying output module: sndio, device: <nil>
Module dir search relative to: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs
Looking for module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../lib/mpg123
Looking for module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/plugins
Looking for module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/libout123/modules/.libs
Looking for module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/libout123/modules
Looking for module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs
Module dir: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs
Module path: /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs/output_sndio.so
Note: sndio is the last output option... showing you any error messages now.
[src/libout123/libout123.c:out123_open():485] error: Found no driver out of [sndio] working with device <default>.
main: [src/mpg123.c:check_fatal_output():332] error: out123 error 3: failure loading driver module

Also attaching same output with debugging enabled.

It was configured with:
./configure --with-optimization=0 --with-audio=sndio,oss --with-default-audio=sndio --with-cpu=x86-64 --prefix=/usr/local --localstatedir=/var --mandir=/usr/local/man --disable-silent-rules --infodir=/usr/local/share/info/ --build=amd64-portbld-freebsd14.0

Compiler version is:
FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)

nm(1) output for sndio and oss (which works fine) modules:

(09:53) novel@kloomba:~/ports/audio/mpg123/work/mpg123-1.28.0/src[novel-mpg123-1.28.0] %> nm /home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs/output_(oss|sndio).so

/home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs/output_oss.so:
00000000000023b0 t INT123_compat_strdup 
0000000000002340 t INT123_safe_realloc
0000000000002360 t INT123_safer_realloc
0000000000003560 d _DYNAMIC         
                 w _Jv_RegisterClasses
0000000000003538 d __CTOR_END__
0000000000003530 d __CTOR_LIST__
0000000000003548 d __DTOR_END__
0000000000003540 d __DTOR_LIST__
0000000000003550 d __JCR_END__
0000000000003550 d __JCR_LIST__
                 w __cxa_finalize   
0000000000002400 t __do_global_ctors_aux
0000000000001c10 t __do_global_dtors_aux
0000000000004710 d __dso_handle
                 U __stack_chk_fail         
                 U __stack_chk_guard
                 U __stderrp
000000000000243c t _fini           
000000000000242c t _init    
                 U close  
0000000000002330 t close_oss 
00000000000020b0 t flush_oss  
                 U fprintf 
                 U free      
00000000000020d0 t get_formats_oss
0000000000000870 r get_formats_oss.fmts
0000000000001c90 t init_oss
                 U ioctl      
                 U malloc                                                                                 
                 U memcpy
0000000000004718 D mpg123_output_module_info
                 U open
0000000000001ce0 t open_oss
                 U realloc
0000000000001c60 t register_classes
                 U strlen
                 U write
00000000000020c0 t write_oss

/home/novel/ports/audio/mpg123/work/mpg123-1.28.0/src/.libs/../libout123/modules/.libs/output_sndio.so:
0000000000001fa0 t INT123_compat_strdup
0000000000001f30 t INT123_safe_realloc
0000000000001f50 t INT123_safer_realloc
0000000000003190 d _DYNAMIC
                 w _Jv_RegisterClasses
0000000000003168 d __CTOR_END__
0000000000003160 d __CTOR_LIST__
0000000000003178 d __DTOR_END__
0000000000003170 d __DTOR_LIST__
0000000000003180 d __JCR_END__
0000000000003180 d __JCR_LIST__
                 w __cxa_finalize
0000000000001ff0 t __do_global_ctors_aux
0000000000001bb0 t __do_global_dtors_aux
0000000000004350 d __dso_handle
                 U __stack_chk_fail
                 U __stack_chk_guard
                 U __stderrp
000000000000202c t _fini
000000000000201c t _init
0000000000001f10 t close_sndio
0000000000001eb0 t flush_sndio
                 U fprintf
                 U free
0000000000001f00 t get_formats_sndio
0000000000001c30 t init_sndio
                 U malloc
                 U memcpy
0000000000004358 D mpg123_output_module_info
0000000000001c80 t open_sndio
                 U realloc
0000000000001c00 t register_classes
                 U sio_close
                 U sio_eof
                 U sio_getpar
                 U sio_initpar
                 U sio_open
                 U sio_setpar
                 U sio_start
                 U sio_write
                 U strlen
0000000000001ec0 t write_sndio

Also I noticed that sndio wasn't working in 1.27.2 too, so the difference is probably a fallback mechanism in 1.28. I've read about --with-(default-)audio changes, it was a little confusing though, need to play around with that.

Please let me know if any additional info is needed.

1 Attachments

Discussion

1 2 > >> (Page 1 of 2)
  • Thomas Orgis

    Thomas Orgis - 2021-06-07

    When was it last seen working for you? It works for me (without sndiod).

    I added some more error messages in svn trunk. Can you build from that and re-test? Configure is generated just with autoreconf -iv, with the autotools present, of course.

     
  • Roman Bogorodskiy

    When was it last seen working for you?

    Don't recall offhand, will test later.

    It works for me (without sndiod).

    Hm, now when you mentioned sndiod, I noticed that it starts working for me after starting sndiod. When I stop it, things stop working again.

    I added some more error messages in svn trunk. Can you build from that and re-test?

    High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
            version 1.28.0; written and copyright by Michael Hipp and others
            free software (LGPL) without any warranty but with best wishes
    Decoder: generic
    Trying output module: sndio, device: <nil>
    Module dir search relative to: /home/novel/code/mpg123/trunk/src/.libs
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/../lib/mpg123
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/plugins
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/libout123/modules/.libs
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/libout123/modules
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs
    Module dir: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs
    Module path: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs/output_sndio.so
    Note: sndio is the last output option... showing you any error messages now.
    [src/libout123/modules/sndio.c:open_sndio():79] error: parameter setup  failure
    [src/libout123/libout123.c:check_output_module():984] error: Module 'sndio' device open failed.
    [src/libout123/libout123.c:out123_open():485] error: Found no driver out of [sndio] working with device <default>.
    main: [src/mpg123.c:check_fatal_output():332] error: out123 error 3: failure loading driver module
    

    I guess [src/libout123/modules/sndio.c:open_sndio():79] error: parameter setup failure is what we're looking for?

    I'm not sure if that's the issue that if it works with sndiod running, I guess I need to change --with-default-audio value from sndio to sndio,oss to keep the old behavior when mpg123 falls back to oss?

     

    Last edit: Roman Bogorodskiy 2021-06-07
  • Thomas Orgis

    Thomas Orgis - 2021-06-07

    Yes, that seems to be the issue. Your hardware does not support signed 16 bit encoding, by any chance?

    Do you get more information when setting SIO_DEBUG=2 in the environment?

    Regarding --with-default-audio … just use --with-audio=sndio,oss. If you don't set --with-default-audio, it's the same.

     
  • Roman Bogorodskiy

    Your hardware does not support signed 16 bit encoding, by any chance?

    How can I check that?

    Do you get more information when setting SIO_DEBUG=2 in the environment?

    Looks like the right flag for my setup is SNDIO_DEBUG and it does provide some additional info:

    Module path: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs/output_sndio.so
    Note: sndio is the last output option... showing you any error messages now.
    _aucat_open: host= unit=0 devnum=0 opt=default
    /tmp/sndio-1001/sock0: No such file or directory
    /tmp/sndio/sock0: No such file or directory
    sio_oss_setpar: CHANNELS: Invalid argument
    [src/libout123/modules/sndio.c:open_sndio():79] error: parameter setup  failure
    

    Regarding --with-default-audio … just use --with-audio=sndio,oss. If you don't set --with-default-audio, it's the same.

    Great, thanks for the info.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-08

    Please have a go with the current https://mpg123.org/snapshot/ . I had to fix up the whole format detection stuff. On my system, it correctly sees the hardware support now (only 44.1 and 48 kHz stereo).

     
  • Roman Bogorodskiy

    I've tried the latest svn version (r4946), assuming it's not older than the snapshot.
    The problem still remains:

    (10:33) novel@kloomba:~/code/mpg123/trunk/src %> SNDIO_DEBUG=2 ./mpg123 -o sndio -vv ~/test.mp3
    High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
            version 1.28.0; written and copyright by Michael Hipp and others
            free software (LGPL) without any warranty but with best wishes
    Decoder: generic
    Trying output module: sndio, device: <nil>
    Module dir search relative to: /home/novel/code/mpg123/trunk/src/.libs
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/../lib/mpg123
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/plugins
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/libout123/modules/.libs
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/libout123/modules
    Looking for module dir: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs
    Module dir: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs
    Module path: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs/output_sndio.so
    Note: sndio is the last output option... showing you any error messages now.
    _aucat_open: host= unit=0 devnum=0 opt=default
    /tmp/sndio-1001/sock0: No such file or directory
    /tmp/sndio/sock0: No such file or directory
    sio_oss_setpar: CHANNELS: Invalid argument
    [src/libout123/modules/sndio.c:open_sndio():127] error: parameter setup  failure
    [src/libout123/libout123.c:check_output_module():984] error: Module 'sndio' device open failed.
    [src/libout123/libout123.c:out123_open():485] error: Found no driver out of [sndio] working with device <default>.
    main: [src/mpg123.c:check_fatal_output():332] error: out123 error 3: failure loading driver module
    (10:34) novel@kloomba:~/code/mpg123/trunk/src %> 
    

    BTW, my sound device info is:

    (10:34) novel@kloomba:~/code/mpg123/trunk/src %> cat /dev/sndstat 
    Installed devices:
    pcm0: <Realtek ALC887 (Rear Analog 7.1/2.0)> (play/rec) default
    pcm1: <Realtek ALC887 (Front Analog)> (play/rec)
    pcm2: <Realtek ALC887 (Onboard Digital)> (play)
    pcm3: <Intel Kaby Lake (HDMI/DP 8ch)> (play)
    No devices installed from userspace.
    (10:34) novel@kloomba:~/code/mpg123/trunk/src %> 
    
     
  • Thomas Orgis

    Thomas Orgis - 2021-06-08

    OK, added one more debugging line. This is weird. Please do a debug build again and compare with my output of

    SNDIO_DEBUG=2 src/mpg123 -o sndio -vv src/tests/sweep.mp3
    
     
  • Roman Bogorodskiy

    It prints the following:

    Module path: /home/novel/code/mpg123/trunk/src/.libs/../libout123/modules/.libs/output_sndio.so
    [src/libout123/module.c:open_module_here():148] debug: Module symbol: mpg123_output_module_info
    Note: sndio is the last output option... showing you any error messages now.
    _aucat_open: host= unit=0 devnum=0 opt=default
    /tmp/sndio-1001/sock0: No such file or directory
    /tmp/sndio/sock0: No such file or directory
    sio_oss_setpar: CHANNELS: Invalid argument
    [src/libout123/modules/sndio.c:open_sndio():128] error: parameter setup  failure
    [src/libout123/libout123.c:check_output_module():978] debug: ao->open() = -1
    [src/libout123/libout123.c:check_output_module():984] error: Module 'sndio' device open failed.
    

    I can see that in your setup it's probing soundcards, and doesn't seem to happen in my case.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    Yes. Where I see sound cards, you see only that line

    sio_oss_setpar: CHANNELS: Invalid argument
    

    At that point, all we do is this:

        struct sio_hdl *hdl;
        struct sio_par par;
    
        hdl = sio_open(ao->device /* NULL is fine */, SIO_PLAY, 0);
        if (hdl == NULL)
        {
            error("Got nothing from sio_open(). ");
            return -1;
        }
    
        sio_initpar(&par);
    
        par.le = SIO_LE_NATIVE;
    
        if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)
            || par.le != SIO_LE_NATIVE )
        {
            if(!AOQUIET)
                error("parameter setup  failure");
            sio_close(hdl);
            return -1;
        }
    

    Could it be that your hardware does not support native endian format?

    We got conversion switches for that. But we'd have to communicate that to the main mpg123 process so that it instructs libmpg123 to swap endianess. Alternatively, we can do the swap also in the module, having it depend on libsyn123 for that or just hacking it.

    Can you confirm your platform being big/little endian, along with the sample format the device expects? You could start with the example above and check the par.le setting.

     
  • Roman Bogorodskiy

    Can you confirm your platform being big/little endian

    I believe it's little endian, as it's amd64 (to be specific, Intel i5-8600).

    ... along with the sample format the device expects?

    I wasn't able to figure out how to check that.

    You could start with the example above and check the par.le setting.

    I've updated the code this way:

    @@ -124,6 +125,7 @@
            if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)
                    || par.le != SIO_LE_NATIVE )
            {
    +               mdebug("par.le = %d (%d)\n", par.le, SIO_LE_NATIVE);
                    if(!AOQUIET)
                            error("parameter setup  failure");
                    sio_close(hdl);
    

    It prints:

    [src/libout123/modules/sndio.c:open_sndio():128] debug: par.le = 1 (1)
    
     
  • Roman Bogorodskiy

    Also I've added one more debug bit:

    @@ -120,10 +121,12 @@
                    sio_close(hdl);
                    return -1;
            }
    +       printf("channels = %d\n", par.pchan);
    

    And it prints:

    channels = -1
    

    Looks like the error message is coming from the following sndio code:

            if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &hdl->chan) == -1) {
                    DPERROR("sio_oss_setpar: CHANNELS");
                    hdl->sio.eof = 1;
                    return 0;
            }
    

    I've updated mpg123's sndio.c to set par.pchan to "2" (instead of -1) and it works.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    I presume the sio_setpar(hdl, &par) is failing right away. Could take that conditonal apart andcheck that first.

    But anyway, SIO_LE_NATIVE is true, so sndio also thinks your platform is little endian. That shouldn't be it … We put nothing into par. The system is free to choose.

    What's with that OSS layer you have? Can you shnow -vv output for -o oss? Do you have native OSS or a mixing/converting layer in between (I remember that from OSS 3 vs 4)?

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    Maybe some FreeBSD people can shed some light on this.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    This doesn't make sense. The call where it is failing is the one to figure out the default format for the device. I'm following the sndio man page here:

    Initialize a sio_par structure using sio_initpar() and fill it with the desired parameters.  Then call sio_setpar() to request the device to use them.  Parameters left unset in
             the sio_par structure will be set to device-specific defaults.
    

    I thought sio_initpar() intiializes the structure for 'unset' values. But maybe it's relying on things being zeroed beforehand. Can you check if it works properly when setting par.pchan=0 ?

    Then … it should also work when you do another svn up, as I am doing explicit zeroing of the structure now (thought sio_initpar() would do that, buggy?).

     

    Last edit: Thomas Orgis 2021-06-10
  • Roman Bogorodskiy

    svn up version doesn't work still. Right after sio_initpar() it prints -1 (actually I noticed that I use "%d" while pchan is unsigned, if I use "%u", it prints 4294967295.
    par.pchan = 0 right after sio_initpar() makes things work again.

    BTW, for sndio-1.7.0 which I'm using implementation looks like this:

    #define SIO_PAR_MAGIC   0x83b905a4
    
    void
    sio_initpar(struct sio_par *par)
    {
            memset(par, 0xff, sizeof(struct sio_par));
            par->__magic = SIO_PAR_MAGIC;
    }
    

    And in sio_oss_setpar() it seems the only thing it does about channels is:

            if (hdl->sio.mode & SIO_PLAY)
                    hdl->chan = par->pchan;
            else if (hdl->sio.mode & SIO_REC)
                    hdl->chan = par->rchan;
    
     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    Oh, OK. So 'unset' doesn't mean zero, it means all bits set. But actually, it does mean zero for you in practice. Let's take the attached example code. It does this on Ubuntu:

    $ !gcc
    gcc -o sndiotest sndiotest.c -lsndio
    $ pasuspender -- ./sndiotest 
    initpar channels: 4294967295
    opened
    setpar successful
    default format: 2 ch, 48000 Hz
    

    For your box, you probably need to change pchan to zero before setting parameters.

    Doesn't that awfully look like a bug in FreeBSD/sndio to you? Can you report that?

    Setting pchan=0 seems to work for both you an me, but is it correct? The documentation suggests that zero means 'unset', while the code does 0xff on the bytes. I dunno what to make of this.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-10

    I updated svn to set pchan to zero for querying mode. I guess we'll have to roll with that. But at least the documentation should be fixed.

     
  • Roman Bogorodskiy

     
  • Roman Bogorodskiy

    This is now fixed in sndio git: https://github.com/ratchov/sndio/commit/aac840d9f91c52a1dc3dcbdbfc3c628a80a717a1.

    Looks like the issue can be closed now. Not sure if the "par.pchan = 0" workaround should be kept or just wait while users eventually move to a newer sndio version that has that issue fixed.

    Thanks

     

    Last edit: Roman Bogorodskiy 2021-06-16
  • Thomas Orgis

    Thomas Orgis - 2021-06-16

    Looks like pchan=0 is still working as before. So I am inclined to keep the workaround for current systems, but will note the time when it was fixed.

    Does upstream have an opinion about this? Are they adding pchan=0 to the docs as equivalent to unset?

     
  • Roman Bogorodskiy

    Are you still talking about upstream as sndio or FreeBSD OSS?

    From what I can see, there's no special treatment of pchan == 0 in sndio, only comparison with the trap value (~0U).

    In OSS it looks like the set channels ioctl just writes back current number of channels if the supplied value is 0: https://cgit.freebsd.org/src/tree/sys/dev/sound/pcm/dsp.c#n1515, which appears to be safe enough.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-16

    Oh, right. This is only an issue in the OSS part of sndio. They did not handle their default unset value.

    Thing is … channel count 0 could trip up other backends of sndio, right? So things work only by accident here, as oss handles 0 channels to mean unset itself.

    Maybe we can try a workaround that does not potentially break other systems. What about this:

    1. Try defaults.
    2. If even defaults fail, try 2 channels as most likely guess.
    3. If even that fails, we got true trouble.
     
  • Roman Bogorodskiy

    That should work, I guess. It looks like we can also use sio_getcap() to make sure 2 channels are supported.

     
  • Thomas Orgis

    Thomas Orgis - 2021-06-16

    Hm. The whole point was ‘give me some default preferred format’. So if that fails … use the getformats stuff. OK, we could call the caps, determine supported channel counts, pick 2 if present, 1 as fallback … or an even higher number if it's a 7 channel interface?

    It would then be up to us to decide on the default count to use. What's reasonable?

    1. 2 channel stereo as the norma
    2. otherwise maximum supported count

    Or always the maximum count? Like a 5.1 system will give you 6 channels as default format?

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.