--- /dev/null
- * This file is part of Libav.
+ /*
- * Libav is free software; you can redistribute it and/or modify
++ * This file is part of FFmpeg.
+ *
- * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
- * with Libav; if not, write to the Free Software Foundation, Inc.,
++ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
- int got_output; // signal an output frame is reday to request_frame()
++ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ /**
+ * @file
+ * progressive to interlaced content filter, inspired by heavy debugging of
+ * tinterlace filter.
+ */
+
+ #ifndef AVFILTER_INTERLACE_H
+ #define AVFILTER_INTERLACE_H
+
+ #include "libavutil/common.h"
+ #include "libavutil/imgutils.h"
+ #include "libavutil/opt.h"
+
+ #include "avfilter.h"
+ #include "formats.h"
+ #include "internal.h"
+ #include "video.h"
+
+ enum ScanMode {
+ MODE_TFF = 0,
+ MODE_BFF = 1,
+ };
+
+ enum FieldType {
+ FIELD_UPPER = 0,
+ FIELD_LOWER = 1,
+ };
+
+ typedef struct InterlaceContext {
+ const AVClass *class;
+ enum ScanMode scan; // top or bottom field first scanning
+ int lowpass; // enable or disable low pass filterning
+ AVFrame *cur, *next; // the two frames from which the new one is obtained
+ void (*lowpass_line)(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp,
+ const uint8_t *srcp_above, const uint8_t *srcp_below);
+ } InterlaceContext;
+
+ void ff_interlace_init_x86(InterlaceContext *interlace);
+
+ #endif /* AVFILTER_INTERLACE_H */
#include "internal.h"
#include "video.h"
- enum ScanMode {
- MODE_TFF = 0,
- MODE_BFF = 1,
- };
-
- enum FieldType {
- FIELD_UPPER = 0,
- FIELD_LOWER = 1,
- };
-
- typedef struct InterlaceContext {
- const AVClass *class;
- enum ScanMode scan; // top or bottom field first scanning
- int lowpass; // enable or disable low pass filterning
- AVFrame *cur, *next; // the two frames from which the new one is obtained
- } InterlaceContext;
-
#define OFFSET(x) offsetof(InterlaceContext, x)
#define V AV_OPT_FLAG_VIDEO_PARAM
-static const AVOption options[] = {
+static const AVOption interlace_options[] = {
{ "scan", "scanning mode", OFFSET(scan),
AV_OPT_TYPE_INT, {.i64 = MODE_TFF }, 0, 1, .flags = V, .unit = "scan" },
{ "tff", "top field first", 0,
{ NULL }
};
-static const AVClass class = {
- .class_name = "interlace filter",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
-};
+AVFILTER_DEFINE_CLASS(interlace);
+ static void lowpass_line_c(uint8_t *dstp, ptrdiff_t linesize,
+ const uint8_t *srcp,
+ const uint8_t *srcp_above,
+ const uint8_t *srcp_below)
+ {
+ int i;
+ 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;
+ }
+ }
+
static const enum AVPixelFormat formats_supported[] = {
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P,
AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P,
outlink->w = inlink->w;
outlink->h = inlink->h;
outlink->time_base = inlink->time_base;
+ outlink->frame_rate = inlink->frame_rate;
// half framerate
- outlink->time_base.num *= 2;
+ outlink->frame_rate.den *= 2;
+ outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
+
+ if (s->lowpass) {
+ s->lowpass_line = lowpass_line_c;
+ if (ARCH_X86)
+ ff_interlace_init_x86(s);
+ }
+
av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n",
s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" : "without");
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
int vsub = desc->log2_chroma_h;
- int plane, i, j;
+ int plane, j;
for (plane = 0; plane < desc->nb_components; plane++) {
- int lines = (plane == 1 || plane == 2) ? -(-inlink->h) >> vsub : inlink->h;
+ int lines = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h;
- int linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
+ ptrdiff_t linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
uint8_t *dstp = dst_frame->data[plane];
const uint8_t *srcp = src_frame->data[plane];
av_frame_copy_props(out, s->cur);
out->interlaced_frame = 1;
out->top_field_first = tff;
- out->pts /= 2; // adjust pts to new framerate
/* copy upper/lower field from cur */
- copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass);
+ copy_picture_field(s, s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass);
av_frame_free(&s->cur);
/* copy lower/upper field from next */
OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun_init.o
OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d_init.o
+OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet_init.o
+ OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace_init.o
+OBJS-$(CONFIG_NOISE_FILTER) += x86/vf_noise.o
+OBJS-$(CONFIG_PULLUP_FILTER) += x86/vf_pullup_init.o
+OBJS-$(CONFIG_SPP_FILTER) += x86/vf_spp.o
OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o
OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif_init.o
YASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o
YASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d.o
+YASM-OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet.o
+ YASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o
+YASM-OBJS-$(CONFIG_PULLUP_FILTER) += x86/vf_pullup.o
YASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o
-YASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o
+YASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o x86/yadif-16.o x86/yadif-10.o
--- /dev/null
-;* This file is part of Libav.
+ ;*****************************************************************************
+ ;* x86-optimized functions for interlace filter
+ ;*
+ ;* Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+ ;*
-;* Libav is free software; you can redistribute it and/or modify
++;* This file is part of FFmpeg.
+ ;*
-;* Libav is distributed in the hope that it will be useful,
++;* FFmpeg is free software; you can redistribute it and/or modify
+ ;* it under the terms of the GNU General Public License as published by
+ ;* the Free Software Foundation; either version 2 of the License, or
+ ;* (at your option) any later version.
+ ;*
-;* with Libav; if not, write to the Free Software Foundation, Inc.,
++;* FFmpeg is distributed in the hope that it will be useful,
+ ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ;* GNU General Public License for more details.
+ ;*
+ ;* You should have received a copy of the GNU General Public License along
++;* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ ;* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ ;******************************************************************************
+
+ %include "libavutil/x86/x86util.asm"
+
+ SECTION_RODATA
+
+ SECTION .text
+
+ %macro LOWPASS_LINE 0
+ cglobal lowpass_line, 5, 5, 7
+ add r0, r1
+ add r2, r1
+ add r3, r1
+ add r4, r1
+ neg r1
+
+ pxor m6, m6
+
+ .loop
+ mova m0, [r2+r1]
+ punpcklbw m1, m0, m6
+ punpckhbw m0, m6
+ paddw m0, m0
+ paddw m1, m1
+
+ mova m2, [r3+r1]
+ punpcklbw m3, m2, m6
+ punpckhbw m2, m6
+
+ mova m4, [r4+r1]
+ punpcklbw m5, m4, m6
+ punpckhbw m4, m6
+
+ paddw m1, m3
+ pavgw m1, m5
+
+ paddw m0, m2
+ pavgw m0, m4
+
+ psrlw m0, 1
+ psrlw m1, 1
+
+ packuswb m1, m0
+ mova [r0+r1], m1
+
+ add r1, mmsize
+ jl .loop
+ REP_RET
+ %endmacro
+
+ INIT_XMM sse2
+ LOWPASS_LINE
+
+ INIT_XMM avx
+ LOWPASS_LINE
--- /dev/null
- * This file is part of Libav.
+ /*
+ * Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+ *
- * Libav is free software; you can redistribute it and/or modify
++ * This file is part of FFmpeg.
+ *
- * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
- * with Libav; if not, write to the Free Software Foundation, Inc.,
++ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
++ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ #include "libavutil/attributes.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/internal.h"
+ #include "libavutil/mem.h"
+ #include "libavutil/x86/asm.h"
+ #include "libavutil/x86/cpu.h"
+
+ #include "libavfilter/interlace.h"
+
+ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize,
+ const uint8_t *srcp,
+ const uint8_t *srcp_above,
+ const uint8_t *srcp_below);
+ void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize,
+ const uint8_t *srcp,
+ const uint8_t *srcp_above,
+ const uint8_t *srcp_below);
+
+ av_cold void ff_interlace_init_x86(InterlaceContext *s)
+ {
+ int cpu_flags = av_get_cpu_flags();
+
+ if (EXTERNAL_SSE2(cpu_flags))
+ s->lowpass_line = ff_lowpass_line_sse2;
+ if (EXTERNAL_AVX(cpu_flags))
+ s->lowpass_line = ff_lowpass_line_avx;
+ }