]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_idet.c
lavfi/hflip: copy palette data in start_frame()
[ffmpeg] / libavfilter / vf_idet.c
index 39b3987699af52c35d8bbf805ee003e03cf4c514..0441c78fd013e3efadc9478f3bff08baa661670b 100644 (file)
 #undef NDEBUG
 #include <assert.h>
 
+#define HIST_SIZE 4
+
+typedef enum {
+    TFF,
+    BFF,
+    PROGRSSIVE,
+    UNDETERMINED,
+} Type;
+
 typedef struct {
     float interlace_threshold;
     float progressive_threshold;
 
-    int stat_tff;
-    int stat_bff;
-    int stat_progressive;
-    int stat_undetermined;
+    Type last_type;
+    Type prestat[4];
+    Type poststat[4];
+
+    uint8_t history[HIST_SIZE];
 
     AVFilterBufferRef *cur;
     AVFilterBufferRef *next;
     AVFilterBufferRef *prev;
     AVFilterBufferRef *out;
-    int (*filter_line)(uint8_t *prev, uint8_t *cur, uint8_t *next, int w);
+    int (*filter_line)(const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w);
 
     const AVPixFmtDescriptor *csp;
 } IDETContext;
 
+static const char *type2str(Type type)
+{
+    switch(type) {
+        case TFF         : return "Top Field First   ";
+        case BFF         : return "Bottom Field First";
+        case PROGRSSIVE  : return "Progressive       ";
+        case UNDETERMINED: return "Undetermined      ";
+    }
+    return NULL;
+}
 
 static int filter_line_c(const uint8_t *a, const uint8_t *b, const uint8_t *c, int w)
 {
@@ -75,12 +95,13 @@ static void filter(AVFilterContext *ctx)
     int y, i;
     int64_t alpha[2]={0};
     int64_t delta=0;
+    Type type, best_type;
+    int match = 0;
 
     for (i = 0; i < idet->csp->nb_components; i++) {
         int w = idet->cur->video->w;
         int h = idet->cur->video->h;
         int refs = idet->cur->linesize[i];
-        int df = (idet->csp->comp[i].depth_minus1 + 8) / 8;
 
         if (i && i<3) {
             w >>= idet->csp->log2_chroma_w;
@@ -101,25 +122,50 @@ static void filter(AVFilterContext *ctx)
 #endif
 
     if      (alpha[0] / (float)alpha[1] > idet->interlace_threshold){
-        av_log(ctx, AV_LOG_INFO, "Interlaced, top field first\n");
-        idet->stat_tff++;
+        type = TFF;
+    }else if(alpha[1] / (float)alpha[0] > idet->interlace_threshold){
+        type = BFF;
+    }else if(alpha[1] / (float)delta    > idet->progressive_threshold){
+        type = PROGRSSIVE;
+    }else{
+        type = UNDETERMINED;
+    }
+
+    memmove(idet->history+1, idet->history, HIST_SIZE-1);
+    idet->history[0] = type;
+    best_type = UNDETERMINED;
+    for(i=0; i<HIST_SIZE; i++){
+        if(idet->history[i] != UNDETERMINED){
+            if(best_type == UNDETERMINED)
+                best_type = idet->history[i];
+
+            if(idet->history[i] == best_type) {
+                match++;
+            }else{
+                match=0;
+                break;
+            }
+        }
+    }
+    if(idet->last_type == UNDETERMINED){
+        if(match  ) idet->last_type = best_type;
+    }else{
+        if(match>2) idet->last_type = best_type;
+    }
+
+    if      (idet->last_type == TFF){
         idet->cur->video->top_field_first = 1;
         idet->cur->video->interlaced = 1;
-    }else if(alpha[1] / (float)alpha[0] > idet->interlace_threshold){
-        av_log(ctx, AV_LOG_INFO, "Interlaced, bottom field first\n");
-        idet->stat_bff++;
+    }else if(idet->last_type == BFF){
         idet->cur->video->top_field_first = 0;
         idet->cur->video->interlaced = 1;
-    }else if(alpha[1] / (float)delta    > idet->progressive_threshold){
-        av_log(ctx, AV_LOG_INFO, "Progressive\n");
-        idet->stat_progressive++;
+    }else if(idet->last_type == PROGRSSIVE){
         idet->cur->video->interlaced = 0;
-    }else{
-        av_log(ctx, AV_LOG_INFO, "Undetermined\n");
-        idet->stat_undetermined++;
-        idet->cur->video->interlaced      = idet->prev->video->interlaced;
-        idet->cur->video->top_field_first = idet->prev->video->top_field_first;
     }
+
+    idet->prestat [           type] ++;
+    idet->poststat[idet->last_type] ++;
+    av_log(ctx, AV_LOG_DEBUG, "Single frame:%s, Multi frame:%s\n", type2str(type), type2str(idet->last_type));
 }
 
 static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
@@ -197,11 +243,17 @@ static av_cold void uninit(AVFilterContext *ctx)
 {
     IDETContext *idet = ctx->priv;
 
-    av_log(ctx, AV_LOG_INFO, "TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
-           idet->stat_tff,
-           idet->stat_bff,
-           idet->stat_progressive,
-           idet->stat_undetermined
+    av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
+           idet->prestat[TFF],
+           idet->prestat[BFF],
+           idet->prestat[PROGRSSIVE],
+           idet->prestat[UNDETERMINED]
+    );
+    av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
+           idet->poststat[TFF],
+           idet->poststat[BFF],
+           idet->poststat[PROGRSSIVE],
+           idet->poststat[UNDETERMINED]
     );
 
     if (idet->prev) avfilter_unref_buffer(idet->prev);
@@ -242,7 +294,6 @@ static int query_formats(AVFilterContext *ctx)
 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 {
     IDETContext *idet = ctx->priv;
-    int cpu_flags = av_get_cpu_flags();
 
     idet->csp = NULL;
 
@@ -251,6 +302,9 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 
     if (args) sscanf(args, "%f:%f", &idet->interlace_threshold, &idet->progressive_threshold);
 
+    idet->last_type = UNDETERMINED;
+    memset(idet->history, UNDETERMINED, HIST_SIZE);
+
     idet->filter_line = filter_line_c;
 
     return 0;