Merge commit '2e1704059ae8625beda2ffde847ad22c5ba416dc'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 15 Nov 2014 01:28:23 +0000 (02:28 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 15 Nov 2014 01:39:49 +0000 (02:39 +0100)
* commit '2e1704059ae8625beda2ffde847ad22c5ba416dc':
  vf_interlace: Add SIMD for lowpass filter

Conflicts:
libavfilter/vf_interlace.c
libavfilter/x86/Makefile

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavfilter/interlace.h
libavfilter/vf_interlace.c
libavfilter/x86/Makefile
libavfilter/x86/vf_interlace.asm
libavfilter/x86/vf_interlace_init.c

index 0000000,2d47050..44f1e06
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,59 +1,58 @@@
 - * 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,
@@@ -109,11 -109,16 +107,18 @@@ static int config_out_props(AVFilterLin
      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");
  
@@@ -126,11 -132,11 +132,11 @@@ static void copy_picture_field(Interlac
  {
      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];
  
@@@ -203,9 -205,10 +204,9 @@@ static int filter_frame(AVFilterLink *i
      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 */
@@@ -1,15 -1,11 +1,17 @@@
  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
index 0000000,8c2e9b0..55b430d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,75 +1,75 @@@
 -;* 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
index 0000000,231ab85..68ee47d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,47 +1,47 @@@
 - * 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;
+ }