9

実際の質問

いくつかの答えが私の問題を解決します:

  1. CGImageのように、ダイレクト データ プロバイダ ( で作成CGDataProviderCreateDirect)からデータを強制的にリロードすることはできCGContextDrawImageますか? または、それを行うために self.layer.contents に設定できる他の方法はありますか?
  2. CGContext1024x768 の画像を少なくとも 30 fps で一貫してレンダリングするために使用できる構成またはトリックはありますかCGContextDrawImage
  3. CVOpenGLESTextureCacheCreateTextureFromImage独自のテクスチャ データを使用して、リアルタイム バッファの更新に成功した人はいますか? CVImageBufferApples のテクスチャに関するドキュメントから他のプロパティをコピーしたので、私の最大の問題は を作成することだと思います。誰かがこれについてさらに情報を持っているなら、それは素晴らしいでしょう.
  4. 30 fps でメモリから画面に画像を取得する方法に関するその他のガイドライン。

背景(ロット):

NPOT 画像データのピクセルをリアルタイム (最小 30 fps) で変更し、iOS の画面に描画する必要があるプロジェクトに取り組んでいます。

私が最初に考えたのは、更新に OpenGL を使用glTexSubimage2Dすることでしたが、残念ながら、ドライバーがフレームごとに回転して RGB データを BGR に変換するため、非常に遅くなりました (iPad では 6 fps)。glTexSubImage2Dだからあなたが言うBGRでそれを送ってください、そして私もそうしますが、何らかの理由でGL_BGRgo figureで呼び出すことができません. 画像データが 2 の累乗ではないため、速度が遅くなることはわかっていますが、私の要件ではそれが求められます。

より多くの読書が私に導きましたCVOpenGLESTextureCacheCreateTextureFromImageが、すべての例は、直接カメラ入力を使用して取得するものCVImageBufferRefです。ドキュメント(公式ではなくヘッダーコメントのみ)を使用して、画像データから独自の CVImageBuffer を作成しようとしましたが、これでは機能しません(いいえこれは、Apple がリアルタイム カメラ データを処理するために特別に構築したものであり、IDK 以外ではあまりテストされていないと思われます。

とにかく、OpenGL をダンプして私の考えをCoreGraphicsに切り替えることで私の尊厳をあきらめた後、iPhone で画面バッファーを描画する最速の方法であるこの質問に導かれました。 CGImage にはそれが必要ですよね。まあ、宣伝されているようにはうまくいかないようです。私が使用すると、すべてが機能します。ピクセル バッファーを変更できます。描画のたびに、必要に応じてデータ プロバイダーから画像データを要求し、(CGImageCGDataProviderCreateDirectCGContextDrawImageCGDataProviderDirectCallbacksNote:以前のものと同じアドレスを持つ場合、更新されたポインターを無視する最適化が組み込まれているようです)。CGContextDrawImage は、補間を無効にして 6 fps から引き上げても、超高速 (約 18 fps) ではありません。Apple のドキュメントによると、 を使用self.layer.contentsすると よりもはるかに高速になりCGContextDrawImageます。を使用self.layer.contentsすると、最初の割り当てで機能しますが、 を呼び出した場合でも、CGImageのようにデータ プロバイダーからのリロードを要求することはありません。私が言及した SO の質問では、フレームごとにデータ ソースから新しい CGImage を作成および破棄することで、ユーザーが問題の解決策を示しています。CGContextDrawImage[layer setNeedsDisplay]

:これらすべての操作をプロファイルしましたが、問題は実際にはglTexSubImageOpenGLの問題CGContextDrawImageであり、実際にはCoreGraphicsの問題であるため、「go profile」の回答はありません。

EDITこの手法を示すソース コードは、 http: //github.com/narpas/image-sequence-streamingにあります。

4

1 に答える 1

9

これを手伝ってくれた Brad Larson と David H に感謝します (コメントで私たちの完全な議論を参照してください)。OpenGL と CoreVideo を使用してCVOpenGLESTextureCache生の画像を画面にプッシュする最速の方法であることが判明し (CoreGraphics が最速ではないことはわかっていました!)、iPad 1 でフルスクリーン 1024x768 画像で 60 fps を実現しました。これについて今、私は人々を助けるためにできるだけ多くを説明しようとします:

CVOpenGLESTextureCacheCreateTextureFromImageを使用すると、作成に使用するメモリに直接マップされたメモリを持つ OpenGL テクスチャを作成できますCVImageBuffer。これにより、生データでたとえば を作成し、CVPixelBufferから収集したデータ ポインタを変更できますCVPixelBufferGetBaseAddress。これにより、実際のテクスチャを変更したり再アップロードしたりする必要なく、OpenGL で即座に結果が得られます。CVPixelBufferLockBaseAddressピクセルを変更する前に必ずロックし、完了したらロックを解除してください。現時点では、これは iOS シミュレーターでは機能せず、CPU が VRAM に直接アクセスできない VRAM/RAM 部門からのものであると私が推測するデバイスでのみ機能します。glTexImage2DBrad は、条件付きコンパイラ チェックを使用して生の更新とテクスチャ キャッシュの使用を切り替えることを推奨しました。

注意すべき点がいくつかあります(これらの組み合わせにより、私には機能しませんでした):

  1. デバイスでテスト
  2. たとえば、参照リンクCVPixelBufferでサポートされていることを確認してください (ありがとう、ブラッド)。kCVPixelBufferIOSurfacePropertiesKey
  3. GL_CLAMP_TO_EDGEOpenGL ES 2.0 で NPOT テクスチャ データを使用する必要があります
  4. テクスチャ キャッシュを glBindTexture(CVOpenGLESTextureGetTarget(_cvTexture), CVOpenGLESTextureGetName(_cvTexture));don't be bad like me でバインドCVOpenGLESTextureGetTargetし、両方のパラメータに使用します。
  5. フレームごとにテクスチャを再作成しないでください。取得したポインタに画像データをコピーしCVPixelBufferGetBaseAddressてテクスチャを更新するだけです。
于 2012-09-01T03:13:50.253 に答える