]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_yadif.c
Merge commit '61b203ffe6c71789acb14f51483d63fe9e516842'
[ffmpeg] / libavfilter / vf_yadif.c
index 7ffce9ad1620bc1647812112da79f117b33fce39..40383a4d06bda7223a11fb264fec119cac19c3cb 100644 (file)
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
 #include "avfilter.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
 #include "yadif.h"
 
+
 typedef struct ThreadData {
     AVFrame *frame;
     int plane;
@@ -37,13 +40,42 @@ typedef struct ThreadData {
     int tff;
 } ThreadData;
 
+typedef struct YADIFContext {
+    const AVClass *class;
+
+    enum YADIFMode   mode;
+    enum YADIFParity parity;
+    enum YADIFDeint  deint;
+
+    int frame_pending;
+
+    AVFrame *cur;
+    AVFrame *next;
+    AVFrame *prev;
+    AVFrame *out;
+
+    /**
+     * Required alignment for filter_line
+     */
+    void (*filter_line)(void *dst,
+                        void *prev, void *cur, void *next,
+                        int w, int prefs, int mrefs, int parity, int mode);
+    void (*filter_edges)(void *dst, void *prev, void *cur, void *next,
+                         int w, int prefs, int mrefs, int parity, int mode);
+
+    const AVPixFmtDescriptor *csp;
+    int eof;
+    uint8_t *temp_line;
+    int temp_line_size;
+} YADIFContext;
+
 #define CHECK(j)\
-    {   int score = FFABS(cur[mrefs - 1 + (j)] - cur[prefs - 1 - (j)])\
-                  + FFABS(cur[mrefs  +(j)] - cur[prefs  -(j)])\
-                  + FFABS(cur[mrefs + 1 + (j)] - cur[prefs + 1 - (j)]);\
+    {   int score = FFABS(cur[mrefs - 1 + j] - cur[prefs - 1 - j])\
+                  + FFABS(cur[mrefs     + j] - cur[prefs     - j])\
+                  + FFABS(cur[mrefs + 1 + j] - cur[prefs + 1 - j]);\
         if (score < spatial_score) {\
             spatial_score= score;\
-            spatial_pred= (cur[mrefs  +(j)] + cur[prefs  -(j)])>>1;\
+            spatial_pred= (cur[mrefs    + j] + cur[prefs     - j])>>1;\
 
 /* The is_not_edge argument here controls when the code will enter a branch
  * which reads up to and including x-3 and x+3. */
@@ -461,6 +493,9 @@ static int config_props(AVFilterLink *link)
 {
     AVFilterContext *ctx = link->src;
     YADIFContext *s = link->src->priv;
+    int cpu_flags = av_get_cpu_flags();
+    int bit_depth = (!s->csp) ? 8
+                                  : s->csp->comp[0].depth_minus1 + 1;
 
     link->time_base.num = link->src->inputs[0]->time_base.num;
     link->time_base.den = link->src->inputs[0]->time_base.den * 2;
@@ -484,9 +519,38 @@ static int config_props(AVFilterLink *link)
         s->filter_edges = filter_edges;
     }
 
-    if (ARCH_X86)
-        ff_yadif_init_x86(s);
-
+#if HAVE_YASM
+    if (bit_depth >= 15) {
+        if (EXTERNAL_SSE4(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_16bit_sse4;
+        else if (EXTERNAL_SSSE3(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_16bit_ssse3;
+        else if (EXTERNAL_SSE2(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_16bit_sse2;
+#if ARCH_X86_32
+        else if (EXTERNAL_MMXEXT(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_16bit_mmxext;
+#endif /* ARCH_X86_32 */
+    } else if ( bit_depth >= 9 && bit_depth <= 14) {
+        if (EXTERNAL_SSSE3(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_10bit_ssse3;
+        else if (EXTERNAL_SSE2(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_10bit_sse2;
+#if ARCH_X86_32
+        else if (EXTERNAL_MMXEXT(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_10bit_mmxext;
+#endif /* ARCH_X86_32 */
+    } else {
+        if (EXTERNAL_SSSE3(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_ssse3;
+        else if (EXTERNAL_SSE2(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_sse2;
+#if ARCH_X86_32
+        else if (EXTERNAL_MMXEXT(cpu_flags))
+            s->filter_line = ff_yadif_filter_line_mmxext;
+#endif /* ARCH_X86_32 */
+    }
+#endif /* HAVE_YASM */
     return 0;
 }
 
@@ -517,25 +581,6 @@ static const AVOption yadif_options[] = {
 
 AVFILTER_DEFINE_CLASS(yadif);
 
-static const AVFilterPad avfilter_vf_yadif_inputs[] = {
-    {
-        .name          = "default",
-        .type          = AVMEDIA_TYPE_VIDEO,
-        .filter_frame  = filter_frame,
-    },
-    { NULL }
-};
-
-static const AVFilterPad avfilter_vf_yadif_outputs[] = {
-    {
-        .name          = "default",
-        .type          = AVMEDIA_TYPE_VIDEO,
-        .request_frame = request_frame,
-        .config_props  = config_props,
-    },
-    { NULL }
-};
-
 AVFilter ff_vf_yadif = {
     .name          = "yadif",
     .description   = NULL_IF_CONFIG_SMALL("Deinterlace the input image."),
@@ -543,7 +588,19 @@ AVFilter ff_vf_yadif = {
     .priv_class    = &yadif_class,
     .uninit        = uninit,
     .query_formats = query_formats,
-    .inputs        = avfilter_vf_yadif_inputs,
-    .outputs       = avfilter_vf_yadif_outputs,
+
+    .inputs        = (const AVFilterPad[]) {{ .name             = "default",
+                                              .type             = AVMEDIA_TYPE_VIDEO,
+                                              .filter_frame     = filter_frame,
+                                            },
+                                            { .name = NULL}},
+
+    .outputs       = (const AVFilterPad[]) {{ .name             = "default",
+                                              .type             = AVMEDIA_TYPE_VIDEO,
+                                              .request_frame    = request_frame,
+                                              .config_props     = config_props,
+                                            },
+                                            { .name = NULL}},
+
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };