Android Camera2 превью иногда поворачивается на 90 градусов

Я работаю над некоторым приложением, используя Android Camera2 API. До сих пор я был в состоянии получить предварительный просмотр в TextureView, Приложение по умолчанию в ландшафтном режиме. При использовании эмулятора предварительный просмотр будет отображаться в обратном порядке. На моем физическом Nexus 5 предварительный просмотр обычно отображается правильно (альбомная, а не перевернутая), но иногда он поворачивается на 90 градусов, но растягивается до размеров экрана. Я думал, что это должно быть легко, и думал, что следующий код вернет необходимую информацию о текущей ориентации:

// display rotation
getActivity().getWindowManager().getDefaultDisplay().getRotation();
// sensor orientation
mManager.getCameraCharacteristics(mCameraId).get(CameraCharacteristics.SENSOR_ORIENTATION);

... Я был очень удивлен, когда увидел, что приведенный выше код всегда возвращается 1 для поворота дисплея и 90 для ориентации датчика, независимо от того, был ли предварительный просмотр повернут на 90 градусов или нет. (В эмуляторе ориентация датчика всегда равна 270, что имеет смысл, если я принимаю 90 как правильную ориентацию). Я также проверил ширину и высоту внутри onMeasure в AutoMeasureTextureView ( взятом из примера Android2 Camera2), который я использую для создания моего TextureView. Но тоже не повезло - ширина и высота сообщаются изнутри onMeasure всегда одинаковы независимо от вращения предварительного просмотра. Так что я не знаю, как решить эту проблему. Кто-нибудь есть идея, что может быть причиной случайных всплесков в моей ориентации предварительного просмотра?

[Редактировать] Деталь, которую я только что узнал: всякий раз, когда предварительный просмотр появляется повернутым onSurfaceTextureSizeChanged в TextureView.SurfaceTextureListener Кажется, не позвонили. В документации для onSurfaceTextureSizeChanged говорят, что этот метод вызывается всякий раз, когда SurfaceTextureРазмер буферов изменен. У меня есть метод createCameraPreviewSession (скопировано из примера Android2 Camera2), в котором я устанавливаю размер буфера по умолчанию для моей текстуры как

texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

Из моего вывода журнала я могу сказать, что onSurfaceTextureSizeChanged вызывается именно после этого - однако не всегда... (или установка размера буфера по умолчанию иногда молча завершается ошибкой?).

3 ответа

Я думаю, что могу ответить на свой собственный вопрос: я создавал свой фрагмент Camera2 по примеру Android2 Camera2. Тем не менее, я на самом деле не рассматривал метод configureTransform быть важным, так как, в отличие от примера кода, мое приложение все равно вынуждено работать в ландшафтном режиме. Оказалось, что это предположение было неверным. Так как имея configureTransform Реинтегрированный в мой код, я больше не испытывал икоты.

Обновление: Оригинальный пример на страницах документации Android, похоже, больше не существует. Я обновил ссылку, которая сейчас указывает на код на Github.

Я следил за всем textureView.setTransform(matrix) Метод, указанный выше, и это сработало. Тем не менее, я также смог вручную установить вращение, используя гораздо более простой textureView.setRotation(270) без необходимости создавать Matrix,

Я также сталкивался с подобной проблемой на устройстве Nexus. Ниже код работает для меня. Вызовите эту функцию перед открытием камеры. А также на Resume ().

private void transformImage (int width, int height) {

    if (textureView == null) {

        return;
    } else try {
        {
            Matrix matrix = new Matrix();
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            RectF textureRectF = new RectF(0, 0, width, height);
            RectF previewRectF = new RectF(0, 0, textureView.getHeight(), textureView.getWidth());
            float centerX = textureRectF.centerX();
            float centerY = textureRectF.centerY();
            if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
                previewRectF.offset(centerX - previewRectF.centerX(), centerY - previewRectF.centerY());
                matrix.setRectToRect(textureRectF, previewRectF, Matrix.ScaleToFit.FILL);
                float scale = Math.max((float) width / width, (float) height / width);
                matrix.postScale(scale, scale, centerX, centerY);
                matrix.postRotate(90 * (rotation - 2), centerX, centerY);
            }
            textureView.setTransform(matrix);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}
Другие вопросы по тегам