]> granicus.if.org Git - handbrake/commitdiff
= Adds an hb_detect_comb() function that indicates whether or not a frame shows inter...
authorjbrjake <jb.rubin@gmail.com>
Sun, 23 Mar 2008 19:53:39 +0000 (19:53 +0000)
committerjbrjake <jb.rubin@gmail.com>
Sun, 23 Mar 2008 19:53:39 +0000 (19:53 +0000)
- Utilitizes that function in scan.c to analyze the preview frames
- Sets a new title->detected_interlacing variable to true if half or more previews show combing, and warns the user in the log.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1359 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/common.h
libhb/hb.c
libhb/hb.h
libhb/scan.c

index aa4cfc084e70b3ac6da61e8c445df165cf5312c0..4758d9c8d9b241173de695e73ff58638368fa907 100644 (file)
@@ -427,6 +427,7 @@ struct hb_title_s
     int         rate;
     int         rate_base;
     int         crop[4];
+    int         detected_interlacing;
 
     uint32_t    palette[16];
 
index b2a67119f9a04715175cb1e9f61346da51a746be..fd3cd45ea6130e6c92781a63e1e69e7a6ece23d8 100644 (file)
@@ -432,6 +432,112 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
     avpicture_free( &pic_in );
 }
 
+ /**
+ * Analyzes a frame to detect interlacing artifacts
+ * and returns true if interlacing (combing) is found.
+ *
+ * Code taken from Thomas Oestreich's 32detect filter
+ * in the Transcode project, with minor formatting changes.
+ *
+ * @param buf         An hb_buffer structure holding valid frame data
+ * @param width       The frame's width in pixels
+ * @param height      The frame's height in pixels
+ * @param color_equal Sensitivity for detecting similar colors
+ * @param color_diff  Sensitivity for detecting different colors
+ * @param threshold   Sensitivity for flagging planes as combed
+ */
+int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, int color_diff, int threshold )
+{
+    int j, k, n, off, block, cc_1, cc_2, cc[3], flag[3];
+    uint16_t s1, s2, s3, s4;
+    cc_1 = 0; cc_2 = 0;
+
+    int offset = 0;
+    
+    for( k = 0; k < 3; k++ )
+    {
+        /* One pas for Y, one pass for Cb, one pass for Cr */
+
+        if( k == 1 )
+        {
+            /* Y has already been checked, now offset by Y's dimensions
+               and divide all the other values by 2, since Cr and Cb
+               are half-size compared to Y.                               */
+            offset = width * height;
+            width >>= 1;
+            height >>= 1;
+            threshold >>= 1;
+            color_equal >>= 1;
+            color_diff >>= 1;
+        }
+        else if ( k == 2 )
+        {
+            /* Y and Cb are done, so the offset needs to be bumped
+               so it's width*height + (width / 2) * (height / 2)  */
+            offset *= 5/4;
+        }
+        
+        /* Look at one horizontal line at a time */
+        block = width;
+        
+        for( j = 0; j < block; ++j )
+        {
+            off = 0;
+            
+            for( n = 0; n < ( height - 4 ); n = n + 2 )
+            {
+                /* Look at groups of 4 sequential horizontal lines */
+                s1 = ( ( buf->data + offset )[ off + j             ] & 0xff );
+                s2 = ( ( buf->data + offset )[ off + j + block     ] & 0xff );
+                s3 = ( ( buf->data + offset )[ off + j + 2 * block ] & 0xff );
+                s4 = ( ( buf->data + offset )[ off + j + 3 * block ] & 0xff );
+                
+                /* Note if the 1st and 2nd lines are more different in
+                   color than the 1st and 3rd lines are similar in color.*/
+                if ( ( abs( s1 - s3 ) < color_equal ) && 
+                     ( abs( s1 - s2 ) > color_diff ) )
+                        ++cc_1;
+    
+                /* Note if the 2nd and 3rd lines are more different in
+                   color than the 2nd and 4th lines are similar in color.*/
+                if ( ( abs( s2 - s4 ) < color_equal ) &&
+                     ( abs( s2 - s3 ) > color_diff) )
+                        ++cc_2;
+                
+                /* Now move down 2 horizontal lines before starting over.*/
+                off += 2 * block;
+            }
+        }
+        
+        // compare results
+        /* The final metric seems to be doing some kind of bits per pixel style calculation
+           to decide whether or not enough lines showed alternating colors for the frame size. */
+        cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
+        
+        /* If the plane's cc score meets the threshold, flag it as combed. */
+        flag[k] = 0;
+        if ( cc[k] > threshold )
+        {
+            flag[k] = 1;
+        }
+    }
+    
+#if 0
+/* Debugging info */
+//    if(flag)
+        hb_log("flags: %i/%i/%i | cc0: %i | cc1: %i | cc2: %i", flag[0], flag[1], flag[2], cc[0], cc[1], cc[2]);
+#endif
+    
+    /* When more than one plane shows combing, tell the caller. */
+    if (flag[0] || flag[1] || flag[2] )
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+
 /**
  * Calculates job width and height for anamorphic content,
  *
index 7454b634b72c0370d978e6eb228b538f64196ce3..6dfbf7be8cccaa4423dacf7d43664ebff0bf45d9 100644 (file)
@@ -76,6 +76,11 @@ void          hb_scan( hb_handle_t *, const char * path,
    Returns the list of valid titles detected by the latest scan. */
 hb_list_t   * hb_get_titles( hb_handle_t * );
 
+/* hb_detect_comb()
+   Analyze a frame for interlacing artifacts, returns true if they're found.
+   Taken from Thomas Oestreich's 32detect filter in the Transcode project.  */
+int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, int color_diff, int threshold );
+
 void          hb_get_preview( hb_handle_t *, hb_title_t *, int,
                               uint8_t * );
 void          hb_set_size( hb_job_t *, int ratio, int pixels );
index 5b62fecb04bc1b17e70b21292997789021a7b7a3..4aee25bc7f482df0fa22ce765400a695c7b27b80 100644 (file)
@@ -286,6 +286,8 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
     hb_list_t     * list_es, * list_raw;
     hb_libmpeg2_t * mpeg2;
     int progressive_count = 0;
+    int interlaced_preview_count = 0;
+
     int ar16_count = 0, ar4_count = 0;
 
     buf_ps   = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
@@ -419,7 +421,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
                 */
                 if( progressive_count == 6 )
                 {
-                    hb_log("Title's mostly progressive NTSC, setting fps to 23.976");
+                    hb_log("Title's mostly NTSC Film, setting fps to 23.976");
                 }
                 title->rate_base = 1126125;
             }
@@ -449,7 +451,14 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
         }
 
         buf_raw = hb_list_item( list_raw, 0 );
-
+        
+        /* Check preview for interlacing artifacts */
+        if( hb_detect_comb( buf_raw, title->width, title->height, 10, 30, 9 ) )
+        {
+            hb_log("Interlacing detected in preview frame %i", i);
+            interlaced_preview_count++;
+        }
+        
         hb_get_tempory_filename( data->h, filename, "%x%d",
                                  (intptr_t)title, i );
 
@@ -523,6 +532,18 @@ skip_preview:
             title->crop[2], title->crop[3],
             title->aspect == HB_ASPECT_BASE * 16 / 9 ? "16:9" :
                 title->aspect == HB_ASPECT_BASE * 4 / 3 ? "4:3" : "none" );
+
+    if( interlaced_preview_count >= ( npreviews / 2 ) )
+    {
+        hb_log("Title is likely interlaced or telecined (%i out of %i previews). You should do something about that.",
+               interlaced_preview_count, npreviews);
+        title->detected_interlacing = 1;
+    }
+    else
+    {
+        title->detected_interlacing = 0;
+    }
+
     goto cleanup;
 
 error: