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