I want to open an existing Movie-File and export every frame of this file to an image like JPEG or TIFF. I got so far until now:
int main(int argc, char* a
If you are working on OS X only I would stick with the QTKit APIs because they are much higher level and generally easier to work with.
The general gist of what you want to do is:
To step through the frames in a QuickTime movie, you can use the QTMovie class in QTKit to do this as follows:
- (void)dumpFramesWithMovie:(QTMovie*)movie toFolder:(NSString*)folderPath
{
[movie setIdling:NO]; // Don't idle the movie
[movie gotoEnd];
QTTime endTime = [movie currentTime];
[movie gotoBeginning];
// Number of frames counted so far
unsigned long numFrames = 0;
// Turn off the Movie's looping so we are quaranteed to stop
[movie setAttribute:[NSNumber numberWithBool:NO] forKey:QTMovieLoopsAttribute];
// Construct a Dictionary of to use when reading frames from a movie
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:QTMovieFrameImageTypeNSImage forKey:QTMovieFrameImageType];
while (true)
{
QTTime curTime = [movie currentTime];
if (QTTimeCompare(curTime, endTime) == NSOrderedSame)
{
// Reached end of file
break;
}
// Get the Current Frame as an NSImage
NSImage* image = [movie frameImageAtTime:curTime
withAttributes:attributes error:nil];
// Get the bitmap representation of this image
// NOTE: This code assumes the first image representation is a NSBitmapImageRep, which is true
// by default in OS X 10.5 and later.
// Production code should do error checking here.
NSBitmapImageRep *bitmap = [[image representations] objectAtIndex: 0];
// Construct a filename based upon the folder path and number of frames read so far
NSString* fileName = [NSString stringWithFormat:@"%@/frame%d.png", folderPath, numFrames];
// Get an PNG representation of this file
NSData *data = [bitmap representationUsingType: NSPNGFileType
properties: nil];
// Write to disk
[data writeToFile: fileName
atomically: NO];
// Step to the next Frame
[movie stepForward];
numFrames++;
}
[movie gotoBeginning];
}
@end
This code compiles but has not been fully tested.
One caveat with this approach is that MPEG-1 files will not decode properly on OS X 10.5 and earlier. This has been fixed as of 10.6 as far as I know. Also, if are writing a Windows application, you'll need to use the lower lever Quicktime-C APIs.
Be sure to check the following reference pages while working on this:
These command line OSX utilities are really good at extracting the contents of a Quicktime movie without having to buy QTPro:
qt_tools
I usually just dump the decoded frames into a binary one after another and then use some YUV-Viewer to see if they look Ok. For that you have to know the exact color format and resolution of the decoded frames. If you have RGB, there are certainly also viewers for that.
UPDATE:
Link doesn't seem to work. You will have to google for a YUV-Viewer. Alternatively, you can buy one from Elecard.
As a beginning, this article on Movie exporters should pretty much get you started:
http://www.mactech.com/articles/mactech/Vol.16/16.05/May00QTToolkit/index.html
Even though MacTech is a Mac resource, all described API functions should be available in the QuickTime for Windows SDK as well.
I will slap some sample code together myself as a reference here as soon as I find the time.
Edit
See this book excerpt for additional info:
QuickTime Toolkit - Basic Movie Playback and Media Types @ Google Books
Edit 2 - The High-Level Approach: Movie Exporters
If all you need to accomplish is to extract all video frames from a QuickTime Movie and convert them to another format supported by the QuickTime API you won't have to take any low-level actions whatsoever if using a Movie Exporter.
The below sample code allows to extract and convert all video frames from a QuickTime Movie to, f.e., a bunch of JPEG files using a programmatically invoked Movie Export Dialog.
Just select Movie to Image Sequence in the Export combo box of the dialog and select your desired image format by hitting Options.
Note 1: If you need to do this non-interactively, just let me know.
Note 2: error handling has been omitted for clarity
#include "Movies.h"
#include "QTML.h"
#pragma comment (lib, "QTMLClient.lib")
...
int flags = createMovieFileDeleteCurFile
| showUserSettingsDialog
| movieToFileOnlyExport;
ItemCount movie_prop_count = 0;
CFStringRef cfpath = 0;
Boolean bool_true = true;
QTNewMoviePropertyElement movie_props[ 2 ];
Movie movie;
// initialize QuickTime API
InitializeQTML( 0 );
EnterMovies();
// set up Core Foundation string for source path (argv[ 1 ]) contains the full path to the MOV file to convert
cfpath = CFStringCreateWithCString( 0, argv[ 1 ], kCFStringEncodingASCII );
movie_props[movie_prop_count].propClass = kQTPropertyClass_DataLocation;
movie_props[movie_prop_count].propID = kQTDataLocationPropertyID_CFStringNativePath;
movie_props[movie_prop_count].propValueSize = sizeof(cfpath);
movie_props[movie_prop_count].propValueAddress = (void*)&cfpath;
movie_props[movie_prop_count].propStatus = 0;
++movie_prop_count;
// make Movie active
movie_props[movie_prop_count].propClass = kQTPropertyClass_NewMovieProperty;
movie_props[movie_prop_count].propID = kQTNewMoviePropertyID_Active;
movie_props[movie_prop_count].propValueSize = sizeof(bool_true);
movie_props[movie_prop_count].propValueAddress = &bool_true;
movie_props[movie_prop_count].propStatus = 0;
++movie_prop_count;
// aquire Movie for our Movie file
NewMovieFromProperties( movie_prop_count, movie_props, 0, 0, &movie );
// invoke conversion dialog
ConvertMovieToFile( movie, 0, 0, 0, 'TVOD', 0, 0, flags, 0 );
// clean up
DisposeMovie( movie );
CFRelease( cfpath );
ExitMovies();
TerminateQTML();
...