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.
VideoFrameToGWorld.c
/* |
File: VideoFrameToGWorld.c |
Description: VideoFrameToGWorld is an example of decompressing frames from a video track |
into an offscreen buffer so the pixels can be manipulated at a later time. |
Author: era based on code provided by Kevin Marks |
Copyright: © Copyright 2000 Apple Computer, Inc. All rights reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Change History (most recent first): <1> 4/1/00 initial release |
*/ |
#include "VideoFrameToGWorld.h" |
// Globals |
//------------------------------------------------------------------------------ |
WindowRef gWindow = NULL; |
GWorldPtr gSrcGWorld = NULL; |
Movie gMovie = NULL; |
TimeValue gMovieTime = 0; // set current time value to begining of the Movie |
UInt32 gFrameCount = -1; |
UInt32 gFrameNumber = 0; |
Rect gMovieBox; |
//------------------------------------------------------------------------------ |
// Open up the Movie file and get a Movie from it. |
//------------------------------------------------------------------------------ |
void OpenMovie( void ) |
{ |
FSSpec theFSSpec; |
short refnum = 0; |
OSType openTypeList[] = {kQTFileTypeMovie}; |
short numTypes = 1; |
OSErr err = noErr; |
err = GetOneFileWithPreview(numTypes, openTypeList, &theFSSpec, NULL); |
BailError(err); |
// open a Movie file using the FSSpec and create a Movie from that file. |
err = OpenMovieFile(&theFSSpec, &refnum, fsRdPerm); |
BailError(err); |
NewMovieFromFile(&gMovie, refnum, NULL, NULL, newMovieActive, NULL); |
bail: |
// we're done with the file. |
if (refnum) |
CloseMovieFile(refnum); |
} |
//------------------------------------------------------------------------------ |
// Count the number of video "frames" in the Movie by stepping through |
// all of the video "interesting times", or in other words, the places where the |
// movie displays a new video sample. The time between these interesting times |
// is not necessarily constant. |
//------------------------------------------------------------------------------ |
void CountThemFrames( void ) |
{ |
OSType whichMediaType = VIDEO_TYPE; |
short flags = nextTimeMediaSample + nextTimeEdgeOK; |
TimeValue duration; |
TimeValue theTime = 0; |
while (theTime >= 0) { |
gFrameCount++; |
GetMovieNextInterestingTime(gMovie, |
flags, |
1, |
&whichMediaType, |
theTime, |
0, |
&theTime, |
&duration); |
// after the first interesting time, don't include the time we |
// are currently at. |
flags = nextTimeMediaSample; |
} // while |
} |
//------------------------------------------------------------------------------ |
// Get the bounding rectangle of the Movie the create a 32-bit GWorld |
// with those dimensions. |
// This GWorld will be used for rendering Movie frames into. |
//------------------------------------------------------------------------------ |
void MakeGWorld( void ) |
{ |
Rect srcRect; |
Rect portRect; |
RGBColor theBlackColor = { 0, 0, 0 }; |
RGBColor theWhiteColor = { 65535, 65535, 65535 }; |
OSErr err = noErr; |
GetMovieBox(gMovie,&srcRect); |
err = NewGWorld(&gSrcGWorld, |
k32ARGBPixelFormat, |
&srcRect, |
NULL, |
NULL, |
0); |
BailError(err); |
LockPixels(GetGWorldPixMap(gSrcGWorld)); |
SetGWorld(gSrcGWorld,NULL); |
GetPortBounds(gSrcGWorld, &portRect); |
RGBBackColor(&theBlackColor); |
RGBForeColor(&theWhiteColor); |
EraseRect(&portRect); |
bail: |
return; |
} |
//------------------------------------------------------------------------------ |
// Blit the contents of the GWorld to the window |
//------------------------------------------------------------------------------ |
void BlitToScreen( void ) |
{ |
Rect srcRect; |
Rect destRect; |
GetPortBounds(gSrcGWorld, &srcRect); |
GetPortBounds(GetWindowPort(gWindow), &destRect); |
CopyBits(GetPortBitMapForCopyBits(gSrcGWorld), |
GetPortBitMapForCopyBits(GetWindowPort(gWindow)), |
&srcRect, |
&destRect, |
srcCopy, |
NULL); |
} |
//------------------------------------------------------------------------------ |
// First get the next frame of the movie, set the movie time for that frame, |
// then task the movie which will draw the frame to the GWorld |
// Modify the movie matrix so the next frame will be rotated just for fun and |
// finally draw the frame number on top of the image and inval the window rect |
//------------------------------------------------------------------------------ |
void NextFrame( void ) |
{ |
CGrafPtr savedPort; |
GDHandle savedDevice; |
Rect theRect; |
char frame[32]; |
Str255 theString; |
Rect invalRect; |
MatrixRecord theMovieMatrix; |
// these don't change, always rotate 30 degrees anchored in |
// the center of the frame |
static Fixed degrees = Long2Fix(30); |
static Fixed x = Long2Fix((gMovieBox.right - gMovieBox.left) / 2); |
static Fixed y = Long2Fix((gMovieBox.bottom - gMovieBox.top) / 2); |
if ( gFrameNumber < gFrameCount ) { |
TimeValue duration; |
GetGWorld(&savedPort, &savedDevice); |
SetGWorld(gSrcGWorld, NULL); |
// get the next frame of the source movie |
short flags = nextTimeMediaSample; |
OSType whichMediaType = VIDEO_TYPE; |
// if this is the first frame, include the frame we are currently on |
if (gFrameNumber == 0) |
flags |= nextTimeEdgeOK; |
// skip to the next interesting time and get the duration for that frame |
GetMovieNextInterestingTime(gMovie, |
flags, |
1, |
&whichMediaType, |
gMovieTime, |
0, |
&gMovieTime, |
&duration); |
// set the time for the frame and give time to the movie toolbox |
SetMovieTimeValue(gMovie,gMovieTime); |
GetPortBounds(gSrcGWorld, &theRect); |
EraseRect(&theRect); // paint the background black |
// *** this does the actual drawing into the GWorld *** |
MoviesTask(gMovie,0); |
//------------------------------------------------------------------------------ |
// You now have pixels you can play with in the GWorld! |
// This sample simply blits the contents of the GWorld back to |
// a window with the frame number drawn on top of the image |
//------------------------------------------------------------------------------ |
// have some fun and rotate the movie frame |
GetMovieMatrix(gMovie, &theMovieMatrix); |
RotateMatrix(&theMovieMatrix, degrees, x, y); |
SetMovieMatrix(gMovie, &theMovieMatrix); |
gFrameNumber++; |
// draw the frame number on top of the image |
TextSize(12); |
TextMode(srcCopy); |
MoveTo( theRect.left + 5, theRect.bottom - 15 ); |
sprintf(frame,"Frame #%ld",gFrameNumber); |
CopyCStringToPascal(frame, theString); |
DrawString(theString); |
SetGWorld(savedPort, savedDevice); |
// inval the window to generate an update event |
GetPort(&savedPort); |
SetPortWindowPort(gWindow); |
GetWindowBounds(gWindow, kWindowContentRgn, &invalRect); |
GlobalToLocal( (Point *)&invalRect.top); |
InvalWindowRect(gWindow, &invalRect); |
SetPort(savedPort); |
} else { |
// reset the movie time back to the beginning |
// then do it all over again |
gMovieTime = 0; |
gFrameNumber = 0; |
NextFrame(); |
} |
} |
int main() |
{ |
Rect rectWnd; |
Rect rectMovie; |
WindowRef pWhichWindow; |
short nPart; |
EventRecord theEvent; |
Boolean bDone = false; |
OSErr result = noErr; |
// initialize for Carbon and QuickTime |
InitCursor(); |
result = EnterMovies(); |
BailError(result); |
// create the window |
SetRect(&rectWnd, 100, 100, 200, 200); |
gWindow = NewCWindow(NULL, &rectWnd, "\pVideoFrameToGworld", false, kWindowDocumentProc, (WindowPtr)-1, true, NULL); |
BailNULL(gWindow); |
SetPortWindowPort(gWindow); |
// get the movie |
OpenMovie(); |
BailNULL(gMovie); |
// normalize the movie rect |
GetMovieBox(gMovie, &rectMovie); |
OffsetRect(&rectMovie, -rectMovie.left, -rectMovie.top); |
SetMovieBox(gMovie, &rectMovie); |
gMovieBox = rectMovie; |
SizeWindow(gWindow, rectMovie.right, rectMovie.bottom, true); |
ShowWindow(gWindow); |
CountThemFrames(); |
// create the offscreen to draw into |
MakeGWorld(); |
BailNULL(gSrcGWorld); |
// *** set the graphics world for displaying the movie *** |
SetMovieGWorld(gMovie, gSrcGWorld, GetGWorldDevice(gSrcGWorld)); |
// get the first frame |
NextFrame(); |
while (!bDone) { |
if (WaitNextEvent(everyEvent, &theEvent, 0, NULL)) { |
switch (theEvent.what) { |
case updateEvt: |
pWhichWindow = (WindowPtr)theEvent.message; |
if (pWhichWindow == gWindow) { |
// draw the frame |
GrafPtr savedPort; |
CGrafPtr windowPort = GetWindowPort(pWhichWindow); |
RgnHandle vizRgn = NewRgn(); |
RgnHandle savedClip = NewRgn(); |
GetPort(&savedPort); |
SetPort(windowPort); |
GetClip(savedClip); |
BeginUpdate(pWhichWindow); |
GetPortVisibleRegion(windowPort, vizRgn); |
SetClip(vizRgn); |
BlitToScreen(); |
EndUpdate(pWhichWindow); |
SetClip(savedClip); |
SetPort(savedPort); |
DisposeRgn(savedClip); |
DisposeRgn(vizRgn); |
} |
break; |
case mouseDown: |
nPart = FindWindow(theEvent.where, &pWhichWindow); |
if (pWhichWindow == gWindow) { |
switch (nPart) { |
case inGoAway: |
// we're done |
bDone = TrackGoAway(pWhichWindow, theEvent.where); |
break; |
case inContent: |
// get the next frame |
NextFrame(); |
break; |
case inDrag: |
BitMap screenBits; |
GetQDGlobalsScreenBits(&screenBits); |
DragWindow(pWhichWindow, theEvent.where, &screenBits.bounds); |
break; |
} // switch |
} |
break; |
} // switch |
} |
} // while |
bail: |
if ( gMovie ) |
DisposeMovie(gMovie); |
if ( gWindow ) |
DisposeWindow(gWindow); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14