From 079f5e83eaf9edc08d323b77ac34cac94c03db36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 26 Dec 2012 17:25:36 +0100 Subject: [PATCH] eglglessink: Add support for video meta and arbitrary strides --- ext/eglgles/gsteglglessink.c | 481 +++++++++++++++++++++++++++++++---- ext/eglgles/gsteglglessink.h | 4 +- 2 files changed, 439 insertions(+), 46 deletions(-) diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c index d991062c7f..1367f28e3c 100644 --- a/ext/eglgles/gsteglglessink.c +++ b/ext/eglgles/gsteglglessink.c @@ -186,9 +186,12 @@ static const char *frag_COPY_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D tex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "void main(void)" "{" - " vec4 t = texture2D(tex, opos);" + " vec4 t = texture2D(tex, opos / tex_scale0);" " gl_FragColor = vec4(t.rgb, 1.0);" "}" }; @@ -198,9 +201,12 @@ static const char *frag_REORDER_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D tex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "void main(void)" "{" - " vec4 t = texture2D(tex, opos);" + " vec4 t = texture2D(tex, opos / tex_scale0);" " gl_FragColor = vec4(t.%c, t.%c, t.%c, 1.0);" "}" }; @@ -212,6 +218,9 @@ static const char *frag_AYUV_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D tex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" @@ -219,7 +228,7 @@ static const char *frag_AYUV_prog = { "void main(void) {" " float r,g,b;" " vec3 yuv;" - " yuv = texture2D(tex,opos).gba;" + " yuv = texture2D(tex,opos / tex_scale0).gba;" " yuv += offset;" " r = dot(yuv, rcoeff);" " g = dot(yuv, gcoeff);" @@ -233,6 +242,9 @@ static const char *frag_YUY2_YVYU_UYVY_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D Ytex, UVtex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" @@ -240,8 +252,8 @@ static const char *frag_YUY2_YVYU_UYVY_prog = { "void main(void) {" " float r, g, b;" " vec3 yuv;" - " yuv.x = texture2D(Ytex,opos).%c;" - " yuv.yz = texture2D(UVtex,opos).%c%c;" + " yuv.x = texture2D(Ytex,opos / tex_scale0).%c;" + " yuv.yz = texture2D(UVtex,opos / tex_scale0).%c%c;" " yuv += offset;" " r = dot(yuv, rcoeff);" " g = dot(yuv, gcoeff);" @@ -257,6 +269,9 @@ static const char *frag_PLANAR_YUV_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D Ytex,Utex,Vtex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" @@ -264,9 +279,9 @@ static const char *frag_PLANAR_YUV_prog = { "void main(void) {" " float r,g,b;" " vec3 yuv;" - " yuv.x=texture2D(Ytex,opos).r;" - " yuv.y=texture2D(Utex,opos).r;" - " yuv.z=texture2D(Vtex,opos).r;" + " yuv.x=texture2D(Ytex,opos / tex_scale0).r;" + " yuv.y=texture2D(Utex,opos / tex_scale1).r;" + " yuv.z=texture2D(Vtex,opos / tex_scale2).r;" " yuv += offset;" " r = dot(yuv, rcoeff);" " g = dot(yuv, gcoeff);" @@ -280,6 +295,9 @@ static const char *frag_NV12_NV21_prog = { "precision mediump float;" "varying vec2 opos;" "uniform sampler2D Ytex,UVtex;" + "uniform vec2 tex_scale0;" + "uniform vec2 tex_scale1;" + "uniform vec2 tex_scale2;" "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" @@ -287,8 +305,8 @@ static const char *frag_NV12_NV21_prog = { "void main(void) {" " float r,g,b;" " vec3 yuv;" - " yuv.x=texture2D(Ytex,opos).r;" - " yuv.yz=texture2D(UVtex,opos).%c%c;" + " yuv.x=texture2D(Ytex,opos / tex_scale0).r;" + " yuv.yz=texture2D(UVtex,opos / tex_scale1).%c%c;" " yuv += offset;" " r = dot(yuv, rcoeff);" " g = dot(yuv, gcoeff);" @@ -1249,6 +1267,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) eglglessink->eglglesctx.fragshader[0] = glCreateShader (GL_FRAGMENT_SHADER); switch (eglglessink->configured_info.finfo->format) { case GST_VIDEO_FORMAT_AYUV: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", frag_AYUV_prog, + eglglessink->eglglesctx.fragshader[0]); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, &frag_AYUV_prog, NULL); eglglessink->eglglesctx.n_textures = 1; @@ -1259,6 +1279,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_PLANAR_YUV_prog, eglglessink->eglglesctx.fragshader[0]); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, &frag_PLANAR_YUV_prog, NULL); eglglessink->eglglesctx.n_textures = 3; @@ -1267,6 +1289,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) texnames[2] = "Vtex"; break; case GST_VIDEO_FORMAT_YUY2: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_YUY2_YVYU_UYVY_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'r', 'g', 'a'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1275,6 +1299,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) texnames[1] = "UVtex"; break; case GST_VIDEO_FORMAT_YVYU: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_YUY2_YVYU_UYVY_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'r', 'a', 'g'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1283,6 +1309,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) texnames[1] = "UVtex"; break; case GST_VIDEO_FORMAT_UYVY: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_YUY2_YVYU_UYVY_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'a', 'r', 'b'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1291,6 +1319,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) texnames[1] = "UVtex"; break; case GST_VIDEO_FORMAT_NV12: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_NV12_NV21_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_NV12_NV21_prog, 'r', 'a'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1299,6 +1329,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) texnames[1] = "UVtex"; break; case GST_VIDEO_FORMAT_NV21: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_NV12_NV21_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_NV12_NV21_prog, 'a', 'r'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1309,6 +1341,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_BGRA: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_REORDER_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_REORDER_prog, 'b', 'g', 'r'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1317,6 +1351,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) break; case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_ARGB: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_REORDER_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_REORDER_prog, 'g', 'b', 'a'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1325,6 +1361,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) break; case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_ABGR: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", + frag_REORDER_prog, eglglessink->eglglesctx.fragshader[0]); tmp_prog = g_strdup_printf (frag_REORDER_prog, 'a', 'b', 'g'); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, (const GLchar **) &tmp_prog, NULL); @@ -1335,6 +1373,8 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_RGB16: + GST_DEBUG_OBJECT (eglglessink, "Sending %s to handle %d", frag_COPY_prog, + eglglessink->eglglesctx.fragshader[0]); glShaderSource (eglglessink->eglglesctx.fragshader[0], 1, &frag_COPY_prog, NULL); eglglessink->eglglesctx.n_textures = 1; @@ -1393,6 +1433,15 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink) glGetAttribLocation (eglglessink->eglglesctx.glslprogram[0], "position"); eglglessink->eglglesctx.texpos_loc = glGetAttribLocation (eglglessink->eglglesctx.glslprogram[0], "texpos"); + eglglessink->eglglesctx.tex_scale_loc[0] = + glGetUniformLocation (eglglessink->eglglesctx.glslprogram[0], + "tex_scale0"); + eglglessink->eglglesctx.tex_scale_loc[1] = + glGetUniformLocation (eglglessink->eglglesctx.glslprogram[0], + "tex_scale1"); + eglglessink->eglglesctx.tex_scale_loc[2] = + glGetUniformLocation (eglglessink->eglglesctx.glslprogram[0], + "tex_scale2"); glEnableVertexAttribArray (eglglessink->eglglesctx.position_loc[0]); if (got_gl_error ("glEnableVertexAttribArray")) @@ -1764,18 +1813,90 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink, if (buf) { switch (eglglessink->selected_fmt->fmt) { - case GST_EGLGLESSINK_IMAGE_RGB888: + case GST_EGLGLESSINK_IMAGE_RGB888:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (c_w * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (c_w * 3 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (stride_width * 3) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (stride_width * 3 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); break; - case GST_EGLGLESSINK_IMAGE_RGB565: + } + case GST_EGLGLESSINK_IMAGE_RGB565:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (c_w * 2 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (stride_width * 2 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); break; + } case GST_EGLGLESSINK_IMAGE_RGBA8888: switch (eglglessink->configured_info.finfo->format) { @@ -1786,43 +1907,210 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink, case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_xBGR:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (c_w * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (stride_width * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, - GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, + 0)); break; - case GST_VIDEO_FORMAT_AYUV: + } + case GST_VIDEO_FORMAT_AYUV:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (c_w * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (stride_width * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, - GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, + 0)); break; + } case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (c_w == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (stride_width == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0), + stride_width, GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_COMP_DATA (&vframe, 0)); + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1); + glActiveTexture (GL_TEXTURE1); + + if (GST_ROUND_UP_8 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (c_w == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (stride_width == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]); glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1), + stride_width, GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_COMP_DATA (&vframe, 1)); + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 2); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 2); + glActiveTexture (GL_TEXTURE2); + + if (GST_ROUND_UP_8 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (c_w == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (stride_width == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[2] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[2]); glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 2), + stride_width, GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 2), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_COMP_DATA (&vframe, 2)); @@ -1830,32 +2118,130 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink, } case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_UYVY:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1); + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (c_w * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + stride_width = stride / 4; + + if (GST_ROUND_UP_8 (stride_width * 4) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (stride_width * 4 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - glActiveTexture (GL_TEXTURE1); - glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GST_ROUND_UP_2 (w) / 2, - h, 0, GL_RGBA, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - break; - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21:{ - glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0), - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0), - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, + stride_width * 2, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); glActiveTexture (GL_TEXTURE1); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, + h, 0, GL_RGBA, GL_UNSIGNED_BYTE, + GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); + break; + } + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21:{ + gint stride; + gint stride_width; + gint c_w; + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0); + + glActiveTexture (GL_TEXTURE0); + + if (GST_ROUND_UP_8 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (c_w) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (c_w == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + stride_width = stride; + + if (GST_ROUND_UP_8 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (GST_ROUND_UP_2 (stride_width) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else if (stride_width == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); + + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]); + glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, + stride_width, + GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0), + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); + + + stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1); + stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1); + + glActiveTexture (GL_TEXTURE1); + + if (GST_ROUND_UP_8 (c_w * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (c_w * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (c_w * 2 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else { + stride_width = stride / 2; + + if (GST_ROUND_UP_8 (stride_width * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 8); + } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + } else if (stride_width * 2 == stride) { + glPixelStorei (GL_UNPACK_ALIGNMENT, 2); + } else { + GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); + goto HANDLE_ERROR; + } + } + if (got_gl_error ("glPixelStorei")) + goto HANDLE_ERROR; + + eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w); + glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]); glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, - GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1), + stride_width, GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1), 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1)); @@ -2002,6 +2388,13 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink, GST_DEBUG_OBJECT (eglglessink, "Drawing video frame"); glUseProgram (eglglessink->eglglesctx.glslprogram[0]); + glUniform2f (eglglessink->eglglesctx.tex_scale_loc[0], eglglessink->stride[0], + 1); + glUniform2f (eglglessink->eglglesctx.tex_scale_loc[1], eglglessink->stride[1], + 1); + glUniform2f (eglglessink->eglglesctx.tex_scale_loc[2], eglglessink->stride[2], + 1); + glVertexAttribPointer (eglglessink->eglglesctx.position_loc[0], 3, GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (0 * sizeof (coord5))); if (got_gl_error ("glVertexAttribPointer")) @@ -2082,9 +2475,7 @@ gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter) static gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { - /* FIXME: Add support for video meta, i.e. arbitrary strides - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); - */ + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); return TRUE; diff --git a/ext/eglgles/gsteglglessink.h b/ext/eglgles/gsteglglessink.h index 55f475f0c7..df440e4ead 100644 --- a/ext/eglgles/gsteglglessink.h +++ b/ext/eglgles/gsteglglessink.h @@ -134,8 +134,9 @@ struct _GstEglGlesRenderContext /* shader vars */ GLuint position_loc[2], texpos_loc; + GLuint tex_scale_loc[3]; GLuint tex_loc[3]; - coord5 position_array[12]; /* 3 x Frame, 3 x Border1, 3 x Border2 */ + coord5 position_array[12]; /* 4 x Frame, 4 x Border1, 4 x Border2 */ unsigned short index_array[4]; unsigned int position_buffer, index_buffer; }; @@ -196,6 +197,7 @@ struct _GstEglGlesSink GstCaps *sinkcaps; GstCaps *current_caps, *configured_caps; GstVideoInfo configured_info; + gfloat stride[3]; GstEglGlesImageFmt *selected_fmt; GstEglGlesRenderContext eglglesctx;