[OpenGL/C++] glDrawPixels met 0,5 FPS

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
Beste Tweakers,

ik ben recentelijk weer met openGL begonnen om een berekening te kunnen visualiseren, immers heb ik hier een stukje deinterlacing gedaan en ik wil het resultaat rechtstreeks naar mijn monitor sturen middels openGL.

Ik heb het basis principe al en het werkt ook, maar ik krijg maar 1 fps.

Ik zal even kort laten zien wat ik doe;

C++: simpleOpenGL.cpp
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
void runTest(int argc, char** argv)
{
   // Create GL context
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_LUMINANCE);
   glutInitWindowSize(window_width, window_height);
   glutCreateWindow("YUV-Viewer");
   // register callbacks
   glutDisplayFunc(display);
   // start rendering mainloop
   glutMainLoop();
}
////////////////////////////////////////////////////////////////////////////////
//! Initialize GL
////////////////////////////////////////////////////////////////////////////////
void initGL()
{
   // initialize necessary OpenGL extensions
   glewInit();
   // default initialization
   glClearColor(0.0, 0.0, 0.0, 1.0);
   glDisable(GL_DEPTH_TEST);
   // viewport
   glViewport(0, 0, window_width, window_height);
   // projection
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(60.0, (GLfloat) window_width / (GLfloat) window_height, 0.1, 10.0);
}
////////////////////////////////////////////////////////////////////////////////
//! Display callback
////////////////////////////////////////////////////////////////////////////////
void display()
{
   glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
   // set view matrix
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   //glRasterPos2i(1280, 720);
   //glPixelZoom(1.0, -1.0);
   glDrawPixels(window_width, window_height, GL_LUMINANCE, GL_BYTE, yData);
   glutSwapBuffers();
   glutPostRedisplay();
}


De pixelwaardes worden in een apparte methode ingelezen en de ruwe Y-component waardes worden in de unsigned char* yData[1280 * 720 * sizeof(char)] geplaatst; Dit gebeurt nu nog maar 1malig, ten tijde van het starten van de applicatie.

Het plaatje komt keurig op mijn scherm terecht (wel horizontaal gespiegeld, maar das (nog) geen probleem).

Het probleem is dat ik maar 1 fps heb; Ik heb dit gecontroleerd middels een timertje en hij komt maar 1 keer per seconde in mijn Display callback functie.

Daarbij draait de CPU ook nog eens op 100%.

Weet er iemand een snellere/efficientere mannier om een hogere fps te krijgen, want dat moet toch gewoon kunnen ?

Daarbij wil ik nog ff vermelden dat ik op Ubuntu 8.10 draai en dus niet de beschikking heb over DirectX oid. ;)

Edit:
Ik heb natuurlijk onderzoek gedaan:
http://lurkertech.com/lg/ogl.video.html
http://www.opengl.org/wik...GL_in_Linux:_GLX_and_Xlib
http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
http://www.dranger.com/ffmpeg/tutorial01.html

De laatste gaan voornamelijk over de Codecks e.d., daar heb ik tot nu toe weinig aan; Immers heb ik ruwe video.

[ Voor 5% gewijzigd door Matis op 05-03-2009 13:24 . Reden: Extra tekst, Typo's ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • FireDrunk
  • Registratie: November 2002
  • Laatst online: 16:25
Het lijkt dat je loop alle CPU opvreet? Kun je die ook posten?

Even niets...


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
thijs_cramer schreef op donderdag 05 maart 2009 @ 13:22:
Het lijkt dat je loop alle CPU opvreet? Kun je die ook posten?
Sure, alleen is er weinig meer dan deze code. hieronder is de mainloop van het hele progje; Meer zit er echt niet in de cpp file.
C++: SimpleOpenGL.cpp
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
const unsigned int window_width = 1280;
const unsigned int window_height = 720;
unsigned char* yData;
char *yDataTemp;
void runTest(int argc, char** argv);
// GL functionality
void initGL();
// rendering callbacks
void display();
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
   std::ifstream yuvReader;
   int size = 1280 * 720;
   yData = (unsigned char*) calloc(size, sizeof(char));
   yDataTemp = (char*) calloc(size, sizeof(char));
   yuvReader.open("out.yuv", std::ios::in);
   if (yuvReader.is_open())
   {
      printf("read \n");
      yuvReader.read(yDataTemp, size);
      for (int i = 0; i < size; i++)
      {
         yData[i] = ((unsigned char) yDataTemp[i] >> 1);
      }
      free(yDataTemp);
   }
   else
   {
      printf("teh suck \n");
      exit(0);
   }
   runTest(argc, argv);
   free(yData);
   exit(0);
}


Edit:
Wat de mainloop doet is het openen van een yuv bestandje en de Y-componenten uitlezen; Deze moeten van een char naar een uchar, dat doet het forloopje wanneer dat in RAM zit begin de openGL init en executie.

Nja natuurlijk nog wat includes, maar verder geen extra calls meer!

[ Voor 7% gewijzigd door Matis op 05-03-2009 13:28 . Reden: Extra tekst, Typo's ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Slackware
  • Registratie: Juni 2001
  • Niet online
Dat CPU gebruik van 100% komt door je display functie, je roept meteen een glutPostRedisplay aan, die roept je display functie weer aan, etc etc. Je zou met bijvoorbeeld een simpele sleep voor aanroep van glutPostRedisplay de CPU load kunnen laten afnemen.

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
Slackware schreef op donderdag 05 maart 2009 @ 13:28:
Dat CPU gebruik van 100% komt door je display functie, je roept meteen een glutPostRedisplay aan, die roept je display functie weer aan, etc etc. Je zou met bijvoorbeeld een simpele sleep voor aanroep van glutPostRedisplay de CPU load kunnen laten afnemen.
Natuurlijk zou dat kunnen, die 100% CPU vind ik niet erg, maar wel het feit dat ik maar 1fps kan halen;

Ik vind net wel een stukje op internet dat het heeft over een "GLhandleARB" waar een shader wordt gemaakt en geladen.
Alleen heb ik daar helemaal geen kaas van gegeten, maar misschien is het wel handig om me daar in te verdiepen.

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Slackware schreef op donderdag 05 maart 2009 @ 13:28:
Dat CPU gebruik van 100% komt door je display functie, je roept meteen een glutPostRedisplay aan, die roept je display functie weer aan, etc etc. Je zou met bijvoorbeeld een simpele sleep voor aanroep van glutPostRedisplay de CPU load kunnen laten afnemen.
Nee hoor, je post een re-display bij glut, die wordt niet per se meteen uitgevoerd. Bovendien moet je ook uuuuren op je bufferswap wachten.

Ik denk dat je je display mode niet op luminance moet zetten; waarschijnlijk wordt dat niet ondersteunt in hardware en krijg je een driver software fallback (vandaar de 100% cpu). Gebruik gewoon GLUT_RGBA.

[ Voor 16% gewijzigd door Zoijar op 05-03-2009 14:00 ]


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
Met de regel:
C++:
1
glutInitDisplayMode(GLUT_LUMINANCE | GL_DOUBLE);

timelapse: 1.643557
timelapse: 1.642986
timelapse: 1.653779
100% CPU van 1 core;

Met de regel:
C++:
1
glutInitDisplayMode(GLUT_RGBA | GL_DOUBLE);

timelapse: 1.632087
timelapse: 1.632861
timelapse: 1.637366
timelapse: 1.638544
100% CPU van 1 core;

Geen significant verschil, wel weet ik dat het swappen van buffers superlang duurt, maar ik *moet* mijn frames op een of andere manier in openGL krijgen ;)

Met een simpele
C++:
1
2
3
4
5
6
glBegin(GL_QUADS); // Start Drawing Quads
    glVertex3f(-1.0f, 1.0f, 0.0f); // Left And Up 1 Unit (Top Left)
    glVertex3f(1.0f, 1.0f, 0.0f); // Right And Up 1 Unit (Top Right)
    glVertex3f(1.0f, -1.0f, 0.0f); // Right And Down One Unit (Bottom Right)
    glVertex3f(-1.0f, -1.0f, 0.0f); // Left And Down One Unit (Bottom Left)
glEnd();

krijg ik hetvolgende
timelapse: 0.000984
timelapse: 0.000579
timelapse: 0.000579
Wat neerkomt op 2000 fps; en dan neem ik aan dat het printf-en van de timelapse nog langer duurt dan het frame zelf.

een
C++:
1
glDrawPixels(window_width / 2, window_height / 2, GL_LUMINANCE, GL_BYTE, yData);

geeft een timelapse van een kwart van de totale timelapse bij een volledige frame, wat dus wel kan kloppen!
timelapse: 0.414948
timelapse: 0.505810
timelapse: 0.363572
timelapse: 0.367089

[ Voor 56% gewijzigd door Matis op 05-03-2009 15:09 . Reden: Extra tekst, Typo's ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:54
Om terug te komen op wat Zoijar ook zei: waarschijnlijk ondersteunt de OpenGL driver geen hardwarematige conversie van RGB naar YUV. Die YUV pixels worden dan in software geconverteerd naar RGB en dat is natuurlijk niet snel. Vandaar dat je je pixel data gewoon eerst naar RGB moet converteren.

Wel vreemd trouwens, want volgens mij zijn er wel programma's als mplayer die OpenGL als renderer gebuiken en dan is YUV conversie nooit een probleem...

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
Soultaker schreef op donderdag 05 maart 2009 @ 15:09:
Wel vreemd trouwens, want volgens mij zijn er wel programma's als mplayer die OpenGL als renderer gebuiken en dan is YUV conversie nooit een probleem...
Precies, mplayer draait op OpenGL renderer en daar speel ik de 720p's gewoon realtime af op cpu-kracht.

Ik zal wel eens een RGB buffer aanmaken.

Edit:
Wat een geniale opmerking van je Soultaker.

C++:
1
glDrawPixels(window_width, window_height, GL_RGB, GL_BYTE, yData); // yData --> 3 x dezelfde waarde voor RGB voor elke Y component

timelapse: 0.020946
timelapse: 0.020819
timelapse: 0.021067
timelapse: 0.021649

[ Voor 26% gewijzigd door Matis op 05-03-2009 15:18 . Reden: Extra tekst, Typo's ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja, drawpixels is sowieso traag. Hoe dat normaal wordt gedaan is door te texture mappen en je data in een texture te laden (met pixel buffer objects (PBO) voor extra snelheid vaak). Maar je kan beginnen met gewoon glTexImage2D. Dit moet veel sneller kunnen. In principe kan je van geheugen naar je video kaart zo'n 2.5-3.0 GB/s halen als je het goed doet, en het afbeelden kost amper tijd. Een HD luminance frame moet in 1 a 2 ms makkelijk te doen zijn (500 FPS)

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Topicstarter
Zoijar schreef op donderdag 05 maart 2009 @ 15:20:
Ja, drawpixels is sowieso traag. Hoe dat normaal wordt gedaan is door te texture mappen en je data in een texture te laden (met pixel buffer objects (PBO) voor extra snelheid vaak). Maar je kan beginnen met gewoon glTexImage2D. Dit moet veel sneller kunnen. In principe kan je van geheugen naar je video kaart zo'n 2.5-3.0 GB/s halen als je het goed doet, en het afbeelden kost amper tijd. Een HD luminance frame moet in 1 a 2 ms makkelijk te doen zijn (500 FPS)
Klopt, dat zag ik ook pas later, maar ik wilde het eerst op de makkelijkere manier proberen te klaren door drawPixels.

Ik zal nu eens kijken hoe het zit met die glTexImage2D functie.

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:54
toaomatis schreef op donderdag 05 maart 2009 @ 15:14:
Precies, mplayer draait op OpenGL renderer en daar speel ik de 720p's gewoon realtime af op cpu-kracht.
Mja, als ik de mplayer broncode er eens bijpak dan lijkt daar ook niet echt een mooie manier te zijn om de YUV conversie te doen. Een YUV pixel format wordt in ieder geval niet gebruikt... wel zijn er 1001 driver-specifieke hacks om de conversie d.m.v. pixelshaders enzo uit te voeren, wat natuurlijk wel op de grafische kaart gebeurt. Misschien is de conclusie dus dat er geen simpele manier is om de conversie efficiënt met OpenGL te doen en dan ben je wellicht beter af door 'm zelf te doen.

Voor geïnteresseerden, de relevante mplayer code:
gl_common.h
gl_common.c
vo_gl.c
vo_gl2.c

mplayer rendert trouwens ook in een texture, die gewoon als quad getekend wordt. Bij het renderen lijkt dan een pixel shader gebruikt te worden voor de YUV->RGB conversie (zie glEnableYUVConversion() b.v.).

[ Voor 7% gewijzigd door Soultaker op 05-03-2009 15:45 ]

Pagina: 1