2017-03-13 6 views
2

私はMediaCodecを使ってカメラからフレームを符号化することに関して、特にグラフィックスメモリの使用量/ Androidの中の流れとを理解しようとしています。これを行うために、私には不明瞭なグラフィックス、OpenGL、Androidの用語/コンセプトを理解する必要があります。私はAndroidのグラフィックアーキテクチャの資料、SOの質問の束、およびソースの束を読んだが、主に用語が異なる文脈で異なる意味を持つように見えるので、私はまだ混乱している。理解AndroidのカメラSurfaceTextureとMediaCodec表面の使用

私はfaddenのサイトhereからCameraToMpegTestを見てきました。私の具体的な質問は、Camera::setPreviewTexture()と一緒にMediaCodec::createInputSurface()がどのように動作するかです。 OpenGLテクスチャが作成された後、これを使用してSurfaceTextureというAndroidを作成し、setPreviewTexture()に渡すことができます。私の具体的な質問:

  1. setPreviewTexture()は、フレームがカメラからどのメモリバッファに移動するのか実際に何をしていますか?私の理解から
  2. OpenGLのテクスチャは、GPUによってアクセス可能なメモリの塊です。 Androidでは、正しい使用フラグを付けてgrallocを使用して割り当てる必要があります。 SurfaceTextureのAndroidの説明には、「与えられたOpenGLテクスチャに画像をストリーミングする」ことができると言われています:https://developer.android.com/reference/android/graphics/SurfaceTexture.html#SurfaceTexture(int)SurfaceTextureはOpenGLテクスチャの上で何をしますか?
  3. MediaCodec::createInputSurface()は、Android Surfaceを返します。私が理解しているように、Android Surfaceはバッファキューのプロデューサ側を表しているため、複数のバッファである可能性があります。 API referenceには、「サーフェスはOpenGL ESなどのハードウェアアクセラレーションAPIでレンダリングする必要があります」と記載されています。カメラでキャプチャしたフレームは、SurfaceTextureからエンコーダに入力されたSurfaceにどのように取得されますか?私はCameraToMpegTestは何とかこのSurfaceを使用しますが、私はこの部分を得ることはありませんEGLについて多くを知らないEGLSurfaceを作成します参照してください。
  4. 「レンダリング」の使用法を明確にすることはできますか?私は、「表面にレンダリング」、「画面にレンダリング」など、さまざまなことを意味するような用途を見ています。

編集:私がしようとすると、より良いCamera::setPreviewTexture()の内部の仕組みを理解し、いくつかのより多くの質問を持っているいくつかのより多くの​​にSurfaceTextureCameraClient::setPreviewTarget()ためのコードの中に掘ら

  1. :mstorsjoさんへのフォローアップ。 SurfaceTextureのようにそれはそうメモリ割り当てを理解する私の元の質問にBufferQueueを作成し、​​は、プラットフォームのカメラHALの実装に関連するIGraphicBufferProducerを渡します。カメラHALはgralloc使用フラグを適切に設定し(例えば、GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_TEXTURE)、BufferQueueからバッファをデキューできます。そのため、カメラがフレームをキャプチャするバッファには、grockocに割り当てられたバッファに、特別な使用フラグ(GRALLOC_USAGE_HW_TEXTUREなど)が割り当てられています。 GPUとCPUが同じメモリにアクセスできるように、統合されたメモリアーキテクチャを備えたARMプラットフォーム上で作業するので、バッファがどのように割り振られているかについてGRALLOC_USAGE_HW_TEXTUREフラグがどのような影響を与えますか?
  2. SurfaceTextureのOpenGL(ES)部分は、主にGLConsumerの一部として実装されており、魔法はupdateTexImage()にあるようです。 OpenGL(ES)テクスチャ用に追加のバッファが割り当てられているか、または使用可能なカメラでいっぱいになっている同じgrallocバッファがありますか? grallocバッファからOpenGL(ES)テクスチャにカメラピクセルデータを取得するためにここで行われなければならないメモリコピーがありますか?私はupdateTexImage()が何を呼び出すのか分かりません。

答えて

3
  1. これは、カメラが不透明ハンドルを介して代わりに(setPreviewCallback又はsetPreviewCallbackWithBufferを使用している場合)、アプリケーションのアドレス空間内のユーザー提供バッファに出力フレームを提供することを意味します。この不透明なハンドル、テクスチャは、OpenGL図面内で使用できます。

  2. ほぼ。この場合、OpenGLテクスチャは物理的なメモリチャンクではなく、EGLコンテキスト内の可変容量のメモリチャンクに対するハンドルです。この場合、サンプルコード自体は実際にテクスチャを割り当てたりサイズを変更したりせず、glGenTexturesを使用してテクスチャの「名前」/ハンドルを作成するだけです。基本的に整数です。通常のOpenGL(ES)内では、OpenGL関数を使用して、テクスチャの実際のストレージを割り当て、コンテンツに埋め込みます。この設定では、SurfaceTextureは、テクスチャにデータを設定するためのAndroidレベルのAPI /抽象化を提供します(つまり、適切なフラグでストレージを割り当て、サイズとコンテンツを提供します)。SurfaceTextureを満たすことができる他のクラスに渡すことができますそのデータにはCameraがあり、SurfaceTextureが直接か、またはSurfaceクラスで囲み、他のコンテキストで使用することができます。これにより、OpenGLテクスチャをコンテンツに効率的に埋め込むことができます。生データのバッファをアプリケーションのプロセスに渡したり、アプリケーションがOpenGLにアップロードしたりする必要はありません。

  3. (回答ポイント3と4の逆順)OpenGL(ES)は描画用の汎用APIです。通常の/オリジナルの設定では、ゲームを考えてください。ゲームのさまざまな部分(背景、小道具、俳優など)にテクスチャを付けてから、OpenGL APIを使って画面に描画します。テクスチャは、スクリーンにそのままコピーされるか、または三角形から構築された3Dオブジェクトの周りを包むことができます。これは、「レンダリング」と呼ばれるプロセスで、入力テクスチャと三角形のセットを取得し、描画します。最も単純な場合は、コンテンツを画面に直接表示します。 GPUは通常、他の出力バッファにも同じレンダリングを実行できます。ゲームでは、あるシーンをテクスチャにレンダリングし、そのレンダリングされたテクスチャを実際に画面に表示される最終レンダリングの一部として使用するのが一般的です。

  4. カメラからの出力をエンコーダ入力に渡すためのEGLコンテキストが作成されます。 EGLコンテキストは、基本的にOpenGLレンダリングを行うためのコンテキストです。レンダリングのターゲットは、エンコーダからのサーフェスです。つまり、OpenGLを使用して描画されたグラフィックは、画面ではなくエンコーダの入力バッファになります。 OpenGLを使用して描画されるシーンは、OpenGL関数呼び出しの任意のシーケンスであり、ゲームシーンをエンコーダにレンダリングすることができます。これは、Androidブレークアウトゲームレコーダの例です。コンテキスト内で、テクスチャハンドルが作成されます。通常のゲームグラフィックスレンダリングのように、ピクチャをディスクからロードしてコンテンツにテクスチャを塗りつぶすのではなく、にしてCameraにカメラの画像を塗りつぶすことができます。 SurfaceTextureクラスは、Cameraがコンテンツを更新したときにシグナルを返すコールバックを提供します。このコールバックが受信されると、EGLコンテキストがアクティブになり、1つのフレームがEGLコンテキスト出力ターゲット(エンコーダ入力)にレンダリングされます。レンダリング自体は何の工夫もしていませんが、入力テクスチャをそのまま出力にそのままコピーします。

これはすべてのかなり遠回りに聞こえるかもしれないが、それはいくつかの利点を与える行います

  • カメラフレームの実際の生のビットは、潜在的に決してアプリケーション・コード内で直接処理する必要はありません(と決してアプリケーションのプロセスとアドレス空間内で)低解像度の場合、これは大きな問題ではありませんが、高解像度の場合はAPIがsetPreviewCallbackのボトルネックになります。
  • OpenGLでは、色の調整やGPUアクセラレーションのほとんどを無料で行うことができます。
+0

あなたの答えに基づいて元の質問にいくつかのフォローアップを追加しました。 –

+0

私はこれらの追加の質問にはほとんどコメントすることができません。最初の質問は、公開APIの観点から(私が知っている)公開APIの観点からであり、後者の質問はプラットフォームの実装方法と詳細のみですプラットフォームの実装者に関連しています。 – mstorsjo

+1

私は、消費者(GLコンテキスト)が前のフレームのレンダリングを続けることができるように、プロデューサ(カメラ)が1つのフレームを書き込むことができるように、SurfaceTextureが実際に複数のバッファのセットであることを期待します。 'updateTexImage()'では、私はこれらのバッファを交換することを期待しています。それはユーザーの視点からの私の印象と仮定ですが、実際の実装はわかりません。 – mstorsjo

関連する問題