Android GL ES + EGL рендеринг с 2 камер - PullRequest
0 голосов
/ 07 февраля 2020

В настоящее время мы работаем над приложением, которое должно захватывать видео с двух камер (мы используем устаревший API камер, поскольку наше устройство имеет только HAL1), визуализировать оба с использованием OpenGL и сохранять результаты в основной памяти как ByteBuffers. Поток с одной из камер также отображается на дисплее с помощью пользовательского представления.

Наше устройство поддерживает одновременную работу 2 камер, и у нас не было проблем с созданием двух отдельных представлений, но у меня возникли проблемы при объединении всего в одном виде.

У меня есть поверхность EGL windows (на основе этой библиотеки ), используемая для рисования с первой камеры, настроенная так:

public void initEgl(Surface surface, EGLContext eglContext) {   
    mEgl = (EGL10) EGLContext.getEGL();

    mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
        throw new RuntimeException("eglGetDisplay failed");
    }

    int[] version = new int[2];
    if (!mEgl.eglInitialize(mEglDisplay, version)) {
        throw new RuntimeException("eglInitialize failed");
    }

    int[] attrib_list = new int[]{
                EGL10.EGL_RED_SIZE, mRedSize,
                EGL10.EGL_GREEN_SIZE, mGreenSize,
                EGL10.EGL_BLUE_SIZE, mBlueSize,
                EGL10.EGL_ALPHA_SIZE, mAlphaSize,
                EGL10.EGL_DEPTH_SIZE, mDepthSize,
                EGL10.EGL_STENCIL_SIZE, mStencilSize,
                EGL10.EGL_RENDERABLE_TYPE, 4,//egl版本  2.0
                EGL10.EGL_NONE};

    int[] num_config = new int[1];
    if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, null, 1,
            num_config)) {
        throw new IllegalArgumentException("eglChooseConfig failed");
    }
    int numConfigs = num_config[0];
    if (numConfigs <= 0) {
        throw new IllegalArgumentException(
                "No configs match configSpec");
    }

    EGLConfig[] configs = new EGLConfig[numConfigs];
    if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, configs, numConfigs,
            num_config)) {
        throw new IllegalArgumentException("eglChooseConfig#2 failed");
    }
    EGLConfig eglConfig = chooseConfig(mEgl, mEglDisplay, configs);
    if (eglConfig == null) {
        eglConfig = configs[0];
    }


    int[] contextAttr = new int[]{
            EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
            EGL10.EGL_NONE
    };

    if (eglContext == null) {
        mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, contextAttr);
    } else {
        mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, eglContext, contextAttr);
    }


    mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfig, surface, null);

    if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
        throw new RuntimeException("eglMakeCurrent fail");
    }
}

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

int[] attrib_list = new int[]{
        EGL10.EGL_RED_SIZE, mRedSize,
        EGL10.EGL_GREEN_SIZE, mGreenSize,
        EGL10.EGL_BLUE_SIZE, mBlueSize,
        EGL10.EGL_ALPHA_SIZE, mAlphaSize,
        EGL10.EGL_DEPTH_SIZE, mDepthSize,
        EGL10.EGL_STENCIL_SIZE, mStencilSize,
        EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
        EGL10.EGL_RENDERABLE_TYPE, 4,//egl版本  2.0
        EGL10.EGL_NONE};

int[] pbufferAttr = new int[] {
                    EGL10.EGL_WIDTH, 1280,
                    EGL10.EGL_HEIGHT, 1280,
                    EGL10.EGL_NONE
            };
mEglSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, eglConfig, pbufferAttr);

Практически все остальное то же самое. Однако, используя его, я получаю следующие ошибки:

E/IMGSRV: :0: IsTextureConsistent: IMGEGLImage is not consistent

E/IMGSRV: :0: GrallocGetBufferParams: Failed to lookup buffer (ID=38061)

W/GLConsumer: [SurfaceTexture-2-4584-1] bindTextureImage: clearing GL error: 0x500

Нет, я понимаю, что OpenGL является поточно-ориентированным, поскольку один контекст является текущим и используется только в одном потоке (что имеет место здесь, так как два контекста EGL имеют разные поверхности и представляют циклы рендеринга в отдельных потоках), поэтому я предполагаю, что фундаментальная установка, подобная этой, не должна возникать.

В чем может быть проблема?

...