From cc2e1fab4420edfd5eb9819e03261f004fb0ee41 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Tue, 27 Jul 2004 16:43:24 +0000 Subject: [PATCH] pixel aspect ratio handling Original commit message from CVS: pixel aspect ratio handling --- ChangeLog | 33 +++ ext/theora/theoradec.c | 17 ++ ext/theora/theoraenc.c | 14 +- gst/ffmpegcolorspace/gstffmpegcolorspace.c | 23 +- gst/videoscale/gstvideoscale.c | 241 ++++++++++++++++++++- gst/videoscale/gstvideoscale.h | 2 + gst/videotestsrc/gstvideotestsrc.c | 1 + sys/ximage/ximagesink.c | 124 ++++++++++- sys/ximage/ximagesink.h | 5 + sys/xvimage/xvimagesink.c | 156 +++++++++++-- sys/xvimage/xvimagesink.h | 9 +- 11 files changed, 574 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7097321b19..ca913ab22e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2004-07-27 Thomas Vander Stichele + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_metadata), + (gst_matroska_demux_video_caps), (gst_matroska_demux_plugin_init): + * gst/mpegaudio/common.c: + * gst/videoscale/gstvideoscale.c: (gst_videoscale_class_init), + (gst_videoscale_getcaps), (gst_videoscale_link), + (gst_videoscale_src_fixate), (gst_videoscale_init), + (gst_videoscale_finalize): + * gst/videoscale/gstvideoscale.h: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_get_capslist): + * gst/wavenc/gstwavenc.c: + * sys/oss/gstossmixer.c: (fill_labels): + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_handle_xevents), + (gst_ximagesink_calculate_pixel_aspect_ratio), + (gst_ximagesink_xcontext_get), (gst_ximagesink_fixate), + (gst_ximagesink_getcaps), (gst_ximagesink_sink_link), + (gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_set_property), (gst_ximagesink_get_property), + (gst_ximagesink_init), (gst_ximagesink_class_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio), + (gst_xvimagesink_xcontext_get), (gst_xvimagesink_sink_link), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + first batch of pixel aspect ratio commits. + 2004-07-27 Thomas Vander Stichele * gst/ffmpegcolorspace/gstffmpegcolorspace.c: diff --git a/ext/theora/theoradec.c b/ext/theora/theoradec.c index 91de86a046..e056b84d87 100644 --- a/ext/theora/theoradec.c +++ b/ext/theora/theoradec.c @@ -532,6 +532,22 @@ theora_dec_chain (GstPad * pad, GstData * data) gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, 0, list); } else if (packet.packetno == 2) { GstCaps *caps; + gint par_num, par_den; + + GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d", + dec->info.fps_numerator, dec->info.fps_denominator, + dec->info.aspect_numerator, dec->info.aspect_denominator); + + /* calculate par + * the info.aspect_* values reflect PAR; + * 0:0 is allowed and can be interpreted as 1:1, so correct for it */ + par_num = dec->info.aspect_numerator; + par_den = dec->info.aspect_denominator; + if (par_num == 0 && par_den == 0) { + par_num = par_den = 1; + } + GST_DEBUG_OBJECT (dec, "video %dx%d, PAR %d/%d", dec->info.width, + dec->info.height, par_num, par_den); /* done */ theora_decode_init (&dec->state, &dec->info); @@ -539,6 +555,7 @@ theora_dec_chain (GstPad * pad, GstData * data) "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), "framerate", G_TYPE_DOUBLE, ((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den, "width", G_TYPE_INT, dec->info.width, "height", G_TYPE_INT, dec->info.height, NULL); gst_pad_set_explicit_caps (dec->srcpad, caps); diff --git a/ext/theora/theoraenc.c b/ext/theora/theoraenc.c index b4539f32ab..34491fd525 100644 --- a/ext/theora/theoraenc.c +++ b/ext/theora/theoraenc.c @@ -234,6 +234,7 @@ theora_enc_sink_link (GstPad * pad, const GstCaps * caps) { GstStructure *structure = gst_caps_get_structure (caps, 0); GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad)); + const GValue *par; if (!gst_caps_is_fixed (caps)) return GST_PAD_LINK_DELAYED; @@ -241,6 +242,7 @@ theora_enc_sink_link (GstPad * pad, const GstCaps * caps) gst_structure_get_int (structure, "width", &enc->width); gst_structure_get_int (structure, "height", &enc->height); gst_structure_get_double (structure, "framerate", &enc->fps); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); /* Theora has a divisible-by-sixteen restriction for the encoded video size */ if ((enc->width & 0x0f) != 0 || (enc->height & 0x0f) != 0) @@ -257,9 +259,15 @@ theora_enc_sink_link (GstPad * pad, const GstCaps * caps) /* do some scaling, we really need fractions in structures... */ enc->info.fps_numerator = enc->fps * 10000000; enc->info.fps_denominator = 10000000; - enc->info.aspect_numerator = 1; - enc->info.aspect_denominator = 1; - /* */ + if (par) { + enc->info.aspect_numerator = gst_value_get_fraction_numerator (par); + enc->info.aspect_denominator = gst_value_get_fraction_denominator (par); + } else { + /* setting them to 0 indicates that the decoder can chose a good aspect + * ratio, defaulting to 1/1 */ + enc->info.aspect_numerator = 0; + enc->info.aspect_denominator = 0; + } enc->info.colorspace = OC_CS_UNSPECIFIED; enc->info.target_bitrate = enc->video_bitrate; diff --git a/gst/ffmpegcolorspace/gstffmpegcolorspace.c b/gst/ffmpegcolorspace/gstffmpegcolorspace.c index b3183340c2..ad176e519f 100644 --- a/gst/ffmpegcolorspace/gstffmpegcolorspace.c +++ b/gst/ffmpegcolorspace/gstffmpegcolorspace.c @@ -175,20 +175,25 @@ gst_ffmpegcolorspace_pad_link (GstPad * pad, const GstCaps * caps) enum PixelFormat pix_fmt; int height, width; double framerate; + const GValue *par = NULL; space = GST_FFMPEGCOLORSPACE (gst_pad_get_parent (pad)); + GST_DEBUG_OBJECT (space, "pad_link on %s:%s with caps %" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (pad), caps); structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); gst_structure_get_double (structure, "framerate", &framerate); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (par) { + GST_DEBUG_OBJECT (space, "setting PAR %d/%d", + gst_value_get_fraction_numerator (par), + gst_value_get_fraction_denominator (par)); + } otherpad = (pad == space->srcpad) ? space->sinkpad : space->srcpad; - GST_DEBUG_OBJECT (space, "pad_link on %s:%s with caps %" GST_PTR_FORMAT, - GST_DEBUG_PAD_NAME (pad), caps); - /* FIXME attempt and/or check for passthru */ /* loop over all possibilities and select the first one we can convert and @@ -205,7 +210,6 @@ gst_ffmpegcolorspace_pad_link (GstPad * pad, const GstCaps * caps) return GST_PAD_LINK_REFUSED; } - /* set the size on the otherpad */ othercaps = gst_pad_get_negotiated_caps (otherpad); if (othercaps) { @@ -215,6 +219,15 @@ gst_ffmpegcolorspace_pad_link (GstPad * pad, const GstCaps * caps) "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", G_TYPE_DOUBLE, framerate, NULL); + if (par) { + GST_DEBUG_OBJECT (space, "setting PAR %d/%d", + gst_value_get_fraction_numerator (par), + gst_value_get_fraction_denominator (par)); + gst_caps_set_simple (newothercaps, + "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (par), + gst_value_get_fraction_denominator (par), NULL); + } ret = gst_pad_try_set_caps (otherpad, newothercaps); if (GST_PAD_LINK_FAILED (ret)) { return ret; diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c index c87d4ed151..510960f8aa 100644 --- a/gst/videoscale/gstvideoscale.c +++ b/gst/videoscale/gstvideoscale.c @@ -108,6 +108,7 @@ static void gst_videoscale_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_videoscale_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_videoscale_finalize (GObject * object); static void gst_videoscale_chain (GstPad * pad, GstData * _data); static GstCaps *gst_videoscale_get_capslist (void); @@ -166,6 +167,7 @@ gst_videoscale_class_init (GstVideoscaleClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->finalize = gst_videoscale_finalize; gobject_class->set_property = gst_videoscale_set_property; gobject_class->get_property = gst_videoscale_get_property; @@ -180,14 +182,14 @@ gst_videoscale_getcaps (GstPad * pad) GstPad *otherpad; int i; - GST_DEBUG ("gst_videoscale_getcaps"); videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad)); otherpad = (pad == videoscale->srcpad) ? videoscale->sinkpad : videoscale->srcpad; othercaps = gst_pad_get_allowed_caps (otherpad); - GST_DEBUG ("othercaps are: %" GST_PTR_FORMAT, othercaps); + GST_DEBUG_OBJECT (pad, "othercaps of otherpad %s:%s are: %" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (otherpad), othercaps); caps = gst_caps_copy (othercaps); for (i = 0; i < gst_caps_get_size (caps); i++) { @@ -196,10 +198,10 @@ gst_videoscale_getcaps (GstPad * pad) gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 16, G_MAXINT, "height", GST_TYPE_INT_RANGE, 16, G_MAXINT, NULL); + gst_structure_remove_field (structure, "pixel-aspect-ratio"); } - GST_DEBUG ("returning caps: %" GST_PTR_FORMAT, caps); - + GST_DEBUG_OBJECT (pad, "returning caps: %" GST_PTR_FORMAT, caps); return caps; } @@ -210,9 +212,13 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps) GstVideoscale *videoscale; GstPadLinkReturn ret; GstPad *otherpad; + GstCaps *othercaps; + GstStructure *otherstructure; GstStructure *structure; struct videoscale_format_struct *format; - int height, width; + int height = 0, width = 0; + const GValue *par = NULL; + const GValue *otherpar; GST_DEBUG_OBJECT (pad, "_link with caps %" GST_PTR_FORMAT, caps); videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad)); @@ -223,15 +229,21 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps) structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "width", &width); ret &= gst_structure_get_int (structure, "height", &height); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); format = videoscale_find_by_structure (structure); if (!ret || format == NULL) return GST_PAD_LINK_REFUSED; + GST_DEBUG_OBJECT (videoscale, + "trying to set caps %" GST_PTR_FORMAT " on pad %s:%s for passthru", + caps, GST_DEBUG_PAD_NAME (otherpad)); + ret = gst_pad_try_set_caps (otherpad, caps); if (ret == GST_PAD_LINK_OK) { /* cool, we can use passthru */ + GST_DEBUG_OBJECT (videoscale, "passthru works"); videoscale->format = format; videoscale->to_width = width; @@ -239,23 +251,88 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps) videoscale->from_width = width; videoscale->from_height = height; - gst_videoscale_setup (videoscale); - - return GST_PAD_LINK_OK; + goto beach; } + /* no passthru, so try to convert */ + GST_DEBUG_OBJECT (videoscale, "no passthru"); + if (gst_pad_is_negotiated (otherpad)) { GstCaps *newcaps = gst_caps_copy (caps); + GST_DEBUG_OBJECT (videoscale, "otherpad %s:%s is negotiated", + GST_DEBUG_PAD_NAME (otherpad)); + if (pad == videoscale->srcpad) { gst_caps_set_simple (newcaps, "width", G_TYPE_INT, videoscale->from_width, "height", G_TYPE_INT, videoscale->from_height, NULL); + GST_DEBUG_OBJECT (videoscale, "from par %d/%d", + gst_value_get_fraction_numerator (videoscale->from_par), + gst_value_get_fraction_denominator (videoscale->from_par)); + if (videoscale->from_par) { + gst_structure_set (gst_caps_get_structure (newcaps, 0), + "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (videoscale->from_par), + gst_value_get_fraction_denominator (videoscale->from_par), NULL); + } } else { + GST_DEBUG_OBJECT (videoscale, "negotiating, checking PAR's"); + /* sink pad is being negotiated, so if there is a PAR, + * 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; @@ -263,23 +340,154 @@ gst_videoscale_link (GstPad * pad, const GstCaps * caps) } videoscale->passthru = FALSE; + GST_DEBUG_OBJECT (videoscale, + "no passthru, otherpad %s:%s is not negotiated", + GST_DEBUG_PAD_NAME (otherpad)); +beach: + /* since we're accepting these caps on this pad, we can store the + * 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) { videoscale->to_width = width; videoscale->to_height = height; + if (par) { + g_free (videoscale->to_par); + videoscale->to_par = g_new0 (GValue, 1); + gst_value_init_and_copy (videoscale->to_par, par); + } } else { videoscale->from_width = width; videoscale->from_height = height; + if (par) { + g_free (videoscale->from_par); + videoscale->from_par = g_new0 (GValue, 1); + gst_value_init_and_copy (videoscale->from_par, par); + } } videoscale->format = format; if (gst_pad_is_negotiated (otherpad)) { gst_videoscale_setup (videoscale); } - return GST_PAD_LINK_OK; } +static GstCaps * +gst_videoscale_src_fixate (GstPad * pad, const GstCaps * caps) +{ + GstVideoscale *videoscale; + GstCaps *newcaps; + int i; + gboolean ret = TRUE; + + videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "asked to fixate caps %" GST_PTR_FORMAT, caps); + + /* don't mess with fixation if we don't have a sink pad PAR */ + if (!videoscale->from_par) { + GST_DEBUG_OBJECT (videoscale, "no PAR to scale from, not fixating"); + return NULL; + } + + /* for each structure, if it contains a pixel aspect ratio, + * fix width and height */ + + newcaps = gst_caps_copy (caps); + for (i = 0; i < gst_caps_get_size (newcaps); i++) { + const GValue *to_par; + + GstStructure *structure = gst_caps_get_structure (newcaps, i); + + to_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (to_par) { + GValue to_ratio = { 0, }; /* w/h of output video */ + int from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d; + int count = 0; + + int w = 0, h = 0; + int num, den; + + /* if both width and height are already fixed, we can't do anything + * about it anymore */ + if (gst_structure_get_int (structure, "width", &w)) + ++count; + if (gst_structure_get_int (structure, "height", &h)) + ++count; + if (count == 2) { + GST_DEBUG_OBJECT (videoscale, + "dimensions already set to %dx%d, not fixating", w, h); + return NULL; + } + + from_w = videoscale->from_width; + from_h = videoscale->from_height; + from_par_n = gst_value_get_fraction_numerator (videoscale->from_par); + from_par_d = gst_value_get_fraction_denominator (videoscale->from_par); + to_par_n = gst_value_get_fraction_numerator (to_par); + to_par_d = gst_value_get_fraction_denominator (to_par); + + g_value_init (&to_ratio, GST_TYPE_FRACTION); + gst_value_set_fraction (&to_ratio, from_w * from_par_n * to_par_d, + from_h * 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, + "scaling input with %dx%d and PAR %d/%d to output PAR %d/%d", + from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d); + GST_DEBUG_OBJECT (videoscale, + "resulting output should respect ratio of %d/%d", 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 (from_h % den == 0) { + GST_DEBUG_OBJECT (videoscale, "keeping video height"); + h = from_h; + w = h * num / den; + } else if (from_w % num == 0) { + GST_DEBUG_OBJECT (videoscale, "keeping video width"); + w = from_w; + h = w * den / num; + } else { + GST_DEBUG_OBJECT (videoscale, "approximating but keeping video height"); + h = from_h; + w = h * num / den; + } + GST_DEBUG_OBJECT (videoscale, "scaling to %dx%d", w, h); + + /* now fixate */ + ret &= + gst_caps_structure_fixate_field_nearest_int (structure, "width", w); + ret &= + gst_caps_structure_fixate_field_nearest_int (structure, "height", h); + } + } + + if (ret) + return newcaps; + + gst_caps_free (newcaps); + return NULL; +} + static void gst_videoscale_init (GstVideoscale * videoscale) { @@ -299,6 +507,7 @@ gst_videoscale_init (GstVideoscale * videoscale) gst_videoscale_handle_src_event); gst_pad_set_link_function (videoscale->srcpad, gst_videoscale_link); gst_pad_set_getcaps_function (videoscale->srcpad, gst_videoscale_getcaps); + gst_pad_set_fixate_function (videoscale->srcpad, gst_videoscale_src_fixate); videoscale->inited = FALSE; @@ -439,6 +648,20 @@ gst_videoscale_get_property (GObject * object, guint prop_id, GValue * value, } } +/* maybe these free's should go in a state change instead; + * in that case, we'd probably also want to clear from/to width/height there. */ +static void +gst_videoscale_finalize (GObject * object) +{ + GstVideoscale *videoscale; + + videoscale = GST_VIDEOSCALE (object); + + g_free (videoscale->from_par); + g_free (videoscale->to_par); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} static gboolean plugin_init (GstPlugin * plugin) diff --git a/gst/videoscale/gstvideoscale.h b/gst/videoscale/gstvideoscale.h index 124ffb0078..bed396f858 100644 --- a/gst/videoscale/gstvideoscale.h +++ b/gst/videoscale/gstvideoscale.h @@ -66,6 +66,8 @@ struct _GstVideoscale { gint to_height; gint from_width; gint from_height; + GValue *to_par; /* pixel aspect ratio of sink pad */ + GValue *from_par; /* pixel aspect ratio of src pad */ gboolean passthru; float framerate; diff --git a/gst/videotestsrc/gstvideotestsrc.c b/gst/videotestsrc/gstvideotestsrc.c index ada6b85e97..adc52f6828 100644 --- a/gst/videotestsrc/gstvideotestsrc.c +++ b/gst/videotestsrc/gstvideotestsrc.c @@ -304,6 +304,7 @@ gst_videotestsrc_get_capslist (void) gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL); gst_caps_append_structure (caps, structure); } diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c index 5f9d4f93ce..2326cd1f4f 100644 --- a/sys/ximage/ximagesink.c +++ b/sys/ximage/ximagesink.c @@ -71,7 +71,8 @@ enum { ARG_0, ARG_DISPLAY, - ARG_SYNCHRONOUS + ARG_SYNCHRONOUS, + ARG_PIXEL_ASPECT_RATIO /* FILL ME */ }; @@ -541,6 +542,10 @@ gst_ximagesink_renegotiate_size (GstXImageSink * ximagesink) "blue_mask", G_TYPE_INT, ximagesink->xcontext->visual->blue_mask, "width", G_TYPE_INT, ximagesink->xwindow->width, "height", G_TYPE_INT, ximagesink->xwindow->height, + /* for now we use the object-set value for par */ + "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (&ximagesink->par), + gst_value_get_fraction_denominator (&ximagesink->par), "framerate", G_TYPE_DOUBLE, ximagesink->framerate, NULL)); if ((r == GST_PAD_LINK_OK) || (r == GST_PAD_LINK_DONE)) { @@ -652,12 +657,55 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink, GstPad * pad) default: GST_DEBUG ("ximagesink unhandled X event (%d)", e.type); } - g_mutex_lock (ximagesink->x_lock); } g_mutex_unlock (ximagesink->x_lock); } +/* This function calculates the pixel aspect ratio based on the properties + * in the xcontext structure and stores it there. */ +static void +gst_ximagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) +{ + gint par[][2] = { + {1, 1}, /* regular screen */ + {16, 15}, /* PAL TV */ + {11, 10}, /* 525 line Rec.601 video */ + {54, 59} /* 625 line Rec.601 video */ + }; + gint i; + gint index; + gdouble ratio; + gdouble delta; + +#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1]))) + + /* first calculate the "real" ratio based on the X values; + * which is the "physical" w/h divided by the w/h in pixels of the display */ + ratio = xcontext->widthmm * xcontext->height + / (xcontext->heightmm * xcontext->width); + GST_DEBUG ("calculated pixel aspect ratio: %f", ratio); + + /* now find the one from par[][2] with the lowest delta to the real one */ + delta = DELTA (0); + index = 0; + + for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) { + gdouble this_delta = DELTA (i); + + if (this_delta < delta) { + index = i; + delta = this_delta; + } + } + + GST_DEBUG ("Decided on index %d (%d/%d)", index, + par[index][0], par[index][1]); + + g_value_init (&xcontext->par, GST_TYPE_FRACTION); + gst_value_set_fraction (&xcontext->par, par[index][0], par[index][1]); +} + /* This function gets the X Display and global info about it. Everything is stored in our object and will be cleaned when the object is disposed. Note here that caps for supported format are generated without any window or @@ -693,6 +741,13 @@ gst_ximagesink_xcontext_get (GstXImageSink * ximagesink) xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num); xcontext->depth = DefaultDepthOfScreen (xcontext->screen); + xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); + xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); + xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num); + xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num); + + gst_ximagesink_calculate_pixel_aspect_ratio (xcontext); + /* We get supported pixmap formats at supported depth */ px_formats = XListPixmapFormats (xcontext->disp, &nb_formats); @@ -750,6 +805,10 @@ gst_ximagesink_xcontext_get (GstXImageSink * ximagesink) "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + /* for now we use the object-set value for par */ + "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (&ximagesink->par), + gst_value_get_fraction_denominator (&ximagesink->par), "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL); g_mutex_unlock (ximagesink->x_lock); @@ -805,6 +864,8 @@ gst_ximagesink_fixate (GstPad * pad, const GstCaps * caps) newcaps = gst_caps_copy (caps); structure = gst_caps_get_structure (newcaps, 0); + /* if par is set and either w or h is set, we can set the other */ + if (gst_caps_structure_fixate_field_nearest_int (structure, "width", 320)) { return newcaps; } @@ -824,13 +885,24 @@ static GstCaps * gst_ximagesink_getcaps (GstPad * pad) { GstXImageSink *ximagesink; + GstCaps *caps; + int i; ximagesink = GST_XIMAGESINK (gst_pad_get_parent (pad)); if (ximagesink->xcontext) return gst_caps_copy (ximagesink->xcontext->caps); - return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + /* get a template copy and add the pixel aspect ratio */ + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + for (i = 0; i < gst_caps_get_size (caps); ++i) { + GstStructure *structure = gst_caps_get_structure (caps, i); + + gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (&ximagesink->par), + gst_value_get_fraction_denominator (&ximagesink->par), NULL); + } + return caps; } static GstPadLinkReturn @@ -839,6 +911,7 @@ gst_ximagesink_sink_link (GstPad * pad, const GstCaps * caps) GstXImageSink *ximagesink; gboolean ret; GstStructure *structure; + const GValue *par; ximagesink = GST_XIMAGESINK (gst_pad_get_parent (pad)); @@ -859,11 +932,15 @@ gst_ximagesink_sink_link (GstPad * pad, const GstCaps * caps) if (!ret) return GST_PAD_LINK_REFUSED; - ximagesink->pixel_width = 1; - gst_structure_get_int (structure, "pixel_width", &ximagesink->pixel_width); - - ximagesink->pixel_height = 1; - gst_structure_get_int (structure, "pixel_height", &ximagesink->pixel_height); + /* if the caps contain pixel-aspect-ratio, they have to match ours, + * otherwise linking should fail */ + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (par) { + if (gst_value_compare (par, &ximagesink->par) != GST_VALUE_EQUAL) { + GST_INFO_OBJECT (ximagesink, "pixel aspect ratio does not match"); + return GST_PAD_LINK_REFUSED; + } + } /* Creating our window and our image */ g_assert (GST_VIDEOSINK_WIDTH (ximagesink) > 0); @@ -985,10 +1062,12 @@ gst_ximagesink_chain (GstPad * pad, GstData * data) /* If this buffer has been allocated using our buffer management we simply put the ximage which is in the PRIVATE pointer */ if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_ximagesink_buffer_free) { + GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly"); gst_ximagesink_ximage_put (ximagesink, GST_BUFFER_PRIVATE (buf)); } else { /* Else we have to copy the data into our private image, */ /* if we have one... */ + GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it"); if (!ximagesink->ximage) { GST_DEBUG_OBJECT (ximagesink, "creating our ximage"); ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink, @@ -1232,9 +1311,15 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id) "endianness", G_TYPE_INT, ximagesink->xcontext->endianness, "red_mask", G_TYPE_INT, ximagesink->xcontext->visual->red_mask, "green_mask", G_TYPE_INT, - ximagesink->xcontext->visual->green_mask, "blue_mask", G_TYPE_INT, - ximagesink->xcontext->visual->blue_mask, "width", G_TYPE_INT, - xwindow->width, "height", G_TYPE_INT, xwindow->height, + ximagesink->xcontext->visual->green_mask, + "blue_mask", G_TYPE_INT, + ximagesink->xcontext->visual->blue_mask, + "width", G_TYPE_INT, xwindow->width, + "height", G_TYPE_INT, xwindow->height, + /* for now we use the object-set value for par */ + "pixel-aspect-ratio", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (&ximagesink->par), + gst_value_get_fraction_denominator (&ximagesink->par), "framerate", G_TYPE_DOUBLE, ximagesink->framerate, NULL)); /* If caps nego succeded updating our size */ @@ -1316,6 +1401,13 @@ gst_ximagesink_set_property (GObject * object, guint prop_id, XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous); } break; + case ARG_PIXEL_ASPECT_RATIO: + if (!g_value_transform (value, &ximagesink->par)) + g_warning ("Could not transform string to aspect ratio"); + GST_DEBUG_OBJECT (ximagesink, "set PAR to %d/%d", + gst_value_get_fraction_numerator (&ximagesink->par), + gst_value_get_fraction_denominator (&ximagesink->par)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1339,6 +1431,9 @@ gst_ximagesink_get_property (GObject * object, guint prop_id, case ARG_SYNCHRONOUS: g_value_set_boolean (value, ximagesink->synchronous); break; + case ARG_PIXEL_ASPECT_RATIO: + g_value_transform (&ximagesink->par, value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1394,7 +1489,6 @@ gst_ximagesink_init (GstXImageSink * ximagesink) ximagesink->x_lock = g_mutex_new (); - ximagesink->pixel_width = ximagesink->pixel_height = 1; ximagesink->image_pool = NULL; ximagesink->pool_lock = g_mutex_new (); @@ -1402,6 +1496,9 @@ gst_ximagesink_init (GstXImageSink * ximagesink) ximagesink->sw_scaling_failed = FALSE; ximagesink->synchronous = FALSE; + g_value_init (&ximagesink->par, GST_TYPE_FRACTION); + gst_value_set_fraction (&ximagesink->par, 1, 1); + GST_FLAG_SET (ximagesink, GST_ELEMENT_THREAD_SUGGESTED); GST_FLAG_SET (ximagesink, GST_ELEMENT_EVENT_AWARE); } @@ -1435,6 +1532,9 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass) g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs " "the X display in synchronous mode. (used only for debugging)", FALSE, 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)); gobject_class->finalize = gst_ximagesink_finalize; gobject_class->set_property = gst_ximagesink_set_property; diff --git a/sys/ximage/ximagesink.h b/sys/ximage/ximagesink.h index 81925f8c54..5f3e2a8908 100644 --- a/sys/ximage/ximagesink.h +++ b/sys/ximage/ximagesink.h @@ -75,6 +75,10 @@ struct _GstXContext { gint bpp; gint endianness; + gint width, height; + gint widthmm, heightmm; + GValue par; /* calculated pixel aspect ratio */ + gboolean use_xshm; GstCaps *caps; @@ -118,6 +122,7 @@ struct _GstXImageSink { /* Unused */ gint pixel_width, pixel_height; + GValue par; /* object-set pixel aspect ratio */ GstClockTime time; diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index d2d1043d5e..24f4275ceb 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -81,7 +81,8 @@ enum ARG_HUE, ARG_SATURATION, ARG_DISPLAY, - ARG_SYNCHRONOUS + ARG_SYNCHRONOUS, + ARG_PIXEL_ASPECT_RATIO /* FILL ME */ }; @@ -390,7 +391,8 @@ gst_xvimagesink_xwindow_decorate (GstXvImageSink * xvimagesink, return TRUE; } -/* This function handles a GstXWindow creation */ +/* This function handles a GstXWindow creation + * The width and height are the actual pixel size on the display */ static GstXWindow * gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink, gint width, gint height) @@ -458,7 +460,8 @@ gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink, g_free (xwindow); } -/* This function resizes a GstXWindow */ +/* This function resizes a GstXWindow. + * The width and height are the actual pixel size on the display. */ static void gst_xvimagesink_xwindow_resize (GstXvImageSink * xvimagesink, GstXWindow * xwindow, guint width, guint height) @@ -815,6 +818,49 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, return caps; } +/* This function calculates the pixel aspect ratio based on the properties + * in the xcontext structure and stores it there. */ +static void +gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) +{ + gint par[][2] = { + {1, 1}, /* regular screen */ + {16, 15}, /* PAL TV */ + {11, 10}, /* 525 line Rec.601 video */ + {54, 59} /* 625 line Rec.601 video */ + }; + gint i; + gint index; + gdouble ratio; + gdouble delta; + +#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1]))) + + /* first calculate the "real" ratio based on the X values; + * which is the "physical" w/h divided by the w/h in pixels of the display */ + ratio = xcontext->widthmm * xcontext->height + / (xcontext->heightmm * xcontext->width); + GST_DEBUG ("calculated pixel aspect ratio: %f", ratio); + /* now find the one from par[][2] with the lowest delta to the real one */ + delta = DELTA (0); + index = 0; + + for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) { + gdouble this_delta = DELTA (i); + + if (this_delta < delta) { + index = i; + delta = this_delta; + } + } + + GST_DEBUG ("Decided on index %d (%d/%d)", index, + par[index][0], par[index][1]); + + g_value_init (&xcontext->par, GST_TYPE_FRACTION); + gst_value_set_fraction (&xcontext->par, par[index][0], par[index][1]); +} + /* This function gets the X Display and global info about it. Everything is stored in our object and will be cleaned when the object is disposed. Note here that caps for supported format are generated without any window or @@ -855,6 +901,12 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink) xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num); xcontext->depth = DefaultDepthOfScreen (xcontext->screen); + xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); + xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); + xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num); + xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num); + + gst_xvimagesink_calculate_pixel_aspect_ratio (xcontext); /* We get supported pixmap formats at supported depth */ px_formats = XListPixmapFormats (xcontext->disp, &nb_formats); @@ -1112,6 +1164,12 @@ gst_xvimagesink_sink_link (GstPad * pad, const GstCaps * caps) GstStructure *structure; gint im_format = 0; gboolean ret; + gint video_width, video_height; + gint video_par_n, video_par_d; /* video's PAR */ + gint display_par_n, display_par_d; /* display's PAR */ + GValue display_ratio = { 0, }; /* display w/h ratio */ + const GValue *caps_par; + gint num, den; xvimagesink = GST_XVIMAGESINK (gst_pad_get_parent (pad)); @@ -1120,15 +1178,15 @@ gst_xvimagesink_sink_link (GstPad * pad, const GstCaps * caps) GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps); structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "width", - &(GST_VIDEOSINK_WIDTH (xvimagesink))); - ret &= gst_structure_get_int (structure, "height", - &(GST_VIDEOSINK_HEIGHT (xvimagesink))); + ret = gst_structure_get_int (structure, "width", &video_width); + ret &= gst_structure_get_int (structure, "height", &video_height); ret &= gst_structure_get_double (structure, "framerate", &xvimagesink->framerate); if (!ret) return GST_PAD_LINK_REFUSED; + xvimagesink->video_width = video_width; + xvimagesink->video_height = video_height; if (!gst_structure_get_fourcc (structure, "format", &im_format)) { im_format = gst_xvimagesink_get_fourcc_from_caps (xvimagesink, @@ -1138,13 +1196,58 @@ gst_xvimagesink_sink_link (GstPad * pad, const GstCaps * caps) return GST_PAD_LINK_REFUSED; } - xvimagesink->pixel_width = 1; - gst_structure_get_int (structure, "pixel_width", &xvimagesink->pixel_width); + /* 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); - xvimagesink->pixel_height = 1; - gst_structure_get_int (structure, "pixel_height", &xvimagesink->pixel_height); + /* 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 */ + display_par_n = gst_value_get_fraction_numerator (&xvimagesink->par); + display_par_d = gst_value_get_fraction_denominator (&xvimagesink->par); - /* Creating our window and our image */ + 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 (xvimagesink, + "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 (xvimagesink, "keeping video height"); + GST_VIDEOSINK_WIDTH (xvimagesink) = video_height * num / den; + GST_VIDEOSINK_HEIGHT (xvimagesink) = video_height; + } else if (video_width % num == 0) { + GST_DEBUG_OBJECT (xvimagesink, "keeping video width"); + GST_VIDEOSINK_WIDTH (xvimagesink) = video_width; + GST_VIDEOSINK_HEIGHT (xvimagesink) = video_width * den / num; + } else { + GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height"); + GST_VIDEOSINK_WIDTH (xvimagesink) = video_height * num / den; + GST_VIDEOSINK_HEIGHT (xvimagesink) = video_height; + } + GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d", + GST_VIDEOSINK_WIDTH (xvimagesink), GST_VIDEOSINK_HEIGHT (xvimagesink)); + + /* Creating our window and our image with the display size in pixels */ g_assert (GST_VIDEOSINK_WIDTH (xvimagesink) > 0); g_assert (GST_VIDEOSINK_HEIGHT (xvimagesink) > 0); if (!xvimagesink->xwindow) @@ -1157,12 +1260,12 @@ gst_xvimagesink_sink_link (GstPad * pad, const GstCaps * caps) GST_VIDEOSINK_HEIGHT (xvimagesink)); } - /* We renew our xvimage only if size or format changed */ + /* We renew our xvimage only if size or format changed; + * the xvimage is the same size as the video pixel size */ if ((xvimagesink->xvimage) && ((im_format != xvimagesink->xvimage->im_format) || - (GST_VIDEOSINK_WIDTH (xvimagesink) != xvimagesink->xvimage->width) || - (GST_VIDEOSINK_HEIGHT (xvimagesink) != - xvimagesink->xvimage->height))) { + (video_width != xvimagesink->xvimage->width) || + (video_height != xvimagesink->xvimage->height))) { GST_DEBUG_OBJECT (xvimagesink, "old format " GST_FOURCC_FORMAT ", new format " GST_FOURCC_FORMAT, GST_FOURCC_ARGS (xvimagesink->xcontext->im_format), @@ -1278,8 +1381,7 @@ gst_xvimagesink_chain (GstPad * pad, GstData * data) if (!xvimagesink->xvimage) { GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage"); xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink, - GST_VIDEOSINK_WIDTH (xvimagesink), - GST_VIDEOSINK_HEIGHT (xvimagesink)); + xvimagesink->video_width, xvimagesink->video_height); if (!xvimagesink->xvimage) { /* No image available. That's very bad ! */ gst_buffer_unref (buf); @@ -1373,7 +1475,7 @@ gst_xvimagesink_buffer_alloc (GstPad * pad, guint64 offset, guint size) /* We found no suitable image in the pool. Creating... */ GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage"); xvimage = gst_xvimagesink_xvimage_new (xvimagesink, - GST_VIDEOSINK_WIDTH (xvimagesink), GST_VIDEOSINK_HEIGHT (xvimagesink)); + xvimagesink->video_width, xvimagesink->video_height); } if (xvimage) { @@ -1680,6 +1782,13 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id, xvimagesink->synchronous ? "TRUE" : "FALSE"); } break; + case ARG_PIXEL_ASPECT_RATIO: + if (!g_value_transform (value, &xvimagesink->par)) + g_warning ("Could not transform string to aspect ratio"); + GST_DEBUG_OBJECT (xvimagesink, "set PAR to %d/%d", + gst_value_get_fraction_numerator (&xvimagesink->par), + gst_value_get_fraction_denominator (&xvimagesink->par)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1715,6 +1824,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, case ARG_SYNCHRONOUS: g_value_set_boolean (value, xvimagesink->synchronous); break; + case ARG_PIXEL_ASPECT_RATIO: + g_value_transform (&xvimagesink->par, value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1777,7 +1889,8 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink) xvimagesink->x_lock = g_mutex_new (); - xvimagesink->pixel_width = xvimagesink->pixel_height = 1; + g_value_init (&xvimagesink->par, GST_TYPE_FRACTION); + gst_value_set_fraction (&xvimagesink->par, 1, 1); xvimagesink->image_pool = NULL; xvimagesink->pool_lock = g_mutex_new (); @@ -1830,6 +1943,9 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) "When enabled, runs " "the X display in synchronous mode. (used only for debugging)", FALSE, 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)); gobject_class->finalize = gst_xvimagesink_finalize; gobject_class->set_property = gst_xvimagesink_set_property; diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h index b043367fd5..b234ed4c88 100644 --- a/sys/xvimage/xvimagesink.h +++ b/sys/xvimage/xvimagesink.h @@ -79,6 +79,10 @@ struct _GstXContext { gint bpp; gint endianness; + gint width, height; + gint widthmm, heightmm; + GValue par; /* calculated pixel aspect ratio */ + gboolean use_xshm; XvPortID xv_port_id; @@ -139,8 +143,9 @@ struct _GstXvImageSink { GMutex *x_lock; - /* Unused */ - gint pixel_width, pixel_height; + guint video_width, video_height; /* size of incoming video; + * used as the size for XvImage */ + GValue par; /* object-set pixel aspect ratio */ GstClockTime time;