1

OpenGLを使用して、1280x720 のクイックタイム ビデオの各フレームで画像処理を行っています。次にフレームが読み戻され、これらから新しいビデオが作成されます。問題は、大量のデータをOpenGLとの間で( glTexImage2DglReadPixelsを使用して) 転送する必要があるため、プロセスが非常に遅くなることです。

現在、AVAssetReaderTrackOutputインスタンスのピクセル形式としてkCVPixelFormatType_32BGRAを使用しています。時間を短縮するために、代わりに 16 ビット ピクセル形式を使用したいと考えています。残念ながら、このような形式に変更すると、AVAssetReaderTrackOutput の copyNextSampleBufferメソッドを呼び出すときに空のフレームが表示されます。AV Foundation で 16 ビット ピクセル形式を使用した経験のある人はいますか?

AV Foundation にフォーマットを変更してもらうことができない場合は、おそらく NEON 命令を使用して、「手動で」32 ビットから 16 ビットに変換できると思いますか? どんな助けでも大歓迎です。

4

1 に答える 1

1

さらに改訂し、これはコミュニティ wiki になりました。なぜなら、この質問だけに答えるのに非常に多くの間違いを犯してしまったからです。

CoreGraphics は一応、次のコードのようなものを使用して 32 ビットから 16 ビットへの変換を行うことができますが、代わりに、「4 整数ビット/コンポーネント; 16 ビット/ピクセル; 3 コンポーネント カラー スペース; kCGImageAlphaPremultipliedLast」がサポートされていないことを報告します。パラメータの組み合わせ。そのため、CoreGraphics は 4 ビット/チャンネルの画像を内部的に理解できないようです。

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, buffer, width*height*4, NULL);
CGImageRef inputImage = CGImageCreate(  width, height,
                                        8, 32, width*4, 
                                        colourSpace, 
                                        kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big,
                                        dataProvider,
                                        NULL, NO,
                                        kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);

unsigned char *outputImage = (unsigned char *)malloc(width*height*2);
CGContextRef targetContext = CGBitmapContextCreate( outputImage,
                                                    width, height,
                                                    4, width*2,
                                                    colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextDrawImage(targetContext, CGRectMake(0, 0, width, height), inputImage);

/* uplopad outputImage to OpenGL here! */

CGContextRelease(targetContext);
CGImageRelease(inputImage);
CGColorSpaceRelease(colourSpace);
free(outputImage);

ただし、ドキュメントごとに:

サポートされているピクセル フォーマットは、kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange、kCVPixelFormatType_420YpCbCr8BiPlanarFullRange、および kCVPixelFormatType_32BGRA です。サポートされているピクセル フォーマットが kCVPixelFormatType_422YpCbCr8 および kCVPixelFormatType_32BGRA である iPhone 3G を除きます。

したがって、受け取るサイズを小さくするために、YCbCr カラー スペースに切り替えることができます。バッファーがバイプラナーに戻ると (つまり、画像全体のすべての y コンポーネント、次にすべての Cb および Cr コンポーネントが個別のブロックとして)、それらを 2 つの個別のテクスチャとして OpenGL にアップロードし、シェーダーで再結合することができます。 3GS 以上に限定し、SGX iOS デバイスで利用可能な 8 つのテクスチャ ユニットのうち 2 つのテクスチャ ユニットを使用する余裕があります。

YCbCr は、色を明るさ (Y) と色 (CbCr) で別々に表現する色空間です。カラー チャネルは明るさよりも低い周波数でサンプリングできることが経験的に示されていますが、誰にもわかりません。ピクセル形式の「420」の部分は、4 つの Y コンポーネントごとに取得する Cb および Cr コンポーネントの数を表します。基本的には、Y の 4 つのサンプルごとに Cb の 1 つのサンプルと Cr の 1 つのサンプルを取得することを示しています。 RGB で 24 ビット/ピクセルではなく 12 ビット/ピクセルの場合、4 つのピクセルを記述するために合計 6 バイト。これにより、ストレージの 50% を節約できます。

GL の目的では、1 回ではなく 2 回のアップロードであるため、追加料金が発生する可能性があります。また、依存するテクスチャの読み取りを避けたい場合は、3 つの変数を使用する必要があります。SGX はそのうちの 8 つに制限されていると思います。

于 2011-05-25T10:46:05.937 に答える