mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 16:08:51 +00:00
gst/videoscale/gstvideoscale.c: Fix negotiation.
Original commit message from CVS: * gst/videoscale/gstvideoscale.c: (gst_videoscale_link): Fix negotiation.
This commit is contained in:
parent
0ca877ffe8
commit
2dd175a86a
2 changed files with 85 additions and 120 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2004-10-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* gst/videoscale/gstvideoscale.c: (gst_videoscale_link):
|
||||||
|
Fix negotiation.
|
||||||
|
|
||||||
2004-10-01 Francis Labonte <francis_labonte@hotmail.com>
|
2004-10-01 Francis Labonte <francis_labonte@hotmail.com>
|
||||||
|
|
||||||
Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
|
@ -212,13 +212,11 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps)
|
||||||
GstVideoscale *videoscale;
|
GstVideoscale *videoscale;
|
||||||
GstPadLinkReturn ret;
|
GstPadLinkReturn ret;
|
||||||
GstPad *otherpad;
|
GstPad *otherpad;
|
||||||
GstCaps *othercaps;
|
GstCaps *othercaps, *newcaps;
|
||||||
GstStructure *otherstructure;
|
GstStructure *otherstructure, *structure, *newstructure;
|
||||||
GstStructure *structure;
|
|
||||||
struct videoscale_format_struct *format;
|
struct videoscale_format_struct *format;
|
||||||
int height = 0, width = 0;
|
int height = 0, width = 0, newwidth, newheight;
|
||||||
const GValue *par = NULL;
|
const GValue *par = NULL, *otherpar;
|
||||||
const GValue *otherpar;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pad, "_link with caps %" GST_PTR_FORMAT, caps);
|
GST_DEBUG_OBJECT (pad, "_link with caps %" GST_PTR_FORMAT, caps);
|
||||||
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
|
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
|
||||||
|
@ -241,15 +239,13 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps)
|
||||||
caps, GST_DEBUG_PAD_NAME (otherpad));
|
caps, GST_DEBUG_PAD_NAME (otherpad));
|
||||||
|
|
||||||
ret = gst_pad_try_set_caps (otherpad, caps);
|
ret = gst_pad_try_set_caps (otherpad, caps);
|
||||||
if (ret == GST_PAD_LINK_OK) {
|
if (GST_PAD_LINK_SUCCESSFUL (ret)) {
|
||||||
/* cool, we can use passthru */
|
/* cool, we can use passthru */
|
||||||
GST_DEBUG_OBJECT (videoscale, "passthru works");
|
GST_DEBUG_OBJECT (videoscale, "passthru works");
|
||||||
|
|
||||||
videoscale->format = format;
|
videoscale->passthru = TRUE;
|
||||||
videoscale->to_width = width;
|
newwidth = width;
|
||||||
videoscale->to_height = height;
|
newheight = height;
|
||||||
videoscale->from_width = width;
|
|
||||||
videoscale->from_height = height;
|
|
||||||
|
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
@ -257,132 +253,96 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps)
|
||||||
/* no passthru, so try to convert */
|
/* no passthru, so try to convert */
|
||||||
GST_DEBUG_OBJECT (videoscale, "no passthru");
|
GST_DEBUG_OBJECT (videoscale, "no passthru");
|
||||||
|
|
||||||
if (gst_pad_is_negotiated (otherpad)) {
|
/* copy caps to find which one works for the otherpad */
|
||||||
GstCaps *newcaps = gst_caps_copy (caps);
|
newcaps = gst_caps_copy (caps);
|
||||||
|
newstructure = gst_caps_get_structure (newcaps, 0);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "otherpad %s:%s is negotiated",
|
/* iterate over other pad's caps, find a nice conversion.
|
||||||
GST_DEBUG_PAD_NAME (otherpad));
|
* For calculations, we only use the first because we
|
||||||
|
* (falsely) assume that all caps have the same PAR and
|
||||||
|
* size values. */
|
||||||
|
othercaps = gst_pad_get_allowed_caps (otherpad);
|
||||||
|
otherstructure = gst_caps_get_structure (othercaps, 0);
|
||||||
|
otherpar = gst_structure_get_value (otherstructure, "pixel-aspect-ratio");
|
||||||
|
if (par && otherpar) {
|
||||||
|
gint num = gst_value_get_fraction_numerator (par),
|
||||||
|
den = gst_value_get_fraction_denominator (par),
|
||||||
|
onum = gst_value_get_fraction_numerator (otherpar),
|
||||||
|
oden = gst_value_get_fraction_denominator (otherpar);
|
||||||
|
gboolean keep_h,
|
||||||
|
w_align = (width * num * oden % (den * onum) == 0),
|
||||||
|
h_align = (height * den * onum % (num * oden) == 0),
|
||||||
|
w_inc = (num * oden > den * onum);
|
||||||
|
|
||||||
if (pad == videoscale->srcpad) {
|
/* decide whether to change width or height */
|
||||||
gst_caps_set_simple (newcaps,
|
if (w_align && w_inc)
|
||||||
"width", G_TYPE_INT, videoscale->from_width,
|
keep_h = TRUE;
|
||||||
"height", G_TYPE_INT, videoscale->from_height, NULL);
|
else if (h_align && !w_inc)
|
||||||
if (videoscale->from_par) {
|
keep_h = FALSE;
|
||||||
GST_DEBUG_OBJECT (videoscale, "from par %d/%d",
|
else if (w_align)
|
||||||
gst_value_get_fraction_numerator (videoscale->from_par),
|
keep_h = TRUE;
|
||||||
gst_value_get_fraction_denominator (videoscale->from_par));
|
else if (h_align)
|
||||||
gst_structure_set (gst_caps_get_structure (newcaps, 0),
|
keep_h = FALSE;
|
||||||
"pixel-aspect-ratio", GST_TYPE_FRACTION,
|
else
|
||||||
gst_value_get_fraction_numerator (videoscale->from_par),
|
keep_h = w_inc;
|
||||||
gst_value_get_fraction_denominator (videoscale->from_par), NULL);
|
|
||||||
}
|
/* take par into effect */
|
||||||
|
if (keep_h) {
|
||||||
|
newwidth = width * num / den;
|
||||||
|
newheight = height;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (videoscale, "negotiating, checking PAR's");
|
newwidth = width;
|
||||||
/* sink pad is being negotiated, so if there is a PAR,
|
newheight = height * den / num;
|
||||||
* convert w/h/PAR to new src
|
|
||||||
* values and try to set them */
|
|
||||||
if (par && videoscale->to_par) {
|
|
||||||
GValue to_ratio = { 0, };
|
|
||||||
gint from_par_n, from_par_d;
|
|
||||||
gint to_par_n, to_par_d;
|
|
||||||
gint num, den;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "both pads have PAR, calculating");
|
|
||||||
from_par_n = gst_value_get_fraction_numerator (par);
|
|
||||||
from_par_d = gst_value_get_fraction_denominator (par);
|
|
||||||
to_par_n = gst_value_get_fraction_numerator (videoscale->to_par);
|
|
||||||
to_par_d = gst_value_get_fraction_denominator (videoscale->to_par);
|
|
||||||
g_value_init (&to_ratio, GST_TYPE_FRACTION);
|
|
||||||
gst_value_set_fraction (&to_ratio,
|
|
||||||
width * from_par_n * to_par_d, height * from_par_d * to_par_n);
|
|
||||||
num = gst_value_get_fraction_numerator (&to_ratio);
|
|
||||||
den = gst_value_get_fraction_denominator (&to_ratio);
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "need to scale to a ratio of %d/%d",
|
|
||||||
num, den);
|
|
||||||
if (height % den == 0) {
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "keeping height %d constant", height);
|
|
||||||
videoscale->to_width = height * num / den;
|
|
||||||
videoscale->to_height = height;
|
|
||||||
} else if (width % num == 0) {
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "keeping width %d constant", height);
|
|
||||||
videoscale->to_width = width;
|
|
||||||
videoscale->to_height = width * den / num;
|
|
||||||
} else {
|
|
||||||
/* approximate keeping height constant */
|
|
||||||
GST_DEBUG_OBJECT (videoscale,
|
|
||||||
"approximating while keeping height %d constant", height);
|
|
||||||
videoscale->to_width = height * num / den;
|
|
||||||
videoscale->to_height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "scaling to %dx%d", videoscale->to_width,
|
|
||||||
videoscale->to_height);
|
|
||||||
gst_caps_set_simple (newcaps,
|
|
||||||
"width", G_TYPE_INT, videoscale->to_width,
|
|
||||||
"height", G_TYPE_INT, videoscale->to_height, NULL);
|
|
||||||
if (videoscale->to_par) {
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "to par %d/%d",
|
|
||||||
gst_value_get_fraction_numerator (videoscale->to_par),
|
|
||||||
gst_value_get_fraction_denominator (videoscale->to_par));
|
|
||||||
gst_structure_set (gst_caps_get_structure (newcaps, 0),
|
|
||||||
"pixel-aspect-ratio", GST_TYPE_FRACTION,
|
|
||||||
gst_value_get_fraction_numerator (videoscale->to_par),
|
|
||||||
gst_value_get_fraction_denominator (videoscale->to_par), NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "trying to set caps %" GST_PTR_FORMAT
|
|
||||||
" on pad %s:%s", newcaps, GST_DEBUG_PAD_NAME (otherpad));
|
|
||||||
ret = gst_pad_try_set_caps (otherpad, newcaps);
|
|
||||||
if (GST_PAD_LINK_FAILED (ret)) {
|
|
||||||
return GST_PAD_LINK_REFUSED;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* (at least) one has no par, so it should accept the other */
|
||||||
|
newwidth = width;
|
||||||
|
newheight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* size: don't check return values. We honestly don't care. */
|
||||||
|
gst_structure_set_value (newstructure, "width",
|
||||||
|
gst_structure_get_value (otherstructure, "width"));
|
||||||
|
gst_structure_set_value (newstructure, "height",
|
||||||
|
gst_structure_get_value (otherstructure, "height"));
|
||||||
|
gst_caps_structure_fixate_field_nearest_int (newstructure, "width", newwidth);
|
||||||
|
gst_caps_structure_fixate_field_nearest_int (newstructure,
|
||||||
|
"height", newheight);
|
||||||
|
gst_structure_get_int (newstructure, "width", &newwidth);
|
||||||
|
gst_structure_get_int (newstructure, "height", &newheight);
|
||||||
|
|
||||||
|
/* obviously, keep PAR if we got one */
|
||||||
|
if (otherpar)
|
||||||
|
gst_structure_set_value (newstructure, "pixel-aspect-ratio", otherpar);
|
||||||
|
GST_DEBUG_OBJECT (videoscale,
|
||||||
|
"trying to set caps %" GST_PTR_FORMAT " on pad %s:%s for non-passthru",
|
||||||
|
caps, GST_DEBUG_PAD_NAME (otherpad));
|
||||||
|
|
||||||
|
/* try - bail out if fail */
|
||||||
|
ret = gst_pad_try_set_caps (otherpad, newcaps);
|
||||||
|
if (GST_PAD_LINK_FAILED (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
videoscale->passthru = FALSE;
|
videoscale->passthru = FALSE;
|
||||||
GST_DEBUG_OBJECT (videoscale,
|
|
||||||
"no passthru, otherpad %s:%s is not negotiated",
|
|
||||||
GST_DEBUG_PAD_NAME (otherpad));
|
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
/* since we're accepting these caps on this pad, we can store the
|
/* whee, works. Save for use in _chain and get moving. */
|
||||||
* values we're using in conversion, like from/to w,h,PAR */
|
|
||||||
othercaps = gst_pad_get_caps (otherpad);
|
|
||||||
otherstructure = gst_caps_get_structure (othercaps, 0);
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
|
||||||
|
|
||||||
par = gst_structure_get_value (structure, "pixel-aspect-ratio");
|
|
||||||
otherpar = gst_structure_get_value (otherstructure, "pixel-aspect-ratio");
|
|
||||||
GST_DEBUG ("othercaps: %" GST_PTR_FORMAT, othercaps);
|
|
||||||
if (par && otherpar) {
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "par %d/%d, otherpar %d/%d",
|
|
||||||
gst_value_get_fraction_numerator (par),
|
|
||||||
gst_value_get_fraction_denominator (par),
|
|
||||||
gst_value_get_fraction_numerator (otherpar),
|
|
||||||
gst_value_get_fraction_denominator (otherpar));
|
|
||||||
}
|
|
||||||
if (pad == videoscale->srcpad) {
|
if (pad == videoscale->srcpad) {
|
||||||
videoscale->to_width = width;
|
videoscale->to_width = width;
|
||||||
videoscale->to_height = height;
|
videoscale->to_height = height;
|
||||||
if (par) {
|
videoscale->from_width = newwidth;
|
||||||
g_free (videoscale->to_par);
|
videoscale->from_height = newheight;
|
||||||
videoscale->to_par = g_new0 (GValue, 1);
|
|
||||||
gst_value_init_and_copy (videoscale->to_par, par);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
videoscale->from_width = width;
|
videoscale->from_width = width;
|
||||||
videoscale->from_height = height;
|
videoscale->from_height = height;
|
||||||
if (par) {
|
videoscale->to_width = newwidth;
|
||||||
g_free (videoscale->from_par);
|
videoscale->to_height = newheight;
|
||||||
videoscale->from_par = g_new0 (GValue, 1);
|
|
||||||
gst_value_init_and_copy (videoscale->from_par, par);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
videoscale->format = format;
|
videoscale->format = format;
|
||||||
|
gst_videoscale_setup (videoscale);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videoscale, "work completed");
|
||||||
|
|
||||||
if (gst_pad_is_negotiated (otherpad)) {
|
|
||||||
gst_videoscale_setup (videoscale);
|
|
||||||
}
|
|
||||||
return GST_PAD_LINK_OK;
|
return GST_PAD_LINK_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue