X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Flibavfilter%2Fvf_tinterlace.c;h=c644895ee0b51009488e2b2be4d63532a6830e08;hp=6bc55b5960a3bba1a34edae85b761b553317858d;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/libavfilter/vf_tinterlace.c b/ffmpeg/libavfilter/vf_tinterlace.c index 6bc55b5..c644895 100644 --- a/ffmpeg/libavfilter/vf_tinterlace.c +++ b/ffmpeg/libavfilter/vf_tinterlace.c @@ -30,33 +30,12 @@ #include "libavutil/avassert.h" #include "avfilter.h" #include "internal.h" - -enum TInterlaceMode { - MODE_MERGE = 0, - MODE_DROP_EVEN, - MODE_DROP_ODD, - MODE_PAD, - MODE_INTERLEAVE_TOP, - MODE_INTERLEAVE_BOTTOM, - MODE_INTERLACEX2, - MODE_NB, -}; - -typedef struct { - const AVClass *class; - enum TInterlaceMode mode; ///< interlace mode selected - int flags; ///< flags affecting interlacing algorithm - int frame; ///< number of the output frame - int vsub; ///< chroma vertical subsampling - AVFrame *cur; - AVFrame *next; - uint8_t *black_data[4]; ///< buffer used to fill padded lines - int black_linesize[4]; -} TInterlaceContext; +#include "tinterlace.h" #define OFFSET(x) offsetof(TInterlaceContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM #define TINTERLACE_FLAG_VLPF 01 +#define TINTERLACE_FLAG_EXACT_TB 2 static const AVOption tinterlace_options[] = { {"mode", "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_MERGE}, 0, MODE_NB-1, FLAGS, "mode"}, @@ -71,6 +50,7 @@ static const AVOption tinterlace_options[] = { {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" }, {"low_pass_filter", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" }, {"vlpf", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" }, + {"exact_tb", "force a timebase which can represent timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_EXACT_TB}, INT_MIN, INT_MAX, FLAGS, "flags" }, {NULL} }; @@ -84,6 +64,12 @@ static const enum AVPixelFormat full_scale_yuvj_pix_fmts[] = { FULL_SCALE_YUVJ_FORMATS, AV_PIX_FMT_NONE }; +static const AVRational standard_tbs[] = { + {1, 25}, + {1, 30}, + {1001, 30000}, +}; + static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { @@ -99,6 +85,18 @@ static int query_formats(AVFilterContext *ctx) return 0; } +static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, + const uint8_t *srcp_above, const uint8_t *srcp_below) +{ + int i; + for (i = 0; i < width; i++) { + // this calculation is an integer representation of + // '0.5 * current + 0.25 * above + 0.25 * below' + // '1 +' is for rounding. + dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; + } +} + static av_cold void uninit(AVFilterContext *ctx) { TInterlaceContext *tinterlace = ctx->priv; @@ -114,6 +112,7 @@ static int config_out_props(AVFilterLink *outlink) 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->flags |= FF_LINK_FLAG_REQUEST_LOOP; @@ -145,10 +144,28 @@ static int config_out_props(AVFilterLink *outlink) tinterlace->mode); tinterlace->flags &= ~TINTERLACE_FLAG_VLPF; } + tinterlace->preout_time_base = inlink->time_base; if (tinterlace->mode == MODE_INTERLACEX2) { - outlink->time_base.num = inlink->time_base.num; - outlink->time_base.den = inlink->time_base.den * 2; + 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_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; itime_base)) + break; + } + if (i == FF_ARRAY_ELEMS(standard_tbs) || + (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB)) + outlink->time_base = tinterlace->preout_time_base; + + if (tinterlace->flags & TINTERLACE_FLAG_VLPF) { + 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", @@ -172,7 +189,8 @@ static int config_out_props(AVFilterLink *outlink) * @param flags context flags */ static inline -void copy_picture_field(uint8_t *dst[4], int dst_linesize[4], +void copy_picture_field(TInterlaceContext *tinterlace, + uint8_t *dst[4], int dst_linesize[4], const uint8_t *src[4], int src_linesize[4], enum AVPixelFormat format, int w, int src_h, int src_field, int interleave, int dst_field, @@ -181,10 +199,11 @@ void copy_picture_field(uint8_t *dst[4], int dst_linesize[4], const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); int plane, vsub = desc->log2_chroma_h; int k = src_field == FIELD_UPPER_AND_LOWER ? 1 : 2; - int h, i; + int h; for (plane = 0; plane < desc->nb_components; plane++) { int lines = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(src_h, vsub) : src_h; + int cols = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT( w, desc->log2_chroma_w) : w; int linesize = av_image_get_linesize(format, w, plane); uint8_t *dstp = dst[plane]; const uint8_t *srcp = src[plane]; @@ -208,12 +227,8 @@ void copy_picture_field(uint8_t *dst[4], int dst_linesize[4], const uint8_t *srcp_below = srcp + src_linesize[plane]; if (h == lines) srcp_above = srcp; // there is no line above if (h == 1) srcp_below = srcp; // there is no line below - for (i = 0; i < linesize; i++) { - // this calculation is an integer representation of - // '0.5 * current + 0.25 * above + 0.25 * below' - // '1 +' is for rounding. */ - dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; - } + + tinterlace->lowpass_line(dstp, cols, srcp, srcp_above, srcp_below); dstp += dstp_linesize; srcp += srcp_linesize; } @@ -254,12 +269,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out->top_field_first = 1; /* write odd frame lines into the upper field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags); /* write even frame lines into the lower field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags); @@ -284,12 +299,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER; /* copy upper and lower fields */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags); /* pad with black the other field */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags); @@ -308,13 +323,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out->top_field_first = tff; /* copy upper/lower field from cur */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tinterlace->flags); /* copy lower/upper field from next */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, @@ -330,6 +345,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts*2; + out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; @@ -340,19 +356,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) return AVERROR(ENOMEM); av_frame_copy_props(out, next); out->interlaced_frame = 1; + out->top_field_first = !tff; if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts + next->pts; else out->pts = AV_NOPTS_VALUE; /* write current frame second field lines into the second field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tinterlace->flags); /* write next frame first field lines into the first field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, @@ -362,6 +379,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) av_assert0(0); } + out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); ret = ff_filter_frame(outlink, out); tinterlace->frame++;