static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; TileContext *tile = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; if (inlink->w > INT_MAX / tile->w) { av_log(ctx, AV_LOG_ERROR, "Total width %ux%u is too much.\n", tile->w, inlink->w); return AVERROR(EINVAL); } if (inlink->h > INT_MAX / tile->h) { av_log(ctx, AV_LOG_ERROR, "Total height %ux%u is too much.\n", tile->h, inlink->h); return AVERROR(EINVAL); } outlink->w = tile->w * inlink->w; outlink->h = tile->h * inlink->h; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){ 1, tile->w * tile->h }); ff_draw_init(&tile->draw, inlink->format, 0); /* TODO make the color an option, or find an unified way of choosing it */ ff_draw_color(&tile->draw, &tile->blank, (uint8_t[]){ 0, 0, 0, -1 }); return 0; }
int main(void) { enum AVPixelFormat f; const AVPixFmtDescriptor *desc; FFDrawContext draw; FFDrawColor color; int r, i; for (f = 0; av_pix_fmt_desc_get(f); f++) { desc = av_pix_fmt_desc_get(f); if (!desc->name) continue; printf("Testing %s...%*s", desc->name, (int)(16 - strlen(desc->name)), ""); r = ff_draw_init(&draw, f, 0); if (r < 0) { char buf[128]; av_strerror(r, buf, sizeof(buf)); printf("no: %s\n", buf); continue; } ff_draw_color(&draw, &color, (uint8_t[]) { 1, 0, 0, 1 }); for (i = 0; i < sizeof(color); i++) if (((uint8_t *)&color)[i] != 128) break; if (i == sizeof(color)) { printf("fallback color\n"); continue; } printf("ok\n"); } return 0; }
static int config_input(AVFilterLink *inlink) { AssContext *ass = inlink->dst->priv; ff_draw_init(&ass->draw, inlink->format, ass->alpha ? FF_DRAW_PROCESS_ALPHA : 0); ass_set_frame_size (ass->renderer, inlink->w, inlink->h); if (ass->original_w && ass->original_h) ass_set_aspect_ratio(ass->renderer, (double)inlink->w / inlink->h, (double)ass->original_w / ass->original_h); if (ass->shaping != -1) ass_set_shaper(ass->renderer, ass->shaping); return 0; }
static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; DrawTextContext *s = ctx->priv; int ret; ff_draw_init(&s->dc, inlink->format, FF_DRAW_PROCESS_ALPHA); ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba); ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba); ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba); ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba); s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w; s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h; s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1; s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR]; s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max; s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max; s->var_values[VAR_X] = NAN; s->var_values[VAR_Y] = NAN; s->var_values[VAR_T] = NAN; av_lfg_init(&s->prng, av_get_random_seed()); av_expr_free(s->x_pexpr); av_expr_free(s->y_pexpr); s->x_pexpr = s->y_pexpr = NULL; if ((ret = av_expr_parse(&s->x_pexpr, s->x_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) return AVERROR(EINVAL); return 0; }
static int color_config_props(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->src; ColorContext *color = ctx->priv; ff_draw_init(&color->draw, inlink->format, 0); ff_draw_color(&color->draw, &color->color, color->color_rgba); color->w = ff_draw_round_to_sub(&color->draw, 0, -1, color->w); color->h = ff_draw_round_to_sub(&color->draw, 1, -1, color->h); if (av_image_check_size(color->w, color->h, 0, ctx) < 0) return AVERROR(EINVAL); av_log(ctx, AV_LOG_INFO, "w:%d h:%d r:%d/%d color:0x%02x%02x%02x%02x\n", color->w, color->h, color->time_base.den, color->time_base.num, color->color_rgba[0], color->color_rgba[1], color->color_rgba[2], color->color_rgba[3]); inlink->w = color->w; inlink->h = color->h; inlink->time_base = color->time_base; return 0; }
int rotate_filter_frame(RotContext *rot, AVFrame *in,int frame_count_out, AVFrame* &out) { int angle_int, s, c, plane; double res; rot->var_values[ROTATE_VAR_N] = frame_count_out; rot->var_values[ROTATE_VAR_T] = 0;//TS2T(in->pts, inlink->time_base); rot->angle = res = av_expr_eval(rot->angle_expr, rot->var_values, rot); av_log(NULL, AV_LOG_DEBUG, "n:%f time:%f angle:%f/PI\n", rot->var_values[ROTATE_VAR_N], rot->var_values[ROTATE_VAR_T], rot->angle/M_PI); qDebug()<<"rotate_filter_frame n:"<<rot->var_values[ROTATE_VAR_N] <<" time:"<< rot->var_values[ROTATE_VAR_T] <<" angle(/PI): "<<(rot->angle/M_PI); angle_int = res * FIXP * 16; s = int_sin(angle_int); c = int_sin(angle_int + INT_PI/2); /* fill background */ if (rot->fillcolor_enable) ff_fill_rectangle(&rot->draw, &rot->color, out->data, out->linesize, 0, 0, out->width, out->height); for (plane = 0; plane < rot->nb_planes; plane++) { int hsub = plane == 1 || plane == 2 ? rot->hsub : 0; int vsub = plane == 1 || plane == 2 ? rot->vsub : 0; const int outw = AV_CEIL_RSHIFT(out->width, hsub); const int outh = AV_CEIL_RSHIFT(out->height, vsub); #if 0 ThreadData td = { .in = in, .out = out, .inw = AV_CEIL_RSHIFT(in->width, hsub), .inh = AV_CEIL_RSHIFT(in->height, vsub), .outh = outh, .outw = outw, .xi = -(outw-1) * c / 2, .yi = (outw-1) * s / 2, .xprime = -(outh-1) * s / 2, .yprime = -(outh-1) * c / 2, .plane = plane, .c = c, .s = s }; #endif ThreadData td; td.in = in; td.out = out; td.inw = AV_CEIL_RSHIFT(in->width, hsub); td.inh = AV_CEIL_RSHIFT(in->height, vsub); td.outh = outh; td.outw = outw; td.xi = -(outw-1) * c / 2; td.yi = (outw-1) * s / 2; td.xprime = -(outh-1) * s / 2; td.yprime = -(outh-1) * c / 2; td.plane = plane; td.c = c; td.s = s; filter_slice(rot, &td, 0, 1); } return 0; } int rotate_config_props(RotContext *rot, AVFrame *in) { const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get((AVPixelFormat)in->format); int ret; double res; char *expr; qDebug()<<"rotate_config_props foramt: "<<in->format; ff_draw_init(&rot->draw, (AVPixelFormat)in->format, 0); ff_draw_color(&rot->draw, &rot->color, rot->fillcolor); rot->hsub = pixdesc->log2_chroma_w; rot->vsub = pixdesc->log2_chroma_h; if (pixdesc->comp[0].depth == 8) rot->interpolate_bilinear = interpolate_bilinear8; else rot->interpolate_bilinear = interpolate_bilinear16; rot->var_values[ROTATE_VAR_IN_W] = rot->var_values[ROTATE_VAR_IW] = in->width; rot->var_values[ROTATE_VAR_IN_H] = rot->var_values[ROTATE_VAR_IH] = in->height; rot->var_values[ROTATE_VAR_HSUB] = 1<<rot->hsub; rot->var_values[ROTATE_VAR_VSUB] = 1<<rot->vsub; rot->var_values[ROTATE_VAR_N] = NAN; rot->var_values[ROTATE_VAR_T] = NAN; rot->var_values[ROTATE_VAR_OUT_W] = rot->var_values[ROTATE_VAR_OW] = NAN; rot->var_values[ROTATE_VAR_OUT_H] = rot->var_values[ROTATE_VAR_OH] = NAN; av_expr_free(rot->angle_expr); rot->angle_expr = NULL; if ((ret = av_expr_parse(&rot->angle_expr, expr = rot->angle_expr_str, var_names, func1_names, func1, NULL, NULL, 0, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Error occurred parsing angle expression '%s'\n", rot->angle_expr_str); return ret; } #define SET_SIZE_EXPR(name, opt_name) do { \ ret = av_expr_parse_and_eval(&res, expr = rot->name##_expr_str, \ var_names, rot->var_values, \ func1_names, func1, NULL, NULL, rot, 0, NULL); \ if (ret < 0 || isnan(res) || isinf(res) || res <= 0) { \ av_log(NULL, AV_LOG_ERROR, \ "Error parsing or evaluating expression for option %s: " \ "invalid expression '%s' or non-positive or indefinite value %f\n", \ opt_name, expr, res); \ return ret; \ } \ } while (0) /* evaluate width and height */ av_expr_parse_and_eval(&res, expr = rot->outw_expr_str, var_names, rot->var_values, func1_names, func1, NULL, NULL, rot, 0, NULL); rot->var_values[ROTATE_VAR_OUT_W] = rot->var_values[ROTATE_VAR_OW] = res; rot->outw = res + 0.5; SET_SIZE_EXPR(outh, "out_h"); rot->var_values[ROTATE_VAR_OUT_H] = rot->var_values[ROTATE_VAR_OH] = res; rot->outh = res + 0.5; /* evaluate the width again, as it may depend on the evaluated output height */ SET_SIZE_EXPR(outw, "out_w"); rot->var_values[ROTATE_VAR_OUT_W] = rot->var_values[ROTATE_VAR_OW] = res; rot->outw = res + 0.5; /* compute number of planes */ rot->nb_planes = av_pix_fmt_count_planes((AVPixelFormat)in->format); ////out->width = rot->outw; ////outlink->h = rot->outh; return 0; }
static int config_out_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = outlink->src->inputs[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); TInterlaceContext *tinterlace = ctx->priv; int i; tinterlace->vsub = desc->log2_chroma_h; outlink->w = inlink->w; outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2? inlink->h*2 : inlink->h; if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2) outlink->sample_aspect_ratio = av_mul_q(inlink->sample_aspect_ratio, av_make_q(2, 1)); if (tinterlace->mode == MODE_PAD) { uint8_t black[4] = { 0, 0, 0, 16 }; int ret; ff_draw_init(&tinterlace->draw, outlink->format, 0); ff_draw_color(&tinterlace->draw, &tinterlace->color, black); if (ff_fmt_is_in(outlink->format, full_scale_yuvj_pix_fmts)) tinterlace->color.comp[0].u8[0] = 0; ret = av_image_alloc(tinterlace->black_data, tinterlace->black_linesize, outlink->w, outlink->h, outlink->format, 16); if (ret < 0) return ret; ff_fill_rectangle(&tinterlace->draw, &tinterlace->color, tinterlace->black_data, tinterlace->black_linesize, 0, 0, outlink->w, outlink->h); } if (tinterlace->flags & (TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF) && !(tinterlace->mode == MODE_INTERLEAVE_TOP || tinterlace->mode == MODE_INTERLEAVE_BOTTOM)) { av_log(ctx, AV_LOG_WARNING, "low_pass_filter flags ignored with mode %d\n", tinterlace->mode); tinterlace->flags &= ~(TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF); } tinterlace->preout_time_base = inlink->time_base; if (tinterlace->mode == MODE_INTERLACEX2) { tinterlace->preout_time_base.den *= 2; outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1}); outlink->time_base = av_mul_q(inlink->time_base , (AVRational){1,2}); } else if (tinterlace->mode == MODE_MERGEX2) { outlink->frame_rate = inlink->frame_rate; outlink->time_base = inlink->time_base; } else if (tinterlace->mode != MODE_PAD) { outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2}); outlink->time_base = av_mul_q(inlink->time_base , (AVRational){2,1}); } for (i = 0; i<FF_ARRAY_ELEMS(standard_tbs); i++){ if (!av_cmp_q(standard_tbs[i], outlink->time_base)) break; } if (i == FF_ARRAY_ELEMS(standard_tbs) || (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB)) outlink->time_base = tinterlace->preout_time_base; tinterlace->csp = av_pix_fmt_desc_get(outlink->format); if (tinterlace->flags & TINTERLACE_FLAG_CVLPF) { if (tinterlace->csp->comp[0].depth > 8) tinterlace->lowpass_line = lowpass_line_complex_c_16; else tinterlace->lowpass_line = lowpass_line_complex_c; if (ARCH_X86) ff_tinterlace_init_x86(tinterlace); } else if (tinterlace->flags & TINTERLACE_FLAG_VLPF) { if (tinterlace->csp->comp[0].depth > 8) tinterlace->lowpass_line = lowpass_line_c_16; else tinterlace->lowpass_line = lowpass_line_c; if (ARCH_X86) ff_tinterlace_init_x86(tinterlace); } av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_CVLPF) ? "complex" : (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "linear" : "off", inlink->h, outlink->h); return 0; }