4

ビデオをキャプチャし、結果の YUV フレームを処理します。出力は次のようになります。 結果のビデオのサンプル

それは私の電話の画面に正常に表示されますが。しかし、私のピアは上の画像のようにそれを受け取ります。すべてのアイテムが繰り返され、水平方向および垂直方向にある値だけシフトされます

キャプチャしたビデオは 352x288 で、YPixelCount = 101376、UVPixelCount = YPIXELCOUNT/4 です。

これを解決する手がかり、または iOS で YUV ビデオ フレームを処理する方法を理解するための出発点はありますか?

    NSNumber* recorderValue = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
    [videoRecorderSession setSessionPreset:AVCaptureSessionPreset352x288];

そしてこれがcaptureOutput関数です

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    if(CMSampleBufferIsValid(sampleBuffer) && CMSampleBufferDataIsReady(sampleBuffer) && ([self isQueueStopped] == FALSE))
    {

        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
        CVPixelBufferLockBaseAddress(imageBuffer,0); 
        UInt8 *baseAddress[3] = {NULL,NULL,NULL};
        uint8_t *yPlaneAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,0);
        UInt32 yPixelCount =  CVPixelBufferGetWidthOfPlane(imageBuffer,0) * CVPixelBufferGetHeightOfPlane(imageBuffer,0);
        uint8_t *uvPlaneAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,1);
        UInt32 uvPixelCount = CVPixelBufferGetWidthOfPlane(imageBuffer,1) * CVPixelBufferGetHeightOfPlane(imageBuffer,1);
        UInt32  p,q,r;
        p=q=r=0;
        memcpy(uPointer, uvPlaneAddress, uvPixelCount);
        memcpy(vPointer, uvPlaneAddress+uvPixelCount, uvPixelCount);

        memcpy(yPointer,yPlaneAddress,yPixelCount);
        baseAddress[0] = (UInt8*)yPointer;
        baseAddress[1] = (UInt8*)uPointer;
        baseAddress[2] = (UInt8*)vPointer;
        CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    }
}

上記のコードに何か問題がありますか?

4

1 に答える 1

2

あなたのコードはそれほど悪くはありません。2 つの間違いと 1 つの潜在的な問題が見られます。

  • uvPixelCount正しくありません。YUV 420 形式は、2 x 2 ピクセル ブロックごとに色情報があることを意味します。したがって、正しいカウントは次のとおりです。

    uvPixelCount = (width / 2) * (height / 2);
    

    あなたは について何か書いてyPixelCount / 4いますが、あなたのコードではそれがわかりません。

  • UV 情報はインターリーブされます。つまり、2 番目のプレーンには、U 値と V 値が交互に含まれます。別の言い方をすれば、すべての偶数バイト アドレスに U 値があり、すべての奇数バイト アドレスに V 値があります。U 情報と V 情報を本当に分離する必要がある場合は、memcpyそうしません。

  • 各ピクセル行の後に余分なバイトがある場合があります。CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0)2 つの行の間のバイト数を取得するために使用する必要があります。結果、シングルmemcpyじゃダメ。代わりに、各ピクセル行を個別にコピーして、行間の余分なバイトを取り除く必要があります。

これらはすべて、結果の画像の一部を説明するだけです。残りの部分は、おそらくコードと受信ピアが期待するものとの違いによるものです。それについては何も書いていませんか?ピアは U 値と V 値を分離する必要がありますか? 圧縮も4:2:0ですか?フルレンジではなくビデオレンジですか?

より多くの情報を提供していただければ、より多くのヒントを提供できます。

于 2011-12-13T21:20:55.620 に答える