Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MyDocument.m
// |
// MyDocument.m |
// StillMotion |
// |
/* |
Disclaimer: IMPORTANT: This Apple software is supplied to you by |
Apple Inc. ("Apple") in consideration of your agreement to the |
following terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, |
install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. |
may be used to endorse or promote products derived from the Apple |
Software without specific prior written permission from Apple. Except |
as expressly stated in this notice, no other rights or licenses, express |
or implied, are granted by Apple herein, including but not limited to |
any patent rights that may be infringed by your derivative works or by |
other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2007 Apple Inc. All Rights Reserved. |
*/ |
#import "MyDocument.h" |
@implementation MyDocument |
- (NSString *)windowNibName |
{ |
return @"MyDocument"; |
} |
- (void)windowControllerDidLoadNib:(NSWindowController *) aController |
{ |
NSError *error = nil; |
[super windowControllerDidLoadNib:aController]; |
[[aController window] setDelegate:self]; |
if (!mMovie) { |
// Create an empty movie that writes to mutable data in memory |
mMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:&error]; |
if (!mMovie) { |
[[NSAlert alertWithError:error] runModal]; |
return; |
} |
} |
[mMovieView setMovie:mMovie]; |
if (!mCaptureSession) { |
// Set up a capture session that outputs raw frames |
BOOL success; |
mCaptureSession = [[QTCaptureSession alloc] init]; |
// Find a video device |
QTCaptureDevice *device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; |
success = [device open:&error]; |
if (!success) { |
[[NSAlert alertWithError:error] runModal]; |
return; |
} |
// Add a device input for that device to the capture session |
mCaptureDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:device]; |
success = [mCaptureSession addInput:mCaptureDeviceInput error:&error]; |
if (!success) { |
[[NSAlert alertWithError:error] runModal]; |
return; |
} |
// Add a decompressed video output that returns raw frames to the session |
mCaptureDecompressedVideoOutput = [[QTCaptureDecompressedVideoOutput alloc] init]; |
[mCaptureDecompressedVideoOutput setDelegate:self]; |
success = [mCaptureSession addOutput:mCaptureDecompressedVideoOutput error:&error]; |
if (!success) { |
[[NSAlert alertWithError:error] runModal]; |
return; |
} |
// Preview the video from the session in the document window |
[mCaptureView setCaptureSession:mCaptureSession]; |
// Start the session |
[mCaptureSession startRunning]; |
} |
} |
- (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]; |
} |
- (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]; |
} |
// This delegate method is called whenever the QTCaptureDecompressedVideoOutput receives a frame |
- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection |
{ |
// Store the latest frame |
// This must be done in a @synchronized block because this delegate method is not called on the main thread |
CVImageBufferRef imageBufferToRelease; |
CVBufferRetain(videoFrame); |
@synchronized (self) { |
imageBufferToRelease = mCurrentImageBuffer; |
mCurrentImageBuffer = videoFrame; |
} |
CVBufferRelease(imageBufferToRelease); |
} |
- (IBAction)addFrame:(id)sender |
{ |
// Get the most recent frame |
// This must be done in a @synchronized block because the delegate method that sets the most recent frame is not called on the main thread |
CVImageBufferRef imageBuffer; |
@synchronized (self) { |
imageBuffer = CVBufferRetain(mCurrentImageBuffer); |
} |
if (imageBuffer) { |
// Create an NSImage and add it to the movie |
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]; |
} |
} |
@end |
Copyright © 2007 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2007-11-14