Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Relevant replacement documents include:
Completed Lab/QTVideo.c
/* |
File: QTVideo.c |
Contains: Code to create video tracks for QuickTime CreateMovie sample |
Written by: Scott Kuechle |
(based heavily on QuickTime sample code in Inside Macintosh: QuickTime) |
Copyright: © 1998 by Apple Computer, Inc. All rights reserved |
Change History (most recent first) |
<1> 6/26/98 srk first file |
*/ |
/************************************************************ |
* * |
* INCLUDE FILES * |
* * |
*************************************************************/ |
#include "ConditionalMacros.h" |
#if TARGET_OS_WIN32 |
#include <QTML.h> |
#endif |
#include <MacTypes.h> |
#include <Errors.h> |
#include <Fonts.h> |
#include <QuickDraw.h> |
#include <FixMath.h> |
#include <Sound.h> |
#include <Movies.h> |
#include <ImageCompression.h> |
#include <NumberFormatting.h> |
#include "CreateMovie.h" |
#include "QTVideo.h" |
/************************************************************ |
* * |
* FUNCTION PROTOTYPES * |
* * |
*************************************************************/ |
static void QTVideo_AddVideoSamplesToMedia (Media theMedia, const Rect *trackFrame); |
static void QTVideo_DrawFrame (const Rect *trackFrame, long curSample); |
/************************************************************ |
* * |
* CONSTANTS * |
* * |
*************************************************************/ |
#define kVideoTimeScale 600 |
#define kNumVideoFrames 70 |
#define kPixelDepth 8 /* use 8-bit depth */ |
#define kNoOffset 0 |
#define kMgrChoose 0 |
#define kSyncSample 0 |
#define kAddOneVideoSample 1 |
#define kSampleDuration 60 /* frame duration = 1/10 sec */ |
#define kTrackStart 0 |
#define kMediaStart 0 |
/************************************************************ |
* * |
* QTVideo_CreateMyVideoTrack() * |
* * |
* Creates a video track for a given QuickTime movie * |
* * |
*************************************************************/ |
void QTVideo_CreateMyVideoTrack(Movie theMovie) |
{ |
Track theTrack; |
Media theMedia; |
OSErr err = noErr; |
Rect trackFrame = {0,0,100,320}; |
// 1. Create the track |
theTrack = NewMovieTrack (theMovie, /* movie specifier */ |
FixRatio(trackFrame.right,1), /* width */ |
FixRatio(trackFrame.bottom,1), /* height */ |
kNoVolume); /* trackVolume */ |
CheckError( GetMoviesError(), "NewMovieTrack error" ); |
// 2. Create the media for the track |
theMedia = NewTrackMedia (theTrack, /* track identifier */ |
VideoMediaType, /* type of media */ |
kVideoTimeScale, /* time coordinate system */ |
nil, /* data reference - use the file that is associated with the movie */ |
0); /* data reference type */ |
CheckError( GetMoviesError(), "NewTrackMedia error" ); |
// 3. Establish a media-editing session |
err = BeginMediaEdits (theMedia); |
CheckError( err, "BeginMediaEdits error" ); |
// 3a. Add Samples to the media |
QTVideo_AddVideoSamplesToMedia (theMedia, &trackFrame); |
// 3b. End media-editing session |
err = EndMediaEdits (theMedia); |
CheckError( err, "EndMediaEdits error" ); |
// 4. Insert a reference to a media segment into the track |
err = InsertMediaIntoTrack (theTrack, /* track specifier */ |
kTrackStart, /* track start time */ |
kMediaStart, /* media start time */ |
GetMediaDuration(theMedia), /* media duration */ |
fixed1); /* media rate ((Fixed) 0x00010000L) */ |
CheckError( err, "InsertMediaIntoTrack error" ); |
} |
/************************************************************ |
* * |
* QTVideo_AddVideoSamplesToMedia() * |
* * |
* Creates video samples for the media in a track * |
* * |
*************************************************************/ |
static void QTVideo_AddVideoSamplesToMedia(Media theMedia, const Rect *trackFrame) |
{ |
GWorldPtr theGWorld = nil; |
long maxCompressedSize; |
long curSample; |
Handle compressedData = nil; |
Ptr compressedDataPtr; |
ImageDescriptionHandle imageDesc = nil; |
CGrafPtr oldPort; |
GDHandle oldGDeviceH; |
OSErr err = noErr; |
// Create a graphics world |
err = NewGWorld (&theGWorld, /* pointer to created gworld */ |
kPixelDepth, /* pixel depth */ |
trackFrame, /* bounds */ |
nil, /* color table */ |
nil, /* handle to GDevice */ |
(GWorldFlags)0); /* flags */ |
CheckError (err, "NewGWorld error"); |
// Lock the pixels |
LockPixels (GetPortPixMap(theGWorld)); |
// Determine the maximum size the image will be after compression. |
// Specify the compression characteristics, along with the image. |
err = GetMaxCompressionSize(GetPortPixMap(theGWorld), /* Handle to the source image */ |
trackFrame, /* bounds */ |
kMgrChoose, /* let ICM choose depth */ |
codecNormalQuality, /* desired image quality */ |
kAnimationCodecType, /* compressor type */ |
(CompressorComponent)anyCodec, /* compressor identifier */ |
&maxCompressedSize); /* returned size */ |
CheckError (err, "GetMaxCompressionSize error" ); |
// Create a new handle of the right size for our compressed image data |
compressedData = NewHandle(maxCompressedSize); |
CheckError( MemError(), "NewHandle error" ); |
MoveHHi( compressedData ); |
HLock( compressedData ); |
compressedDataPtr = *compressedData; |
// Create a handle for the Image Description Structure |
imageDesc = (ImageDescriptionHandle)NewHandle(4); |
CheckError( MemError(), "NewHandle error" ); |
// Change the current graphics port to the GWorld |
GetGWorld(&oldPort, &oldGDeviceH); |
SetGWorld(theGWorld, nil); |
// For each sample... |
for (curSample = 1; curSample <= kNumVideoFrames; curSample++) { |
// Call DrawFrame to actually do the drawing of our image |
QTVideo_DrawFrame(trackFrame, curSample); |
// Use the ICM to compress the image |
err = CompressImage(GetPortPixMap(theGWorld), /* source image to compress */ |
trackFrame, /* bounds */ |
codecNormalQuality, /* desired image quality */ |
kAnimationCodecType, /* compressor identifier */ |
imageDesc, /* handle to Image Description Structure; will be resized by call */ |
compressedDataPtr); /* pointer to a location to recieve the compressed image data */ |
CheckError( err, "CompressImage error" ); |
// Add sample data and a description to a media |
err = AddMediaSample(theMedia, /* media specifier */ |
compressedData, /* handle to sample data - dataIn */ |
kNoOffset, /* specifies offset into data reffered to by dataIn handle */ |
(**imageDesc).dataSize, /* number of bytes of sample data to be added */ |
kSampleDuration, /* frame duration = 1/10 sec */ |
(SampleDescriptionHandle)imageDesc, /* sample description handle */ |
kAddOneVideoSample, /* number of samples */ |
kSyncSample, /* control flag indicating self-contained samples */ |
nil); /* returns a time value where sample was insterted */ |
CheckError( err, "AddMediaSample error" ); |
} // for loop |
SetGWorld (oldPort, oldGDeviceH); |
// Dealocate our previously alocated handles and GWorld |
if (imageDesc) |
{ |
DisposeHandle ((Handle)imageDesc); |
} |
if (compressedData) |
{ |
DisposeHandle (compressedData); |
} |
if (theGWorld) |
{ |
DisposeGWorld (theGWorld); |
} |
} |
/************************************************************ |
* * |
* QTVideo_DrawFrame() * |
* * |
* contains code to "draw" a video frame * |
* * |
*************************************************************/ |
static void QTVideo_DrawFrame(const Rect *trackFrame, long curSample) |
{ |
Str255 numStr; |
EraseRect (trackFrame); |
ForeColor( redColor ); |
PaintRect( trackFrame ); |
ForeColor( blueColor ); |
NumToString (curSample, numStr); |
MoveTo ( (short)(trackFrame->right / 2), (short)(trackFrame->bottom / 2)); |
TextSize ( (short)(trackFrame->bottom / 3)); |
DrawString (numStr); |
if ( curSample == 70 ) { |
ForeColor( greenColor ); |
MoveTo((short)(trackFrame->left + 12), (short)(trackFrame->bottom / 2 )); |
TextSize( (short)(trackFrame->bottom / 4) ); |
DrawString("\pWhoa cool!"); |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14