From 7c9aaa689f7ffcd5568190a13f6ce01c5b036c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Mon, 31 Aug 2015 15:18:34 +0200 Subject: [PATCH] avfilter/codecview/WIP: add QP support --- libavfilter/vf_codecview.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c index df45f55..5e1334e 100644 --- a/libavfilter/vf_codecview.c +++ b/libavfilter/vf_codecview.c @@ -27,7 +27,6 @@ * libavcodec/mpegvideo.c. * * TODO: segmentation - * TODO: quantization */ #include "libavutil/imgutils.h" @@ -43,11 +42,14 @@ typedef struct { const AVClass *class; unsigned mv; + int hsub, vsub; + int qp; } CodecViewContext; #define OFFSET(x) offsetof(CodecViewContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption codecview_options[] = { + { "qp", NULL, OFFSET(qp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS }, { "mv", "set motion vectors to visualize", OFFSET(mv), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv" }, {"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = MV_P_FOR }, INT_MIN, INT_MAX, FLAGS, "mv"}, {"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = MV_B_FOR }, INT_MIN, INT_MAX, FLAGS, "mv"}, @@ -198,6 +200,31 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) CodecViewContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + if (s->qp) { + int qstride, qp_type; + int8_t *qp_table = av_frame_get_qp_table(frame, &qstride, &qp_type); + + if (qp_table) { + int x, y; + const int w = FF_CEIL_RSHIFT(frame->width, s->hsub); + const int h = FF_CEIL_RSHIFT(frame->height, s->vsub); + uint8_t *pu = frame->data[1]; + uint8_t *pv = frame->data[2]; + const int lzu = frame->linesize[1]; + const int lzv = frame->linesize[2]; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + const int qp = ff_norm_qscale(qp_table[(y >> 3) * qstride + (x >> 3)], qp_type); + pu[x] = pv[x] = qp; + } + pu += lzu; + pv += lzv; + } + } + } + + if (s->mv) { AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS); if (sd) { int i; @@ -213,14 +240,28 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) 100, 0, mv->source > 0); } } + } + return ff_filter_frame(outlink, frame); } +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + CodecViewContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->hsub = desc->log2_chroma_w; + s->vsub = desc->log2_chroma_h; + return 0; +} + static const AVFilterPad codecview_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = filter_frame, + .config_props = config_input, .needs_writable = 1, }, { NULL } -- 2.5.1