Retired Document
Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid.
Movie Export - Always fill in the MovieExportGetDataParams dataSize field
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:
Document Revision History
Date | Notes |
---|---|
2005-02-25 | New document that outlines the importance of correctly filling in the MovieExportGetDataParams dataSize field when exporting from procedures. |
Copyright © 2005 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2005-02-25