gst/videoscale/gstvideoscale.c: Videoscale doesn't pass on pixel-aspect ratio. Handle...
authorWim Taymans <wim.taymans@gmail.com>
Fri, 28 Apr 2006 14:33:45 +0000 (14:33 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 28 Apr 2006 14:33:45 +0000 (14:33 +0000)
Original commit message from CVS:
* gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps),
(gst_video_scale_fixate_caps), (gst_video_scale_src_event):
Videoscale doesn't pass on pixel-aspect ratio. Handle all
fixation cases better. Fixes #338991

ChangeLog
gst/videoscale/gstvideoscale.c

index aceee49..cc15360 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2006-04-28  Wim Taymans  <wim@fluendo.com>
 
+       * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps),
+       (gst_video_scale_fixate_caps), (gst_video_scale_src_event):
+       Videoscale doesn't pass on pixel-aspect ratio. Handle all
+       fixation cases better. Fixes #338991
+
+2006-04-28  Wim Taymans  <wim@fluendo.com>
+
        * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_create):
        Handle 0/1 framerate correctly Fixes #331901.
 
index e92740b..d1fa384 100644 (file)
@@ -316,22 +316,42 @@ gst_video_scale_transform_caps (GstBaseTransform * trans,
 {
   GstVideoScale *videoscale;
   GstCaps *ret;
-  int i;
+  GstStructure *structure;
+  const GValue *par;
 
   videoscale = GST_VIDEO_SCALE (trans);
 
   ret = gst_caps_copy (caps);
 
-  for (i = 0; i < gst_caps_get_size (ret); i++) {
-    GstStructure *structure = gst_caps_get_structure (ret, i);
+  /* this function is always called with a simple caps */
+  g_return_val_if_fail (GST_CAPS_IS_SIMPLE (ret), NULL);
+
+  structure = gst_caps_get_structure (ret, 0);
+
+  gst_structure_set (structure,
+      "width", GST_TYPE_INT_RANGE, 16, 4096,
+      "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
+
+  /* if pixel aspect ratio, make a range of it */
+  if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) {
+    GstCaps *copy;
+    GstStructure *cstruct;
+
+    /* copy input PAR first, this is the prefered PAR */
+    gst_structure_set_value (structure, "pixel-aspect-ratio", par);
 
-    gst_structure_set (structure,
-        "width", GST_TYPE_INT_RANGE, 16, 4096,
-        "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
-    gst_structure_remove_field (structure, "pixel-aspect-ratio");
+    /* then make a copy with a fraction range as a second choice */
+    copy = gst_caps_copy (ret);
+    cstruct = gst_caps_get_structure (copy, 0);
+    gst_structure_set (cstruct,
+        "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+
+    /* and append */
+    gst_caps_append (ret, copy);
   }
 
   GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);
+
   return ret;
 }
 
@@ -521,11 +541,29 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
   from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
   to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
 
+  /* we have both PAR but they might not be fixated */
   if (from_par && to_par) {
     GValue to_ratio = { 0, };   /* w/h of output video */
     gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
     gint count = 0, w = 0, h = 0, num, den;
 
+    /* from_par should be fixed */
+    g_return_if_fail (gst_value_is_fixed (from_par));
+
+    from_par_n = gst_value_get_fraction_numerator (from_par);
+    from_par_d = gst_value_get_fraction_denominator (from_par);
+
+    /* fixate the out PAR */
+    if (!gst_value_is_fixed (to_par)) {
+      GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", from_par_n,
+          from_par_d);
+      gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio",
+          from_par_n, from_par_d);
+    }
+
+    to_par_n = gst_value_get_fraction_numerator (to_par);
+    to_par_d = gst_value_get_fraction_denominator (to_par);
+
     /* if both width and height are already fixed, we can't do anything
      * about it anymore */
     if (gst_structure_get_int (outs, "width", &w))
@@ -540,10 +578,6 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
 
     gst_structure_get_int (ins, "width", &from_w);
     gst_structure_get_int (ins, "height", &from_h);
-    from_par_n = gst_value_get_fraction_numerator (from_par);
-    from_par_d = gst_value_get_fraction_denominator (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,
@@ -560,20 +594,30 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
      * 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 (base, "keeping video height");
-      h = from_h;
+    /* if one of the output width or height is fixed, we work from there */
+    if (h) {
+      GST_DEBUG_OBJECT (base, "height is fixed,scaling width");
       w = h * num / den;
-    } else if (from_w % num == 0) {
-      GST_DEBUG_OBJECT (base, "keeping video width");
-      w = from_w;
+    } else if (w) {
+      GST_DEBUG_OBJECT (base, "width is fixes, scaling height");
       h = w * den / num;
     } else {
-      GST_DEBUG_OBJECT (base, "approximating but keeping video height");
-      h = from_h;
-      w = h * num / den;
+      /* none of width or height is fixed, figure out both of them based only on
+       * the input width and height */
+      /* check hd / den is an integer scale factor, and scale wd with the PAR */
+      if (from_h % den == 0) {
+        GST_DEBUG_OBJECT (base, "keeping video height");
+        h = from_h;
+        w = h * num / den;
+      } else if (from_w % num == 0) {
+        GST_DEBUG_OBJECT (base, "keeping video width");
+        w = from_w;
+        h = w * den / num;
+      } else {
+        GST_DEBUG_OBJECT (base, "approximating but keeping video height");
+        h = from_h;
+        w = h * num / den;
+      }
     }
     GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);