5

Android の MediaProjection API には、いくつかの問題があります (実際にはもっと多くの問題がありますが、これらはより重大なものです)。グラフィックス アーキテクチャを読んでもあまり役に立たないので、コード フローで何かをスキップしたかどうかを理解しようとしています。

次のように仮定します。

  1. 専用の GL レンダリング スレッドがあり、初期化され、GL テクスチャが生成されています。テクスチャのデフォルトのバッファ サイズを WxH に設定しました。

  2. GL テクスチャを使用して SurfaceTexture を作成し、このサーフェス テクスチャの Surface を作成します。

  3. MediaProjection を介してサイズ WxH の仮想ディスプレイを作成し、そのサーフェスを上記のサーフェスに設定します。

問題 1: すべてが完全に機能する (完全なフレームが正しく表示される) か、そうでない (すべてのフレームが黒い、または各フレームの半分しか表示されない、たとえば、すべてのフレームで同じ半分が表示される、または画面の一部が他の部分に繰り返される)。一部、時には歪んでいることさえあります)。

問題 2: いくつかのフルスクリーン GL ゲームで時間が費やされている間、固定時間 (約 4 分) の後、すべての着信フレームがフリーズします (たとえば、「新しい」フレームを受け取りますが、実際には 1 つの同じ画像です)。 . glReadPixels でそれを読むと、結果が確認されます-問題は、実際の表示がそのフレームをはるかに超えていることです。強制的に「回復」させる唯一の方法は、ステータスバーまたはナビゲーションバーを表示することです。これにより、正しいフレームがすぐに送信され始めます。もちろん、さらに4分後、再び起こります...

問題 3: GL テクスチャに対して setDefaultBUfferSize() も呼び出した後、VirtualDisplay で resize() を呼び出すと、90% のケースで問題 #1 (黒/カット フレーム、他の画面領域のアーティファクト) が発生します。 )

同じスレッドで updateTextureImage -> GL texture draw の一連の呼び出しを使用しているため、通常の理解では、ハーフフルの GL バッファーなどから何らかの方法で読み取っているということは決して起こらないはずです...そうですか?

この問題は、VirtualDisplay を MediaCodec の表面に直接レンダリングすることでもテストしました (カスタム GL は関係ありません) - 同じ動作です。 update実際には、MediaCodec は固定サイズの作成済みサーフェスを持っているため、仮想ディスプレイのサイズを変更することしかできず、エンコーダのサーフェス サイズを変更できないため、バグを再現することはできません。したがって、これは実際にはバグではありません (ただし、このようにしても、それに応じて何らかの方法でサーフェスのサイズを変更する VirtualDisplay )。

仮想ディスプレイを閉じるときに何かが漏れている、または仮想ディスプレイの作成間で正しく初期化されていない、一貫性がないために何かが漏れているように感じます。作成したばかりの表面テクスチャを備えた真新しい仮想ディスプレイを使用した真新しい MediaProjection スクリーン キャプチャ許可により、最終的にハーフカット フレームしか得られず、ポーカー フェイスが大きくなる可能性があります。 ..

PS: これはすべて、Android 6.0.1 を搭載した Nexus 6 で発生しています。

4

1 に答える 1

1

私はあきらめて、新しいSurfaceTextureの新しいSurface を使用して、仮想ディスプレイをすべて一緒に再作成しました (ただし、GL テクスチャは保持しました)。これにより、ちらつきやハーフサイズのフレームがなくなります。また、以前に使用された SurfaceTexture の BufferQueue が放棄され、VirtualDisplay で release() を呼び出した後に 1 つまたは 2 つの onFrameAvailable コールバックを取得したという logcat 警告もいくつかありました (おそらく非同期であり、stop() コールバックを待つ必要がありますが、取得されます)。その時点で複雑すぎる)。

そして、これをすべて行った後でも、まだ非常に奇妙なことが起こります。キャプチャが MY APPLICATION のみをキャプチャする場合があります。ステータス バーを下にスワイプするか、ホームに移動すると、すべてが黒くなります (アプリがステータス バー ウィンドウの背後にある場合でも)。この後の唯一の解決策は、画面をオフ/オンにするか、カメラ/カメラ 2 プレビューを SurfaceTexture にレンダリングしてから、VirtualDisplay を再作成することです。テクスチャに関しては、舞台裏で何かが間違いなく間違っています。

VirtualDisplay.resize() が壊れているようで、同じことが既存の SurfaceTexture を使用して新しい仮想ディスプレイを作成する場合にも当てはまります。

于 2016-03-30T11:52:20.720 に答える