Menu

#285 Input from STDIN pipe on Windows

1.25.x
closed-fixed
nobody
5
2021-10-18
2019-12-13
Ivo Andonov
No

Hello,

Windows build x86. Tested on x86 (Windows XP) and x64 (Windows 7) with 1.8, 1.21, 1.24, 1.25.13.

I have been trying to pipe the output of my program to feed as input to mpg123 and subsequently to libmpg123. If the output (WriteFile on the pipe) is started before mpg123 starts reading, then the latter fails and exits with

[src/libmpg123/parse.c:549] debug: read error

If I leave a random delay in my program before starting WriteFile on the pipe then there is no problem.

In this case libmpg123 uses the stream reader. If I use the option "--streamdump nul" then a bufferred reader is used and the problem does not appear

Further tested with a standard (not my program) feeder using the command line to reproduce the problem:

type some.mp3 | mpg123 -

  • result is the same problem. Sometimes multiple -v might be needed to reproduce.

then with

type some.mp3 | mpg123 --streamdump nul -

  • result is no problem and the stream plays fine

I traced the problem and did a workaround for my case by changing line 1052 in readers.c (1.25.13)
fr->rdat.filelen = fr->p.flags & MPG123_NO_PEEK_END ? -1 : get_fileinfo(fr);
to
fr->rdat.filelen = -1;

It seems that get_fileinfo has unexpected behavior on Windows when working on pipes. As stated here https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointer

Calling the SetFilePointer function with a handle to a non-seeking device such as a pipe or a communications device is not supported, even though the SetFilePointer function may not return an error. The behavior of the SetFilePointer function in this case is undefined.

I assume the latter causes libmpg123 to read 128 bytes for ID3. Here's the debug log:

[src/libmpg123/readers.c:1159] debug: stream reader
[src/libmpg123/readers.c:60] debug: read 128 bytes of 128
main: [src/mpg123.c:643] debug: Track successfully opened.

Playing MPEG stream 1 of 1: - ...
main: [src/mpg123.c:743] debug: play_frame
[src/libmpg123/libmpg123.c:623] debug: read frame
[src/libmpg123/parse.c:519] debug: trying to get frame 0 at 0
[src/libmpg123/readers.c:60] debug: read 4 bytes of 4
Note: Junk at the beginning (0x69730f70) - this junk is at position 128 of the stream being fed.
[src/libmpg123/parse.c:1183] debug: searching for header...

My suggestion would be to modify the mpg123 app so that if playing from standard input set the MPG123_NO_PEEK_END flag. However I did not have the chance to further look into the code and I leave for the more experienced developers to decide on how to resolve the problem.

Discussion

  • Thomas Orgis

    Thomas Orgis - 2019-12-13

    The use of --streamdump triggers the replacement of reader functions by read/lseek wrappers that also write to the dump file. No buffering. I'm a bit puzzled why that fixes your issue.

    Maybe it works by introducing delays.

    An I/O function with undefined behaviour, possibly not returning an error (possibly!) is comedy gold. How am I supposed to notice that the stream is not seekable?

    Adding the MPG123_NO_PEEK_END flag of course can be done for '-' as file. No harm caused by that, I suppose. That does not really rule out intentional seeks triggered by mpg123, though that is less of an issue on Windows.

     
  • Thomas Orgis

    Thomas Orgis - 2020-01-22

    OK, I did that now in trunk and made a new snapshot (MPG123_NO_PEEK_END on file "-"). Does that work for you?

    Bonus: This even helped me spot a missing check for empty ID3 data before printout …

     
  • Thomas Orgis

    Thomas Orgis - 2020-05-16
    • status: open --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB