From a90946b5890892f105bc89161f7c3b7b8f0b7f52 Mon Sep 17 00:00:00 2001 From: Haihua Hu Date: Fri, 13 Nov 2015 10:51:25 +0800 Subject: [PATCH 10/26] support video crop for glimagesink 1.Add video crop meta copy in glupload 2.Calculate the new texture coordinate in vertices array and bind to buffer object 3.Make glimagesink only updating vertices array when video crop meta changed Upstream-Status: Inappropriate [i.MX specific] Signed-off-by: Haihua Hu --- ext/gl/gstglimagesink.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ ext/gl/gstglimagesink.h | 3 +++ ext/gl/gstgluploadelement.c | 14 +++++++++-- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c index f6a61ac..75d3214 100644 --- a/ext/gl/gstglimagesink.c +++ b/ext/gl/gstglimagesink.c @@ -764,6 +764,8 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink) glimage_sink->handle_events = TRUE; glimage_sink->ignore_alpha = TRUE; glimage_sink->overlay_compositor = NULL; + glimage_sink->cropmeta = NULL; + glimage_sink->prev_cropmeta = NULL; glimage_sink->mview_output_mode = DEFAULT_MULTIVIEW_MODE; glimage_sink->mview_output_flags = DEFAULT_MULTIVIEW_FLAGS; @@ -1253,6 +1255,12 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) gst_object_unref (glimage_sink->display); glimage_sink->display = NULL; } + + glimage_sink->cropmeta = NULL; + if (glimage_sink->prev_cropmeta) + g_slice_free(GstVideoCropMeta, glimage_sink->prev_cropmeta); + glimage_sink->prev_cropmeta = NULL; + break; default: break; @@ -1737,6 +1745,8 @@ gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) GST_VIDEO_SINK_WIDTH (glimage_sink), GST_VIDEO_SINK_HEIGHT (glimage_sink)); + glimage_sink->cropmeta = gst_buffer_get_video_crop_meta (buf); + /* Ask the underlying window to redraw its content */ if (!gst_glimage_sink_redisplay (glimage_sink)) goto redisplay_failed; @@ -2222,6 +2232,54 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink) gst_gl_shader_use (gl_sink->redisplay_shader); + if (gl_sink->cropmeta) { + gint width = GST_VIDEO_SINK_WIDTH (gl_sink); + gint height = GST_VIDEO_SINK_HEIGHT (gl_sink); + + if (!gl_sink->prev_cropmeta){ + /* Initialize the previous crop meta and set all memroy to zero */ + gl_sink->prev_cropmeta = (GstVideoCropMeta *) g_slice_new0(GstVideoCropMeta); + } + + /* If crop meta not equal to the previous, recalculate the vertices */ + if (gl_sink->prev_cropmeta->x != gl_sink->cropmeta->x + || gl_sink->prev_cropmeta->y != gl_sink->cropmeta->y + || gl_sink->prev_cropmeta->width != gl_sink->cropmeta->width + || gl_sink->prev_cropmeta->height != gl_sink->cropmeta->height){ + + GLfloat crop_vertices[] = { + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f + }; + + crop_vertices[8] = (float)(gl_sink->cropmeta->x) / width; + crop_vertices[9] = (float)(gl_sink->cropmeta->y) / height; + + crop_vertices[3] = (float)(gl_sink->cropmeta->width + gl_sink->cropmeta->x) / width; + crop_vertices[4] = crop_vertices[9]; + + crop_vertices[13] = crop_vertices[8]; + crop_vertices[14] = (float)(gl_sink->cropmeta->height + gl_sink->cropmeta->y) / height; + + crop_vertices[18] = crop_vertices[3]; + crop_vertices[19] = crop_vertices[14]; + + gl->BindBuffer (GL_ARRAY_BUFFER, gl_sink->vertex_buffer); + gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), crop_vertices, + GL_STATIC_DRAW); + + gl->BindBuffer (GL_ARRAY_BUFFER, 0); + + /* Store the previous crop meta */ + gl_sink->prev_cropmeta->x = gl_sink->cropmeta->x; + gl_sink->prev_cropmeta->y = gl_sink->cropmeta->y; + gl_sink->prev_cropmeta->width = gl_sink->cropmeta->width; + gl_sink->prev_cropmeta->height = gl_sink->cropmeta->height; + } + } + if (gl->GenVertexArrays) gl->BindVertexArray (gl_sink->vao); _bind_buffer (gl_sink); diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h index 8833103..0723e08 100644 --- a/ext/gl/gstglimagesink.h +++ b/ext/gl/gstglimagesink.h @@ -120,6 +120,9 @@ struct _GstGLImageSink guint window_width; guint window_height; + GstVideoCropMeta *cropmeta; + GstVideoCropMeta *prev_cropmeta; + GstVideoRectangle display_rect; GstGLShader *redisplay_shader; diff --git a/ext/gl/gstgluploadelement.c b/ext/gl/gstgluploadelement.c index f9e52f6..52bd76a 100644 --- a/ext/gl/gstgluploadelement.c +++ b/ext/gl/gstgluploadelement.c @@ -256,9 +256,19 @@ gst_gl_upload_element_prepare_output_buffer (GstBaseTransform * bt, /* basetransform doesn't unref if they're the same */ if (buffer == *outbuf) gst_buffer_unref (*outbuf); - else + else { + GstVideoCropMeta *incropmeta, *outcropmeta; + /* add video crop meta to out buffer if need */ + incropmeta = gst_buffer_get_video_crop_meta (buffer); + if (incropmeta) { + outcropmeta = gst_buffer_add_video_crop_meta (*outbuf); + outcropmeta->x = incropmeta->x; + outcropmeta->y = incropmeta->y; + outcropmeta->width = incropmeta->width; + outcropmeta->height = incropmeta->height; + } bclass->copy_metadata (bt, buffer, *outbuf); - + } return GST_FLOW_OK; } -- 1.9.1