[590/906] up/download: fix scaling on transfer

i.e. uploading from a 10x10 video frame to a 20x20 texture into another 30x30 videoframe
This commit is contained in:
Matthew Waters 2012-09-25 15:20:21 +10:00 committed by Tim-Philipp Müller
parent 89569276c5
commit 39866ea830
6 changed files with 247 additions and 231 deletions

View file

@ -174,11 +174,8 @@ gst_gl_display_init (GstGLDisplay * display)
display->gen_shader = NULL;
display->del_shader = NULL;
display->uploads = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free,
g_object_unref);
display->downloads =
g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free,
g_object_unref);
display->uploads = NULL;
display->downloads = NULL;
#ifdef OPENGL_ES2
display->redisplay_vertex_shader_str =
@ -267,11 +264,11 @@ gst_gl_display_finalize (GObject * object)
display->error_message = NULL;
}
if (display->uploads) {
g_hash_table_destroy (display->uploads);
g_slist_free_full (display->uploads, g_object_unref);
display->uploads = NULL;
}
if (display->downloads) {
g_hash_table_destroy (display->downloads);
g_slist_free_full (display->downloads, g_object_unref);
display->downloads = NULL;
}
}

View file

@ -129,8 +129,8 @@ struct _GstGLDisplay
GstGLDisplayConversion colorspace_conversion;
GHashTable *uploads;
GHashTable *downloads;
GSList *uploads;
GSList *downloads;
//foreign gl context
gulong external_gl_context;

View file

@ -244,23 +244,23 @@ gst_gl_download_finalize (GObject * object)
static inline gboolean
_init_format_pre (GstGLDownload * download, GstVideoFormat v_format,
guint width, guint height)
guint out_width, guint out_height)
{
g_return_val_if_fail (download != NULL, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_ENCODED, FALSE);
g_return_val_if_fail (width > 0 && height > 0, FALSE);
g_return_val_if_fail (out_width > 0 && out_height > 0, FALSE);
return TRUE;
}
gboolean
gst_gl_download_init_format (GstGLDownload * download, GstVideoFormat v_format,
guint width, guint height)
guint out_width, guint out_height)
{
GstVideoInfo info;
if (!_init_format_pre (download, v_format, width, height))
if (!_init_format_pre (download, v_format, out_width, out_height))
return FALSE;
g_mutex_lock (&download->lock);
@ -272,7 +272,7 @@ gst_gl_download_init_format (GstGLDownload * download, GstVideoFormat v_format,
download->initted = TRUE;
}
gst_video_info_set_format (&info, v_format, width, height);
gst_video_info_set_format (&info, v_format, out_width, out_height);
download->info = info;
@ -286,11 +286,11 @@ gst_gl_download_init_format (GstGLDownload * download, GstVideoFormat v_format,
gboolean
gst_gl_download_init_format_thread (GstGLDownload * download,
GstVideoFormat v_format, guint width, guint height)
GstVideoFormat v_format, guint out_width, guint out_height)
{
GstVideoInfo info;
if (!_init_format_pre (download, v_format, width, height))
if (!_init_format_pre (download, v_format, out_width, out_height))
return FALSE;
g_mutex_lock (&download->lock);
@ -302,7 +302,7 @@ gst_gl_download_init_format_thread (GstGLDownload * download,
download->initted = TRUE;
}
gst_video_info_set_format (&info, v_format, width, height);
gst_video_info_set_format (&info, v_format, out_width, out_height);
download->info = info;
@ -471,28 +471,31 @@ gst_gl_download_perform_with_data_unlocked_thread (GstGLDownload * download,
return TRUE;
}
static inline guint64 *
_gen_key (GstVideoFormat v_format, guint width, guint height)
{
guint64 *key;
/* this limits the width and the height to 2^29-1 = 536870911 */
key = g_malloc (sizeof (guint64 *));
*key = v_format | ((guint64) width << 6) | ((guint64) height << 35);
return key;
}
static inline GstGLDownload *
_find_download (GstGLDisplay * display, guint64 * key)
GstGLDownload *
gst_gl_display_find_download_unlocked (GstGLDisplay * display,
GstVideoFormat v_format, guint out_width, guint out_height)
{
GstGLDownload *ret;
GSList *walk;
ret = g_hash_table_lookup (display->downloads, key);
walk = display->downloads;
while (walk) {
ret = walk->data;
if (ret && v_format == GST_VIDEO_INFO_FORMAT (&ret->info) &&
out_width == GST_VIDEO_INFO_WIDTH (&ret->info) &&
out_height == GST_VIDEO_INFO_HEIGHT (&ret->info))
break;
ret = NULL;
walk = g_slist_next (walk);
}
if (!ret) {
ret = gst_gl_download_new (display);
g_hash_table_insert (display->downloads, key, ret);
display->downloads = g_slist_prepend (display->downloads, ret);
}
return ret;
@ -500,45 +503,29 @@ _find_download (GstGLDisplay * display, guint64 * key)
GstGLDownload *
gst_gl_display_find_download (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height)
guint out_width, guint out_height)
{
GstGLDownload *ret;
guint64 *key;
key = _gen_key (v_format, width, height);
gst_gl_display_lock (display);
ret = _find_download (display, key);
ret = gst_gl_display_find_download_unlocked (display, v_format,
out_width, out_height);
gst_gl_display_unlock (display);
return ret;
}
GstGLDownload *
gst_gl_display_find_download_thread (GstGLDisplay * display,
GstVideoFormat v_format, guint width, guint height)
{
GstGLDownload *ret;
guint64 *key;
key = _gen_key (v_format, width, height);
ret = _find_download (display, key);
return ret;
}
static void
_init_download (GstGLDisplay * display, GstGLDownload * download)
{
GstVideoFormat v_format;
guint width, height;
guint out_width, out_height;
width = GST_VIDEO_INFO_WIDTH (&download->info);
height = GST_VIDEO_INFO_HEIGHT (&download->info);
v_format = GST_VIDEO_INFO_FORMAT (&download->info);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
GST_TRACE ("initializing texture download for format %d", v_format);
@ -569,33 +556,32 @@ _init_download (GstGLDisplay * display, GstGLDownload * download)
*/
gst_gl_display_set_error (display,
"Context, EXT_framebuffer_object supported: no");
return;
}
GST_INFO ("Context, EXT_framebuffer_object supported: yes");
/* setup FBO */
if (!download->fbo && !download->depth_buffer) {
glGenFramebuffersEXT (1, &download->fbo);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
glGenFramebuffersEXT (1, &download->fbo);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
/* setup the render buffer for depth */
glGenRenderbuffersEXT (1, &download->depth_buffer);
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, download->depth_buffer);
/* setup the render buffer for depth */
glGenRenderbuffersEXT (1, &download->depth_buffer);
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, download->depth_buffer);
#ifndef OPENGL_ES2
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
width, height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
width, height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
out_width, out_height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
out_width, out_height);
#else
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
width, height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
out_width, out_height);
#endif
}
/* setup a first texture to render to */
glGenTextures (1, &download->out_texture[0]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[0]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
out_width, out_height, 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,
@ -615,7 +601,7 @@ _init_download (GstGLDisplay * display, GstGLDownload * download)
glGenTextures (1, &download->out_texture[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[1]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
out_width, out_height, 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,
@ -634,7 +620,7 @@ _init_download (GstGLDisplay * display, GstGLDownload * download)
glGenTextures (1, &download->out_texture[2]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[2]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
out_width, out_height, 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,
@ -901,14 +887,14 @@ static void
_do_download (GstGLDisplay * display, GstGLDownload * download)
{
GstVideoFormat v_format;
guint width, height;
guint out_width, out_height;
width = GST_VIDEO_INFO_WIDTH (&download->info);
height = GST_VIDEO_INFO_HEIGHT (&download->info);
v_format = GST_VIDEO_INFO_FORMAT (&download->info);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
GST_TRACE ("downloading texture:%u format:%d, dimensions:%ux%u",
download->in_texture, v_format, width, height);
download->in_texture, v_format, out_width, out_height);
switch (v_format) {
case GST_VIDEO_FORMAT_RGBx:
@ -953,10 +939,10 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
#else
guint width, height;
guint out_width, out_height;
width = GST_VIDEO_INFO_WIDTH (&download->info);
height = GST_VIDEO_INFO_HEIGHT (&download->info);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f,
1.0f, 0.0f,
@ -970,7 +956,7 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
glViewport (0, 0, width, height);
glViewport (0, 0, out_width, out_height);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -1003,7 +989,7 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
GL_UNSIGNED_BYTE, download->data[0]);
#else
glReadPixels (0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, out_width, out_height, GL_RGBA, GL_UNSIGNED_BYTE,
download->data[0]);
#endif
break;
@ -1019,10 +1005,10 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
#endif /* G_BYTE_ORDER */
#else /* OPENGL_ES2 */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
glReadPixels (0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8,
download->data[0]);
glReadPixels (0, 0, out_width, out_eight, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
#else
glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
glReadPixels (0, 0, out_width, out_eight, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
#endif /* G_BYTE_ORDER */
#endif /* !OPENGL_ES2 */
@ -1051,7 +1037,7 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
GL_UNSIGNED_BYTE, download->data[0]);
#else
glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, out_width, out_height, GL_RGB, GL_UNSIGNED_BYTE,
download->data[0]);
#endif
break;
@ -1080,7 +1066,7 @@ static void
_do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
{
GstVideoFormat v_format;
guint width, height;
guint out_width, out_height;
GLenum multipleRT[] = {
GL_COLOR_ATTACHMENT0_EXT,
@ -1104,10 +1090,13 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
#endif
width = GST_VIDEO_INFO_WIDTH (&download->info);
height = GST_VIDEO_INFO_HEIGHT (&download->info);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
v_format = GST_VIDEO_INFO_FORMAT (&download->info);
GST_TRACE ("doing YUV download of texture:%u (%ux%u) using fbo:%u",
download->in_texture, out_width, out_height, download->fbo);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
#ifndef OPENGL_ES2
@ -1116,7 +1105,7 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluOrtho2D (0.0, width, 0.0, height);
gluOrtho2D (0.0, out_width, 0.0, out_height);
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
@ -1125,7 +1114,7 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
glGetIntegerv (GL_VIEWPORT, viewport_dim);
#endif
glViewport (0, 0, width, height);
glViewport (0, 0, out_width, out_height);
switch (v_format) {
case GST_VIDEO_FORMAT_YUY2:
@ -1179,8 +1168,8 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
glActiveTextureARB (GL_TEXTURE0_ARB);
gst_gl_shader_set_uniform_1i (download->shader, "tex", 0);
gst_gl_shader_set_uniform_1f (download->shader, "w", (gfloat) width);
gst_gl_shader_set_uniform_1f (download->shader, "h", (gfloat) height);
gst_gl_shader_set_uniform_1f (download->shader, "w", (gfloat) out_width);
gst_gl_shader_set_uniform_1f (download->shader, "h", (gfloat) out_height);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
}
break;
@ -1196,11 +1185,11 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
glBegin (GL_QUADS);
glTexCoord2i (0, 0);
glVertex2f (-1.0f, -1.0f);
glTexCoord2i (width, 0);
glTexCoord2i (out_width, 0);
glVertex2f (1.0f, -1.0f);
glTexCoord2i (width, height);
glTexCoord2i (out_width, out_height);
glVertex2f (1.0f, 1.0f);
glTexCoord2i (0, height);
glTexCoord2i (0, out_height);
glVertex2f (-1.0f, 1.0f);
glEnd ();
@ -1229,8 +1218,6 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
gst_gl_display_check_framebuffer_status ();
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
#ifndef OPENGL_ES2
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
@ -1239,64 +1226,64 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
switch (v_format) {
case GST_VIDEO_FORMAT_AYUV:
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
glReadPixels (0, 0, width, height, GL_BGRA,
glReadPixels (0, 0, out_width, out_height, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
#else
glReadPixels (0, 0, width, height, GL_BGRA,
glReadPixels (0, 0, out_width, out_height, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
#endif
break;
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY:
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, out_height, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
#else
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, out_height, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
#endif
break;
case GST_VIDEO_FORMAT_I420:
{
glReadPixels (0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[0]);
#ifndef OPENGL_ES2
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
#endif
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2,
GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[1]);
#ifndef OPENGL_ES2
glReadBuffer (GL_COLOR_ATTACHMENT2_EXT);
#endif
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2,
GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[2]);
}
break;
case GST_VIDEO_FORMAT_YV12:
{
glReadPixels (0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[0]);
#ifndef OPENGL_ES2
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
#endif
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2,
GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[2]);
#ifndef OPENGL_ES2
glReadBuffer (GL_COLOR_ATTACHMENT2_EXT);
#endif
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2,
GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
download->data[1]);
}
break;

View file

@ -90,9 +90,9 @@ struct _GstGLDownloadClass
GstGLDownload * gst_gl_download_new (GstGLDisplay * display);
gboolean gst_gl_download_init_format (GstGLDownload * download, GstVideoFormat v_format,
guint width, guint height);
guint out_width, guint out_height);
gboolean gst_gl_download_init_format_thread (GstGLDownload * download, GstVideoFormat v_format,
guint width, guint height);
guint out_width, guint out_height);
gboolean gst_gl_download_perform_with_memory_thread (GstGLDownload * download, GstGLMemory * gl_mem);
gboolean gst_gl_download_perform_with_data_thread (GstGLDownload * download, GLuint texture_id,
@ -102,10 +102,10 @@ gboolean gst_gl_download_perform_with_memory (GstGLDownload * download, G
gboolean gst_gl_download_perform_with_data (GstGLDownload * download, GLuint texture_id,
gpointer data[GST_VIDEO_MAX_PLANES]);
GstGLDownload * gst_gl_display_find_download_thread (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height);
GstGLDownload * gst_gl_display_find_download (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height);
GstGLDownload * gst_gl_display_find_download_unlocked (GstGLDisplay * display, GstVideoFormat v_format,
guint out_width, guint out_height);
GstGLDownload * gst_gl_display_find_download (GstGLDisplay * display, GstVideoFormat v_format,
guint out_width, guint out_height);
G_END_DECLS

View file

@ -220,14 +220,15 @@ gst_gl_upload_finalize (GObject * object)
gboolean
gst_gl_upload_init_format (GstGLUpload * upload, GstVideoFormat v_format,
guint width, guint height)
guint in_width, guint in_height, guint out_width, guint out_height)
{
GstVideoInfo info;
g_return_val_if_fail (upload != NULL, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_ENCODED, FALSE);
g_return_val_if_fail (width > 0 && height > 0, FALSE);
g_return_val_if_fail (in_width > 0 && in_height > 0, FALSE);
g_return_val_if_fail (out_width > 0 && out_height > 0, FALSE);
g_mutex_lock (&upload->lock);
@ -238,9 +239,11 @@ gst_gl_upload_init_format (GstGLUpload * upload, GstVideoFormat v_format,
upload->initted = TRUE;
}
gst_video_info_set_format (&info, v_format, width, height);
gst_video_info_set_format (&info, v_format, out_width, out_height);
upload->info = info;
upload->in_width = in_width;
upload->in_height = in_height;
gst_gl_display_thread_add (upload->display,
(GstGLDisplayThreadFunc) _init_upload, upload);
@ -252,14 +255,15 @@ gst_gl_upload_init_format (GstGLUpload * upload, GstVideoFormat v_format,
gboolean
gst_gl_upload_init_format_thread (GstGLUpload * upload, GstVideoFormat v_format,
guint width, guint height)
guint in_width, guint in_height, guint out_width, guint out_height)
{
GstVideoInfo info;
g_return_val_if_fail (upload != NULL, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_ENCODED, FALSE);
g_return_val_if_fail (width > 0 && height > 0, FALSE);
g_return_val_if_fail (in_width > 0 && in_height > 0, FALSE);
g_return_val_if_fail (out_width > 0 && out_height > 0, FALSE);
g_mutex_lock (&upload->lock);
@ -270,9 +274,11 @@ gst_gl_upload_init_format_thread (GstGLUpload * upload, GstVideoFormat v_format,
upload->initted = TRUE;
}
gst_video_info_set_format (&info, v_format, width, height);
gst_video_info_set_format (&info, v_format, out_width, out_height);
upload->info = info;
upload->in_width = in_width;
upload->in_height = in_height;
_init_upload (upload->display, upload);
@ -298,6 +304,9 @@ gst_gl_upload_perform_with_memory (GstGLUpload * upload, GstGLMemory * gl_mem)
g_mutex_lock (&upload->lock);
upload->in_width = GST_VIDEO_INFO_WIDTH (&upload->info);
upload->in_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
data[i] = (guint8 *) gl_mem->data +
GST_VIDEO_INFO_PLANE_OFFSET (&upload->info, i);
@ -342,10 +351,6 @@ _perform_with_data_unlocked_pre (GstGLUpload * upload,
&& GST_VIDEO_INFO_FORMAT (&upload->info) != GST_VIDEO_FORMAT_ENCODED,
FALSE);
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
g_return_val_if_fail (data[i] != NULL, FALSE);
}
upload->out_texture = texture_id;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
upload->data[i] = data[i];
@ -432,28 +437,33 @@ gst_gl_upload_perform_with_data_unlocked_thread (GstGLUpload * upload,
return TRUE;
}
static inline guint64 *
_gen_key (GstVideoFormat v_format, guint width, guint height)
{
guint64 *key;
/* this limits the width and the height to 2^29-1 = 536870911 */
key = g_malloc (sizeof (guint64 *));
*key = v_format | ((guint64) width << 6) | ((guint64) height << 35);
return key;
}
static inline GstGLUpload *
_find_upload (GstGLDisplay * display, guint64 * key)
GstGLUpload *
gst_gl_display_find_upload_unlocked (GstGLDisplay * display,
GstVideoFormat v_format, guint in_width, guint in_height,
guint out_width, guint out_height)
{
GstGLUpload *ret;
GSList *walk;
ret = g_hash_table_lookup (display->uploads, key);
walk = display->uploads;
while (walk) {
ret = walk->data;
if (ret && v_format == GST_VIDEO_INFO_FORMAT (&ret->info) &&
out_width == GST_VIDEO_INFO_WIDTH (&ret->info) &&
out_height == GST_VIDEO_INFO_HEIGHT (&ret->info) &&
in_width == ret->in_width && in_height == ret->in_height)
break;
ret = NULL;
walk = g_slist_next (walk);
}
if (!ret) {
ret = gst_gl_upload_new (display);
g_hash_table_insert (display->uploads, key, ret);
display->uploads = g_slist_prepend (display->uploads, ret);
}
return ret;
@ -461,43 +471,33 @@ _find_upload (GstGLDisplay * display, guint64 * key)
GstGLUpload *
gst_gl_display_find_upload (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height)
guint in_width, guint in_height, guint out_width, guint out_height)
{
GstGLUpload *ret;
guint64 *key;
key = _gen_key (v_format, width, height);
gst_gl_display_lock (display);
ret = _find_upload (display, key);
ret =
gst_gl_display_find_upload_unlocked (display, v_format, in_width,
in_height, out_width, out_height);
gst_gl_display_unlock (display);
return ret;
}
GstGLUpload *
gst_gl_display_find_upload_thread (GstGLDisplay * display,
GstVideoFormat v_format, guint width, guint height)
{
GstGLUpload *ret;
guint64 *key;
key = _gen_key (v_format, width, height);
ret = _find_upload (display, key);
return ret;
}
/* Called in the gl thread */
void
_init_upload (GstGLDisplay * display, GstGLUpload * upload)
{
GstVideoFormat v_format;
guint in_width, in_height, out_width, out_height;
v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
in_width = upload->in_width;
in_height = upload->in_height;
out_width = GST_VIDEO_INFO_WIDTH (&upload->info);
out_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
GST_TRACE ("initializing texture upload for format:%d", v_format);
@ -512,6 +512,8 @@ _init_upload (GstGLDisplay * display, GstGLUpload * upload)
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
if (in_width != out_width || in_height != out_height)
_init_upload_fbo (display, upload);
/* color space conversion is not needed */
break;
case GST_VIDEO_FORMAT_YUY2:
@ -771,11 +773,11 @@ _init_upload (GstGLDisplay * display, GstGLUpload * upload)
void
_init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload)
{
guint width, height;
guint out_width, out_height;
GLuint fake_texture = 0; /* a FBO must hava texture to init */
width = GST_VIDEO_INFO_WIDTH (&upload->info);
height = GST_VIDEO_INFO_HEIGHT (&upload->info);
out_width = GST_VIDEO_INFO_WIDTH (&upload->info);
out_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
if (!GLEW_EXT_framebuffer_object) {
/* turn off the pipeline because Frame buffer object is a not present */
@ -795,18 +797,18 @@ _init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload)
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, upload->depth_buffer);
#ifndef OPENGL_ES2
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
width, height);
out_width, out_height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
width, height);
out_width, out_height);
#else
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
width, height);
out_width, out_height);
#endif
/* a fake texture is attached to the upload FBO (cannot init without it) */
glGenTextures (1, &fake_texture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height, 0,
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, out_width, out_height, 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);
@ -847,14 +849,16 @@ void
_do_upload (GstGLDisplay * display, GstGLUpload * upload)
{
GstVideoFormat v_format;
guint width, height;
guint in_width, in_height, out_width, out_height;
width = GST_VIDEO_INFO_WIDTH (&upload->info);
height = GST_VIDEO_INFO_HEIGHT (&upload->info);
out_width = GST_VIDEO_INFO_WIDTH (&upload->info);
out_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
in_width = upload->in_width;
in_height = upload->in_height;
GST_TRACE ("uploading texture:%u dimensions: %ux%u", upload->out_texture,
width, height);
out_width, out_height);
_do_upload_fill (display, upload);
@ -869,6 +873,8 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload)
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
if (in_width != out_width || in_height != out_height)
_do_upload_draw (display, upload);
/* color space conversion is not needed */
break;
case GST_VIDEO_FORMAT_YUY2:
@ -887,6 +893,8 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload)
/* not yet supported */
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
if (in_width != out_width || in_height != out_height)
_do_upload_draw (display, upload);
/* color space conversion is not needed */
break;
default:
@ -910,10 +918,10 @@ void
_do_upload_make (GstGLDisplay * display, GstGLUpload * upload)
{
GstVideoFormat v_format;
guint width, height;
guint in_width, in_height;
width = GST_VIDEO_INFO_WIDTH (&upload->info);
height = GST_VIDEO_INFO_HEIGHT (&upload->info);
in_width = upload->in_width;
in_height = upload->in_height;
v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
glGenTextures (1, &upload->in_texture[0]);
@ -929,31 +937,33 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload)
case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
in_width, in_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
in_width, in_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
break;
case GST_VIDEO_FORMAT_AYUV:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
break;
case GST_VIDEO_FORMAT_YUY2:
switch (display->colorspace_conversion) {
case GST_GL_DISPLAY_CONVERSION_GLSL:
case GST_GL_DISPLAY_CONVERSION_MATRIX:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
in_width, in_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
NULL);
glGenTextures (1, &upload->in_texture[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
NULL);
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, in_width,
in_height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
break;
default:
gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
@ -967,15 +977,17 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload)
case GST_GL_DISPLAY_CONVERSION_GLSL:
case GST_GL_DISPLAY_CONVERSION_MATRIX:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
in_width, in_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
NULL);
glGenTextures (1, &upload->in_texture[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
NULL);
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, in_width,
in_height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
break;
default:
gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
@ -987,19 +999,21 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload)
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
in_width, in_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
glGenTextures (1, &upload->in_texture[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
GST_ROUND_UP_2 (in_width) / 2,
GST_ROUND_UP_2 (in_height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
NULL);
glGenTextures (1, &upload->in_texture[2]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
GST_ROUND_UP_2 (in_width) / 2,
GST_ROUND_UP_2 (in_height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
NULL);
break;
default:
@ -1016,10 +1030,12 @@ void
_do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
{
GstVideoFormat v_format;
guint width, height;
guint in_width, in_height, out_width, out_height;
width = GST_VIDEO_INFO_WIDTH (&upload->info);
height = GST_VIDEO_INFO_HEIGHT (&upload->info);
in_width = upload->in_width;
in_height = upload->in_height;
out_width = GST_VIDEO_INFO_WIDTH (&upload->info);
out_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
switch (v_format) {
@ -1034,7 +1050,10 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
/* color space conversion is not needed */
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
if (in_width != out_width || in_height != out_height)
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
else
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
break;
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY:
@ -1047,7 +1066,10 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
if (in_width != out_width || in_height != out_height)
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
else
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
break;
default:
gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
@ -1065,49 +1087,50 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
switch (v_format) {
case GST_VIDEO_FORMAT_RGB:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_RGB, GL_UNSIGNED_BYTE, upload->data[0]);
break;
case GST_VIDEO_FORMAT_BGR:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_BGR, GL_UNSIGNED_BYTE, upload->data[0]);
break;
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_RGBA:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_RGBA, GL_UNSIGNED_BYTE, upload->data[0]);
break;
case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_BGRA:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_BGRA, GL_UNSIGNED_BYTE, upload->data[0]);
break;
case GST_VIDEO_FORMAT_AYUV:
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_ARGB:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, upload->data[0]);
break;
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_ABGR:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, upload->data[0]);
break;
case GST_VIDEO_FORMAT_YUY2:
switch (display->colorspace_conversion) {
case GST_GL_DISPLAY_CONVERSION_GLSL:
case GST_GL_DISPLAY_CONVERSION_MATRIX:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width,
in_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, height,
GST_ROUND_UP_2 (in_width) / 2, in_height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]);
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, upload->data[0]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width,
in_height, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA,
upload->data[0]);
break;
default:
gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
@ -1120,17 +1143,18 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
switch (display->colorspace_conversion) {
case GST_GL_DISPLAY_CONVERSION_GLSL:
case GST_GL_DISPLAY_CONVERSION_MATRIX:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width,
in_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, height,
GST_ROUND_UP_2 (in_width) / 2, in_height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]);
break;
case GST_GL_DISPLAY_CONVERSION_MESA:
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, upload->data[0]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width,
in_height, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA,
upload->data[0]);
break;
default:
gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
@ -1141,33 +1165,33 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
break;
case GST_VIDEO_FORMAT_I420:
{
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[0]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GST_ROUND_UP_2 (in_width) / 2, GST_ROUND_UP_2 (in_height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GST_ROUND_UP_2 (in_width) / 2, GST_ROUND_UP_2 (in_height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[2]);
}
break;
case GST_VIDEO_FORMAT_YV12: /* same as I420 except plane 1+2 swapped */
{
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[0]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GST_ROUND_UP_2 (in_width) / 2, GST_ROUND_UP_2 (in_height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[1]);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GST_ROUND_UP_2 (in_width) / 2, GST_ROUND_UP_2 (in_height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[2]);
}
break;
@ -1190,7 +1214,7 @@ void
_do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
{
GstVideoFormat v_format;
guint width, height;
guint in_width, in_height, out_width, out_height;
#ifdef OPENGL_ES2
GLint viewport_dim[4];
@ -1208,8 +1232,10 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
#endif
width = GST_VIDEO_INFO_WIDTH (&upload->info);
height = GST_VIDEO_INFO_HEIGHT (&upload->info);
in_width = upload->in_width;
in_height = upload->in_height;
out_width = GST_VIDEO_INFO_WIDTH (&upload->info);
out_height = GST_VIDEO_INFO_HEIGHT (&upload->info);
v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, upload->fbo);
@ -1233,7 +1259,7 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluOrtho2D (0.0, width, 0.0, height);
gluOrtho2D (0.0, out_width, 0.0, out_height);
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
@ -1242,7 +1268,7 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
glGetIntegerv (GL_VIEWPORT, viewport_dim);
#endif
glViewport (0, 0, width, height);
glViewport (0, 0, out_width, out_height);
#ifndef OPENGL_ES2
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
@ -1469,13 +1495,13 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
#ifndef OPENGL_ES2
glBegin (GL_QUADS);
glTexCoord2i (width, 0);
glTexCoord2i (in_width, 0);
glVertex2f (1.0f, -1.0f);
glTexCoord2i (0, 0);
glVertex2f (-1.0f, -1.0f);
glTexCoord2i (0, height);
glTexCoord2i (0, in_height);
glVertex2f (-1.0f, 1.0f);
glTexCoord2i (width, height);
glTexCoord2i (in_width, in_height);
glVertex2f (1.0f, 1.0f);
glEnd ();

View file

@ -60,13 +60,15 @@ struct _GstGLUpload
GLuint depth_buffer;
GLuint out_texture;
GLuint in_texture[GST_VIDEO_MAX_PLANES];
guint in_width;
guint in_height;
GstGLShader *shader;
#ifdef OPENGL_ES2
GLint shader_attr_position_loc;
GLint shader_attr_texture_loc;
#endif
/* output data */
/* input data */
GstVideoInfo info;
/* <private> */
@ -90,9 +92,11 @@ struct _GstGLUploadClass
GstGLUpload * gst_gl_upload_new (GstGLDisplay * display);
gboolean gst_gl_upload_init_format (GstGLUpload * upload, GstVideoFormat v_format,
guint width, guint height);
guint in_width, guint in_height,
guint out_width, guint out_height);
gboolean gst_gl_upload_init_format_thread (GstGLUpload * upload, GstVideoFormat v_format,
guint width, guint height);
guint in_width, guint in_height,
guint out_width, guint out_height);
gboolean gst_gl_upload_perform_with_memory (GstGLUpload * upload, GstGLMemory * gl_mem);
gboolean gst_gl_upload_perform_with_data (GstGLUpload * upload, GLuint texture_id,
@ -101,10 +105,12 @@ gboolean gst_gl_upload_perform_with_memory_thread (GstGLUpload * upload, GstGLMe
gboolean gst_gl_upload_perform_with_data_thread (GstGLUpload * upload, GLuint texture_id,
gpointer data[GST_VIDEO_MAX_PLANES]);
GstGLUpload * gst_gl_display_find_upload (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height);
GstGLUpload * gst_gl_display_find_upload_thread (GstGLDisplay * display, GstVideoFormat v_format,
guint width, guint height);
GstGLUpload * gst_gl_display_find_upload (GstGLDisplay * display, GstVideoFormat v_format,
guint in_width, guint in_height,
guint out_width, guint out_height);
GstGLUpload * gst_gl_display_find_upload_unlocked (GstGLDisplay * display, GstVideoFormat v_format,
guint in_width, guint in_height,
guint out_width, guint out_height);
G_END_DECLS