diff options
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-decl.txt | 3 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-undocumented.txt | 2 | ||||
-rw-r--r-- | ext/directfb/dfbvideosink.c | 184 | ||||
-rw-r--r-- | ext/directfb/dfbvideosink.h | 3 |
5 files changed, 186 insertions, 26 deletions
@@ -1,3 +1,23 @@ +2005-12-18 Julien MOUTTE <julien@moutte.net> + + * docs/plugins/gst-plugins-bad-plugins-decl.txt: + * docs/plugins/gst-plugins-bad-plugins-undocumented.txt: Updates. + * ext/directfb/dfbvideosink.c: (gst_dfbvideosink_surface_create), + (gst_dfbvideosink_event_thread), (gst_dfbvideosink_enum_devices), + (gst_dfbvideosink_setup), (gst_dfbvideosink_cleanup), + (gst_dfbvideosink_can_blit_from_format), + (gst_dfbvideosink_getcaps), (gst_dfbvideosink_setcaps), + (gst_dfbvideosink_show_frame), (gst_dfbvideosink_buffer_alloc), + (gst_dfbsurface_finalize), + (gst_dfbvideosink_navigation_send_event), + (gst_dfbvideosink_update_colorbalance), + (gst_dfbvideosink_set_property), (gst_dfbvideosink_get_property), + (gst_dfbvideosink_finalize), (gst_dfbvideosink_init), + (gst_dfbvideosink_class_init): + * ext/directfb/dfbvideosink.h: Implement pixel-aspect-ratio. + This should work both for hardware accelerated scaling and + reverse caps negotiation with a scaling element. + 2005-12-17 Julien MOUTTE <julien@moutte.net> * docs/plugins/gst-plugins-bad-plugins-decl.txt: diff --git a/docs/plugins/gst-plugins-bad-plugins-decl.txt b/docs/plugins/gst-plugins-bad-plugins-decl.txt index 0d26d3d1..dcd20c0f 100644 --- a/docs/plugins/gst-plugins-bad-plugins-decl.txt +++ b/docs/plugins/gst-plugins-bad-plugins-decl.txt @@ -112,6 +112,9 @@ struct _GstDfbVideoSink { gint hue; gint saturation; gboolean cb_changed; + + /* object-set pixel aspect ratio */ + GValue *par; }; </STRUCT> <STRUCT> diff --git a/docs/plugins/gst-plugins-bad-plugins-undocumented.txt b/docs/plugins/gst-plugins-bad-plugins-undocumented.txt index 3c6b8cfb..69f30a77 100644 --- a/docs/plugins/gst-plugins-bad-plugins-undocumented.txt +++ b/docs/plugins/gst-plugins-bad-plugins-undocumented.txt @@ -1,5 +1,5 @@ 100% symbol docs coverage. -4 symbols documented. +9 symbols documented. 0 symbols incomplete. 0 not documented. diff --git a/ext/directfb/dfbvideosink.c b/ext/directfb/dfbvideosink.c index 1beb4421..b425de61 100644 --- a/ext/directfb/dfbvideosink.c +++ b/ext/directfb/dfbvideosink.c @@ -131,6 +131,7 @@ enum ARG_BRIGHTNESS, ARG_HUE, ARG_SATURATION, + ARG_PIXEL_ASPECT_RATIO, ARG_VSYNC }; @@ -1173,6 +1174,15 @@ gst_dfbvideosink_getcaps (GstBaseSink * bsink) "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + if (!dfbvideosink->hw_scaling && dfbvideosink->par) { + int nom, den; + + nom = gst_value_get_fraction_numerator (dfbvideosink->par); + den = gst_value_get_fraction_denominator (dfbvideosink->par); + gst_structure_set (structure, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } } GST_DEBUG_OBJECT (dfbvideosink, "returning our caps %" GST_PTR_FORMAT, caps); @@ -1207,11 +1217,90 @@ gst_dfbvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps) pixel_format = gst_dfbvideosink_get_format_from_caps (caps); - GST_DEBUG_OBJECT (dfbvideosink, "setcaps called, %dx%d %s video at %d/%d fps", + GST_DEBUG_OBJECT (dfbvideosink, "setcaps called with %" GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (dfbvideosink, "our format is: %dx%d %s video at %d/%d fps", video_width, video_height, gst_dfbvideosink_get_format_name (pixel_format), dfbvideosink->fps_n, dfbvideosink->fps_d); + if (dfbvideosink->hw_scaling && dfbvideosink->par) { + gint video_par_n, video_par_d; /* video's PAR */ + gint display_par_n, display_par_d; /* display's PAR */ + gint num, den; + GValue display_ratio = { 0, }; /* display w/h ratio */ + const GValue *caps_par; + + /* get aspect ratio from caps if it's present, and + * convert video width and height to a display width and height + * using wd / hd = wv / hv * PARv / PARd + * the ratio wd / hd will be stored in display_ratio */ + g_value_init (&display_ratio, GST_TYPE_FRACTION); + + /* get video's PAR */ + caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (caps_par) { + video_par_n = gst_value_get_fraction_numerator (caps_par); + video_par_d = gst_value_get_fraction_denominator (caps_par); + } else { + video_par_n = 1; + video_par_d = 1; + } + /* get display's PAR */ + if (dfbvideosink->par) { + display_par_n = gst_value_get_fraction_numerator (dfbvideosink->par); + display_par_d = gst_value_get_fraction_denominator (dfbvideosink->par); + } else { + display_par_n = 1; + display_par_d = 1; + } + + gst_value_set_fraction (&display_ratio, + video_width * video_par_n * display_par_d, + video_height * video_par_d * display_par_n); + + num = gst_value_get_fraction_numerator (&display_ratio); + den = gst_value_get_fraction_denominator (&display_ratio); + GST_DEBUG_OBJECT (dfbvideosink, + "video width/height: %dx%d, calculated display ratio: %d/%d", + video_width, video_height, num, den); + + /* now find a width x height that respects this display ratio. + * prefer those that have one of w/h the same as the incoming video + * using wd / hd = num / den */ + + /* start with same height, because of interlaced video */ + /* check hd / den is an integer scale factor, and scale wd with the PAR */ + if (video_height % den == 0) { + GST_DEBUG_OBJECT (dfbvideosink, "keeping video height"); + GST_VIDEO_SINK_WIDTH (dfbvideosink) = video_height * num / den; + GST_VIDEO_SINK_HEIGHT (dfbvideosink) = video_height; + } else if (video_width % num == 0) { + GST_DEBUG_OBJECT (dfbvideosink, "keeping video width"); + GST_VIDEO_SINK_WIDTH (dfbvideosink) = video_width; + GST_VIDEO_SINK_HEIGHT (dfbvideosink) = video_width * den / num; + } else { + GST_DEBUG_OBJECT (dfbvideosink, "approximating while keeping height"); + GST_VIDEO_SINK_WIDTH (dfbvideosink) = video_height * num / den; + GST_VIDEO_SINK_HEIGHT (dfbvideosink) = video_height; + } + GST_DEBUG_OBJECT (dfbvideosink, "scaling to %dx%d", + GST_VIDEO_SINK_WIDTH (dfbvideosink), + GST_VIDEO_SINK_HEIGHT (dfbvideosink)); + } else { + if (dfbvideosink->par) { + const GValue *par; + + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (par) { + if (gst_value_compare (par, dfbvideosink->par) != GST_VALUE_EQUAL) { + goto wrong_aspect; + } + } + } + GST_VIDEO_SINK_WIDTH (dfbvideosink) = video_width; + GST_VIDEO_SINK_HEIGHT (dfbvideosink) = video_height; + } + /* Try to adapt the video mode to the video geometry */ if (dfbvideosink->dfb) { DFBResult ret; @@ -1221,8 +1310,9 @@ gst_dfbvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps) "geometry"); /* Set video mode and layer configuration appropriately */ - if (gst_dfbvideosink_get_best_vmode (dfbvideosink, video_width, - video_height, &vmode)) { + if (gst_dfbvideosink_get_best_vmode (dfbvideosink, + GST_VIDEO_SINK_WIDTH (dfbvideosink), + GST_VIDEO_SINK_HEIGHT (dfbvideosink), &vmode)) { DFBDisplayLayerConfig lc; gint width, height, bpp; @@ -1240,22 +1330,21 @@ gst_dfbvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps) "at %d bpp", width, height, bpp); } - lc.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; - lc.width = width; - lc.height = height; + lc.flags = DLCONF_PIXELFORMAT; lc.pixelformat = pixel_format; ret = dfbvideosink->layer->SetConfiguration (dfbvideosink->layer, &lc); if (ret != DFB_OK) { - GST_WARNING_OBJECT (dfbvideosink, "failed setting layer " - "configuration to %dx%d", width, height); + GST_WARNING_OBJECT (dfbvideosink, "failed setting layer pixelformat " + "to %s", gst_dfbvideosink_get_format_name (pixel_format)); } else { - dfbvideosink->out_width = width; - dfbvideosink->out_height = height; - dfbvideosink->pixel_format = pixel_format; + dfbvideosink->layer->GetConfiguration (dfbvideosink->layer, &lc); + dfbvideosink->out_width = lc.width; + dfbvideosink->out_height = lc.height; + dfbvideosink->pixel_format = lc.pixelformat; GST_DEBUG_OBJECT (dfbvideosink, "layer %d now configured to %dx%d %s", - dfbvideosink->layer_id, width, height, - gst_dfbvideosink_get_format_name (pixel_format)); + dfbvideosink->layer_id, lc.width, lc.height, + gst_dfbvideosink_get_format_name (lc.pixelformat)); } } } @@ -1273,6 +1362,13 @@ gst_dfbvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps) beach: return result; + +/* ERRORS */ +wrong_aspect: + { + GST_INFO_OBJECT (dfbvideosink, "pixel aspect ratio does not match"); + return FALSE; + } } static GstStateChangeReturn @@ -1373,22 +1469,13 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf) goto beach; } - if (GST_IS_DFBSURFACE (buf)) { - GstDfbSurface *surface = GST_DFBSURFACE (buf); - - src.w = surface->width; - src.h = surface->height; - } else { - src.w = dfbvideosink->video_width; - src.h = dfbvideosink->video_height; - } - /* If we are rendering from a buffer we did not allocate or to an external * surface, we will memcpy data */ if (!GST_IS_DFBSURFACE (buf) || dfbvideosink->ext_surface) { IDirectFBSurface *dest = NULL, *surface = NULL; gpointer data; gint dest_pitch, src_pitch, line; + GstStructure *structure; /* As we are not blitting no acceleration is possible. If the surface is * too small we do clipping, if it's too big we center. Theoretically as @@ -1405,6 +1492,14 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf) "(vsync %d)", dfbvideosink->vsync); } + structure = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + if (structure) { + gst_structure_get_int (structure, "width", &src.w); + gst_structure_get_int (structure, "height", &src.h); + } else { + src.w = dfbvideosink->video_width; + src.h = dfbvideosink->video_height; + } res = surface->GetSize (surface, &dst.w, &dst.h); /* Center / Clip */ @@ -1459,6 +1554,9 @@ gst_dfbvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf) GST_DEBUG_OBJECT (dfbvideosink, "blitting to a primary surface (vsync %d)", dfbvideosink->vsync); + src.w = GST_VIDEO_SINK_WIDTH (dfbvideosink); + src.h = GST_VIDEO_SINK_HEIGHT (dfbvideosink); + dfbvideosink->primary->GetSize (dfbvideosink->primary, &dst.w, &dst.h); /* Unlocking surface before blit */ @@ -1587,6 +1685,16 @@ gst_dfbvideosink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, gst_structure_set (structure, "width", G_TYPE_INT, result.w, NULL); gst_structure_set (structure, "height", G_TYPE_INT, result.h, NULL); + /* PAR property overrides the X calculated one */ + if (dfbvideosink->par) { + gint nom, den; + + nom = gst_value_get_fraction_numerator (dfbvideosink->par); + den = gst_value_get_fraction_denominator (dfbvideosink->par); + gst_structure_set (structure, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } + if (gst_pad_accept_caps (peer, desired_caps)) { gint bpp; @@ -1767,8 +1875,8 @@ gst_dfbvideosink_navigation_send_event (GstNavigation * navigation, double x, y; GstPad *pad = NULL; - src.w = dfbvideosink->video_width; - src.h = dfbvideosink->video_height; + src.w = GST_VIDEO_SINK_WIDTH (dfbvideosink); + src.h = GST_VIDEO_SINK_HEIGHT (dfbvideosink); dst.w = dfbvideosink->out_width; dst.h = dfbvideosink->out_height; gst_video_sink_center_rect (src, dst, &result, dfbvideosink->hw_scaling); @@ -1966,6 +2074,19 @@ gst_dfbvideosink_set_property (GObject * object, guint prop_id, dfbvideosink->cb_changed = TRUE; gst_dfbvideosink_update_colorbalance (dfbvideosink); break; + case ARG_PIXEL_ASPECT_RATIO: + g_free (dfbvideosink->par); + dfbvideosink->par = g_new0 (GValue, 1); + g_value_init (dfbvideosink->par, GST_TYPE_FRACTION); + if (!g_value_transform (value, dfbvideosink->par)) { + GST_WARNING_OBJECT (dfbvideosink, "Could not transform string to " + "aspect ratio"); + gst_value_set_fraction (dfbvideosink->par, 1, 1); + } + GST_DEBUG_OBJECT (dfbvideosink, "set PAR to %d/%d", + gst_value_get_fraction_numerator (dfbvideosink->par), + gst_value_get_fraction_denominator (dfbvideosink->par)); + break; case ARG_VSYNC: dfbvideosink->vsync = g_value_get_boolean (value); break; @@ -1997,6 +2118,10 @@ gst_dfbvideosink_get_property (GObject * object, guint prop_id, case ARG_SATURATION: g_value_set_int (value, dfbvideosink->saturation); break; + case ARG_PIXEL_ASPECT_RATIO: + if (dfbvideosink->par) + g_value_transform (dfbvideosink->par, value); + break; case ARG_VSYNC: g_value_set_boolean (value, dfbvideosink->vsync); break; @@ -2018,6 +2143,10 @@ gst_dfbvideosink_finalize (GObject * object) dfbvideosink = GST_DFBVIDEOSINK (object); + if (dfbvideosink->par) { + g_free (dfbvideosink->par); + dfbvideosink->par = NULL; + } if (dfbvideosink->pool_lock) { g_mutex_free (dfbvideosink->pool_lock); dfbvideosink->pool_lock = NULL; @@ -2060,6 +2189,8 @@ gst_dfbvideosink_init (GstDfbVideoSink * dfbvideosink) dfbvideosink->contrast = -1; dfbvideosink->hue = -1; dfbvideosink->saturation = -1; + + dfbvideosink->par = NULL; } static void @@ -2107,6 +2238,9 @@ gst_dfbvideosink_class_init (GstDfbVideoSinkClass * klass) g_param_spec_int ("saturation", "Saturation", "The saturation of the video", 0x0000, 0xFFFF, 0x8000, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_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_object_class_install_property (gobject_class, ARG_VSYNC, g_param_spec_boolean ("vsync", "Vertical synchronisation", "Wait for next vertical sync to draw frames", TRUE, diff --git a/ext/directfb/dfbvideosink.h b/ext/directfb/dfbvideosink.h index f62d659a..9bdfbf48 100644 --- a/ext/directfb/dfbvideosink.h +++ b/ext/directfb/dfbvideosink.h @@ -113,6 +113,9 @@ struct _GstDfbVideoSink { gint hue; gint saturation; gboolean cb_changed; + + /* object-set pixel aspect ratio */ + GValue *par; }; struct _GstDfbVideoSinkClass { |