Modificando a saída da câmera usando SurfaceTexture e OpenGL

Eu estou tentando filtrar o fluxo proveniente do hardware da câmera, executando-o através de um filtro openGL e, em seguida, exibi-lo em um GLSurfaceView. Quando o OpenGL vai renderizar o quadro, o LogCat envia repetidamente um erro:

[unnamed-3314-0] updateTexImage: limpando o erro GL: 0x502

0x502 é um erro genérico de openGL e realmente não me ajuda a rastrear o problema. Esta é uma sequência de como o código funciona (ou pelo menos deveria estar funcionando como visto na minha cabeça), e eu copiei meu código abaixo disso. Espero que alguém possa ver qual é o meu problema.

Crie um novo MyGLSurfaceView. Isso cria internamente o novo objeto MyGL20Renderer também. Este MyGLSurfaceView é definido como a exibição de conteúdo.Uma vez que o MyGLSurfaceView é feito insuflando / inicializando, este evento de conclusão aciona o renderizador para criar um objeto de desenho DirectVideo, que compila / liga os shaders definidos e os adiciona a um programa openGL. Em seguida, ele cria um novo objeto de textura openGL e, em seguida, retorna a MainActivity com o ID do objeto de textura.Quando o método MainActivity é chamado a partir do renderizador, ele cria um novo objeto SurfaceTexture usando o objeto de textura openGL transmitido. Em seguida, ele se define como o onFrameListener da superfície. Em seguida, ele cria / abre o objeto da câmera, define o SurfaceTexture criado como o destino do fluxo de vídeo e inicia o feed da câmera.Quando um quadro está disponível no feed, o onFrameAvailable envia uma solicitação de renderização ao renderizador. Isso é capturado no thread openGL, que chama o updateTexImage () do SurfaceTexture, que carrega a memória do frame na textura do openGL. Em seguida, chama o objeto de desenho do DirectVideo e a sequência do programa openGL é executada.Se eu comentar esta linha .draw (), o erro mencionado acima desaparece, então parece provável que o problema esteja em algum lugar aqui dentro, mas não estou descartando que isso seja causado por uma textura indevidamente vinculada / criada.

MainActivity.java

public class MainActivity extends Activity implements SurfaceTexture.OnFrameAvailableListener
{
    private Camera mCamera;
    private MyGLSurfaceView glSurfaceView;
    private SurfaceTexture surface;
    MyGL20Renderer renderer;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        glSurfaceView = new MyGLSurfaceView(this);
        renderer = glSurfaceView.getRenderer();
        setContentView(glSurfaceView);
    }

    public void startCamera(int texture)
    {
        surface = new SurfaceTexture(texture);
        surface.setOnFrameAvailableListener(this);
        renderer.setSurface(surface);

        mCamera = Camera.open();

        try
        {
            mCamera.setPreviewTexture(surface);
            mCamera.startPreview();
        }
        catch (IOException ioe)
        {
            Log.w("MainActivity","CAM LAUNCH FAILED");
        }
    }

    public void onFrameAvailable(SurfaceTexture surfaceTexture)
    {
        glSurfaceView.requestRender();
    }

    @Override
    public void onPause()
    {
        mCamera.stopPreview();
        mCamera.release();
        System.exit(0);
    }

MyGLSurfaceView.java

class MyGLSurfaceView extends GLSurfaceView
{
    MyGL20Renderer renderer;
    public MyGLSurfaceView(Context context)
    {
        super(context);

        setEGLContextClientVersion(2);

        renderer = new MyGL20Renderer((MainActivity)context);
        setRenderer(renderer);
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    }
    public MyGL20Renderer getRenderer()
    {
        return renderer;
    }
}

MyGL20Renderer.java

public class MyGL20Renderer implements GLSurfaceView.Renderer
{

    DirectVideo mDirectVideo;
    int texture;
    private SurfaceTexture surface;
    MainActivity delegate;

    public MyGL20Renderer(MainActivity _delegate)
    {
        delegate = _delegate;
    }

    public void onSurfaceCreated(GL10 unused, EGLConfig config)
    {
        mDirectVideo = new DirectVideo(texture);
        texture = createTexture();
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        delegate.startCamera(texture);
    }

    public void onDrawFrame(GL10 unused)
    {
            float[] mtx = new float[16];
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            surface.updateTexImage();
            surface.getTransformMatrix(mtx); 

            mDirectVideo.draw();
    }

    public void onSurfaceChanged(GL10 unused, int width, int height)
    {
        GLES20.glViewport(0, 0, width, height);
    }

    static public int loadShader(int type, String shaderCode)
    {
        int shader = GLES20.glCreateShader(type);

        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;
    }

    static private int createTexture()
    {
        int[] texture = new int[1];

        GLES20.glGenTextures(1,texture, 0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);        
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

        return texture[0];
    }

    public void setSurface(SurfaceTexture _surface)
    {
        surface = _surface;
    }
}

DirectVideo.java

public class DirectVideo {


    private final String vertexShaderCode =
            "#extension GL_OES_EGL_image_external : require\n"+
            "attribute vec4 position;" +
            "attribute vec4 inputTextureCoordinate;" +
            "varying vec2 textureCoordinate;" +
            "void main()" +
            "{"+
                "gl_Position = position;"+
                "textureCoordinate = inputTextureCoordinate.xy;" +
            "}";

        private final String fragmentShaderCode =
            "#extension GL_OES_EGL_image_external : require\n"+
            "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}";

        private FloatBuffer vertexBuffer, textureVerticesBuffer;
        private ShortBuffer drawListBuffer;
         private final int mProgram;
            private int mPositionHandle;
            private int mColorHandle;
            private int mTextureCoordHandle;


    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 2;
    static float squareVertices[] = { // in counterclockwise order:
         -1.0f,  1.0f,
         -1.0f,  -1.0f,
         1.0f,  -1.0f,
         1.0f,  1.0f
    };

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

    static float textureVertices[] = { // in counterclockwise order:
        1.0f,  1.0f,
        1.0f,  0.0f,
        0.0f,  1.0f,
        0.0f,  0.0f
   };

    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private int texture;

    public DirectVideo(int _texture)
    {
        texture = _texture;

        ByteBuffer bb = ByteBuffer.allocateDirect(squareVertices.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareVertices);
        vertexBuffer.position(0);

        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        ByteBuffer bb2 = ByteBuffer.allocateDirect(textureVertices.length * 4);
        bb2.order(ByteOrder.nativeOrder());
        textureVerticesBuffer = bb2.asFloatBuffer();
        textureVerticesBuffer.put(textureVertices);
        textureVerticesBuffer.position(0);

        int vertexShader = MyGL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = MyGL20Renderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        mProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        GLES20.glLinkProgram(mProgram);          
    }

    public void draw()
    {
        GLES20.glUseProgram(mProgram);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture);

        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,vertexStride, vertexBuffer);

        mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
        GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
        GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,vertexStride, textureVerticesBuffer);

        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
        GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
    }
}

questionAnswers(1)

yourAnswerToTheQuestion