Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

i420_rgb.h

00001 /*****************************************************************************
00002  * i420_rgb.h : YUV to bitmap RGB conversion module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2000, 2004 the VideoLAN team
00005  * $Id: i420_rgb.h 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Samuel Hocevar <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  * 
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00025 #define CMAP_RGB2_SIZE 256
00026 
00033 struct chroma_sys_t
00034 {
00035     uint8_t  *p_buffer;
00036     int *p_offset;
00037 
00038 #ifdef MODULE_NAME_IS_i420_rgb
00039 
00040     void *p_base;                      
00041     uint8_t   *p_rgb8;                 
00042     uint16_t  *p_rgb16;                
00043     uint32_t  *p_rgb32;                
00049     uint16_t  p_rgb_r[CMAP_RGB2_SIZE];  
00050     uint16_t  p_rgb_g[CMAP_RGB2_SIZE];  
00051     uint16_t  p_rgb_b[CMAP_RGB2_SIZE];  
00052 #endif
00053 };
00054 
00055 /*****************************************************************************
00056  * Prototypes
00057  *****************************************************************************/
00058 #ifdef MODULE_NAME_IS_i420_rgb
00059 void E_(I420_RGB8)         ( vout_thread_t *, picture_t *, picture_t * );
00060 void E_(I420_RGB16_dither) ( vout_thread_t *, picture_t *, picture_t * );
00061 #endif
00062 void E_(I420_RGB16)        ( vout_thread_t *, picture_t *, picture_t * );
00063 void E_(I420_RGB32)        ( vout_thread_t *, picture_t *, picture_t * );
00064 
00065 /*****************************************************************************
00066  * CONVERT_*_PIXEL: pixel conversion macros
00067  *****************************************************************************
00068  * These conversion routines are used by YUV conversion functions.
00069  * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
00070  * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
00071  * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
00072  *****************************************************************************/
00073 #define CONVERT_Y_PIXEL( BPP )                                                \
00074     /* Only Y sample is present */                                            \
00075     p_ybase = p_yuv + *p_y++;                                                 \
00076     *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] |     \
00077         p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT)       \
00078         + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
00079 
00080 #define CONVERT_YUV_PIXEL( BPP )                                              \
00081     /* Y, U and V samples are present */                                      \
00082     i_uval =    *p_u++;                                                       \
00083     i_vval =    *p_v++;                                                       \
00084     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
00085     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
00086     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
00087     CONVERT_Y_PIXEL( BPP )                                                    \
00088 
00089 #define CONVERT_Y_PIXEL_DITHER( BPP )                                         \
00090     /* Only Y sample is present */                                            \
00091     p_ybase = p_yuv + *p_y++;                                                 \
00092     *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128+p_dither[i_real_y])>>SHIFT) + i_red] |     \
00093         p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128+p_dither[i_real_y])>>SHIFT)       \
00094         + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128+p_dither[i_real_y])>>SHIFT) + i_blue];
00095 
00096 #define CONVERT_YUV_PIXEL_DITHER( BPP )                                       \
00097     /* Y, U and V samples are present */                                      \
00098     i_uval =    *p_u++;                                                       \
00099     i_vval =    *p_v++;                                                       \
00100     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
00101     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
00102     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
00103     CONVERT_Y_PIXEL_DITHER( BPP )                                             \
00104 
00105 #define CONVERT_4YUV_PIXEL( CHROMA )                                          \
00106     *p_pic++ = p_lookup[                                                      \
00107         (((*p_y++ + dither10[i_real_y]) >> 4) << 7)                           \
00108       + ((*p_u + dither20[i_real_y]) >> 5) * 9                                \
00109       + ((*p_v + dither20[i_real_y]) >> 5) ];                                 \
00110     *p_pic++ = p_lookup[                                                      \
00111         (((*p_y++ + dither11[i_real_y]) >> 4) << 7)                           \
00112       + ((*p_u++ + dither21[i_real_y]) >> 5) * 9                              \
00113       + ((*p_v++ + dither21[i_real_y]) >> 5) ];                               \
00114     *p_pic++ = p_lookup[                                                      \
00115         (((*p_y++ + dither12[i_real_y]) >> 4) << 7)                           \
00116       + ((*p_u + dither22[i_real_y]) >> 5) * 9                                \
00117       + ((*p_v + dither22[i_real_y]) >> 5) ];                                 \
00118     *p_pic++ = p_lookup[                                                      \
00119         (((*p_y++ + dither13[i_real_y]) >> 4) << 7)                           \
00120       + ((*p_u++ + dither23[i_real_y]) >> 5) * 9                              \
00121       + ((*p_v++ + dither23[i_real_y]) >> 5) ];                               \
00122 
00123 #define CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                    \
00124     *p_pic++ = p_lookup[                                                      \
00125         ( ((*p_y + dither10[i_real_y]) >> 4) << 7)                            \
00126         + ((*p_u + dither20[i_real_y]) >> 5) * 9                              \
00127         + ((*p_v + dither20[i_real_y]) >> 5) ];                               \
00128     p_y += *p_offset++;                                                       \
00129     p_u += *p_offset;                                                         \
00130     p_v += *p_offset++;                                                       \
00131     *p_pic++ = p_lookup[                                                      \
00132         ( ((*p_y + dither11[i_real_y]) >> 4) << 7)                            \
00133         + ((*p_u + dither21[i_real_y]) >> 5) * 9                              \
00134         + ((*p_v + dither21[i_real_y]) >> 5) ];                               \
00135     p_y += *p_offset++;                                                       \
00136     p_u += *p_offset;                                                         \
00137     p_v += *p_offset++;                                                       \
00138     *p_pic++ = p_lookup[                                                      \
00139         ( ((*p_y + dither12[i_real_y]) >> 4) << 7)                            \
00140         + ((*p_u + dither22[i_real_y]) >> 5) * 9                              \
00141         + ((*p_v + dither22[i_real_y]) >> 5) ];                               \
00142     p_y += *p_offset++;                                                       \
00143     p_u += *p_offset;                                                         \
00144     p_v += *p_offset++;                                                       \
00145     *p_pic++ = p_lookup[                                                      \
00146         ( ((*p_y + dither13[i_real_y]) >> 4) << 7)                            \
00147         + ((*p_u + dither23[i_real_y]) >> 5) * 9                              \
00148         + ((*p_v + dither23[i_real_y]) >> 5) ];                               \
00149     p_y += *p_offset++;                                                       \
00150     p_u += *p_offset;                                                         \
00151     p_v += *p_offset++;                                                       \
00152 
00153 /*****************************************************************************
00154  * SCALE_WIDTH: scale a line horizontally
00155  *****************************************************************************
00156  * This macro scales a line using rendering buffer and offset array. It works
00157  * for 1, 2 and 4 Bpp.
00158  *****************************************************************************/
00159 #define SCALE_WIDTH                                                           \
00160     if( b_hscale )                                                            \
00161     {                                                                         \
00162         /* Horizontal scaling, conversion has been done to buffer.            \
00163          * Rewind buffer and offset, then copy and scale line */              \
00164         p_buffer = p_buffer_start;                                            \
00165         p_offset = p_offset_start;                                            \
00166         for( i_x = p_vout->output.i_width / 16; i_x--; )                      \
00167         {                                                                     \
00168             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00169             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00170             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00171             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00172             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00173             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00174             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00175             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00176             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00177             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00178             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00179             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00180             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00181             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00182             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00183             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00184         }                                                                     \
00185         for( i_x = p_vout->output.i_width & 15; i_x--; )                      \
00186         {                                                                     \
00187             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
00188         }                                                                     \
00189         p_pic = (void*)((uint8_t*)p_pic + i_right_margin );                   \
00190     }                                                                         \
00191     else                                                                      \
00192     {                                                                         \
00193         /* No scaling, conversion has been done directly in picture memory.   \
00194          * Increment of picture pointer to end of line is still needed */     \
00195         p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch );               \
00196     }                                                                         \
00197 
00198 /*****************************************************************************
00199  * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
00200  *****************************************************************************
00201  * This macro scales a line using an offset array.
00202  *****************************************************************************/
00203 #define SCALE_WIDTH_DITHER( CHROMA )                                          \
00204     if( b_hscale )                                                            \
00205     {                                                                         \
00206         /* Horizontal scaling - we can't use a buffer due to dithering */     \
00207         p_offset = p_offset_start;                                            \
00208         for( i_x = p_vout->output.i_width / 16; i_x--; )                      \
00209         {                                                                     \
00210             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
00211             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
00212             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
00213             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
00214         }                                                                     \
00215     }                                                                         \
00216     else                                                                      \
00217     {                                                                         \
00218         for( i_x = p_vout->render.i_width / 16; i_x--;  )                     \
00219         {                                                                     \
00220             CONVERT_4YUV_PIXEL( CHROMA )                                      \
00221             CONVERT_4YUV_PIXEL( CHROMA )                                      \
00222             CONVERT_4YUV_PIXEL( CHROMA )                                      \
00223             CONVERT_4YUV_PIXEL( CHROMA )                                      \
00224         }                                                                     \
00225     }                                                                         \
00226     /* Increment of picture pointer to end of line is still needed */         \
00227     p_pic = (void*)((uint8_t*)p_pic + i_right_margin );                       \
00228                                                                               \
00229     /* Increment the Y coordinate in the matrix, modulo 4 */                  \
00230     i_real_y = (i_real_y + 1) & 0x3;                                          \
00231 
00232 /*****************************************************************************
00233  * SCALE_HEIGHT: handle vertical scaling
00234  *****************************************************************************
00235  * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
00236  * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
00237  * and 4 Bpp.
00238  *****************************************************************************/
00239 #define SCALE_HEIGHT( CHROMA, BPP )                                           \
00240     /* If line is odd, rewind 4:2:0 U and V samples */                        \
00241     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
00242     {                                                                         \
00243         p_u -= i_chroma_width;                                                \
00244         p_v -= i_chroma_width;                                                \
00245     }                                                                         \
00246                                                                               \
00247     /*                                                                        \
00248      * Handle vertical scaling. The current line can be copied or next one    \
00249      * can be ignored.                                                        \
00250      */                                                                       \
00251     switch( i_vscale )                                                        \
00252     {                                                                         \
00253     case -1:                             /* vertical scaling factor is < 1 */ \
00254         while( (i_scale_count -= p_vout->output.i_height) > 0 )               \
00255         {                                                                     \
00256             /* Height reduction: skip next source line */                     \
00257             p_y += p_vout->render.i_width;                                    \
00258             i_y++;                                                            \
00259             if( (CHROMA == 420) || (CHROMA == 422) )                          \
00260             {                                                                 \
00261                 if( i_y & 0x1 )                                               \
00262                 {                                                             \
00263                     p_u += i_chroma_width;                                    \
00264                     p_v += i_chroma_width;                                    \
00265                 }                                                             \
00266             }                                                                 \
00267             else if( CHROMA == 444 )                                          \
00268             {                                                                 \
00269                 p_u += p_vout->render.i_width;                                \
00270                 p_v += p_vout->render.i_width;                                \
00271             }                                                                 \
00272         }                                                                     \
00273         i_scale_count += p_vout->render.i_height;                             \
00274         break;                                                                \
00275     case 1:                              /* vertical scaling factor is > 1 */ \
00276         while( (i_scale_count -= p_vout->render.i_height) > 0 )               \
00277         {                                                                     \
00278             /* Height increment: copy previous picture line */                \
00279             p_vout->p_vlc->pf_memcpy( p_pic, p_pic_start,                     \
00280                                       p_vout->output.i_width * BPP );         \
00281             p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch );           \
00282         }                                                                     \
00283         i_scale_count += p_vout->output.i_height;                             \
00284         break;                                                                \
00285     }                                                                         \
00286 
00287 /*****************************************************************************
00288  * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
00289  *****************************************************************************
00290  * This macro handles vertical scaling for a picture. CHROMA may be 420,
00291  * 422 or 444 for RGB conversion, or 400 for gray conversion.
00292  *****************************************************************************/
00293 #define SCALE_HEIGHT_DITHER( CHROMA )                                         \
00294                                                                               \
00295     /* If line is odd, rewind 4:2:0 U and V samples */                        \
00296     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
00297     {                                                                         \
00298         p_u -= i_chroma_width;                                                \
00299         p_v -= i_chroma_width;                                                \
00300     }                                                                         \
00301                                                                               \
00302     /*                                                                        \
00303      * Handle vertical scaling. The current line can be copied or next one    \
00304      * can be ignored.                                                        \
00305      */                                                                       \
00306                                                                               \
00307     switch( i_vscale )                                                        \
00308     {                                                                         \
00309     case -1:                             /* vertical scaling factor is < 1 */ \
00310         while( (i_scale_count -= p_vout->output.i_height) > 0 )               \
00311         {                                                                     \
00312             /* Height reduction: skip next source line */                     \
00313             p_y += p_vout->render.i_width;                                    \
00314             i_y++;                                                            \
00315             if( (CHROMA == 420) || (CHROMA == 422) )                          \
00316             {                                                                 \
00317                 if( i_y & 0x1 )                                               \
00318                 {                                                             \
00319                     p_u += i_chroma_width;                                    \
00320                     p_v += i_chroma_width;                                    \
00321                 }                                                             \
00322             }                                                                 \
00323             else if( CHROMA == 444 )                                          \
00324             {                                                                 \
00325                 p_u += p_vout->render.i_width;                                \
00326                 p_v += p_vout->render.i_width;                                \
00327             }                                                                 \
00328         }                                                                     \
00329         i_scale_count += p_vout->render.i_height;                             \
00330         break;                                                                \
00331     case 1:                              /* vertical scaling factor is > 1 */ \
00332         while( (i_scale_count -= p_vout->render.i_height) > 0 )               \
00333         {                                                                     \
00334             p_y -= p_vout->render.i_width;                                    \
00335             p_u -= i_chroma_width;                                            \
00336             p_v -= i_chroma_width;                                            \
00337             SCALE_WIDTH_DITHER( CHROMA );                                     \
00338         }                                                                     \
00339         i_scale_count += p_vout->output.i_height;                             \
00340         break;                                                                \
00341     }                                                                         \
00342 

Generated on Tue Dec 20 10:14:50 2005 for vlc-0.8.4a by  doxygen 1.4.2