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