Tôi đang cố gắng hoàn thành Chuyển đổi YV12 sang RGB được đề cập in this post bằng trình đổ bóng GLSL.Sự cố khi chuyển đổi YV12 sang RGB qua GLSL
Ứng dụng của tôi tải khung YV12 thô từ đĩa và cố thực hiện chuyển đổi bằng trình đổ bóng GLSL. Tuy nhiên, ảnh kết quả được lật theo chiều dọc và có một số vấn đề về màu sắc. Tôi nghĩ rằng vấn đề có thể là hình ảnh đang được đọc như là một mảng của char
(1 byte) và sau đó chuyển đổi thành một mảng của GLushort
(2 byte). Bạn nghĩ sao?
Đây là cách khung YUV liệu trông giống như:
and the raw frame loaded by the application can be downloaded from here.
và đây là kết quả tôi nhận được:
Tôi chia sẻ mã nguồn của ứng dụng dưới đây:
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <iostream>
#include <fstream>
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
static GLint ImgWidth, ImgHeight;
static GLushort *ImageYUV = NULL;
static void DrawObject(void)
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
glTexCoord2f(ImgWidth, 0);
glVertex2f(1.0, -1.0);
glTexCoord2f(ImgWidth, ImgHeight);
glVertex2f(1.0, 1.0);
glTexCoord2f(0, ImgHeight);
glVertex2f(-1.0, 1.0);
glEnd();
}
static void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(Xrot, 1.0, 0.0, 0.0);
glRotatef(Yrot, 0.0, 1.0, 0.0);
glRotatef(Zrot, 0.0, 0.0, 1.0);
DrawObject();
glPopMatrix();
glutSwapBuffers();
}
static void Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Vertical flip so texture appears right
glFrustum(-1.0, 1.0, 1.0, -1.0, 10.0, 100.0);
//glFrustum(-1.0, 1.0, -1.0, 1.0, 10.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -15.0);
}
static void Key(unsigned char key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void SpecialKey(int key, int x, int y)
{
float step = 3.0;
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
Xrot += step;
break;
case GLUT_KEY_DOWN:
Xrot -= step;
break;
case GLUT_KEY_LEFT:
Yrot += step;
break;
case GLUT_KEY_RIGHT:
Yrot -= step;
break;
}
glutPostRedisplay();
}
bool CheckShader(int n_shader_object)
{
int n_tmp;
glGetShaderiv(n_shader_object, GL_COMPILE_STATUS, &n_tmp);
bool b_compiled = n_tmp == GL_TRUE;
int n_log_length;
glGetShaderiv(n_shader_object, GL_INFO_LOG_LENGTH, &n_log_length);
// query status ...
if(n_log_length > 1) {
char *p_s_temp_info_log;
if(!(p_s_temp_info_log = (char*)malloc(n_log_length)))
return false;
int n_tmp;
glGetShaderInfoLog(n_shader_object, n_log_length, &n_tmp,
p_s_temp_info_log);
assert(n_tmp <= n_log_length);
fprintf(stderr, "%s\n", p_s_temp_info_log);
free(p_s_temp_info_log);
}
// get/concat info-log
return b_compiled;
}
static void Init(int argc, char *argv[])
{
GLuint texObj = 100;
const char *file;
printf("Checking GL_ARB_texture_rectangle\n");
if (!glutExtensionSupported("GL_ARB_texture_rectangle")) {
printf("Sorry, GL_ARB_texture_rectangle is required\n");
exit(0);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texObj);
#ifdef LINEAR_FILTER
/* linear filtering looks much nicer but is much slower for Mesa */
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#else
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#endif
std::ifstream yuv_file("data.yv12", std::ios::in | std::ios::binary | std::ios::ate);
if (!yuv_file.is_open())
{
std::cout << "> GLWidget::GLWidget !!! Failed to load yuv file";
return;
}
int yuv_file_sz = yuv_file.tellg();
ImgWidth = 1280;
ImgHeight = 720;
ImageYUV = new GLushort[yuv_file_sz];
char* memblock = new char[yuv_file_sz];
if (!memblock)
{
std::cout << "> GLWidget::GLWidget !!! Failed to allocate memblock";
return;
}
yuv_file.seekg(0, std::ios::beg);
yuv_file.read(memblock, yuv_file_sz);
yuv_file.close();
// A simple "memcpy(ImageYUV, memblock, yuv_file_sz);"
// won't work because the data read is stored as char (1 byte) and GLushort is 2 bytes.
// So, doing a manual copy:
for (int i = 0; i < yuv_file_sz; i++)
{
ImageYUV[i] = (GLushort)memblock[i];
}
delete[] memblock;
printf("Image: %dx%d\n", ImgWidth, ImgHeight);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
GL_LUMINANCE_ALPHA, ImgWidth, ImgHeight, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, ImageYUV);
assert(glGetError() == GL_NO_ERROR);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
0, 0, ImgWidth, ImgHeight,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, ImageYUV);
assert(glGetError() == GL_NO_ERROR);
delete[] ImageYUV;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glShadeModel(GL_FLAT);
glClearColor(0.3, 0.3, 0.4, 1.0);
static const char *p_s_vertex_shader =
"varying vec2 t;"
"void main()"
"{"
" t = gl_MultiTexCoord0.xy;"
" gl_Position = ftransform();"
"}";
static const char *p_s_fragment_shader =
"#extension GL_ARB_texture_rectangle : enable\n"
"varying vec2 t;"
"uniform sampler2DRect tex;"
"void main()"
"{"
" vec2 tcEven = vec2(floor(t.x * .5) * 2.0, t.y);"
" vec2 tcOdd = vec2(tcEven.x + 1.0, t.y);"
" float Cb = texture2DRect(tex, tcEven).x - .5;"
" float Cr = texture2DRect(tex, tcOdd).x - .5;"
" float y = texture2DRect(tex, t).w;" // redundant texture read optimized away by texture cache
" float r = y + 1.28033 * Cr;"
" float g = y - .21482 * Cb - .38059 * Cr;"
" float b = y + 2.12798 * Cb;"
" gl_FragColor = vec4(r, g, b, 1.0);"
"}";
int v = glCreateShader(GL_VERTEX_SHADER);
int f = glCreateShader(GL_FRAGMENT_SHADER);
int p = glCreateProgram();
glShaderSource(v, 1, &p_s_vertex_shader, 0);
glShaderSource(f, 1, &p_s_fragment_shader, 0);
glCompileShader(v);
CheckShader(v);
glCompileShader(f);
CheckShader(f);
glAttachShader(p, v);
glAttachShader(p, f);
glLinkProgram(p);
glUseProgram(p);
glUniform1i(glGetUniformLocation(p, "tex"), 0);
if (argc > 1 && strcmp(argv[1], "-info")==0) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
}
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(1280, 720);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
glewInit();
Init(argc, argv);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Display);
glutMainLoop();
return 0;
}
+1 Để có ** câu trả lời chất lượng cao **. Điều này nên được bỏ phiếu rất nhiều! – karlphillip
Trên Linux, với cả card đồ họa ATI và Intel [kết quả là màu vàng-ish] (http://i41.tinypic.com/2ynmrl0.jpg). Bạn có biết điều gì có thể xảy ra không? – karlphillip
Nhân tiện, mã của chúng tôi trình bày kết quả được lật theo chiều dọc (lộn ngược).Để khắc phục điều đó, chỉ cần thay đổi 'glFrustum()' bên trong 'Reshape()' thành 'glFrustum (-1.0, 1.0, 1.0, -1.0, 10.0, 100.0);'. Tôi đã sửa lỗi của tôi trong câu hỏi. – karlphillip