#include "drawutils.h"
#include "framesync.h"
#include "video.h"
+#include "vf_overlay.h"
typedef struct ThreadData {
AVFrame *dst, *src;
NULL
};
-enum var_name {
- VAR_MAIN_W, VAR_MW,
- VAR_MAIN_H, VAR_MH,
- VAR_OVERLAY_W, VAR_OW,
- VAR_OVERLAY_H, VAR_OH,
- VAR_HSUB,
- VAR_VSUB,
- VAR_X,
- VAR_Y,
- VAR_N,
- VAR_POS,
- VAR_T,
- VAR_VARS_NB
-};
-
#define MAIN 0
#define OVERLAY 1
EVAL_MODE_NB
};
-enum OverlayFormat {
- OVERLAY_FORMAT_YUV420,
- OVERLAY_FORMAT_YUV422,
- OVERLAY_FORMAT_YUV444,
- OVERLAY_FORMAT_RGB,
- OVERLAY_FORMAT_GBRP,
- OVERLAY_FORMAT_AUTO,
- OVERLAY_FORMAT_NB
-};
-
-typedef struct OverlayContext {
- const AVClass *class;
- int x, y; ///< position of overlaid picture
-
- uint8_t main_is_packed_rgb;
- uint8_t main_rgba_map[4];
- uint8_t main_has_alpha;
- uint8_t overlay_is_packed_rgb;
- uint8_t overlay_rgba_map[4];
- uint8_t overlay_has_alpha;
- int format; ///< OverlayFormat
- int alpha_format;
- int eval_mode; ///< EvalMode
-
- FFFrameSync fs;
-
- int main_pix_step[4]; ///< steps per pixel for each plane of the main output
- int overlay_pix_step[4]; ///< steps per pixel for each plane of the overlay
- int hsub, vsub; ///< chroma subsampling values
- const AVPixFmtDescriptor *main_desc; ///< format descriptor for main input
-
- double var_values[VAR_VARS_NB];
- char *x_expr, *y_expr;
-
- AVExpr *x_pexpr, *y_pexpr;
-
- int (*blend_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
-} OverlayContext;
-
static av_cold void uninit(AVFilterContext *ctx)
{
OverlayContext *s = ctx->priv;
uint8_t *S, *sp, *d, *dp;
i = FFMAX(-y, 0);
- imax = FFMIN(-y + dst_h, src_h);
+ imax = FFMIN3(-y + dst_h, FFMIN(src_h, dst_h), y + src_h);
- slice_start = (imax * jobnr) / nb_jobs;
- slice_end = (imax * (jobnr+1)) / nb_jobs;
+ slice_start = i + (imax * jobnr) / nb_jobs;
+ slice_end = i + (imax * (jobnr+1)) / nb_jobs;
- sp = src->data[0] + (i + slice_start) * src->linesize[0];
- dp = dst->data[0] + (y + i + slice_start) * dst->linesize[0];
+ sp = src->data[0] + (slice_start) * src->linesize[0];
+ dp = dst->data[0] + (y + slice_start) * dst->linesize[0];
- for (i = i + slice_start; i < slice_end; i++) {
+ for (i = slice_start; i < slice_end; i++) {
j = FFMAX(-x, 0);
S = sp + j * sstep;
d = dp + (x+j) * dstep;
int jobnr,
int nb_jobs)
{
+ OverlayContext *octx = ctx->priv;
int src_wp = AV_CEIL_RSHIFT(src_w, hsub);
int src_hp = AV_CEIL_RSHIFT(src_h, vsub);
int dst_wp = AV_CEIL_RSHIFT(dst_w, hsub);
int slice_start, slice_end;
j = FFMAX(-yp, 0);
- jmax = FFMIN(-yp + dst_hp, src_hp);
+ jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp);
- slice_start = (jmax * jobnr) / nb_jobs;
- slice_end = (jmax * (jobnr+1)) / nb_jobs;
+ slice_start = j + (jmax * jobnr) / nb_jobs;
+ slice_end = j + (jmax * (jobnr+1)) / nb_jobs;
- sp = src->data[i] + slice_start * src->linesize[i];
+ sp = src->data[i] + (slice_start) * src->linesize[i];
dp = dst->data[dst_plane]
+ (yp + slice_start) * dst->linesize[dst_plane]
+ dst_offset;
ap = src->data[3] + (slice_start << vsub) * src->linesize[3];
dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3];
- for (j = j + slice_start; j < slice_end; j++) {
+ for (j = slice_start; j < slice_end; j++) {
k = FFMAX(-xp, 0);
d = dp + (xp+k) * dst_step;
s = sp + k;
a = ap + (k<<hsub);
da = dap + ((xp+k) << hsub);
+ kmax = FFMIN(-xp + dst_wp, src_wp);
+
+ if (((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]);
- for (kmax = FFMIN(-xp + dst_wp, src_wp); k < kmax; k++) {
+ s += c;
+ d += dst_step * c;
+ da += (1 << hsub) * c;
+ a += (1 << hsub) * c;
+ k += c;
+ }
+ for (; k < kmax; k++) {
int alpha_v, alpha_h, alpha;
// average alpha for color components, improve quality
sa = src->data[3] + (i + slice_start) * src->linesize[3];
da = dst->data[3] + (y + i + slice_start) * dst->linesize[3];
- for (i = i + slice_start; i < imax; i++) {
+ for (i = i + slice_start; i < slice_end; i++) {
j = FFMAX(-x, 0);
s = sa + j;
d = da + x+j;
}
if (!s->alpha_format)
- return 0;
+ goto end;
switch (s->format) {
case OVERLAY_FORMAT_YUV420:
}
break;
}
+
+end:
+ if (ARCH_X86)
+ ff_overlay_init_x86(s, s->format, inlink->format,
+ s->alpha_format, s->main_has_alpha);
+
return 0;
}
s->var_values[VAR_Y], s->y);
}
- if (s->x < mainpic->width && s->x + second->width >= 0 ||
+ if (s->x < mainpic->width && s->x + second->width >= 0 &&
s->y < mainpic->height && s->y + second->height >= 0) {
ThreadData td;
td.dst = mainpic;
td.src = second;
- ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMIN(mainpic->height - s->y, second->height),
+ ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMAX(1, FFMIN3(s->y + second->height, FFMIN(second->height, mainpic->height), mainpic->height - s->y)),
ff_filter_get_nb_threads(ctx)));
}
return ff_filter_frame(ctx->outputs[0], mainpic);