1

I would like to use an iPhone as the audio source for an ICEcast stream.

1) is the AudioQueueInputCallback where I should be sending this stream?

2) I have been able to identify the protocol for ICEcast Icecast 2: protocol description, streaming to it using C# However, I am not certain how to do this in the callback code (i.e. how to send the binary audio)

UPDATE

static void MyAQInputCallback( void *inUserData, 
  AudioQueueRef inQueue,
  AudioQueueBufferRef inBuffer,
  const AudioTimeStamp *inStartTime,
  UInt32 inNumPackets,
  cont AudioStreamPacketDescription *inPacketDesc)
{

    if (inNumPackets > 0)
    {
       // instead of
       //     AudioFileWritePackets(someFile, FALSE, 
       //           inBuffer->mAudioDataByteSize,
       //           inPacketDesc, recordPacketNumber, 
       //           &inNumPackets, inBuffer->mAudioData);

       // I want to send to http://myicecastserver
       // instead
    }

}

UPDATE

I will open a socket connection to my icecast server to send the data.

Community
  • 1
  • 1
JonathanC
  • 967
  • 11
  • 30
  • Can you post the code you have so far? – Brad Oct 16 '12 at 14:44
  • @JonathanC Hi, Have you achieved this? Could you please share the code how are you sending the data to icecast server? And which socket library you are using? – TheTiger Dec 06 '17 at 13:47

1 Answers1

1

This is a non-trivial problem. The "protocol" you mention is just some guy sniffing a few packets and making a few guesses. If you examine the ICES source code you can see the actual methodology for sending to a Icecast server and it is a highly complex, custom streaming protocol. The relevant code is in two files: stream.c and stream_shared.c assuming you have your stream already encoded to PCM. To give a sense for the complexity of this streaming algorithm, here is a small extract from the sender:

   else if (sdsc->enc)
    {
        ogg_page og;
        int be = (sdsc->input->subtype == INPUT_PCM_BE_16)?1:0;
        int ret=1;

        /* We use critical as a flag to say 'start a new stream' */
        if(buffer->critical)
        {
            if(sdsc->resamp) {
                resample_finish(sdsc->resamp);
                encode_data_float(sdsc->enc, sdsc->resamp->buffers,
                        sdsc->resamp->buffill);
                resample_clear(sdsc->resamp);
                sdsc->resamp = resample_initialise (sdsc->stream->channels,
                        sdsc->stream->resampleinrate, sdsc->stream->resampleoutrate);
            }
            encode_finish(sdsc->enc);
            while(encode_flush(sdsc->enc, &og) != 0)
            {
                if ((ret = stream_send_data(sdsc, og.header, og.header_len)) == 0)
                    return 0;
                if ((ret = stream_send_data(sdsc, og.body, og.body_len)) == 0)
                    return 0;
            }
            encode_clear(sdsc->enc);

            if(sdsc->input->metadata_update)
            {
                vorbis_comment_clear(&sdsc->vc);
                vorbis_comment_init(&sdsc->vc);

                sdsc->input->metadata_update(sdsc->input->internal, &sdsc->vc);
            }

As I said, this is only about 10% of the code. There are literally pages and pages of error checking, metadata transmissions, etc etc. If you wanted to create a custom Icecast source client you would have to copy all this code, port it to your program, then encode your input as PCM and then packetize it for delivery to the routines in stream.c and stream_shared.c.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • I suppose this is the correct way to do it. I am working on a proof of concept so I think for my first step I will simply try to create a rudimentary source client using the information other people have gathered by sniffing packets. Then I might try to do a proper port. – JonathanC Nov 01 '12 at 18:40
  • 1
    @Tyler, If you have corrections to make to my answer, please do. Sure, if you want to include GPL code in your project, you can use code from the Icecast source client. If you have time on your hands, you could take it apart and work through it. Or, you could look at the raw data being sent, which is very simple. I don't disagree that using what is already built is the way to go when possible, but you imply that what I have posted is incorrect because it was written based on observation. I don't agree. Again, if you see something wrong, feel free to edit, or comment and I will edit. – Brad Nov 02 '12 at 05:35