]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_idet.c
libavfilter: src_buffer: add time_base for audio
[ffmpeg] / libavfilter / vf_idet.c
index eee1671f58d6d9d488766c59c592b2f52506ab4c..0441c78fd013e3efadc9478f3bff08baa661670b 100644 (file)
@@ -26,6 +26,8 @@
 #undef NDEBUG
 #include <assert.h>
 
+#define HIST_SIZE 4
+
 typedef enum {
     TFF,
     BFF,
@@ -37,18 +39,31 @@ typedef struct {
     float interlace_threshold;
     float progressive_threshold;
 
-
+    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)
 {
@@ -80,13 +95,13 @@ static void filter(AVFilterContext *ctx)
     int y, i;
     int64_t alpha[2]={0};
     int64_t delta=0;
-    Type type;
+    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;
@@ -116,24 +131,41 @@ static void filter(AVFilterContext *ctx)
         type = UNDETERMINED;
     }
 
-    idet->prestat[type] ++;
+    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      (type == TFF){
-        av_log(ctx, AV_LOG_INFO, "Interlaced, top field first\n");
+    if      (idet->last_type == TFF){
         idet->cur->video->top_field_first = 1;
         idet->cur->video->interlaced = 1;
-    }else if(type == BFF){
-        av_log(ctx, AV_LOG_INFO, "Interlaced, bottom field first\n");
+    }else if(idet->last_type == BFF){
         idet->cur->video->top_field_first = 0;
         idet->cur->video->interlaced = 1;
-    }else if(type == PROGRSSIVE){
-        av_log(ctx, AV_LOG_INFO, "Progressive\n");
+    }else if(idet->last_type == PROGRSSIVE){
         idet->cur->video->interlaced = 0;
-    }else{
-        av_log(ctx, AV_LOG_INFO, "Undetermined\n");
-        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)
@@ -211,12 +243,18 @@ 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",
+    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);
     if (idet->cur ) avfilter_unref_buffer(idet->cur );
@@ -256,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;
 
@@ -265,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;