का उपयोग करके एंड्रॉइड एनएनडी से ओपनएल एएस 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
। बेशक, जब सबकुछ शुरू होता है तो मैं प्रत्येक डीकोडेड फ्रेम के बाद सीधे ड्राफ्रेम को कॉल करता हूं।
मेरे पास अब आउटपुट है।
छवि का आकार सही है, लेकिन अब मैं यहां ब्लॉक कर रहा हूँ। मुझे समझ में नहीं आता कि छवि प्रदर्शन क्यों हरा है! कोई भी विचार
क्या 3T कॉल में glTexSubImage2D रिपोर्ट त्रुटि है? ध्यान दें कि आप (++ i) का उपयोग कर रहे हैं जो उसके बाद [0, 2] में [1, 3] है। yuv_width [3] परिभाषित नहीं प्रतीत होता है इसलिए अंतिम कॉल निश्चित रूप से गलत होना चाहिए (i = 3 के लिए)। आपको यह भी पता होना चाहिए कि glGetError त्रुटि स्टैक से शीर्ष मान देता है और इसे पॉप करता है। इसका मतलब यह है कि आपको स्टैक से सभी त्रुटियों को प्राप्त करने के लिए आम तौर पर थोड़ी देर की आवश्यकता होती है। चूंकि आप ऐसा नहीं करते हैं, तो आपको अगली glGetError कॉल पर त्रुटि की सूचना मिल सकती है, हालांकि यह पिछली पंक्ति द्वारा उत्पन्न की गई थी। –
जैसा कि मैंने शेडर को देखा है, ऐसा नहीं लगता है कि आप रंग घटकों का उपयोग यूयूवी के रूप में करते हैं बल्कि आरजीबी के रूप में करते हैं और फिर उन्हें आरजीबी में बदल देते हैं। यह मेरे लिए ठीक लगता है लेकिन आपको GL_LUMINANCE के बजाय GL_RGB का उपयोग करना चाहिए और शेर में आरजीबी मानों को YUV के रूप में मानना चाहिए जो आप पहले से ही कर रहे हैं (या नहीं, खंड का शेडर थोड़ा अजीब लगता है। शायद कोड में कुछ टिप्पणियां होंगी मदद)। –
मैंने टिप्पणी जोड़ने और मेरे एंड्रॉइड मॉनिटर के आउटपुट को जोड़ने के लिए पोस्ट संपादित किया। प्रारंभ करने के लिए, पहली कॉल पर और अंतिम कॉल पर glTexSubImage2D रिपोर्ट त्रुटि। मेरे लूप में उपयोग किए जाने वाले बयान से पहले वृद्धि सही है। इस मामले में, यह 1 से 3 तक शुरू नहीं होगा लेकिन 0 से 2 तक शुरू होगा। कुछ संकलन एक अस्थायी विशेषता का उपयोग करते हैं यदि आप कथन के बाद वृद्धि का उपयोग करते हैं, तो मुझे इस तरह लूप के लिए लिखने के लिए उपयोग प्राप्त हुआ है क्योंकि यह अस्थायी विशेषता का उपयोग नहीं करेगा (यह है थोड़ा तेज़)। मेरे एंड्रॉइड मॉनीटर आउटपुट को आपको दिखाने के लिए मुझे यह लॉग मिला था कि यह सही है। –