Signed-off-by: Thomas Mundt <loud...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel