]> git.sesse.net Git - vlc/blob - src/video_output/vout_pictures.c
9633728269afbc48cc271a52e3431c09f438fb5d
[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.13 2002/02/08 15:57:29 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 <errno.h>                                                 /* ENOMEM */
29 #include <stdlib.h>                                                /* free() */
30 #include <stdio.h>                                              /* sprintf() */
31 #include <string.h>                                            /* strerror() */
32
33 #include <videolan/vlc.h>
34
35 #include "video.h"
36 #include "video_output.h"
37
38 /*****************************************************************************
39  * vout_DisplayPicture: display a picture
40  *****************************************************************************
41  * Remove the reservation flag of a picture, which will cause it to be ready for
42  * display. The picture won't be displayed until vout_DatePicture has been
43  * called.
44  *****************************************************************************/
45 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
46 {
47     vlc_mutex_lock( &p_vout->picture_lock );
48     switch( p_pic->i_status )
49     {
50     case RESERVED_PICTURE:
51         p_pic->i_status = RESERVED_DISP_PICTURE;
52         break;
53     case RESERVED_DATED_PICTURE:
54         p_pic->i_status = READY_PICTURE;
55         break;
56 #ifdef DEBUG
57     default:
58         intf_ErrMsg( "error: picture %p has invalid status %d",
59                      p_pic, p_pic->i_status );
60         break;
61 #endif
62     }
63
64 #ifdef TRACE_VOUT
65     intf_DbgMsg("picture %p", p_pic);
66 #endif
67     vlc_mutex_unlock( &p_vout->picture_lock );
68 }
69
70 /*****************************************************************************
71  * vout_DatePicture: date a picture
72  *****************************************************************************
73  * Remove the reservation flag of a picture, which will cause it to be ready
74  * for display. The picture won't be displayed until vout_DisplayPicture has
75  * been called.
76  *****************************************************************************/
77 void vout_DatePicture( vout_thread_t *p_vout,
78                        picture_t *p_pic, mtime_t date )
79 {
80 #ifdef TRACE_VOUT
81     char        psz_date[ MSTRTIME_MAX_SIZE ];                       /* date */
82 #endif
83
84     vlc_mutex_lock( &p_vout->picture_lock );
85     p_pic->date = date;
86     switch( p_pic->i_status )
87     {
88     case RESERVED_PICTURE:
89         p_pic->i_status = RESERVED_DATED_PICTURE;
90         break;
91     case RESERVED_DISP_PICTURE:
92         p_pic->i_status = READY_PICTURE;
93         break;
94 #ifdef DEBUG
95     default:
96         intf_ErrMsg( "error: picture %p has invalid status %d",
97                      p_pic, p_pic->i_status );
98         break;
99 #endif
100     }
101
102 #ifdef TRACE_VOUT
103     intf_DbgMsg( "picture %p, display date: %s",
104                  p_pic, mstrtime( psz_date, p_pic->date) );
105 #endif
106     vlc_mutex_unlock( &p_vout->picture_lock );
107 }
108
109 /*****************************************************************************
110  * vout_CreatePicture: allocate a picture in the video output heap.
111  *****************************************************************************
112  * This function creates a reserved image in the video output heap.
113  * A null pointer is returned if the function fails. This method provides an
114  * already allocated zone of memory in the picture data fields. It needs locking
115  * since several pictures can be created by several producers threads.
116  *****************************************************************************/
117 picture_t *vout_CreatePicture( vout_thread_t *p_vout,
118                                boolean_t b_progressive,
119                                boolean_t b_top_field_first,
120                                boolean_t b_repeat_first_field )
121 {
122     int         i_pic;                                      /* picture index */
123     picture_t * p_pic;
124     picture_t * p_freepic = NULL;                      /* first free picture */
125
126     /* Get lock */
127     vlc_mutex_lock( &p_vout->picture_lock );
128
129     /*
130      * Look for an empty place. We start at 1 because the first
131      * directbuffer is reserved for memcpy()ed pictures.
132      */
133     for( i_pic = 0; i_pic < I_RENDERPICTURES && p_freepic == NULL; i_pic++ )
134     {
135         p_pic = PP_RENDERPICTURE[ i_pic ];
136
137         /* If the picture we found is a memory buffer, and we have enough
138          * pictures in the stack, and we might have enough room later for
139          * a direct buffer, skip it. If no other pictures are found, the
140          * video decoder will try again later. */
141         if( p_vout->b_direct && ( p_vout->output.i_pictures > 5 )
142              && ( p_pic->i_type != DIRECT_PICTURE ) )
143         {
144             break;
145         }
146
147         switch( p_pic->i_status )
148         {
149             case DESTROYED_PICTURE:
150                 /* Memory will not be reallocated, and function can end
151                  * immediately - this is the best possible case, since no
152                  * memory allocation needs to be done */
153                 p_pic->i_status   = RESERVED_PICTURE;
154                 p_pic->i_refcount = 0;
155
156                 p_pic->b_progressive        = b_progressive;
157                 p_pic->b_repeat_first_field = b_repeat_first_field;
158                 p_pic->b_top_field_first    = b_top_field_first;
159
160                 p_vout->i_heap_size++;
161                 vlc_mutex_unlock( &p_vout->picture_lock );
162                 return( p_pic );
163
164             case FREE_PICTURE:
165                 /* Picture is empty and ready for allocation */
166                 p_freepic = p_pic;
167                 break;
168
169             default:
170                 break;
171         }
172     }
173
174     /*
175      * Prepare picture
176      */
177     if( p_freepic != NULL )
178     {
179         vout_AllocatePicture( p_freepic,
180                               p_vout->render.i_width, p_vout->render.i_height,
181                               p_vout->render.i_chroma );
182
183         if( p_freepic->i_planes )
184         {
185             /* Copy picture information, set some default values */
186             p_freepic->i_status   = RESERVED_PICTURE;
187             p_freepic->i_type     = MEMORY_PICTURE;
188
189             p_freepic->i_refcount = 0;
190
191             p_freepic->b_progressive        = b_progressive;
192             p_freepic->b_repeat_first_field = b_repeat_first_field;
193             p_freepic->b_top_field_first    = b_top_field_first;
194
195             p_freepic->i_matrix_coefficients = 1;
196
197             p_vout->i_heap_size++;
198         }
199         else
200         {
201             /* Memory allocation failed : set picture as empty */
202             p_freepic->i_status = FREE_PICTURE;
203             p_freepic = NULL;
204
205             intf_ErrMsg( "vout error: picture allocation failed" );
206         }
207
208         vlc_mutex_unlock( &p_vout->picture_lock );
209
210         /* Initialize mutex */
211         vlc_mutex_init( &(p_freepic->lock_deccount) );
212
213         return( p_freepic );
214     }
215
216     /* No free or destroyed picture could be found, but the decoder
217      * will try again in a while. */
218     vlc_mutex_unlock( &p_vout->picture_lock );
219
220     return( NULL );
221 }
222
223 /*****************************************************************************
224  * vout_DestroyPicture: remove a permanent or reserved picture from the heap
225  *****************************************************************************
226  * This function frees a previously reserved picture or a permanent
227  * picture. It is meant to be used when the construction of a picture aborted.
228  * Note that the picture will be destroyed even if it is linked !
229  *****************************************************************************/
230 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
231 {
232     vlc_mutex_lock( &p_vout->picture_lock );
233
234 #ifdef DEBUG
235     /* Check if picture status is valid */
236     if( (p_pic->i_status != RESERVED_PICTURE) &&
237         (p_pic->i_status != RESERVED_DATED_PICTURE) &&
238         (p_pic->i_status != RESERVED_DISP_PICTURE) )
239     {
240         intf_ErrMsg( "error: picture %p has invalid status %d",
241                      p_pic, p_pic->i_status );
242     }
243 #endif
244
245     p_pic->i_status = DESTROYED_PICTURE;
246     p_vout->i_heap_size--;
247
248     /* destroy the lock that had been initialized in CreatePicture */
249     vlc_mutex_destroy( &(p_pic->lock_deccount) );
250
251     vlc_mutex_unlock( &p_vout->picture_lock );
252 }
253
254 /*****************************************************************************
255  * vout_LinkPicture: increment reference counter of a picture
256  *****************************************************************************
257  * This function increments the reference counter of a picture in the video
258  * heap. It needs a lock since several producer threads can access the picture.
259  *****************************************************************************/
260 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
261 {
262     vlc_mutex_lock( &p_vout->picture_lock );
263     p_pic->i_refcount++;
264
265 #ifdef TRACE_VOUT
266     intf_DbgMsg( "picture %p refcount=%d", p_pic, p_pic->i_refcount );
267 #endif
268
269     vlc_mutex_unlock( &p_vout->picture_lock );
270 }
271
272 /*****************************************************************************
273  * vout_UnlinkPicture: decrement reference counter of a picture
274  *****************************************************************************
275  * This function decrement the reference counter of a picture in the video heap.
276  *****************************************************************************/
277 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
278 {
279     vlc_mutex_lock( &p_vout->picture_lock );
280     p_pic->i_refcount--;
281
282 #ifdef TRACE_VOUT
283     if( p_pic->i_refcount < 0 )
284     {
285         intf_DbgMsg( "error: refcount < 0" );
286         p_pic->i_refcount = 0;
287     }
288 #endif
289
290     if( ( p_pic->i_refcount == 0 ) &&
291         ( p_pic->i_status == DISPLAYED_PICTURE ) )
292     {
293         p_pic->i_status = DESTROYED_PICTURE;
294         p_vout->i_heap_size--;
295     }
296
297 #ifdef TRACE_VOUT
298     intf_DbgMsg( "picture %p refcount=%d", p_pic, p_pic->i_refcount );
299 #endif
300
301     vlc_mutex_unlock( &p_vout->picture_lock );
302 }
303
304 /*****************************************************************************
305  * vout_RenderPicture: render a picture
306  *****************************************************************************
307  * This function chooses whether the current picture needs to be copied
308  * before rendering, does the subpicture magic, and tells the video output
309  * thread which direct buffer needs to be displayed.
310  *****************************************************************************/
311 picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
312                                                        subpicture_t *p_subpic )
313 {
314     if( p_pic == NULL )
315     {
316         /* XXX: subtitles */
317
318         return NULL;
319     }
320
321     if( p_pic->i_type == DIRECT_PICTURE )
322     {
323         if( p_pic->i_refcount )
324         {
325             /* Picture is in a direct buffer and is still in use,
326              * we need to copy it to another direct buffer before
327              * displaying it if there are subtitles. */
328             if( p_subpic != NULL )
329             {
330                     //printf("memcpy (refcount != 0)\n");
331                 /* We have subtitles. First copy the picture to
332                  * the spare direct buffer, then render the
333                  * subtitles. */
334                 vout_CopyPicture( p_pic, PP_OUTPUTPICTURE[0] );
335
336                 vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
337
338                 return PP_OUTPUTPICTURE[0];
339             }
340
341             /* No subtitles, picture is in a directbuffer so
342              * we can display it directly even if it is still
343              * in use. */
344                     //printf("direct (refcount == 0)\n");
345             return p_pic;
346         }
347
348         /* Picture is in a direct buffer but isn't used by the
349          * decoder. We can safely render subtitles on it and
350          * display it. */
351                     //printf("direct (refcount == 0)\n");
352         vout_RenderSubPictures( p_vout, p_pic, p_subpic );
353
354         return p_pic;
355     }
356
357     /* Not a direct buffer. We either need to copy it to a direct buffer,
358      * or render it if the chroma isn't the same. */
359     if( p_vout->b_direct )
360     {
361         /* Picture is not in a direct buffer, but is exactly the
362          * same size as the direct buffers. A memcpy() is enough,
363          * then render the subtitles. */
364                     //printf("memcpy (not a direct buffer)\n");
365         vout_CopyPicture( p_pic, PP_OUTPUTPICTURE[0] );
366
367         vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic );
368
369         return PP_OUTPUTPICTURE[0];
370     }
371
372     /* Picture is not in a direct buffer, and needs to be converted to
373      * another size/chroma. Then the subtitles need to be rendered as
374      * well. */
375
376     /* This usually means software YUV, or hardware YUV with a
377      * different chroma. */
378
379     /* XXX: render to the first direct buffer */
380                     //printf("render (not a direct buffer)\n");
381     p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] );
382
383     vout_RenderSubPictures( p_vout, p_pic, p_subpic );
384
385     return &p_vout->p_picture[0];
386 }
387
388 /*****************************************************************************
389  * vout_PlacePicture: calculate image window coordinates
390  *****************************************************************************
391  * This function will be accessed by plugins. It calculates the relative
392  * position of the output window and the image window.
393  *****************************************************************************/
394 void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height,
395                         int *pi_x, int *pi_y, int *pi_width, int *pi_height )
396 {
397     if( (i_width <= 0) || (i_height <=0) )
398     {
399         *pi_width = *pi_height = *pi_x = *pi_y = 0;
400
401         return;
402     }
403
404     if( p_vout->b_scale )
405     {
406         *pi_width = i_width;
407         *pi_height = i_height;
408     }
409     else
410     {
411         *pi_width = MIN( i_width, p_vout->render.i_width );
412         *pi_height = MIN( i_height, p_vout->render.i_height );
413     }
414
415     if( VOUT_ASPECT_FACTOR * *pi_width / *pi_height < p_vout->render.i_aspect )
416     {
417         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
418     }
419     else
420     {
421         *pi_height = *pi_width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
422     }
423
424     if( *pi_width > i_width )
425     {
426         *pi_width = i_width;
427         *pi_height = VOUT_ASPECT_FACTOR * *pi_width / p_vout->render.i_aspect;
428     }
429
430     if( *pi_height > i_height )
431     {
432         *pi_height = i_height;
433         *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
434     }
435
436     *pi_x = ( i_width - *pi_width ) / 2;
437     *pi_y = ( i_height - *pi_height ) / 2;
438 }
439
440 /*****************************************************************************
441  * vout_AllocatePicture: allocate a new picture in the heap.
442  *****************************************************************************
443  * This function allocates a fake direct buffer in memory, which can be
444  * used exactly like a video buffer. The video output thread then manages
445  * how it gets displayed.
446  *****************************************************************************/
447 void vout_AllocatePicture( picture_t *p_pic,
448                            int i_width, int i_height, u32 i_chroma )
449 {
450     int i_bytes, i_index;
451
452     /* Store default values */
453     for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
454     {
455         p_pic->p[i_index].p_pixels = NULL;
456         p_pic->p[i_index].b_margin = 0;
457         p_pic->p[i_index].i_pixel_bytes = 1;
458     }
459
460     /* Calculate coordinates */
461     switch( i_chroma )
462     {
463         case FOURCC_YV12:
464         case FOURCC_I420:
465         case FOURCC_IYUV:
466             p_pic->p[ Y_PLANE ].i_lines = i_height;
467             p_pic->p[ Y_PLANE ].i_pitch = i_width;
468             p_pic->p[ U_PLANE ].i_lines = i_height / 2;
469             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
470             p_pic->p[ V_PLANE ].i_lines = i_height / 2;
471             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
472             p_pic->i_planes = 3;
473             break;
474
475         case FOURCC_I422:
476             p_pic->p[ Y_PLANE ].i_lines = i_height;
477             p_pic->p[ Y_PLANE ].i_pitch = i_width;
478             p_pic->p[ U_PLANE ].i_lines = i_height;
479             p_pic->p[ U_PLANE ].i_pitch = i_width / 2;
480             p_pic->p[ V_PLANE ].i_lines = i_height;
481             p_pic->p[ V_PLANE ].i_pitch = i_width / 2;
482             p_pic->i_planes = 3;
483             break;
484
485         case FOURCC_I444:
486             p_pic->p[ Y_PLANE ].i_lines = i_height;
487             p_pic->p[ Y_PLANE ].i_pitch = i_width;
488             p_pic->p[ U_PLANE ].i_lines = i_height;
489             p_pic->p[ U_PLANE ].i_pitch = i_width;
490             p_pic->p[ V_PLANE ].i_lines = i_height;
491             p_pic->p[ V_PLANE ].i_pitch = i_width;
492             p_pic->i_planes = 3;
493             break;
494
495         case FOURCC_Y211:
496             p_pic->p->i_lines = i_height;
497             p_pic->p->i_pitch = i_width;
498             p_pic->p->i_pixel_bytes = 4;
499             p_pic->i_planes = 1;
500             break;
501
502         case FOURCC_RV15:
503             p_pic->p->i_lines = i_height;
504             p_pic->p->i_pitch = i_width * 2;
505             p_pic->p->i_pixel_bytes = 2;
506             p_pic->p->i_red_mask =   0x001f;
507             p_pic->p->i_green_mask = 0x03e0;
508             p_pic->p->i_blue_mask =  0x7c00;
509             p_pic->i_planes = 1;
510             break;
511
512         case FOURCC_RV16:
513             p_pic->p->i_lines = i_height;
514             p_pic->p->i_pitch = i_width * 2;
515             p_pic->p->i_pixel_bytes = 2;
516             p_pic->p->i_red_mask =   0x001f;
517             p_pic->p->i_green_mask = 0x07e0;
518             p_pic->p->i_blue_mask =  0xf800;
519             p_pic->i_planes = 1;
520             break;
521
522         case FOURCC_RV32:
523             p_pic->p->i_lines = i_height;
524             p_pic->p->i_pitch = i_width * 4;
525             p_pic->p->i_pixel_bytes = 4;
526             p_pic->p->i_red_mask =   0xff0000;
527             p_pic->p->i_green_mask = 0x00ff00;
528             p_pic->p->i_blue_mask =  0x0000ff;
529             p_pic->i_planes = 1;
530             break;
531
532         default:
533             intf_ErrMsg( "vout error: unknown chroma type 0x%.8x (%4.4s)",
534                          i_chroma, (char*)&i_chroma );
535             p_pic->i_planes = 0;
536             return;
537     }
538
539     /* Calculate how big the new image should be */
540     for( i_bytes = 0, i_index = 0; i_index < p_pic->i_planes; i_index++ )
541     {
542         i_bytes += p_pic->p[ i_index ].i_lines * p_pic->p[ i_index ].i_pitch;
543     }
544
545     p_pic->p_data = memalign( 16, i_bytes );
546
547     if( p_pic->p_data == NULL )
548     {
549         p_pic->i_planes = 0;
550         return;
551     }
552
553     /* Fill the p_pixels field for each plane */
554     p_pic->p[ 0 ].p_pixels = p_pic->p_data;
555
556     for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
557     {
558         p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels
559                                           + p_pic->p[i_index-1].i_lines
560                                              * p_pic->p[i_index-1].i_pitch;
561     }
562 }
563