2012-08-26 27 views
8

Tengo un problema con la conversión de la vista previa de la cámara en Android del formato YUV a RGB. El propósito de la conversión es aplicar algunos efectos. Intento convertir por shader de fragmento porque la conversión por código nativo es lenta (alrededor de 14 fps). La referencia que he usado es http://jyrom.tistory.com/m/post/view/id/187. Intento llevar este código a la plataforma de Android, pero el resultado es un rectángulo negro-verde. Pero, puedo ver alguna forma a través de la salida que obtengo. Podría intentar ayudarme a resolver este problema. Creo que este es un problema popular: aplicar efectos a la vista previa de la cámara. También doy un enlace a mi proyecto para probar: https://dl.dropbox.com/u/12829395/application/FilterGL/FilterGL.zip. Gracias.
Actualizado:
Este es mi onPreviewFrame método: Conversión de YUV a RGB por fragment shader

public void onPreviewFrame(byte[] data, Camera camera) { 
    yBuffer.put(data); 
    yBuffer.position(0); 

    System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4 * 2); 
    uBuffer.put(uData); 
    uBuffer.position(0); 

    System.arraycopy(data, V_INDEX, vData, 0, LENGTH_4); 
    vBuffer.put(vData); 
    vBuffer.position(0); 
} 

Así es como me ato las matrices de bytes a OpenGL textura en onDrawFrame método:

GLES20.glUniform1i(yTexture, 1); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      320, 240, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, yBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 

    GLES20.glUniform1i(uTexture, 2); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, uBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 

    GLES20.glUniform1i(vTexture, 3); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, vBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 

Y esto es mi código de sombreador de fragmentos:

#ifdef GL_ES 
precision highp float; 
#endif 

varying vec2 v_texCoord; 
uniform sampler2D y_texture; 
uniform sampler2D u_texture; 
uniform sampler2D v_texture; 

void main() 
{ 
    float nx,ny,r,g,b,y,u,v; 
    nx=v_texCoord.x; 
    ny=v_texCoord.y; 
    y=texture2D(y_texture,v_texCoord).r; 
    u=texture2D(u_texture,v_texCoord).r; 
    v=texture2D(v_texture,v_texCoord).r; 

    y=1.1643*(y-0.0625); 
    u=u-0.5; 
    v=v-0.5; 

    r=y+1.5958*v; 
    g=y-0.39173*u-0.81290*v; 
    b=y+2.017*u; 

    gl_FragColor = vec4(r,g,b,1.0); 
} 

Respuesta

3

No estoy seguro de si ya ha solucionado este problem.My respuesta

  1. Por salida de la cámara por defecto es NV12, pero en el fragmento shader YUV a RGB está utilizando YV12 -> RGB. Usted tendrá que hacer setPreviewFormat(ImageFormat.YV12);, o puede ser el uso de sombreado de alguna otra
  2. Hay 3 texturas, asegúrese de hacer

    GLES20.glActiveTexture(GLES20.GL_TEXTURE2); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, muTextureName)

    antes de llamar a cualquier glTexImage2D. y glTexSubImage2D

  3. También puede usar glTexSubImage2D con cada fotograma y glTexImage2D una vez.

  4. tamaño de U y V es el mismo, al menos para YV12,

    System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4 * 2);

    debería ser System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4); cambio el tamaño en consecuencia en el código.

1

Finalmente, su proyecto muestra las vistas previas de la cámara. Encontré 2 problemas: 1. Antes de enlazar y cambiar las características de la superficie, debe llamar a GLES20.glActiveTexture (GLES20.surfacenumber); 2. El problema más importante y oculto es que GLES20.glTexImage2D() no funciona con ancho y alto, que no son potencia de 2 números. Después de cargar la textura con el tamaño, por ejemplo, 1024X1024, debe llamar a GLES20.glTexSubImage2D()

¡Buena suerte!

2

No sé si ha resuelto su problema.

Utilicé su código y lo resolví en este modo.

public class MyRenderer implements Renderer{ 
public static final int recWidth = Costanti.recWidth; 
public static final int recHeight = Costanti.recHeight; 

private static final int U_INDEX = recWidth*recHeight; 
private static final int V_INDEX = recWidth*recHeight*5/4; 
private static final int LENGTH = recWidth*recHeight; 
private static final int LENGTH_4 = recWidth*recHeight/4; 

private int previewFrameWidth = 256; 
private int previewFrameHeight = 256; 

private int[] yTextureNames; 
private int[] uTextureNames; 
private int[] vTextureNames; 

private MainActivity activity; 

private FloatBuffer mVertices; 
private ShortBuffer mIndices; 

private int mProgramObject; 
private int mPositionLoc; 
private int mTexCoordLoc; 

private int yTexture; 
private int uTexture; 
private int vTexture; 

private final float[] mVerticesData = { -1.f, 1.f, 0.0f, // Position 0 
     0.0f, 0.0f, // TexCoord 0 
     -1.f, -1.f, 0.0f, // Position 1 
     0.0f, 1.0f, // TexCoord 1 
     1.f, -1.f, 0.0f, // Position 2 
     1.0f, 1.0f, // TexCoord 2 
     1.f, 1.f, 0.0f, // Position 3 
     1.0f, 0.0f // TexCoord 3 
}; 
private final short[] mIndicesData = { 0, 1, 2, 0, 2, 3 }; 

private ByteBuffer yBuffer; 
private ByteBuffer uBuffer; 
private ByteBuffer vBuffer; 

private IntBuffer frameBuffer; 
private IntBuffer renderBuffer; 
private IntBuffer parameterBufferWidth; 
private IntBuffer parameterBufferHeigth; 

byte[] ydata = new byte[LENGTH]; 
byte[] uData = new byte[LENGTH_4]; 
byte[] vData = new byte[LENGTH_4]; 

public MyRenderer(MainActivity activity) { 
    this.activity = activity; 

    mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4) 
      .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    mVertices.put(mVerticesData).position(0); 

    mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2) 
      .order(ByteOrder.nativeOrder()).asShortBuffer(); 
    mIndices.put(mIndicesData).position(0); 

    yBuffer = MyGraphUtils.makeByteBuffer(LENGTH); 
    uBuffer = MyGraphUtils.makeByteBuffer(LENGTH_4/* * 2*/); 
    vBuffer = MyGraphUtils.makeByteBuffer(LENGTH_4); 
} 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 
    GLES20.glActiveTexture(GLES20.GL_ACTIVE_TEXTURE); 
    GLES20.glViewport(0, 0, width, height); 
} 

@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
    Log.d("debug", "on surface created"); 
    // Define a simple shader program for our point. 
    final String vShaderStr = readTextFileFromRawResource(activity, R.raw.v_simple); 
    final String fShaderStr = readTextFileFromRawResource(activity, R.raw.f_convert); 
    frameBuffer = IntBuffer.allocate(1); 
    renderBuffer= IntBuffer.allocate(1); 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 

    GLES20.glGenFramebuffers(1, frameBuffer); 
    GLES20.glGenRenderbuffers(1, renderBuffer); 
    GLES20.glActiveTexture(GLES20.GL_ACTIVE_TEXTURE); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer.get(0)); 
    GLES20.glClear(0); 
    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBuffer.get(0));  

    GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, 
           320, 240); 

    parameterBufferHeigth = IntBuffer.allocate(1); 
    parameterBufferWidth = IntBuffer.allocate(1); 
    GLES20.glGetRenderbufferParameteriv(GLES20.GL_RENDERBUFFER, GLES20.GL_RENDERBUFFER_WIDTH, parameterBufferWidth); 
    GLES20.glGetRenderbufferParameteriv(GLES20.GL_RENDERBUFFER, GLES20.GL_RENDERBUFFER_HEIGHT, parameterBufferHeigth); 
    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER, renderBuffer.get(0)); 
    if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)!=GLES20.GL_FRAMEBUFFER_COMPLETE){ 
     Log.d("debug", "gl frame buffer status != frame buffer complete"); 
    } 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    GLES20.glClear(0); 

    mProgramObject = loadProgram(vShaderStr, fShaderStr); 

    // Get the attribute locations 
    mPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_position"); 
    mTexCoordLoc = GLES20.glGetAttribLocation(mProgramObject, "a_texCoord"); 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
    yTexture = GLES20.glGetUniformLocation(mProgramObject, "y_texture"); 
    yTextureNames = new int[1]; 
    GLES20.glGenTextures(1, yTextureNames, 0); 
    int yTextureName = yTextureNames[0]; 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
    uTexture = GLES20.glGetUniformLocation(mProgramObject, "u_texture"); 
    uTextureNames = new int[1]; 
    GLES20.glGenTextures(1, uTextureNames, 0); 
    int uTextureName = uTextureNames[0]; 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
    vTexture = GLES20.glGetUniformLocation(mProgramObject, "v_texture"); 
    vTextureNames = new int[1]; 
    GLES20.glGenTextures(1, vTextureNames, 0); 
    int vTextureName = vTextureNames[0]; 

    GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); 
} 

@Override 
public final void onDrawFrame(GL10 gl) { 
    Log.d("debug", "on Draw frame"); 
    // Clear the color buffer 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    // Use the program object 
    GLES20.glUseProgram(mProgramObject); 

    // Load the vertex position 
    mVertices.position(0); 
    GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 5*4, mVertices); 
    // Load the texture coordinate 
    mVertices.position(3); 
    GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 5*4, mVertices); 

    GLES20.glEnableVertexAttribArray(mPositionLoc); 
    GLES20.glEnableVertexAttribArray(mTexCoordLoc); 

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTextureNames[0]); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      320, 240, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, yBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTextureNames[0]); 
    GLES20.glUniform1i(yTexture, 0); 

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTextureNames[0]); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, uBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE1+2); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTextureNames[0]); 
    GLES20.glUniform1i(uTexture, 2); 

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, vTextureNames[0]); 
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
      160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, vBuffer); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE1+1); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, vTextureNames[0]); 
    GLES20.glUniform1i(vTexture, 1); 

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mIndices); 
} 



public void setPreviewFrameSize(int realWidth, int realHeight) { 
    previewFrameHeight = realHeight; 
    previewFrameWidth = realWidth; 
} 

public static String readTextFileFromRawResource(final Context context, final int resourceId) { 
    final InputStream inputStream = context.getResources().openRawResource(resourceId); 
    final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 
    final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

    String nextLine; 
    final StringBuilder body = new StringBuilder(); 

    try { 
     while ((nextLine = bufferedReader.readLine()) != null) { 
      body.append(nextLine); 
      body.append('\n'); 
     } 
    } catch (IOException e) { 
     return null; 
    } 

    return body.toString(); 
} 

public static int loadShader(int type, String shaderSrc) { 
    int shader; 
    int[] compiled = new int[1]; 

    // Create the shader object 
    shader = GLES20.glCreateShader(type); 
    if (shader == 0) { 
     return 0; 
    } 
    // Load the shader source 
    GLES20.glShaderSource(shader, shaderSrc); 
    // Compile the shader 
    GLES20.glCompileShader(shader); 
    // Check the compile status 
    GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 

    if (compiled[0] == 0) { 
     Log.e("ESShader", GLES20.glGetShaderInfoLog(shader)); 
     GLES20.glDeleteShader(shader); 
     return 0; 
    } 
    return shader; 
} 

public static int loadProgram(String vertShaderSrc, String fragShaderSrc) { 
    int vertexShader; 
    int fragmentShader; 
    int programObject; 
    int[] linked = new int[1]; 

    // Load the vertex/fragment shaders 
    vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertShaderSrc); 
    if (vertexShader == 0) { 
     return 0; 
    } 

    fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragShaderSrc); 
    if (fragmentShader == 0) { 
     GLES20.glDeleteShader(vertexShader); 
     return 0; 
    } 

    // Create the program object 
    programObject = GLES20.glCreateProgram(); 

    if (programObject == 0) { 
     return 0; 
    } 

    GLES20.glAttachShader(programObject, vertexShader); 
    GLES20.glAttachShader(programObject, fragmentShader); 

    // Link the program 
    GLES20.glLinkProgram(programObject); 

    // Check the link status 
    GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0); 

    if (linked[0] == 0) { 
     Log.e("ESShader", "Error linking program:"); 
     Log.e("ESShader", GLES20.glGetProgramInfoLog(programObject)); 
     GLES20.glDeleteProgram(programObject); 
     return 0; 
    } 

    // Free up no longer needed shader resources 
    GLES20.glDeleteShader(vertexShader); 
    GLES20.glDeleteShader(fragmentShader); 

    return programObject; 
} 

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 

    System.arraycopy(data, 0, ydata, 0, LENGTH); 
    yBuffer.put(ydata); 
    yBuffer.position(0); 

    System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4); 
    uBuffer.put(uData); 
    uBuffer.position(0); 

    System.arraycopy(data, V_INDEX, vData, 0, LENGTH_4); 
    vBuffer.put(vData); 
    vBuffer.position(0); 
} 

}

1

Para la forma más rápida y optimizada, sólo tiene que utilizar el común GL Extensión

//Fragment Shader 
#extension GL_OES_EGL_image_external : require 
uniform samplerExternalOES u_Texture; 

Que en Java

surfaceTexture = new SurfaceTexture(textureIDs[0]); 
try { 
    someCamera.setPreviewTexture(surfaceTexture); 
} catch (IOException t) { 
    Log.e(TAG, "Cannot set preview texture target!"); 
} 

someCamera.startPreview(); 

private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65; 

En Java GL Tema

GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureIDs[0]); 
GLES20.glUniform1i(uTextureHandle, 0); 

La conversión de color ya está hecha para usted. Puedes hacer lo que quieras justo en el sombreador Fragment.

Espero que le ahorre algo de tiempo en su investigación.

0

Apliqué la solución del formulario How to render Android's YUV-NV21 camera image on the background in libgdx with OpenGLES 2.0 in real-time? al proyecto compartido en la pregunta y obtuve un proyecto en funcionamiento. Si eres como yo buscando un código de tutorial que haga la conversión de YUV a RGB por fragment shader, simplemente puedes seguir los siguientes pasos para obtener un ejemplo de trabajo.

  1. Descargue el proyecto https://dl.dropbox.com/u/12829395/application/FilterGL/FilterGL.zip y descomprima.
  2. Reemplazar archivo GLRenderer.java y res/raw/f_convert.glsl en su totalidad por el código compartido a continuación.
  3. Abra el proyecto en Eclipse o import the project to Android Studio.

Los temas principales del código en la pregunta son:

  1. sin GLES20.glActiveTexture (GLES20.GL_TEXTURE1);, yBuffer no se pasa a GL.
  2. los datos YUV toman el formato YUV-NV21, y u_texture y v_texture no se pasaron y se manejaron correctamente en el sombreado. Consulte this post para obtener más información.

Ahora el código corregido: por favor, sustituir GLRenderer.java con

package com.filtergl.shader; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.PreviewCallback; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView.Renderer; 
import android.util.Log; 

public class GLRenderer 
implements Renderer, PreviewCallback { 
    private static final int LENGTH = 76800; 
    private static final int LENGTH_2 = 38400; 

    private ActivityFilterGL activity; 

    private FloatBuffer mVertices; 
    private ShortBuffer mIndices; 

    private int previewFrameWidth = 256; 
    private int previewFrameHeight = 256; 
    private int mProgramObject; 
    private int mPositionLoc; 
    private int mTexCoordLoc; 
// private int mSamplerLoc; 
    private int yTexture; 
    private int uTexture; 
    private int vTexture; 

    private final float[] mVerticesData = { -1.f, 1.f, 0.0f, // Position 0 
      0.0f, 0.0f, // TexCoord 0 
      -1.f, -1.f, 0.0f, // Position 1 
      0.0f, 1.0f, // TexCoord 1 
      1.f, -1.f, 0.0f, // Position 2 
      1.0f, 1.0f, // TexCoord 2 
      1.f, 1.f, 0.0f, // Position 3 
      1.0f, 0.0f // TexCoord 3 
    }; 

    private final short[] mIndicesData = { 0, 1, 2, 0, 2, 3 }; 

    private ByteBuffer frameData = null; 
    private ByteBuffer yBuffer; 
    private ByteBuffer uBuffer; 

    public GLRenderer(ActivityFilterGL activity) { 
     this.activity = activity; 

     mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4) 
       .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     mVertices.put(mVerticesData).position(0); 

     mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2) 
       .order(ByteOrder.nativeOrder()).asShortBuffer(); 
     mIndices.put(mIndicesData).position(0); 

     yBuffer = GraphicsUtil.makeByteBuffer(LENGTH); 
     uBuffer = GraphicsUtil.makeByteBuffer(LENGTH_2); 
    } 

    @Override 
    public final void onDrawFrame(GL10 gl) { 
     // Clear the color buffer 
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

     // Use the program object 
     GLES20.glUseProgram(mProgramObject); 

     // Load the vertex position 
     mVertices.position(0); 
     GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 5 * 4, mVertices); 
     // Load the texture coordinate 
     mVertices.position(3); 
     GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 5 * 4, mVertices); 

     GLES20.glEnableVertexAttribArray(mPositionLoc); 
     GLES20.glEnableVertexAttribArray(mTexCoordLoc); 

     GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 

     GLES20.glUniform1i(yTexture, 1); 
     GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 
       320, 240, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, yBuffer); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

     GLES20.glActiveTexture(GLES20.GL_TEXTURE2); 

     GLES20.glUniform1i(uTexture, 2); 
     GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE_ALPHA, 
       160, 120, 0, GLES20.GL_LUMINANCE_ALPHA, GLES20.GL_UNSIGNED_BYTE, uBuffer); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

     GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mIndices); 
    } 

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

    @Override 
    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 

     // Define a simple shader program for our point. 
     final String vShaderStr = readTextFileFromRawResource(activity, R.raw.v_simple); 
     final String fShaderStr = readTextFileFromRawResource(activity, R.raw.f_convert); 

     // Load the shaders and get a linked program object 
     mProgramObject = loadProgram(vShaderStr, fShaderStr); 

     // Get the attribute locations 
     mPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_position"); 
     mTexCoordLoc = GLES20.glGetAttribLocation(mProgramObject, "a_texCoord"); 

     GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
     yTexture = GLES20.glGetUniformLocation(mProgramObject, "y_texture"); 
     int[] yTextureNames = new int[1]; 
     GLES20.glGenTextures(1, yTextureNames, 0); 
     int yTextureName = yTextureNames[0]; 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTextureName); 

     GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
     uTexture = GLES20.glGetUniformLocation(mProgramObject, "u_texture"); 
     int[] uTextureNames = new int[1]; 
     GLES20.glGenTextures(1, uTextureNames, 0); 
     int uTextureName = uTextureNames[0]; 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE2); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTextureName); 

     // Set the background clear color to black. 
     GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); 
    } 

    public void setPreviewFrameSize(int realWidth, int realHeight) { 
     previewFrameHeight = realHeight; 
     previewFrameWidth = realWidth; 

//  frameData = GraphicsUtil.makeByteBuffer(previewFrameHeight * previewFrameWidth * 3); 
    } 

    public static String readTextFileFromRawResource(final Context context, final int resourceId) { 
     final InputStream inputStream = context.getResources().openRawResource(resourceId); 
     final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 
     final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

     String nextLine; 
     final StringBuilder body = new StringBuilder(); 

     try { 
      while ((nextLine = bufferedReader.readLine()) != null) { 
       body.append(nextLine); 
       body.append('\n'); 
      } 
     } catch (IOException e) { 
      return null; 
     } 

     return body.toString(); 
    } 

    public static int loadShader(int type, String shaderSrc) { 
     int shader; 
     int[] compiled = new int[1]; 

     // Create the shader object 
     shader = GLES20.glCreateShader(type); 
     if (shader == 0) { 
      return 0; 
     } 
     // Load the shader source 
     GLES20.glShaderSource(shader, shaderSrc); 
     // Compile the shader 
     GLES20.glCompileShader(shader); 
     // Check the compile status 
     GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 

     if (compiled[0] == 0) { 
      Log.e("ESShader", GLES20.glGetShaderInfoLog(shader)); 
      GLES20.glDeleteShader(shader); 
      return 0; 
     } 
     return shader; 
    } 

    public static int loadProgram(String vertShaderSrc, String fragShaderSrc) { 
     int vertexShader; 
     int fragmentShader; 
     int programObject; 
     int[] linked = new int[1]; 

     // Load the vertex/fragment shaders 
     vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertShaderSrc); 
     if (vertexShader == 0) { 
      return 0; 
     } 

     fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragShaderSrc); 
     if (fragmentShader == 0) { 
      GLES20.glDeleteShader(vertexShader); 
      return 0; 
     } 

     // Create the program object 
     programObject = GLES20.glCreateProgram(); 

     if (programObject == 0) { 
      return 0; 
     } 

     GLES20.glAttachShader(programObject, vertexShader); 
     GLES20.glAttachShader(programObject, fragmentShader); 

     // Link the program 
     GLES20.glLinkProgram(programObject); 

     // Check the link status 
     GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0); 

     if (linked[0] == 0) { 
      Log.e("ESShader", "Error linking program:"); 
      Log.e("ESShader", GLES20.glGetProgramInfoLog(programObject)); 
      GLES20.glDeleteProgram(programObject); 
      return 0; 
     } 

     // Free up no longer needed shader resources 
     GLES20.glDeleteShader(vertexShader); 
     GLES20.glDeleteShader(fragmentShader); 

     return programObject; 
    } 

    @Override 
    public void onPreviewFrame(byte[] data, Camera camera) { 
     yBuffer.put(data, 0, LENGTH); 
     yBuffer.position(0); 

     uBuffer.put(data, LENGTH, LENGTH/2); 
     uBuffer.position(0); 
    } 

} 

y reemplazar f_convert.glsl con

#ifdef GL_ES 
precision highp float; 
#endif 

varying vec2 v_texCoord; 
uniform sampler2D y_texture; 
uniform sampler2D u_texture; 

void main() 
{ 
    float r, g, b, y, u, v; 

    //We had put the Y values of each pixel to the R,G,B components by 
    //GL_LUMINANCE, that's why we're pulling it from the R component, 
    //we could also use G or B 
    y = texture2D(y_texture, v_texCoord).r; 

    //We had put the U and V values of each pixel to the A and R,G,B 
    //components of the texture respectively using GL_LUMINANCE_ALPHA. 
    //Since U,V bytes are interspread in the texture, this is probably 
    //the fastest way to use them in the shader 
    u = texture2D(u_texture, v_texCoord).a - 0.5; 
    v = texture2D(u_texture, v_texCoord).r - 0.5; 

    //The numbers are just YUV to RGB conversion constants 
    r = y + 1.13983*v; 
    g = y - 0.39465*u - 0.58060*v; 
    b = y + 2.03211*u; 

    gl_FragColor = vec4(r,g,b,1.0); 
} 
Cuestiones relacionadas