[113/906] git-svn-id: svn://svn.wobow.com/GStreamer_playground/gst-plugins-gl@554 93df14bb-0f41-7a43-8087-d3e2a2f0e464

This commit is contained in:
Julien Isorce 2008-06-28 23:28:11 +00:00 committed by Matthew Waters
parent 652914f17b
commit 37a0568858
4 changed files with 147 additions and 77 deletions

View file

@ -29,7 +29,7 @@ static void gst_gl_display_finalize (GObject * object);
static gpointer gst_gl_display_glutThreadFunc (GstGLDisplay* display); static gpointer gst_gl_display_glutThreadFunc (GstGLDisplay* display);
static void gst_gl_display_glutCreateWindow (GstGLDisplay* display); static void gst_gl_display_glutCreateWindow (GstGLDisplay* display);
static void gst_gl_display_glutInitUpload (GstGLDisplay* display); static void gst_gl_display_glutInitUpload (GstGLDisplay* display);
static void gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display); static void gst_gl_display_glutInitDownload (GstGLDisplay *display);
static void gst_gl_display_glutGenerateFBO (GstGLDisplay *display); static void gst_gl_display_glutGenerateFBO (GstGLDisplay *display);
static void gst_gl_display_glutUseFBO (GstGLDisplay *display); static void gst_gl_display_glutUseFBO (GstGLDisplay *display);
static void gst_gl_display_glutUseFBO2 (GstGLDisplay *display); static void gst_gl_display_glutUseFBO2 (GstGLDisplay *display);
@ -110,7 +110,7 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
display->cond_destroyFBO = g_cond_new (); display->cond_destroyFBO = g_cond_new ();
display->cond_create = g_cond_new (); display->cond_create = g_cond_new ();
display->cond_destroy = g_cond_new (); display->cond_destroy = g_cond_new ();
display->cond_download = g_cond_new (); display->cond_init_download = g_cond_new ();
display->cond_initShader = g_cond_new (); display->cond_initShader = g_cond_new ();
display->cond_destroyShader = g_cond_new (); display->cond_destroyShader = g_cond_new ();
@ -366,9 +366,9 @@ gst_gl_display_finalize (GObject *object)
g_cond_free (display->cond_video); g_cond_free (display->cond_video);
display->cond_video = NULL; display->cond_video = NULL;
} }
if (display->cond_download) { if (display->cond_init_download) {
g_cond_free (display->cond_download); g_cond_free (display->cond_init_download);
display->cond_download = NULL; display->cond_init_download = NULL;
} }
if (display->cond_initShader) { if (display->cond_initShader) {
g_cond_free (display->cond_initShader); g_cond_free (display->cond_initShader);
@ -702,9 +702,9 @@ gst_gl_display_glutInitUpload (GstGLDisplay *display)
} }
/* Called by the idle funtion */ /* Called by the gl thread */
static void static void
gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display) gst_gl_display_glutInitDownload (GstGLDisplay *display)
{ {
glutSetWindow (display->glutWinId); glutSetWindow (display->glutWinId);
@ -738,33 +738,61 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->videoTexture, 0); GL_TEXTURE_RECTANGLE_ARB, display->videoTexture, 0);
//setup a second texture to render to switch (display->outputVideo_format)
glGenTextures (1, &display->videoTexture_u); {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_u); case GST_VIDEO_FORMAT_RGBx:
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, case GST_VIDEO_FORMAT_BGRx:
display->outputWidth, display->outputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); case GST_VIDEO_FORMAT_xRGB:
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); case GST_VIDEO_FORMAT_xBGR:
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); case GST_VIDEO_FORMAT_RGBA:
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); case GST_VIDEO_FORMAT_BGRA:
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY:
case GST_VIDEO_FORMAT_AYUV:
//only one attached texture is needed
break;
//attach the second texture to the FBO to renderer to case GST_VIDEO_FORMAT_I420:
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, case GST_VIDEO_FORMAT_YV12:
GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_u, 0); //setup a second texture to render to
glGenTextures (1, &display->videoTexture_u);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_u);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->outputWidth, display->outputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//setup a third texture to render to //attach the second texture to the FBO to renderer to
glGenTextures (1, &display->videoTexture_v); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_v); GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_u, 0);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->outputWidth, display->outputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the third texture to the FBO to renderer to //setup a third texture to render to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, glGenTextures (1, &display->videoTexture_v);
GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_v, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_v);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->outputWidth, display->outputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the third texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->videoTexture_v, 0);
display->multipleRT[0] = GL_COLOR_ATTACHMENT0_EXT;
display->multipleRT[1] = GL_COLOR_ATTACHMENT1_EXT;
display->multipleRT[2] = GL_COLOR_ATTACHMENT2_EXT;
break;
default:
g_assert_not_reached ();
}
//attach the depth render buffer to the FBO //attach the depth render buffer to the FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
@ -777,40 +805,79 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
//unbind the FBO //unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
display->multipleRT[0] = GL_COLOR_ATTACHMENT0_EXT;
display->multipleRT[1] = GL_COLOR_ATTACHMENT1_EXT;
display->multipleRT[2] = GL_COLOR_ATTACHMENT2_EXT;
} }
else else
{ {
GST_DEBUG ("Context %d, EXT_framebuffer_object supported: no", display->glutWinId); //turn off the pipeline because Frame buffer object is a requirement
g_assert_not_reached (); g_print ("Context %d, EXT_framebuffer_object supported: no\n", display->glutWinId);
display->isAlive = FALSE;
} }
if (GLEW_ARB_fragment_shader) switch (display->outputVideo_format)
{
gchar program[2048];
//from texture to video
sprintf (program, display->textFProgram_to_YUY2_UYVY, "y2,u,y1,v");
display->GLSLProgram_to_YUY2 = gst_gl_display_loadGLSLprogram (program);
sprintf (program, display->textFProgram_to_YUY2_UYVY, "v,y1,u,y2");
display->GLSLProgram_to_UYVY = gst_gl_display_loadGLSLprogram (program);
display->GLSLProgram_to_I420_YV12 = gst_gl_display_loadGLSLprogram (display->textFProgram_to_I420_YV12);
display->GLSLProgram_to_AYUV = gst_gl_display_loadGLSLprogram (display->textFProgram_to_AYUV);
}
else
{ {
GST_DEBUG ("Context %d, ARB_fragment_program supported: no", display->glutWinId); case GST_VIDEO_FORMAT_RGBx:
g_assert_not_reached (); case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_RGBA:
case GST_VIDEO_FORMAT_BGRA:
case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
//color space conversion is not needed
break;
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY:
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
case GST_VIDEO_FORMAT_AYUV:
//color space conversion is needed
{
//check if fragment shader is available, then load them
//GLSL is a requirement for donwload
if (GLEW_ARB_fragment_shader)
{
switch (display->outputVideo_format)
{
case GST_VIDEO_FORMAT_YUY2:
{
gchar program[2048];
sprintf (program, display->textFProgram_to_YUY2_UYVY, "y2,u,y1,v");
display->GLSLProgram_to_YUY2 = gst_gl_display_loadGLSLprogram (program);
}
break;
case GST_VIDEO_FORMAT_UYVY:
{
gchar program[2048];
sprintf (program, display->textFProgram_to_YUY2_UYVY, "v,y1,u,y2");
display->GLSLProgram_to_UYVY = gst_gl_display_loadGLSLprogram (program);
}
break;
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
display->GLSLProgram_to_I420_YV12 = gst_gl_display_loadGLSLprogram (display->textFProgram_to_I420_YV12);
break;
case GST_VIDEO_FORMAT_AYUV:
display->GLSLProgram_to_AYUV = gst_gl_display_loadGLSLprogram (display->textFProgram_to_AYUV);
break;
default:
g_assert_not_reached ();
}
}
else
{
//turn off the pipeline because colorspace conversion is not possible
GST_DEBUG ("Context %d, ARB_fragment_shader supported: no", display->glutWinId);
display->isAlive = FALSE;
}
}
break;
default:
g_assert_not_reached ();
} }
g_cond_signal (display->cond_download); g_cond_signal (display->cond_init_download);
} }
@ -1214,8 +1281,8 @@ gst_gl_display_glutDispatchAction (GstGLDisplayMsg* msg)
case GST_GL_DISPLAY_ACTION_USEFBO2: case GST_GL_DISPLAY_ACTION_USEFBO2:
gst_gl_display_glutUseFBO2 (msg->display); gst_gl_display_glutUseFBO2 (msg->display);
break; break;
case GST_GL_DISPLAY_ACTION_OVFBO: case GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD:
gst_gl_display_glutGenerateOutputVideoFBO (msg->display); gst_gl_display_glutInitDownload (msg->display);
break; break;
case GST_GL_DISPLAY_ACTION_GENSHADER: case GST_GL_DISPLAY_ACTION_GENSHADER:
gst_gl_display_glutInitShader (msg->display); gst_gl_display_glutInitShader (msg->display);
@ -1255,7 +1322,7 @@ gst_gl_display_checkMsgValidity (GstGLDisplayMsg *msg)
case GST_GL_DISPLAY_ACTION_DELFBO: case GST_GL_DISPLAY_ACTION_DELFBO:
case GST_GL_DISPLAY_ACTION_USEFBO: case GST_GL_DISPLAY_ACTION_USEFBO:
case GST_GL_DISPLAY_ACTION_USEFBO2: case GST_GL_DISPLAY_ACTION_USEFBO2:
case GST_GL_DISPLAY_ACTION_OVFBO: case GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD:
case GST_GL_DISPLAY_ACTION_GENSHADER: case GST_GL_DISPLAY_ACTION_GENSHADER:
case GST_GL_DISPLAY_ACTION_DELSHADER: case GST_GL_DISPLAY_ACTION_DELSHADER:
//msg is out of date if the associated display is not in the map //msg is out of date if the associated display is not in the map
@ -1562,13 +1629,15 @@ gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo,
/* Called by gst_gl elements */ /* Called by gst_gl elements */
void void
gst_gl_display_initDonwloadFBO (GstGLDisplay* display, gint width, gint height) gst_gl_display_init_download (GstGLDisplay* display, GstVideoFormat video_format,
gint width, gint height)
{ {
gst_gl_display_lock (display); gst_gl_display_lock (display);
display->outputVideo_format = video_format;
display->outputWidth = width; display->outputWidth = width;
display->outputHeight = height; display->outputHeight = height;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_OVFBO, display); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD, display);
g_cond_wait (display->cond_download, display->mutex); g_cond_wait (display->cond_init_download, display->mutex);
gst_gl_display_unlock (display); gst_gl_display_unlock (display);
} }
@ -2203,8 +2272,7 @@ gst_gl_display_fill_video (GstGLDisplay* display)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
//gluOrtho2D(0.0, width, 0.0, height); gluOrtho2D(0.0, width, 0.0, height);
gluPerspective(45, (gfloat)width/(gfloat)height, 0.1, 100);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();

View file

@ -65,7 +65,7 @@ typedef enum {
GST_GL_DISPLAY_ACTION_DELFBO, GST_GL_DISPLAY_ACTION_DELFBO,
GST_GL_DISPLAY_ACTION_USEFBO, GST_GL_DISPLAY_ACTION_USEFBO,
GST_GL_DISPLAY_ACTION_USEFBO2, GST_GL_DISPLAY_ACTION_USEFBO2,
GST_GL_DISPLAY_ACTION_OVFBO, GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD,
GST_GL_DISPLAY_ACTION_GENSHADER, GST_GL_DISPLAY_ACTION_GENSHADER,
GST_GL_DISPLAY_ACTION_DELSHADER GST_GL_DISPLAY_ACTION_DELSHADER
@ -110,7 +110,7 @@ struct _GstGLDisplay {
GCond* cond_useFBO; GCond* cond_useFBO;
GCond* cond_useFBO2; GCond* cond_useFBO2;
GCond* cond_destroyFBO; GCond* cond_destroyFBO;
GCond* cond_download; GCond* cond_init_download;
GCond* cond_initShader; GCond* cond_initShader;
GCond* cond_destroyShader; GCond* cond_destroyShader;
@ -271,7 +271,8 @@ void gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint t
gpointer* p1, gpointer* p2); gpointer* p1, gpointer* p2);
void gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo, void gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo,
guint depthbuffer); guint depthbuffer);
void gst_gl_display_initDonwloadFBO (GstGLDisplay* display, gint width, gint height); void gst_gl_display_init_download (GstGLDisplay* display, GstVideoFormat video_format,
gint width, gint height);
void gst_gl_display_initShader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader); void gst_gl_display_initShader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader);
void gst_gl_display_destroyShader (GstGLDisplay* display, GLhandleARB shader); void gst_gl_display_destroyShader (GstGLDisplay* display, GLhandleARB shader);
void gst_gl_display_set_windowId (GstGLDisplay* display, gulong winId); void gst_gl_display_set_windowId (GstGLDisplay* display, gulong winId);

View file

@ -394,12 +394,12 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps,
colorscale->output_video_width, colorscale->output_video_height, colorscale->output_video_width, colorscale->output_video_height,
0, FALSE); 0, FALSE);
//init colorspace conversion if needed //blocking call, init colorspace conversion if needed
gst_gl_display_init_upload (colorscale->display, colorscale->input_video_format, gst_gl_display_init_upload (colorscale->display, colorscale->input_video_format,
colorscale->output_video_width, colorscale->output_video_height); colorscale->output_video_width, colorscale->output_video_height);
//blocking call //blocking call, init colorspace conversion if needed
gst_gl_display_initDonwloadFBO (colorscale->display, gst_gl_display_init_download (colorscale->display, colorscale->output_video_format,
colorscale->output_video_width, colorscale->output_video_height); colorscale->output_video_width, colorscale->output_video_height);
return ret; return ret;

View file

@ -289,21 +289,22 @@ static GstFlowReturn
gst_gl_download_transform (GstBaseTransform* trans, GstBuffer* inbuf, gst_gl_download_transform (GstBaseTransform* trans, GstBuffer* inbuf,
GstBuffer* outbuf) GstBuffer* outbuf)
{ {
GstGLDownload* download = NULL; GstGLDownload* download = GST_GL_DOWNLOAD (trans);
GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf);
download = GST_GL_DOWNLOAD (trans);
if (download->display == NULL) if (download->display == NULL)
{ {
download->display = g_object_ref (gl_inbuf->display); download->display = g_object_ref (gl_inbuf->display);
gst_gl_display_initDonwloadFBO (download->display, download->width, download->height);
//blocking call, init color space conversion if needed
gst_gl_display_init_download (download->display, download->video_format,
download->width, download->height);
} }
else else
g_assert (download->display == gl_inbuf->display); g_assert (download->display == gl_inbuf->display);
GST_DEBUG ("making video %p size %d", GST_DEBUG ("making video %p size %d",
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
//blocking call //blocking call
gst_gl_display_videoChanged(download->display, download->video_format, gst_gl_display_videoChanged(download->display, download->video_format,