1

Media Projection API を使用した実装は問題なく動作します。しかし、キャプチャした画像をファイルに書き込もうとすると、フレームが失われることがよくあります。すべての io コードが別々のスレッドで実行されている場合でも。

キャプチャしたフレームに対してオンライン画像分析を行いたかったため、スクリーンレコードや同様のツールを使用できません。

ネイティブ コードから Android Media Projection メソッドを呼び出す方法はありますか? より良いパフォーマンスを得るには?

キャプチャ プロセス中に io 操作を呼び出さないようにしました。私たちは最後まですべてを記憶に留めました。しかし、30fps でフレームが欠落するという問題がまだ残っています。どうすればそれを避けることができますか?

        try {
            image = mImageReader.acquireLatestImage();
            if (image != null) {
                Image.Plane[] planes = image.getPlanes();
                ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * mWidth;
                String.valueOf(pixelStride) + " -- rowStride: " + String.valueOf(rowStride) + " rowPadding: " + String.valueOf(rowPadding));
                // create bitmap
                if(mBitmap==null || rowPadding != mRowPadding || pixelStride != mPixelStride) {
                    mRowPadding = rowPadding; mPixelStride = pixelStride;
                    mBitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
                }
                mBitmap.copyPixelsFromBuffer(buffer);
                Bitmap myBitmap = Bitmap.createScaledBitmap(mBitmap, (mWidth + rowPadding / pixelStride) / 16, mHeight / 16, false);

                ramStorage.add(myBitmap);
4

1 に答える 1

2

Bitmap で重要なことを行うすべてのコードはネイティブに実装されているため、既存のコードを JNI を使用するように変換しても違いはありません。メモリ帯域幅または CPU の制限 (各フレームのデータのコピーとスケーリングによる) に直面しているか、スケジューラが他のスレッドを実行させているためにリアルタイムの期限を逃していると思います。

最適なアプローチは、必要な品質レベルとアプリの機能によって異なります。一連の独立したフレームをキャプチャするのではなく、ビデオ ストリームとして記録すると、メモリと CPU の使用量が大幅に削減されます。30 fps で数 MB/秒しか書き込みを行わない場合は、RAM にデータを保持する方が実用的です。アプリが画面上のすべてのピクセルを頻繁に変更する場合、これはうまく機能しない可能性があります。分析コードは、マクロブロッキングとベクトル量子化エラーに耐えられる必要があります。

保存する前にビットマップをスケーリングしないことで、CPU と RAM をトレードオフできます。Bitmap を完全に回避し、独自の copy + scale 操作を実行して ImageReader のコンテンツを RAM ストレージに転送し、両方の操作を 1 回のパスで実行することもできます (ネイティブ コードで copy-scale 関数を記述します)。

于 2016-03-03T17:36:00.903 に答える