~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to modules/video_chroma/i420_rgb.h

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * i420_rgb.h : YUV to bitmap RGB conversion module for vlc
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2000, 2004 VideoLAN
 
5
 * $Id: i420_rgb.h 7194 2004-03-29 19:57:07Z fenrir $
 
6
 *
 
7
 * Authors: Samuel Hocevar <sam@zoy.org>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 * 
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
22
 *****************************************************************************/
 
23
 
 
24
/** Number of entries in RGB palette/colormap */
 
25
#define CMAP_RGB2_SIZE 256
 
26
 
 
27
/**
 
28
 * chroma_sys_t: chroma method descriptor
 
29
 
 
30
 * This structure is part of the chroma transformation descriptor, it
 
31
 * describes the yuv2rgb specific properties.
 
32
 */
 
33
struct chroma_sys_t
 
34
{
 
35
    uint8_t  *p_buffer;
 
36
    int *p_offset;
 
37
 
 
38
#ifdef MODULE_NAME_IS_i420_rgb
 
39
    /**< Pre-calculated conversion tables */
 
40
    void *p_base;                      /**< base for all conversion tables */
 
41
    uint8_t   *p_rgb8;                 /**< RGB 8 bits table */
 
42
    uint16_t  *p_rgb16;                /**< RGB 16 bits table */
 
43
    uint32_t  *p_rgb32;                /**< RGB 32 bits table */
 
44
 
 
45
    /**< To get RGB value for palette entry i, use (p_rgb_r[i], p_rgb_g[i],
 
46
       p_rgb_b[i]). Note these are 16 bits per pixel. For 8bpp entries,
 
47
       shift right 8 bits.
 
48
    */
 
49
    uint16_t  p_rgb_r[CMAP_RGB2_SIZE];  /**< Red values of palette */
 
50
    uint16_t  p_rgb_g[CMAP_RGB2_SIZE];  /**< Green values of palette */
 
51
    uint16_t  p_rgb_b[CMAP_RGB2_SIZE];  /**< Blue values of palette */
 
52
#endif
 
53
};
 
54
 
 
55
/*****************************************************************************
 
56
 * Prototypes
 
57
 *****************************************************************************/
 
58
#ifdef MODULE_NAME_IS_i420_rgb
 
59
void E_(I420_RGB8)         ( vout_thread_t *, picture_t *, picture_t * );
 
60
void E_(I420_RGB16_dither) ( vout_thread_t *, picture_t *, picture_t * );
 
61
#endif
 
62
void E_(I420_RGB16)        ( vout_thread_t *, picture_t *, picture_t * );
 
63
void E_(I420_RGB32)        ( vout_thread_t *, picture_t *, picture_t * );
 
64
 
 
65
/*****************************************************************************
 
66
 * CONVERT_*_PIXEL: pixel conversion macros
 
67
 *****************************************************************************
 
68
 * These conversion routines are used by YUV conversion functions.
 
69
 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
 
70
 * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
 
71
 * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
 
72
 *****************************************************************************/
 
73
#define CONVERT_Y_PIXEL( BPP )                                                \
 
74
    /* Only Y sample is present */                                            \
 
75
    p_ybase = p_yuv + *p_y++;                                                 \
 
76
    *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] |     \
 
77
        p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT)       \
 
78
        + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
 
79
 
 
80
#define CONVERT_YUV_PIXEL( BPP )                                              \
 
81
    /* Y, U and V samples are present */                                      \
 
82
    i_uval =    *p_u++;                                                       \
 
83
    i_vval =    *p_v++;                                                       \
 
84
    i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
 
85
    i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
 
86
    i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
 
87
    CONVERT_Y_PIXEL( BPP )                                                    \
 
88
 
 
89
#define CONVERT_Y_PIXEL_DITHER( BPP )                                         \
 
90
    /* Only Y sample is present */                                            \
 
91
    p_ybase = p_yuv + *p_y++;                                                 \
 
92
    *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128+p_dither[i_real_y])>>SHIFT) + i_red] |     \
 
93
        p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128+p_dither[i_real_y])>>SHIFT)       \
 
94
        + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128+p_dither[i_real_y])>>SHIFT) + i_blue];
 
95
 
 
96
#define CONVERT_YUV_PIXEL_DITHER( BPP )                                       \
 
97
    /* Y, U and V samples are present */                                      \
 
98
    i_uval =    *p_u++;                                                       \
 
99
    i_vval =    *p_v++;                                                       \
 
100
    i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
 
101
    i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
 
102
    i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
 
103
    CONVERT_Y_PIXEL_DITHER( BPP )                                             \
 
104
 
 
105
#define CONVERT_4YUV_PIXEL( CHROMA )                                          \
 
106
    *p_pic++ = p_lookup[                                                      \
 
107
        (((*p_y++ + dither10[i_real_y]) >> 4) << 7)                           \
 
108
      + ((*p_u + dither20[i_real_y]) >> 5) * 9                                \
 
109
      + ((*p_v + dither20[i_real_y]) >> 5) ];                                 \
 
110
    *p_pic++ = p_lookup[                                                      \
 
111
        (((*p_y++ + dither11[i_real_y]) >> 4) << 7)                           \
 
112
      + ((*p_u++ + dither21[i_real_y]) >> 5) * 9                              \
 
113
      + ((*p_v++ + dither21[i_real_y]) >> 5) ];                               \
 
114
    *p_pic++ = p_lookup[                                                      \
 
115
        (((*p_y++ + dither12[i_real_y]) >> 4) << 7)                           \
 
116
      + ((*p_u + dither22[i_real_y]) >> 5) * 9                                \
 
117
      + ((*p_v + dither22[i_real_y]) >> 5) ];                                 \
 
118
    *p_pic++ = p_lookup[                                                      \
 
119
        (((*p_y++ + dither13[i_real_y]) >> 4) << 7)                           \
 
120
      + ((*p_u++ + dither23[i_real_y]) >> 5) * 9                              \
 
121
      + ((*p_v++ + dither23[i_real_y]) >> 5) ];                               \
 
122
 
 
123
#define CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                    \
 
124
    *p_pic++ = p_lookup[                                                      \
 
125
        ( ((*p_y + dither10[i_real_y]) >> 4) << 7)                            \
 
126
        + ((*p_u + dither20[i_real_y]) >> 5) * 9                              \
 
127
        + ((*p_v + dither20[i_real_y]) >> 5) ];                               \
 
128
    p_y += *p_offset++;                                                       \
 
129
    p_u += *p_offset;                                                         \
 
130
    p_v += *p_offset++;                                                       \
 
131
    *p_pic++ = p_lookup[                                                      \
 
132
        ( ((*p_y + dither11[i_real_y]) >> 4) << 7)                            \
 
133
        + ((*p_u + dither21[i_real_y]) >> 5) * 9                              \
 
134
        + ((*p_v + dither21[i_real_y]) >> 5) ];                               \
 
135
    p_y += *p_offset++;                                                       \
 
136
    p_u += *p_offset;                                                         \
 
137
    p_v += *p_offset++;                                                       \
 
138
    *p_pic++ = p_lookup[                                                      \
 
139
        ( ((*p_y + dither12[i_real_y]) >> 4) << 7)                            \
 
140
        + ((*p_u + dither22[i_real_y]) >> 5) * 9                              \
 
141
        + ((*p_v + dither22[i_real_y]) >> 5) ];                               \
 
142
    p_y += *p_offset++;                                                       \
 
143
    p_u += *p_offset;                                                         \
 
144
    p_v += *p_offset++;                                                       \
 
145
    *p_pic++ = p_lookup[                                                      \
 
146
        ( ((*p_y + dither13[i_real_y]) >> 4) << 7)                            \
 
147
        + ((*p_u + dither23[i_real_y]) >> 5) * 9                              \
 
148
        + ((*p_v + dither23[i_real_y]) >> 5) ];                               \
 
149
    p_y += *p_offset++;                                                       \
 
150
    p_u += *p_offset;                                                         \
 
151
    p_v += *p_offset++;                                                       \
 
152
 
 
153
/*****************************************************************************
 
154
 * SCALE_WIDTH: scale a line horizontally
 
155
 *****************************************************************************
 
156
 * This macro scales a line using rendering buffer and offset array. It works
 
157
 * for 1, 2 and 4 Bpp.
 
158
 *****************************************************************************/
 
159
#define SCALE_WIDTH                                                           \
 
160
    if( b_hscale )                                                            \
 
161
    {                                                                         \
 
162
        /* Horizontal scaling, conversion has been done to buffer.            \
 
163
         * Rewind buffer and offset, then copy and scale line */              \
 
164
        p_buffer = p_buffer_start;                                            \
 
165
        p_offset = p_offset_start;                                            \
 
166
        for( i_x = p_vout->output.i_width / 16; i_x--; )                      \
 
167
        {                                                                     \
 
168
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
169
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
170
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
171
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
172
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
173
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
174
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
175
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
176
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
177
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
178
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
179
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
180
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
181
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
182
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
183
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
184
        }                                                                     \
 
185
        for( i_x = p_vout->output.i_width & 15; i_x--; )                      \
 
186
        {                                                                     \
 
187
            *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
 
188
        }                                                                     \
 
189
        p_pic = (void*)((uint8_t*)p_pic + i_right_margin );                   \
 
190
    }                                                                         \
 
191
    else                                                                      \
 
192
    {                                                                         \
 
193
        /* No scaling, conversion has been done directly in picture memory.   \
 
194
         * Increment of picture pointer to end of line is still needed */     \
 
195
        p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch );               \
 
196
    }                                                                         \
 
197
 
 
198
/*****************************************************************************
 
199
 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
 
200
 *****************************************************************************
 
201
 * This macro scales a line using an offset array.
 
202
 *****************************************************************************/
 
203
#define SCALE_WIDTH_DITHER( CHROMA )                                          \
 
204
    if( b_hscale )                                                            \
 
205
    {                                                                         \
 
206
        /* Horizontal scaling - we can't use a buffer due to dithering */     \
 
207
        p_offset = p_offset_start;                                            \
 
208
        for( i_x = p_vout->output.i_width / 16; i_x--; )                      \
 
209
        {                                                                     \
 
210
            CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
 
211
            CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
 
212
            CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
 
213
            CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
 
214
        }                                                                     \
 
215
    }                                                                         \
 
216
    else                                                                      \
 
217
    {                                                                         \
 
218
        for( i_x = p_vout->render.i_width / 16; i_x--;  )                     \
 
219
        {                                                                     \
 
220
            CONVERT_4YUV_PIXEL( CHROMA )                                      \
 
221
            CONVERT_4YUV_PIXEL( CHROMA )                                      \
 
222
            CONVERT_4YUV_PIXEL( CHROMA )                                      \
 
223
            CONVERT_4YUV_PIXEL( CHROMA )                                      \
 
224
        }                                                                     \
 
225
    }                                                                         \
 
226
    /* Increment of picture pointer to end of line is still needed */         \
 
227
    p_pic = (void*)((uint8_t*)p_pic + i_right_margin );                       \
 
228
                                                                              \
 
229
    /* Increment the Y coordinate in the matrix, modulo 4 */                  \
 
230
    i_real_y = (i_real_y + 1) & 0x3;                                          \
 
231
 
 
232
/*****************************************************************************
 
233
 * SCALE_HEIGHT: handle vertical scaling
 
234
 *****************************************************************************
 
235
 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
 
236
 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
 
237
 * and 4 Bpp.
 
238
 *****************************************************************************/
 
239
#define SCALE_HEIGHT( CHROMA, BPP )                                           \
 
240
    /* If line is odd, rewind 4:2:0 U and V samples */                        \
 
241
    if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
 
242
    {                                                                         \
 
243
        p_u -= i_chroma_width;                                                \
 
244
        p_v -= i_chroma_width;                                                \
 
245
    }                                                                         \
 
246
                                                                              \
 
247
    /*                                                                        \
 
248
     * Handle vertical scaling. The current line can be copied or next one    \
 
249
     * can be ignored.                                                        \
 
250
     */                                                                       \
 
251
    switch( i_vscale )                                                        \
 
252
    {                                                                         \
 
253
    case -1:                             /* vertical scaling factor is < 1 */ \
 
254
        while( (i_scale_count -= p_vout->output.i_height) > 0 )               \
 
255
        {                                                                     \
 
256
            /* Height reduction: skip next source line */                     \
 
257
            p_y += p_vout->render.i_width;                                    \
 
258
            i_y++;                                                            \
 
259
            if( (CHROMA == 420) || (CHROMA == 422) )                          \
 
260
            {                                                                 \
 
261
                if( i_y & 0x1 )                                               \
 
262
                {                                                             \
 
263
                    p_u += i_chroma_width;                                    \
 
264
                    p_v += i_chroma_width;                                    \
 
265
                }                                                             \
 
266
            }                                                                 \
 
267
            else if( CHROMA == 444 )                                          \
 
268
            {                                                                 \
 
269
                p_u += p_vout->render.i_width;                                \
 
270
                p_v += p_vout->render.i_width;                                \
 
271
            }                                                                 \
 
272
        }                                                                     \
 
273
        i_scale_count += p_vout->render.i_height;                             \
 
274
        break;                                                                \
 
275
    case 1:                              /* vertical scaling factor is > 1 */ \
 
276
        while( (i_scale_count -= p_vout->render.i_height) > 0 )               \
 
277
        {                                                                     \
 
278
            /* Height increment: copy previous picture line */                \
 
279
            p_vout->p_vlc->pf_memcpy( p_pic, p_pic_start,                     \
 
280
                                      p_vout->output.i_width * BPP );         \
 
281
            p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch );           \
 
282
        }                                                                     \
 
283
        i_scale_count += p_vout->output.i_height;                             \
 
284
        break;                                                                \
 
285
    }                                                                         \
 
286
 
 
287
/*****************************************************************************
 
288
 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
 
289
 *****************************************************************************
 
290
 * This macro handles vertical scaling for a picture. CHROMA may be 420,
 
291
 * 422 or 444 for RGB conversion, or 400 for gray conversion.
 
292
 *****************************************************************************/
 
293
#define SCALE_HEIGHT_DITHER( CHROMA )                                         \
 
294
                                                                              \
 
295
    /* If line is odd, rewind 4:2:0 U and V samples */                        \
 
296
    if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
 
297
    {                                                                         \
 
298
        p_u -= i_chroma_width;                                                \
 
299
        p_v -= i_chroma_width;                                                \
 
300
    }                                                                         \
 
301
                                                                              \
 
302
    /*                                                                        \
 
303
     * Handle vertical scaling. The current line can be copied or next one    \
 
304
     * can be ignored.                                                        \
 
305
     */                                                                       \
 
306
                                                                              \
 
307
    switch( i_vscale )                                                        \
 
308
    {                                                                         \
 
309
    case -1:                             /* vertical scaling factor is < 1 */ \
 
310
        while( (i_scale_count -= p_vout->output.i_height) > 0 )               \
 
311
        {                                                                     \
 
312
            /* Height reduction: skip next source line */                     \
 
313
            p_y += p_vout->render.i_width;                                    \
 
314
            i_y++;                                                            \
 
315
            if( (CHROMA == 420) || (CHROMA == 422) )                          \
 
316
            {                                                                 \
 
317
                if( i_y & 0x1 )                                               \
 
318
                {                                                             \
 
319
                    p_u += i_chroma_width;                                    \
 
320
                    p_v += i_chroma_width;                                    \
 
321
                }                                                             \
 
322
            }                                                                 \
 
323
            else if( CHROMA == 444 )                                          \
 
324
            {                                                                 \
 
325
                p_u += p_vout->render.i_width;                                \
 
326
                p_v += p_vout->render.i_width;                                \
 
327
            }                                                                 \
 
328
        }                                                                     \
 
329
        i_scale_count += p_vout->render.i_height;                             \
 
330
        break;                                                                \
 
331
    case 1:                              /* vertical scaling factor is > 1 */ \
 
332
        while( (i_scale_count -= p_vout->render.i_height) > 0 )               \
 
333
        {                                                                     \
 
334
            p_y -= p_vout->render.i_width;                                    \
 
335
            p_u -= i_chroma_width;                                            \
 
336
            p_v -= i_chroma_width;                                            \
 
337
            SCALE_WIDTH_DITHER( CHROMA );                                     \
 
338
        }                                                                     \
 
339
        i_scale_count += p_vout->output.i_height;                             \
 
340
        break;                                                                \
 
341
    }                                                                         \
 
342