]> git.sesse.net Git - x264/blobdiff - filters/video/depth.c
cli: Refactor filter option parsing
[x264] / filters / video / depth.c
index 43b84db91ce378f143a76c3687c3032e079ab891..000ec1efa2642c9d783cdcc9e7e0d7e10261ff75 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * depth.c: bit-depth conversion video filter
  *****************************************************************************
- * Copyright (C) 2010-2012 x264 project
+ * Copyright (C) 2010-2016 x264 project
  *
  * Authors: Oskar Arvidsson <oskar@irock.se>
  *
@@ -50,13 +50,20 @@ static int depth_filter_csp_is_supported( int csp )
            csp_mask == X264_CSP_YV16 ||
            csp_mask == X264_CSP_YV24 ||
            csp_mask == X264_CSP_NV12 ||
-           csp_mask == X264_CSP_NV16;
+           csp_mask == X264_CSP_NV21 ||
+           csp_mask == X264_CSP_NV16 ||
+           csp_mask == X264_CSP_BGR ||
+           csp_mask == X264_CSP_RGB ||
+           csp_mask == X264_CSP_BGRA;
 }
 
 static int csp_num_interleaved( int csp, int plane )
 {
     int csp_mask = csp & X264_CSP_MASK;
-    return ( (csp_mask == X264_CSP_NV12 || csp_mask == X264_CSP_NV16) && plane == 1 ) ? 2 : 1;
+    return (csp_mask == X264_CSP_NV12 || csp_mask == X264_CSP_NV21 || csp_mask == X264_CSP_NV16) && plane == 1 ? 2 :
+           csp_mask == X264_CSP_BGR || csp_mask == X264_CSP_RGB ? 3 :
+           csp_mask == X264_CSP_BGRA ? 4 :
+           1;
 }
 
 /* The dithering algorithm is based on Sierra-2-4A error diffusion. It has been
@@ -65,12 +72,12 @@ static int csp_num_interleaved( int csp, int plane )
  * depth again is lossless. */
 #define DITHER_PLANE( pitch ) \
 static void dither_plane_##pitch( pixel *dst, int dst_stride, uint16_t *src, int src_stride, \
-                                        int width, int height, int16_t *errors ) \
+                                  int width, int height, int16_t *errors ) \
 { \
-    const int lshift = 16-BIT_DEPTH; \
-    const int rshift = 2*BIT_DEPTH-16; \
-    const int pixel_max = (1 << BIT_DEPTH)-1; \
-    const int half = 1 << (16-BIT_DEPTH); \
+    const int lshift = 16-X264_BIT_DEPTH; \
+    const int rshift = 16-X264_BIT_DEPTH+2; \
+    const int half = 1 << (16-X264_BIT_DEPTH+1); \
+    const int pixel_max = (1 << X264_BIT_DEPTH)-1; \
     memset( errors, 0, (width+1) * sizeof(int16_t) ); \
     for( int y = 0; y < height; y++, src += src_stride, dst += dst_stride ) \
     { \
@@ -78,14 +85,16 @@ static void dither_plane_##pitch( pixel *dst, int dst_stride, uint16_t *src, int
         for( int x = 0; x < width; x++ ) \
         { \
             err = err*2 + errors[x] + errors[x+1]; \
-            dst[x*pitch] = x264_clip3( (((src[x*pitch]+half)<<2)+err)*pixel_max >> 18, 0, pixel_max ); \
-            errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift); \
+            dst[x*pitch] = x264_clip3( ((src[x*pitch]<<2)+err+half) >> rshift, 0, pixel_max ); \
+            errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift); \
         } \
     } \
 }
 
 DITHER_PLANE( 1 )
 DITHER_PLANE( 2 )
+DITHER_PLANE( 3 )
+DITHER_PLANE( 4 )
 
 static void dither_image( cli_image_t *out, cli_image_t *img, int16_t *error_buf )
 {
@@ -100,27 +109,35 @@ static void dither_image( cli_image_t *out, cli_image_t *img, int16_t *error_buf
         dither_plane_##pitch( ((pixel*)out->plane[i])+off, out->stride[i]/sizeof(pixel), \
                 ((uint16_t*)img->plane[i])+off, img->stride[i]/2, width, height, error_buf )
 
-        if( num_interleaved == 1 )
+        if( num_interleaved == 4 )
         {
-            CALL_DITHER_PLANE( 1, 0 );
+            CALL_DITHER_PLANE( 4, 0 );
+            CALL_DITHER_PLANE( 4, 1 );
+            CALL_DITHER_PLANE( 4, 2 );
+            CALL_DITHER_PLANE( 4, 3 ); //we probably can skip this one
         }
-        else
+        else if( num_interleaved == 3 )
+        {
+            CALL_DITHER_PLANE( 3, 0 );
+            CALL_DITHER_PLANE( 3, 1 );
+            CALL_DITHER_PLANE( 3, 2 );
+        }
+        else if( num_interleaved == 2 )
         {
             CALL_DITHER_PLANE( 2, 0 );
             CALL_DITHER_PLANE( 2, 1 );
         }
+        else //if( num_interleaved == 1 )
+        {
+            CALL_DITHER_PLANE( 1, 0 );
+        }
     }
 }
 
 static void scale_image( cli_image_t *output, cli_image_t *img )
 {
-    /* this function mimics how swscale does upconversion. 8-bit is converted
-     * to 16-bit through left shifting the orginal value with 8 and then adding
-     * the original value to that. This effectively keeps the full color range
-     * while also being fast. for n-bit we basically do the same thing, but we
-     * discard the lower 16-n bits. */
     int csp_mask = img->csp & X264_CSP_MASK;
-    const int shift = 16-BIT_DEPTH;
+    const int shift = X264_BIT_DEPTH - 8;
     for( int i = 0; i < img->planes; i++ )
     {
         uint8_t *src = img->plane[i];
@@ -131,7 +148,7 @@ static void scale_image( cli_image_t *output, cli_image_t *img )
         for( int j = 0; j < height; j++ )
         {
             for( int k = 0; k < width; k++ )
-                dst[k] = ((src[k] << 8) + src[k]) >> shift;
+                dst[k] = src[k] << shift;
 
             src += img->stride[i];
             dst += output->stride[i]/2;
@@ -183,7 +200,7 @@ static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info,
 
     if( opt_string )
     {
-        static const char *optlist[] = { "bit_depth", NULL };
+        static const char * const optlist[] = { "bit_depth", NULL };
         char **opts = x264_split_options( opt_string, optlist );
 
         if( opts )
@@ -194,13 +211,13 @@ static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info,
             ret = bit_depth < 8 || bit_depth > 16;
             csp = bit_depth > 8 ? csp | X264_CSP_HIGH_DEPTH : csp & ~X264_CSP_HIGH_DEPTH;
             change_fmt = (info->csp ^ csp) & X264_CSP_HIGH_DEPTH;
-            x264_free_string_array( opts );
+            free( opts );
         }
         else
             ret = 1;
     }
 
-    FAIL_IF_ERROR( bit_depth != BIT_DEPTH, "this build supports only bit depth %d\n", BIT_DEPTH )
+    FAIL_IF_ERROR( bit_depth != X264_BIT_DEPTH, "this build supports only bit depth %d\n", X264_BIT_DEPTH )
     FAIL_IF_ERROR( ret, "unsupported bit depth conversion.\n" )
 
     /* only add the filter to the chain if it's needed */