Создавание приложения движения остановки 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 для анимируемых эффектов.