glsink with correct threading support
authorGernot Ziegler <gz@lysator.liu.se>
Fri, 31 Oct 2003 16:40:20 +0000 (16:40 +0000)
committerGernot Ziegler <gz@lysator.liu.se>
Fri, 31 Oct 2003 16:40:20 +0000 (16:40 +0000)
Original commit message from CVS:
glsink with correct threading support

sys/glsink/ARB_multitexture.h
sys/glsink/gstgl_nvimage.c
sys/glsink/gstgl_rgbimage.c
sys/glsink/gstglsink.c
sys/glsink/gstglxwindow.c
sys/glsink/regcomb_yuvrgb.c

index af6de323e5f8a925f8a6a52933bef2452e68b7dc..36dcf011ed66aeba23a83c9db58ab86698977be2 100644 (file)
@@ -201,7 +201,9 @@ int CheckForARBMultitextureSupport(void) {
     int i, pos=0;\r
     int maxpos=strlen(search)-1;\r
     char extensions[10000];\r
+    printf("Getting GLstring, context is %p\n",  glXGetCurrentContext());\r
     strcpy(extensions,(const char *)glGetString(GL_EXTENSIONS));\r
+    printf("Examinig GLstring\n");\r
     int len=strlen(extensions);\r
     for ( i=0; i<len; i++) {\r
         if ((i==0) || ((i>1) && extensions[i-1]==' ')) {\r
index e7ee1b624ed6194134b40fea1ce5ec6bc574e630..79caf2be6c6b660d345f327efbf7e86ffd6c0026 100644 (file)
@@ -103,7 +103,7 @@ gboolean
 gst_gl_nvimage_check_xvideo ()
 {
   //int ver, rel, req, ev, err;
-  
+  printf("Checking NVidia OpenGL extensions.\n");
   if (!GL_ARB_multitexture_Init()) return FALSE;
   if (!GL_EXT_paletted_texture_Init()) return FALSE;
   if (!GL_NV_register_combiners_Init()) return FALSE;
@@ -127,9 +127,13 @@ gst_gl_nvimage_get_caps (GstImageInfo *info)
   GstCaps *caps = NULL;
   GstGLImageInfo *xinfo = gst_gl_nvimage_info (info);
   
-  g_warning("nvimage get caps called !\n");
+  g_warning("nvimage get caps called, context %p !\n", glXGetCurrentContext());
   /* we don't handle these image information */
-  if (xinfo == NULL) return NULL;
+  if (xinfo == NULL) 
+    {
+      printf("Invalid XInfo struct !\n");
+      return NULL;
+    }
 
   if (gst_gl_nvimage_check_xvideo () == FALSE)
   {
@@ -138,7 +142,7 @@ gst_gl_nvimage_get_caps (GstImageInfo *info)
   }
 
   caps = gst_caps_append (caps, GST_CAPS_NEW (
-                                             "xvimage_caps",
+                                             "nvimage_caps",
                                              "video/x-raw-yuv",
                                              "format",  GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y', 'V', '1', '2')),
                                              "width",   GST_PROPS_INT_RANGE (0, 1024),
@@ -201,7 +205,7 @@ gst_gl_nvimage_get_image (GstImageInfo *info, GstImageConnection *conn)
   if (nvconn == NULL) return NULL;
 
   // I should also check the current GLX context ! 
-  // Ah, Don't have to, I am guarantueed to always be in the same thread
+  // Ah, Don't have to, I am guarantueed to be in the same thread as put_image
 
   image = g_new0(GstNvImage, 1);
 
@@ -242,16 +246,19 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image)
   g_assert (xinfo != NULL);
   
   // both upload the video, and redraw the screen
+  //glClearColor(0,0.5, 0.3,1.0); // a test color
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glTranslatef(0.0, 0.0, -25.0);
-  glEnable(GL_TEXTURE_2D);
+  glTranslatef(0.0, 0.0, -5.0);
+  glDisable(GL_TEXTURE_2D);
 
   if (xinfo->info.demo)
     {
+      //g_print("Putting image, context is %p\n", glXGetCurrentContext());
 
+      glTranslatef(0.0, 0.0, -5.0); // make it avoid the clipping plane, zoom 2.0 instead
       glRotatef(180.0*sin(xinfo->rotX),1,0,0);
       glRotatef(180.0*cos(xinfo->rotY),0,1,0);
 
@@ -261,10 +268,10 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image)
       glScalef(zoom,zoom,zoom); 
       //glScalef(0.1,0.1,0.1); 
 
-      if (xinfo->zoom > 1.0)
+      if (xinfo->zoom > 2.0)
        xinfo->zoomdir = -0.01;
 
-      if (xinfo->zoom < 0.5)
+      if (xinfo->zoom < 1.0)
        xinfo->zoomdir = 0.01;
 
       xinfo->zoom += xinfo->zoomdir;
@@ -289,28 +296,29 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image)
   glBegin(GL_QUADS);
 
   float aspect = img_width/(float)img_height;
-  float hor = 4 * aspect;
+  float hor = aspect;
 
+  //g_print("Drawing vertices, context is %p\n", glXGetCurrentContext());
   glNormal3f(0, -1, 0);
   glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,0); 
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0); 
   glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,0); 
-  glVertex3f(-hor,4,0);
+  glVertex3f(-hor,1,0);
 
   glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,ymax); 
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,ymax); 
   glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,ymax); 
-  glVertex3f(-hor,-4,0);
+  glVertex3f(-hor,-1,0);
 
   glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,ymax); 
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,ymax); 
   glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,ymax); 
-  glVertex3f(hor,-4,0);
+  glVertex3f(hor,-1,0);
 
   glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,0); 
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,0); 
   glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,0); 
-  glVertex3f(hor,4,0);
+  glVertex3f(hor,1,0);
 
   glEnd();
 
@@ -339,7 +347,7 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image)
       if (outfile != NULL)
        {
          fprintf(outfile, "P6\n"); 
-         fprintf(outfile,"# created by raw_zb\n"); 
+         fprintf(outfile,"# created by glsink from GStreamer\n"); 
          fprintf(outfile,"%d %d\n",img_width,img_height); 
          fprintf(outfile,"255\n"); 
          fwrite(cap_image_data2, sizeof(char), img_width*img_height*3, outfile);
@@ -380,6 +388,7 @@ gst_gl_nvimage_open_conn (GstImageConnection *conn, GstImageInfo *info)
     Ywidth = TEX_XSIZE; Yheight = TEX_YSIZE;  UVwidth = TEX_XSIZE/2; UVheight = TEX_YSIZE/2;
     Initialize_Backend(Ywidth,Yheight,UVwidth,UVheight,GL_LINEAR);
   }
+  g_print("Done\n");
 }
 
 static void
index 68a1329a0a2df56cd7c316e3a738a8c0bb99689f..a09e7a256ef67f7db7ae085aa2cad8e5fd584e33 100644 (file)
@@ -98,6 +98,7 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info)
   XImage *ximage;
   GstGLImageInfo *xinfo = gst_gl_rgbimage_info (info);
   
+  g_warning("rgbimage get caps called, context %p, endianness %d !\n", glXGetCurrentContext(), G_BIG_ENDIAN);
   /* we don't handle this image information */
   if (xinfo == NULL) return NULL;
 
@@ -122,9 +123,9 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info)
                    "format",          GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
                    "depth",        GST_PROPS_INT(24),
                    "bpp",          GST_PROPS_INT(24),
-                   "red_mask",        GST_PROPS_INT(0xff0000),
+                   "red_mask",        GST_PROPS_INT(0xff),
                    "green_mask",        GST_PROPS_INT(0xff00),
-                   "blue_mask",        GST_PROPS_INT(0xff),
+                   "blue_mask",        GST_PROPS_INT(0xff0000),
                    "endianness",  GST_PROPS_INT(G_BIG_ENDIAN), /*= 1234/4321 (INT) <- endianness */
                    
                    "width",      GST_PROPS_INT_RANGE (0, TEX_XSIZE), /* can't have videos larger than TEX_SIZE */
@@ -133,7 +134,7 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info)
     XDestroyImage (ximage);
   }
   
-  GST_DEBUG ("GL_RGBImage: returning caps at %p", caps);
+  printf ("GL_RGBImage: returning caps at %p", caps);
   return caps;
 }
 
@@ -245,13 +246,13 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image)
 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glTranslatef(0.0, 0.0, -25.0);
+  glTranslatef(0.0, 0.0, -5.0);
 
   glEnable(GL_TEXTURE_2D);
 
   if (xinfo->info.demo)
     {
-
+      glTranslatef(0.0, 0.0, -5.0); // make it avoid the clipping plane, zoom 2.0 instead
       glRotatef(180.0*sin(xinfo->rotX),1,0,0);
       glRotatef(180.0*cos(xinfo->rotY),0,1,0);
 
@@ -259,12 +260,11 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image)
       xinfo->rotY -= 0.015;
       float zoom = xinfo->zoom;
       glScalef(zoom,zoom,zoom); 
-      //glScalef(0.1,0.1,0.1); 
 
-      if (xinfo->zoom > 1.0)
+      if (xinfo->zoom > 2.0)
        xinfo->zoomdir = -0.01;
 
-      if (xinfo->zoom < 0.5)
+      if (xinfo->zoom < 1.0)
        xinfo->zoomdir = 0.01;
 
       xinfo->zoom += xinfo->zoomdir;
@@ -278,7 +278,7 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image)
   ymax = (float)im->conn->h/TEX_YSIZE;
 
   float aspect = img_width/(float)img_height;
-  float hor = 4 * aspect;
+  float hor = aspect;
 
   glColor4f(1,1,1,1);
   glBegin(GL_QUADS);
@@ -286,16 +286,16 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image)
   glNormal3f(0, -1, 0);
   
   glTexCoord2f(xmax, 0);
-  glVertex3f(hor,4,0);
+  glVertex3f(hor,1,0);
 
   glTexCoord2f(0, 0);
-  glVertex3f(-hor,4,0);
+  glVertex3f(-hor,1,0);
 
   glTexCoord2f(0, ymax);
-  glVertex3f(-hor,-4,0);
+  glVertex3f(-hor,-1,0);
 
   glTexCoord2f(xmax, ymax);
-  glVertex3f(hor,-4,0);
+  glVertex3f(hor,-1,0);
   glEnd();
 
   if (xinfo->info.dumpvideo)
index 8a4449fafb9eaa7654c5ae184ec09baba2df2a79..30268d31c5a8664730823fbe9ad45417d864e89f 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/*
+<ds-work> your element belongs to a scheduler, which calls some functions from the same thread
+<ds-work> all the other functions could be called from any random thread
+<gernot> ds-work: which are the "some" function in that case ? 
+<gernot> It is quite costly to do glXGetCurrentContext for every function call.
+<ds-work> _chain, -get, _loop
+*/
+
 #include <config.h>
 #include <string.h>
 
@@ -140,6 +148,8 @@ extern GstImagePlugin*              get_gl_rgbimage_plugin          (void);
 extern GstImagePlugin*                 get_gl_nvimage_plugin           (void);
 /* default output */
 extern void                    gst_glxwindow_new               (GstGLSink *sink);
+extern void                    gst_glxwindow_hook_context              (GstImageInfo *info);
+extern void                    gst_glxwindow_unhook_context            (GstImageInfo *info);
 
 
 static GstPadTemplate *sink_template;
@@ -257,9 +267,12 @@ gst_glsink_init (GstGLSink *sink)
   sink->conn = NULL;
   
   /* do initialization of default hook here */
-  gst_glxwindow_new (sink);
+  gst_glxwindow_new (sink); 
+  //printf("GLSink_init: Current context %p\n", glXGetCurrentContext());
+  gst_glxwindow_unhook_context(sink->hook);
 }
 
+/** frees the temporary connection that tests the window system capabilities */
 static void
 gst_glsink_release_conn (GstGLSink *sink)
 {
@@ -357,16 +370,21 @@ gst_glsink_get_bufferpool (GstPad *pad)
 static gboolean
 gst_glsink_set_caps (GstGLSink *sink, GstCaps *caps)
 {
-  //g_warning("in set caps!\n");
+  g_warning("in glsink set caps!\n");
+  printf("Getting GLstring, context is %p\n",  glXGetCurrentContext());
+    
   GList *list = ((GstGLSinkClass *) G_OBJECT_GET_CLASS (sink))->plugins;
   GstImageConnection *conn = NULL;
   while (list)    
   {
+  printf("AGetting GLstring, context is %p\n",  glXGetCurrentContext());
     GstImagePlugin *plugin = (GstImagePlugin *) list->data;
     if ((conn = plugin->set_caps (sink->hook, caps)) != NULL)
     {
-      gst_glsink_release_conn (sink);
+      //gst_glsink_release_conn (sink);
+  printf("BGetting GLstring, context is %p\n",  glXGetCurrentContext());
       sink->conn = conn;
+  printf("CGetting GLstring, context is %p\n",  glXGetCurrentContext());
       sink->plugin = plugin;
       sink->conn->open_conn (sink->conn, sink->hook);
       return TRUE;
@@ -382,9 +400,9 @@ Link the input video sink internally.
 static GstPadLinkReturn
 gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps)
 {
-  fprintf(stderr, "in sinkconnect!\n");
+  g_warning("in glsink sinkconnect!\n");
   GstGLSink *sink;
-  guint32 fourcc, print_format;
+  guint32 fourcc, print_format, result;
 
   sink = GST_GLSINK (gst_pad_get_parent (pad));
 
@@ -392,11 +410,15 @@ gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps)
   if (!GST_CAPS_IS_FIXED (caps))
     return GST_PAD_LINK_DELAYED;
   
+  gst_glxwindow_hook_context(sink->hook);
   /* try to set the caps on the output */
-  if (gst_glsink_set_caps (sink, caps) == FALSE)
-  {
-    return GST_PAD_LINK_REFUSED;
-  }
+  result = gst_glsink_set_caps (sink, caps);
+  gst_glxwindow_unhook_context(sink->hook);
+
+  if (result == FALSE)
+    {
+      return GST_PAD_LINK_REFUSED;
+    }
   
   /* remember width & height */
   gst_caps_get_int (caps, "width", &sink->width);
@@ -418,18 +440,20 @@ gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps)
 static GstCaps *
 gst_glsink_getcaps (GstPad *pad, GstCaps *caps)
 {
-  //g_warning("in get caps!\n");
+  g_warning("in glsink get caps!\n");
   /* what is the "caps" parameter good for? */
   GstGLSink *sink = GST_GLSINK (gst_pad_get_parent (pad));
   GstCaps *ret = NULL;
   GList *list = ((GstGLSinkClass *) G_OBJECT_GET_CLASS (sink))->plugins;
   
+  gst_glxwindow_hook_context(sink->hook);
   while (list)    
   {
     ret = gst_caps_append (ret, ((GstImagePlugin *) list->data)->get_caps (sink->hook));
     list = g_list_next (list);
   }
 
+  gst_glxwindow_unhook_context(sink->hook);
   return ret;
 }
 
@@ -446,9 +470,8 @@ gst_glsink_chain (GstPad *pad, GstData *_data)
   //g_warning("in glsink_chain!\n");
   GstBuffer *buf = GST_BUFFER (_data);
   GstGLSink *sink;
-  //GstClockTime time = GST_BUFFER_TIMESTAMP (buf);
+
   GstBuffer *buffer;
-  //static int frame_drops = 0;
 
   g_return_if_fail (pad != NULL);
   g_return_if_fail (GST_IS_PAD (pad));
@@ -468,7 +491,10 @@ gst_glsink_chain (GstPad *pad, GstData *_data)
   GST_DEBUG ("glsink: clock wait: %llu %u", 
                  GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_SIZE (buf));
 
-#if 0 
+#if 0
+  GstClockTime time = GST_BUFFER_TIMESTAMP (buf);
+  static int frame_drops = 0;
+
   if (sink->clock && time != -1) {
     if (time < gst_clock_get_time(sink->clock))
       {
@@ -500,10 +526,55 @@ gst_glsink_chain (GstPad *pad, GstData *_data)
 
   if (!sink->muted)
   {
+    if (glXGetCurrentContext() == NULL)
+      {
+       printf("Rehooking window !\n");
+       gst_glxwindow_hook_context(sink->hook);
+
+#if 1
+       GST_DEBUG("Initializing OpenGL parameters\n");
+       /* initialize OpenGL drawing */
+       glEnable(GL_DEPTH_TEST);
+       glEnable(GL_TEXTURE_2D);
+       glClearDepth(1.0f);
+       glClearColor(0, 0, 0, 0);
+       
+       glEnable(GL_AUTO_NORMAL); // let OpenGL generate the Normals
+       
+       glDisable(GL_BLEND);
+       glDisable(GL_CULL_FACE);
+       glPolygonMode(GL_FRONT, GL_FILL);
+       glPolygonMode(GL_BACK, GL_FILL);
+       
+       glShadeModel(GL_SMOOTH);
+       glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
+       
+       GstGLImageInfo *window = (GstGLImageInfo *)sink->hook;
+       int w=window->width, h = window->height;
+
+       glViewport(0, 0, (GLint) w, (GLint) h);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       
+       GLfloat aspect = (GLfloat) w / (GLfloat) h;
+       glFrustum(-aspect, aspect, -1.0, 1.0, 5.0, 500.0);
+
+#endif
+       gst_glxwindow_unhook_context(sink->hook);
+       gst_glxwindow_hook_context(sink->hook);
+       glMatrixMode(GL_MODELVIEW);
+#if 0 
+       sink->hook->free_info(sink->hook);
+       printf("Reallocating window brutally !\n");
+       gst_glxwindow_new(sink);
+#endif
+      }
+    
     /* free last_image, if any */
     if (sink->last_image != NULL)
       gst_buffer_unref (sink->last_image);
     if (sink->bufferpool && GST_BUFFER_BUFFERPOOL (buf) == sink->bufferpool) {
+      
       // awful hack ! But I currently have no other solution without changing the API
       sink->hook->demo = sink->demo;
       sink->hook->dumpvideo = sink->dumpvideo;
@@ -522,6 +593,8 @@ gst_glsink_chain (GstPad *pad, GstData *_data)
       sink->last_image = buffer;
       gst_buffer_unref (buf);
     }
+
+    //gst_glxwindow_unhook_context(sink->hook);
   }
   
 }
@@ -687,12 +760,6 @@ plugin_init (GModule *module, GstPlugin *plugin)
   factory = gst_element_factory_new("glsink",GST_TYPE_GLSINK,
                                    &gst_glsink_details);
 
-  if (factory == NULL)
-    {
-      g_warning("DANGER; WILL !\n");
-    }
-
-      g_warning("INIT GST_LITTLE_ENDIAN %d!\n", G_LITTLE_ENDIAN);
   g_return_val_if_fail(factory != NULL, FALSE);
 
   /* this is needed later on in the _real_ init (during a gst-launch) */
index 79b743a02123cd38af88846f94adfef994b97e2d..3f9d3df9058a954ef33327938b7b9c05df1b6944 100644 (file)
@@ -44,6 +44,38 @@ GLfloat LightDiffuse[] = { 0.6, 0.6, 0.6, 1.0 };  /* bluish  diffuse light. */
 GLfloat LightPosition[] = { 1.5, 1.5, 1.5, 0.0 };    /* position */
 
 
+void
+gst_glxwindow_unhook_context(GstImageInfo *info)
+{
+  GstGLImageInfo *window = (GstGLImageInfo *) info;
+
+  if (window->ctx)
+    {
+      if (!glXMakeCurrent(window->dpy, None, NULL))
+        {
+         printf("Could not release drawing context.\n");
+        }
+      else
+         printf("Released drawing context.\n");
+    }
+}
+
+void
+gst_glxwindow_hook_context(GstImageInfo *info)
+{
+  GstGLImageInfo *window = (GstGLImageInfo *) info;
+
+  if (window->ctx && window->win && window->ctx)
+    {
+      if (!glXMakeCurrent(window->dpy, window->win, window->ctx))
+        {
+         printf("Could not acquire GLX drawing context.\n");
+        }
+      else
+         printf("Acquired drawing context.\n");
+    }
+}
+
 static void
 gst_glxwindow_free (GstImageInfo *info)
 {
@@ -92,7 +124,7 @@ gst_glxwindow_callback(GObject *object, GParamSpec *pspec, GstGLImageInfo *data)
       XMapRaised (data->dpy, data->win);
 
       // resize OpenGL
-      //g_warning("resizing in OpenGL");
+      g_warning("resizing in OpenGL");
       glViewport(0, 0, (GLint) w, (GLint) h);
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
@@ -205,7 +237,7 @@ gst_glxwindow_new (GstElement *sink)
   else
     GST_DEBUG ("Sorry, no Direct Rendering possible!\n");
 
-  GST_DEBUG("Initializing OpenGL parameters\n");
+  g_warning("Initializing OpenGL parameters\n");
   /* initialize OpenGL drawing */
   glEnable(GL_DEPTH_TEST);
   //glShadeModel(GL_SMOOTH);
index 0c953c6f0c29481e96118f23eef1bed3234ef8fb..39c86a0f55becb0cc12aeec7c5e5b955e2bcf039 100644 (file)
@@ -325,9 +325,9 @@ void LoadYUVPlanes(GLuint Yhandle, GLuint Uhandle, GLuint Vhandle,
 void Initialize_Backend(unsigned int Ywidth, unsigned int Yheight, unsigned int UVwidth, unsigned int UVheight, GLenum filter) 
 {
   printf("Reinitializing register combiner backend with res %d x %d!\n", Ywidth, Yheight);
-  if (!GL_ARB_multitexture_Init()) exit(0);
-  if (!GL_EXT_paletted_texture_Init()) exit(0);
-  if (!GL_NV_register_combiners_Init()) exit(0);
+  //if (!GL_ARB_multitexture_Init()) exit(0);
+  //if (!GL_EXT_paletted_texture_Init()) exit(0);
+  //if (!GL_NV_register_combiners_Init()) exit(0);
   unsigned char Ypal[768];
   unsigned char Upal[768];
   unsigned char Vpal[768];