[FFmpeg-devel,7/7] libavfilter/vf_overlay.c: add the yuv420p10 10bit support

Submitted by lance.lmwang@gmail.com on May 24, 2019, 9:36 a.m.

Details

Message ID 20190524093616.74647-7-lance.lmwang@gmail.com
State New
Headers show

Commit Message

lance.lmwang@gmail.com May 24, 2019, 9:36 a.m.
From: Limin Wang <lance.lmwang@gmail.com>

The test ffmpeg command in iMAC:
./ffmpeg -y  -i input.ts -i ./logo.png -filter_complex overlay=50:50:format=yuv420p10  -c:v hevc_videotoolbox ./test.ts
Now I have tested with 8bit and check the result is OK
---
 libavfilter/vf_overlay.c | 54 ++++++++++++++++++++++++++++++++++------
 libavfilter/vf_overlay.h |  1 +
 2 files changed, 48 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index 8376494efc..48e6a90f8b 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -153,7 +153,7 @@  static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
 }
 
 static const enum AVPixelFormat alpha_pix_fmts[] = {
-    AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
+    AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
     AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA,
     AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE
 };
@@ -172,6 +172,14 @@  static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE
     };
 
+    static const enum AVPixelFormat main_pix_fmts_yuv420p10[] = {
+        AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE,
+        AV_PIX_FMT_NONE
+    };
+    static const enum AVPixelFormat overlay_pix_fmts_yuv420p10[] = {
+        AV_PIX_FMT_YUVA420P10LE, AV_PIX_FMT_NONE
+    };
+
     static const enum AVPixelFormat main_pix_fmts_yuv422[] = {
         AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_NONE
     };
@@ -217,6 +225,13 @@  static int query_formats(AVFilterContext *ctx)
                 goto fail;
             }
         break;
+    case OVERLAY_FORMAT_YUV420P10:
+        if (!(main_formats    = ff_make_format_list(main_pix_fmts_yuv420p10)) ||
+                !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv420p10))) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        break;
     case OVERLAY_FORMAT_YUV422:
         if (!(main_formats    = ff_make_format_list(main_pix_fmts_yuv422)) ||
             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv422))) {
@@ -494,7 +509,7 @@  static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
         kmax = FFMIN(-xp + dst_wp, src_wp);                                                                            \
                                                                                                                        \
         if (nbits == 8 && ((vsub && j+1 < src_hp) || !vsub) && octx->blend_row[i]) {                                   \
-            int c = octx->blend_row[i](d, da, s, a, kmax - k, src->linesize[3]);                                       \
+            int c = octx->blend_row[i]((uint8_t*)d, (uint8_t*)da, (uint8_t*)s, (uint8_t*)a, kmax - k, src->linesize[3]); \
                                                                                                                        \
             s += c;                                                                                                    \
             d += dst_step * c;                                                                                         \
@@ -539,18 +554,18 @@  static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
                 if (nbits > 8)                                                                                         \
                    *d = (*d * (max - alpha) + *s * alpha) / max;                                                       \
                 else                                                                                                   \
-                    *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha);                                                 \
+                    *d = FAST_DIV255(*d * (max - alpha) + *s * alpha);                                                 \
             } else {                                                                                                   \
                 if (nbits > 8) {                                                                                       \
                     if (i && yuv)                                                                                      \
-                        *d = av_clip((*d * (max - alpha) + *s * alpha) / max + *s - 128, -128, 128) + 128;             \
+                        *d = av_clip((*d * (max - alpha) + *s * alpha) / max + *s - mid, -mid, mid) + mid;             \
                     else                                                                                               \
-                        *d = FFMIN((*d * (max - alpha) + *s * alpha) / max + *s, 255);                                 \
+                        *d = FFMIN((*d * (max - alpha) + *s * alpha) / max + *s, max);                                 \
                 } else {                                                                                               \
                     if (i && yuv)                                                                                      \
-                        *d = av_clip(FAST_DIV255((*d - 128) * (255 - alpha)) + *s - 128, -128, 128) + 128;             \
+                        *d = av_clip(FAST_DIV255((*d - mid) * (max - alpha)) + *s - mid, -mid, mid) + mid;             \
                     else                                                                                               \
-                        *d = FFMIN(FAST_DIV255(*d * (255 - alpha)) + *s, 255);                                         \
+                        *d = FFMIN(FAST_DIV255(*d * (max - alpha)) + *s, max);                                         \
                 }                                                                                                      \
             }                                                                                                          \
             s++;                                                                                                       \
@@ -565,6 +580,7 @@  static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
     }                                                                                                                  \
 }
 DEFINE_BLEND_PLANE(8, 8);
+DEFINE_BLEND_PLANE(16, 10);
 
 #define DEFINE_ALPHA_COMPOSITE(depth, nbits)                                                                           \
 static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, const AVFrame *dst,                     \
@@ -620,6 +636,7 @@  static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, c
     }                                                                                                                  \
 }
 DEFINE_ALPHA_COMPOSITE(8, 8);
+DEFINE_ALPHA_COMPOSITE(16, 10);
 
 #define DEFINE_BLEND_SLICE_YUV(depth, nbits)                                                                           \
 static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterContext *ctx,                             \
@@ -650,6 +667,7 @@  static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterCon
         alpha_composite_##depth##_##nbits##bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs);           \
 }
 DEFINE_BLEND_SLICE_YUV(8, 8);
+DEFINE_BLEND_SLICE_YUV(16, 10);
 
 static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
                                                     AVFrame *dst, const AVFrame *src,
@@ -696,6 +714,21 @@  static int blend_slice_yuva420(AVFilterContext *ctx, void *arg, int jobnr, int n
     return 0;
 }
 
+static int blend_slice_yuv420p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    OverlayContext *s = ctx->priv;
+    ThreadData *td = arg;
+    blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 1, jobnr, nb_jobs);
+    return 0;
+}
+
+static int blend_slice_yuva420p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    OverlayContext *s = ctx->priv;
+    ThreadData *td = arg;
+    blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 1, jobnr, nb_jobs);
+    return 0;
+}
 static int blend_slice_yuv422(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     OverlayContext *s = ctx->priv;
@@ -859,6 +892,9 @@  static int config_input_main(AVFilterLink *inlink)
     case OVERLAY_FORMAT_YUV420:
         s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420;
         break;
+    case OVERLAY_FORMAT_YUV420P10:
+        s->blend_slice = s->main_has_alpha ? blend_slice_yuva420p10 : blend_slice_yuv420p10;
+        break;
     case OVERLAY_FORMAT_YUV422:
         s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422;
         break;
@@ -876,6 +912,9 @@  static int config_input_main(AVFilterLink *inlink)
         case AV_PIX_FMT_YUVA420P:
             s->blend_slice = blend_slice_yuva420;
             break;
+        case AV_PIX_FMT_YUVA420P10:
+            s->blend_slice = blend_slice_yuva420p10;
+            break;
         case AV_PIX_FMT_YUVA422P:
             s->blend_slice = blend_slice_yuva422;
             break;
@@ -1030,6 +1069,7 @@  static const AVOption overlay_options[] = {
     { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
     { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1, FLAGS, "format" },
         { "yuv420", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420}, .flags = FLAGS, .unit = "format" },
+        { "yuv420p10", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420P10}, .flags = FLAGS, .unit = "format" },
         { "yuv422", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422}, .flags = FLAGS, .unit = "format" },
         { "yuv444", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444}, .flags = FLAGS, .unit = "format" },
         { "rgb",    "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_RGB},    .flags = FLAGS, .unit = "format" },
diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h
index 98b06eaacf..d68c4f931b 100644
--- a/libavfilter/vf_overlay.h
+++ b/libavfilter/vf_overlay.h
@@ -41,6 +41,7 @@  enum var_name {
 
 enum OverlayFormat {
     OVERLAY_FORMAT_YUV420,
+    OVERLAY_FORMAT_YUV420P10,
     OVERLAY_FORMAT_YUV422,
     OVERLAY_FORMAT_YUV444,
     OVERLAY_FORMAT_RGB,