Я пытаюсь сделать некоторые оптимизации в частном видеоплеера для Linux с целью повышения производительности, потому что играют MP4 файлы тяжелы на процессоре, так как видеокадров закодированы в YV12, и OpenGL не предоставляет собственный способ отображения этого формата. Прямо сейчас есть код, который запускается на процессоре для преобразования YV12 в RGB, прежде чем изображение будет отправлено на графический процессор для отображения, и это потребляет 100% обработки ЦП.glPopMatrix() орет «неподдерживаемый формат текстур в setup_hardware_state»
В настоящее время я изучаю , как декодировать кадры YV12 без необходимости писать шейдер для преобразования YV12 -> RGB. Насколько я понимаю, один из способов сделать это - через GL_MESA_ycbcr_texture, по-видимому, поддерживается моей системой (сообщено glxinfo
).
В этом блоке Fedora у меня есть видеоустройство ATI Technologies Inc RV610 [Radeon HD 2400 PRO], что является достойной видеокартой. Затем я загрузил тест yuvrect и внес несколько изменений, чтобы заменить GL_TEXTURE_RECTANGLE_NV
на текстуру, поддерживаемую этой картой: GL_TEXTURE_RECTANGLE_ARB
.
Однако, когда я исполняю это модифицированное приложение выводит:
The MESA driver reports *unsupported texture format in setup_hardware_state*
Я заметил, что эта ошибка появляется, когда glPopMatrix();
выполняется из Display()
обратных вызова. Теперь, это не похоже на ошибку в моем приложении, потому что я запустил этот точный код в другом блоке Fedora (той же системе), у которого есть другая видеокарта: Intel Corporation Sandy Bridge Integrated Graphics Controller (rev 09) , и он работает красиво.
Единственная видимая разница между двумя двоичными файлами - это библиотеки, с которыми они связаны. На (проблемной) ATI карты LDD отчетов:
linux-gate.so.1 => (0x00da3000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x077bd000)
libGLU.so.1 => /usr/lib/libGLU.so.1 (0x0783b000)
libglut.so.3 => /usr/lib/libglut.so.3 (0x005a9000)
libGLEW.so.1.5 => /usr/lib/libGLEW.so.1.5 (0x00aa3000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x057e2000)
libm.so.6 => /lib/libm.so.6 (0x004e4000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x0053f000)
libc.so.6 => /lib/libc.so.6 (0x00358000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x0071b000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x009c5000)
libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00af7000)
libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00b76000)
libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x0014e000)
libdrm.so.2 => /usr/lib/libdrm.so.2 (0x00101000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00510000)
libdl.so.2 => /lib/libdl.so.2 (0x0052d000)
libXi.so.6 => /usr/lib/libXi.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00337000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00859000)
librt.so.1 => /lib/librt.so.1 (0x00534000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x00854000)
Между тем, на плате Intel вы можете увидеть, что это связанно с libv4l и некоторыми другими библиотеками в то время как ATI не делали! Интересно, если это имеет ничего общего с этой проблемой я столкнулся:
linux-gate.so.1 => (0x008d6000)
/usr/lib/libv4l/v4l1compat.so (0x00345000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x4fb85000)
libGLU.so.1 => /usr/lib/libGLU.so.1 (0x4fc10000)
libglut.so.3 => /usr/lib/libglut.so.3 (0x005a9000)
libGLEW.so.1.5 => /usr/lib/libGLEW.so.1.5 (0x4fc82000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x42ca7000)
libm.so.6 => /lib/libm.so.6 (0x41fbc000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x42017000)
libc.so.6 => /lib/libc.so.6 (0x41e30000)
libv4l1.so.0 => /usr/lib/libv4l1.so.0 (0x00110000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x421f8000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x424c0000)
libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x42c0e000)
libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x42d98000)
libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x432a2000)
libdrm.so.2 => /usr/lib/libdrm.so.2 (0x4247b000)
libpthread.so.0 => /lib/libpthread.so.0 (0x41fe8000)
libdl.so.2 => /lib/libdl.so.2 (0x42005000)
libXi.so.6 => /usr/lib/libXi.so.6 (0x42748000)
/lib/ld-linux.so.2 (0x41e0f000)
libv4l2.so.0 => /usr/lib/libv4l2.so.0 (0x4217c000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x42337000)
librt.so.1 => /lib/librt.so.1 (0x4200c000)
libv4lconvert.so.0 => /usr/lib/libv4lconvert.so.0 (0x42357000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x421f3000)
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x43317000)
Если вы хотите, чтобы запустить пример ниже вам нужно readtex.c, readtex.h и girl.rgb, и скомпилировать его с: g++ yuvrect.cpp -o yuvrect -lGL -lGLU -lglut -lGLEW
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "readtex.c" /* I know, this is a hack. */
#define TEXTURE_FILE "girl.rgb"
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(); // <--- error message comes from this call
glutSwapBuffers();
}
static void Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
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();
}
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_NV_texture_rectangle is required\n");
exit(0);
}
printf("Checking GL_MESA_ycbcr_texture\n");
if (!glutExtensionSupported("GL_MESA_ycbcr_texture")) {
printf("Sorry, GL_MESA_ycbcr_texture 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
if (argc > 1)
file = argv[1];
else
file = TEXTURE_FILE;
ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight);
if (!ImageYUV) {
printf("Couldn't read %s\n", TEXTURE_FILE);
exit(0);
}
printf("Image: %dx%d\n", ImgWidth, ImgHeight);
printf("Calling glTexImage2D\n");
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
GL_YCBCR_MESA, ImgWidth, ImgHeight, 0,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, ImageYUV);
printf("Called glTexImage2D\n");
assert(glGetError() == GL_NO_ERROR);
printf("* Assert #1\n");
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
0, 0, ImgWidth, ImgHeight,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, ImageYUV);
assert(glGetError() == GL_NO_ERROR);
printf("* Assert #2\n");
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);
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(300, 300);
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;
}
Любые советы по решению этой проблемы, ребята?
Действительно ли это ** glPopMatrix **, вызывающее ошибку, или сообщение об ошибке только размывается после ** DrawObject **? В Fedora вам может понадобиться пакет lib4vl-devel и/или патч (обновление) MESA. Кажется маловероятным, что у Mesa будет зависимость для кодирования цветового пространства, но, возможно, стоит попробовать. –
GDB сообщает мне, что это 'glPopMatrix()', который вызывает ошибку msg. – karlphillip