vout_pictures.c 35.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
 *
 * 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_common.h>
zorglub's avatar
zorglub committed
34 35
#include <vlc_vout.h>
#include <vlc_osd.h>
36
#include <vlc_filter.h>
37 38
#include "vout_pictures.h"

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

41 42 43
/**
 * Display a picture
 *
gbazin's avatar
 
gbazin committed
44 45
 * 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
46
 * called.
47
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
48
void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
49 50
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
51
    switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
52 53
    {
    case RESERVED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
54
        p_pic->i_status = RESERVED_DISP_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
55 56
        break;
    case RESERVED_DATED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
57
        p_pic->i_status = READY_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
58 59
        break;
    default:
60 61
        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
62 63 64 65 66 67
        break;
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

68 69 70
/**
 * Date a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
71 72 73
 * 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.
74 75 76 77
 * \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
78
void vout_DatePicture( vout_thread_t *p_vout,
Sam Hocevar's avatar
 
Sam Hocevar committed
79
                       picture_t *p_pic, mtime_t date )
Sam Hocevar's avatar
 
Sam Hocevar committed
80 81
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
82 83
    p_pic->date = date;
    switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
84 85
    {
    case RESERVED_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
86
        p_pic->i_status = RESERVED_DATED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
87 88
        break;
    case RESERVED_DISP_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
89
        p_pic->i_status = READY_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
90 91
        break;
    default:
92 93
        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
94 95 96 97 98 99
        break;
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

100 101 102
/**
 * Allocate a picture in the video output heap.
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
103 104
 * 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
105 106 107
 * already allocated zone of memory in the picture data fields.
 * It needs locking since several pictures can be created by several producers
 * threads.
108
 */
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
int vout_CountPictureAvailable( vout_thread_t *p_vout )
{
    int i_free = 0;
    int i_pic;

    vlc_mutex_lock( &p_vout->picture_lock );
    for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
    {
        picture_t *p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1) % I_RENDERPICTURES];

        switch( p_pic->i_status )
        {
            case DESTROYED_PICTURE:
                i_free++;
                break;

            case FREE_PICTURE:
                i_free++;
                break;

            default:
                break;
        }
    }
    vlc_mutex_unlock( &p_vout->picture_lock );

    return i_free;
}

Sam Hocevar's avatar
 
Sam Hocevar committed
138
picture_t *vout_CreatePicture( vout_thread_t *p_vout,
139 140
                               bool b_progressive,
                               bool b_top_field_first,
141
                               unsigned int i_nb_fields )
Sam Hocevar's avatar
 
Sam Hocevar committed
142
{
Sam Hocevar's avatar
 
Sam Hocevar committed
143 144 145
    int         i_pic;                                      /* picture index */
    picture_t * p_pic;
    picture_t * p_freepic = NULL;                      /* first free picture */
Sam Hocevar's avatar
 
Sam Hocevar committed
146 147 148 149 150

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

    /*
gbazin's avatar
 
gbazin committed
151
     * Look for an empty place in the picture heap.
Sam Hocevar's avatar
 
Sam Hocevar committed
152
     */
gbazin's avatar
 
gbazin committed
153
    for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
Sam Hocevar's avatar
 
Sam Hocevar committed
154
    {
gbazin's avatar
 
gbazin committed
155 156
        p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
                                 % I_RENDERPICTURES];
Sam Hocevar's avatar
 
Sam Hocevar committed
157

Sam Hocevar's avatar
 
Sam Hocevar committed
158
        switch( p_pic->i_status )
Sam Hocevar's avatar
 
Sam Hocevar committed
159
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
160 161 162 163
            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
164 165
                p_pic->i_status   = RESERVED_PICTURE;
                p_pic->i_refcount = 0;
166
                p_pic->b_force    = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
167

Sam Hocevar's avatar
 
Sam Hocevar committed
168
                p_pic->b_progressive        = b_progressive;
169
                p_pic->i_nb_fields          = i_nb_fields;
Sam Hocevar's avatar
 
Sam Hocevar committed
170
                p_pic->b_top_field_first    = b_top_field_first;
Sam Hocevar's avatar
 
Sam Hocevar committed
171

Sam Hocevar's avatar
 
Sam Hocevar committed
172
                p_vout->i_heap_size++;
gbazin's avatar
 
gbazin committed
173 174 175
                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
176
                vlc_mutex_unlock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
177
                return( p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
178

Sam Hocevar's avatar
 
Sam Hocevar committed
179
            case FREE_PICTURE:
Sam Hocevar's avatar
 
Sam Hocevar committed
180
                /* Picture is empty and ready for allocation */
gbazin's avatar
 
gbazin committed
181 182 183
                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
184
                p_freepic = p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
185 186 187 188 189
                break;

            default:
                break;
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
190 191 192 193 194
    }

    /*
     * Prepare picture
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
195
    if( p_freepic != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
196
    {
gbazin's avatar
 
gbazin committed
197 198
        vout_AllocatePicture( VLC_OBJECT(p_vout),
                              p_freepic, p_vout->render.i_chroma,
Sam Hocevar's avatar
 
Sam Hocevar committed
199
                              p_vout->render.i_width, p_vout->render.i_height,
gbazin's avatar
 
gbazin committed
200
                              p_vout->render.i_aspect );
Sam Hocevar's avatar
 
Sam Hocevar committed
201

Sam Hocevar's avatar
 
Sam Hocevar committed
202
        if( p_freepic->i_planes )
Sam Hocevar's avatar
 
Sam Hocevar committed
203 204
        {
            /* Copy picture information, set some default values */
Sam Hocevar's avatar
 
Sam Hocevar committed
205 206
            p_freepic->i_status   = RESERVED_PICTURE;
            p_freepic->i_type     = MEMORY_PICTURE;
207
            p_freepic->b_slow     = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
208

Sam Hocevar's avatar
 
Sam Hocevar committed
209
            p_freepic->i_refcount = 0;
210
            p_freepic->b_force = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
211

Sam Hocevar's avatar
 
Sam Hocevar committed
212
            p_freepic->b_progressive        = b_progressive;
213
            p_freepic->i_nb_fields          = i_nb_fields;
Sam Hocevar's avatar
 
Sam Hocevar committed
214
            p_freepic->b_top_field_first    = b_top_field_first;
Sam Hocevar's avatar
 
Sam Hocevar committed
215

Sam Hocevar's avatar
 
Sam Hocevar committed
216
            p_freepic->i_matrix_coefficients = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
217

Sam Hocevar's avatar
 
Sam Hocevar committed
218
            p_vout->i_heap_size++;
Sam Hocevar's avatar
 
Sam Hocevar committed
219 220 221 222
        }
        else
        {
            /* Memory allocation failed : set picture as empty */
Sam Hocevar's avatar
 
Sam Hocevar committed
223 224
            p_freepic->i_status = FREE_PICTURE;
            p_freepic = NULL;
Sam Hocevar's avatar
 
Sam Hocevar committed
225

226
            msg_Err( p_vout, "picture allocation failed" );
Sam Hocevar's avatar
 
Sam Hocevar committed
227 228 229 230
        }

        vlc_mutex_unlock( &p_vout->picture_lock );

Sam Hocevar's avatar
 
Sam Hocevar committed
231
        return( p_freepic );
Sam Hocevar's avatar
 
Sam Hocevar committed
232 233 234 235 236 237 238 239 240
    }

    /* 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 );
}

241 242 243
/**
 * Remove a permanent or reserved picture from the heap
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
244 245 246
 * 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 !
247
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
248
void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
249 250 251
{
    vlc_mutex_lock( &p_vout->picture_lock );

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
252
#ifndef NDEBUG
Sam Hocevar's avatar
 
Sam Hocevar committed
253
    /* Check if picture status is valid */
Sam Hocevar's avatar
 
Sam Hocevar committed
254 255 256
    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
257
    {
258 259
        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
260 261 262
    }
#endif

Sam Hocevar's avatar
 
Sam Hocevar committed
263
    p_pic->i_status = DESTROYED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
264
    p_vout->i_heap_size--;
265
    picture_CleanupQuant( p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
266 267 268 269

    vlc_mutex_unlock( &p_vout->picture_lock );
}

270 271 272
/**
 * Increment reference counter of a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
273 274
 * 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.
275
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
276
void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
277 278
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
279
    p_pic->i_refcount++;
Sam Hocevar's avatar
 
Sam Hocevar committed
280 281 282
    vlc_mutex_unlock( &p_vout->picture_lock );
}

283 284 285
/**
 * Decrement reference counter of a picture
 *
gbazin's avatar
 
gbazin committed
286
 * This function decrement the reference counter of a picture in the video heap
287
 */
Sam Hocevar's avatar
 
Sam Hocevar committed
288
void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
Sam Hocevar's avatar
 
Sam Hocevar committed
289 290
{
    vlc_mutex_lock( &p_vout->picture_lock );
Sam Hocevar's avatar
 
Sam Hocevar committed
291
    p_pic->i_refcount--;
Sam Hocevar's avatar
 
Sam Hocevar committed
292

Sam Hocevar's avatar
 
Sam Hocevar committed
293 294
    if( ( p_pic->i_refcount == 0 ) &&
        ( p_pic->i_status == DISPLAYED_PICTURE ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
295
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
296
        p_pic->i_status = DESTROYED_PICTURE;
Sam Hocevar's avatar
 
Sam Hocevar committed
297
        p_vout->i_heap_size--;
298
        picture_CleanupQuant( p_pic );
Sam Hocevar's avatar
 
Sam Hocevar committed
299 300 301 302 303
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}

304 305 306 307 308 309 310 311 312 313 314 315
static int vout_LockPicture( vout_thread_t *p_vout, picture_t *p_picture )
{
    if( p_picture->pf_lock )
        return p_picture->pf_lock( p_vout, p_picture );
    return VLC_SUCCESS;
}
static void vout_UnlockPicture( vout_thread_t *p_vout, picture_t *p_picture )
{
    if( p_picture->pf_unlock )
        p_picture->pf_unlock( p_vout, p_picture );
}

316 317 318
/**
 * Render a picture
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
319 320 321
 * 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.
322
 */
323
picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
Laurent Aimar's avatar
Laurent Aimar committed
324
                               subpicture_t *p_subpic, bool b_paused )
Sam Hocevar's avatar
 
Sam Hocevar committed
325
{
Sam Hocevar's avatar
 
Sam Hocevar committed
326
    if( p_pic == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
327
        return NULL;
328

Sam Hocevar's avatar
 
Sam Hocevar committed
329
    if( p_pic->i_type == DIRECT_PICTURE )
Sam Hocevar's avatar
 
Sam Hocevar committed
330
    {
331 332 333
        /* Picture is in a direct buffer. */

        if( p_subpic != NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
334
        {
335 336 337 338 339
            /* We have subtitles. First copy the picture to
             * the spare direct buffer, then render the
             * subtitles. */
            if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
                return NULL;
Sam Hocevar's avatar
 
Sam Hocevar committed
340

341
            picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
342

343 344
            spu_RenderSubpictures( p_vout->p_spu,
                                   PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
Laurent Aimar's avatar
Laurent Aimar committed
345
                                   p_subpic, &p_vout->fmt_in, b_paused );
346 347 348 349 350

            vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );

            return PP_OUTPUTPICTURE[0];
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
351

352 353 354
        /* No subtitles, picture is in a directbuffer so
         * we can display it directly (even if it is still
         * in use or not). */
Sam Hocevar's avatar
 
Sam Hocevar committed
355
        return p_pic;
Sam Hocevar's avatar
 
Sam Hocevar committed
356 357 358 359
    }

    /* 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
360
    if( p_vout->b_direct )
Sam Hocevar's avatar
 
Sam Hocevar committed
361 362 363 364
    {
        /* 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
365

366 367
        if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
            return NULL;
gbazin's avatar
 
gbazin committed
368

369
        picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
370 371
        spu_RenderSubpictures( p_vout->p_spu,
                               PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
Laurent Aimar's avatar
Laurent Aimar committed
372
                               p_subpic, &p_vout->fmt_in, b_paused );
Sam Hocevar's avatar
 
Sam Hocevar committed
373

374
        vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
gbazin's avatar
 
gbazin committed
375

Sam Hocevar's avatar
 
Sam Hocevar committed
376
        return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
 
Sam Hocevar committed
377 378 379 380
    }

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

384 385 386 387 388 389 390 391 392
    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),
393 394 395 396
                                  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 );
397 398
            p_tmp_pic->i_type = MEMORY_PICTURE;
            p_tmp_pic->i_status = RESERVED_PICTURE;
399 400
            /* some modules (such as blend)  needs to know the extra information in picture heap */
            p_tmp_pic->p_heap = &p_vout->output;
401 402 403
        }

        /* Convert image to the first direct buffer */
dionoea's avatar
dionoea committed
404
        p_vout->p_chroma->p_owner = (filter_owner_sys_t *)p_tmp_pic;
405
        p_vout->p_chroma->pf_video_filter( p_vout->p_chroma, p_pic );
gbazin's avatar
 
gbazin committed
406

407
        /* Render subpictures on the first direct buffer */
408 409
        spu_RenderSubpictures( p_vout->p_spu,
                               p_tmp_pic, &p_vout->fmt_out,
Laurent Aimar's avatar
Laurent Aimar committed
410
                               p_subpic, &p_vout->fmt_in, b_paused );
Sam Hocevar's avatar
 
Sam Hocevar committed
411

412 413
        if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
            return NULL;
414

415
        picture_Copy( &p_vout->p_picture[0], p_tmp_pic );
416 417 418
    }
    else
    {
419 420
        if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
            return NULL;
421 422

        /* Convert image to the first direct buffer */
dionoea's avatar
dionoea committed
423
        p_vout->p_chroma->p_owner = (filter_owner_sys_t *)&p_vout->p_picture[0];
424
        p_vout->p_chroma->pf_video_filter( p_vout->p_chroma, p_pic );
425 426

        /* Render subpictures on the first direct buffer */
427 428
        spu_RenderSubpictures( p_vout->p_spu,
                               &p_vout->p_picture[0], &p_vout->fmt_out,
Laurent Aimar's avatar
Laurent Aimar committed
429
                               p_subpic, &p_vout->fmt_in, b_paused );
430
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
431

432
    vout_UnlockPicture( p_vout, &p_vout->p_picture[0] );
gbazin's avatar
 
gbazin committed
433

Sam Hocevar's avatar
 
Sam Hocevar committed
434 435 436
    return &p_vout->p_picture[0];
}

437 438 439
/**
 * Calculate image window coordinates
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
440 441
 * This function will be accessed by plugins. It calculates the relative
 * position of the output window and the image window.
442
 */
443 444 445 446
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
447
{
gbazin's avatar
 
gbazin committed
448
    if( (i_width <= 0) || (i_height <=0) )
gbazin's avatar
 
gbazin committed
449 450
    {
        *pi_width = *pi_height = *pi_x = *pi_y = 0;
gbazin's avatar
 
gbazin committed
451
        return;
gbazin's avatar
 
gbazin committed
452
    }
gbazin's avatar
 
gbazin committed
453

Sam Hocevar's avatar
 
Sam Hocevar committed
454 455 456 457 458 459 460
    if( p_vout->b_scale )
    {
        *pi_width = i_width;
        *pi_height = i_height;
    }
    else
    {
461 462
        *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
463 464
    }

465 466 467 468 469 470
     int64_t i_scaled_width = p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
                              *pi_height / p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
     int64_t i_scaled_height = p_vout->fmt_in.i_visible_height * (int64_t)p_vout->fmt_in.i_sar_den *
                               *pi_width / p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;

    if( i_scaled_width <= 0 || i_scaled_height <= 0 )
Sam Hocevar's avatar
 
Sam Hocevar committed
471
    {
472 473 474
        msg_Warn( p_vout, "ignoring broken aspect ratio" );
        i_scaled_width = *pi_width;
        i_scaled_height = *pi_height;
Sam Hocevar's avatar
 
Sam Hocevar committed
475
    }
476 477 478

    if( i_scaled_width > *pi_width )
        *pi_height = i_scaled_height;
Sam Hocevar's avatar
 
Sam Hocevar committed
479
    else
480
        *pi_width = i_scaled_width;
Sam Hocevar's avatar
 
Sam Hocevar committed
481

gbazin's avatar
 
gbazin committed
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    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
505 506
}

507 508 509
/**
 * Allocate a new picture in the heap.
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
510 511 512
 * 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.
513
 */
514 515 516
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
517
{
518 519 520 521 522
    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
523

524 525 526 527 528 529
    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
530 531

    /* Calculate how big the new image should be */
gbazin's avatar
 
gbazin committed
532
    i_bytes = p_pic->format.i_bits_per_pixel *
533
        i_width_aligned * i_height_aligned / 8;
gbazin's avatar
 
gbazin committed
534 535 536 537 538 539

    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;
540
        return VLC_EGENERIC;
gbazin's avatar
 
gbazin committed
541 542 543 544 545 546 547
    }

    /* 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++ )
    {
548 549
        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
550
    }
551 552

    return VLC_SUCCESS;
gbazin's avatar
 
gbazin committed
553 554
}

555 556 557
/**
 * Initialise the video format fields given chroma/size.
 *
gbazin's avatar
 
gbazin committed
558 559
 * This function initializes all the video_frame_format_t fields given the
 * static properties of a picture (chroma and size).
560 561 562 563 564 565
 * \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
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
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 )
    {
585 586 587
        case FOURCC_YUVA:
            p_format->i_bits_per_pixel = 32;
            break;
gbazin's avatar
 
gbazin committed
588
        case FOURCC_I444:
589
        case FOURCC_J444:
gbazin's avatar
 
gbazin committed
590 591 592 593
            p_format->i_bits_per_pixel = 24;
            break;
        case FOURCC_I422:
        case FOURCC_YUY2:
594
        case FOURCC_UYVY:
595
        case FOURCC_J422:
gbazin's avatar
 
gbazin committed
596 597
            p_format->i_bits_per_pixel = 16;
            break;
598 599 600 601
        case FOURCC_I440:
        case FOURCC_J440:
            p_format->i_bits_per_pixel = 16;
            break;
gbazin's avatar
 
gbazin committed
602 603 604
        case FOURCC_I411:
        case FOURCC_YV12:
        case FOURCC_I420:
605
        case FOURCC_J420:
gbazin's avatar
 
gbazin committed
606 607 608 609
        case FOURCC_IYUV:
            p_format->i_bits_per_pixel = 12;
            break;
        case FOURCC_I410:
610
        case FOURCC_YVU9:
611
            p_format->i_bits_per_pixel = 9;
gbazin's avatar
 
gbazin committed
612 613 614 615
            break;
        case FOURCC_Y211:
            p_format->i_bits_per_pixel = 8;
            break;
616 617 618 619
        case FOURCC_YUVP:
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
 
gbazin committed
620
        case FOURCC_RV32:
621
        case FOURCC_RGBA:
gbazin's avatar
 
gbazin committed
622 623 624 625 626 627 628 629 630 631 632 633
            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;
634 635

        case FOURCC_GREY:
636 637
        case FOURCC_Y800:
        case FOURCC_Y8:
638
        case FOURCC_RGBP:
639 640 641
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
 
gbazin committed
642 643 644 645 646 647
        default:
            p_format->i_bits_per_pixel = 0;
            break;
    }
}

648 649 650
/**
 * Initialise the picture_t fields given chroma/size.
 *
gbazin's avatar
 
gbazin committed
651 652
 * This function initializes most of the picture_t fields given a chroma and
 * size. It makes the assumption that stride == width.
653 654 655 656 657 658 659
 * \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
 */
660 661 662
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
663
{
664
    int i_index, i_width_aligned, i_height_aligned;
gbazin's avatar
 
gbazin committed
665

Sam Hocevar's avatar
 
Sam Hocevar committed
666 667 668 669
    /* Store default values */
    for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
    {
        p_pic->p[i_index].p_pixels = NULL;
670
        p_pic->p[i_index].i_pixel_pitch = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
671 672
    }

673 674 675
    p_pic->pf_release = NULL;
    p_pic->pf_lock = NULL;
    p_pic->pf_unlock = NULL;
676 677
    p_pic->i_refcount = 0;

678 679 680 681
    p_pic->p_q = NULL;
    p_pic->i_qstride = 0;
    p_pic->i_qtype = 0;

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

684 685 686 687
    /* 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
688
    /* Calculate coordinates */
Sam Hocevar's avatar
 
Sam Hocevar committed
689
    switch( i_chroma )
Sam Hocevar's avatar
 
Sam Hocevar committed
690
    {
gbazin's avatar
 
gbazin committed
691
        case FOURCC_I411:
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;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
698 699
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
700 701
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
702 703
            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
704 705 706
            p_pic->i_planes = 3;
            break;

707
        case FOURCC_I410:
708
        case FOURCC_YVU9:
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 / 4;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 4;
715 716
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
717 718
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 4;
719 720
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
721 722 723
            p_pic->i_planes = 3;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
724
        case FOURCC_YV12:
Sam Hocevar's avatar
 
Sam Hocevar committed
725 726
        case FOURCC_I420:
        case FOURCC_IYUV:
727
        case FOURCC_J420:
728 729
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
730 731
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
732 733
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
734 735
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
736 737
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
738 739
            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
740
            p_pic->i_planes = 3;
Sam Hocevar's avatar
 
Sam Hocevar committed
741 742
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
743
        case FOURCC_I422:
744
        case FOURCC_J422:
745 746
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
747 748
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
749 750
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
751 752
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
753 754
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
755 756
            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
757
            p_pic->i_planes = 3;
Sam Hocevar's avatar
 
Sam Hocevar committed
758 759
            break;

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
        case FOURCC_I440:
        case FOURCC_J440:
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
            p_pic->i_planes = 3;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
777
        case FOURCC_I444:
778
        case FOURCC_J444:
779 780
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
781 782
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
783 784
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
785 786
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
787 788
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
789 790
            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
791 792 793
            p_pic->i_planes = 3;
            break;

794
        case FOURCC_YUVA:
795 796
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
797 798
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
799 800
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
801 802
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
803 804
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
805 806
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
807 808
            p_pic->p[ A_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ A_PLANE ].i_visible_lines = i_height;
809 810
            p_pic->p[ A_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ A_PLANE ].i_visible_pitch = i_width;
811 812 813 814
            p_pic->i_planes = 4;
            break;

        case FOURCC_YUVP:
815 816
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
817 818
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
819 820 821 822
            p_pic->p->i_pixel_pitch = 8;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
823
        case FOURCC_Y211:
824 825
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
826 827
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
828
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
829 830 831
            p_pic->i_planes = 1;
            break;

832
        case FOURCC_UYVY:
833
        case FOURCC_YUY2:
834 835
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
836 837
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
838
            p_pic->p->i_pixel_pitch = 4;
839 840 841
            p_pic->i_planes = 1;
            break;

842
        case FOURCC_RGB2:
843 844
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
845 846
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
847 848 849 850
            p_pic->p->i_pixel_pitch = 1;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
851
        case FOURCC_RV15:
852 853
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
854 855
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
856
            p_pic->p->i_pixel_pitch = 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
857 858 859 860
            p_pic->i_planes = 1;
            break;

        case FOURCC_RV16:
861 862
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
863 864
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
865
            p_pic->p->i_pixel_pitch = 2;
Sam Hocevar's avatar
 
Sam Hocevar committed
866
            p_pic->i_planes = 1;
Sam Hocevar's avatar
 
Sam Hocevar committed
867 868
            break;

gbazin's avatar
 
gbazin committed
869
        case FOURCC_RV24:
870 871
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
872 873
            p_pic->p->i_pitch = i_width_aligned * 3;
            p_pic->p->i_visible_pitch = i_width * 3;
gbazin's avatar
 
gbazin committed
874 875 876 877
            p_pic->p->i_pixel_pitch = 3;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
878
        case FOURCC_RV32:
879
        case FOURCC_RGBA:
880 881
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
882 883
            p_pic->p->i_pitch = i_width_aligned * 4;
            p_pic->p->i_visible_pitch = i_width * 4;
884
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
 
Sam Hocevar committed
885 886 887