From c98a8fc00bbd1ec6983880f60aadf1bfe45b57ee Mon Sep 17 00:00:00 2001
From: Martin Vignali <martin.vignali@gmail.com>
Date: Thu, 23 Aug 2018 18:22:04 +0200
Subject: [PATCH 2/4] swscale/unscale : add bitexact conversion for float to
 uint8

---
 libswscale/swscale_internal.h | 13 +++++++++++++
 libswscale/swscale_unscaled.c | 26 +++++++++++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 3bbb486b4d..3b6b682d5f 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -942,6 +942,19 @@ static inline uint16_t flt_2_uint16(int32_t v)
     return (v + (1 << 23)) >> (127 + 7 - exp);
 }
 
+/**
+ * Convert from 32-bit float as uint32_t to uint8_t.
+ *
+ * @param v 32-bit float
+ *
+ * @return normalized 8-bit unsigned int
+ */
+static inline uint8_t flt_2_uint8(int32_t v)
+{
+    uint16_t v16 = flt_2_uint16(v);
+    return v16 >> 8;
+}
+
 #define MAX_SLICE_PLANES 4
 
 /// Slice plane
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index 973fa4875f..9e55cccc33 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -1507,6 +1507,26 @@ static int float_y_to_uint_y_wrapper(SwsContext *c, const uint8_t* src[],
     return srcSliceH;
 }
 
+static int float_y_to_uint_y_bitexact_wrapper(SwsContext *c, const uint8_t* src[],
+                                              int srcStride[], int srcSliceY,
+                                              int srcSliceH, uint8_t* dst[], int dstStride[])
+{
+    int y, x;
+    ptrdiff_t srcStrideFloat = srcStride[0] >> 2;
+    const uint32_t *srcPtr = (const uint32_t *)src[0];
+    uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
+
+    for (y = 0; y < srcSliceH; ++y){
+        for (x = 0; x < c->srcW; ++x){
+            dstPtr[x] = flt_2_uint8(srcPtr[x]);
+        }
+        srcPtr += srcStrideFloat;
+        dstPtr += dstStride[0];
+    }
+
+    return srcSliceH;
+}
+
 /* unscaled copy like stuff (assumes nearly identical formats) */
 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
                              int srcStride[], int srcSliceY, int srcSliceH,
@@ -1946,7 +1966,11 @@ void ff_get_unscaled_swscale(SwsContext *c)
 
     /* float Y to uint Y */
     if (srcFormat == AV_PIX_FMT_GRAYF32 && dstFormat == AV_PIX_FMT_GRAY8){
-        c->swscale = float_y_to_uint_y_wrapper;
+        if (c->flags & SWS_BITEXACT) {
+            c->swscale = float_y_to_uint_y_bitexact_wrapper;
+        } else {
+            c->swscale = float_y_to_uint_y_wrapper;
+        }
     }
 
     /* LQ converters if -sws 0 or -sws 4*/
-- 
2.14.3 (Apple Git-98)

