summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-decl.txt3
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-undocumented.txt2
-rw-r--r--ext/directfb/dfbvideosink.c184
-rw-r--r--ext/directfb/dfbvideosink.h3
5 files changed, 186 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 0e37d2cd..8813e4ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 {