Q: Our application uses MovieExportFromProceduresToDataRef to export video from a data source other than a QuickTime Movie. How important is it to fill in the dataSize parameter of the MovieExportGetDataParams structure? We've been using 0 hoping QuickTime will "do the right thing."A: The size of the data being returned from this callback is a critical piece of information for QuickTime. So it's very important to correctly fill in the MovieExportGetDataParams dataSize field in your MovieExportGetDataProc . Some decompressors will not work unless they know the size of their sample data. If the data is coming straight from a chunky raster image, GWorld , PixMap , or the image data associated with a CGBitmapContext for example, the dataSize should be (rowBytes * height ). If you use the utility MakeImageDescriptionForPixMap API, it will fill in the correct dataSize value in the returned ImageDescriptionHandle which can then be used to fill in the MovieExportGetDataParams dataSize field. See Listing 1. Failure to follow this guidelines will result in future compatibility issues. Listing 1: A simple MovieExportGetDataProc providing video frames from a PixMap.
#define kMovieLengthInSeconds 10 // the length of our data in seconds
#define kVideoSampleRate 3000 // 30 frames per second
#define kVideoFrameDuration 100
#define kVideoFrameHeight 120L
#define kVideoFrameWidth 160L
// the structure that stores information we want passed to the app-defined
// procedure that generates video data
// a pointer to this struct is pass to MovieExportAddDataSource as the refCon
typedef struct {
GWorldPtr fGWorld;
long fTrackID;
long fDataSize;
ImageDescriptionHandle fImageDescription;
} VideoDataRec, *VideoDataRecPtr;
static pascal OSErr My_VideoDataProc(void *inRefCon, MovieExportGetDataParams *inParams)
{
CGrafPtr myOldPort;
GDHandle myOldDevice;
Rect myRect;
Str255 myString;
static long myFrameNum = 0;
VideoDataRecPtr myVideoDataRecPtr = (VideoDataRecPtr)inRefCon;
if (NULL == myVideoDataRecPtr) return paramErr;
// end the data after desired length of movie
if (inParams->requestedTime >
kVideoSampleRate * kMovieLengthInSeconds) return eofErr;
// set the size of the video frame
MacSetRect(&myRect, 0, 0, kVideoFrameWidth, kVideoFrameHeight);
// if we haven't allocated a GWorld yet do it now
// this is our "source" for the video frame
if (NULL == myVideoDataRecPtr->fGWorld) {
PixMapHandle myPixMap = NULL;
OSErr myErr = noErr;
QTNewGWorld(&(myVideoDataRecPtr->fGWorld), k32ARGBPixelFormat,
&myRect, NULL, NULL, 0);
if (NULL == myVideoDataRecPtr->fGWorld) return memFullErr;
// grab the pixmap and create the ImageDescription
myPixMap = GetGWorldPixMap(myVideoDataRecPtr->fGWorld);
if (NULL == myPixMap) return memFullErr;
LockPixels(myPixMap);
// creates an Image Description for our "source" PixMap
// MakeImageDescriptionForPixMap fills in the dataSize parameter of the
// ImageDescription structure with the correct value
myErr = MakeImageDescriptionForPixMap(myPixMap,
&(myVideoDataRecPtr->fImageDescription));
if (noErr != myErr) return myErr;
myVideoDataRecPtr->fDataSize = (**(myVideoDataRecPtr->fImageDescription)).dataSize;
}
GetGWorld(&myOldPort, &myOldDevice);
SetGWorld(myVideoDataRecPtr->fGWorld, NULL);
// draw a frame:
// white rectangle with black frame number centered horizontally in frame
EraseRect(&myRect);
ForeColor(whiteColor);
PaintRect(&myRect);
ForeColor(blackColor);
NumToString(++myFrameNum, myString);
MoveTo((short)(myRect.right / 2) - (StringWidth(myString) / 2),
(short)(myRect.bottom / 2));
TextSize((short)(myRect.bottom / 4));
DrawString(myString);
// fill in the MovieExportGetDataParams for QuickTime
inParams->actualTime = inParams->requestedTime;
inParams->dataPtr = GetPixBaseAddr(GetGWorldPixMap(myVideoDataRecPtr->fGWorld));
// we know the dataSize is correct as MakeImageDescriptionForPixMap
// supplied this value
inParams->dataSize = myVideoDataRecPtr->fDataSize;
inParams->desc = (SampleDescriptionHandle)(myVideoDataRecPtr->fImageDescription);
inParams->descType = VideoMediaType;
inParams->descSeed = 1;
inParams->actualSampleCount = 1;
inParams->durationPerSample = kVideoFrameDuration;
inParams->sampleFlags = 0L; // sync sample
// restore the original graphics port and device
SetGWorld(myOldPort, myOldDevice);
return noErr;
}
References:Back to Top Document Revision HistoryDate | Notes |
---|
2005-02-25 | Outlines the importance of correctly filling in the MovieExportGetDataParams dataSize field when exporting from procedures. |
Posted: 2005-02-25
|