2016-01-13 12 views
24

का उपयोग करके एंड्रॉइड एनएनडी से ओपनएल एएस 2.0 का उपयोग करके प्रदर्शित करें। मैं वर्तमान में वीडियो स्ट्रीम को कनेक्ट और डीकोड करने के लिए ffmpeg का उपयोग करके एंड्रॉइड पर आरटीएसपी प्लेयर पर काम कर रहा हूं। मैं वाईयूवी फ्रेम को आरजीबी फ्रेम में बदलने और इसे प्रदर्शित करने के लिए ओपनजीएल एसएस 2.0 का उपयोग करना चाहता हूं लेकिन मुझे अवरुद्ध कर दिया गया है (यह पहली बार है जब मैं ओपनजीएल का उपयोग करता हूं)।आरयूजी रूपांतरण के लिए यूयूवी और शेडर्स

मैं स्पष्ट रूप से व्याख्या करने की कोशिश करूंगा कि मेरी समस्या क्या है।

NDK एंड्रॉयड मैं इस पद्धति का उपयोग (धागा मैं छवियों को प्रदर्शित करने का उपयोग करना चाहते से) एक ओपन संदर्भ प्रारंभ से:

// 
EGLint attribs[] = { 
     EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 
     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
     EGL_BLUE_SIZE, 8, 
     EGL_GREEN_SIZE, 8, 
     EGL_RED_SIZE, 8, 
     EGL_ALPHA_SIZE, 8, 
     EGL_NONE 
}; 
EGLint contextAttrs[] = { 
     EGL_CONTEXT_CLIENT_VERSION, 2, 
     EGL_NONE 
}; 

LOGI("Initializing context"); 

if((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) 
{ 
    closeContext(); 
    return; 
} 

if(!eglInitialize(display, 0, 0)) 
{ 
    closeContext(); 
    return; 
} 

if(!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) 
{ 
    closeContext(); 
    return; 
} 

if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) 
{ 
    closeContext(); 
    return; 
} 

ANativeWindow_setBuffersGeometry(window, 0, 0, format); 

if(!(surface = eglCreateWindowSurface(display, config, window, 0))) 
{ 
    closeContext(); 
    return; 
} 

if(!(context = eglCreateContext(display, config, 0, contextAttrs))) 
{ 
    closeContext(); 
    return; 
} 

if(!eglMakeCurrent(display, surface, surface, context)) 
{ 
    closeContext(); 
    return; 
} 

if(!eglQuerySurface(display, surface, EGL_WIDTH, &width) || !eglQuerySurface(display, surface, EGL_HEIGHT, &height)) 
{ 
    closeContext(); 
    return; 
} 

LOGI("EGLWIDTH : %d EGLHEIGHT : %d ", (int)width, (int)height); 

isInitEGLContext = 1; 
फिर

मैं सेटअप ग्राफिक्स इस पद्धति का उपयोग:

// 
//Load Vertex and Fragment Shader, attach shader and link program 
programId = createProgram(kVertexShader, kFragmentShader); 
LOGI("Program id : %d error : %d",(int) programId, glGetError()); 


if(!programId) 
{ 
    LOGI("Could not create program"); 
    return; 
} 
// get index of the generic vertex attribute bound to vPosition 
positionObject = (int) glGetAttribLocation(programId, "vPosition"); 

// get index of the generic vertex attribute bound to vTexCoord 
texturePosition = (int) glGetAttribLocation(programId, "vTexCoord"); 

// get the location of yTexture within the program (corresponding to program id) 
yuv_texture_object[0] = glGetUniformLocation(programId, "yTexture"); 

// get the location of uTexture within the program 
yuv_texture_object[1] = glGetUniformLocation(programId, "uTexture"); 

// get the location of vTexture within the program 
yuv_texture_object[2] = glGetUniformLocation(programId, "vTexture"); 

// Setup width of each planes (display size) 
stream_yuv_width[0] = 800; 
stream_yuv_width[1] = 400; 
stream_yuv_width[2] = 400; 

// Setup height of each planes (display size) 
stream_yuv_height[0] = 600; 
stream_yuv_height[1] = 300; 
stream_yuv_height[2] = 300; 

//set the view port 
glViewport(0,0,stream_yuv_width[0],stream_yuv_height[0]); 
LOGI("glViewPort() %d ", glGetError()); 

मैंने प्रदर्शन आकार (अब के लिए) को हार्डकोड किया है जब तक कि मुझे कुछ ऐसा काम न हो जाए।

createProgram विधि, शेडर्स लोड करें, प्रोग्राम बनाएं, शेडर्स को सफलतापूर्वक लिंक करें और लिंक करें।

यहाँ मेरी shaders हैं:

void setupYUVTexture() 
{ 
//Setup the pixel alignement 
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
LOGI("glPixelStorei() : %d ", glGetError()); 
int i = 0; 

for(i = 0 ; i < 3 ; ++i) 
{ 
    //Check if the texture already setup 
    if(yuv_texture_id[i] != 0) 
    { 
     glDeleteTextures(1, &yuv_texture_id[i]); 
     yuv_texture_id[i] = 0; 
    } 
    // Active the i texture 
    glActiveTexture(GL_TEXTURE0 + i); 

    //Generate the texture name 
    glGenTextures(1, &yuv_texture_id[i]); 

    // Bind the texture 
    glBindTexture(GL_TEXTURE_2D, yuv_texture_id[i]); 

    // Setup the texture parameters 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 


    //Define the texture image 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, yuv_width[i], yuv_height[i], 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); 
    LOGI("glTexImage2D() %d ", glGetError()); 
} 
} 

void renderToTexture() 
{ 
// Generate framebuffer object name 
    glGenFramebuffers(1, &frameBufferObject); 
    //Bind the framebuffer 
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 


    //Generate render buffer object name 
    glGenRenderbuffers(1, &renderBufferObject); 

    //Bind render buffer 
    glBindRenderbuffer(GL_RENDERBUFFER, renderBufferObject); 

    //Create and initialize render buffer for display RGBA with the same size of the viewport 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 800, 600); 

    //Attach render buffer to frame buffer object 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferObject); 

    //Attach y plane to frame buffer object 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[0], 0); 

    //Attach u plane to frame buffer object 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[1], 0); 

    //Attach v plane to frame buffer object 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[2], 0); 

    // Bind the framebuffer 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    //Check if the framebuffer is correctly setup 
    GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 

    if(status != GL_FRAMEBUFFER_COMPLETE) 
    { 
     LOGI(" FBO setting fault : %d ", status); 
     return; 
    } 
} 
:

const char kVertexShader[] = 
"attribute vec4 vPosition;\n" 
"attribute vec2 vTexCoord;\n" 
"varying vec2 v_vTexCoord;\n" 
"void main() {\n" 
"gl_Position = vPosition;\n" 
"v_vTexCoord = vTexCoord;\n" 
"}\n"; 

const char kFragmentShader[] = 
"precision mediump float; \n" 
"varying vec2 v_vTexCoord;\n" 
"uniform sampler2D yTexture;\n" 
"uniform sampler2D uTexture;\n" 
"uniform sampler2D vTexture;\n" 
"void main() {\n" 
"float nx, ny; \n" 
"nx = v_vTexCoord.x; \n" 
"ny = v_vTexCoord.y; \n" 
"float y=texture2D(yTexture, v_vTexCoord).r;\n" 
"float u=texture2D(uTexture, vec2(nx/2.0, ny/2.0)).r;\n" 
"float v=texture2D(vTexture, vec2(nx/2.0, ny/2.0)).r;\n" 
"y = 1.1643 * (y - 0.0625);\n" 
"u = u - 0.5; \n" 
"v = v - 0.5; \n" 
"float r=y + 1.5958 * v;\n" 
"float g=y - 0.39173 * u - 0.81290 * v;\n" 
"float b=y + 2.017 * u;\n" 
"gl_FragColor = vec4(r, g, b, 1.0);\n" 
"}\n"; 

const GLfloat kVertexInformation[] = { 
    -1.0f, 1.0f,   // TexCoord 0 top left 
    -1.0f,-1.0f,   // TexCoord 1 bottom left 
    1.0f,-1.0f,   // TexCoord 2 bottom right 
    1.0f, 1.0f   // TexCoord 3 top right 
}; 
const GLshort kTextureCoordinateInformation[] = { 
    0, 0,   // TexCoord 0 top left 
    0, 1,   // TexCoord 1 bottom left 
    1, 1,   // TexCoord 2 bottom right 
    1, 0   // TexCoord 3 top right 
}; 
const GLuint kStride = 0;//COORDS_PER_VERTEX * 4; 
const GLshort kIndicesInformation[] = { 
    0, 1, 2, 
    0, 2, 3 
}; 

तो मैं सेटअप YUV बनावट और इस पल yuv_width [i] और yuv_height पर, बनावट के लिए प्रस्तुत करना [i] मूल्य सही करने के लिए सेट कर रहे हैं

समाप्त करने के लिए, मेरे ड्रा फ्रेम विधि:

void drawFrame() 
{ 
LOGI("DrawFrame"); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 
printGLError("glBindFramebuffer"); 
glUseProgram(programId); 
printGLError("glUseProgram"); 
int i = 0; 
for(i = 0 ; i < 3 ; ++i) 
{ 
    glActiveTexture(GL_TEXTURE0 + i); 
    printGLError("glActiveTexture"); 

    glBindTexture(GL_TEXTURE_2D, yuv_texture_object[i]); 
    printGLError("glBindTexture"); 

    glUniform1i(yuv_texture_object[i], i); 
    printGLError("glUniform1i");    
    LOGI("Plan : %d Largeur : %d Hauteur : %d ", i, yuv_width[i], yuv_height[i]); 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,yuv_width[i], yuv_height[i], GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv_planes[i]); 
      printGLError("glTexSubImage2D"); 

    } 

    glVertexAttribPointer(positionObject, 2, GL_FLOAT, GL_FALSE, kStride, kVertexInformation); 
    printGLError("glVertexAttribPointer"); 

    glVertexAttribPointer(texturePosition, 2, GL_SHORT, GL_FALSE, kStride, kTextureCoordinateInformation); 
    printGLError("glVertexAttribPointer"); 

    glEnableVertexAttribArray(positionObject);  
    printGLError("glVertexAttribArray"); 

    glEnableVertexAttribArray(texturePosition); 
    printGLError("glVertexAttribArray"); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    printGLError("glBindFramebuffer"); 

    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, kIndicesInformation); 
    printGLError("glDrawElements"); 

    eglSwapBuffers(display, surface); 
    printGLError("eglSwapBuffers"); 

} 

मैं एक बार OpenGL संरचना और अन्य प्रारंभ गुण जो आवश्यक हैं, फिर जब एक फ्रेम डीकोड होता है तो मैं y12 बफर को yuv_planes[0] में दोहराता हूं, आप yuv_planes[ 1] में बफर और yuv_planes[2] में v buffer।

एक बार एक फ्रेम सही ढंग से ffmpeg मैं इस क्रम में फोन का उपयोग कर डीकोड:
- initContext()
- setupGraphics()
- setupYUVTexture()
- renderToTexture()

तो मैं फोन drawFrame। बेशक, जब सबकुछ शुरू होता है तो मैं प्रत्येक डीकोडेड फ्रेम के बाद सीधे ड्राफ्रेम को कॉल करता हूं।

मेरे पास अब आउटपुट है।

Video display by opengl

छवि का आकार सही है, लेकिन अब मैं यहां ब्लॉक कर रहा हूँ। मुझे समझ में नहीं आता कि छवि प्रदर्शन क्यों हरा है! कोई भी विचार

+0

क्या 3T कॉल में glTexSubImage2D रिपोर्ट त्रुटि है? ध्यान दें कि आप (++ i) का उपयोग कर रहे हैं जो उसके बाद [0, 2] में [1, 3] है। yuv_width [3] परिभाषित नहीं प्रतीत होता है इसलिए अंतिम कॉल निश्चित रूप से गलत होना चाहिए (i = 3 के लिए)। आपको यह भी पता होना चाहिए कि glGetError त्रुटि स्टैक से शीर्ष मान देता है और इसे पॉप करता है। इसका मतलब यह है कि आपको स्टैक से सभी त्रुटियों को प्राप्त करने के लिए आम तौर पर थोड़ी देर की आवश्यकता होती है। चूंकि आप ऐसा नहीं करते हैं, तो आपको अगली glGetError कॉल पर त्रुटि की सूचना मिल सकती है, हालांकि यह पिछली पंक्ति द्वारा उत्पन्न की गई थी। –

+0

जैसा कि मैंने शेडर को देखा है, ऐसा नहीं लगता है कि आप रंग घटकों का उपयोग यूयूवी के रूप में करते हैं बल्कि आरजीबी के रूप में करते हैं और फिर उन्हें आरजीबी में बदल देते हैं। यह मेरे लिए ठीक लगता है लेकिन आपको GL_LUMINANCE के बजाय GL_RGB का उपयोग करना चाहिए और शेर में आरजीबी मानों को YUV के रूप में मानना ​​चाहिए जो आप पहले से ही कर रहे हैं (या नहीं, खंड का शेडर थोड़ा अजीब लगता है। शायद कोड में कुछ टिप्पणियां होंगी मदद)। –

+0

मैंने टिप्पणी जोड़ने और मेरे एंड्रॉइड मॉनिटर के आउटपुट को जोड़ने के लिए पोस्ट संपादित किया। प्रारंभ करने के लिए, पहली कॉल पर और अंतिम कॉल पर glTexSubImage2D रिपोर्ट त्रुटि। मेरे लूप में उपयोग किए जाने वाले बयान से पहले वृद्धि सही है। इस मामले में, यह 1 से 3 तक शुरू नहीं होगा लेकिन 0 से 2 तक शुरू होगा। कुछ संकलन एक अस्थायी विशेषता का उपयोग करते हैं यदि आप कथन के बाद वृद्धि का उपयोग करते हैं, तो मुझे इस तरह लूप के लिए लिखने के लिए उपयोग प्राप्त हुआ है क्योंकि यह अस्थायी विशेषता का उपयोग नहीं करेगा (यह है थोड़ा तेज़)। मेरे एंड्रॉइड मॉनीटर आउटपुट को आपको दिखाने के लिए मुझे यह लॉग मिला था कि यह सही है। –

उत्तर

1

यह बहुत सारे कोड से गुज़रने के लिए है और बहुत सी चीजें गलत हो सकती हैं;)। इस तरह के मुद्दों को डीबग करने के लिए, मैं चरण-दर-चरण जाऊंगा।

  1. यह सुनिश्चित करने के लिए कि आपकी कॉन्फ़िगरेशन ठीक से काम कर रही है, केवल आउटपुट लाल (gl_FragColor = vec4(1.0, 0.5, 0.5, 1.0))।
  2. ग्रेस्केल में प्रत्येक बनावट को आउटपुट करने का प्रयास करें।(gl_FragColor = vec4(y, y, y, 1.0))
  3. यदि यह सब काम कर रहा है तो इसका सबसे अधिक संभावना है कि आपका yuv => आरजीबी रूपांतरण कहीं गलत है।
  4. यदि यह काम नहीं कर रहा है, तो मुझे बनावट मैपिंग में कुछ संदेह होगा। अपने glTexSubImage2D कॉल को दो बार जांचें। आपको एक अलग कदम पारित करने या एक अलग समन्वय प्रणाली का उपयोग करने की आवश्यकता हो सकती है।
संबंधित मुद्दे