Iphone 在将多个帧发送到AVAssetWriter之前,请在内存中保留这些帧

Iphone 在将多个帧发送到AVAssetWriter之前,请在内存中保留这些帧,iphone,avfoundation,avcapturesession,avassetwriter,Iphone,Avfoundation,Avcapturesession,Avassetwriter,我需要将captureSession中的一些视频帧保存在内存中,并在发生“某些事情”时将其写入文件 与之类似,我使用以下代码将帧放入NSMutableArray: - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection {

我需要将captureSession中的一些视频帧保存在内存中,并在发生“某些事情”时将其写入文件

与之类似,我使用以下代码将帧放入NSMutableArray:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{       
    //...
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    uint8 *baseAddress = (uint8*)CVPixelBufferGetBaseAddress(imageBuffer);
    NSData *rawFrame = [[NSData alloc] initWithBytes:(void*)baseAddress length:(height * bytesPerRow)];
    [m_frameDataArray addObject:rawFrame];
    [rawFrame release];
    //...
}
下面是编写视频文件的步骤:

-(void)writeFramesToFile
{
    //...
    NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt:640], AVVideoWidthKey,
                                    [NSNumber numberWithInt:480], AVVideoHeightKey,
                                    AVVideoCodecH264, AVVideoCodecKey,
                                    nil ];
    AVAssetWriterInput *bufferAssetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings];
    AVAssetWriter *bufferAssetWriter = [[AVAssetWriter alloc]initWithURL:pathURL fileType:AVFileTypeQuickTimeMovie error:&error];
    [bufferAssetWriter addInput:bufferAssetWriterInput];

    [bufferAssetWriter startWriting];
    [bufferAssetWriter startSessionAtSourceTime:startTime];
    for (NSInteger i = 1; i < m_frameDataArray.count; i++){
        NSData *rawFrame = [m_frameDataArray objectAtIndex:i];
        CVImageBufferRef imgBuf = [rawFrame bytes];
        [pixelBufferAdaptor appendPixelBuffer:imgBuf withPresentationTime:CMTimeMake(1,10)]; //<-- EXC_BAD_ACCESS
        [rawFrame release];
    }
    //... (finishing video file)
}
-(无效)writeFramesToFile
{
//...
NSDictionary*outputSettings=[NSDictionary Dictionary WithObjectsAndKeys:
[NSNumber numberWithInt:640],AVVideoWidthKey,
[NSNumber Number Withint:480],AVVideoHeightKey,
AVVideoCodecH264,AVVideoCodeKey,
零];
AVAssetWriterInput*bufferAssetWriterInput=[AVAssetWriterInput assetWriterInputWithMediaType:AvMediaType视频输出设置:输出设置];
AVAssetWriter*bufferAssetWriter=[[AVAssetWriter alloc]initWithURL:pathURL文件类型:AVFileTypeQuickTimeMovie错误:&error];
[bufferAssetWriter附加输入:bufferAssetWriterInput];
[bufferAssetWriter开始编写];
[bufferAssetWriter startSessionAtSourceTime:startTime];
对于(NSInteger i=1;i[PixelBufferAdapter appendPixelBuffer:imgbufwithPresentationTime:CMTimeMake(1,10)];//在访问imageBuffer的属性之前,应该锁定基址

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
uint8 *baseAddress = (uint8*)CVPixelBufferGetBaseAddress(imageBuffer);
NSData *rawFrame = [[NSData alloc] initWithBytes:(void*)baseAddress length:(height * bytesPerRow)];
[m_frameDataArray addObject:rawFrame];
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

这已经很古老了,但为了帮助后来的人,有几个问题需要解决:

  • 根据Alex的回答,在复制时锁定/解锁基址
  • CVImageBufferRef是一种抽象基类类型。您希望使用CVPixelBufferCreateWithBytes创建实例,而不仅仅是对原始像素字节进行类型转换。(系统需要知道这些像素的大小/格式)
  • 您应该直接从原始数据创建并存储新的CVPixelBuffer,而不是使用中间NSData进行存储。这样,您只需复制一个而不是两个

  • 谢谢你的评论。我的代码中确实有这些行,但是我忘了在这里添加它们,对不起。我还尝试在不解锁的情况下锁定缓冲区(大约300个示例),但这也不起作用。CaptureSession的队列大小似乎限制在5帧左右。您缺少代码中的第一帧。NSArray从0开始索引。此外,CVImageBuffer不仅仅是原始字节的集合。它是一种结构。您应该创建一个CVPixelBuffer。请查看核心视频framewor中的CVPixelBuffer.hk、 基本上,创建一个新的像素缓冲区。