1

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で直接それを行うことができますか?

4

1 に答える 1

4

私は解決策を見つけました。iOS5(私はアップデートを見逃していました)では、AVAssetWriterを設定してビデオをトリミングすることができます(Steveも指摘しています)。AVVideoScalingModeKeyをAVVideoScalingModeResizeAspectFillに設定します

videoWriter = [[AVAssetWriter alloc] initWithURL:filmurl 
                                        fileType:AVFileTypeQuickTimeMovie 
                                           error:&error];  
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
     AVVideoCodecH264, AVVideoCodecKey, 
     [NSNumber numberWithInt:1280], AVVideoWidthKey,  
     [NSNumber numberWithInt:200], AVVideoHeightKey,
     AVVideoScalingModeResizeAspectFill, AVVideoScalingModeKey,// This turns the
                                                               // scale into a crop
     nil]; 
videoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 
                                                       outputSettings:videoSettings] retain];
于 2012-09-08T08:45:04.893 に答える