[FFmpeg-devel] [PATCH 4/4] avfilter/vf_colormatrix: add 10 & 12 bit depth support

Thomas Mundt loudmax at yahoo.de
Fri Mar 25 23:32:18 CET 2016


Signed-off-by: Thomas Mundt <loudmax at yahoo.de>
---
 libavfilter/vf_colormatrix.c | 182 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 179 insertions(+), 3 deletions(-)

diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c
index 5fe9ce3..92224b6 100644
--- a/libavfilter/vf_colormatrix.c
+++ b/libavfilter/vf_colormatrix.c
@@ -59,6 +59,7 @@ enum ColorMode {
 
 typedef struct {
     const AVClass *class;
+    const AVPixFmtDescriptor *csp;
     int yuv_convert[25][3][3];
     int source, dest;        ///< ColorMode
     int mode;
@@ -386,11 +387,177 @@ static int process_slice_yuv420p(AVFilterContext *ctx, void *arg, int jobnr, int
     return 0;
 }
 
+static int process_slice_yuv444p_16bit(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    const ThreadData *td = arg;
+    const AVFrame *src = td->src;
+    AVFrame *dst = td->dst;
+    ColorMatrixContext *color = ctx->priv;
+    const int numbits = 1 << color->csp->comp[0].depth;
+    const int height = src->height;
+    const int width = src->width;
+    const int slice_start = (height *  jobnr   ) / nb_jobs;
+    const int slice_end   = (height * (jobnr+1)) / nb_jobs;
+    const int src_pitchY  = src->linesize[0] / 2;
+    const int src_pitchUV = src->linesize[1] / 2;
+    const uint16_t *srcpU = (const uint16_t *)src->data[1] + slice_start * src_pitchUV;
+    const uint16_t *srcpV = (const uint16_t *)src->data[2] + slice_start * src_pitchUV;
+    const uint16_t *srcpY = (const uint16_t *)src->data[0] + slice_start * src_pitchY;
+    const int dst_pitchY  = dst->linesize[0] / 2;
+    const int dst_pitchUV = dst->linesize[1] / 2;
+    uint16_t *dstpU = (uint16_t *)dst->data[1] + slice_start * dst_pitchUV;
+    uint16_t *dstpV = (uint16_t *)dst->data[2] + slice_start * dst_pitchUV;
+    uint16_t *dstpY = (uint16_t *)dst->data[0] + slice_start * dst_pitchY;
+    const int c2 = td->c2;
+    const int c3 = td->c3;
+    const int c4 = td->c4;
+    const int c5 = td->c5;
+    const int c6 = td->c6;
+    const int c7 = td->c7;
+    const int cin_shift  = numbits >> 1;
+    const int cout_shift = (numbits + 1) << 15;
+    const int clip_max   = numbits - 1;
+    int x, y;
+
+    for (y = slice_start; y < slice_end; y++) {
+        for (x = 0; x < width; x++) {
+            const int u = srcpU[x] - cin_shift;
+            const int v = srcpV[x] - cin_shift;
+            const int uvval = (c2 * u + c3 * v + 32768) >> 16;
+            dstpY[x] = av_clip(srcpY[x] + uvval, 0, clip_max);
+            dstpU[x] = av_clip((c4 * u + c5 * v + cout_shift) >> 16, 0, clip_max);
+            dstpV[x] = av_clip((c6 * u + c7 * v + cout_shift) >> 16, 0, clip_max);
+        }
+        srcpY += src_pitchY;
+        dstpY += dst_pitchY;
+        srcpU += src_pitchUV;
+        srcpV += src_pitchUV;
+        dstpU += dst_pitchUV;
+        dstpV += dst_pitchUV;
+    }
+
+    return 0;
+}
+
+static int process_slice_yuv422p_16bit(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    const ThreadData *td = arg;
+    const AVFrame *src = td->src;
+    AVFrame *dst = td->dst;
+    ColorMatrixContext *color = ctx->priv;
+    const int numbits = 1 << color->csp->comp[0].depth;
+    const int height = src->height;
+    const int width = src->width;
+    const int slice_start = (height *  jobnr   ) / nb_jobs;
+    const int slice_end   = (height * (jobnr+1)) / nb_jobs;
+    const int src_pitchY  = src->linesize[0] / 2;
+    const int src_pitchUV = src->linesize[1] / 2;
+    const uint16_t *srcpU = (const uint16_t *)src->data[1] + slice_start * src_pitchUV;
+    const uint16_t *srcpV = (const uint16_t *)src->data[2] + slice_start * src_pitchUV;
+    const uint16_t *srcpY = (const uint16_t *)src->data[0] + slice_start * src_pitchY;
+    const int dst_pitchY  = dst->linesize[0] / 2;
+    const int dst_pitchUV = dst->linesize[1] / 2;
+    uint16_t *dstpU = (uint16_t *)dst->data[1] + slice_start * dst_pitchUV;
+    uint16_t *dstpV = (uint16_t *)dst->data[2] + slice_start * dst_pitchUV;
+    uint16_t *dstpY = (uint16_t *)dst->data[0] + slice_start * dst_pitchY;
+    const int c2 = td->c2;
+    const int c3 = td->c3;
+    const int c4 = td->c4;
+    const int c5 = td->c5;
+    const int c6 = td->c6;
+    const int c7 = td->c7;
+    const int cin_shift  = numbits >> 1;
+    const int cout_shift = (numbits + 1) << 15;
+    const int clip_max   = numbits - 1;
+    int x, y;
+
+    for (y = slice_start; y < slice_end; y++) {
+        for (x = 0; x < width; x += 2) {
+            const int u = srcpU[x >> 1] - cin_shift;
+            const int v = srcpV[x >> 1] - cin_shift;
+            const int uvval = (c2 * u + c3 * v + 32768) >> 16;
+            dstpY[x + 0] = av_clip(srcpY[x + 0] + uvval, 0, clip_max);
+            dstpY[x + 1] = av_clip(srcpY[x + 1] + uvval, 0, clip_max);
+            dstpU[x >> 1] = av_clip((c4 * u + c5 * v + cout_shift) >> 16, 0, clip_max);
+            dstpV[x >> 1] = av_clip((c6 * u + c7 * v + cout_shift) >> 16, 0, clip_max);
+        }
+        srcpY += src_pitchY;
+        dstpY += dst_pitchY;
+        srcpU += src_pitchUV;
+        srcpV += src_pitchUV;
+        dstpU += dst_pitchUV;
+        dstpV += dst_pitchUV;
+    }
+
+    return 0;
+}
+
+static int process_slice_yuv420p_16bit(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    const ThreadData *td = arg;
+    const AVFrame *src = td->src;
+    AVFrame *dst = td->dst;
+    ColorMatrixContext *color = ctx->priv;
+    const int numbits = 1 << color->csp->comp[0].depth;
+    const int height = FFALIGN(src->height, 2) >> 1;
+    const int width = src->width;
+    const int slice_start = ((height *  jobnr   ) / nb_jobs) << 1;
+    const int slice_end   = ((height * (jobnr+1)) / nb_jobs) << 1;
+    const int src_pitchY  = src->linesize[0] / 2;
+    const int src_pitchUV = src->linesize[1] / 2;
+    const int dst_pitchY  = dst->linesize[0] / 2;
+    const int dst_pitchUV = dst->linesize[1] / 2;
+    const uint16_t *srcpY = (const uint16_t *)src->data[0] + src_pitchY * slice_start;
+    const uint16_t *srcpU = (const uint16_t *)src->data[1] + src_pitchUV * (slice_start >> 1);
+    const uint16_t *srcpV = (const uint16_t *)src->data[2] + src_pitchUV * (slice_start >> 1);
+    const uint16_t *srcpN = (const uint16_t *)src->data[0] + src_pitchY * (slice_start + 1);
+    uint16_t *dstpU = (uint16_t *)dst->data[1] + dst_pitchUV * (slice_start >> 1);
+    uint16_t *dstpV = (uint16_t *)dst->data[2] + dst_pitchUV * (slice_start >> 1);
+    uint16_t *dstpY = (uint16_t *)dst->data[0] + dst_pitchY * slice_start;
+    uint16_t *dstpN = (uint16_t *)dst->data[0] + dst_pitchY * (slice_start + 1);
+    const int c2 = td->c2;
+    const int c3 = td->c3;
+    const int c4 = td->c4;
+    const int c5 = td->c5;
+    const int c6 = td->c6;
+    const int c7 = td->c7;
+    const int cin_shift  = numbits >> 1;
+    const int cout_shift = (numbits + 1) << 15;
+    const int clip_max   = numbits - 1;
+    int x, y;
+
+    for (y = slice_start; y < slice_end; y += 2) {
+        for (x = 0; x < width; x += 2) {
+            const int u = srcpU[x >> 1] - cin_shift;
+            const int v = srcpV[x >> 1] - cin_shift;
+            const int uvval = (c2 * u + c3 * v + 32768) >> 16;
+            dstpY[x + 0] = av_clip(srcpY[x + 0] + uvval, 0, clip_max);
+            dstpY[x + 1] = av_clip(srcpY[x + 1] + uvval, 0, clip_max);
+            dstpN[x + 0] = av_clip(srcpN[x + 0] + uvval, 0, clip_max);
+            dstpN[x + 1] = av_clip(srcpN[x + 1] + uvval, 0, clip_max);
+            dstpU[x >> 1] = av_clip((c4 * u + c5 * v + cout_shift) >> 16, 0, clip_max);
+            dstpV[x >> 1] = av_clip((c6 * u + c7 * v + cout_shift) >> 16, 0, clip_max);
+        }
+        srcpY += src_pitchY << 1;
+        dstpY += dst_pitchY << 1;
+        srcpN += src_pitchY << 1;
+        dstpN += dst_pitchY << 1;
+        srcpU += src_pitchUV;
+        srcpV += src_pitchUV;
+        dstpU += dst_pitchUV;
+        dstpV += dst_pitchUV;
+    }
+
+    return 0;
+}
+
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
     ColorMatrixContext *color = ctx->priv;
 
+    color->csp = av_pix_fmt_desc_get(inlink->format);
+
     av_log(ctx, AV_LOG_VERBOSE, "%s -> %s\n",
            color_modes[color->source], color_modes[color->dest]);
 
@@ -400,9 +567,9 @@ static int config_input(AVFilterLink *inlink)
 static int query_formats(AVFilterContext *ctx)
 {
     static const enum AVPixelFormat pix_fmts[] = {
-        AV_PIX_FMT_YUV444P,
-        AV_PIX_FMT_YUV422P,
-        AV_PIX_FMT_YUV420P,
+        AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12,
+        AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12,
+        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12,
         AV_PIX_FMT_UYVY422,
         AV_PIX_FMT_NONE
     };
@@ -474,6 +641,15 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
     else if (in->format == AV_PIX_FMT_YUV420P)
         ctx->internal->execute(ctx, process_slice_yuv420p, &td, NULL,
                                FFMIN(in->height / 2, ctx->graph->nb_threads));
+    else if (in->format == AV_PIX_FMT_YUV444P10 || in->format == AV_PIX_FMT_YUV444P12)
+        ctx->internal->execute(ctx, process_slice_yuv444p_16bit, &td, NULL,
+                               FFMIN(in->height, ctx->graph->nb_threads));
+    else if (in->format == AV_PIX_FMT_YUV422P10 || in->format == AV_PIX_FMT_YUV422P12)
+        ctx->internal->execute(ctx, process_slice_yuv422p_16bit, &td, NULL,
+                               FFMIN(in->height, ctx->graph->nb_threads));
+    else if (in->format == AV_PIX_FMT_YUV420P10 || in->format == AV_PIX_FMT_YUV420P12)
+        ctx->internal->execute(ctx, process_slice_yuv420p_16bit, &td, NULL,
+                               FFMIN(in->height / 2, ctx->graph->nb_threads));
     else
         ctx->internal->execute(ctx, process_slice_uyvy422, &td, NULL,
                                FFMIN(in->height, ctx->graph->nb_threads));
-- 
2.7.4.windows.1




More information about the ffmpeg-devel mailing list