私は非常に簡単なことをやろうとしています。私は、フルスクリーンでビデオレイヤーを表示したいと思います。そして、1秒に1回、CMSampleBufferRefでUIImageを更新します。しかし私は2つの異なる問題に遭遇しています。最初の1であることを変える:キャプチャ出力プロトコルから画像を呼び出すと画像が更新されないのはなぜですか?
[connection setVideoMaxFrameDuration:CMTimeMake(1, 1)];
[connection setVideoMinFrameDuration:CMTimeMake(1, 1)];
また、ビデオプレビュー層を変更します、私はそれが唯一のAV基盤がデリゲートに情報を送るところでレートを変更するだろうと思ったが、セッション全体に影響を及ぼしているようです(それはより明白に見える)。これにより、毎秒私のビデオが更新されます。私はそれらの行を省略することができ、それを処理する別のメソッドにCMSampleBufferRefを毎秒送信するように、デリゲートにタイマーを追加するだけです。しかし、これが正しいアプローチであるかどうかは分かりません。
私の第二の問題は、UIImageViewが更新されていない、あるいは時にはそれが一度だけ更新した後に変更されないということです。私はそれを更新するには、このメソッドを使用しています:私はリンゴの例から取った
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection {
//NSData *jpeg = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:sampleBuffer] ;
UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
[imageView setImage:image];
// Add your code here that uses the image.
NSLog(@"update");
}
。このメソッドは、更新メッセージを読んでチェックする毎秒正しく呼び出されています。しかし、イメージは全く変化していません。また、sampleBufferが自動的に破棄されるか、またはそれを解放する必要がありますか? ビューがロードDID:UIImageに
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
session = [[AVCaptureSession alloc] init];
// Add inputs and outputs.
if ([session canSetSessionPreset:AVCaptureSessionPreset640x480]) {
session.sessionPreset = AVCaptureSessionPreset640x480;
}
else {
// Handle the failure.
NSLog(@"Cannot set session preset to 640x480");
}
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(@"Could create input: %@", error);
}
if ([session canAddInput:input]) {
[session addInput:input];
}
else {
// Handle the failure.
NSLog(@"Could not add input");
}
// DATA OUTPUT
dataOutput = [[AVCaptureVideoDataOutput alloc] init];
if ([session canAddOutput:dataOutput]) {
[session addOutput:dataOutput];
dataOutput.videoSettings =
[NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey: (id)kCVPixelBufferPixelFormatTypeKey];
//dataOutput.minFrameDuration = CMTimeMake(1, 15);
//dataOutput.minFrameDuration = CMTimeMake(1, 1);
AVCaptureConnection *connection = [dataOutput connectionWithMediaType:AVMediaTypeVideo];
[connection setVideoMaxFrameDuration:CMTimeMake(1, 1)];
[connection setVideoMinFrameDuration:CMTimeMake(1, 1)];
}
else {
// Handle the failure.
NSLog(@"Could not add output");
}
// DATA OUTPUT END
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[dataOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
[captureVideoPreviewLayer setBounds:videoLayer.layer.bounds];
[captureVideoPreviewLayer setPosition:videoLayer.layer.position];
[videoLayer.layer addSublayer:captureVideoPreviewLayer];
[session startRunning];
}
隠密CMSampleBufferRefを:あなたは私を与えることができます任意の助けを事前に
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
{
// Get a CMSampleBuffer's Core Video image buffer for the media data
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// Get the number of bytes per row for the pixel buffer
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
// Get the number of bytes per row for the pixel buffer
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
// Get the pixel buffer width and height
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
// Create a device-dependent RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// Free up the context and color space
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// Create an image object from the Quartz image
UIImage *image = [UIImage imageWithCGImage:quartzImage];
// Release the Quartz image
CGImageRelease(quartzImage);
return (image);
}
おかげ
これは、他の2つの重要な方法です。 captureOutput:didOutputSampleBuffer:fromConnection:
メソッドのドキュメントから
私が望んでメイントレッドacomplishにそれを移動するには、トレッドの良い学習サイトを知ることが起こるのか?私は彼らに全く新しいです。また、最初の質問は、私はリアルタイムで表示されるビデオが欲しいですが、私は重度のprossesingを行う予定とiphoneがそれを処理することができない可能性があるため、毎秒1フレームを処理したい。だから私はどのようにビデオfpsを通常に設定し、毎秒1回出力ルーチンをキャプチャするのか分からない。 – Pochi
私はアップルのドキュメントはあなたが得ることができる最高だと思います。【発送キュー](https://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1)と[Threading](https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html)を参照してください。あなたの他の問題については、私の答えで提案した技術がうまくいくと思います。 – adig