Надежный захват экрана с помощью Android Media Projection API

Наши реализации, использующие Media Projection API, работают нормально. Но мы часто теряем кадры, пытаясь записать отснятые изображения в файлы. Даже если весь io-код выполняется в отдельных потоках.

Мы хотели сделать некоторый онлайн-анализ изображений на захваченных кадрах, поэтому мы не можем использовать запись экрана или подобные инструменты.

Есть ли способ вызвать методы Android Media Projection из собственного кода? Для повышения производительности?

Мы даже старались не вызывать никаких операций ввода-вывода в процессе захвата. Мы сохранили все в памяти до конца. Но у нас все еще есть проблемы с пропущенными кадрами при 30 кадрах в секунду. Как мы можем этого избежать?

        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);

person user3387542    schedule 03.03.2016    source источник
comment
Старайтесь всегда повторно использовать растровые изображения вместо их повторного создания. Кроме того, вы можете дать ImageReader больше кадров (последний параметр в методе конструктора)   -  person Simon Marquis    schedule 05.03.2016


Ответы (1)


Весь код, который делает что-то важное с Bitmap, реализован изначально, поэтому преобразование вашего существующего кода для использования JNI не будет иметь значения. Я предполагаю, что вы сталкиваетесь с пропускной способностью памяти или ограничениями ЦП (из-за копирования и масштабирования данных для каждого кадра) или просто пропускаете крайние сроки в реальном времени, потому что планировщик разрешает выполнение какого-то другого потока.

Лучший подход зависит от требуемого уровня качества и того, что делает приложение. Если вы записываете как видеопоток, а не серию независимых кадров, вы будете использовать гораздо меньше памяти и процессора. Хранение данных в ОЗУ более практично, когда вы записываете всего несколько МБ/с со скоростью 30 кадров в секунду. Это может не сработать, если ваше приложение часто меняет каждый пиксель на экране. Ваш код анализа должен быть терпим к ошибкам макроблокировки и векторного квантования.

Вы можете обменять ЦП на ОЗУ, не масштабируя растровое изображение перед его сохранением. Вы также можете полностью отказаться от Bitmap и выполнить свою собственную операцию копирования + масштабирования для передачи содержимого ImageReader в хранилище RAM, выполняя обе операции за один проход (вы хотите написать функцию масштабирования копирования в собственном коде).

person fadden    schedule 03.03.2016