-1

I'm trying to implement a program that reads a stream of MP3 from a Radio server and plays it. I'm doing this because I want to build a radio using a ESP8266, and I want to understand exactly how the flow of retrieving the stream from the web server goes so I can understand why it is currently not working so well..

Anyway, right now I have a small HTTP-Client C program that issues a GET request to a radio station server and outputs the response to a file.

This is the part that reads from the socket:

while((recived_len = recv(sock, BUF, BUFSIZ-1, 0)) > 0)
    {   
        BUF[recived_len] = '\0';
        printf("%s, BUF);
        
    }

This loop goes forever, writing the data to STDOUT, and I then redirect it to a file. The problem is that for some reason the file is defective, the MP3 player doesn't play it.

If I do the same thing with curl:

$ curl http://kanliveicy.media.kan.org.il/icy/kanbet_mp3 > curl_stream.mp3
// wait for a while
^C

It goes great - the MP3 player plays it well.

I did try to inspect the file that is outputted from my program. I used this MP3 parser to parse the file, and it seems that there is a lot of resyncing, i.e. stepping through the calculated frame size doesn't put you in the next MP3 header, and some of the headers show incorrect values, such as layer: 1, etc.

What could be the reason for this malfunctioning? What is the difference between my simple program and curl? Of course there are plenty of differences lol but I mean - what else is there other than just reading from the TCP socket?

Hint: I did notice that the download speed is significantly different: curl downloads the stream much faster than my client application. Could this be related?

Love some help!

YoavKlein
  • 2,005
  • 9
  • 38
  • It's hard to tell without code what the difference is. But I assume this is the same project where you were hinted at the "chunked" transfer encoding. In that case, you can't just write the data to a file. It'll have HTTP encoding info in it. – Emanuel P Apr 20 '21 at 18:27
  • I know [this link uses different language tech](https://stackoverflow.com/questions/1972027/android-playing-mp3-from-byte), but seems to do similar stuff. It may help to take a look. – ryyker Apr 20 '21 at 18:30
  • That's exactly what I do with `curl` - just writing it to a file - and it goes great. The Content-Type is of type `audio/mpeg` and by inspecting it I can see that it is a MP3 file - it contains MP3 headers. – YoavKlein Apr 20 '21 at 18:32
  • @YoavKlein Yes, but `curl` is a program that removes such encoding from the stream (among other things). – Emanuel P Apr 20 '21 at 18:34
  • No it doesn't remove that encoding from the stream. It does remove the `\r\n\r\n` sections from a chunked `Transfer-Encoding`, but when you run it with `--raw` it doesn't do even that - in which case it also plays the MP3 file well, just with some interruptions in the middle.. – YoavKlein Apr 20 '21 at 18:37
  • In the case of chunked transfer encoding, that pretty much is the encoding info. – Emanuel P Apr 20 '21 at 18:44

1 Answers1

1

I believe that your code will truncate every received buffer when it contains a NULL byte.

Just compare curl's raw output with the one you receive, and you should be able to see the difference.

Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
  • It's a bit of a problem to compare those outputs, since the content always changes (it's a stream) - If I had some way to have both curl and my code read at the exact same time I could maybe do it. Anyways I can see that the output of my program is damaged - the frames are not of the same size, the values in the headers are not concise, etc. Why do you think that my code truncates every received buffer when it contains a NULL byte? – YoavKlein Apr 21 '21 at 06:46
  • Ohhh I got it, I print the output with `printf` which only outputs until the NULL byte ! Thanks a lot !! – YoavKlein Apr 21 '21 at 06:52
  • I didn't realize that the MP3 stream may contain a NULL byte as well :), that solved it, thanks !! – YoavKlein Apr 21 '21 at 07:44