vout_pictures.c 32.1 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 22 23 24 25 26 27 28 29 30 31
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                                /* free() */
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                            /* strerror() */

32
#include <vlc/vlc.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
33

34
#include "vlc_video.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
35
#include "video_output.h"
36
#include "vlc_spu.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
37

38 39
#include "vout_pictures.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
                               vlc_bool_t b_progressive,
                               vlc_bool_t 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 222 223
{
    vlc_mutex_lock( &p_vout->picture_lock );

#ifdef DEBUG
    /* 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
    if( p_pic->i_refcount < 0 )
Sam Hocevar's avatar
 
Sam Hocevar committed
263
    {
zorglub's avatar
zorglub committed
264
        msg_Err( p_vout, "picture %p refcount is %i",
265
                 p_pic, p_pic->i_refcount );
Sam Hocevar's avatar
 
Sam Hocevar committed
266
        p_pic->i_refcount = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
267 268
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
269 270
    if( ( p_pic->i_refcount == 0 ) &&
        ( p_pic->i_status == DISPLAYED_PICTURE ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
271
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
272
        p_pic->i_status = DESTROYED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
273
        p_vout->i_heap_size--;
Sam Hocevar's avatar
 
Sam Hocevar committed
274 275 276 277 278
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

279 280 281
/**
 * Render a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
282 283 284
 * 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.
285
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
286
picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
Sam Hocevar's avatar
 
Sam Hocevar committed
287 288
                                                       subpicture_t *p_subpic )
{
289 290
    int i_scale_width, i_scale_height;

Sam Hocevar's avatar
 
Sam Hocevar committed
291
    if( p_pic == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
292 293 294 295 296
    {
        /* XXX: subtitles */
        return NULL;
    }

297 298 299 300
    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;
301

Sam Hocevar's avatar
 
Sam Hocevar committed
302
    if( p_pic->i_type == DIRECT_PICTURE )
Sam Hocevar's avatar
 
Sam Hocevar committed
303
    {
304 305
        if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount ||
            p_pic->b_force )
Sam Hocevar's avatar
 
Sam Hocevar committed
306 307 308 309 310 311 312 313 314
        {
            /* 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. */
315
                vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
316

317
                spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out,
318 319
                                       PP_OUTPUTPICTURE[0], p_pic, p_subpic,
                                       i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
320

Sam Hocevar's avatar
 
Sam Hocevar committed
321
                return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
 
Sam Hocevar committed
322 323 324 325 326
            }

            /* 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
327
            return p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
328 329 330 331 332
        }

        /* Picture is in a direct buffer but isn't used by the
         * decoder. We can safely render subtitles on it and
         * display it. */
333 334
        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
335

Sam Hocevar's avatar
 
Sam Hocevar committed
336
        return p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
337 338 339 340
    }

    /* 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
341
    if( p_vout->b_direct )
Sam Hocevar's avatar
 
Sam Hocevar committed
342 343 344 345
    {
        /* 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
346 347 348 349 350

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

351
        vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
352 353 354
        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
355

gbazin's avatar
 
gbazin committed
356 357 358
        if( PP_OUTPUTPICTURE[0]->pf_unlock )
            PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );

Sam Hocevar's avatar
 
Sam Hocevar committed
359
        return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
 
Sam Hocevar committed
360 361 362 363
    }

    /* 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
364
     * well. This usually means software YUV, or hardware YUV with a
Sam Hocevar's avatar
 
Sam Hocevar committed
365 366
     * different chroma. */

367 368 369 370 371 372 373 374 375
    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),
376 377 378 379
                                  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 );
380 381 382 383 384 385
            p_tmp_pic->i_type = MEMORY_PICTURE;
            p_tmp_pic->i_status = RESERVED_PICTURE;
        }

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

387
        /* Render subpictures on the first direct buffer */
388
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out, p_tmp_pic,
389 390
                               p_tmp_pic, p_subpic,
                               i_scale_width, i_scale_height );
Sam Hocevar's avatar
 
Sam Hocevar committed
391

392 393 394 395
        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;

396
        vout_CopyPicture( p_vout, &p_vout->p_picture[0], p_tmp_pic );
397 398 399 400 401 402 403 404 405 406 407
    }
    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 */
408 409 410
        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 );
411
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
412

gbazin's avatar
 
gbazin committed
413 414 415
    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
416 417 418
    return &p_vout->p_picture[0];
}

419 420 421
/**
 * Calculate image window coordinates
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
422 423
 * This function will be accessed by plugins. It calculates the relative
 * position of the output window and the image window.
424
 */
425 426 427 428
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
429
{
gbazin's avatar
 
gbazin committed
430
    if( (i_width <= 0) || (i_height <=0) )
gbazin's avatar
 
gbazin committed
431 432
    {
        *pi_width = *pi_height = *pi_x = *pi_y = 0;
gbazin's avatar
 
gbazin committed
433
        return;
gbazin's avatar
 
gbazin committed
434
    }
gbazin's avatar
 
gbazin committed
435

Sam Hocevar's avatar
 
Sam Hocevar committed
436 437 438 439 440 441 442
    if( p_vout->b_scale )
    {
        *pi_width = i_width;
        *pi_height = i_height;
    }
    else
    {
443 444
        *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
445 446
    }

447
    if( p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
448 449
        *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
450
    {
451
        *pi_height = p_vout->fmt_in.i_visible_height *
452
            (int64_t)p_vout->fmt_in.i_sar_den * *pi_width /
453
            p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;
Sam Hocevar's avatar
 
Sam Hocevar committed
454 455 456
    }
    else
    {
457
        *pi_width = p_vout->fmt_in.i_visible_width *
458
            (int64_t)p_vout->fmt_in.i_sar_num * *pi_height /
459
            p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
Sam Hocevar's avatar
 
Sam Hocevar committed
460 461
    }

gbazin's avatar
 
gbazin committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
    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
485 486
}

487 488 489
/**
 * Allocate a new picture in the heap.
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
490 491 492
 * 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.
493
 */
494 495 496
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
497
{
498 499 500 501 502
    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
503

504 505 506 507 508 509
    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
510 511

    /* Calculate how big the new image should be */
gbazin's avatar
 
gbazin committed
512
    i_bytes = p_pic->format.i_bits_per_pixel *
513
        i_width_aligned * i_height_aligned / 8;
gbazin's avatar
 
gbazin committed
514 515 516 517 518 519

    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;
520
        return VLC_EGENERIC;
gbazin's avatar
 
gbazin committed
521 522 523 524 525 526 527
    }

    /* 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++ )
    {
528 529
        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
530
    }
531 532

    return VLC_SUCCESS;
gbazin's avatar
 
gbazin committed
533 534
}

535 536 537
/**
 * Initialise the video format fields given chroma/size.
 *
gbazin's avatar
 
gbazin committed
538 539
 * This function initializes all the video_frame_format_t fields given the
 * static properties of a picture (chroma and size).
540 541 542 543 544 545
 * \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
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
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 )
    {
565 566 567
        case FOURCC_YUVA:
            p_format->i_bits_per_pixel = 32;
            break;
gbazin's avatar
 
gbazin committed
568
        case FOURCC_I444:
569
        case FOURCC_J444:
gbazin's avatar
 
gbazin committed
570 571 572 573
            p_format->i_bits_per_pixel = 24;
            break;
        case FOURCC_I422:
        case FOURCC_YUY2:
574
        case FOURCC_UYVY:
575
        case FOURCC_J422:
gbazin's avatar
 
gbazin committed
576 577 578 579 580 581
            p_format->i_bits_per_pixel = 16;
            p_format->i_bits_per_pixel = 16;
            break;
        case FOURCC_I411:
        case FOURCC_YV12:
        case FOURCC_I420:
582
        case FOURCC_J420:
gbazin's avatar
 
gbazin committed
583 584 585 586
        case FOURCC_IYUV:
            p_format->i_bits_per_pixel = 12;
            break;
        case FOURCC_I410:
587
        case FOURCC_YVU9:
gbazin's avatar
 
gbazin committed
588 589 590 591 592
            p_format->i_bits_per_pixel = 9;
            break;
        case FOURCC_Y211:
            p_format->i_bits_per_pixel = 8;
            break;
593 594 595 596
        case FOURCC_YUVP:
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
 
gbazin committed
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
        case FOURCC_RV32:
            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;
        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 827
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
828 829
            p_pic->p->i_pitch = i_width_aligned * 4;
            p_pic->p->i_visible_pitch = i_width * 4;
830
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
831 832 833
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
834
        default:
gbazin's avatar
 
gbazin committed
835
            msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
836
                             i_chroma, (char*)&i_chroma );
Sam Hocevar's avatar
 
Sam Hocevar committed
837
            p_pic->i_planes = 0;
838
            return VLC_EGENERIC;
Sam Hocevar's avatar
 
Sam Hocevar committed
839
    }
840 841

    return VLC_SUCCESS;
Sam Hocevar's avatar
 
Sam Hocevar committed
842 843
}

844 845 846
/**
 * Compare two chroma values
 *
847
 * This function returns 1 if the two fourcc values given as argument are
gbazin's avatar
 
gbazin committed
848
 * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
849
 */
850 851 852 853 854 855 856 857 858 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
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;
    }
}

906
/*****************************************************************************
907
 * vout_CopyPicture: copy a picture to another one
908 909 910
 *****************************************************************************
 * This function takes advantage of the image format, and reduces the
 * number of calls to memcpy() to the minimum. Source and destination
911
 * images must have same width (hence i_visible_pitch), height, and chroma.
912
 *****************************************************************************/
913 914
void __vout_CopyPicture( vlc_object_t *p_this,
                         picture_t *p_dest, picture_t *p_src )