diff --git a/configure b/configure
index 6761d0cb32..d989498bba 100755
--- a/configure
+++ b/configure
@@ -2143,6 +2143,7 @@ ARCH_FEATURES="
     fast_64bit
     fast_clz
     fast_cmov
+    float16
     local_aligned
     simd_align_16
     simd_align_32
@@ -6228,6 +6229,7 @@ check_builtin MemoryBarrier windows.h "MemoryBarrier()"
 check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval; __sync_val_compare_and_swap(ptr, oldval, newval)"
 check_builtin gmtime_r time.h "time_t *time; struct tm *tm; gmtime_r(time, tm)"
 check_builtin localtime_r time.h "time_t *time; struct tm *tm; localtime_r(time, tm)"
+check_builtin float16 "" "_Float16 f16var"
 
 case "$custom_allocator" in
     jemalloc)
diff --git a/libswscale/input.c b/libswscale/input.c
index 68abc4d62c..0b5bd952e8 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -1111,6 +1111,89 @@ static void grayf32##endian_name##ToY16_c(uint8_t *dst, const uint8_t *src,
 rgbf32_planar_funcs_endian(le, 0)
 rgbf32_planar_funcs_endian(be, 1)
 
+static void rgbaf16ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV,
+                               const uint8_t *unused0, const uint8_t *src1, const uint8_t *src2,
+                               int width, uint32_t *_rgb2yuv)
+{
+#if HAVE_FLOAT16
+    const _Float16 *src = (const _Float16*)src1;
+    uint16_t *dstU = (uint16_t*)_dstU;
+    uint16_t *dstV = (uint16_t*)_dstV;
+    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
+    int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX];
+    int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX];
+    int i;
+    av_assert1(src1==src2);
+    for (i = 0; i < width; i++) {
+        int r = (lrintf(av_clipf(65535.0f * src[i*8+0], 0.0f, 65535.0f)) +
+                 lrintf(av_clipf(65535.0f * src[i*8+4], 0.0f, 65535.0f))) >> 1;
+        int g = (lrintf(av_clipf(65535.0f * src[i*8+1], 0.0f, 65535.0f)) +
+                 lrintf(av_clipf(65535.0f * src[i*8+5], 0.0f, 65535.0f))) >> 1;
+        int b = (lrintf(av_clipf(65535.0f * src[i*8+2], 0.0f, 65535.0f)) +
+                 lrintf(av_clipf(65535.0f * src[i*8+6], 0.0f, 65535.0f))) >> 1;
+
+        dstU[i] = (ru*r + gu*g + bu*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+        dstV[i] = (rv*r + gv*g + bv*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+    }
+#endif
+}
+
+static void rgbaf16ToUV_c(uint8_t *_dstU, uint8_t *_dstV,
+                          const uint8_t *unused0, const uint8_t *src1, const uint8_t *src2,
+                          int width, uint32_t *_rgb2yuv)
+{
+#if HAVE_FLOAT16
+    const _Float16 *src = (const _Float16*)src1;
+    uint16_t *dstU = (uint16_t*)_dstU;
+    uint16_t *dstV = (uint16_t*)_dstV;
+    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
+    int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX];
+    int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX];
+    int i;
+    av_assert1(src1==src2);
+    for (i = 0; i < width; i++) {
+        int r = lrintf(av_clipf(65535.0f * src[i*4+0], 0.0f, 65535.0f));
+        int g = lrintf(av_clipf(65535.0f * src[i*4+1], 0.0f, 65535.0f));
+        int b = lrintf(av_clipf(65535.0f * src[i*4+2], 0.0f, 65535.0f));
+
+        dstU[i] = (ru*r + gu*g + bu*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+        dstV[i] = (rv*r + gv*g + bv*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+    }
+#endif
+}
+
+static void rgbaf16ToY_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused0, const uint8_t *unused1,
+                         int width, uint32_t *_rgb2yuv)
+{
+#if HAVE_FLOAT16
+    const _Float16 *src = (const _Float16*)_src;
+    uint16_t *dst = (uint16_t*)_dst;
+    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
+    int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX];
+    int i;
+    for (i = 0; i < width; i++) {
+        int r = lrintf(av_clipf(65535.0f * src[i*4+0], 0.0f, 65535.0f));
+        int g = lrintf(av_clipf(65535.0f * src[i*4+1], 0.0f, 65535.0f));
+        int b = lrintf(av_clipf(65535.0f * src[i*4+2], 0.0f, 65535.0f));
+
+        dst[i] = (ry*r + gy*g + by*b + (0x2001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
+    }
+#endif
+}
+
+static void rgbaf16ToA_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused0, const uint8_t *unused1,
+                         int width, uint32_t *unused2)
+{
+#if HAVE_FLOAT16
+    const _Float16 *src = (const _Float16*)_src;
+    uint16_t *dst = (uint16_t*)_dst;
+    int i;
+    for (i=0; i<width; i++) {
+        dst[i] = lrintf(av_clipf(65535.0f * src[i*4+3], 0.0f, 65535.0f));
+    }
+#endif
+}
+
 av_cold void ff_sws_init_input_funcs(SwsContext *c)
 {
     enum AVPixelFormat srcFormat = c->srcFormat;
@@ -1375,6 +1458,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
         case AV_PIX_FMT_X2BGR10LE:
             c->chrToYV12 = bgr30leToUV_half_c;
             break;
+        case AV_PIX_FMT_RGBAF16:
+            c->chrToYV12 = rgbaf16ToUV_half_c;
+            break;
         }
     } else {
         switch (srcFormat) {
@@ -1462,6 +1548,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
         case AV_PIX_FMT_X2BGR10LE:
             c->chrToYV12 = bgr30leToUV_c;
             break;
+        case AV_PIX_FMT_RGBAF16:
+            c->chrToYV12 = rgbaf16ToUV_c;
+            break;
         }
     }
 
@@ -1750,6 +1839,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_X2BGR10LE:
         c->lumToYV12 = bgr30leToY_c;
         break;
+    case AV_PIX_FMT_RGBAF16:
+        c->lumToYV12 = rgbaf16ToY_c;
+        break;
     }
     if (c->needAlpha) {
         if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
@@ -1769,6 +1861,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
         case AV_PIX_FMT_ARGB:
             c->alpToYV12 = abgrToA_c;
             break;
+        case AV_PIX_FMT_RGBAF16:
+            c->alpToYV12 = rgbaf16ToA_c;
+            break;
         case AV_PIX_FMT_YA8:
             c->alpToYV12 = uyvyToY_c;
             break;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 34503e57f4..c5c22017ff 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -259,6 +259,9 @@ static const FormatEntry format_entries[] = {
     [AV_PIX_FMT_P416LE]      = { 1, 1 },
     [AV_PIX_FMT_NV16]        = { 1, 1 },
     [AV_PIX_FMT_VUYA]        = { 1, 1 },
+#if HAVE_FLOAT16
+    [AV_PIX_FMT_RGBAF16]     = { 1, 0 },
+#endif
 };
 
 int ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos,
diff --git a/libswscale/version.h b/libswscale/version.h
index 3193562d18..d8694bb5c0 100644
--- a/libswscale/version.h
+++ b/libswscale/version.h
@@ -29,7 +29,7 @@
 #include "version_major.h"
 
 #define LIBSWSCALE_VERSION_MINOR   8
-#define LIBSWSCALE_VERSION_MICRO 102
+#define LIBSWSCALE_VERSION_MICRO 103
 
 #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
                                                LIBSWSCALE_VERSION_MINOR, \
