我正在使用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(然而,在iPhone 4s上不是别人提到的60fps),当计时适配器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);
}这也行得通,视频看起来没问题。然而,它非常慢,并且帧速率变得不可接受。奇怪的是,最大的减速不是复制,而是适配器appendPixelBuffer步骤现在比以前多花了10-100倍的时间。所以我猜它不喜欢我创建的pxbuffer,但我知道为什么。我在设置视频输出和适配器时使用的是kCVPixelFormatType_32BGRA。
有没有人能推荐一种更好的复制/裁剪方法?你能直接在ImageBuffer上做吗?
发布于 2012-09-08 16:45:05
我找到了一个解决方案。在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];https://stackoverflow.com/questions/12314865
复制相似问题