diff options
author | Julien Isorce <julien.isorce@gmail.com> | 2010-05-04 11:37:38 +0200 |
---|---|---|
committer | Julien Isorce <julien.isorce@gmail.com> | 2010-05-04 11:37:38 +0200 |
commit | abb711ae06a24cfd8f7cc2ebfae6c2854aebf5b4 (patch) | |
tree | 6b2c4cfd9f7648a8d9570a5be30bf62bdb8d9324 | |
parent | 56d180896aeaffe04876c93796478f1a0d7716db (diff) |
glimagesink: handle pixel-aspect-ratio
-rw-r--r-- | gst-libs/gst/gl/gstgldisplay.c | 11 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstgldisplay.h | 3 | ||||
-rw-r--r-- | gst/gl/gstglimagesink.c | 79 | ||||
-rw-r--r-- | gst/gl/gstglimagesink.h | 5 | ||||
-rw-r--r-- | tests/pipelines | 4 |
5 files changed, 91 insertions, 11 deletions
diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index f96bc14..b95ce64 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -2167,8 +2167,9 @@ gst_gl_display_create_context (GstGLDisplay * display, /* Called by the glimagesink element */ gboolean -gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, gint width, - gint height, gboolean keep_aspect_ratio) +gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, + gint gl_width, gint gl_height, gint window_width, gint window_height, + gboolean keep_aspect_ratio) { gboolean isAlive = TRUE; @@ -2185,12 +2186,12 @@ gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, gint width, if (texture) { display->redisplay_texture = texture; - display->redisplay_texture_width = width; - display->redisplay_texture_height = height; + display->redisplay_texture_width = gl_width; + display->redisplay_texture_height = gl_height; } display->keep_aspect_ratio = keep_aspect_ratio; if (display->gl_window) - gst_gl_window_draw (display->gl_window, width, height); + gst_gl_window_draw (display->gl_window, window_width, window_height); } gst_gl_display_unlock (display); diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 670d339..00789b8 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -241,7 +241,8 @@ GstGLDisplay *gst_gl_display_new (void); void gst_gl_display_create_context (GstGLDisplay * display, gulong external_gl_context); gboolean gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, - gint width, gint height, gboolean keep_aspect_ratio); + gint gl_width, gint gl_height, gint window_width, gint window_height, + gboolean keep_aspect_ratio); void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data); diff --git a/gst/gl/gstglimagesink.c b/gst/gl/gstglimagesink.c index 02ff7f9..25d16d9 100644 --- a/gst/gl/gstglimagesink.c +++ b/gst/gl/gstglimagesink.c @@ -151,7 +151,8 @@ enum PROP_CLIENT_RESHAPE_CALLBACK, PROP_CLIENT_DRAW_CALLBACK, PROP_CLIENT_DATA, - PROP_FORCE_ASPECT_RATIO + PROP_FORCE_ASPECT_RATIO, + PROP_PIXEL_ASPECT_RATIO }; GST_BOILERPLATE_FULL (GstGLImageSink, gst_glimage_sink, GstVideoSink, @@ -233,6 +234,11 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass) "When enabled, scaling will respect original aspect ratio", FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO, + g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio", + "The pixel aspect ratio of the device", "1/1", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gobject_class->finalize = gst_glimage_sink_finalize; gstelement_class->change_state = gst_glimage_sink_change_state; @@ -257,6 +263,7 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink, glimage_sink->clientDrawCallback = NULL; glimage_sink->client_data = NULL; glimage_sink->keep_aspect_ratio = FALSE; + glimage_sink->par = NULL; } static void @@ -296,6 +303,17 @@ gst_glimage_sink_set_property (GObject * object, guint prop_id, glimage_sink->keep_aspect_ratio = g_value_get_boolean (value); break; } + case PROP_PIXEL_ASPECT_RATIO: + { + g_free (glimage_sink->par); + glimage_sink->par = g_new0 (GValue, 1); + g_value_init (glimage_sink->par, GST_TYPE_FRACTION); + if (!g_value_transform (value, glimage_sink->par)) { + g_warning ("Could not transform string to aspect ratio"); + gst_value_set_fraction (glimage_sink->par, 1, 1); + } + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -311,6 +329,11 @@ gst_glimage_sink_finalize (GObject * object) glimage_sink = GST_GLIMAGE_SINK (object); + if (glimage_sink->par) { + g_free (glimage_sink->par); + glimage_sink->par = NULL; + } + if (glimage_sink->caps) gst_caps_unref (glimage_sink->caps); @@ -336,6 +359,10 @@ gst_glimage_sink_get_property (GObject * object, guint prop_id, case PROP_FORCE_ASPECT_RATIO: g_value_set_boolean (value, glimage_sink->keep_aspect_ratio); break; + case PROP_PIXEL_ASPECT_RATIO: + if (glimage_sink->par) + g_value_transform (glimage_sink->par, value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -352,7 +379,8 @@ gst_glimage_sink_query (GstElement * element, GstQuery * query) case GST_QUERY_CUSTOM: { GstStructure *structure = gst_query_get_structure (query); - gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER, glimage_sink->display, NULL); + gst_structure_set (structure, "gstgldisplay", G_TYPE_POINTER, + glimage_sink->display, NULL); res = GST_ELEMENT_CLASS (parent_class)->query (element, query); break; } @@ -463,6 +491,8 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) gboolean ok; gint fps_n, fps_d; gint par_n, par_d; + gint display_par_n, display_par_d; + guint display_ratio_num, display_ratio_den; GstVideoFormat format; GstStructure *structure; gboolean is_gl; @@ -481,13 +511,16 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) is_gl = FALSE; ok = gst_video_format_parse_caps (caps, &format, &width, &height); + if (!ok) + return FALSE; + /* init colorspace conversion if needed */ gst_gl_display_init_upload (glimage_sink->display, format, width, height, width, height); } gst_gl_display_set_client_reshape_callback (glimage_sink->display, - glimage_sink->clientReshapeCallback); + glimage_sink->clientReshapeCallback); gst_gl_display_set_client_draw_callback (glimage_sink->display, glimage_sink->clientDrawCallback); @@ -501,6 +534,43 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) if (!ok) return FALSE; + /* get display's PAR */ + if (glimage_sink->par) { + display_par_n = gst_value_get_fraction_numerator (glimage_sink->par); + display_par_d = gst_value_get_fraction_denominator (glimage_sink->par); + } else { + display_par_n = 1; + display_par_d = 1; + } + + ok = gst_video_calculate_display_ratio (&display_ratio_num, + &display_ratio_den, width, height, par_n, par_d, display_par_n, + display_par_d); + + if (!ok) + return FALSE; + + if (height % display_ratio_den == 0) { + GST_DEBUG ("keeping video height"); + glimage_sink->window_width = (guint) + gst_util_uint64_scale_int (height, display_ratio_num, + display_ratio_den); + glimage_sink->window_height = height; + } else if (width % display_ratio_num == 0) { + GST_DEBUG ("keeping video width"); + glimage_sink->window_width = width; + glimage_sink->window_height = (guint) + gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); + } else { + GST_DEBUG ("approximating while keeping video height"); + glimage_sink->window_width = (guint) + gst_util_uint64_scale_int (height, display_ratio_num, + display_ratio_den); + glimage_sink->window_height = height; + } + GST_DEBUG ("scaling to %dx%d", + glimage_sink->window_width, glimage_sink->window_height); + GST_VIDEO_SINK_WIDTH (glimage_sink) = width; GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; glimage_sink->is_gl = is_gl; @@ -562,6 +632,7 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) if (gl_buffer->texture && gst_gl_display_redisplay (glimage_sink->display, gl_buffer->texture, gl_buffer->width, gl_buffer->height, + glimage_sink->window_width, glimage_sink->window_height, glimage_sink->keep_aspect_ratio)) return GST_FLOW_OK; else @@ -604,7 +675,7 @@ gst_glimage_sink_expose (GstXOverlay * overlay) glimage_sink->window_id); } - gst_gl_display_redisplay (glimage_sink->display, 0, 0, 0, + gst_gl_display_redisplay (glimage_sink->display, 0, 0, 0, 0, 0, glimage_sink->keep_aspect_ratio); } } diff --git a/gst/gl/gstglimagesink.h b/gst/gl/gstglimagesink.h index 453fbfe..c61b5c5 100644 --- a/gst/gl/gstglimagesink.h +++ b/gst/gl/gstglimagesink.h @@ -1,4 +1,4 @@ -/* +/* * GStreamer * Copyright (C) 2003 Julien Moutte <julien@moutte.net> * Copyright (C) 2005,2006,2007 David A. Schleef <ds@schleef.org> @@ -59,6 +59,8 @@ struct _GstGLImageSink GstCaps *caps; gint width; gint height; + gint window_width; + gint window_height; gboolean is_gl; gint fps_n, fps_d; gint par_n, par_d; @@ -71,6 +73,7 @@ struct _GstGLImageSink gpointer client_data; gboolean keep_aspect_ratio; + GValue *par; }; struct _GstGLImageSinkClass diff --git a/tests/pipelines b/tests/pipelines index 6eb1523..5f9d45c 100644 --- a/tests/pipelines +++ b/tests/pipelines @@ -65,3 +65,7 @@ gst-launch-0.10 videotestsrc ! "video/x-raw-yuv, format=(fourcc)YUY2" ! glupload gst-launch-0.10 -v videotestsrc ! glupload ! gloverlay location=image.png proportion-png=40 proportion-video=40 xpos-png=75 ypos-png=50 xpos-video=30 ypos-video=50 rotate-png=2 rotate-video=2 angle-png=-15 angle-video=15 ! glimagesink +gst-launch-0.10 videotestsrc ! "video/x-raw-yuv, pixel-aspect-ratio=(fraction)5/2" ! glimagesink + +gst-launch-0.10 videotestsrc ! "video/x-raw-yuv,format=(fourcc)I420,width=720,height=576,pixel-aspect-ratio=(fraction)64/45" ! glupload ! glimagesink + |