/* Copy active surface contents - assumes output is big enough */ static void copy_surface( struct ren_vid_surface *out, const struct ren_vid_surface *in) { const struct format_info *fmt = &fmts[in->format]; copy_plane(out->py, in->py, fmt->y_bpp, in->h, in->w, out->pitch, in->pitch); copy_plane(out->pc, in->pc, fmt->c_bpp, in->h/fmt->c_ss_vert, in->w/fmt->c_ss_horz, out->pitch/fmt->c_ss_horz, in->pitch/fmt->c_ss_horz); copy_plane(out->pa, in->pa, 1, in->h, in->w, out->pitch, in->pitch); }
static void yuv422p_yv12(int width, int height, const u_char **in, int *istride, u_char **out, int *ostride) { copy_plane(0, 0, 1, 1); red_plane(1, 2, 2, 1, 1, 2); red_plane(2, 1, 2, 1, 1, 2); }
static void yvu9_yv12(int width, int height, const u_char **in, int *istride, u_char **out, int *ostride) { copy_plane(0, 0, 1, 1); exp_plane(1, 2, 4, 2, 2); exp_plane(2, 1, 4, 2, 2); }
// To be called in arAllFramesReady mode // In manual mode, all planes are called for processing. int PlaneProcessor::process_frame (::VSFrameRef &dst, int n, void *frame_data_ptr, ::VSFrameContext &frame_ctx, ::VSCore &core, NodeRefSPtr src_node1_sptr, NodeRefSPtr src_node2_sptr, NodeRefSPtr src_node3_sptr) { assert (&dst != 0); assert (n >= 0); assert (&frame_ctx != 0); assert (&core != 0); assert (_input_flag); int ret_val = 0; for (int plane_index = 0 ; plane_index < _nbr_planes && ret_val == 0 ; ++plane_index) { const double mode = _proc_mode_arr [plane_index]; const int mode_i = fstb::round_int (mode); if (_manual_flag || mode_i == PlaneProcMode_PROCESS) { ret_val = _cb.process_plane ( dst, n, plane_index, frame_data_ptr, frame_ctx, core, src_node1_sptr, src_node2_sptr, src_node3_sptr ); } else if (mode_i >= PlaneProcMode_COPY1 && mode_i <= PlaneProcMode_COPY3) { NodeRefSPtr src_clip_sptr ( (mode_i == PlaneProcMode_COPY3) ? src_node3_sptr : (mode_i == PlaneProcMode_COPY2) ? src_node2_sptr : src_node1_sptr); if (src_clip_sptr.get () != 0) { FrameRefSPtr src_sptr ( _vsapi.getFrameFilter (n, src_clip_sptr.get (), &frame_ctx), _vsapi ); copy_plane (dst, *src_sptr, plane_index); } } else if (mode < PlaneProcMode_COPY1) { fill_plane (dst, -mode, plane_index); } } return (ret_val); }
static int il_put_image(struct vf_dlopen_context *ctx) { ildetect_data_t *il = ctx->priv; unsigned int x, y; int first_frame = 0; size_t sz = ctx->inpic.planestride[0] * ctx->inpic.planeheight[0]; if (sz != il->buffer_size) { il->buffer_data = realloc(il->buffer_data, sz); il->buffer_size = sz; first_frame = 1; } assert(ctx->inpic.planes == 1); assert(ctx->outpic[0].planes == 1); assert(ctx->inpic.planewidth[0] == ctx->outpic[0].planewidth[0]); assert(ctx->inpic.planeheight[0] == ctx->outpic[0].planeheight[0] + 4); if (first_frame) { printf("First frame\n"); il->lastcombed = -1; } else { // detect interlacing // for each row of 5 pixels, compare: // p2 vs (p1 + p3) / 2 // p2 vs (p0 + p4) / 2 unsigned int totalcombedframes = 0; // add 255 per combed pixel unsigned int totalpixels = 0; for (y = 0; y < ctx->inpic.planeheight[0] - 4; ++y) { unsigned char *in_line = &ctx->inpic.plane[0][ctx->inpic.planestride[0] * y]; unsigned char *buf_line = &il->buffer_data[ctx->inpic.planestride[0] * y]; unsigned char *out_line = &ctx->outpic->plane[0][ctx->outpic->planestride[0] * y]; for (x = 0; x < ctx->inpic.planewidth[0]; ++x) { int b2 = buf_line[x + ctx->inpic.planestride[0] * 2]; int p0 = in_line[x]; int p1 = in_line[x + ctx->inpic.planestride[0]]; int p2 = in_line[x + ctx->inpic.planestride[0] * 2]; int p3 = in_line[x + ctx->inpic.planestride[0] * 3]; int p4 = in_line[x + ctx->inpic.planestride[0] * 4]; int is_moving = abs(b2 - p2) > il->motion_threshold; if (!is_moving) { out_line[x] = 128; continue; } ++totalpixels; int combed = il_decision(ctx, p0, p1, p2, p3, p4); totalcombedframes += combed; out_line[x] = 255 * combed; } } double avgpixels = totalpixels / (double) ((ctx->inpic.planeheight[0] - 4) * ctx->inpic.planewidth[0]); if (avgpixels > il->motion_amount) { double avgcombed = totalcombedframes / (double) totalpixels; if (il->lastcombed >= 0) { if (il->lastcombed < il->no_threshold || il->lastcombed > il->yes_threshold) if (avgcombed < il->no_threshold || avgcombed > il->yes_threshold) ++il->numdecidedadjacentframes; if (il->lastcombed > il->yes_threshold && avgcombed < il->no_threshold) ++il->numjumpingadjacentframes; if (il->lastcombed < il->no_threshold && avgcombed > il->yes_threshold) ++il->numjumpingadjacentframes; } il->lastcombed = avgcombed; if (avgcombed > il->yes_threshold) { ++il->numdecidedframes; ++il->totalcombedframes; } else if (avgcombed < il->no_threshold) { ++il->numdecidedframes; } } else il->lastcombed = -1; } ++il->numtotalframes; copy_plane( il->buffer_data, ctx->inpic.planestride[0], ctx->inpic.plane[0], ctx->inpic.planestride[0], ctx->inpic.planewidth[0], ctx->inpic.planeheight[0]); ctx->outpic[0].pts = ctx->inpic.pts; return 1; }
static int tc_put_image(struct vf_dlopen_context *ctx) { tc_data_t *tc = ctx->priv; unsigned p; unsigned np = ctx->outpic[0].planes; assert(ctx->inpic.planes == ctx->outpic[0].planes); int need_reinit = 0; // fix buffers for (p = 0; p < np; ++p) { size_t sz = ctx->inpic.planestride[p] * ctx->inpic.planeheight[p]; if (sz != tc->buffer_size[p]) { if (p == 0 && tc->buffer_plane[p]) printf("WARNING: reinitializing telecine buffers.\n"); tc->buffer_plane[p] = realloc(tc->buffer_plane[p], sz); tc->buffer_size[p] = sz; need_reinit = 1; } } // too big pts change? reinit if (ctx->inpic.pts < tc->lastpts_in || ctx->inpic.pts > tc->lastpts_in + 0.5) need_reinit = 1; if (need_reinit) { // initialize telecine tc->pattern_pos = 0; tc->occupied = 0; tc->lastpts_in = ctx->inpic.pts; tc->lastpts_out = ctx->inpic.pts; } int len = tc->pattern[tc->pattern_pos] - '0'; unsigned nout; double delta = ctx->inpic.pts - tc->lastpts_in; tc->lastpts_in = ctx->inpic.pts; for (nout = 0; nout < ctx->out_cnt; ++nout) { for (p = 0; p < np; ++p) { assert(ctx->inpic.planewidth[p] == ctx->outpic[nout].planewidth[p]); assert(ctx->inpic.planeheight[p] == ctx->outpic[nout].planeheight[p]); } } nout = 0; if (tc->pattern_pos == 0 && !tc->occupied) { // at the start of the pattern, reset pts // printf("pts reset: %f -> %f (delta: %f)\n", tc->lastpts_out, ctx->inpic.pts, ctx->inpic.pts - tc->lastpts_out); tc->lastpts_out = ctx->inpic.pts; tc->first_frame_of_group = 1; } ++tc->pattern_pos; if (!tc->pattern[tc->pattern_pos]) tc->pattern_pos = 0; if (len == 0) { // do not output any field from this frame return 0; } if (tc->occupied) { for (p = 0; p < np; ++p) { // fill in the EARLIER field from the buffered pic copy_plane( &ctx->outpic[nout].plane[p][ctx->outpic[nout].planestride[p] * tc->firstfield], ctx->outpic[nout].planestride[p] * 2, &tc->buffer_plane[p][ctx->inpic.planestride[p] * tc->firstfield], ctx->inpic.planestride[p] * 2, MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]), (ctx->inpic.planeheight[p] - tc->firstfield + 1) / 2 ); // fill in the LATER field from the new pic copy_plane( &ctx->outpic[nout].plane[p][ctx->outpic[nout].planestride[p] * !tc->firstfield], ctx->outpic[nout].planestride[p] * 2, &ctx->inpic.plane[p][ctx->inpic.planestride[p] * !tc->firstfield], ctx->inpic.planestride[p] * 2, MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]), (ctx->inpic.planeheight[p] - !tc->firstfield + 1) / 2 ); } if (tc->first_frame_of_group) tc->first_frame_of_group = 0; else tc->lastpts_out += (delta * tc->pts_num) / tc->pts_denom; ctx->outpic[nout].pts = tc->lastpts_out; // printf("pts written: %f\n", ctx->outpic[nout].pts); ++nout; --len; tc->occupied = 0; } while (len >= 2) { // output THIS image as-is for (p = 0; p < np; ++p) copy_plane( ctx->outpic[nout].plane[p], ctx->outpic[nout].planestride[p], ctx->inpic.plane[p], ctx->inpic.planestride[p], MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]), ctx->inpic.planeheight[p] ); if (tc->first_frame_of_group) tc->first_frame_of_group = 0; else tc->lastpts_out += (delta * tc->pts_num) / tc->pts_denom; ctx->outpic[nout].pts = tc->lastpts_out; // printf("pts written: %f\n", ctx->outpic[nout].pts); ++nout; len -= 2; } if (len >= 1) { // copy THIS image to the buffer, we need it later for (p = 0; p < np; ++p) copy_plane( &tc->buffer_plane[p][0], ctx->inpic.planestride[p], &ctx->inpic.plane[p][0], ctx->inpic.planestride[p], ctx->inpic.planestride[p], ctx->inpic.planeheight[p] ); tc->occupied = 1; } return nout; }