Reputation: 977
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.
Upvotes: 1
Views: 1763
Reputation: 11562
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.
Upvotes: 1