AudioFileStream, CFReadStream and AudioQueueEnqueueBuffer
Here is what I have got so far with regards to streaming and playing an MP3 using AudioFileStream, CFReadStream and AudioQueue..
I hope it helps some people start, and I hope some people can help me finish!
First, I define a custom data structure to hold stuff throughout..
typedef struct {
AudioFileStreamID audioFileStream;
AudioStreamBasicDescription mDataFormat;
AudioQueueRef mQueue;
CFReadStream readStream;
UInt32 mNumPackets;
AudioStreamPacketDescription *mPacketDescs;
} CustomData;
CustomData customData;
I also set up an AudioQueue with a callback..
AudioQueueNewOutput(&customData.mDataFormat,
AudioOutputCallBack,
&customData,
NULL,
kCFRunLoopCommonModes,
0,
&customData.mQueue);
I set up an AudioFileStream..
AudioFileStreamOpen(0,
audioFileStream_Properties,
audioFileStream_Packets,
kAudioFileMP3Type,
&customData.audioFileStream);
..this has call back functions attached when the AudioFileStream receives either stream properties or stream packets..
I then open a data stream to a URL of an MP3 stream..
NSURL *url = [NSURL URLWithString:@"http://mp3stream.com"];
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(kCFAllocatorDefault,
CFSTR("GET"),
(CFURLRef)url,
kCFHTTPVersion1_1);
customData.readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, message);
CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccured | kCFStreamEventEndEncountered;
CFStreamClientContext dataStreamContext = {0, self, NULL, NULL, NULL};
if (CFReadStreamSetClient(customData.readStream, events, readStreamEventCallBack, &dataStreamContext)) {
CFReadStreamScheduleWithRunLoop(customData.readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}
CFReadStreamOpen(customData.readStream);
..this opens a CFReadStream with a call back function that is called on bytes available events, error events and end events..
void readStreamEventCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientcallBackInfo) {
switch(eventType) {
case kCFStreamEventHasBytesAvailable:
UInt8 buf[4096];
CFIndex bytesRead = CFReadStreamRead(stream, buf, 4096);
if (bytesRead > 0) {
AudioFileStreamParseBytes(customData.audioFileStream, bytesRead, buf, 0);
}
case kCFStreamEventErrorOccurred:
//do stuff
break;
case kCFStreamEventEndOccurred:
//do stuff
break;
}
}
So when the CFReadStream reads some bytes it passes them to the AudioFileStream which will in turn call its callback functions when it receives stream properties or stream packets..
In audioFileStream_Properties I attempt to get the dataFormat of the stream..
void audioFileStream_Properties (void *inClientData,
AudioFileStreamID inAudioFileStream,
AudioFileStreamPropertyID inPropertyID,
UInt32 *ioFlags) {
if (inPropertyID == kAudioFileStreamProperty_DataFormat) {
UInt32 size;
AudioFileStreamGetPropertyInfo(inAudioFileStream, inPropertyID, &size, nil)
AudioFileStreamGetProperty(inAudioFileStream, inPropertyID, &size, &customData.mDataFormat);
}
}
Most of these function calls return an OSStatus which should be checked for error (!= 0) but I have left them out for now..
Then the AudioFileStream packets..
void audioFileStream_Packets (void *inClientData,
UInt32 inNumberBytes,
UInt32 inNumberPackets,
const void *inInputData,
AudioStreamPacketDescription *inPacketDescs) {
customData.mNumPackets = inNumberPackets;
customData.mPacketDescs = inPacketDescs;
AudioQueueBufferRef outBuffer;
AudioQueueAllocateBuffer(customData.mQueue, inNumberBytes, &outBuffer);
AudioOutputCallBack(&customData, customData.mQueue, outBuffer);
}
..here I try and allocate the stream packets into the an AudioQueueBuffer and force that buffer into the AudioQueue callback..
static void AudioOutputCallBack(void *inCustomData,
AudioQueueRef outAQ,
AudioQueueBufferRef) {
CustomData *customData = (CustomData*)inCustomData;
AudioQueueEnqueueBuffer(customData->mQueue, outBuffer, (customData->mPacketDescs ? customData->mNumPackets : 0), playState->mPacketDescs);
}
..Now, I would hope this would be queuing buffers up ready to play! However,
AudioQueueEnqueueBuffer returns error 1718449215 - I am not sure what this means, I am led to believe it might be a dataFormat error 😟
Hope everyone call follow!
Adam
null
Message was edited by: adamlah
macbook, Mac OS X (10.5.4), its good