5

「何か」が発生したときに、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)
}

しかし、imgBuf 参照に何か問題があります。助言がありますか?前もって感謝します。

4

2 に答える 2

4

You're supposed to lock base address before accessing imageBuffer's properties.

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);
于 2011-06-04T11:53:17.903 に答える
2

これはかなり古いものですが、後に続く人を助けるために、いくつかの問題を修正する必要があります。

  1. アレックスの回答で提案されているように、コピーするときにベースアドレスをロック/ロック解除します
  2. CVImageBufferRef は抽象基本クラス型です。CVPixelBufferCreateWithBytes を使用して、生のピクセル バイトを型キャストするだけでなく、インスタンスを作成します。(システムはそれらのピクセルのサイズ/フォーマットを知る必要があります)
  3. ストレージに中間の NSData を使用するのではなく、元のデータから直接新しい CVPixelBuffer を作成して保存する必要があります。そうすれば、コピーを 2 つではなく 1 つ実行するだけで済みます。
于 2015-02-13T18:55:21.670 に答える