Sunday, January 8

Playing memory-mapped files with QuickTime

For my current development, I needed the ability to play a memory-mapped media file(mp3,mid,etc..) with the QuickTime API in Mac OS X. I already knew how to play regular files from disk, but had no clue how to do it from memory.

After spending two days diving into tutorials, documentation and technical notes(!) from Apple, I finally came up with some working code. The code looks pretty straight-forward but it took me ages to find any document covering the topic. Here is a code snippet some people might find useful in the future:

Handle MyCreatePointerReferenceHandle(void *data, Size dataSize)
{
PointerDataRefRecord ptrDataRefRec;
Handle dataRef = NULL;
OSErr err = noErr;


ptrDataRefRec.data = data;
ptrDataRefRec.dataLength = dataSize;

// create a data reference handle for our data
err = PtrToHand( &ptrDataRefRec, &dataRef, sizeof(PointerDataRefRecord));

return dataRef;
}

OSErr AddMIMETypeDataRefExtension ( Handle theDataRef, StringPtr theMIMEType )
{
unsigned long myAtomHeader[2];
OSErr myErr = noErr;

if (theMIMEType == NULL)
return(paramErr);

myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader) +
theMIMEType[0] + 1);
myAtomHeader[1] =
EndianU32_NtoB(kDataRefExtensionMIMEType);

myErr = PtrAndHand(myAtomHeader, theDataRef,
sizeof(myAtomHeader));
if (myErr == noErr)
myErr = PtrAndHand(theMIMEType, theDataRef,
theMIMEType[0] + 1);

return(myErr);
}

void CToPascal (StringPtr outString, const char *inString)
{
unsigned char x = 0;
do {
*(((char*)outString) + x + 1) = *(inString + x); x++;
} while ((*(inString + x) != 0));
*((char*)outString) = (char) x;
}

play_mp3()
{

char* data = something(); // pointer to memory-mapped file
int dataSize = whatever(); // size of the file in memory

Handle dataRef;
Movie movie;
Str255 mimeType;

dataRef = MyCreatePointerReferenceHandle((char*)data, dataSize);

// Assuming the memory-mapped file is mp3
CToPascal ( mimeType, "audio/x-mp3" );

AddMIMETypeDataRefExtension( dataRef, mimeType );

NewMovieFromDataRef( &movie, 0, 0, dataRef, 'ptr ');

DisposeHandle( dataRef );

// Now we are ready to play the mp3

GoToBeginningOfMovie( movie );
StartMovie( movie );

}

No comments: