AVAssetWriterを使用して、カメラからのライブフィードを保存しています。これは、このコードを使用してうまく機能します
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CMTime lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
if(videoWriter.status != AVAssetWriterStatusWriting){
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:lastSampleTime];
}
if(adaptor.assetWriterInput.readyForMoreMediaData) [adaptor appendPixelBuffer:imageBuffer withPresentationTime:lastSampleTime];
else NSLog(@"adaptor not ready",);
}
私は通常30fpsに近づいています(ただし、他の人が指摘しているようにiPhone4sでは60fpsではありません)。タイミング[adaptor appendPixelBuffer]の場合、数ミリ秒しかかかりません。
ただし、フルフレームは必要ありませんが、高品質(低圧縮、フレームごとのキーフレーム)が必要であり、数回後にプロセスを読み戻す予定です。したがって、書き込む前に画像をトリミングしたいと思います。幸いなことに、バッファの単純なmemcpyを実行できるように、中央にストリップが必要なだけです。これを行うために、アダプターにコピーして書き込むCVPixelBufferRefを作成しています。
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CMTime lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
if(videoWriter.status != AVAssetWriterStatusWriting){
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:lastSampleTime];
}
CVPixelBufferLockBaseAddress(imageBuffer,0);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
void * buffIn = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, nil, &pxbuffer);
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *buffOut = CVPixelBufferGetBaseAddress(pxbuffer);
NSParameterAssert(buffOut != NULL);
//Copy the whole buffer while testing
memcpy(buffOut, buffIn, width * height * 4);
//memcpy(buffOut, buffIn+sidecrop, width * 100 * 4);
if (adaptor.assetWriterInput.readyForMoreMediaData) [adaptor appendPixelBuffer:pxbuffer withPresentationTime:lastSampleTime];
else NSLog(@"adaptor not ready");
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}
これも機能し、ビデオは問題ないように見えます。ただし、それは非常に遅く、フレームレートは許容できなくなります。そして不思議なことに、大きな速度低下はコピーではなく、[adaptor appendPixelBuffer]ステップに以前の10〜100倍の時間がかかるようになったことです。ですから、私が作成したpxbufferは気に入らないと思いますが、その理由はわかります。ビデオ出力とアダプターの両方をセットアップするときにkCVPixelFormatType_32BGRAを使用しています。
誰かがコピー/トリミングを行うためのより良い方法を提案できますか?ImageBufferで直接それを行うことができますか?