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",);
}

我通常接近 30 fps(但在 iPhone 4s 上不是 60 fps,正如其他人所指出的那样),并且在计时 [适配器 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 来裁剪您的视频(史蒂夫也指出)。将 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 回答