]> git.sesse.net Git - vlc/blobdiff - plugins/yuv/video_yuv.c
(0.2.92 branch)
[vlc] / plugins / yuv / video_yuv.c
index 1826a11ea5c9d8c002e4d9be731d4e35a086abe4..f613870226b6386edebc61a8dafb848bc1bf4d77 100644 (file)
@@ -4,9 +4,10 @@
  * are a complete and portable C implementation, and may be replaced in certain
  * case by optimized functions.
  *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: video_yuv.c,v 1.16 2001/11/28 15:08:06 massiot Exp $
  *
- * Authors:
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +25,9 @@
  * Boston, MA 02111-1307, USA.
  *****************************************************************************/
 
+#define MODULE_NAME yuv
+#include "modules_inner.h"
+
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 
 #include "config.h"
 #include "common.h"
+#include "intf_msg.h"
 #include "threads.h"
 #include "mtime.h"
-#include "plugins.h"
+#include "tests.h"
+
 #include "video.h"
 #include "video_output.h"
-#include "video_yuv.h"
 
-#include "intf_msg.h"
+#include "video_common.h"
+
+#include "modules.h"
+#include "modules_export.h"
+
+static int     yuv_Probe      ( probedata_t *p_data );
+static int     yuv_Init       ( vout_thread_t *p_vout );
+static int     yuv_Reset      ( vout_thread_t *p_vout );
+static void    yuv_End        ( vout_thread_t *p_vout );
+
+static void    SetGammaTable  ( int *pi_table, double f_gamma );
+static void    SetYUV         ( vout_thread_t *p_vout );
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+void _M( yuv_getfunctions )( function_list_t * p_function_list )
+{
+    p_function_list->pf_probe = yuv_Probe;
+    p_function_list->functions.yuv.pf_init = yuv_Init;
+    p_function_list->functions.yuv.pf_reset = yuv_Reset;
+    p_function_list->functions.yuv.pf_end = yuv_End;
+}
+
+/*****************************************************************************
+ * yuv_Probe: tests probe the audio device and return a score
+ *****************************************************************************
+ * This function tries to open the DSP and returns a score to the plugin
+ * manager so that it can choose the most appropriate one.
+ *****************************************************************************/
+static int yuv_Probe( probedata_t *p_data )
+{
+    if( TestMethod( YUV_METHOD_VAR, "yuv" )
+         || TestMethod( YUV_METHOD_VAR, "c" ) )
+    {
+        return( 999 );
+    }
+
+    /* This module always works */
+    return( 50 );
+}
 
 /*****************************************************************************
- * vout_InitYUV: allocate and initialize translations tables
+ * yuv_Init: allocate and initialize translations tables
  *****************************************************************************
  * This function will allocate memory to store translation tables, depending
  * of the screen depth.
  *****************************************************************************/
-int yuv_CInit( vout_thread_t *p_vout )
+static int yuv_Init( vout_thread_t *p_vout )
 {
     size_t      tables_size;                        /* tables size, in bytes */
 
@@ -78,7 +124,7 @@ int yuv_CInit( vout_thread_t *p_vout )
     p_vout->yuv.p_base = malloc( tables_size );
     if( p_vout->yuv.p_base == NULL )
     {
-        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+        intf_ErrMsg("error: %s", strerror(ENOMEM));
         return( 1 );
     }
 
@@ -86,7 +132,7 @@ int yuv_CInit( vout_thread_t *p_vout )
     p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
     if( p_vout->yuv.p_buffer == NULL )
     {
-        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+        intf_ErrMsg("error: %s", strerror(ENOMEM));
         free( p_vout->yuv.p_base );
         return( 1 );
     }
@@ -97,7 +143,7 @@ int yuv_CInit( vout_thread_t *p_vout )
                              ( ( p_vout->i_bytes_per_pixel == 1 ) ? 2 : 1 ) );
     if( p_vout->yuv.p_offset == NULL )
     {
-        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+        intf_ErrMsg("error: %s", strerror(ENOMEM));
         free( p_vout->yuv.p_base );
         free( p_vout->yuv.p_buffer );
         return( 1 );
@@ -109,11 +155,11 @@ int yuv_CInit( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * yuv_CEnd: destroy translations tables
+ * yuv_End: destroy translations tables
  *****************************************************************************
  * Free memory allocated by yuv_CCreate.
  *****************************************************************************/
-void yuv_CEnd( vout_thread_t *p_vout )
+static void yuv_End( vout_thread_t *p_vout )
 {
     free( p_vout->yuv.p_base );
     free( p_vout->yuv.p_buffer );
@@ -121,25 +167,23 @@ void yuv_CEnd( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * yuv_CReset: re-initialize translations tables
+ * yuv_Reset: re-initialize translations tables
  *****************************************************************************
  * This function will initialize the tables allocated by vout_CreateTables and
  * set functions pointers.
  *****************************************************************************/
-int yuv_CReset( vout_thread_t *p_vout )
+static int yuv_Reset( vout_thread_t *p_vout )
 {
-    yuv_CEnd( p_vout );
-    return( yuv_CInit( p_vout ) );
+    yuv_End( p_vout );
+    return( yuv_Init( p_vout ) );
 }
 
-/* following functions are local */
-
 /*****************************************************************************
  * SetGammaTable: return intensity table transformed by gamma curve.
  *****************************************************************************
  * pi_table is a table of 256 entries from 0 to 255.
  *****************************************************************************/
-void SetGammaTable( int *pi_table, double f_gamma )
+static void SetGammaTable( int *pi_table, double f_gamma )
 {
     int         i_y;                                       /* base intensity */
 
@@ -155,8 +199,8 @@ void SetGammaTable( int *pi_table, double f_gamma )
 
 /*****************************************************************************
  * SetYUV: compute tables and set function pointers
-+ *****************************************************************************/
-void SetYUV( vout_thread_t *p_vout )
+ *****************************************************************************/
+static void SetYUV( vout_thread_t *p_vout )
 {
     int         pi_gamma[256];                                /* gamma table */
     int         i_index;                                  /* index in tables */
@@ -189,7 +233,7 @@ void SetYUV( vout_thread_t *p_vout )
                     transp[ i_index ] = 0;
                 }
                 /* the colors have been allocated, we can set the palette */
-                p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
+                p_vout->pf_setpalette( p_vout, bright, bright, bright, transp );
                 p_vout->i_white_pixel = 0xff;
                 p_vout->i_black_pixel = 0x00;
                 p_vout->i_gray_pixel = 0x44;
@@ -262,7 +306,7 @@ void SetYUV( vout_thread_t *p_vout )
                                 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
                         {
                             /* this one should never happen unless someone fscked up my code */
-                            if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette\n" ); break; }
+                            if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette" ); break; }
 
                             /* clip the colors */
                             red[j] = CLIP( r );
@@ -287,7 +331,7 @@ void SetYUV( vout_thread_t *p_vout )
                 /* the colors have been allocated, we can set the palette */
                 /* there will eventually be a way to know which colors
                  * couldn't be allocated and try to find a replacement */
-                p_vout->p_set_palette( p_vout, red, green, blue, transp );
+                p_vout->pf_setpalette( p_vout, red, green, blue, transp );
 
                 p_vout->i_white_pixel = 0xff;
                 p_vout->i_black_pixel = 0x00;
@@ -395,31 +439,64 @@ void SetYUV( vout_thread_t *p_vout )
     /*
      * Set functions pointers
      */
-    if( p_vout->b_grayscale )
+    if( p_vout->b_YCbr)
+    {
+        switch( p_vout->i_bytes_per_pixel)
+        {
+#define _X( foo ) (vout_yuv_convert_t *) _M( foo )
+        case 1:
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420YCbr8 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422YCbr8 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444YCbr8 );
+            break;
+        
+        case 2:
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420YCbr16 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422YCbr16 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444YCbr16 );
+           break;
+        
+        case 3:
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420YCbr24 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422YCbr24 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444YCbr24 );
+             break;
+        
+        case 4:
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420YCbr32 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422YCbr32 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444YCbr32 );
+            break;
+        }
+#undef _X
+    }    
+    else if( p_vout->b_grayscale )
     {
         /* Grayscale */
         switch( p_vout->i_bytes_per_pixel )
         {
+#define _X( foo ) (vout_yuv_convert_t *) _M( foo )
         case 1:
-            p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
-            p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
-            p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
+            p_vout->yuv.pf_yuv420 = _X( ConvertY4Gray8 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertY4Gray8 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertY4Gray8 );
             break;
         case 2:
-            p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
-            p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
-            p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
+            p_vout->yuv.pf_yuv420 = _X( ConvertY4Gray16 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertY4Gray16 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertY4Gray16 );
             break;
         case 3:
-            p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
-            p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
-            p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
+            p_vout->yuv.pf_yuv420 = _X( ConvertY4Gray24 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertY4Gray24 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertY4Gray24 );
             break;
         case 4:
-            p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
-            p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
-            p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
+            p_vout->yuv.pf_yuv420 = _X( ConvertY4Gray32 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertY4Gray32 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertY4Gray32 );
             break;
+#undef _X
         }
     }
     else
@@ -427,27 +504,30 @@ void SetYUV( vout_thread_t *p_vout )
         /* Color */
         switch( p_vout->i_bytes_per_pixel )
         {
+#define _X( foo ) (vout_yuv_convert_t *) _M( foo )
         case 1:
-            p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
-            p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
-            p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420RGB8 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422RGB8 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444RGB8 );
             break;
         case 2:
-            p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB16;
-            p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB16;
-            p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB16;
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420RGB16 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422RGB16 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444RGB16 );
             break;
         case 3:
-            p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB24;
-            p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB24;
-            p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB24;
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420RGB24 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422RGB24 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444RGB24 );
             break;
         case 4:
-            p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB32;
-            p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB32;
-            p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB32;
+            p_vout->yuv.pf_yuv420 = _X( ConvertYUV420RGB32 );
+            p_vout->yuv.pf_yuv422 = _X( ConvertYUV422RGB32 );
+            p_vout->yuv.pf_yuv444 = _X( ConvertYUV444RGB32 );
             break;
-        }
+#undef _X
+      }
     }
 }
 
@@ -458,9 +538,9 @@ void SetYUV( vout_thread_t *p_vout )
  * It will also set horizontal and vertical scaling indicators. If b_double
  * is set, the p_offset structure has interleaved Y and U/V offsets.
  *****************************************************************************/
-void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
-                boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset,
-                boolean_t b_double )
+void _M( SetOffset )( int i_width, int i_height, int i_pic_width,
+                      int i_pic_height, boolean_t *pb_h_scaling,
+                      int *pi_v_scaling, int *p_offset, boolean_t b_double )
 {
     int i_x;                                    /* x position in destination */
     int i_scale_count;                                     /* modulo counter */
@@ -468,53 +548,71 @@ void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
     /*
      * Prepare horizontal offset array
      */
-    if( i_pic_width - i_width > 0 )
+    if( i_pic_width - i_width == 0 )
+    {
+        /* No horizontal scaling: YUV conversion is done directly to picture */
+        *pb_h_scaling = 0;
+    }
+    else if( i_pic_width - i_width > 0 )
     {
         /* Prepare scaling array for horizontal extension */
         *pb_h_scaling = 1;
         i_scale_count = i_pic_width;
-        if( b_double )
+        if( !b_double )
         {
-            int i_dummy = 0;
             for( i_x = i_width; i_x--; )
             {
                 while( (i_scale_count -= i_width) > 0 )
                 {
                     *p_offset++ = 0;
-                    *p_offset++ = 0;
                 }
                 *p_offset++ = 1;
-                *p_offset++ = i_dummy & 1;
-                i_dummy++;
                 i_scale_count += i_pic_width;
             }
         }
         else
         {
+            int i_dummy = 0;
             for( i_x = i_width; i_x--; )
             {
                 while( (i_scale_count -= i_width) > 0 )
                 {
                     *p_offset++ = 0;
+                    *p_offset++ = 0;
                 }
                 *p_offset++ = 1;
+                *p_offset++ = i_dummy;
+                i_dummy = 1 - i_dummy;
                 i_scale_count += i_pic_width;
             }
         }
     }
-    else if( i_pic_width - i_width < 0 )
+    else /* if( i_pic_width - i_width < 0 ) */
     {
         /* Prepare scaling array for horizontal reduction */
-        *pb_h_scaling =  1;
-        i_scale_count =         i_pic_width;
-        if( b_double )
+        *pb_h_scaling = 1;
+        i_scale_count = i_width;
+        if( !b_double )
+        {
+           for( i_x = i_pic_width; i_x--; )
+            {
+                *p_offset = 1;
+                while( (i_scale_count -= i_pic_width) > 0 )
+                {
+                    *p_offset += 1;
+                }
+                p_offset++;
+                i_scale_count += i_width;
+            }
+        }
+        else
         {
             int i_remainder = 0;
             int i_jump;
             for( i_x = i_pic_width; i_x--; )
             {
                 i_jump = 1;
-                while( (i_scale_count -= i_pic_width) >= 0 )
+                while( (i_scale_count -= i_pic_width) > 0 )
                 {
                     i_jump += 1;
                 }
@@ -523,41 +621,23 @@ void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
                 i_remainder = i_jump & 1;
                 i_scale_count += i_width;
             }
-         }
-        else
-        {
-           for( i_x = i_pic_width; i_x--; )
-            {
-                *p_offset = 1;
-                while( (i_scale_count -= i_pic_width) >= 0 )
-                {
-                    *p_offset += 1;
-                }
-                p_offset++;
-                i_scale_count += i_width;
-            }
         }
-    }
-    else
-    {
-        /* No horizontal scaling: YUV conversion is done directly to picture */
-        *pb_h_scaling = 0;
-    }
+     }
 
     /*
      * Set vertical scaling indicator
      */
-    if( i_pic_height - i_height > 0 )
+    if( i_pic_height - i_height == 0 )
     {
-        *pi_v_scaling = 1;
+        *pi_v_scaling = 0;
     }
-    else if( i_pic_height - i_height < 0 )
+    else if( i_pic_height - i_height > 0 )
     {
-        *pi_v_scaling = -1;
+        *pi_v_scaling = 1;
     }
-    else
+    else /* if( i_pic_height - i_height < 0 ) */
     {
-        *pi_v_scaling = 0;
+        *pi_v_scaling = -1;
     }
 }