All pastes #896941 Raw Edit

someone

public text v1 · immutable
·published 2008-02-09 01:59 UTC
rendered paste body
Index: libhb/deinterlace.c===================================================================--- libhb/deinterlace.c	(revision 1252)+++ libhb/deinterlace.c	(working copy)@@ -41,6 +41,7 @@     int              yadif_mode;
     int              yadif_parity;
     int              yadif_ready;
+    int              comb;
     
     uint8_t        * yadif_ref[4][3];        
     int              yadif_ref_stride[3];
@@ -84,6 +85,53 @@     hb_deinterlace_close,
 };
 
+int detect_comb( hb_buffer_t * buf, int width, int height);
+
+int detect_comb( hb_buffer_t * buf, int width, int height)
+{
+    /* See if frame shows interlacing */
+    int j, n, off, block, cc_1, cc_2, cc, flag, eq, diff, thres;
+    uint16_t s1, s2, s3, s4;
+    cc_1 = 0; cc_2 = 0;
+    eq = 10; diff = 30; thres = 0;
+    
+    block = width;
+    flag = 0;
+    
+    for(j=0; j<block; ++j)
+    {
+        off=0;
+        
+        for(n=0; n<(height-4); n=n+2)
+        {
+            s1 = (buf->data[off+j        ] & 0xff);
+            s2 = (buf->data[off+j+  block] & 0xff);
+            s3 = (buf->data[off+j+2*block] & 0xff);
+            s4 = (buf->data[off+j+3*block] & 0xff);
+
+            if((abs(s1 - s3) < eq) &&
+                (abs(s1 - s2) > diff)) ++cc_1;
+
+            if((abs(s2 - s4) < eq) &&
+                (abs(s2 - s3) > diff)) ++cc_2;
+
+            off +=2*block;
+        }
+    }
+    
+    // compare results
+
+    cc = (int)((cc_1 + cc_2)*1000.0/(width*height));
+
+    flag = (cc > thres) ? 1:0;
+    
+    if(cc)
+        hb_log("flag: %i | cc: %i | cc1: %i | cc2: %i", flag, cc, cc_1, cc_2);
+        
+    return flag;
+}
+
+
 static void yadif_store_ref( const uint8_t ** pic, 
                              hb_filter_private_t * pv )
 {
@@ -115,6 +163,26 @@     }
 }
 
+static void yadif_get_ref( uint8_t ** pic, hb_filter_private_t * pv, int frm )
+{
+    int i;
+    for( i = 0; i < 3; i++ )
+    {
+        uint8_t * dst = pic[i];
+        const uint8_t * ref = pv->yadif_ref[frm][i];
+        int w = pv->width[i];
+        int ref_stride = pv->yadif_ref_stride[i];
+        
+        int y;
+        for( y = 0; y < pv->height[i]; y++ )
+        {
+            memcpy(dst, ref, w);
+            dst += w;
+            ref += ref_stride;
+        }
+    }
+}
+
 static void yadif_filter_line( uint8_t *dst,
                                uint8_t *prev,
                                uint8_t *cur, 
@@ -520,13 +588,25 @@     {        
         avpicture_fill( &pv->pic_out, pv->buf_out[0]->data, 
                         pix_fmt, width, height );
-        
-        avpicture_deinterlace( &pv->pic_out, &pv->pic_in, 
+
+        if( detect_comb(buf_in, width, height) )
+        {
+            hb_log("found combing!");
+            
+            avpicture_deinterlace( &pv->pic_out, &pv->pic_in, 
                                pix_fmt, width, height );
-        
-        hb_buffer_copy_settings( pv->buf_out[0], buf_in );
+            
+            hb_buffer_copy_settings( pv->buf_out[0], buf_in );
+            
+            *buf_out = pv->buf_out[0];
 
-        *buf_out = pv->buf_out[0];
+        }
+        else
+        {
+            hb_buffer_copy_settings( pv->buf_out[0], buf_in );
+
+            *buf_out = buf_in;
+        }
         
         return FILTER_OK;
     }
@@ -544,6 +624,7 @@     
     /* Store current frame in yadif cache */
     yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
+    pv->comb = (pv->comb << 1) | detect_comb(buf_in, width, height);
     
     /* If yadif is not ready, store another ref and return FILTER_DELAY */
     if( pv->yadif_ready == 0 )
@@ -551,50 +632,64 @@         yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
         
         hb_buffer_copy_settings( pv->buf_settings, buf_in );
--        /* don't let 'work_loop' send a chapter mark upstream */-        buf_in->new_chap  = 0; 
+        /* don't let 'work_loop' send a chapter mark upstream */
+        buf_in->new_chap  = 0;
+
         pv->yadif_ready = 1;
         
         return FILTER_DELAY;
     }
 
-    /* Perform yadif and mcdeint filtering */
-    int frame;
-    for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ )
+    /* yadif & mcdeint work one frame behind so if the previous frame
+     * had combing, deinterlace it otherwise just output it. */
+    if(  (pv->comb & 2 ) == 0 )
     {
-        int parity = frame ^ tff ^ 1;
-        
-        avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data, 
-                        pix_fmt, width, height );
-        
-        yadif_filter( pv->pic_out.data, parity, tff, pv );
+        /* previous frame not interlaced - copy cached input frame to buf_out */
+        avpicture_fill( &pv->pic_out,  pv->buf_out[0]->data, pix_fmt, width, height );
+        yadif_get_ref( (uint8_t**)pv->pic_out.data, pv, 1 );
+        *buf_out = pv->buf_out[0];
+    }
+    else
+    {
+        /* Perform yadif and mcdeint filtering */
+        hb_log("combing detected, passing to yadif");
 
-        if( pv->mcdeint_mode >= 0 )
+        int frame;
+        for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ )
         {
-            avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data, 
+            int parity = frame ^ tff ^ 1;
+            
+            avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data, 
                             pix_fmt, width, height );
-            
-            mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
-            
-            *buf_out = pv->buf_out[ (frame^1)];
+
+            yadif_filter( pv->pic_out.data, parity, tff, pv );
+
+            if( pv->mcdeint_mode >= 0 )
+            {
+                avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data, 
+                                pix_fmt, width, height );
+
+                mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
+
+                *buf_out = pv->buf_out[ (frame^1)];
+            }
+            else
+            {
+                *buf_out = pv->buf_out[!(frame^1)];
+            }
         }
-        else
-        {
-            *buf_out = pv->buf_out[!(frame^1)];
-        }
     }
-    
+
     /* Copy buffered settings to output buffer settings */
     hb_buffer_copy_settings( *buf_out, pv->buf_settings );
     
     /* Replace buffered settings with input buffer settings */
     hb_buffer_copy_settings( pv->buf_settings, buf_in );    
--    /* don't let 'work_loop' send a chapter mark upstream */-    buf_in->new_chap  = 0; 
+    /* don't let 'work_loop' send a chapter mark upstream */
+    buf_in->new_chap  = 0;
+
     return FILTER_OK;
 }