我正在使用 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 上执行此操作吗?