vout_pictures.c 32.3 KB
Newer Older
Sam Hocevar's avatar
 
Sam Hocevar committed
1 2 3
/*****************************************************************************
 * vout_pictures.c : picture management functions
 *****************************************************************************
4
 * Copyright (C) 2000-2004 the VideoLAN team
5
 * $Id$
Sam Hocevar's avatar
 
Sam Hocevar committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
Sam Hocevar's avatar
 
Sam Hocevar committed
23 24 25 26 27 28
 *****************************************************************************/

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

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

33
#include <vlc/vlc.h>
zorglub's avatar
zorglub committed
34 35
#include <vlc_vout.h>
#include <vlc_osd.h>
36 37
#include "vout_pictures.h"

Rafaël Carré's avatar
Rafaël Carré committed
38 39
#include <assert.h>

40 41 42
/**
 * Display a picture
 *
gbazin's avatar
 
gbazin committed
43 44
 * Remove the reservation flag of a picture, which will cause it to be ready
 * for display. The picture won't be displayed until vout_DatePicture has been
Sam Hocevar's avatar
 
Sam Hocevar committed
45
 * called.
46
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
47
void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
48 49
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
50
    switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
51 52
    {
    case RESERVED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
53
        p_pic->i_status = RESERVED_DISP_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
54 55
        break;
    case RESERVED_DATED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
56
        p_pic->i_status = READY_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
57 58
        break;
    default:
59 60
        msg_Err( p_vout, "picture to display %p has invalid status %d",
                         p_pic, p_pic->i_status );
Sam Hocevar's avatar
 
Sam Hocevar committed
61 62 63 64 65 66
        break;
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

67 68 69
/**
 * Date a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
70 71 72
 * Remove the reservation flag of a picture, which will cause it to be ready
 * for display. The picture won't be displayed until vout_DisplayPicture has
 * been called.
73 74 75 76
 * \param p_vout The vout in question
 * \param p_pic The picture to date
 * \param date The date to display the picture
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
77
void vout_DatePicture( vout_thread_t *p_vout,
Sam Hocevar's avatar
 
Sam Hocevar committed
78
                       picture_t *p_pic, mtime_t date )
Sam Hocevar's avatar
 
Sam Hocevar committed
79 80
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
81 82
    p_pic->date = date;
    switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
83 84
    {
    case RESERVED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
85
        p_pic->i_status = RESERVED_DATED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
86 87
        break;
    case RESERVED_DISP_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
88
        p_pic->i_status = READY_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
89 90
        break;
    default:
91 92
        msg_Err( p_vout, "picture to date %p has invalid status %d",
                         p_pic, p_pic->i_status );
Sam Hocevar's avatar
 
Sam Hocevar committed
93 94 95 96 97 98
        break;
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

99 100 101
/**
 * Allocate a picture in the video output heap.
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
102 103
 * This function creates a reserved image in the video output heap.
 * A null pointer is returned if the function fails. This method provides an
gbazin's avatar
 
gbazin committed
104 105 106
 * already allocated zone of memory in the picture data fields.
 * It needs locking since several pictures can be created by several producers
 * threads.
107
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
108
picture_t *vout_CreatePicture( vout_thread_t *p_vout,
109 110
                               bool b_progressive,
                               bool b_top_field_first,
111
                               unsigned int i_nb_fields )
Sam Hocevar's avatar
 
Sam Hocevar committed
112
{
Sam Hocevar's avatar
 
Sam Hocevar committed
113 114 115
    int         i_pic;                                      /* picture index */
    picture_t * p_pic;
    picture_t * p_freepic = NULL;                      /* first free picture */
Sam Hocevar's avatar
 
Sam Hocevar committed
116 117 118 119 120

    /* Get lock */
    vlc_mutex_lock( &p_vout->picture_lock );

    /*
gbazin's avatar
 
gbazin committed
121
     * Look for an empty place in the picture heap.
Sam Hocevar's avatar
 
Sam Hocevar committed
122
     */
gbazin's avatar
 
gbazin committed
123
    for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
Sam Hocevar's avatar
 
Sam Hocevar committed
124
    {
gbazin's avatar
 
gbazin committed
125 126
        p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
                                 % I_RENDERPICTURES];
Sam Hocevar's avatar
 
Sam Hocevar committed
127

Sam Hocevar's avatar
 
Sam Hocevar committed
128
        switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
129
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
130 131 132 133
            case DESTROYED_PICTURE:
                /* Memory will not be reallocated, and function can end
                 * immediately - this is the best possible case, since no
                 * memory allocation needs to be done */
Sam Hocevar's avatar
 
Sam Hocevar committed
134 135
                p_pic->i_status   = RESERVED_PICTURE;
                p_pic->i_refcount = 0;
136
                p_pic->b_force    = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
137

Sam Hocevar's avatar
 
Sam Hocevar committed
138
                p_pic->b_progressive        = b_progressive;
139
                p_pic->i_nb_fields          = i_nb_fields;
Sam Hocevar's avatar
 
Sam Hocevar committed
140
                p_pic->b_top_field_first    = b_top_field_first;
Sam Hocevar's avatar
 
Sam Hocevar committed
141

Sam Hocevar's avatar
 
Sam Hocevar committed
142
                p_vout->i_heap_size++;
gbazin's avatar
 
gbazin committed
143 144 145
                p_vout->render.i_last_used_pic =
                    ( p_vout->render.i_last_used_pic + i_pic + 1 )
                    % I_RENDERPICTURES;
Sam Hocevar's avatar
 
Sam Hocevar committed
146
                vlc_mutex_unlock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
147
                return( p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
148

Sam Hocevar's avatar
 
Sam Hocevar committed
149
            case FREE_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
150
                /* Picture is empty and ready for allocation */
gbazin's avatar
 
gbazin committed
151 152 153
                p_vout->render.i_last_used_pic =
                    ( p_vout->render.i_last_used_pic + i_pic + 1 )
                    % I_RENDERPICTURES;
Sam Hocevar's avatar
 
Sam Hocevar committed
154
                p_freepic = p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
155 156 157 158 159
                break;

            default:
                break;
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
160 161 162 163 164
    }

    /*
     * Prepare picture
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
165
    if( p_freepic != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
166
    {
gbazin's avatar
 
gbazin committed
167 168
        vout_AllocatePicture( VLC_OBJECT(p_vout),
                              p_freepic, p_vout->render.i_chroma,
Sam Hocevar's avatar
 
Sam Hocevar committed
169
                              p_vout->render.i_width, p_vout->render.i_height,
gbazin's avatar
 
gbazin committed
170
                              p_vout->render.i_aspect );
Sam Hocevar's avatar
 
Sam Hocevar committed
171

Sam Hocevar's avatar
 
Sam Hocevar committed
172
        if( p_freepic->i_planes )
Sam Hocevar's avatar
 
Sam Hocevar committed
173 174
        {
            /* Copy picture information, set some default values */
Sam Hocevar's avatar
 
Sam Hocevar committed
175 176
            p_freepic->i_status   = RESERVED_PICTURE;
            p_freepic->i_type     = MEMORY_PICTURE;
177
            p_freepic->b_slow     = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
178

Sam Hocevar's avatar
 
Sam Hocevar committed
179
            p_freepic->i_refcount = 0;
180
            p_freepic->b_force = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
181

Sam Hocevar's avatar
 
Sam Hocevar committed
182
            p_freepic->b_progressive        = b_progressive;
183
            p_freepic->i_nb_fields          = i_nb_fields;
Sam Hocevar's avatar
 
Sam Hocevar committed
184
            p_freepic->b_top_field_first    = b_top_field_first;
Sam Hocevar's avatar
 
Sam Hocevar committed
185

Sam Hocevar's avatar
 
Sam Hocevar committed
186
            p_freepic->i_matrix_coefficients = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
187

Sam Hocevar's avatar
 
Sam Hocevar committed
188
            p_vout->i_heap_size++;
Sam Hocevar's avatar
 
Sam Hocevar committed
189 190 191 192
        }
        else
        {
            /* Memory allocation failed : set picture as empty */
Sam Hocevar's avatar
 
Sam Hocevar committed
193 194
            p_freepic->i_status = FREE_PICTURE;
            p_freepic = NULL;
Sam Hocevar's avatar
 
Sam Hocevar committed
195

196
            msg_Err( p_vout, "picture allocation failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
197 198 199 200
        }

        vlc_mutex_unlock( &p_vout->picture_lock );

Sam Hocevar's avatar
 
Sam Hocevar committed
201
        return( p_freepic );
Sam Hocevar's avatar
 
Sam Hocevar committed
202 203 204 205 206 207 208 209 210
    }

    /* No free or destroyed picture could be found, but the decoder
     * will try again in a while. */
    vlc_mutex_unlock( &p_vout->picture_lock );

    return( NULL );
}

211 212 213
/**
 * Remove a permanent or reserved picture from the heap
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
214 215 216
 * This function frees a previously reserved picture or a permanent
 * picture. It is meant to be used when the construction of a picture aborted.
 * Note that the picture will be destroyed even if it is linked !
217
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
218
void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
219 220 221
{
    vlc_mutex_lock( &p_vout->picture_lock );

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
222
#ifndef NDEBUG
Sam Hocevar's avatar
 
Sam Hocevar committed
223
    /* Check if picture status is valid */
Sam Hocevar's avatar
 
Sam Hocevar committed
224 225 226
    if( (p_pic->i_status != RESERVED_PICTURE) &&
        (p_pic->i_status != RESERVED_DATED_PICTURE) &&
        (p_pic->i_status != RESERVED_DISP_PICTURE) )
Sam Hocevar's avatar
 
Sam Hocevar committed
227
    {
228 229
        msg_Err( p_vout, "picture to destroy %p has invalid status %d",
                         p_pic, p_pic->i_status );
Sam Hocevar's avatar
 
Sam Hocevar committed
230 231 232
    }
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
233
    p_pic->i_status = DESTROYED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
234
    p_vout->i_heap_size--;
Sam Hocevar's avatar
 
Sam Hocevar committed
235 236 237 238

    vlc_mutex_unlock( &p_vout->picture_lock );
}

239 240 241
/**
 * Increment reference counter of a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
242 243
 * This function increments the reference counter of a picture in the video
 * heap. It needs a lock since several producer threads can access the picture.
244
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
245
void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
246 247
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
248
    p_pic->i_refcount++;
Sam Hocevar's avatar
 
Sam Hocevar committed
249 250 251
    vlc_mutex_unlock( &p_vout->picture_lock );
}

252 253 254
/**
 * Decrement reference counter of a picture
 *
gbazin's avatar
 
gbazin committed
255
 * This function decrement the reference counter of a picture in the video heap
256
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
257
void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
258 259
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
260
    p_pic->i_refcount--;
Sam Hocevar's avatar
 
Sam Hocevar committed
261

Sam Hocevar's avatar
 
Sam Hocevar committed
262 263
    if( ( p_pic->i_refcount == 0 ) &&
        ( p_pic->i_status == DISPLAYED_PICTURE ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
264
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
265
        p_pic->i_status = DESTROYED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
266
        p_vout->i_heap_size--;
Sam Hocevar's avatar
 
Sam Hocevar committed
267 268 269 270 271
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

272 273 274
/**
 * Render a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
275 276 277
 * This function chooses whether the current picture needs to be copied
 * before rendering, does the subpicture magic, and tells the video output
 * thread which direct buffer needs to be displayed.
278
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
279
picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
Sam Hocevar's avatar
 
Sam Hocevar committed
280 281
                                                       subpicture_t *p_subpic )
{
282 283
    int i_scale_width, i_scale_height;

Sam Hocevar's avatar
 
Sam Hocevar committed
284
    if( p_pic == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
285 286 287 288 289
    {
        /* XXX: subtitles */
        return NULL;
    }

290 291 292 293
    i_scale_width = p_vout->fmt_out.i_visible_width * 1000 /
        p_vout->fmt_in.i_visible_width;
    i_scale_height = p_vout->fmt_out.i_visible_height * 1000 /
        p_vout->fmt_in.i_visible_height;
294

Sam Hocevar's avatar
 
Sam Hocevar committed
295
    if( p_pic->i_type == DIRECT_PICTURE )
Sam Hocevar's avatar
 
Sam Hocevar committed
296
    {
297 298
        if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount ||
            p_pic->b_force )
Sam Hocevar's avatar
 
Sam Hocevar committed
299 300 301 302 303 304 305 306 307
        {
            /* Picture is in a direct buffer and is still in use,
             * we need to copy it to another direct buffer before
             * displaying it if there are subtitles. */
            if( p_subpic != NULL )
            {
                /* We have subtitles. First copy the picture to
                 * the spare direct buffer, then render the
                 * subtitles. */
308
                vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
309

310
                spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out,
311 312
                                       PP_OUTPUTPICTURE[0], p_pic, p_subpic,
                                       i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
313

Sam Hocevar's avatar
 
Sam Hocevar committed
314
                return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
 
Sam Hocevar committed
315 316 317 318 319
            }

            /* No subtitles, picture is in a directbuffer so
             * we can display it directly even if it is still
             * in use. */
Sam Hocevar's avatar
 
Sam Hocevar committed
320
            return p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
321 322 323 324 325
        }

        /* Picture is in a direct buffer but isn't used by the
         * decoder. We can safely render subtitles on it and
         * display it. */
326 327
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out, p_pic, p_pic,
                               p_subpic, i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
328

Sam Hocevar's avatar
 
Sam Hocevar committed
329
        return p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
330 331 332 333
    }

    /* Not a direct buffer. We either need to copy it to a direct buffer,
     * or render it if the chroma isn't the same. */
Sam Hocevar's avatar
 
Sam Hocevar committed
334
    if( p_vout->b_direct )
Sam Hocevar's avatar
 
Sam Hocevar committed
335 336 337 338
    {
        /* Picture is not in a direct buffer, but is exactly the
         * same size as the direct buffers. A memcpy() is enough,
         * then render the subtitles. */
gbazin's avatar
 
gbazin committed
339 340 341 342 343

        if( PP_OUTPUTPICTURE[0]->pf_lock )
            if( PP_OUTPUTPICTURE[0]->pf_lock( p_vout, PP_OUTPUTPICTURE[0] ) )
                return NULL;

344
        vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
345 346 347
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out,
                               PP_OUTPUTPICTURE[0], p_pic,
                               p_subpic, i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
348

gbazin's avatar
 
gbazin committed
349 350 351
        if( PP_OUTPUTPICTURE[0]->pf_unlock )
            PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );

Sam Hocevar's avatar
 
Sam Hocevar committed
352
        return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
 
Sam Hocevar committed
353 354 355 356
    }

    /* Picture is not in a direct buffer, and needs to be converted to
     * another size/chroma. Then the subtitles need to be rendered as
Sam Hocevar's avatar
 
Sam Hocevar committed
357
     * well. This usually means software YUV, or hardware YUV with a
Sam Hocevar's avatar
 
Sam Hocevar committed
358 359
     * different chroma. */

360 361 362 363 364 365 366 367 368
    if( p_subpic != NULL && p_vout->p_picture[0].b_slow )
    {
        /* The picture buffer is in slow memory. We'll use
         * the "2 * VOUT_MAX_PICTURES + 1" picture as a temporary
         * one for subpictures rendering. */
        picture_t *p_tmp_pic = &p_vout->p_picture[2 * VOUT_MAX_PICTURES];
        if( p_tmp_pic->i_status == FREE_PICTURE )
        {
            vout_AllocatePicture( VLC_OBJECT(p_vout),
369 370 371 372
                                  p_tmp_pic, p_vout->fmt_out.i_chroma,
                                  p_vout->fmt_out.i_width,
                                  p_vout->fmt_out.i_height,
                                  p_vout->fmt_out.i_aspect );
373 374
            p_tmp_pic->i_type = MEMORY_PICTURE;
            p_tmp_pic->i_status = RESERVED_PICTURE;
375 376
            /* some modules (such as blend)  needs to know the extra information in picture heap */
            p_tmp_pic->p_heap = &p_vout->output;
377 378 379 380
        }

        /* Convert image to the first direct buffer */
        p_vout->chroma.pf_convert( p_vout, p_pic, p_tmp_pic );
gbazin's avatar
 
gbazin committed
381

382
        /* Render subpictures on the first direct buffer */
383
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out, p_tmp_pic,
384 385
                               p_tmp_pic, p_subpic,
                               i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
386

387 388 389 390
        if( p_vout->p_picture[0].pf_lock )
            if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) )
                return NULL;

391
        vout_CopyPicture( p_vout, &p_vout->p_picture[0], p_tmp_pic );
392 393 394 395 396 397 398 399 400 401 402
    }
    else
    {
        if( p_vout->p_picture[0].pf_lock )
            if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) )
                return NULL;

        /* Convert image to the first direct buffer */
        p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] );

        /* Render subpictures on the first direct buffer */
403 404 405
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out,
                               &p_vout->p_picture[0], &p_vout->p_picture[0],
                               p_subpic, i_scale_width, i_scale_height );
406
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
407

gbazin's avatar
 
gbazin committed
408 409 410
    if( p_vout->p_picture[0].pf_unlock )
        p_vout->p_picture[0].pf_unlock( p_vout, &p_vout->p_picture[0] );

Sam Hocevar's avatar
 
Sam Hocevar committed
411 412 413
    return &p_vout->p_picture[0];
}

414 415 416
/**
 * Calculate image window coordinates
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
417 418
 * This function will be accessed by plugins. It calculates the relative
 * position of the output window and the image window.
419
 */
420 421 422 423
void vout_PlacePicture( vout_thread_t *p_vout,
                        unsigned int i_width, unsigned int i_height,
                        unsigned int *pi_x, unsigned int *pi_y,
                        unsigned int *pi_width, unsigned int *pi_height )
Sam Hocevar's avatar
 
Sam Hocevar committed
424
{
gbazin's avatar
 
gbazin committed
425
    if( (i_width <= 0) || (i_height <=0) )
gbazin's avatar
 
gbazin committed
426 427
    {
        *pi_width = *pi_height = *pi_x = *pi_y = 0;
gbazin's avatar
 
gbazin committed
428
        return;
gbazin's avatar
 
gbazin committed
429
    }
gbazin's avatar
 
gbazin committed
430

Sam Hocevar's avatar
 
Sam Hocevar committed
431 432 433 434 435 436 437
    if( p_vout->b_scale )
    {
        *pi_width = i_width;
        *pi_height = i_height;
    }
    else
    {
438 439
        *pi_width = __MIN( i_width, p_vout->fmt_in.i_visible_width );
        *pi_height = __MIN( i_height, p_vout->fmt_in.i_visible_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
440 441
    }

442
    if( p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
443 444
        *pi_height / p_vout->fmt_in.i_visible_height /
        p_vout->fmt_in.i_sar_den > *pi_width )
Sam Hocevar's avatar
 
Sam Hocevar committed
445
    {
446
        *pi_height = p_vout->fmt_in.i_visible_height *
447
            (int64_t)p_vout->fmt_in.i_sar_den * *pi_width /
448
            p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;
Sam Hocevar's avatar
 
Sam Hocevar committed
449 450 451
    }
    else
    {
452
        *pi_width = p_vout->fmt_in.i_visible_width *
453
            (int64_t)p_vout->fmt_in.i_sar_num * *pi_height /
454
            p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
Sam Hocevar's avatar
 
Sam Hocevar committed
455 456
    }

gbazin's avatar
 
gbazin committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
    switch( p_vout->i_alignment & VOUT_ALIGN_HMASK )
    {
    case VOUT_ALIGN_LEFT:
        *pi_x = 0;
        break;
    case VOUT_ALIGN_RIGHT:
        *pi_x = i_width - *pi_width;
        break;
    default:
        *pi_x = ( i_width - *pi_width ) / 2;
    }

    switch( p_vout->i_alignment & VOUT_ALIGN_VMASK )
    {
    case VOUT_ALIGN_TOP:
        *pi_y = 0;
        break;
    case VOUT_ALIGN_BOTTOM:
        *pi_y = i_height - *pi_height;
        break;
    default:
        *pi_y = ( i_height - *pi_height ) / 2;
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
480 481
}

482 483 484
/**
 * Allocate a new picture in the heap.
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
485 486 487
 * This function allocates a fake direct buffer in memory, which can be
 * used exactly like a video buffer. The video output thread then manages
 * how it gets displayed.
488
 */
489 490 491
int __vout_AllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
                            vlc_fourcc_t i_chroma,
                            int i_width, int i_height, int i_aspect )
Sam Hocevar's avatar
 
Sam Hocevar committed
492
{
493 494 495 496 497
    int i_bytes, i_index, i_width_aligned, i_height_aligned;

    /* Make sure the real dimensions are a multiple of 16 */
    i_width_aligned = (i_width + 15) >> 4 << 4;
    i_height_aligned = (i_height + 15) >> 4 << 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
498

499 500 501 502 503 504
    if( vout_InitPicture( p_this, p_pic, i_chroma,
                          i_width, i_height, i_aspect ) != VLC_SUCCESS )
    {
        p_pic->i_planes = 0;
        return VLC_EGENERIC;
    }
gbazin's avatar
 
gbazin committed
505 506

    /* Calculate how big the new image should be */
gbazin's avatar
 
gbazin committed
507
    i_bytes = p_pic->format.i_bits_per_pixel *
508
        i_width_aligned * i_height_aligned / 8;
gbazin's avatar
 
gbazin committed
509 510 511 512 513 514

    p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );

    if( p_pic->p_data == NULL )
    {
        p_pic->i_planes = 0;
515
        return VLC_EGENERIC;
gbazin's avatar
 
gbazin committed
516 517 518 519 520 521 522
    }

    /* Fill the p_pixels field for each plane */
    p_pic->p[ 0 ].p_pixels = p_pic->p_data;

    for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
    {
523 524
        p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels +
            p_pic->p[i_index-1].i_lines * p_pic->p[i_index-1].i_pitch;
gbazin's avatar
 
gbazin committed
525
    }
526 527

    return VLC_SUCCESS;
gbazin's avatar
 
gbazin committed
528 529
}

530 531 532
/**
 * Initialise the video format fields given chroma/size.
 *
gbazin's avatar
 
gbazin committed
533 534
 * This function initializes all the video_frame_format_t fields given the
 * static properties of a picture (chroma and size).
535 536 537 538 539 540
 * \param p_format Pointer to the format structure to initialize
 * \param i_chroma Chroma to set
 * \param i_width Width to set
 * \param i_height Height to set
 * \param i_aspect Aspect ratio
 */
gbazin's avatar
 
gbazin committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
void vout_InitFormat( video_frame_format_t *p_format, vlc_fourcc_t i_chroma,
                      int i_width, int i_height, int i_aspect )
{
    p_format->i_chroma   = i_chroma;
    p_format->i_width    = p_format->i_visible_width  = i_width;
    p_format->i_height   = p_format->i_visible_height = i_height;
    p_format->i_x_offset = p_format->i_y_offset = 0;
    p_format->i_aspect   = i_aspect;

#if 0
    /* Assume we have square pixels */
    if( i_width && i_height )
        p_format->i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
    else
        p_format->i_aspect = 0;
#endif

    switch( i_chroma )
    {
560 561 562
        case FOURCC_YUVA:
            p_format->i_bits_per_pixel = 32;
            break;
gbazin's avatar
 
gbazin committed
563
        case FOURCC_I444:
564
        case FOURCC_J444:
gbazin's avatar
 
gbazin committed
565 566 567 568
            p_format->i_bits_per_pixel = 24;
            break;
        case FOURCC_I422:
        case FOURCC_YUY2:
569
        case FOURCC_UYVY:
570
        case FOURCC_J422:
gbazin's avatar
 
gbazin committed
571 572 573 574 575
            p_format->i_bits_per_pixel = 16;
            break;
        case FOURCC_I411:
        case FOURCC_YV12:
        case FOURCC_I420:
576
        case FOURCC_J420:
gbazin's avatar
 
gbazin committed
577 578 579 580
        case FOURCC_IYUV:
            p_format->i_bits_per_pixel = 12;
            break;
        case FOURCC_I410:
581
        case FOURCC_YVU9:
gbazin's avatar
 
gbazin committed
582 583 584 585 586
            p_format->i_bits_per_pixel = 9;
            break;
        case FOURCC_Y211:
            p_format->i_bits_per_pixel = 8;
            break;
587 588 589 590
        case FOURCC_YUVP:
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
 
gbazin committed
591
        case FOURCC_RV32:
592
        case FOURCC_RGBA:
gbazin's avatar
 
gbazin committed
593 594 595 596 597 598 599 600 601 602 603 604
            p_format->i_bits_per_pixel = 32;
            break;
        case FOURCC_RV24:
            p_format->i_bits_per_pixel = 24;
            break;
        case FOURCC_RV15:
        case FOURCC_RV16:
            p_format->i_bits_per_pixel = 16;
            break;
        case FOURCC_RGB2:
            p_format->i_bits_per_pixel = 8;
            break;
605 606 607 608 609

        case FOURCC_GREY:
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
 
gbazin committed
610 611 612 613 614 615
        default:
            p_format->i_bits_per_pixel = 0;
            break;
    }
}

616 617 618
/**
 * Initialise the picture_t fields given chroma/size.
 *
gbazin's avatar
 
gbazin committed
619 620
 * This function initializes most of the picture_t fields given a chroma and
 * size. It makes the assumption that stride == width.
621 622 623 624 625 626 627
 * \param p_this The calling object
 * \param p_pic Pointer to the picture to initialize
 * \param i_chroma The chroma fourcc to set
 * \param i_width The width of the picture
 * \param i_height The height of the picture
 * \param i_aspect The aspect ratio of the picture
 */
628 629 630
int __vout_InitPicture( vlc_object_t *p_this, picture_t *p_pic,
                        vlc_fourcc_t i_chroma,
                        int i_width, int i_height, int i_aspect )
gbazin's avatar
 
gbazin committed
631
{
632
    int i_index, i_width_aligned, i_height_aligned;
gbazin's avatar
 
gbazin committed
633

Sam Hocevar's avatar
 
Sam Hocevar committed
634 635 636 637
    /* Store default values */
    for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
    {
        p_pic->p[i_index].p_pixels = NULL;
638
        p_pic->p[i_index].i_pixel_pitch = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
639 640
    }

641 642 643 644 645
    p_pic->pf_release = 0;
    p_pic->pf_lock = 0;
    p_pic->pf_unlock = 0;
    p_pic->i_refcount = 0;

gbazin's avatar
 
gbazin committed
646 647
    vout_InitFormat( &p_pic->format, i_chroma, i_width, i_height, i_aspect );

648 649 650 651
    /* Make sure the real dimensions are a multiple of 16 */
    i_width_aligned = (i_width + 15) >> 4 << 4;
    i_height_aligned = (i_height + 15) >> 4 << 4;

Sam Hocevar's avatar
 
Sam Hocevar committed
652
    /* Calculate coordinates */
Sam Hocevar's avatar
 
Sam Hocevar committed
653
    switch( i_chroma )
Sam Hocevar's avatar
 
Sam Hocevar committed
654
    {
gbazin's avatar
 
gbazin committed
655
        case FOURCC_I411:
656 657
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
658 659
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
660 661
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
662 663
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
664 665
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
666 667
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
gbazin's avatar
 
gbazin committed
668 669 670
            p_pic->i_planes = 3;
            break;

671
        case FOURCC_I410:
672
        case FOURCC_YVU9:
673 674
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
675 676
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
677 678
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 4;
679 680
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
681 682
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 4;
683 684
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
685 686 687
            p_pic->i_planes = 3;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
688
        case FOURCC_YV12:
Sam Hocevar's avatar
 
Sam Hocevar committed
689 690
        case FOURCC_I420:
        case FOURCC_IYUV:
691
        case FOURCC_J420:
692 693
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
694 695
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
696 697
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
698 699
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
700 701
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
702 703
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
704
            p_pic->i_planes = 3;
Sam Hocevar's avatar
 
Sam Hocevar committed
705 706
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
707
        case FOURCC_I422:
708
        case FOURCC_J422:
709 710
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
711 712
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
713 714
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
715 716
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
717 718
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
719 720
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
721
            p_pic->i_planes = 3;
Sam Hocevar's avatar
 
Sam Hocevar committed
722 723
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
724
        case FOURCC_I444:
725
        case FOURCC_J444:
726 727
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
728 729
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
730 731
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
732 733
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
734 735
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
736 737
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
Sam Hocevar's avatar
 
Sam Hocevar committed
738 739 740
            p_pic->i_planes = 3;
            break;

741
        case FOURCC_YUVA:
742 743
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
744 745
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
746 747
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
748 749
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
750 751
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
752 753
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
754 755
            p_pic->p[ A_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ A_PLANE ].i_visible_lines = i_height;
756 757
            p_pic->p[ A_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ A_PLANE ].i_visible_pitch = i_width;
758 759 760 761
            p_pic->i_planes = 4;
            break;

        case FOURCC_YUVP:
762 763
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
764 765
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
766 767 768 769
            p_pic->p->i_pixel_pitch = 8;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
770
        case FOURCC_Y211:
771 772
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
773 774
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
775
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
776 777 778
            p_pic->i_planes = 1;
            break;

779
        case FOURCC_UYVY:
780
        case FOURCC_YUY2:
781 782
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
783 784
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
785
            p_pic->p->i_pixel_pitch = 4;
786 787 788
            p_pic->i_planes = 1;
            break;

789
        case FOURCC_RGB2:
790 791
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
792 793
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
794 795 796 797
            p_pic->p->i_pixel_pitch = 1;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
798
        case FOURCC_RV15:
799 800
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
801 802
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
803
            p_pic->p->i_pixel_pitch = 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
804 805 806 807
            p_pic->i_planes = 1;
            break;

        case FOURCC_RV16:
808 809
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
810 811
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
812
            p_pic->p->i_pixel_pitch = 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
813
            p_pic->i_planes = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
814 815
            break;

gbazin's avatar
 
gbazin committed
816
        case FOURCC_RV24:
817 818
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
819 820
            p_pic->p->i_pitch = i_width_aligned * 3;
            p_pic->p->i_visible_pitch = i_width * 3;
gbazin's avatar
 
gbazin committed
821 822 823 824
            p_pic->p->i_pixel_pitch = 3;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
825
        case FOURCC_RV32:
826
        case FOURCC_RGBA:
827 828
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
829 830
            p_pic->p->i_pitch = i_width_aligned * 4;
            p_pic->p->i_visible_pitch = i_width * 4;
831
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
832 833 834
            p_pic->i_planes = 1;
            break;

835 836 837 838 839 840 841 842 843
        case FOURCC_GREY:
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
            p_pic->p->i_pixel_pitch = 1;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
844
        default:
gbazin's avatar
 
gbazin committed
845
            msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
846
                             i_chroma, (char*)&i_chroma );
Sam Hocevar's avatar
 
Sam Hocevar committed
847
            p_pic->i_planes = 0;
848
            return VLC_EGENERIC;
Sam Hocevar's avatar
 
Sam Hocevar committed
849
    }
850 851

    return VLC_SUCCESS;
Sam Hocevar's avatar
 
Sam Hocevar committed
852 853
}

854 855 856
/**
 * Compare two chroma values
 *
857
 * This function returns 1 if the two fourcc values given as argument are
gbazin's avatar
 
gbazin committed
858
 * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
859
 */
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
{
    /* If they are the same, they are the same ! */
    if( i_chroma == i_amorhc )
    {
        return 1;
    }

    /* Check for equivalence classes */
    switch( i_chroma )
    {
        case FOURCC_I420:
        case FOURCC_IYUV:
        case FOURCC_YV12:
            switch( i_amorhc )
            {
                case FOURCC_I420:
                case FOURCC_IYUV:
                case FOURCC_YV12:
                    return 1;

                default:
                    return 0;
            }

        case FOURCC_UYVY:
        case FOURCC_UYNV:
        case FOURCC_Y422:
            switch( i_amorhc )
            {
                case FOURCC_UYVY:
                case FOURCC_UYNV:
                case FOURCC_Y422:
                    return 1;

                default:
                    return 0;
            }

        case FOURCC_YUY2:
        case FOURCC_YUNV:
            switch( i_amorhc )
            {
                case FOURCC_YUY2:
                case FOURCC_YUNV:
                    return 1;

                default:
                    return 0;
            }

        default:
            return 0;
    }
}

916
/*****************************************************************************