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