* all: modified files for video transcoding. Still needed configure.ac.in
[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.34 2003/01/22 10:44:50 fenrir 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 refcount is %i", p_pic->i_refcount );
263         p_pic->i_refcount = 0;
264     }
265
266     if( ( p_pic->i_refcount == 0 ) &&
267         ( p_pic->i_status == DISPLAYED_PICTURE ) )
268     {
269         p_pic->i_status = DESTROYED_PICTURE;
270         p_vout->i_heap_size--;
271     }
272
273     vlc_mutex_unlock( &p_vout->picture_lock );
274 }
275
276 /*****************************************************************************
277  * vout_RenderPicture: render a picture
278  *****************************************************************************
279  * This function chooses whether the current picture needs to be copied
280  * before rendering, does the subpicture magic, and tells the video output
281  * thread which direct buffer needs to be displayed.
282  *****************************************************************************/
283 picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
284                                                        subpicture_t *p_subpic )
285 {
286     if( p_pic == NULL )
287     {
288         /* XXX: subtitles */
289
290         return NULL;
291     }
292
293     if( p_pic->i_type == DIRECT_PICTURE )
294     {
295         if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount )
296         {
297             /* Picture is in a direct buffer and is still in use,
298              * we need to copy it to another direct buffer before
299              * displaying it if there are subtitles. */
300             if( p_subpic != NULL )
301             {
302                 /* We have subtitles. First copy the picture to
303                  * the spare direct buffer, then render the
304                  * subtitles. */
305                 CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
306
307                 vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
308
309                 return PP_OUTPUTPICTURE[0];
310             }
311
312             /* No subtitles, picture is in a directbuffer so
313              * we can display it directly even if it is still
314              * in use. */
315             return p_pic;
316         }
317
318         /* Picture is in a direct buffer but isn't used by the
319          * decoder. We can safely render subtitles on it and
320          * display it. */
321         vout_RenderSubPictures( p_vout, p_pic, p_subpic );
322
323         return p_pic;
324     }
325
326     /* Not a direct buffer. We either need to copy it to a direct buffer,
327      * or render it if the chroma isn't the same. */
328     if( p_vout->b_direct )
329     {
330         /* Picture is not in a direct buffer, but is exactly the
331          * same size as the direct buffers. A memcpy() is enough,
332          * then render the subtitles. */
333         CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] );
334
335         vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
336
337         return PP_OUTPUTPICTURE[0];
338     }
339
340     /* Picture is not in a direct buffer, and needs to be converted to
341      * another size/chroma. Then the subtitles need to be rendered as
342      * well. This usually means software YUV, or hardware YUV with a
343      * different chroma. */
344
345     /* Convert image to the first direct buffer */
346     p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] );
347
348     /* Render subpictures on the first direct buffer */
349     vout_RenderSubPictures( p_vout, &p_vout->p_picture[0], p_subpic );
350
351     return &p_vout->p_picture[0];
352 }
353
354 /*****************************************************************************
355  * vout_PlacePicture: calculate image window coordinates
356  *****************************************************************************
357  * This function will be accessed by plugins. It calculates the relative
358  * position of the output window and the image window.
359  *****************************************************************************/
360 void vout_PlacePicture( vout_thread_t *p_vout,
361                         unsigned int i_width, unsigned int i_height,
362                         unsigned int *pi_x, unsigned int *pi_y,
363                         unsigned int *pi_width, unsigned int *pi_height )
364 {
365     if( (i_width <= 0) || (i_height <=0) )
366     {
367         *pi_width = *pi_height = *pi_x = *pi_y = 0;
368
369         return;
370     }
371
372     if( p_vout->b_scale )
373     {
374         *pi_width = i_width;
375         *pi_height = i_height;
376     }
377     else
378     {
379         *pi_width = __MIN( i_width, p_vout->render.i_width );
380         *pi_height = __MIN( i_height, p_vout->render.i_height );
381     }
382
383     if( VOUT_ASPECT_FACTOR * *pi_width / *pi_height < p_vout->render.i_aspect )
384     {
385         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
386     }
387     else
388     {
389         *pi_height = *pi_width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
390     }
391
392     if( *pi_width > i_width )
393     {
394         *pi_width = i_width;
395         *pi_height = VOUT_ASPECT_FACTOR * *pi_width / p_vout->render.i_aspect;
396     }
397
398     if( *pi_height > i_height )
399     {
400         *pi_height = i_height;
401         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
402     }
403
404     *pi_x = ( i_width - *pi_width ) / 2;
405     *pi_y = ( i_height - *pi_height ) / 2;
406 }
407
408 /*****************************************************************************
409  * vout_AllocatePicture: allocate a new picture in the heap.
410  *****************************************************************************
411  * This function allocates a fake direct buffer in memory, which can be
412  * used exactly like a video buffer. The video output thread then manages
413  * how it gets displayed.
414  *****************************************************************************/
415 void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic,
416                            int i_width, int i_height, vlc_fourcc_t i_chroma )
417 {
418     int i_bytes, i_index;
419
420     /* Store default values */
421     for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
422     {
423         p_pic->p[i_index].p_pixels = NULL;
424         p_pic->p[i_index].i_pixel_pitch = 1;
425     }
426
427     /* Calculate coordinates */
428     switch( i_chroma )
429     {
430         case FOURCC_I410:
431             p_pic->p[ Y_PLANE ].i_lines = i_height;
432             p_pic->p[ Y_PLANE ].i_pitch = i_width;
433             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
434             p_pic->p[ U_PLANE ].i_lines = i_height / 4;
435             p_pic->p[ U_PLANE ].i_pitch = i_width / 4;
436             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
437             p_pic->p[ V_PLANE ].i_lines = i_height / 4;
438             p_pic->p[ V_PLANE ].i_pitch = i_width / 4;
439             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
440             p_pic->i_planes = 3;
441             break;
442
443         case FOURCC_YV12:
444         case FOURCC_I420:
445         case FOURCC_IYUV:
446             p_pic->p[ Y_PLANE ].i_lines = i_height;
447             p_pic->p[ Y_PLANE ].i_pitch = i_width;
448             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
449             p_pic->p[ U_PLANE ].i_lines = i_height / 2;
450             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
451             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
452             p_pic->p[ V_PLANE ].i_lines = i_height / 2;
453             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
454             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
455             p_pic->i_planes = 3;
456             break;
457
458         case FOURCC_I422:
459             p_pic->p[ Y_PLANE ].i_lines = i_height;
460             p_pic->p[ Y_PLANE ].i_pitch = i_width;
461             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
462             p_pic->p[ U_PLANE ].i_lines = i_height;
463             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
464             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
465             p_pic->p[ V_PLANE ].i_lines = i_height;
466             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
467             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
468             p_pic->i_planes = 3;
469             break;
470
471         case FOURCC_I444:
472             p_pic->p[ Y_PLANE ].i_lines = i_height;
473             p_pic->p[ Y_PLANE ].i_pitch = i_width;
474             p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch;
475             p_pic->p[ U_PLANE ].i_lines = i_height;
476             p_pic->p[ U_PLANE ].i_pitch = i_width;
477             p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch;
478             p_pic->p[ V_PLANE ].i_lines = i_height;
479             p_pic->p[ V_PLANE ].i_pitch = i_width;
480             p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch;
481             p_pic->i_planes = 3;
482             break;
483
484         case FOURCC_Y211:
485             p_pic->p->i_lines = i_height;
486             p_pic->p->i_pitch = i_width;
487             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
488             p_pic->p->i_pixel_pitch = 4;
489             p_pic->i_planes = 1;
490             break;
491
492         case FOURCC_YUY2:
493             p_pic->p->i_lines = i_height;
494             p_pic->p->i_pitch = i_width * 2;
495             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
496             p_pic->p->i_pixel_pitch = 4;
497             p_pic->i_planes = 1;
498             break;
499
500         case FOURCC_RGB2:
501             p_pic->p->i_lines = i_height;
502             p_pic->p->i_pitch = i_width;
503             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
504             p_pic->p->i_pixel_pitch = 1;
505             p_pic->i_planes = 1;
506             break;
507
508         case FOURCC_RV15:
509             p_pic->p->i_lines = i_height;
510             p_pic->p->i_pitch = i_width * 2;
511             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
512             p_pic->p->i_pixel_pitch = 2;
513 /* FIXME: p_heap isn't always reachable
514             p_pic->p_heap->i_rmask = 0x001f;
515             p_pic->p_heap->i_gmask = 0x03e0;
516             p_pic->p_heap->i_bmask = 0x7c00; */
517             p_pic->i_planes = 1;
518             break;
519
520         case FOURCC_RV16:
521             p_pic->p->i_lines = i_height;
522             p_pic->p->i_pitch = i_width * 2;
523             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
524             p_pic->p->i_pixel_pitch = 2;
525 /* FIXME: p_heap isn't always reachable
526             p_pic->p_heap->i_rmask = 0x001f;
527             p_pic->p_heap->i_gmask = 0x07e0;
528             p_pic->p_heap->i_bmask = 0xf800; */
529             p_pic->i_planes = 1;
530             break;
531
532         case FOURCC_RV32:
533             p_pic->p->i_lines = i_height;
534             p_pic->p->i_pitch = i_width * 4;
535             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
536             p_pic->p->i_pixel_pitch = 4;
537 /* FIXME: p_heap isn't always reachable
538             p_pic->p_heap->i_rmask = 0xff0000;
539             p_pic->p_heap->i_gmask = 0x00ff00;
540             p_pic->p_heap->i_bmask = 0x0000ff; */
541             p_pic->i_planes = 1;
542             break;
543
544         default:
545             msg_Err( p_vout, "unknown chroma type 0x%.8x (%4.4s)",
546                              i_chroma, (char*)&i_chroma );
547             p_pic->i_planes = 0;
548             return;
549     }
550
551     /* Calculate how big the new image should be */
552     for( i_bytes = 0, i_index = 0; i_index < p_pic->i_planes; i_index++ )
553     {
554         i_bytes += p_pic->p[ i_index ].i_lines * p_pic->p[ i_index ].i_pitch;
555     }
556
557     p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );
558
559     if( p_pic->p_data == NULL )
560     {
561         p_pic->i_planes = 0;
562         return;
563     }
564
565     /* Fill the p_pixels field for each plane */
566     p_pic->p[ 0 ].p_pixels = p_pic->p_data;
567
568     for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
569     {
570         p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels
571                                           + p_pic->p[i_index-1].i_lines
572                                              * p_pic->p[i_index-1].i_pitch;
573     }
574 }
575
576 /*****************************************************************************
577  * vout_ChromaCmp: compare two chroma values
578  *****************************************************************************
579  * This function returns 1 if the two fourcc values given as argument are
580  * the same format (eg. UYVY / UYNV) or almost the same format (eg. I420/YV12)
581  *****************************************************************************/
582 int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
583 {
584     /* If they are the same, they are the same ! */
585     if( i_chroma == i_amorhc )
586     {
587         return 1;
588     }
589
590     /* Check for equivalence classes */
591     switch( i_chroma )
592     {
593         case FOURCC_I420:
594         case FOURCC_IYUV:
595         case FOURCC_YV12:
596             switch( i_amorhc )
597             {
598                 case FOURCC_I420:
599                 case FOURCC_IYUV:
600                 case FOURCC_YV12:
601                     return 1;
602
603                 default:
604                     return 0;
605             }
606
607         case FOURCC_UYVY:
608         case FOURCC_UYNV:
609         case FOURCC_Y422:
610             switch( i_amorhc )
611             {
612                 case FOURCC_UYVY:
613                 case FOURCC_UYNV:
614                 case FOURCC_Y422:
615                     return 1;
616
617                 default:
618                     return 0;
619             }
620
621         case FOURCC_YUY2:
622         case FOURCC_YUNV:
623             switch( i_amorhc )
624             {
625                 case FOURCC_YUY2:
626                 case FOURCC_YUNV:
627                     return 1;
628
629                 default:
630                     return 0;
631             }
632
633         default:
634             return 0;
635     }
636 }
637
638 /* Following functions are local */
639
640 /*****************************************************************************
641  * CopyPicture: copy a picture to another one
642  *****************************************************************************
643  * This function takes advantage of the image format, and reduces the
644  * number of calls to memcpy() to the minimum. Source and destination
645  * images must have same width (hence i_visible_pitch), height, and chroma.
646  *****************************************************************************/
647 static void CopyPicture( vout_thread_t * p_vout,
648                          picture_t *p_src, picture_t *p_dest )
649 {
650     int i;
651
652     for( i = 0; i < p_src->i_planes ; i++ )
653     {
654         if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
655         {
656             /* There are margins, but with the same width : perfect ! */
657             p_vout->p_vlc->pf_memcpy(
658                          p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
659                          p_src->p[i].i_pitch * p_src->p[i].i_lines );
660         }
661         else
662         {
663             /* We need to proceed line by line */
664             uint8_t *p_in = p_src->p[i].p_pixels;
665             uint8_t *p_out = p_dest->p[i].p_pixels;
666             int i_line;
667
668             for( i_line = p_src->p[i].i_lines; i_line--; )
669             {
670                 p_vout->p_vlc->pf_memcpy( p_out, p_in,
671                                           p_src->p[i].i_visible_pitch );
672                 p_in += p_src->p[i].i_pitch;
673                 p_out += p_dest->p[i].i_pitch;
674             }
675         }
676     }
677     p_dest->date = p_src->date;
678 }