i422_yuy2.c 18.2 KB
Newer Older
1
/*****************************************************************************
2
 * i422_yuy2.c : Planar YUV 4:2:2 to Packed YUV conversion module for vlc
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2000, 2001 VLC authors and VideoLAN
5
 * $Id$
6 7
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
8
 *          Damien Fouilleul <damienf@videolan.org>
9
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
10 11 12
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
13
 * (at your option) any later version.
14
 *
15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
20 21 22
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27 28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

29 30 31 32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

33
#include <vlc_common.h>
34
#include <vlc_plugin.h>
35
#include <vlc_filter.h>
36
#include <vlc_picture.h>
37
#include <vlc_cpu.h>
38 39 40 41 42

#include "i422_yuy2.h"

#define SRC_FOURCC  "I422"
#if defined (MODULE_NAME_IS_i422_yuy2)
43
#    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,Y211"
44
#else
45
#    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV"
46 47 48 49 50 51 52
#endif

/*****************************************************************************
 * Local and extern prototypes.
 *****************************************************************************/
static int  Activate ( vlc_object_t * );

53 54 55 56 57 58 59 60
static void I422_YUY2               ( filter_t *, picture_t *, picture_t * );
static void I422_YVYU               ( filter_t *, picture_t *, picture_t * );
static void I422_UYVY               ( filter_t *, picture_t *, picture_t * );
static void I422_IUYV               ( filter_t *, picture_t *, picture_t * );
static picture_t *I422_YUY2_Filter  ( filter_t *, picture_t * );
static picture_t *I422_YVYU_Filter  ( filter_t *, picture_t * );
static picture_t *I422_UYVY_Filter  ( filter_t *, picture_t * );
static picture_t *I422_IUYV_Filter  ( filter_t *, picture_t * );
61
#if defined (MODULE_NAME_IS_i422_yuy2)
62 63
static void I422_Y211               ( filter_t *, picture_t *, picture_t * );
static picture_t *I422_Y211_Filter  ( filter_t *, picture_t * );
64 65 66 67 68
#endif

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
69
vlc_module_begin ()
70
#if defined (MODULE_NAME_IS_i422_yuy2)
71
    set_description( N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) )
72
    set_capability( "video converter", 80 )
73
# define vlc_CPU_capable() (true)
74
# define VLC_TARGET
75
#elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
76
    set_description( N_("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) )
77
    set_capability( "video converter", 100 )
78
# define vlc_CPU_capable() vlc_CPU_MMX()
79
# define VLC_TARGET VLC_MMX
80
#elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
81
    set_description( N_("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) )
82
    set_capability( "video converter", 120 )
83
# define vlc_CPU_capable() vlc_CPU_SSE2()
84
# define VLC_TARGET VLC_SSE
85
#endif
86 87
    set_callbacks( Activate, NULL )
vlc_module_end ()
88 89 90 91 92 93 94 95

/*****************************************************************************
 * Activate: allocate a chroma function
 *****************************************************************************
 * This function allocates and initializes a chroma function
 *****************************************************************************/
static int Activate( vlc_object_t *p_this )
{
96
    filter_t *p_filter = (filter_t *)p_this;
97

98
    if( !vlc_CPU_capable() )
99
        return VLC_EGENERIC;
100 101
    if( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) & 1
     || (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) & 1 )
102 103 104 105
    {
        return -1;
    }

106 107 108 109 110
    if( p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
    {
        return VLC_EGENERIC;
    }

111
    switch( p_filter->fmt_in.video.i_chroma )
112
    {
113
        case VLC_CODEC_I422:
114
            switch( p_filter->fmt_out.video.i_chroma )
115
            {
116
                case VLC_CODEC_YUYV:
117
                    p_filter->pf_video_filter = I422_YUY2_Filter;
118 119
                    break;

120
                case VLC_CODEC_YVYU:
121
                    p_filter->pf_video_filter = I422_YVYU_Filter;
122 123
                    break;

124
                case VLC_CODEC_UYVY:
125
                    p_filter->pf_video_filter = I422_UYVY_Filter;
126 127
                    break;

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
128
                case VLC_FOURCC('I','U','Y','V'):
129
                    p_filter->pf_video_filter = I422_IUYV_Filter;
130 131 132
                    break;

#if defined (MODULE_NAME_IS_i422_yuy2)
133
                case VLC_CODEC_Y211:
134
                    p_filter->pf_video_filter = I422_Y211_Filter;
135 136 137 138 139 140 141 142 143 144 145
                    break;
#endif

                default:
                    return -1;
            }
            break;

        default:
            return -1;
    }
Jean-Paul Saman's avatar
Jean-Paul Saman committed
146
    return 0;
147 148 149 150
}

/* Following functions are local */

151 152 153 154 155 156 157 158
VIDEO_FILTER_WRAPPER( I422_YUY2 )
VIDEO_FILTER_WRAPPER( I422_YVYU )
VIDEO_FILTER_WRAPPER( I422_UYVY )
VIDEO_FILTER_WRAPPER( I422_IUYV )
#if defined (MODULE_NAME_IS_i422_yuy2)
VIDEO_FILTER_WRAPPER( I422_Y211 )
#endif

159 160 161
/*****************************************************************************
 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
 *****************************************************************************/
162
VLC_TARGET
163 164
static void I422_YUY2( filter_t *p_filter, picture_t *p_source,
                                           picture_t *p_dest )
165
{
166
    uint8_t *p_line = p_dest->p->p_pixels;
167 168 169
    uint8_t *p_y = p_source->Y_PIXELS;
    uint8_t *p_u = p_source->U_PIXELS;
    uint8_t *p_v = p_source->V_PIXELS;
170 171 172

    int i_x, i_y;

173
    const int i_source_margin = p_source->p[0].i_pitch
174 175
                                 - p_source->p[0].i_visible_pitch
                                 - p_filter->fmt_in.video.i_x_offset;
176
    const int i_source_margin_c = p_source->p[1].i_pitch
177 178
                                 - p_source->p[1].i_visible_pitch
                                 - ( p_filter->fmt_in.video.i_x_offset );
179
    const int i_dest_margin = p_dest->p->i_pitch
180 181
                               - p_dest->p->i_visible_pitch
                               - ( p_filter->fmt_out.video.i_x_offset * 2 );
182 183 184 185

#if defined (MODULE_NAME_IS_i422_yuy2_sse2)

    if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
186
        ((intptr_t)p_line|(intptr_t)p_y))) )
187 188
    {
        /* use faster SSE2 aligned fetch and store */
189
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
190
        {
191
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
192 193 194
            {
                SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
            }
195
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
196 197 198 199 200 201 202 203 204 205 206
            {
                C_YUV422_YUYV( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    else {
        /* use slower SSE2 unaligned fetch and store */
207
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
208
        {
209
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
210 211 212
            {
                SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
            }
213
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
214 215 216 217 218 219 220 221 222 223 224 225 226
            {
                C_YUV422_YUYV( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    SSE2_END;

#else

227
    for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
228
    {
229
        for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
230 231 232 233 234 235
        {
#if defined (MODULE_NAME_IS_i422_yuy2)
            C_YUV422_YUYV( p_line, p_y, p_u, p_v );
            C_YUV422_YUYV( p_line, p_y, p_u, p_v );
            C_YUV422_YUYV( p_line, p_y, p_u, p_v );
            C_YUV422_YUYV( p_line, p_y, p_u, p_v );
236 237
#elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
            MMX_CALL( MMX_YUV422_YUYV );
238 239
#endif
        }
240
        for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 8 ) / 2; i_x-- ; )
241 242 243 244 245 246 247
        {
            C_YUV422_YUYV( p_line, p_y, p_u, p_v );
        }
        p_y += i_source_margin;
        p_u += i_source_margin_c;
        p_v += i_source_margin_c;
        p_line += i_dest_margin;
248
    }
249 250
#if defined (MODULE_NAME_IS_i422_yuy2_mmx)
    MMX_END;
251 252
#endif

253
#endif
254 255 256 257 258
}

/*****************************************************************************
 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
 *****************************************************************************/
259
VLC_TARGET
260 261
static void I422_YVYU( filter_t *p_filter, picture_t *p_source,
                                           picture_t *p_dest )
262
{
263
    uint8_t *p_line = p_dest->p->p_pixels;
264 265 266
    uint8_t *p_y = p_source->Y_PIXELS;
    uint8_t *p_u = p_source->U_PIXELS;
    uint8_t *p_v = p_source->V_PIXELS;
267 268 269

    int i_x, i_y;

270
    const int i_source_margin = p_source->p[0].i_pitch
271 272
                                 - p_source->p[0].i_visible_pitch
                                 - p_filter->fmt_in.video.i_x_offset;
273
    const int i_source_margin_c = p_source->p[1].i_pitch
274 275
                                 - p_source->p[1].i_visible_pitch
                                 - ( p_filter->fmt_in.video.i_x_offset );
276
    const int i_dest_margin = p_dest->p->i_pitch
277 278
                               - p_dest->p->i_visible_pitch
                               - ( p_filter->fmt_out.video.i_x_offset * 2 );
279 280 281 282

#if defined (MODULE_NAME_IS_i422_yuy2_sse2)

    if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
283
        ((intptr_t)p_line|(intptr_t)p_y))) )
284 285
    {
        /* use faster SSE2 aligned fetch and store */
286
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
287
        {
288
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
289 290 291
            {
                SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
            }
292
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
293 294 295 296 297 298 299 300 301 302 303
            {
                C_YUV422_YVYU( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    else {
        /* use slower SSE2 unaligned fetch and store */
304
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
305
        {
306
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
307 308 309
            {
                SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
            }
310
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
311 312 313 314 315 316 317 318 319 320 321 322 323
            {
                C_YUV422_YVYU( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    SSE2_END;

#else

324
    for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
325
    {
326
        for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
327 328 329 330 331 332
        {
#if defined (MODULE_NAME_IS_i422_yuy2)
            C_YUV422_YVYU( p_line, p_y, p_u, p_v );
            C_YUV422_YVYU( p_line, p_y, p_u, p_v );
            C_YUV422_YVYU( p_line, p_y, p_u, p_v );
            C_YUV422_YVYU( p_line, p_y, p_u, p_v );
333 334
#elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
            MMX_CALL( MMX_YUV422_YVYU );
335 336
#endif
        }
337
        for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 8 ) / 2; i_x-- ; )
338 339 340 341 342 343 344
        {
            C_YUV422_YVYU( p_line, p_y, p_u, p_v );
        }
        p_y += i_source_margin;
        p_u += i_source_margin_c;
        p_v += i_source_margin_c;
        p_line += i_dest_margin;
345
    }
346 347
#if defined (MODULE_NAME_IS_i422_yuy2_mmx)
    MMX_END;
348 349
#endif

350
#endif
351 352 353 354 355
}

/*****************************************************************************
 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
 *****************************************************************************/
356
VLC_TARGET
357 358
static void I422_UYVY( filter_t *p_filter, picture_t *p_source,
                                           picture_t *p_dest )
359
{
360
    uint8_t *p_line = p_dest->p->p_pixels;
361 362 363
    uint8_t *p_y = p_source->Y_PIXELS;
    uint8_t *p_u = p_source->U_PIXELS;
    uint8_t *p_v = p_source->V_PIXELS;
364 365 366

    int i_x, i_y;

367
    const int i_source_margin = p_source->p[0].i_pitch
368 369
                                 - p_source->p[0].i_visible_pitch
                                 - p_filter->fmt_in.video.i_x_offset;
370
    const int i_source_margin_c = p_source->p[1].i_pitch
371 372
                                 - p_source->p[1].i_visible_pitch
                                 - ( p_filter->fmt_in.video.i_x_offset );
373
    const int i_dest_margin = p_dest->p->i_pitch
374 375
                               - p_dest->p->i_visible_pitch
                               - ( p_filter->fmt_out.video.i_x_offset * 2 );
376 377 378 379

#if defined (MODULE_NAME_IS_i422_yuy2_sse2)

    if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
380
        ((intptr_t)p_line|(intptr_t)p_y))) )
381 382
    {
        /* use faster SSE2 aligned fetch and store */
383
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
384
        {
385
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
386 387 388
            {
                SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
            }
389
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
390 391 392 393 394 395 396 397 398 399 400
            {
                C_YUV422_UYVY( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    else {
        /* use slower SSE2 unaligned fetch and store */
401
        for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
402
        {
403
            for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
404 405 406
            {
                SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
            }
407
            for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
408 409 410 411 412 413 414 415 416 417 418 419 420
            {
                C_YUV422_UYVY( p_line, p_y, p_u, p_v );
            }
            p_y += i_source_margin;
            p_u += i_source_margin_c;
            p_v += i_source_margin_c;
            p_line += i_dest_margin;
        }
    }
    SSE2_END;

#else

421
    for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
422
    {
423
        for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
424 425 426 427 428 429
        {
#if defined (MODULE_NAME_IS_i422_yuy2)
            C_YUV422_UYVY( p_line, p_y, p_u, p_v );
            C_YUV422_UYVY( p_line, p_y, p_u, p_v );
            C_YUV422_UYVY( p_line, p_y, p_u, p_v );
            C_YUV422_UYVY( p_line, p_y, p_u, p_v );
430 431
#elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
            MMX_CALL( MMX_YUV422_UYVY );
432 433
#endif
        }
434
        for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 8 ) / 2; i_x-- ; )
435 436 437 438 439 440 441
        {
            C_YUV422_UYVY( p_line, p_y, p_u, p_v );
        }
        p_y += i_source_margin;
        p_u += i_source_margin_c;
        p_v += i_source_margin_c;
        p_line += i_dest_margin;
442
    }
443 444
#if defined (MODULE_NAME_IS_i422_yuy2_mmx)
    MMX_END;
445 446
#endif

447
#endif
448 449 450 451 452
}

/*****************************************************************************
 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
 *****************************************************************************/
453 454
static void I422_IUYV( filter_t *p_filter, picture_t *p_source,
                                           picture_t *p_dest )
455
{
Rafaël Carré's avatar
Rafaël Carré committed
456
    VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
457
    /* FIXME: TODO ! */
458
    msg_Err( p_filter, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
459 460 461 462 463 464
}

/*****************************************************************************
 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
 *****************************************************************************/
#if defined (MODULE_NAME_IS_i422_yuy2)
465 466
static void I422_Y211( filter_t *p_filter, picture_t *p_source,
                                           picture_t *p_dest )
467
{
468
    uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
469 470 471
    uint8_t *p_y = p_source->Y_PIXELS;
    uint8_t *p_u = p_source->U_PIXELS;
    uint8_t *p_v = p_source->V_PIXELS;
472 473 474

    int i_x, i_y;

475
    for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
476
    {
477
        for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
478 479 480 481 482 483 484
        {
            C_YUV422_Y211( p_line, p_y, p_u, p_v );
            C_YUV422_Y211( p_line, p_y, p_u, p_v );
        }
    }
}
#endif