2016-11-22 2 views
0

Jusqu'à présent, j'ai utilisé différents shaders et les ai appliqués à un VideoSurfaceView personnalisé pendant la lecture d'une vidéo. Tout fonctionnait bien jusqu'à aujourd'hui quand je voulais ajouter un effet gamma:Erreur GLES 1282 inattendue sur Android

public class GammaEffect implements ShaderInterface { 
/** 
* Initialize Effect 
*/ 
public GammaEffect() { 
} 

@Override 
public String getShader(GLSurfaceView mGlSurfaceView) { 

    String shader = "#extension GL_OES_EGL_image_external : require\n" 
      +"precision mediump float;\n" 

      +"varying vec2 textureCoordinate;\n" 
      +"uniform sampler2D inputImageTexture;\n" 
      +"uniform float gamma;\n" 

      +"void main() {\n" 

      +"vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" 
      +"gl_FragColor = vec4(pow(textureColor.rgb, vec3(gamma)), textureColor.w);\n" 

      +"}\n"; 


    return shader; 
    } 
} 

Et la classe VideoSurface personnalisée:

public class VideoSurfaceView extends GLSurfaceView { 
private static final String TAG = "VideoSurfaceView"; 
private VideoRender mRenderer; 
private MediaPlayer mMediaPlayer = null; 
private static VideoSurfaceView mSurfaceView; 
private Context mContext; 
private static ShaderInterface effect; 

public VideoSurfaceView(Context context) { 
    super(context); 
    mContext = context; 
    setEGLContextClientVersion(2); 
    mRenderer = new VideoRender(mContext); 
    setRenderer(mRenderer); 
    mSurfaceView = this; 
} 

public VideoSurfaceView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    mContext = context; 
    setEGLContextClientVersion(2); 
    mRenderer = new VideoRender(mContext); 
    setRenderer(mRenderer); 
    mSurfaceView = this; 
} 

/** 
* initializes media player and the effect that is going to be applied on 
* video. The video is played automatically so you dont need to call play. 
* 
* @param mediaPlayer instance of {@link MediaPlayer} 
* @param shaderEffect any effect that implements {@link ShaderInterface} 
*/ 
public void init(MediaPlayer mediaPlayer, ShaderInterface shaderEffect) { 
    if (mediaPlayer == null) 
     Toast.makeText(mContext, "Set MediaPlayer before continuing", 
       Toast.LENGTH_LONG).show(); 
    else 
     mMediaPlayer = mediaPlayer; 
    if (shaderEffect == null) 
     effect = new NoEffect(); 
    else 
     effect = shaderEffect; 
} 

@Override 
public void onResume() { 
    if (mMediaPlayer == null) { 
     Log.e(TAG, "Call init() before Continuing"); 
     return; 
    } 
    queueEvent(new Runnable() { 
     @Override 
     public void run() { 
      mRenderer.setMediaPlayer(mMediaPlayer); 
     } 
    }); 

    super.onResume(); 
} 

private static class VideoRender implements Renderer, 
     SurfaceTexture.OnFrameAvailableListener { 
    private static String TAG = "VideoRender"; 

    private static final int FLOAT_SIZE_BYTES = 4; 
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 
    private final float[] mTriangleVerticesData = { 
      // X, Y, Z, U, V 
      -1.0f, -1.0f, 0, 0.f, 0.f, 1.0f, -1.0f, 0, 1.f, 0.f, -1.0f, 
      1.0f, 0, 0.f, 1.f, 1.0f, 1.0f, 0, 1.f, 1.f,}; 

    private FloatBuffer mTriangleVertices; 

    private final String mVertexShader = "uniform mat4 uMVPMatrix;\n" 
      + "uniform mat4 uSTMatrix;\n" + "attribute vec4 aPosition;\n" 
      + "attribute vec4 aTextureCoord;\n" 
      + "varying vec2 vTextureCoord;\n" + "void main() {\n" 
      + " gl_Position = uMVPMatrix * aPosition;\n" 
      + " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + "}\n"; 
    private float[] mMVPMatrix = new float[16]; 
    private float[] mSTMatrix = new float[16]; 

    private int mProgram; 
    private int mTextureID[] = new int[2]; 
    private int muMVPMatrixHandle; 
    private int muSTMatrixHandle; 
    private int maPositionHandle; 
    private int maTextureHandle; 

    private SurfaceTexture mSurface; 
    private boolean updateSurface = false; 

    private static int GL_TEXTURE_EXTERNAL_OES = 0x8D65; 

    private MediaPlayer mMediaPlayer; 

    public VideoRender(Context context) { 
     mTriangleVertices = ByteBuffer 
       .allocateDirect(
         mTriangleVerticesData.length * FLOAT_SIZE_BYTES) 
       .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     mTriangleVertices.put(mTriangleVerticesData).position(0); 

     Matrix.setIdentityM(mSTMatrix, 0); 
    } 

    public void setMediaPlayer(MediaPlayer player) { 
     mMediaPlayer = player; 
    } 

    @Override 
    public void onDrawFrame(GL10 glUnused) { 
     synchronized (this) { 
      if (updateSurface) { 
       mSurface.updateTexImage(); 
       mSurface.getTransformMatrix(mSTMatrix); 
       updateSurface = false; 
      } 
     } 
     mProgram = createProgram(mVertexShader, 
       effect.getShader(mSurfaceView)); 
     GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 
     GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT 
       | GLES20.GL_COLOR_BUFFER_BIT); 

     GLES20.glUseProgram(mProgram); 
     checkGlError("glUseProgram"); 

     GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
     GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]); 

     mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 
     GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, 
       false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
       mTriangleVertices); 
     checkGlError("glVertexAttribPointer maPosition"); 
     GLES20.glEnableVertexAttribArray(maPositionHandle); 
     checkGlError("glEnableVertexAttribArray maPositionHandle"); 

     mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
     GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, 
       false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
       mTriangleVertices); 
     checkGlError("glVertexAttribPointer maTextureHandle"); 
     GLES20.glEnableVertexAttribArray(maTextureHandle); 
     checkGlError("glEnableVertexAttribArray maTextureHandle"); 

     Matrix.setIdentityM(mMVPMatrix, 0); 
     GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 
       0); 
     GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); 

     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 
     checkGlError("glDrawArrays"); 
     GLES20.glFinish(); 

    } 

    @Override 
    public void onSurfaceChanged(GL10 glUnused, int width, int height) { 

    } 

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

     mProgram = createProgram(mVertexShader, 
       effect.getShader(mSurfaceView)); 
     if (mProgram == 0) { 
      return; 
     } 
     maPositionHandle = GLES20 
       .glGetAttribLocation(mProgram, "aPosition"); 
     checkGlError("glGetAttribLocation aPosition"); 
     if (maPositionHandle == -1) { 
      throw new RuntimeException(
        "Could not get attrib location for aPosition"); 
     } 
     maTextureHandle = GLES20.glGetAttribLocation(mProgram, 
       "aTextureCoord"); 
     checkGlError("glGetAttribLocation aTextureCoord"); 
     if (maTextureHandle == -1) { 
      throw new RuntimeException(
        "Could not get attrib location for aTextureCoord"); 
     } 

     muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, 
       "uMVPMatrix"); 
     checkGlError("glGetUniformLocation uMVPMatrix"); 
     if (muMVPMatrixHandle == -1) { 
      throw new RuntimeException(
        "Could not get attrib location for uMVPMatrix"); 
     } 

     muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, 
       "uSTMatrix"); 
     checkGlError("glGetUniformLocation uSTMatrix"); 
     if (muSTMatrixHandle == -1) { 
      throw new RuntimeException(
        "Could not get attrib location for uSTMatrix"); 
     } 

     // int[] textures = new int[1]; 
     GLES20.glGenTextures(2, mTextureID, 0); 
     // GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]); 

     // mTextureID = textures[0]; 
     GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]); 
     checkGlError("glBindTexture mTextureID"); 

     // GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, 
     // GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
     // GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, 
     // GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     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.glTexParameteri(GLES20.GL_TEXTURE_2D, 
       GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 
       GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

     /* 
     * Create the SurfaceTexture that will feed this textureID, and pass 
     * it to the MediaPlayer 
     */ 
     mSurface = new SurfaceTexture(mTextureID[0]); 
     mSurface.setOnFrameAvailableListener(this); 

     Surface surface = new Surface(mSurface); 
     mMediaPlayer.setSurface(surface); 
     mMediaPlayer.setScreenOnWhilePlaying(true); 
     surface.release(); 

     try { 
      mMediaPlayer.prepare(); 
     } catch (IOException t) { 
      Log.e(TAG, "media player prepare failed"); 
     } 

     synchronized (this) { 
      updateSurface = false; 
     } 

     mMediaPlayer.start(); 
    } 

    @Override 
    synchronized public void onFrameAvailable(SurfaceTexture surface) { 
     updateSurface = true; 
    } 

    private int loadShader(int shaderType, String source) { 
     int shader = GLES20.glCreateShader(shaderType); 
     if (shader != 0) { 
      GLES20.glShaderSource(shader, source); 
      GLES20.glCompileShader(shader); 
      int[] compiled = new int[1]; 
      GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, 
        compiled, 0); 
      if (compiled[0] == 0) { 
       Log.e(TAG, "Could not compile shader " + shaderType + ":"); 
       Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 
       GLES20.glDeleteShader(shader); 
       shader = 0; 
      } 
     } 
     return shader; 
    } 

    private int createProgram(String vertexSource, String fragmentSource) { 
     int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 
     if (vertexShader == 0) { 
      return 0; 
     } 
     int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, 
       fragmentSource); 
     if (pixelShader == 0) { 
      return 0; 
     } 

     int program = GLES20.glCreateProgram(); 
     if (program != 0) { 
      GLES20.glAttachShader(program, vertexShader); 
      checkGlError("glAttachShader"); 
      GLES20.glAttachShader(program, pixelShader); 
      checkGlError("glAttachShader"); 
      GLES20.glLinkProgram(program); 
      int[] linkStatus = new int[1]; 
      GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, 
        linkStatus, 0); 
      if (linkStatus[0] != GLES20.GL_TRUE) { 
       Log.e(TAG, "Could not link program: "); 
       Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 
       GLES20.glDeleteProgram(program); 
       program = 0; 
      } 
     } 
     return program; 
    } 

    private void checkGlError(String op) { 
     int error; 
     if ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 
      Log.e(TAG, op + ": glError " + error); 
      throw new RuntimeException(op + ": glError " + error); 
     } 
    } 

    } // End of class VideoRender. 

} // End of class VideoSurfaceView. 

La méthode « checkGLError » renvoie 1282. Il est la première fois il le fait et je ne comprends pas pourquoi.

J'ai cherché sur Stack pour les réponses et je n'ai pas trouvé quelque chose de convenable pour ce cas. Pouvez-vous s'il vous plaît donner votre opinion sur ce qui doit être changé?

+0

Copie possible de [Vec shader - hue video filtering] (http://stackoverflow.com/questions/40619903/vec-shader-hue-video-filtering) – solidpixel

+0

N'est-ce pas juste une copie du même problème dans votre autre question? – solidpixel

+0

Selon l'autre question. (1) Précisément quelle fonction échoue - vous avez plusieurs appels à checkGlError? Juste nous dire la chaîne de journal aiderait. (2) L'erreur est GL_INVALID_OPERATION. Utilisez (1) et (2) et lisez le manuel - le manuel GL est assez bon pour expliquer les causes d'erreur ... – solidpixel

Répondre

0

Le problème résidait dans la manière dont le shader Gamma a été créé. Être un peu difficile à modifier le code C sans compilateur, je devais faire quelques changements et la version finale du code:

public class GammaEffect implements ShaderInterface { 
/** 
* Initialize Effect 
*/ 
public GammaEffect() { 
} 

@Override 
public String getShader(GLSurfaceView mGlSurfaceView) { 

    String shader = "#extension GL_OES_EGL_image_external : require\n" 

      +"precision mediump float;\n" 
      +"uniform samplerExternalOES sTexture;\n" 
      +"varying vec2 vTextureCoord;\n" 
      +"float gamma;\n" 

      +"void main() {\n" 

      +"gamma = 2.0;\n" 

    +"vec4 color = texture2D(sTexture, vTextureCoord);\n" 
      +"gl_FragColor = vec4(pow(color.rgb, vec3(gamma)), color.a);\n" 

      +"}\n"; 

return shader; 

    } 
} 

fonctionne comme un charme. J'espère que cela aidera les programmeurs qui veulent apprendre le GLSL!

0

Je pense que la question est là que vous définissez vos données UV:

GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, 
          false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
          mTriangleVertices); 

Vous n'avez pas 3 valeurs pour les UV, vous avez 2, de sorte que vous utilisez l'extrémité du tableau. En OpenGL ES natif normal, ceci serait probablement une erreur de segmentation; Java autorise la vérification des limites sur le tableau, ce qui signifie que vous obtenez une erreur.

+0

Il est vrai qu'il n'y a que 2 valeurs, mais quand je compile et renvoie le shader, la même erreur se produit ... –

+0

Qu'est-ce que le shader a à voir avec ça? Le problème est une discordance entre la taille de 'mTriangleVerticesData' et les définitions d'attributs qui le référencent. Cela n'a rien à voir avec le shader ... (en supposant que ce soit le problème). – solidpixel

+0

En fait, cela a beaucoup à voir avec ça. Il y avait un problème avec la syntaxe, je vais mettre à jour la réponse. Merci pour votre aide @solidpixel! –