Here's another category I found while cleaning out my dev folder. It's another bit of Quicktime code for Cocoa. This is a category on
QTMovie that makes it easier to deal with standard movies (i.e. ones with one video track and any number of audio tracks).
This same category exists in the
MovieStepper project, but that version won't compile for 64-bit Cocoa applications because Apple has removed access to the underlying Quicktime data structures like
Track and
Media. This version uses only QTKit objects to accomplish the same tasks, and thus will compile for both 32-bit and 64-bit applications.
QTMovie-Frame.h
#import <Cocoa/Cocoa.h>
#import <QTKit/QTKit.h>
@interface QTMovie(Frames)
- (long)numberOfFrames;
- (void)gotoFrameNumber:(long)frameNum;
- (long)currentFrameNumber;
- (int)displayFPS;
- (float)desiredFPS;
- (NSImage *)frameImageForFrame:(int)frameNumber;
- (NSSize)size;
@end
QTMovie.m
#import "QTMovie-Frames.h"
@implementation QTMovie(Frames)
- (long)numberOfFrames
{
NSArray *tracks = [self tracksOfMediaType:QTMediaTypeVideo];
for (QTTrack *track in tracks)
{
QTMedia *media = [track media];
NSNumber *frames = [media attributeForKey:QTMediaSampleCountAttribute];
if (frames != nil)
return [frames longValue];
}
return -1L;
}
- (void)gotoFrameNumber:(long)frameNum
{
int frames = [self numberOfFrames];
double percentDone = (double)frameNum / (double) frames;
QTTime duration = [self duration];
QTTime newTime;
newTime.timeScale = duration.timeScale;
newTime.flags = duration.flags;
newTime.timeValue = duration.timeValue * percentDone;
[self setCurrentTime:newTime];
}
- (long)currentFrameNumber
{
QTTime now = [self currentTime];
QTTime duration = [self duration];
if (now.timeValue == 0 || duration.timeValue == 0)
return 0;
double percentDone = (double)now.timeValue / (double)duration.timeValue;
int frames = [self numberOfFrames];
return (int) ((double)frames * percentDone)+1;
}
- (Fixed)rawFPS
{
NSArray *tracks = [self tracksOfMediaType:QTMediaTypeVideo];
for (QTTrack *track in tracks)
{
QTMedia *media = [track media];
QTTime duration = [[media attributeForKey:QTMediaDurationAttribute] QTTimeValue];
long numFrames = [self numberOfFrames];
double frameRate = numFrames*(double)duration.timeScale/(double)duration.timeValue;
return X2Fix(frameRate);
}
return -1;
}
- (int)displayFPS
{
return FixRound([self rawFPS]);
}
- (float)desiredFPS
{
return FixedToFloat([self rawFPS]);
}
- (NSImage *)frameImageForFrame:(int)frameNumber
{
QTTime restoreTime = [self currentTime];
[self gotoFrameNumber:frameNumber];
NSImage *ret = [self currentFrameImage];
[self setCurrentTime:restoreTime];
return ret;
}
- (NSSize)size
{
return [[self attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
}
@end