vout_pictures.c 36.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_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--;
Sam Hocevar's avatar
   
Sam Hocevar committed
265
266
267
268

    vlc_mutex_unlock( &p_vout->picture_lock );
}

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

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

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

    vlc_mutex_unlock( &p_vout->picture_lock );
}

302
303
304
/**
 * Render a picture
 *
Sam Hocevar's avatar
   
Sam Hocevar committed
305
306
307
 * 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.
308
 */
Sam Hocevar's avatar
   
Sam Hocevar committed
309
picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
Sam Hocevar's avatar
   
Sam Hocevar committed
310
311
                                                       subpicture_t *p_subpic )
{
312
313
    int i_scale_width, i_scale_height;

Sam Hocevar's avatar
   
Sam Hocevar committed
314
    if( p_pic == NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
315
316
317
318
319
    {
        /* XXX: subtitles */
        return NULL;
    }

320
321
322
323
    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;
324

Sam Hocevar's avatar
   
Sam Hocevar committed
325
    if( p_pic->i_type == DIRECT_PICTURE )
Sam Hocevar's avatar
   
Sam Hocevar committed
326
    {
327
328
        if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount ||
            p_pic->b_force )
Sam Hocevar's avatar
   
Sam Hocevar committed
329
330
331
332
333
334
335
336
337
        {
            /* 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. */
338
                vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
Sam Hocevar's avatar
   
Sam Hocevar committed
339

340
                spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out,
341
342
                                       PP_OUTPUTPICTURE[0], p_pic, p_subpic,
                                       i_scale_width, i_scale_height );
Sam Hocevar's avatar
   
Sam Hocevar committed
343

Sam Hocevar's avatar
   
Sam Hocevar committed
344
                return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
   
Sam Hocevar committed
345
346
347
348
349
            }

            /* 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
350
            return p_pic;
Sam Hocevar's avatar
   
Sam Hocevar committed
351
352
353
354
355
        }

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

Sam Hocevar's avatar
   
Sam Hocevar committed
359
        return p_pic;
Sam Hocevar's avatar
   
Sam Hocevar committed
360
361
362
363
    }

    /* 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
364
    if( p_vout->b_direct )
Sam Hocevar's avatar
   
Sam Hocevar committed
365
366
367
368
    {
        /* 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
369
370
371
372
373

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

374
        vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic );
375
376
377
        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
378

gbazin's avatar
   
gbazin committed
379
380
381
        if( PP_OUTPUTPICTURE[0]->pf_unlock )
            PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );

Sam Hocevar's avatar
   
Sam Hocevar committed
382
        return PP_OUTPUTPICTURE[0];
Sam Hocevar's avatar
   
Sam Hocevar committed
383
384
385
386
    }

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

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

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

413
        /* Render subpictures on the first direct buffer */
414
        spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out, p_tmp_pic,
415
416
                               p_tmp_pic, p_subpic,
                               i_scale_width, i_scale_height );
Sam Hocevar's avatar
   
Sam Hocevar committed
417

418
419
420
421
        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;

422
        vout_CopyPicture( p_vout, &p_vout->p_picture[0], p_tmp_pic );
423
424
425
426
427
428
429
430
    }
    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 */
dionoea's avatar
dionoea committed
431
        p_vout->p_chroma->p_owner = (filter_owner_sys_t *)&p_vout->p_picture[0];
432
        p_vout->p_chroma->pf_video_filter( p_vout->p_chroma, p_pic );
433
434

        /* Render subpictures on the first direct buffer */
435
436
437
        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 );
438
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
439

gbazin's avatar
   
gbazin committed
440
441
442
    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
443
444
445
    return &p_vout->p_picture[0];
}

446
447
448
/**
 * Calculate image window coordinates
 *
Sam Hocevar's avatar
   
Sam Hocevar committed
449
450
 * This function will be accessed by plugins. It calculates the relative
 * position of the output window and the image window.
451
 */
452
453
454
455
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
456
{
gbazin's avatar
   
gbazin committed
457
    if( (i_width <= 0) || (i_height <=0) )
gbazin's avatar
   
gbazin committed
458
459
    {
        *pi_width = *pi_height = *pi_x = *pi_y = 0;
gbazin's avatar
   
gbazin committed
460
        return;
gbazin's avatar
   
gbazin committed
461
    }
gbazin's avatar
   
gbazin committed
462

Sam Hocevar's avatar
   
Sam Hocevar committed
463
464
465
466
467
468
469
    if( p_vout->b_scale )
    {
        *pi_width = i_width;
        *pi_height = i_height;
    }
    else
    {
470
471
        *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
472
473
    }

474
    if( p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
475
476
        *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
477
    {
478
        *pi_height = p_vout->fmt_in.i_visible_height *
479
            (int64_t)p_vout->fmt_in.i_sar_den * *pi_width /
480
            p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;
Sam Hocevar's avatar
   
Sam Hocevar committed
481
482
483
    }
    else
    {
484
        *pi_width = p_vout->fmt_in.i_visible_width *
485
            (int64_t)p_vout->fmt_in.i_sar_num * *pi_height /
486
            p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
Sam Hocevar's avatar
   
Sam Hocevar committed
487
488
    }

gbazin's avatar
   
gbazin committed
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
    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
512
513
}

514
515
516
/**
 * Allocate a new picture in the heap.
 *
Sam Hocevar's avatar
   
Sam Hocevar committed
517
518
519
 * 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.
520
 */
521
522
523
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
524
{
525
526
527
528
529
    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
530

531
532
533
534
535
536
    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
537
538

    /* Calculate how big the new image should be */
gbazin's avatar
   
gbazin committed
539
    i_bytes = p_pic->format.i_bits_per_pixel *
540
        i_width_aligned * i_height_aligned / 8;
gbazin's avatar
   
gbazin committed
541
542
543
544
545
546

    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;
547
        return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
548
549
550
551
552
553
554
    }

    /* 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++ )
    {
555
556
        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
557
    }
558
559

    return VLC_SUCCESS;
gbazin's avatar
   
gbazin committed
560
561
}

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

gbazin's avatar
   
gbazin committed
627
        case FOURCC_RV32:
628
        case FOURCC_RGBA:
gbazin's avatar
   
gbazin committed
629
630
631
632
633
634
635
636
637
638
639
640
            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;
641
642

        case FOURCC_GREY:
643
644
        case FOURCC_Y800:
        case FOURCC_Y8:
645
646
647
            p_format->i_bits_per_pixel = 8;
            break;

gbazin's avatar
   
gbazin committed
648
649
650
651
652
653
        default:
            p_format->i_bits_per_pixel = 0;
            break;
    }
}

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

Sam Hocevar's avatar
   
Sam Hocevar committed
672
673
674
675
    /* Store default values */
    for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
    {
        p_pic->p[i_index].p_pixels = NULL;
676
        p_pic->p[i_index].i_pixel_pitch = 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
677
678
    }

679
680
681
682
683
    p_pic->pf_release = 0;
    p_pic->pf_lock = 0;
    p_pic->pf_unlock = 0;
    p_pic->i_refcount = 0;

684
685
686
687
    p_pic->p_q = NULL;
    p_pic->i_qstride = 0;
    p_pic->i_qtype = 0;

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

690
691
692
693
    /* 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
694
    /* Calculate coordinates */
Sam Hocevar's avatar
   
Sam Hocevar committed
695
    switch( i_chroma )
Sam Hocevar's avatar
   
Sam Hocevar committed
696
    {
gbazin's avatar
   
gbazin committed
697
        case FOURCC_I411:
698
699
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
700
701
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
702
703
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
704
705
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
706
707
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
708
709
            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
710
711
712
            p_pic->i_planes = 3;
            break;

713
        case FOURCC_I410:
714
        case FOURCC_YVU9:
715
716
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
717
718
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
719
720
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height / 4;
721
722
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
723
724
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height / 4;
725
726
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
727
728
729
            p_pic->i_planes = 3;
            break;

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

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

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
        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
783
        case FOURCC_I444:
784
        case FOURCC_J444:
785
786
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
787
788
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
789
790
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
791
792
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
793
794
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
795
796
            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
797
798
799
            p_pic->i_planes = 3;
            break;

800
        case FOURCC_YUVA:
801
802
            p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
803
804
            p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
805
806
            p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ U_PLANE ].i_visible_lines = i_height;
807
808
            p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
809
810
            p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ V_PLANE ].i_visible_lines = i_height;
811
812
            p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
813
814
            p_pic->p[ A_PLANE ].i_lines = i_height_aligned;
            p_pic->p[ A_PLANE ].i_visible_lines = i_height;
815
816
            p_pic->p[ A_PLANE ].i_pitch = i_width_aligned;
            p_pic->p[ A_PLANE ].i_visible_pitch = i_width;
817
818
819
820
            p_pic->i_planes = 4;
            break;

        case FOURCC_YUVP:
821
822
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
823
824
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
825
826
827
828
            p_pic->p->i_pixel_pitch = 8;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
   
Sam Hocevar committed
829
        case FOURCC_Y211:
830
831
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
832
833
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
834
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
   
Sam Hocevar committed
835
836
837
            p_pic->i_planes = 1;
            break;

838
        case FOURCC_UYVY:
839
        case FOURCC_YUY2:
840
841
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
842
843
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
844
            p_pic->p->i_pixel_pitch = 4;
845
846
847
            p_pic->i_planes = 1;
            break;

848
        case FOURCC_RGB2:
849
850
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
851
852
            p_pic->p->i_pitch = i_width_aligned;
            p_pic->p->i_visible_pitch = i_width;
853
854
855
856
            p_pic->p->i_pixel_pitch = 1;
            p_pic->i_planes = 1;
            break;

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

        case FOURCC_RV16:
867
868
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
869
870
            p_pic->p->i_pitch = i_width_aligned * 2;
            p_pic->p->i_visible_pitch = i_width * 2;
871
            p_pic->p->i_pixel_pitch = 2;
Sam Hocevar's avatar
   
Sam Hocevar committed
872
            p_pic->i_planes = 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
873
874
            break;

gbazin's avatar
   
gbazin committed
875
        case FOURCC_RV24:
876
877
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
878
879
            p_pic->p->i_pitch = i_width_aligned * 3;
            p_pic->p->i_visible_pitch = i_width * 3;
gbazin's avatar
   
gbazin committed
880
881
882
883
            p_pic->p->i_pixel_pitch = 3;
            p_pic->i_planes = 1;
            break;

Sam Hocevar's avatar
   
Sam Hocevar committed
884
        case FOURCC_RV32:
885
        case FOURCC_RGBA:
886
887
            p_pic->p->i_lines = i_height_aligned;
            p_pic->p->i_visible_lines = i_height;
888
889
            p_pic->p->i_pitch = i_width_aligned * 4;
            p_pic->p->i_visible_pitch = i_width * 4;
890
            p_pic->p->i_pixel_pitch = 4;
Sam Hocevar's avatar
   
Sam Hocevar committed
891
892
893
            p_pic->i_planes = 1;
            break;

894
        case FOURCC_GREY:
895
896
        case FOURCC_Y800:
        case FOURCC_Y8:
897
898
899
900
901
902
903
904
            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
905
        default:
906
907
908
            if( p_this )
                msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
                                 i_chroma, (char*)&i_chroma );
Sam Hocevar's avatar
   
Sam Hocevar committed
909
            p_pic->i_planes = 0;
910
            return VLC_EGENERIC;
Sam Hocevar's avatar
   
Sam Hocevar committed
911
    }
912
913

    return VLC_SUCCESS;
Sam Hocevar's avatar
   
Sam Hocevar committed
914
915
}

916
917
918
/**
 * Compare two chroma values
 *
919
 * This function returns 1 if the two fourcc values given as argument are
gbazin's avatar
   
gbazin committed
920
 * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
921
 */
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
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;
            }

973
974
975
976
977
978
979
980
981
982
983
984
985
986
        case FOURCC_GREY:
        case FOURCC_Y800:
        case FOURCC_Y8:
            switch( i_amorhc )
            {
                case FOURCC_GREY:
                case FOURCC_Y800:
                case FOURCC_Y8:
                    return 1;

                default:
                    return 0;
            }

987
988
989
990
991
        default:
            return 0;
    }
}

992
/*****************************************************************************
993
 * vout_CopyPicture: copy a picture to another one
994
995
996
 *****************************************************************************
 * This function takes advantage of the image format, and reduces the
 * number of calls to memcpy() to the minimum. Source and destination
997
 * images must have same width (hence i_visible_pitch), height, and chroma.
998
 *****************************************************************************/
999
1000
void __vout_CopyPicture( vlc_object_t *p_this,
                         picture_t *p_dest, picture_t *p_src )
1001
{
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
    VLC_UNUSED(p_this);
    picture_Copy( p_dest, p_src );
}

/*****************************************************************************
 *
 *****************************************************************************/
static void PictureReleaseCallback( picture_t *p_picture )
{
    if( --p_picture->i_refcount > 0 )
        return;
    picture_Delete( p_picture );
}
/*****************************************************************************
 *
 *****************************************************************************/
picture_t *picture_New( vlc_fourcc_t i_chroma, int i_width, int i_height, int i_aspect )
{
    picture_t *p_picture = malloc( sizeof(*p_picture) );

    if( !p_picture )
        return NULL;

    memset( p_picture, 0, sizeof(*p_picture) );
    if( __vout_AllocatePicture( NULL, p_picture,
                                i_chroma, i_width, i_height, i_aspect ) )
    {
        free( p_picture );
        return NULL;
    }

    p_picture->i_refcount = 1;
    p_picture->pf_release = PictureReleaseCallback;
    p_picture->i_status = RESERVED_PICTURE;

    return p_picture;
}

/*****************************************************************************
 *
 *****************************************************************************/
void picture_Delete( picture_t *p_picture )
{
    assert( p_picture && p_picture->i_refcount == 0 );

    free( p_picture->p_data_orig );
    free( p_picture->p_sys );
    free( p_picture );
}

/*****************************************************************************
 *
 *****************************************************************************/
void picture_CopyPixels( picture_t *p_dst, const picture_t *p_src )
{
1057
1058
1059
    int i;

    for( i = 0; i < p_src->i_planes ; i++ )
1060
1061
        plane_CopyPixels( p_dst->p+i, p_src->p+i );
}
1062

1063
1064
1065
1066
1067
1068
void plane_CopyPixels( plane_t *p_dst, const plane_t *p_src )
{
    const unsigned i_width  = __MIN( p_dst->i_visible_pitch,
                                     p_src->i_visible_pitch );
    const unsigned i_height = __MIN( p_dst->i_visible_lines,
                                     p_src->i_visible_lines );
1069

1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
    if( p_src->i_pitch == p_dst->i_pitch )
    {
        /* There are margins, but with the same width : perfect ! */
        vlc_memcpy( p_dst->p_pixels, p_src->p_pixels,
                    p_src->i_pitch * i_height );
    }
    else
    {
        /* We need to proceed line by line */
        uint8_t *p_in = p_src->p_pixels;
        uint8_t *p_out = p_dst->p_pixels;
        int i_line;
1082

1083
1084
1085
1086
1087
1088
1089
1090
        assert( p_in );
        assert( p_out );

        for( i_line = i_height; i_line--; )
        {
            vlc_memcpy( p_out, p_in, i_width );
            p_in += p_src->i_pitch;
            p_out += p_dst->i_pitch;
1091
1092
1093
        }
    }
}
Laurent Aimar's avatar
Laurent Aimar committed
1094

1095
1096
1097
1098
1099
/*****************************************************************************
 *
 *****************************************************************************/