為了完成實時的捕獲私沮,首先初始化一個AVCaputureSession對象用于創(chuàng)建一個捕獲會話(session)郑兴,我們可以使用AVCaptureSession對象將AV輸入設(shè)備的數(shù)據(jù)流以另一種形式轉(zhuǎn)換到輸出册招。
然后,我們初始化一個AVCaptureDeviceInput對象兼雄,以創(chuàng)建一個輸入數(shù)據(jù)源部默,該數(shù)據(jù)源為捕獲會話(session)提供視頻數(shù)據(jù),再調(diào)用addInput方法將創(chuàng)建的輸入添加到AVCaptureSession對象称近。
接著初始化一個AVCaptureVideoDataOuput對象第队,以創(chuàng)建一個輸出目標(biāo),然后調(diào)用addOutput方法將該對象添加到捕獲會話中刨秆。
AVCaptureVideoDataOutput可用于處理從視頻中捕獲的未經(jīng)壓縮的幀凳谦。一個AVCaptureVideoDataOutput實例能處理許多其他多媒體API能處理的視頻幀,你可以通過captureOutput:didOutputSampleBuffer:fromConnection:這個委托方法獲取幀衡未,使用setSampleBufferDelegate:queue:設(shè)置抽樣緩存委托和將應(yīng)用回調(diào)的隊列尸执。AVCaptureVideoDataOutputSampleBuffer對象的委托必須采用AVCaptureVideoDataOutputSampleBufferDelegate協(xié)議家凯,使用sessionPreset協(xié)議來制定輸出品質(zhì)。
我們可以通過調(diào)用捕獲會話的startRunning方法啟動從輸入到輸出的數(shù)據(jù)流如失,通過stopRunning方法來停止數(shù)據(jù)流绊诲。
列表1給出了一個例子。setupCaptureSession創(chuàng)建了一個捕獲會話褪贵,添加了一個視頻輸入提供提視頻幀掂之,一個輸出目標(biāo)獲取捕獲的幀,然后啟動從輸入到輸出的數(shù)據(jù)流脆丁。當(dāng)捕獲會話正在運行時世舰,使用captureOut:didOutputSampleBuffer:fromConnection方法將被捕獲的視頻抽樣幀發(fā)送給抽樣緩存委托,然后每個抽樣緩存(CMSampleBufferRef)被轉(zhuǎn)換成imageFromSampleBuffer中的一個UIImage對象槽卫。
---------------------------
列表1:使用AV Foundation設(shè)置一個捕獲設(shè)備錄制視頻并將是視頻幀保存為UIImage對象跟压。
#import
// 創(chuàng)建并配置一個捕獲會話并且啟用它
- (void)setupCaptureSession
{
NSError *error = nil;
// 創(chuàng)建session
AVCaptureSession *session = [[AVCaptureSession alloc] init];
// 可以配置session以產(chǎn)生解析度較低的視頻幀,如果你的處理算法能夠應(yīng)付(這種低解析度)歼培。
// 我們將選擇的設(shè)備指定為中等質(zhì)量震蒋。
session.sessionPreset = AVCaptureSessionPresetMedium;
// 找到一個合適的AVCaptureDevice
AVCaptureDevice *device = [AVCaptureDevice
defaultDeviceWithMediaType:AVMediaTypeVideo];
// 用device對象創(chuàng)建一個設(shè)備對象input,并將其添加到session
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
error:&error];
if (!input) {
// 處理相應(yīng)的錯誤
}
[session addInput:input];
// 創(chuàng)建一個VideoDataOutput對象躲庄,將其添加到session
AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
[session addOutput:output];
// 配置output對象
dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
// 指定像素格式
output.videoSettings =
[NSDictionary dictionaryWithObject:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
// 如果你想將視頻的幀數(shù)指定一個頂值, 例如15ps
// 可以設(shè)置minFrameDuration(該屬性在iOS 5.0中棄用)
output.minFrameDuration = CMTimeMake(1, 15);
// 啟動session以啟動數(shù)據(jù)流
[session startRunning];
// 將session附給實例變量
[self setSession:session];
}
// 抽樣緩存寫入時所調(diào)用的委托程序
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
// 通過抽樣緩存數(shù)據(jù)創(chuàng)建一個UIImage對象
UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
< 此處添加使用該image對象的代碼 >
}
// 通過抽樣緩存數(shù)據(jù)創(chuàng)建一個UIImage對象
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
{
// 為媒體數(shù)據(jù)設(shè)置一個CMSampleBuffer的Core Video圖像緩存對象
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 鎖定pixel buffer的基地址
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// 得到pixel buffer的基地址
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
// 得到pixel buffer的行字節(jié)數(shù)
size_tbytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
// 得到pixel buffer的寬和高
size_twidth = CVPixelBufferGetWidth(imageBuffer);
size_theight = CVPixelBufferGetHeight(imageBuffer);
// 創(chuàng)建一個依賴于設(shè)備的RGB顏色空間
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// 用抽樣緩存的數(shù)據(jù)創(chuàng)建一個位圖格式的圖形上下文(graphics context)對象
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// 根據(jù)這個位圖context中的像素數(shù)據(jù)創(chuàng)建一個Quartz image對象
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// 解鎖pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// 釋放context和顏色空間
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// 用Quartz image創(chuàng)建一個UIImage對象image
UIImage *image = [UIImage imageWithCGImage:quartzImage];
// 釋放Quartz image對象
CGImageRelease(quartzImage);
return (image);
}