Создавание приложения движения остановки QTKit
Выполнение шагов обрисовало в общих чертах в этой главе, Вы создаете простое приложение устройства записи движения остановки, позволяющее Вам получить живой видео канал, захватить кадры по одному с большой точностью, и затем записать вывод тех кадров к фильму в формате QuickTime. Вы выполняете это меньше чем с 100 строками кода Objective C, создавая выборку, поскольку Вы сделали в предыдущих главах в Xcode 3.2 и Интерфейсном Разработчике 3.2.
В создавании Вашего приложения устройства записи движения остановки Вы работаете со следующими тремя классами QTKit:
QTCaptureSession. Основной интерфейс для получения мультимедийных потоков.QTCaptureDecompressedVideoOutput. Выходное место назначения для aQTCaptureSessionвозразите, что можно использовать для обработки распакованных кадров от получающегося видео. Используя методы, предоставленные в этом классе, можно произвести распакованные видеокадры, подходящие для высококачественной обработки видеоданных.QTCaptureDeviceInput. Входной источник для устройств хранения данных, таких как камеры и микрофоны.
Пример кода, описанный в этой главе, не поддерживает ввод от камер DV, имеющих тип QTMediaTypeMuxed, вместо QTMediaTypeVideo. Для добавления поддержки камер DV считайте главу, Расширяющую Приложение Медиапроигрывателя.
Моделируйте приложение устройства записи движения остановки
Так же, как Вы сделали в разделе Prototype the Recorder, запустите путем создания грубого эскиза приложения устройства записи движения остановки QTKit. Думайте, снова, того, какие элементы дизайна Вы хотите включить в приложение.

В этом прототипе проекта Вы запускаете с трех простых объектов: представление получения, представление фильма в формате QuickTime и единственная кнопка для добавления кадров. Они будут стандартными блоками для Вашего приложения. Можно добавить больше сложности к проекту позже. После того, как Вы изобразили схематически свой прототип, думайте, как поднять трубку объекты в Интерфейсном Разработчике и что кодирует Вас потребность в Вашем проекте XCode заставить это произойти. Обратите внимание на то, что необходимо добавить контроллер фильма к QTMovieView объект на иллюстрации выше.
Создайте проект Используя Xcode 3.2
Для создания проекта выполните эти шаги, как в предыдущих главах:
Xcode 3.2 запуска и выбирает File> New Project.
Когда новое окно проекта появится, выберите Cocoa Document-based Application и нажмите Choose.
Назовите проект
StopMotionи перейдите к расположению, где Вы хотите, чтобы приложение XCode создало папку проекта.Окно проекта XCode появляется.


Из Меню действий в Вашем проекте XCode выберите Add> Add to Existing Frameworks.
Добавьте платформу QTKit к Вашему
StopMotionпроект, находящийся в/System/Library/Frameworksкаталог.Теперь добавьте Кварцевую платформу Ядра к своему проекту, также находящемуся в
/System/Library/Frameworksкаталог.Выбрать
QuartzCore.framework, и нажмите Add, когда появится окно Add To Targets.
Это завершает первую последовательность шагов в Вашем проекте. В следующей последовательности Вы определяете действия и выходы в XCode прежде, чем работать с Интерфейсным Разработчиком.
Поскольку Вы уже моделировали свое приложение устройства записи движения остановки QTKit, по крайней мере в грубой форме с ясно определенной моделью данных, можно теперь определить, какие действия и выходы должны быть реализованы. В этом случае у Вас есть a
QTCaptureViewобъект, который является подклассомNSView, aQTMovieViewвозразите для отображения полученных кадров и одной кнопки, чтобы записать полученный мультимедийный контент и добавить каждый единственный кадр к выводу фильма в формате QuickTime.
Импортируйте заголовки QTKit и установите Ваш файл реализации
Откройтесь
MyDocument.hфайл объявления в Вашем проекте XCode.В файле удалите оператора импорта Какао и замените его оператором импорта QTKit.
#import <QTKit/QTKit.h>
Откройтесь
MyDocument.mфайл реализации в Вашем проекте. Удалите содержание файла за исключением следующих строк кода:#import "MyDocument.h"
@implementation MyDocument
- (NSString *)windowNibName
{return @"MyDocument";
}
@end
Сохраните свой файл.
Определите действия и выходы, которые Вы хотите
Теперь начните добавлять выходы и действия.
В Вашем
MyDocument.hфайл, добавляют переменные экземпляраmCaptureViewиmMovieView.IBOutlet QTCaptureView *mCaptureView;
IBOutlet QTMovieView *mMovieView;
Добавьте
addFrame:метод действия.- (IBAction)addFrame:(id)sender;
Сохраните свой файл.
Теперь откройте Ваш
MyDocument.mфайл и добавляет тот же метод действия, сопровождаемый фигурными скобками для кода, который Вы добавляете позже для реализации этого действия.- (IBAction)addFrame:(id)sender
{}
Это завершает второй этап Вашего проекта. Теперь Вы работаете с Интерфейсным Разработчиком 3.2 для построения пользовательского интерфейса для проекта. Убедитесь, что Вы сохранили и свое объявление и файлы реализации, так, чтобы действия и выходы, которые Вы объявили, были синхронно обновлены в Вашем Интерфейсном пере Разработчика.
Создайте пользовательский интерфейс
В следующей фазе Вашего проекта Вы создаете пользовательский интерфейс для своего проекта.
Откройте Interface Builder 3.2 и щелкните
MyDocument.xibфайл в Вашем окне проекта XCode.В Интерфейсном Разработчике 3.2, выберите Tools> Library для открытия библиотеки объектов.
Прокрутите вниз к объекту представления получения QuickTime.

QTCaptureViewобъект предоставляет Вам экземпляр подкласса представления для отображения предварительного просмотра видеовыхода, полученного сеансом получения.Перетащите
QTCaptureViewвозразите в свое окно и измените размеры объекта соответствовать окну, предусмотрев пространство в нижней части для Вашей кнопки Add Frame (уже показанный на иллюстрации ниже) и вправо для ВашегоQTMovieViewвозразите в своем приложении устройства записи движения остановки QTKit.Выберите Tools> Inspector. В панели Identity выберите информацию («я») значок. Щелкните в поле Class и Вашем
QTCaptureViewобъект появляется.

Установите автокалибровку для объекта в панели Capture View Size.


Теперь повторите ту же последовательность, описанную на Шаге № 2 для добавления Вашего
QTMovieViewвозразите против своего окна (уже показанный выше).Прокрутите к
QTMovieViewобъект.Выберите
QTMovieViewобъект (символизируемый синим Q) и перетаскивает его в Ваше Окно рядом сQTCaptureViewобъект, показанный ниже.Выберите Tools> Inspector. В Инспекторе Идентификационных данных выберите информацию («я») значок. Щелкните в поле Class и Вашем
QTMovieViewобъект появляется.

Установите автокалибровку для Вашего
QTMovieViewобъект, как Вы сделали дляQTCaptureViewобъект на шагах выше.
Теперь укажите атрибуты окна в Вашем
MyDocument.xibфайл.Выберите объект окна в своем пере.
Щелкните по значку атрибутов в панели.
Определите размер окна, который Вы хотите в Вашем
MyDocument.xibпутем выбора значка размера (символизируемый желтой линейкой) в панели Window Size.
Укажите соединения розетки делегата Владельца Файла в панели Window Connections.


В Библиотеке выберите Кнопочное управление и перетащите его к окну.
Введите текст
Add Frame.Установите автокалибровку для кнопки в центре и прямо вне угла, оставив внутренние распорки нетронутыми, как показано на иллюстрации.

Выберите
MyDocument.xibфайл и нажимает Connections Inspector.Теперь обеспечьте электричеством выходы и полученные действия.
Перетащите управление каждую переменную экземпляра выхода к объекту Владельца Файла.

Выберите объект Владельца Файла в Вашем
MyDocument.xibфайл.Щелкните по значку Class Identity в Интерфейсном Инспекторе Разработчика.
Обратите внимание на то, что зеленый свет в левом углу Вашего
StopMotion.xcodeprojвключен, указав, что XCode и Интерфейсный Разработчик синхронизировали действия и выходы в Вашем проекте.
Сохраните свой Интерфейсный файл Разработчика.
Подготовьте получать видео Единственного Кадра
В последней фазе Вашего проекта, после добавления и завершения кода реализации, Вы готовы получить видео единственного кадра, с помощью приложения устройства записи движения остановки, как показано ниже.


Завершите реализацию класса MyDocument в XCode
Для завершения реализации класса MyDocument Вы определяете переменные экземпляра, указывающие на сеанс получения, а также на ввод устройства и распакованные объекты видеовыхода.
В Вашем проекте XCode добавьте переменные экземпляра к объявлению интерфейса.
Включите эти строки кода Ваш
MyDocument.hфайл объявления:@interface MyDocument : NSDocument
{QTMovie *mMovie;
QTCaptureSession *mCaptureSession;
QTCaptureDeviceInput *mCaptureDeviceInput;
QTCaptureDecompressedVideoOutput *mCaptureDecompressedVideoOutput;
}
mMovieпеременная экземпляра указывает наQTMovieобъект, иmCaptureSessionпеременная экземпляра указывает наQTCaptureSessionобъект. Аналогично,*mCaptureDeviceInputпеременная экземпляра указывает наQTCaptureDeviceInputобъект и следующая строка объявляют чтоmCaptureDecompressedVideoOutputпеременная экземпляра указывает наQTCaptureDecompressedVideoOutputобъект.Объявите
mCurrentImageBufferпеременная экземпляра.CVImageBufferRef mCurrentImageBuffer;
Эта переменная экземпляра хранит новый кадр, который Вы захватили в a
CVImageBufferRef.Это завершает код, который необходимо добавить к Вашему
MyDocument.hфайл.Откройте Ваш
MyDocument.mфайл и выполняет эти шаги.Создайте пустой фильм, пишущий в непостоянные данные в памяти, с помощью
initToWritableData:метод.- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{NSError *error = nil;
[super windowControllerDidLoadNib:aController];
[[aController window] setDelegate:self];
if (!mMovie) {mMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:&error];
if (!mMovie) {[[NSAlert alertWithError:error] runModal];
return;
}
}
Установите сеанс получения, выводящий необработанные кадры, которые Вы хотите захватить.
[mMovieView setMovie:mMovie];
if (!mCaptureSession) {BOOL success;
mCaptureSession = [[QTCaptureSession alloc] init];
Найдите видеоустройство и добавьте ввод устройства для того устройства к сеансу получения.
QTCaptureDevice *device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
success = [device open:&error];
if (!success) {[[NSAlert alertWithError:error] runModal];
return;
}
mCaptureDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:device];
success = [mCaptureSession addInput:mCaptureDeviceInput error:&error];
if (!success) {[[NSAlert alertWithError:error] runModal];
return;
}
Добавьте распакованный видеовыход, возвращающий необработанные кадры, которые Вы захватили к сеансу, и затем предварительно просматривает видео от сеанса в окне документа.
mCaptureDecompressedVideoOutput = [[QTCaptureDecompressedVideoOutput alloc] init];
[mCaptureDecompressedVideoOutput setDelegate:self];
success = [mCaptureSession addOutput:mCaptureDecompressedVideoOutput error:&error];
if (!success) {[[NSAlert alertWithError:error] runModal];
return;
}
Предварительно просмотрите видео от сеанса в окне документа.
[mCaptureView setCaptureSession:mCaptureSession];
Запустите сеанс, с помощью
startRunningметод Вы использовали ранее вMyRecorderпример кода.[mCaptureSession startRunning];
}
}
Реализуйте метод делегата это
QTCaptureDecompressedVideoOutputвызовы каждый раз, когда это принимает кадр.- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
Сохраните последний кадр. Сделайте это в a
@synchronizedблокируйте, потому что метод делегата не вызывают на основном потоке.CVImageBufferRef imageBufferToRelease;
CVBufferRetain(videoFrame);
@synchronized (self) {imageBufferToRelease = mCurrentImageBuffer;
mCurrentImageBuffer = videoFrame;
}
CVBufferRelease(imageBufferToRelease);
}
Окно дескриптора заключительные уведомления для Вашего ввода устройства и остановки сеанс получения.
- (void)windowWillClose:(NSNotification *)notification
{[mCaptureSession stopRunning];
QTCaptureDevice *device = [mCaptureDeviceInput device];
if ([device isOpen])
[device close];
}
Освободите память для своих объектов получения.
- (void)dealloc
{[mMovie release];
[mCaptureSession release];
[mCaptureDeviceInput release];
[mCaptureDecompressedVideoOutput release];
[super dealloc];
}
Укажите выходное место назначения для своих носителей с записанными данными, в этом случае доступный для редактирования фильм в формате QuickTime.
- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError
{QTMovie *newMovie = [[QTMovie alloc] initWithURL:absoluteURL error:outError];
if (newMovie) {[newMovie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
[mMovie release];
mMovie = newMovie;
}
return (newMovie != nil);
}
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError
{return [mMovie writeToFile:[absoluteURL path] withAttributes:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:QTMovieFlatten] error:outError];
}
Добавьте
addFrame:метод действия, который Вы указали ранее в Вашем файле реализации. Это позволяет Вам получить новый кадр, который Вы захватили. Сделайте это в a@synchronizedблокируйте, потому что метод делегата, устанавливающий новый кадр, не вызывают на основном потоке. Обратите внимание на то, что Вы обертываете aCVImageBufferRefобъект вNSImage. После созданияNSImage, можно тогда добавить его к фильму.- (IBAction)addFrame:(id)sender
{CVImageBufferRef imageBuffer;
@synchronized (self) {imageBuffer = CVBufferRetain(mCurrentImageBuffer);
}
if (imageBuffer) {NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:imageBuffer]];
NSImage *image = [[[NSImage alloc] initWithSize:[imageRep size]] autorelease];
[image addRepresentation:imageRep];
CVBufferRelease(imageBuffer);
[mMovie addImage:image forDuration:QTMakeTime(1, 10) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
@"jpeg", QTAddImageCodecType, nil]];
[mMovie setCurrentTime:[mMovie duration]];
[mMovieView setNeedsDisplay:YES];
[self updateChangeCount:NSChangeDone];
}
}
Создайте и скомпилируйте свое приложение устройства записи движения остановки
После сохранения проекта нажмите Build и Go. После компиляции нажмите кнопку Add Frame, чтобы записать каждый полученный кадр и вывести тот кадр к фильму в формате QuickTime. Вывод Вашего полученного сеанса сохраняется как фильм в формате QuickTime.
Теперь можно начать получать и записывать с приложением устройства записи движения остановки QTKit. Как правило, можно записать любое число кадров, иллюстрирующих перемещение или действие, с помощью объектов глины или рисунков линиями, например, который, когда объединено и зарегистрировано, создаст иллюзию движения в фильме или анимированной последовательности. Метод распространен в работе с различными неодушевленными объектами, которые могут быть собраны в определенную историю или рассказ.
Сводка
В этой главе Вы фокусировались на создании приложения устройства записи движения остановки с помощью трех объектов получения: QTCaptureSession, QTCaptureDecompressedVideoOutput и QTCaptureDeviceInput. Они были существенными стандартными блоками для Вашего проекта. Вы учились как:
Моделируйте и разработайте модель данных и управление для Вашего проекта в грубом эскизе прежде, чем создать фактический пользовательский интерфейс.
Определите определенное действие IB как кнопку для добавления кадров к записи.
Создайте пользовательский интерфейс с помощью
QTCaptureViewплагин от библиотеки Interface Builder средств управления.Обеспечьте электричеством Добавить кнопку Управления кадром для своего пользовательского интерфейса.
Определите переменные экземпляра, указывающие на сеанс получения, а также на ввод устройства и распакованные объекты видеовыхода.
Сборка и запущенный приложение устройства записи движения остановки, с помощью iSight камеры в качестве устройства ввода данных.
Выведите единственные полученные кадры к фильму в формате QuickTime для анимируемых эффектов.