shithub: dav1d

Download patch

ref: 3bfe8c7c8a553728e2d6556e4a95f5cd246d1c92
parent: 484d6595afc4d155ffe4dca2bbcdb01d77f8f198
author: Henrik Gramner <gramner@twoorioles.com>
date: Tue Sep 1 11:03:29 EDT 2020

cli: Use proper integer math in Y4M PAR calculations

The previous floating-point implementation produced results that were
sometimes slightly off due to rounding errors.

For example, a frame size of 432x240 with a render size of 176x240
previously resulted in a PAR of 98:240 instead of the correct 11:27.

Also reduce fractions to produce more readable numbers.

--- a/tools/output/y4m2.c
+++ b/tools/output/y4m2.c
@@ -28,6 +28,7 @@
 #include "config.h"
 
 #include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -77,13 +78,17 @@
         chr_names_8bpc_i420[p->seq_hdr->chr > 2 ? DAV1D_CHR_UNKNOWN : p->seq_hdr->chr] :
         ss_names[p->p.layout][p->seq_hdr->hbd];
 
-    int fw = p->frame_hdr->width[0], fh = p->frame_hdr->height;
-    int rw = p->frame_hdr->render_width, rh = p->frame_hdr->render_height;
-    int aw = rw > rh ? rw : (rw + 0.5) / fw * fh;
-    int ah = rh > rw ? rh : (rh + 0.5) / fh * fw;
+    const unsigned fw = p->p.w;
+    const unsigned fh = p->p.h;
+    uint64_t aw = (uint64_t)fh * p->frame_hdr->render_width;
+    uint64_t ah = (uint64_t)fw * p->frame_hdr->render_height;
+    uint64_t gcd = ah;
+    for (uint64_t a = aw, b; (b = a % gcd); a = gcd, gcd = b);
+    aw /= gcd;
+    ah /= gcd;
 
-    fprintf(c->f, "YUV4MPEG2 W%d H%d F%d:%d Ip A%d:%d C%s\n",
-            p->p.w, p->p.h, c->fps[0], c->fps[1], aw, ah, ss_name);
+    fprintf(c->f, "YUV4MPEG2 W%u H%u F%u:%u Ip A%"PRIu64":%"PRIu64" C%s\n",
+            fw, fh, c->fps[0], c->fps[1], aw, ah, ss_name);
 
     return 0;
 }