]> git.sesse.net Git - vlc/blob - src/video_output/vout_pictures.c
c26d0cea9b5bbb5b3c23575bca1e7e8c19774808
[vlc] / src / video_output / vout_pictures.c
1 /*****************************************************************************
2  * vout_pictures.c : picture management functions
3  *****************************************************************************
4  * Copyright (C) 2000-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                                /* free() */
29 #include <stdio.h>                                              /* sprintf() */
30 #include <string.h>                                            /* strerror() */
31
32 #include <vlc/vlc.h>
33
34 #include "vlc_video.h"
35 #include "video_output.h"
36
37 #include "vout_pictures.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static void CopyPicture( vout_thread_t *, picture_t *, picture_t * );
43
44 /**
45  * Display a picture
46  *
47  * Remove the reservation flag of a picture, which will cause it to be ready
48  * for display. The picture won't be displayed until vout_DatePicture has been
49  * called.
50  */
51 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
52 {
53     vlc_mutex_lock( &p_vout->picture_lock );
54     switch( p_pic->i_status )
55     {
56     case RESERVED_PICTURE:
57         p_pic->i_status = RESERVED_DISP_PICTURE;
58         break;
59     case RESERVED_DATED_PICTURE:
60         p_pic->i_status = READY_PICTURE;
61         break;
62     default:
63         msg_Err( p_vout, "picture to display %p has invalid status %d",
64                          p_pic, p_pic->i_status );
65         break;
66     }
67
68     vlc_mutex_unlock( &p_vout->picture_lock );
69 }
70
71 /**
72  * Date a picture
73  *
74  * Remove the reservation flag of a picture, which will cause it to be ready
75  * for display. The picture won't be displayed until vout_DisplayPicture has
76  * been called.
77  * \param p_vout The vout in question
78  * \param p_pic The picture to date
79  * \param date The date to display the picture
80  */
81 void vout_DatePicture( vout_thread_t *p_vout,
82                        picture_t *p_pic, mtime_t date )
83 {
84     vlc_mutex_lock( &p_vout->picture_lock );
85     p_pic->date = date;
86     switch( p_pic->i_status )
87     {
88     case RESERVED_PICTURE:
89         p_pic->i_status = RESERVED_DATED_PICTURE;
90         break;
91     case RESERVED_DISP_PICTURE:
92         p_pic->i_status = READY_PICTURE;
93         break;
94     default:
95         msg_Err( p_vout, "picture to date %p has invalid status %d",
96                          p_pic, p_pic->i_status );
97         break;
98     }
99
100     vlc_mutex_unlock( &p_vout->picture_lock );
101 }
102
103 /**
104  * Allocate a picture in the video output heap.
105  *
106  * This function creates a reserved image in the video output heap.
107  * A null pointer is returned if the function fails. This method provides an
108  * already allocated zone of memory in the picture data fields.
109  * It needs locking since several pictures can be created by several producers
110  * threads.
111  */
112 picture_t *vout_CreatePicture( vout_thread_t *p_vout,
113                                vlc_bool_t b_progressive,
114                                vlc_bool_t b_top_field_first,
115                                unsigned int i_nb_fields )
116 {
117     int         i_pic;                                      /* picture index */
118     picture_t * p_pic;
119     picture_t * p_freepic = NULL;                      /* first free picture */
120
121     /* Get lock */
122     vlc_mutex_lock( &p_vout->picture_lock );
123
124     /*
125      * Look for an empty place in the picture heap.
126      */
127     for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
128     {
129         p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
130                                  % I_RENDERPICTURES];
131
132         switch( p_pic->i_status )
133         {
134             case DESTROYED_PICTURE:
135                 /* Memory will not be reallocated, and function can end
136                  * immediately - this is the best possible case, since no
137                  * memory allocation needs to be done */
138                 p_pic->i_status   = RESERVED_PICTURE;
139                 p_pic->i_refcount = 0;
140                 p_pic->b_force    = 0;
141
142                 p_pic->b_progressive        = b_progressive;
143                 p_pic->i_nb_fields          = i_nb_fields;
144                 p_pic->b_top_field_first    = b_top_field_first;
145
146                 p_vout->i_heap_size++;
147                 p_vout->render.i_last_used_pic =
148                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
149                     % I_RENDERPICTURES;
150                 vlc_mutex_unlock( &p_vout->picture_lock );
151                 return( p_pic );
152
153             case FREE_PICTURE:
154                 /* Picture is empty and ready for allocation */
155                 p_vout->render.i_last_used_pic =
156                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
157                     % I_RENDERPICTURES;
158                 p_freepic = p_pic;
159                 break;
160
161             default:
162                 break;
163         }
164     }
165
166     /*
167      * Prepare picture
168      */
169     if( p_freepic != NULL )
170     {
171         vout_AllocatePicture( VLC_OBJECT(p_vout),
172                               p_freepic, p_vout->render.i_chroma,
173                               p_vout->render.i_width, p_vout->render.i_height,
174                               p_vout->render.i_aspect );
175
176         if( p_freepic->i_planes )
177         {
178             /* Copy picture information, set some default values */
179             p_freepic->i_status   = RESERVED_PICTURE;
180             p_freepic->i_type     = MEMORY_PICTURE;
181             p_freepic->b_slow     = 0;
182
183             p_freepic->i_refcount = 0;
184             p_freepic->b_force = 0;
185
186             p_freepic->b_progressive        = b_progressive;
187             p_freepic->i_nb_fields          = i_nb_fields;
188             p_freepic->b_top_field_first    = b_top_field_first;
189
190             p_freepic->i_matrix_coefficients = 1;
191
192             p_vout->i_heap_size++;
193         }
194         else
195         {
196             /* Memory allocation failed : set picture as empty */
197             p_freepic->i_status = FREE_PICTURE;
198             p_freepic = NULL;
199
200             msg_Err( p_vout, "picture allocation failed" );
201         }
202
203         vlc_mutex_unlock( &p_vout->picture_lock );
204
205         return( p_freepic );
206     }
207
208     /* No free or destroyed picture could be found, but the decoder
209      * will try again in a while. */
210     vlc_mutex_unlock( &p_vout->picture_lock );
211
212     return( NULL );
213 }
214
215 /**
216  * Remove a permanent or reserved picture from the heap
217  *
218  * This function frees a previously reserved picture or a permanent
219  * picture. It is meant to be used when the construction of a picture aborted.
220  * Note that the picture will be destroyed even if it is linked !
221  */
222 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
223 {
224     vlc_mutex_lock( &p_vout->picture_lock );
225
226 #ifdef DEBUG
227     /* Check if picture status is valid */
228     if( (p_pic->i_status != RESERVED_PICTURE) &&
229         (p_pic->i_status != RESERVED_DATED_PICTURE) &&
230         (p_pic->i_status != RESERVED_DISP_PICTURE) )
231     {
232         msg_Err( p_vout, "picture to destroy %p has invalid status %d",
233                          p_pic, p_pic->i_status );
234     }
235 #endif
236
237     p_pic->i_status = DESTROYED_PICTURE;
238     p_vout->i_heap_size--;
239
240     vlc_mutex_unlock( &p_vout->picture_lock );
241 }
242
243 /**
244  * Increment reference counter of a picture
245  *
246  * This function increments the reference counter of a picture in the video
247  * heap. It needs a lock since several producer threads can access the picture.
248  */
249 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
250 {
251     vlc_mutex_lock( &p_vout->picture_lock );
252     p_pic->i_refcount++;
253     vlc_mutex_unlock( &p_vout->picture_lock );
254 }
255
256 /**
257  * Decrement reference counter of a picture
258  *
259  * This function decrement the reference counter of a picture in the video heap
260  */
261 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
262 {
263     vlc_mutex_lock( &p_vout->picture_lock );
264     p_pic->i_refcount--;
265
266     if( p_pic->i_refcount < 0 )
267     {
268         msg_Err( p_vout, "picture %p refcount is %i",
269                  p_pic, p_pic->i_refcount );
270         p_pic->i_refcount = 0;
271     }
272
273     if( ( p_pic->i_refcount == 0 ) &&
274         ( p_pic->i_status == DISPLAYED_PICTURE ) )
275     {
276         p_pic->i_status = DESTROYED_PICTURE;
277         p_vout->i_heap_size--;
278     }
279
280     vlc_mutex_unlock( &p_vout->picture_lock );
281 }
282
283 /**
284  * Render a picture
285  *
286  * This function chooses whether the current picture needs to be copied
287  * before rendering, does the subpicture magic, and tells the video output
288  * thread which direct buffer needs to be displayed.
289  */
290 picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
291                                                        subpicture_t *p_subpic )
292 {
293     if( p_pic == NULL )
294     {
295         /* XXX: subtitles */
296
297         return NULL;
298     }
299
300     if( p_pic->i_type == DIRECT_PICTURE )
301     {
302         if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount )
303         {
304             /* Picture is in a direct buffer and is still in use,
305              * we need to copy it to another direct buffer before
306              * displaying it if there are subtitles. */
307             if( p_subpic != NULL )
308             {
309                 /* We have subtitles. First copy the picture to
310                  * the spare direct buffer, then render the
311                  * subtitles. */
312                 CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
313
314                 vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
315
316                 return PP_OUTPUTPICTURE[0];
317             }
318
319             /* No subtitles, picture is in a directbuffer so
320              * we can display it directly even if it is still
321              * in use. */
322             return p_pic;
323         }
324
325         /* Picture is in a direct buffer but isn't used by the
326          * decoder. We can safely render subtitles on it and
327          * display it. */
328         vout_RenderSubPictures( p_vout, p_pic, p_subpic );
329
330         return p_pic;
331     }
332
333     /* Not a direct buffer. We either need to copy it to a direct buffer,
334      * or render it if the chroma isn't the same. */
335     if( p_vout->b_direct )
336     {
337         /* Picture is not in a direct buffer, but is exactly the
338          * same size as the direct buffers. A memcpy() is enough,
339          * then render the subtitles. */
340
341         if( PP_OUTPUTPICTURE[0]->pf_lock )
342             if( PP_OUTPUTPICTURE[0]->pf_lock( p_vout, PP_OUTPUTPICTURE[0] ) )
343             {
344                 if( PP_OUTPUTPICTURE[0]->pf_unlock )
345                 PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );
346
347                 return NULL;
348             }
349
350         if( p_subpic == NULL ||
351             ( p_vout->render.b_allow_modify_pics && !p_pic->i_refcount ) )
352         {
353             vout_RenderSubPictures( p_vout, p_pic, p_subpic );
354             CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
355         }
356         else if( PP_OUTPUTPICTURE[0]->b_slow )
357         {
358             /* The picture buffer is in slow memory. We'll use
359              * the "2 * VOUT_MAX_PICTURES + 1" picture as a temporary
360              * one for subpictures rendering. */
361             picture_t *p_tmp_pic = &p_vout->p_picture[2 * VOUT_MAX_PICTURES];
362             if( p_tmp_pic->i_status == FREE_PICTURE )
363             {
364                 vout_AllocatePicture( VLC_OBJECT(p_vout),
365                                       p_tmp_pic, p_vout->render.i_chroma,
366                                       p_vout->render.i_width,
367                                       p_vout->render.i_height,
368                                       p_vout->render.i_aspect );
369                 p_tmp_pic->i_type = MEMORY_PICTURE;
370                 p_tmp_pic->i_status = RESERVED_PICTURE;
371             }
372
373             CopyPicture( p_vout, p_pic, p_tmp_pic );
374
375             vout_RenderSubPictures( p_vout, p_tmp_pic, p_subpic );
376
377             CopyPicture( p_vout, p_tmp_pic, PP_OUTPUTPICTURE[0] );
378         }
379         else
380         {
381             CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
382
383             vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
384         }
385
386         if( PP_OUTPUTPICTURE[0]->pf_unlock )
387             PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] );
388
389         return PP_OUTPUTPICTURE[0];
390     }
391
392     /* Picture is not in a direct buffer, and needs to be converted to
393      * another size/chroma. Then the subtitles need to be rendered as
394      * well. This usually means software YUV, or hardware YUV with a
395      * different chroma. */
396
397     if( p_subpic != NULL && p_vout->p_picture[0].b_slow )
398     {
399         /* The picture buffer is in slow memory. We'll use
400          * the "2 * VOUT_MAX_PICTURES + 1" picture as a temporary
401          * one for subpictures rendering. */
402         picture_t *p_tmp_pic = &p_vout->p_picture[2 * VOUT_MAX_PICTURES];
403         if( p_tmp_pic->i_status == FREE_PICTURE )
404         {
405             vout_AllocatePicture( VLC_OBJECT(p_vout),
406                                   p_tmp_pic, p_vout->output.i_chroma,
407                                   p_vout->output.i_width,
408                                   p_vout->output.i_height,
409                                   p_vout->output.i_aspect );
410             p_tmp_pic->i_type = MEMORY_PICTURE;
411             p_tmp_pic->i_status = RESERVED_PICTURE;
412         }
413
414         /* Convert image to the first direct buffer */
415         p_vout->chroma.pf_convert( p_vout, p_pic, p_tmp_pic );
416
417         /* Render subpictures on the first direct buffer */
418         vout_RenderSubPictures( p_vout, p_tmp_pic, p_subpic );
419
420         if( p_vout->p_picture[0].pf_lock )
421             if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) )
422                 return NULL;
423
424         CopyPicture( p_vout, p_tmp_pic, &p_vout->p_picture[0] );
425     }
426     else
427     {
428         if( p_vout->p_picture[0].pf_lock )
429             if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) )
430                 return NULL;
431
432         /* Convert image to the first direct buffer */
433         p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] );
434
435         /* Render subpictures on the first direct buffer */
436         vout_RenderSubPictures( p_vout, &p_vout->p_picture[0], p_subpic );
437     }
438
439     if( p_vout->p_picture[0].pf_unlock )
440         p_vout->p_picture[0].pf_unlock( p_vout, &p_vout->p_picture[0] );
441
442     return &p_vout->p_picture[0];
443 }
444
445 /**
446  * Calculate image window coordinates
447  *
448  * This function will be accessed by plugins. It calculates the relative
449  * position of the output window and the image window.
450  */
451 void vout_PlacePicture( vout_thread_t *p_vout,
452                         unsigned int i_width, unsigned int i_height,
453                         unsigned int *pi_x, unsigned int *pi_y,
454                         unsigned int *pi_width, unsigned int *pi_height )
455 {
456     if( (i_width <= 0) || (i_height <=0) )
457     {
458         *pi_width = *pi_height = *pi_x = *pi_y = 0;
459
460         return;
461     }
462
463     if( p_vout->b_scale )
464     {
465         *pi_width = i_width;
466         *pi_height = i_height;
467     }
468     else
469     {
470         *pi_width = __MIN( i_width, p_vout->render.i_width );
471         *pi_height = __MIN( i_height, p_vout->render.i_height );
472     }
473
474     if( VOUT_ASPECT_FACTOR * *pi_width / *pi_height < p_vout->render.i_aspect )
475     {
476         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
477     }
478     else
479     {
480         *pi_height = *pi_width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
481     }
482
483     if( *pi_width > i_width )
484     {
485         *pi_width = i_width;
486         *pi_height = VOUT_ASPECT_FACTOR * *pi_width / p_vout->render.i_aspect;
487     }
488
489     if( *pi_height > i_height )
490     {
491         *pi_height = i_height;
492         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
493     }
494
495     switch( p_vout->i_alignment & VOUT_ALIGN_HMASK )
496     {
497     case VOUT_ALIGN_LEFT:
498         *pi_x = 0;
499         break;
500     case VOUT_ALIGN_RIGHT:
501         *pi_x = i_width - *pi_width;
502         break;
503     default:
504         *pi_x = ( i_width - *pi_width ) / 2;
505     }
506
507     switch( p_vout->i_alignment & VOUT_ALIGN_VMASK )
508     {
509     case VOUT_ALIGN_TOP:
510         *pi_y = 0;
511         break;
512     case VOUT_ALIGN_BOTTOM:
513         *pi_y = i_height - *pi_height;
514         break;
515     default:
516         *pi_y = ( i_height - *pi_height ) / 2;
517     }
518 }
519
520 /**
521  * Allocate a new picture in the heap.
522  *
523  * This function allocates a fake direct buffer in memory, which can be
524  * used exactly like a video buffer. The video output thread then manages
525  * how it gets displayed.
526  */
527 void vout_AllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
528                            vlc_fourcc_t i_chroma,
529                            int i_width, int i_height, int i_aspect )
530 {
531     int i_bytes, i_index;
532
533     vout_InitPicture( p_this, p_pic, i_chroma,
534                       i_width, i_height, i_aspect );
535
536     /* Calculate how big the new image should be */
537     i_bytes = p_pic->format.i_bits_per_pixel *
538         p_pic->format.i_width * p_pic->format.i_height / 8;
539
540     p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );
541
542     if( p_pic->p_data == NULL )
543     {
544         p_pic->i_planes = 0;
545         return;
546     }
547
548     /* Fill the p_pixels field for each plane */
549     p_pic->p[ 0 ].p_pixels = p_pic->p_data;
550
551     for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
552     {
553         p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels
554                                           + p_pic->p[i_index-1].i_lines
555                                              * p_pic->p[i_index-1].i_pitch;
556     }
557 }
558
559 /**
560  * Initialise the video format fields given chroma/size.
561  *
562  * This function initializes all the video_frame_format_t fields given the
563  * static properties of a picture (chroma and size).
564  * \param p_format Pointer to the format structure to initialize
565  * \param i_chroma Chroma to set
566  * \param i_width Width to set
567  * \param i_height Height to set
568  * \param i_aspect Aspect ratio
569  */
570 void vout_InitFormat( video_frame_format_t *p_format, vlc_fourcc_t i_chroma,
571                       int i_width, int i_height, int i_aspect )
572 {
573     p_format->i_chroma   = i_chroma;
574     p_format->i_width    = p_format->i_visible_width  = i_width;
575     p_format->i_height   = p_format->i_visible_height = i_height;
576     p_format->i_x_offset = p_format->i_y_offset = 0;
577     p_format->i_aspect   = i_aspect;
578
579 #if 0
580     /* Assume we have square pixels */
581     if( i_width && i_height )
582         p_format->i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
583     else
584         p_format->i_aspect = 0;
585 #endif
586
587     switch( i_chroma )
588     {
589         case FOURCC_YUVA:
590             p_format->i_bits_per_pixel = 32;
591             break;
592         case FOURCC_I444:
593             p_format->i_bits_per_pixel = 24;
594             break;
595         case FOURCC_I422:
596         case FOURCC_YUY2:
597         case FOURCC_UYVY:
598             p_format->i_bits_per_pixel = 16;
599             p_format->i_bits_per_pixel = 16;
600             break;
601         case FOURCC_I411:
602         case FOURCC_YV12:
603         case FOURCC_I420:
604         case FOURCC_IYUV:
605             p_format->i_bits_per_pixel = 12;
606             break;
607         case FOURCC_I410:
608         case FOURCC_YVU9:
609             p_format->i_bits_per_pixel = 9;
610             break;
611         case FOURCC_Y211:
612             p_format->i_bits_per_pixel = 8;
613             break;
614         case FOURCC_YUVP:
615             p_format->i_bits_per_pixel = 8;
616             break;
617
618         case FOURCC_RV32:
619             p_format->i_bits_per_pixel = 32;
620             break;
621         case FOURCC_RV24:
622             /* FIXME: Should be 24 here but x11 and our chroma conversion
623              * routines assume 32. */
624 #ifdef WIN32
625             p_format->i_bits_per_pixel = 24;
626 #else
627             p_format->i_bits_per_pixel = 32;
628 #endif
629             break;
630         case FOURCC_RV15:
631         case FOURCC_RV16:
632             p_format->i_bits_per_pixel = 16;
633             break;
634         case FOURCC_RGB2:
635             p_format->i_bits_per_pixel = 8;
636             break;
637         default:
638             p_format->i_bits_per_pixel = 0;
639             break;
640     }
641 }
642
643 /**
644  * Initialise the picture_t fields given chroma/size.
645  *
646  * This function initializes most of the picture_t fields given a chroma and
647  * size. It makes the assumption that stride == width.
648  * \param p_this The calling object
649  * \param p_pic Pointer to the picture to initialize
650  * \param i_chroma The chroma fourcc to set
651  * \param i_width The width of the picture
652  * \param i_height The height of the picture
653  * \param i_aspect The aspect ratio of the picture
654  */
655 void vout_InitPicture( vlc_object_t *p_this, picture_t *p_pic,
656                        vlc_fourcc_t i_chroma,
657                        int i_width, int i_height, int i_aspect )
658 {
659     int i_index;
660
661     /* Store default values */
662     for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
663     {
664         p_pic->p[i_index].p_pixels = NULL;
665         p_pic->p[i_index].i_pixel_pitch = 1;
666     }
667
668     vout_InitFormat( &p_pic->format, i_chroma, i_width, i_height, i_aspect );
669
670     /* Calculate coordinates */
671     switch( i_chroma )
672     {
673         case FOURCC_I411:
674             p_pic->p[ Y_PLANE ].i_lines = i_height;
675             p_pic->p[ Y_PLANE ].i_pitch = i_width;
676             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
677             p_pic->p[ U_PLANE ].i_lines = i_height;
678             p_pic->p[ U_PLANE ].i_pitch = i_width / 4;
679             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
680             p_pic->p[ V_PLANE ].i_lines = i_height;
681             p_pic->p[ V_PLANE ].i_pitch = i_width / 4;
682             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
683             p_pic->i_planes = 3;
684             break;
685
686         case FOURCC_I410:
687         case FOURCC_YVU9:
688             p_pic->p[ Y_PLANE ].i_lines = i_height;
689             p_pic->p[ Y_PLANE ].i_pitch = i_width;
690             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
691             p_pic->p[ U_PLANE ].i_lines = i_height / 4;
692             p_pic->p[ U_PLANE ].i_pitch = i_width / 4;
693             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
694             p_pic->p[ V_PLANE ].i_lines = i_height / 4;
695             p_pic->p[ V_PLANE ].i_pitch = i_width / 4;
696             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
697             p_pic->i_planes = 3;
698             break;
699
700         case FOURCC_YV12:
701         case FOURCC_I420:
702         case FOURCC_IYUV:
703             p_pic->p[ Y_PLANE ].i_lines = i_height;
704             p_pic->p[ Y_PLANE ].i_pitch = i_width;
705             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
706             p_pic->p[ U_PLANE ].i_lines = i_height / 2;
707             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
708             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
709             p_pic->p[ V_PLANE ].i_lines = i_height / 2;
710             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
711             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
712             p_pic->i_planes = 3;
713             break;
714
715         case FOURCC_I422:
716             p_pic->p[ Y_PLANE ].i_lines = i_height;
717             p_pic->p[ Y_PLANE ].i_pitch = i_width;
718             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
719             p_pic->p[ U_PLANE ].i_lines = i_height;
720             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
721             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
722             p_pic->p[ V_PLANE ].i_lines = i_height;
723             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
724             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
725             p_pic->i_planes = 3;
726             break;
727
728         case FOURCC_I444:
729             p_pic->p[ Y_PLANE ].i_lines = i_height;
730             p_pic->p[ Y_PLANE ].i_pitch = i_width;
731             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
732             p_pic->p[ U_PLANE ].i_lines = i_height;
733             p_pic->p[ U_PLANE ].i_pitch = i_width;
734             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
735             p_pic->p[ V_PLANE ].i_lines = i_height;
736             p_pic->p[ V_PLANE ].i_pitch = i_width;
737             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
738             p_pic->i_planes = 3;
739             break;
740
741         case FOURCC_YUVA:
742             p_pic->p[ Y_PLANE ].i_lines = i_height;
743             p_pic->p[ Y_PLANE ].i_pitch = i_width;
744             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
745             p_pic->p[ U_PLANE ].i_lines = i_height;
746             p_pic->p[ U_PLANE ].i_pitch = i_width;
747             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
748             p_pic->p[ V_PLANE ].i_lines = i_height;
749             p_pic->p[ V_PLANE ].i_pitch = i_width;
750             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
751             p_pic->p[ A_PLANE ].i_lines = i_height;
752             p_pic->p[ A_PLANE ].i_pitch = i_width;
753             p_pic->p[ A_PLANE ].i_visible_pitch = p_pic->p[ A_PLANE ].i_pitch;
754             p_pic->i_planes = 4;
755             break;
756
757         case FOURCC_YUVP:
758             p_pic->p->i_lines = i_height;
759             p_pic->p->i_pitch = i_width;
760             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
761             p_pic->p->i_pixel_pitch = 8;
762             p_pic->i_planes = 1;
763             break;
764
765         case FOURCC_Y211:
766             p_pic->p->i_lines = i_height;
767             p_pic->p->i_pitch = i_width;
768             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
769             p_pic->p->i_pixel_pitch = 4;
770             p_pic->i_planes = 1;
771             break;
772
773         case FOURCC_UYVY:
774         case FOURCC_YUY2:
775             p_pic->p->i_lines = i_height;
776             p_pic->p->i_pitch = i_width * 2;
777             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
778             p_pic->p->i_pixel_pitch = 4;
779             p_pic->i_planes = 1;
780             break;
781
782         case FOURCC_RGB2:
783             p_pic->p->i_lines = i_height;
784             p_pic->p->i_pitch = i_width;
785             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
786             p_pic->p->i_pixel_pitch = 1;
787             p_pic->i_planes = 1;
788             break;
789
790         case FOURCC_RV15:
791             p_pic->p->i_lines = i_height;
792             p_pic->p->i_pitch = i_width * 2;
793             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
794             p_pic->p->i_pixel_pitch = 2;
795 /* FIXME: p_heap isn't always reachable
796             p_pic->p_heap->i_rmask = 0x001f;
797             p_pic->p_heap->i_gmask = 0x03e0;
798             p_pic->p_heap->i_bmask = 0x7c00; */
799             p_pic->i_planes = 1;
800             break;
801
802         case FOURCC_RV16:
803             p_pic->p->i_lines = i_height;
804             p_pic->p->i_pitch = i_width * 2;
805             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
806             p_pic->p->i_pixel_pitch = 2;
807 /* FIXME: p_heap isn't always reachable
808             p_pic->p_heap->i_rmask = 0x001f;
809             p_pic->p_heap->i_gmask = 0x07e0;
810             p_pic->p_heap->i_bmask = 0xf800; */
811             p_pic->i_planes = 1;
812             break;
813
814         case FOURCC_RV24:
815             p_pic->p->i_lines = i_height;
816
817             /* FIXME: Should be 3 here but x11 and our chroma conversion
818              * routines assume 4. */
819 #ifdef WIN32
820             p_pic->p->i_pitch = i_width * 3;
821             p_pic->p->i_pixel_pitch = 3;
822 #else
823             p_pic->p->i_pitch = i_width * 4;
824             p_pic->p->i_pixel_pitch = 4;
825 #endif
826             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
827 /* FIXME: p_heap isn't always reachable
828             p_pic->p_heap->i_rmask = 0xff0000;
829             p_pic->p_heap->i_gmask = 0x00ff00;
830             p_pic->p_heap->i_bmask = 0x0000ff; */
831             p_pic->i_planes = 1;
832             break;
833
834         case FOURCC_RV32:
835             p_pic->p->i_lines = i_height;
836             p_pic->p->i_pitch = i_width * 4;
837             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
838             p_pic->p->i_pixel_pitch = 4;
839 /* FIXME: p_heap isn't always reachable
840             p_pic->p_heap->i_rmask = 0xff0000;
841             p_pic->p_heap->i_gmask = 0x00ff00;
842             p_pic->p_heap->i_bmask = 0x0000ff; */
843             p_pic->i_planes = 1;
844             break;
845
846         default:
847             msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
848                              i_chroma, (char*)&i_chroma );
849             p_pic->i_planes = 0;
850             return;
851     }
852 }
853
854 /**
855  * Compare two chroma values
856  *
857  * This function returns 1 if the two fourcc values given as argument are
858  * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
859  */
860 int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
861 {
862     /* If they are the same, they are the same ! */
863     if( i_chroma == i_amorhc )
864     {
865         return 1;
866     }
867
868     /* Check for equivalence classes */
869     switch( i_chroma )
870     {
871         case FOURCC_I420:
872         case FOURCC_IYUV:
873         case FOURCC_YV12:
874             switch( i_amorhc )
875             {
876                 case FOURCC_I420:
877                 case FOURCC_IYUV:
878                 case FOURCC_YV12:
879                     return 1;
880
881                 default:
882                     return 0;
883             }
884
885         case FOURCC_UYVY:
886         case FOURCC_UYNV:
887         case FOURCC_Y422:
888             switch( i_amorhc )
889             {
890                 case FOURCC_UYVY:
891                 case FOURCC_UYNV:
892                 case FOURCC_Y422:
893                     return 1;
894
895                 default:
896                     return 0;
897             }
898
899         case FOURCC_YUY2:
900         case FOURCC_YUNV:
901             switch( i_amorhc )
902             {
903                 case FOURCC_YUY2:
904                 case FOURCC_YUNV:
905                     return 1;
906
907                 default:
908                     return 0;
909             }
910
911         default:
912             return 0;
913     }
914 }
915
916 /* Following functions are local */
917
918 /*****************************************************************************
919  * CopyPicture: copy a picture to another one
920  *****************************************************************************
921  * This function takes advantage of the image format, and reduces the
922  * number of calls to memcpy() to the minimum. Source and destination
923  * images must have same width (hence i_visible_pitch), height, and chroma.
924  *****************************************************************************/
925 static void CopyPicture( vout_thread_t * p_vout,
926                          picture_t *p_src, picture_t *p_dest )
927 {
928     int i;
929
930     for( i = 0; i < p_src->i_planes ; i++ )
931     {
932         if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
933         {
934             /* There are margins, but with the same width : perfect ! */
935             p_vout->p_vlc->pf_memcpy(
936                          p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
937                          p_src->p[i].i_pitch * p_src->p[i].i_lines );
938         }
939         else
940         {
941             /* We need to proceed line by line */
942             uint8_t *p_in = p_src->p[i].p_pixels;
943             uint8_t *p_out = p_dest->p[i].p_pixels;
944             int i_line;
945
946             for( i_line = p_src->p[i].i_lines; i_line--; )
947             {
948                 p_vout->p_vlc->pf_memcpy( p_out, p_in,
949                                           p_src->p[i].i_visible_pitch );
950                 p_in += p_src->p[i].i_pitch;
951                 p_out += p_dest->p[i].i_pitch;
952             }
953         }
954     }
955     p_dest->date = p_src->date;
956 }