Используйте rotateM() Matrix, чтобы повернуть матрицу из SurfaceTexture, но испортить вывод видео

Мне удалось воспроизвести видео с помощью OpenGLES, я использовал способ ContinuousCaptureActivity от Grafika, мой источник данных - MediaPlayer, а не Camera, что не имеет значения. MediaPlayer непрерывно создает видеокадры, и я рисую каждый кадр на экране в обратном вызове onFrameAvailable. Код выглядит следующим образом:

    mVideoTexture.updateTexImage();
    mVideoTexture.getTransformMatrix(mTmpMatrix);
    mDisplaySurface.makeCurrent();
    int viewWidth = getWidth();
    int viewHeight = getHeight();
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
    mFullFrameBlit.drawFrame(mTextureId, mTmpMatrix);
    mDisplaySurface.swapBuffers();

Теперь я хочу повернуть видеокадры на 270 градусов, поэтому я изменил код:

        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    mVideoTexture.updateTexImage();
    mVideoTexture.getTransformMatrix(mTmpMatrix);
    mDisplaySurface.makeCurrent();
    int viewWidth = getWidth();
    int viewHeight = getHeight();
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
    Matrix.rotateM(mTmpMatrix, 0, 270, 1f, 0, 0);
    mFullFrameBlit.drawFrame(mTextureId, mTmpMatrix);
    mDisplaySurface.swapBuffers();

Но результат странный, взгляните на картинку ниже:

Но я могу успешно перевернуть видеокадр с кодом ниже:

        mVideoTexture.updateTexImage();
    mVideoTexture.getTransformMatrix(mTmpMatrix);
    mDisplaySurface.makeCurrent();
    int viewWidth = getWidth();
    int viewHeight = getHeight();
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
    mTmpMatrix[5] = -1 * mTmpMatrix[5];
    mTmpMatrix[13] = 1.0f - mTmpMatrix[13];
    mFullFrameBlit.drawFrame(mTextureId, mTmpMatrix);
    mDisplaySurface.swapBuffers();

Как добиться вращения, кто-нибудь может мне помочь?

ДОБАВЛЯТЬ:

Во-первых, я хочу сказать, что я всегда использовал этот код для каждого действия рисования:

        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

Я использую эту демонстрацию, чтобы сделать мой тест, это очень хорошая демонстрация для этого теста. https://github.com/izacus/AndroidOpenGLVideoDemo

Матрица, полученная из поверхностной текстуры, имеет вид:

1,0, 0,0, 0,0, 0,0

0,0, -1,0, 0,0, 0,0

0,0, 0,0, 1,0, 0,0

0,0, 1,0, 0,0, 1,0

После "Matrix.setRotateM(videoTextureTransform, 0, 270, 0, 0, 1);",

стало:

1,1924881E-8, -1,0, 0,0, 0,0

1,0, 1,1924881E-8, 0,0, 0,0

0,0, 0,0, 1,0, 0,0

0,0, 0,0, 0,0, 1,0

И этот видео эффект:

2 ответа

Решение

За матрицей вращения Фаддена вокруг оси z должен следовать правильный перевод, чтобы, так сказать, вернуть его на экран. Я проверил все 3 поворота ниже на видео SurfaceTexture:

ПОВЕРНУТЬ 90

Matrix.rotateM(mTmpMatrix, 0, 90, 0, 0, 1);
Matrix.translateM(mTmpMatrix, 0, 0, -1, 0);

ПОВЕРНУТЬ 180

Matrix.rotateM(mTmpMatrix, 0, 180, 0, 0, 1);
Matrix.translateM(mTmpMatrix, 0, -1, -1, 0);

ПОВЕРНУТЬ 270

Matrix.rotateM(mTmpMatrix, 0, 270, 0, 0, 1);
Matrix.translateM(mTmpMatrix, 0, -1, 0, 0);

Вы вращаетесь вокруг оси X:

Matrix.rotateM(mTmpMatrix, 0, 270, 1f, 0, 0);

По соглашению, который идет слева направо. Ось действует как ось; переворачивая его на 270 градусов, вы поворачиваете плоскость так, что смотрите на нее с края, и она фактически исчезает. Я думаю, что вы видите по сути неинициализированные данные, и если вы позвоните glClear() вместо этого вы увидите цвет фона.

Попробуйте повернуть вокруг оси Z, которая является линией, указывающей на экран:

Matrix.rotateM(mTmpMatrix, 0, 270, 0, 0, 1);

(Также было бы интересно поэкспериментировать с поворотом на 15 градусов вокруг оси X, просто чтобы посмотреть, как это выглядит. При работе с матрицами часто полезно начинать с небольших значений.)

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