https://trac.ffmpeg.org/ticket/7226

Index: ffmpeg-4.0/libavfilter/vf_blend.c
===================================================================
--- ffmpeg-4.0.orig/libavfilter/vf_blend.c	2018-05-23 20:51:44.308348975 +0300
+++ ffmpeg-4.0/libavfilter/vf_blend.c	2018-05-23 21:22:38.242312699 +0300
@@ -22,6 +22,7 @@
 #include "libavutil/eval.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixfmt.h"
+#include "libavutil/intreadwrite.h"
 #include "avfilter.h"
 #include "bufferqueue.h"
 #include "formats.h"
@@ -173,7 +174,10 @@ static void blend_normal_16bit(const uin
 
     for (i = 0; i < height; i++) {
         for (j = 0; j < width; j++) {
-            dst[j] = top[j] * opacity + bottom[j] * (1. - opacity);
+            uint16_t top_v = AV_RN16(top + j);
+            uint16_t bottom_v = AV_RN16(bottom + j);
+            uint16_t dst_v = top_v * opacity + bottom_v * (1. - opacity);
+            AV_WN16(dst + j, dst_v);
         }
         dst    += dst_linesize;
         top    += top_linesize;
@@ -193,7 +197,9 @@ static void blend_## name##_8bit(const u
                                                                                \
     for (i = 0; i < height; i++) {                                             \
         for (j = 0; j < width; j++) {                                          \
-            dst[j] = top[j] + ((expr) - top[j]) * opacity;                     \
+            uint8_t top_v = top[j];                                            \
+            uint8_t bottom_v = bottom[j];                                      \
+            dst[j] = top_v + ((expr) - top_v) * opacity;                       \
         }                                                                      \
         dst    += dst_linesize;                                                \
         top    += top_linesize;                                                \
@@ -219,7 +225,10 @@ static void blend_## name##_16bit(const
                                                                                \
     for (i = 0; i < height; i++) {                                             \
         for (j = 0; j < width; j++) {                                          \
-            dst[j] = top[j] + ((expr) - top[j]) * opacity;                     \
+            uint16_t top_v = AV_RN16(top + j);                                 \
+            uint16_t bottom_v = AV_RN16(bottom + j);                           \
+            uint16_t dst_v = top_v + ((expr) - top_v) * opacity;               \
+            AV_WN16(dst + j, dst_v);                                           \
         }                                                                      \
         dst    += dst_linesize;                                                \
         top    += top_linesize;                                                \
@@ -227,8 +236,8 @@ static void blend_## name##_16bit(const
     }                                                                          \
 }
 
-#define A top[j]
-#define B bottom[j]
+#define A top_v
+#define B bottom_v
 
 #define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 255))
 #define SCREEN(x, a, b)   (255 - (x) * ((255 - (a)) * (255 - (b)) / 255))
@@ -311,38 +320,59 @@ DEFINE_BLEND16(xor,        A ^ B)
 DEFINE_BLEND16(vividlight, (A < 32768) ? BURN(2 * A, B) : DODGE(2 * (A - 32768), B))
 DEFINE_BLEND16(linearlight,av_clip_uint16((B < 32768) ? B + 2 * A - 65535 : B + 2 * (A - 32768)))
 
-#define DEFINE_BLEND_EXPR(type, name, div)                                     \
-static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize,          \
-                               const uint8_t *_bottom, ptrdiff_t bottom_linesize,    \
-                               uint8_t *_dst, ptrdiff_t dst_linesize,                \
-                               ptrdiff_t width, ptrdiff_t height,              \
-                               FilterParams *param, double *values, int starty) \
-{                                                                              \
-    const type *top = (type*)_top;                                             \
-    const type *bottom = (type*)_bottom;                                       \
-    type *dst = (type*)_dst;                                                   \
-    AVExpr *e = param->e;                                                      \
-    int y, x;                                                                  \
-    dst_linesize /= div;                                                       \
-    top_linesize /= div;                                                       \
-    bottom_linesize /= div;                                                    \
-                                                                               \
-    for (y = 0; y < height; y++) {                                             \
-        values[VAR_Y] = y + starty;                                            \
-        for (x = 0; x < width; x++) {                                          \
-            values[VAR_X]      = x;                                            \
-            values[VAR_TOP]    = values[VAR_A] = top[x];                       \
-            values[VAR_BOTTOM] = values[VAR_B] = bottom[x];                    \
-            dst[x] = av_expr_eval(e, values, NULL);                            \
-        }                                                                      \
-        dst    += dst_linesize;                                                \
-        top    += top_linesize;                                                \
-        bottom += bottom_linesize;                                             \
-    }                                                                          \
+static void blend_expr_8bit(const uint8_t *top, ptrdiff_t top_linesize,
+                               const uint8_t *bottom, ptrdiff_t bottom_linesize,
+                               uint8_t *dst, ptrdiff_t dst_linesize,
+                               ptrdiff_t width, ptrdiff_t height,
+                               FilterParams *param, double *values, int starty)
+{
+    AVExpr *e = param->e;
+    int y, x;
+
+    for (y = 0; y < height; y++) {
+        values[VAR_Y] = y + starty;
+        for (x = 0; x < width; x++) {
+            values[VAR_X]      = x;
+            values[VAR_TOP]    = values[VAR_A] = top[x];
+            values[VAR_BOTTOM] = values[VAR_B] = bottom[x];
+            dst[x] = av_expr_eval(e, values, NULL);
+        }
+        dst    += dst_linesize;
+        top    += top_linesize;
+        bottom += bottom_linesize;
+    }
 }
 
-DEFINE_BLEND_EXPR(uint8_t, 8bit, 1)
-DEFINE_BLEND_EXPR(uint16_t, 16bit, 2)
+static void blend_expr_16bit(const uint8_t *_top, ptrdiff_t top_linesize,
+                               const uint8_t *_bottom, ptrdiff_t bottom_linesize,
+                               uint8_t *_dst, ptrdiff_t dst_linesize,
+                               ptrdiff_t width, ptrdiff_t height,
+                               FilterParams *param, double *values, int starty)
+{
+    const uint16_t *top = (uint16_t*)_top;
+    const uint16_t *bottom = (uint16_t*)_bottom;
+    uint16_t *dst = (uint16_t*)_dst;
+    AVExpr *e = param->e;
+    int y, x;
+    dst_linesize /= 2;
+    top_linesize /= 2;
+    bottom_linesize /= 2;
+
+    for (y = 0; y < height; y++) {
+        values[VAR_Y] = y + starty;
+        for (x = 0; x < width; x++) {
+            uint16_t dst_v;
+            values[VAR_X]      = x;
+            values[VAR_TOP]    = values[VAR_A] = AV_RN16(top + x);
+            values[VAR_BOTTOM] = values[VAR_B] = AV_RN16(bottom + x);
+            dst_v = av_expr_eval(e, values, NULL);
+            AV_WN16(dst + x, dst_v);
+        }
+        dst    += dst_linesize;
+        top    += top_linesize;
+        bottom += bottom_linesize;
+    }
+}
 
 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
