00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00033 #include <openvideo/nodes/GLUTSink.h>
00034 #include <openvideo/openVideo.h>
00035
00036 #ifdef ENABLE_GLUTSINK
00037
00038 #include <openvideo/State.h>
00039 #include <openvideo/Manager.h>
00040
00041 #include <GL/gl.h>
00042 #include <GL/glut.h>
00043 #include <GL/glu.h>
00044
00045 #if defined(WIN32)&&(_MSC_VER>=1400)
00046
00047
00048 BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
00049 #endif //WIN32
00050
00051 #include <ace/OS.h>
00052 #include <ace/Thread.h>
00053 #include <ace/Condition_Thread_Mutex.h>
00054 #include <ace/Thread_Mutex.h>
00055 #include <ace/Mutex.h>
00056
00057 #include <iostream>
00058
00059 #if defined(OV_IS_WINXP) && !defined(_IS_KLIMTES_)
00060 #pragma comment(lib,"opengl32.lib")
00061 #pragma comment(lib,"glu32.lib")
00062 #pragma comment(lib,"glut32.lib")
00063 #endif
00064
00065 using namespace openvideo;
00066
00067 bool GLUTSink::isGlutThread=false;
00068 std::vector<GLUTSink*> GLUTSink::glutSinks;
00069 bool GLUTSink::glutRedraw=false;
00070
00071
00072 GLUTSink::GLUTSink()
00073 {
00074 name = typeName = "GLUTSink";
00075 state=NULL;
00076 originX=originY=0;
00077 width=height=0;
00078 updateVideo=false;
00079 internalFormat=0;
00080 glContext=NULL;
00081 updateCtr = 0;
00082 #ifdef LINUX
00083 dsp=NULL;
00084 #endif
00085
00086 }
00087
00088 #ifdef WIN32
00089 HGLRC
00090 GLUTSink::getGLContext()
00091 {
00092 return glContext;
00093 }
00094
00095 HDC
00096 GLUTSink::getDeviceHandle()
00097 {
00098 return dc;
00099 }
00100 #endif
00101
00102 #ifdef LINUX
00103 GLXContext
00104 GLUTSink::getGLContext()
00105 {
00106 return glContext;
00107 }
00108
00109 GLXDrawable
00110 GLUTSink::getDeviceHandle()
00111 {
00112 return dc;
00113 }
00114
00115 Display*
00116 GLUTSink::getDisplay() {
00117 return dsp;
00118 }
00119 #endif
00120
00121 void
00122 GLUTSink::initPixelFormats()
00123 {
00124
00125
00126
00127
00128
00129 this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_R8G8B8));
00130 this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_B8G8R8));
00131 this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_R8G8B8X8));
00132 this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_B8G8R8X8));
00133 this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_L8));
00134 }
00135
00136 GLUTSink::~GLUTSink()
00137 {
00138 }
00139
00140
00141 void*
00142 GLUTSink::mainLoop(void *)
00143 {
00144
00145 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
00146
00147
00148
00149
00150 for(int i=0;i<(int)GLUTSink::glutSinks.size();i++)
00151 {
00152 GLUTSink *glutSink=GLUTSink::glutSinks[i];
00153 glutInitWindowPosition (glutSink->originX, glutSink->originY );
00154 int w,h;
00155 if(glutSink->width==0)
00156 w=1;
00157 else
00158 w=glutSink->width;
00159 if( glutSink->height==0)
00160 h=1;
00161 else
00162 h=glutSink->height;
00163 glutInitWindowSize (w,h);
00164 glutSink->winHandle=glutCreateWindow(glutSink->getName());
00165 glutDisplayFunc(GLUTSink::mainDisplayFunc);
00166 glutIdleFunc(GLUTSink::idleFunc);
00168 #ifdef WIN32
00169 glutSink->glContext=wglGetCurrentContext();
00170 glutSink->dc=wglGetCurrentDC();
00171 #endif
00172 #ifdef LINUX
00173 glutSink->dc=glXGetCurrentDrawable();
00174 glutSink->dsp=glXGetCurrentDisplay();
00175 glutSink->glContext=glXGetCurrentContext();
00176 #endif
00177
00179
00180 glEnable(GL_TEXTURE_2D);
00181 long data_size = 4 * sizeof(GLubyte) * TEXTURE_WIDTH * TEXTURE_HEIGHT;
00182 GLubyte *data = (GLubyte*)malloc(data_size);
00183 memset(data, 0xFF, data_size);
00184 glGenTextures(1, &glutSink->video_texture_id);
00185 glBindTexture(GL_TEXTURE_2D, glutSink->video_texture_id);
00186 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00187 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00188 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00189 glTexImage2D(GL_TEXTURE_2D, 0, glutSink->internalFormat, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
00190 glutSink->format, GL_UNSIGNED_BYTE, data);
00191
00192 glDisable(GL_TEXTURE_2D);
00193 free(data);
00195 }
00196
00197
00198
00199 glutMainLoop();
00200
00201 return 0;
00202 }
00203
00204 void
00205 GLUTSink::init()
00206 {
00207 Manager::getInstance()->getLogger()->logEx("OpenVideo: init GLUTSink '%s' \n",name.c_str());
00208
00209
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 switch(curPixelFormat)
00239 {
00240 case FORMAT_R8G8B8:
00241 format=GL_RGB;
00242 internalFormat=3;
00243 break;
00244
00245 case FORMAT_B8G8R8:
00246 format=GL_BGR_EXT;
00247 internalFormat=3;
00248 break;
00249
00250 case FORMAT_R8G8B8X8:
00251 format=GL_RGBA;
00252 internalFormat=4;
00253 break;
00254
00255 case FORMAT_B8G8R8X8:
00256 format=GL_BGRA_EXT;
00257 internalFormat=4;
00258 break;
00259
00260
00261
00262
00263
00264
00265
00266 case FORMAT_L8:
00267 format=GL_LUMINANCE;
00268 internalFormat=GL_LUMINANCE8;
00269 break;
00270
00271 default:
00272 Manager::getInstance()->getLogger()->logEx("GL_TEXTURE_2D_Sink does not suppport the current pixel format %s\n",
00273 (PixelFormat::FormatToString(curPixelFormat)).c_str());
00274 exit(-1);
00275
00276 }
00277
00278
00279
00280 if(inputs.size()<=0)
00281 return;
00282 state=this->inputs[0]->getState();
00283 if(state)
00284 {
00285 this->width=state->width;
00286 this->height=state->height;
00287
00288 flip_h = false;
00289 flip_v = true;
00290
00291 float u_rt = (float)width / TEXTURE_WIDTH;
00292 float v_rt = (float)height / TEXTURE_HEIGHT;
00293
00294 t_u0 = (flip_h ? u_rt : 0 );
00295 t_u1 = (flip_h ? 0 : u_rt);
00296 t_v0 = (flip_v ? v_rt : 0 );
00297 t_v1 = (flip_v ? 0 : v_rt);
00298
00299 GLUTSink::glutSinks.push_back(this);
00300 }
00301 }
00302
00303 void
00304 GLUTSink::start()
00305 {
00306 Manager::getInstance()->getLogger()->log("GLUTSink::start()\n");
00307 if(!GLUTSink::isGlutThread){
00308
00309 GLUTSink::isGlutThread=true;
00310 ACE_hthread_t* threadHandle = new ACE_hthread_t();
00311 if(ACE_Thread::spawn((ACE_THR_FUNC)GLUTSink::mainLoop,
00312 0,
00313 THR_NEW_LWP|THR_JOINABLE,
00314 0,
00315 threadHandle,
00316 0,
00317 0,
00318 0
00319 )==-1)
00320 {
00321 Manager::getInstance()->getLogger()->log("Error in spawning thread\n");
00322 }
00323 }
00324 }
00325
00326
00327 void
00328 GLUTSink::process()
00329 {
00330 if(!state)
00331 return;
00332
00333 if(Buffer* buffer = state->getCurrentBuffer())
00334 bufferSychronizer.assign(buffer);
00335 }
00336
00337
00338 void
00339 GLUTSink::updateTexture()
00340 {
00341
00342
00343 if(Buffer* buffer = bufferSychronizer.getLocked())
00344 {
00345
00346
00347 if(updateCtr != buffer->getUpdateCounter())
00348 {
00349 updateCtr = buffer->getUpdateCounter();
00350 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00351 glEnable(GL_TEXTURE_2D);
00352 glBindTexture(GL_TEXTURE_2D, video_texture_id);
00353 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
00354 width,height, this->format, GL_UNSIGNED_BYTE,
00355 (void*)buffer->getPixels());
00356 glDisable(GL_TEXTURE_2D);
00357
00358 }
00359 else
00360 {
00361
00362 }
00363
00364 buffer->unlock();
00365 }
00366 }
00367
00368
00369 void
00370 GLUTSink::redraw()
00371 {
00372
00373 glPushMatrix();
00374 glMatrixMode(GL_PROJECTION);
00375 glPushMatrix();
00376 glLoadIdentity();
00377 glMatrixMode(GL_MODELVIEW);
00378 glLoadIdentity();
00379 glPushAttrib(GL_ALL_ATTRIB_BITS);
00380 glDisable(GL_DEPTH_TEST);
00381 glDepthMask(GL_FALSE);
00382 glDisable(GL_LIGHTING);
00383 glDisable(GL_ALPHA_TEST);
00384 glDisable(GL_BLEND);
00386
00387 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00388 glEnable(GL_TEXTURE_2D);
00389
00390
00391 glBindTexture(GL_TEXTURE_2D, video_texture_id);
00392 glBegin(GL_QUADS);
00393
00394 glTexCoord2f(t_u0,t_v0); glVertex3f(-1.0f, -1.0f, 0.0f);
00395 glTexCoord2f(t_u1,t_v0); glVertex3f( 1.0f, -1.0f, 0.0f);
00396 glTexCoord2f(t_u1,t_v1); glVertex3f( 1.0f, 1.0f, 0.0f);
00397 glTexCoord2f(t_u0,t_v1); glVertex3f(-1.0f, 1.0f, 0.0f);
00398 glEnd();
00399
00400 glDisable(GL_TEXTURE_2D);
00401
00403 glPopAttrib();
00404 glMatrixMode(GL_PROJECTION);
00405 glPopMatrix();
00406 glMatrixMode(GL_MODELVIEW);
00407 glPopMatrix();
00408 }
00409
00410 void
00411 GLUTSink::idleFunc()
00412 {
00413 glutPostRedisplay();
00414 }
00415
00416 void
00417 GLUTSink::mainDisplayFunc()
00418 {
00419 if(Manager::getInstance()->glContextChanged)
00420
00421 {
00422 printf("GLUTSINK::try to set new gl context \n");
00423 if((int)(GLUTSink::glutSinks.size())>0)
00424 {
00425 #ifdef WIN32
00426 bool hasGLContext=wglMakeCurrent(GLUTSink::glutSinks[0]->getDeviceHandle(),GLUTSink::glutSinks[0]->getGLContext());
00427 #endif
00428 #ifdef LINUX
00429 bool hasGLContext=glXMakeCurrent(GLUTSink::glutSinks[0]->getDisplay(),
00430 GLUTSink::glutSinks[0]->getDeviceHandle(),
00431 GLUTSink::glutSinks[0]->getGLContext());
00432 #endif
00433
00434 if(hasGLContext)
00435 Manager::getInstance()->getLogger()->logEx("OpenVideo: successfully set new glContext in GLUTSink thread\n") ;
00436 else{
00437 Manager::getInstance()->getLogger()->logEx("OpenVideo: couldn't set new glContext\n");
00438 return;
00439 }
00440 }
00441 Manager::getInstance()->glContextChanged=false;
00442 }
00443
00444 int size=(int)GLUTSink::glutSinks.size();
00445 for (int i=0;i<size;i++)
00446 {
00447 glutSetWindow(glutSinks[i]->winHandle);
00448 glutSinks[i]->updateTexture();
00449 glutSinks[i]->redraw();
00450 }
00451
00452 glutSwapBuffers();
00453
00454 }
00455
00456 #endif //ENABLE_GLUTSINK