Далее следует метод инициализатора. Он создает структуру фильма из файла с целью извлечения необработанных пикселей для обработки в соответствии с Apple QA1443 . Затем для удобства он оборачивается в QTMovie - sourceMovie = [QTMovie movieWithQuickTimeMovie: ...]
.
После инициализации такого объекта вызывается второй метод, и мы пытаемся использовать sourceMovie
. Однако оказывается, что любая попытка доступа к sourceMovie здесь приводит к EXC_BAD_ACCESS. Например, NSLog(@"%@", sourceMovie)
невозможна. Похоже, фильм был освобожден, хотя неясно, почему.
Кроме того, в этом втором методе обычные методы для получения CVPixelBufferRef не работают должным образом: QTVisualContextIsNewImageAvailable, кажется, всегда возвращает NO, а QTVisualContextCopyImageForTime всегда дает вам imageBuffer, указывающий на 0x00. (Я думаю, это не удивительно, если QTMovie, Movie или visualContext каким-то образом освобождаются.)
Тогда возникает вопрос: почему sourceMovie
недоступен из второго метода? Это освобождается, как кажется? Если так, то почему?
А теперь код, и заранее извините за длину.
// From the .h, we have the following inst var declarations:
Movie myMovie;
QTMovie *sourceMovie;
QTVisualContextRef visualContext;
CVPixelBufferRef imageBuffer;
pixels_xy sourceSize;
MovieAnalyzer *analyzer;
// And now to the @implementation...
-(id)initWithFileString:(NSString *)file {
if (self = [super init]) {
NSError *e;
// Bit of a hack - get the movie size using temporary QTMovie.
sourceMovie = [QTMovie movieWithFile:file error:&e];
if (e) {
[self release];
NSLog(@"Could not open movie.");
return nil;
}
NSSize movieSize = [[sourceMovie posterImage] size];
CGRect bounds = CGRectMake(0, 0, movieSize.width, movieSize.height);
// Save the size in pixels.
sourceSize.x = (int)movieSize.width, sourceSize.y = (int)movieSize.height;
CFStringRef movieLocation = (CFStringRef) file;
// Get a QT Visual Context, and create a movie inialized to use it for output.
visualContext = NULL;
OSStatus status = CreatePixelBufferContext(k32ARGBPixelFormat, &bounds, &visualContext);
if (noErr != status && NULL == visualContext) {
[self release];
NSLog(@"Problem initializing QT Visual Context.");
return nil;
}
/*** Instantiate the Movie ***/
myMovie = NULL;
Boolean trueValue = true;
QTNewMoviePropertyElement newMovieProperties[3] = {0};
// Setup movie location
newMovieProperties[0].propClass = kQTPropertyClass_DataLocation;
newMovieProperties[0].propID = kQTDataLocationPropertyID_CFStringPosixPath;
newMovieProperties[0].propValueSize = sizeof(CFStringRef);
newMovieProperties[0].propValueAddress = &movieLocation;
// Assign the visual context - could also be NULL
newMovieProperties[1].propClass = kQTPropertyClass_Context;
newMovieProperties[1].propID = kQTContextPropertyID_VisualContext;
newMovieProperties[1].propValueSize = sizeof(visualContext);
newMovieProperties[1].propValueAddress = &visualContext;
// Make the movie active
newMovieProperties[2].propClass = kQTPropertyClass_NewMovieProperty;
newMovieProperties[2].propID = kQTNewMoviePropertyID_Active;
newMovieProperties[2].propValueSize = sizeof(trueValue);
newMovieProperties[2].propValueAddress = &trueValue;
status = NewMovieFromProperties(3, newMovieProperties, 0, NULL, &myMovie);
if (status != noErr || myMovie == NULL) {
NSLog(@"Problem initializing theMovie"); // problem
[self release];
return nil;
}
// Create a new QTMovie with the Movie as its backing object
sourceMovie = [QTMovie movieWithQuickTimeMovie:myMovie disposeWhenDone:NO error:&e];
if (e) {
NSLog(@"Could not initialize QTMovie from Movie.");
[self release];
return nil;
}
[sourceMovie stepForward];
analyzer = [[MovieAnalyzer alloc] initWithColorString:"BGRA" andSourceSize:sourceSize];
}
return self;
}
-(NSImage*) supplyCalibrationImage {
NSLog(@"%x", &sourceMovie);
[sourceMovie stepForward]; // This fails!
....
}