1 /*******************************************************************************
2 * video_output.c : video output thread
4 *******************************************************************************
5 * This module describes the programming interface for video output threads.
6 * It includes functions allowing to open a new thread, send pictures to a
7 * thread, and destroy a previously oppenned video output thread.
8 *******************************************************************************/
10 /*******************************************************************************
12 *******************************************************************************/
25 #include "vlc_thread.h"
27 #include "video_output.h"
28 #include "video_sys.h"
32 /*******************************************************************************
34 *******************************************************************************/
36 /* CLIP_BYTE: return value if between 0 and 255, else return nearest boundary
38 #define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
40 /* YUV_GRAYSCALE: parametric macro for YUV grayscale transformation.
41 * Due to the high performance need of this loop, all possible conditions
42 * evaluations are made outside the transformation loop. However, the code does
43 * not change much for two different loops. This macro allows to change slightly
44 * the content of the loop without having to copy and paste code. It is used in
45 * RenderYUVPicture function. */
46 #define YUV_GRAYSCALE( TRANS_RED, TRANS_GREEN, TRANS_BLUE, P_PIC ) \
48 for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \
50 for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x++) \
53 *P_PIC++ = TRANS_RED[i_y] | TRANS_GREEN[i_y] | TRANS_BLUE[i_y]; \
55 /* Skip until beginning of next line */ \
56 P_PIC += i_eol_offset; \
59 /* YUV_TRANSFORM: parametric macro for YUV transformation.
60 * Due to the high performance need of this loop, all possible conditions
61 * evaluations are made outside the transformation loop. However, the code does
62 * not change much for two different loops. This macro allows to change slightly
63 * the content of the loop without having to copy and paste code. It is used in
64 * RenderYUVPicture function. */
65 #define YUV_TRANSFORM( CHROMA, TRANS_RED, TRANS_GREEN, TRANS_BLUE, P_PIC ) \
67 for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \
69 for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2) \
71 /* First sample (complete) */ \
72 i_y = 76309 * *p_y++ - 1188177; \
76 TRANS_RED [(i_y+i_crv*i_v) >>16] | \
77 TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
78 TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
79 i_y = 76309 * *p_y++ - 1188177; \
80 /* Second sample (partial) */ \
87 TRANS_RED [(i_y+i_crv*i_v) >>16] | \
88 TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
89 TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
91 if( (CHROMA == 420) && !(i_pic_y & 0x1) ) \
93 p_u -= i_chroma_width; \
94 p_v -= i_chroma_width; \
96 /* Skip until beginning of next line */ \
97 P_PIC += i_eol_offset; \
100 /*******************************************************************************
102 *******************************************************************************/
104 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
105 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
107 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
108 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
109 {104597, 132201, 25675, 53279}, /* unspecified */
110 {104597, 132201, 25675, 53279}, /* reserved */
111 {104448, 132798, 24759, 53109}, /* FCC */
112 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
113 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
114 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
117 /*******************************************************************************
118 * External prototypes
119 *******************************************************************************/
121 /* YUV transformations for MMX - in yuv-mmx.S
122 * p_y, p_u, p_v: Y U and V planes
123 * i_width, i_height: frames dimensions (pixels)
124 * i_ypitch, i_vpitch: Y and V lines sizes (bytes)
125 * i_aspect: vertical aspect factor
127 * i_dci_offset: ?? x offset for left image border
128 * i_offset_to_line_0: ?? x offset for left image border
129 * i_pitch: RGB line size (bytes)
130 * i_colortype: 0 for 565, 1 for 555 */
131 void vout_YUV420_16_MMX( u8* p_y, u8* p_u, u8 *p_v,
132 unsigned int i_width, unsigned int i_height,
133 unsigned int i_ypitch, unsigned int i_vpitch,
134 unsigned int i_aspect, u8 *pi_pic,
135 u32 i_dci_offset, u32 i_offset_to_line_0,
136 int CCOPitch, int i_colortype );
139 /*******************************************************************************
141 *******************************************************************************/
142 static int InitThread ( vout_thread_t *p_vout );
143 static void RunThread ( vout_thread_t *p_vout );
144 static void ErrorThread ( vout_thread_t *p_vout );
145 static void EndThread ( vout_thread_t *p_vout );
146 static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
147 static void RenderYUVGrayPicture ( vout_thread_t *p_vout, picture_t *p_pic );
148 static void RenderYUV16Picture ( vout_thread_t *p_vout, picture_t *p_pic );
149 static void RenderYUV32Picture ( vout_thread_t *p_vout, picture_t *p_pic );
150 static void RenderInfo ( vout_thread_t *p_vout );
152 /*******************************************************************************
153 * vout_CreateThread: creates a new video output thread
154 *******************************************************************************
155 * This function creates a new video output thread, and returns a pointer
156 * to its description. On error, it returns NULL.
157 * If pi_status is NULL, then the function will block until the thread is ready.
158 * If not, it will be updated using one of the THREAD_* constants.
159 *******************************************************************************/
160 vout_thread_t * vout_CreateThread (
162 char *psz_display, Window root_window,
164 int i_width, int i_height, int *pi_status
167 vout_thread_t * p_vout; /* thread descriptor */
168 int i_status; /* thread status */
170 /* Allocate descriptor */
171 p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
174 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
178 /* Initialize some fields used by the system-dependant method - these fields will
179 * probably be modified by the method */
185 p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
186 VOUT_GRAYSCALE_DEFAULT );
187 p_vout->i_width = i_width;
188 p_vout->i_height = i_height;
189 p_vout->i_bytes_per_line = i_width * 2;
190 p_vout->i_screen_depth = 15;
191 p_vout->i_bytes_per_pixel = 2;
192 p_vout->f_x_ratio = 1;
193 p_vout->f_y_ratio = 1;
194 intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
195 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
196 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
197 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
199 /* Create and initialize system-dependant method - this function issues its
200 * own error messages */
201 if( vout_SysCreate( p_vout
202 #if defined(VIDEO_X11)
203 , psz_display, root_window
210 intf_DbgMsg("actual configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
211 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
212 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
213 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
215 /* Terminate the initialization */
218 p_vout->b_active = 0;
219 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
220 *p_vout->pi_status = THREAD_CREATE;
223 p_vout->c_idle_loops = 0;
224 p_vout->c_pictures = 0;
227 /* Create thread and set locks */
228 vlc_mutex_init( &p_vout->lock );
229 if( vlc_thread_create( &p_vout->thread_id, "video output",
230 (void *) RunThread, (void *) p_vout) )
232 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
233 vout_SysDestroy( p_vout );
238 intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
239 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
241 /* If status is NULL, wait until the thread is created */
242 if( pi_status == NULL )
246 msleep( THREAD_SLEEP );
247 }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
248 && (i_status != THREAD_FATAL) );
249 if( i_status != THREAD_READY )
257 /*******************************************************************************
258 * vout_DestroyThread: destroys a previously created thread
259 *******************************************************************************
260 * Destroy a terminated thread.
261 * The function will request a destruction of the specified thread. If pi_error
262 * is NULL, it will return once the thread is destroyed. Else, it will be
263 * update using one of the THREAD_* constants.
264 *******************************************************************************/
265 void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
267 int i_status; /* thread status */
270 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
271 *p_vout->pi_status = THREAD_DESTROY;
273 /* Request thread destruction */
276 /* If status is NULL, wait until thread has been destroyed */
277 if( pi_status == NULL )
281 msleep( THREAD_SLEEP );
282 }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
283 && (i_status != THREAD_FATAL) );
287 /*******************************************************************************
288 * vout_DisplayPicture: display a picture
289 *******************************************************************************
290 * Remove the reservation flag of a picture, which will cause it to be ready for
292 *******************************************************************************/
293 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
296 char psz_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
299 vlc_mutex_lock( &p_vout->lock );
302 /* Check if picture status is valid */
303 if( p_pic->i_status != RESERVED_PICTURE )
305 intf_DbgMsg("error: picture %d has invalid status %d\n",
306 p_pic, p_pic->i_status );
310 /* Remove reservation flag */
311 p_pic->i_status = READY_PICTURE;
315 p_vout->c_pictures++;
319 /* Send picture informations */
320 intf_DbgMsg("picture %p: type=%d, %dx%d, date=%s\n", p_pic, p_pic->i_type,
321 p_pic->i_width,p_pic->i_height, mstrtime( psz_date, p_pic->date ) );
324 vlc_mutex_unlock( &p_vout->lock );
327 /*******************************************************************************
328 * vout_CreatePicture: allocate a picture in the video output heap.
329 *******************************************************************************
330 * This function create a reserved image in the video output heap.
331 * A null pointer is returned if the function fails. This method provides an
332 * already allocated zone of memory in the picture data fields.
333 *******************************************************************************/
334 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
335 int i_width, int i_height, int i_bytes_per_line )
337 int i_picture; /* picture index */
338 picture_t * p_free_picture = NULL; /* first free picture */
339 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
342 vlc_mutex_lock( &p_vout->lock );
345 * Look for an empty place
348 i_picture < VOUT_MAX_PICTURES;
351 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
353 /* Picture is marked for destruction, but is still allocated */
354 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
355 (p_vout->p_picture[i_picture].i_height == i_height) &&
356 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
358 /* Memory size do match : memory will not be reallocated, and function
359 * can end immediately - this is the best possible case, since no
360 * memory allocation needs to be done */
361 p_vout->p_picture[i_picture].i_width = i_width;
362 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
364 intf_DbgMsg("picture %p (in destroyed picture slot)\n",
365 &p_vout->p_picture[i_picture] );
367 vlc_mutex_unlock( &p_vout->lock );
368 return( &p_vout->p_picture[i_picture] );
370 else if( p_destroyed_picture == NULL )
372 /* Memory size do not match, but picture index will be kept in
373 * case no other place are left */
374 p_destroyed_picture = &p_vout->p_picture[i_picture];
377 else if( (p_free_picture == NULL) &&
378 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
380 /* Picture is empty and ready for allocation */
381 p_free_picture = &p_vout->p_picture[i_picture];
385 /* If no free picture is available, use a destroyed picture */
386 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
388 /* No free picture or matching destroyed picture has been found, but
389 * a destroyed picture is still avalaible */
390 free( p_destroyed_picture->p_data );
391 p_free_picture = p_destroyed_picture;
397 if( p_free_picture != NULL )
399 /* Allocate memory */
402 case YUV_420_PICTURE: /* YUV picture: bits per pixel */
403 case YUV_422_PICTURE:
404 case YUV_444_PICTURE:
405 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
406 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
407 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
408 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
412 intf_DbgMsg("error: unknown picture type %d\n", i_type );
413 p_free_picture->p_data = NULL;
418 if( p_free_picture->p_data != NULL )
420 /* Copy picture informations */
421 p_free_picture->i_type = i_type;
422 p_free_picture->i_status = RESERVED_PICTURE;
423 p_free_picture->i_width = i_width;
424 p_free_picture->i_height = i_height;
425 p_free_picture->i_bytes_per_line = i_bytes_per_line;
426 p_free_picture->i_refcount = 0;
427 p_free_picture->i_matrix_coefficients = 1;
431 /* Memory allocation failed : set picture as empty */
432 p_free_picture->i_type = EMPTY_PICTURE;
433 p_free_picture->i_status = FREE_PICTURE;
434 p_free_picture = NULL;
435 intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
439 intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture );
441 vlc_mutex_unlock( &p_vout->lock );
442 return( p_free_picture );
445 // No free or destroyed picture could be found
446 intf_DbgMsg( "warning: heap is full\n" );
447 vlc_mutex_unlock( &p_vout->lock );
451 /*******************************************************************************
452 * vout_DestroyPicture: remove a permanent or reserved picture from the heap
453 *******************************************************************************
454 * This function frees a previously reserved picture or a permanent
455 * picture. It is meant to be used when the construction of a picture aborted.
456 * Note that the picture will be destroyed even if it is linked !
457 *******************************************************************************/
458 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
460 vlc_mutex_lock( &p_vout->lock );
463 /* Check if picture status is valid */
464 if( p_pic->i_status != RESERVED_PICTURE )
466 intf_DbgMsg("error: picture %d has invalid status %d\n",
467 p_pic, p_pic->i_status );
471 p_pic->i_status = DESTROYED_PICTURE;
474 intf_DbgMsg("picture %p\n", p_pic);
477 vlc_mutex_unlock( &p_vout->lock );
480 /*******************************************************************************
481 * vout_LinkPicture: increment reference counter of a picture
482 *******************************************************************************
483 * This function increment the reference counter of a picture in the video
485 *******************************************************************************/
486 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
488 vlc_mutex_lock( &p_vout->lock );
492 intf_DbgMsg("picture %p\n", p_pic);
495 vlc_mutex_unlock( &p_vout->lock );
498 /*******************************************************************************
499 * vout_UnlinkPicture: decrement reference counter of a picture
500 *******************************************************************************
501 * This function decrement the reference counter of a picture in the video heap.
502 *******************************************************************************/
503 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
505 vlc_mutex_lock( &p_vout->lock );
507 if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
509 p_pic->i_status = DESTROYED_PICTURE;
513 intf_DbgMsg("picture %p\n", p_pic);
516 vlc_mutex_unlock( &p_vout->lock );
519 /* following functions are local */
521 /*******************************************************************************
522 * InitThread: initialize video output thread
523 *******************************************************************************
524 * This function is called from RunThread and performs the second step of the
525 * initialization. It returns 0 on success. Note that the thread's flag are not
526 * modified inside this function.
527 *******************************************************************************/
528 static int InitThread( vout_thread_t *p_vout )
530 int i_index; /* generic index */
531 int i_pixel_size; /* pixel size, in bytes, for translations tables */
534 *p_vout->pi_status = THREAD_START;
536 /* Initialize pictures */
537 p_vout->i_pictures = 0;
538 for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
540 p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
541 p_vout->p_picture[i_index].i_status= FREE_PICTURE;
545 /* Initialize FPS index - since samples won't be used until a minimum of
546 * pictures, they don't need to be initialized */
547 p_vout->i_fps_index = 0;
550 /* Initialize output method - this function issues its own error messages */
551 if( vout_SysInit( p_vout ) )
553 *p_vout->pi_status = THREAD_ERROR;
557 /* Allocate translation tables */
558 switch( p_vout->i_bytes_per_pixel )
560 case 2: /* 15 or 16 bpp, use 16 bits translations tables */
561 i_pixel_size = sizeof( u16 );
563 case 3: /* 24 or 32 bpp, use 32 bits translations tables */
568 i_pixel_size = sizeof( u32 );
572 intf_DbgMsg("error: invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel );
573 i_pixel_size = sizeof( u32 );
577 p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
578 (u16 *)malloc( 1024 * i_pixel_size );
579 p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
580 (u16 *)malloc( 1024 * i_pixel_size );
581 p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
582 (u16 *)malloc( 1024 * i_pixel_size );
583 if( (p_vout->pi_trans16_red == NULL) ||
584 (p_vout->pi_trans16_green == NULL ) ||
585 (p_vout->pi_trans16_blue == NULL ) )
587 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
588 *p_vout->pi_status = THREAD_ERROR;
589 if( p_vout->pi_trans16_red != NULL )
591 free( p_vout->pi_trans16_red );
593 if( p_vout->pi_trans16_green != NULL )
595 free( p_vout->pi_trans16_green );
597 if( p_vout->pi_trans16_blue != NULL )
599 free( p_vout->pi_trans16_blue );
604 /* Translate translation tables */
605 p_vout->pi_trans16_red += 384;
606 p_vout->pi_trans16_green += 384;
607 p_vout->pi_trans16_blue += 384;
608 p_vout->pi_trans32_red += 384;
609 p_vout->pi_trans32_green += 384;
610 p_vout->pi_trans32_blue += 384;
612 /* Build translation tables */
613 switch( p_vout->i_screen_depth )
616 for( i_index = -384; i_index < 640; i_index++)
618 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
619 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
620 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
624 for( i_index = -384; i_index < 640; i_index++)
626 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
627 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xfc)<<3;
628 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
633 for( i_index = -384; i_index < 640; i_index++)
635 p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
636 p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
637 p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
642 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
647 /* Mark thread as running and return */
648 p_vout->b_active = 1;
649 *p_vout->pi_status = THREAD_READY;
650 intf_DbgMsg("thread ready\n");
654 /*******************************************************************************
655 * RunThread: video output thread
656 *******************************************************************************
657 * Video output thread. This function does only returns when the thread is
658 * terminated. It handles the pictures arriving in the video heap and the
659 * display device events.
660 *******************************************************************************/
661 static void RunThread( vout_thread_t *p_vout)
663 int i_picture; /* picture index */
664 int i_err; /* error code */
665 mtime_t current_date; /* current date */
666 picture_t * p_pic; /* picture pointer */
667 mtime_t pic_date = 0; /* picture date */
670 * Initialize thread and free configuration
672 p_vout->b_error = InitThread( p_vout );
673 if( p_vout->b_error )
675 free( p_vout ); /* destroy descriptor */
680 * Main loop - it is not executed if an error occured during
683 while( (!p_vout->b_die) && (!p_vout->b_error) )
686 * Find the picture to display - this is the only operation requiring
687 * the lock on the picture, since once a READY_PICTURE has been found,
688 * it can't be modified by the other threads (except if it is unliked,
689 * but its data remains)
692 vlc_mutex_lock( &p_vout->lock );
693 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
695 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
697 (p_vout->p_picture[i_picture].date < pic_date) ) )
699 p_pic = &p_vout->p_picture[i_picture];
700 pic_date = p_pic->date;
703 vlc_mutex_unlock( &p_vout->lock );
706 * Render picture if any
711 /* Computes FPS rate */
712 p_vout->fps_sample[ p_vout->i_fps_index++ ] = pic_date;
713 if( p_vout->i_fps_index == VOUT_FPS_SAMPLES )
715 p_vout->i_fps_index = 0;
718 current_date = mdate();
719 if( pic_date < current_date )
721 /* Picture is late: it will be destroyed and the thread will go
722 * immediately to next picture */
723 vlc_mutex_lock( &p_vout->lock );
724 if( p_pic->i_refcount )
726 p_pic->i_status = DISPLAYED_PICTURE;
730 p_pic->i_status = DESTROYED_PICTURE;
734 intf_DbgMsg( "warning: late picture %p skipped\n", p_pic );
736 vlc_mutex_unlock( &p_vout->lock );
739 else if( pic_date > current_date + VOUT_DISPLAY_DELAY )
741 /* A picture is ready to be rendered, but its rendering date is
742 * far from the current one so the thread will perform an empty loop
743 * as if no picture were found. The picture state is unchanged */
748 /* Picture has not yet been displayed, and has a valid display
749 * date : render it, then forget it */
750 RenderPicture( p_vout, p_pic );
751 vlc_mutex_lock( &p_vout->lock );
752 if( p_pic->i_refcount )
754 p_pic->i_status = DISPLAYED_PICTURE;
758 p_pic->i_status = DESTROYED_PICTURE;
760 vlc_mutex_unlock( &p_vout->lock );
762 /* Print additional informations */
765 RenderInfo( p_vout );
771 * Check events, sleep and display picture
773 i_err = vout_SysManage( p_vout );
776 /* A fatal error occured, and the thread must terminate immediately,
777 * without displaying anything - setting b_error to 1 cause the
778 * immediate end of the main while() loop. */
785 /* A picture is ready to be displayed : sleep until its display date */
790 vout_SysDisplay( p_vout );
795 /* Sleep to wait for new pictures */
796 msleep( VOUT_IDLE_SLEEP );
798 /* Update counters */
799 p_vout->c_idle_loops++;
805 /* Update counters */
813 if( p_vout->b_error )
815 ErrorThread( p_vout );
820 intf_DbgMsg( "thread end\n" );
823 /*******************************************************************************
824 * ErrorThread: RunThread() error loop
825 *******************************************************************************
826 * This function is called when an error occured during thread main's loop. The
827 * thread can still receive feed, but must be ready to terminate as soon as
829 *******************************************************************************/
830 static void ErrorThread( vout_thread_t *p_vout )
832 /* Wait until a `die' order */
833 while( !p_vout->b_die )
836 msleep( VOUT_IDLE_SLEEP );
840 /*******************************************************************************
841 * EndThread: thread destruction
842 *******************************************************************************
843 * This function is called when the thread ends after a sucessfull
845 *******************************************************************************/
846 static void EndThread( vout_thread_t *p_vout )
848 int * pi_status; /* thread status */
852 pi_status = p_vout->pi_status;
853 *pi_status = THREAD_END;
855 /* Destroy all remaining pictures */
856 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
858 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
860 free( p_vout->p_picture[i_picture].p_data );
864 /* Destroy translation tables - remeber these tables are translated */
865 free( p_vout->pi_trans16_red - 384 );
866 free( p_vout->pi_trans16_green - 384 );
867 free( p_vout->pi_trans16_blue - 384 );
869 /* Destroy thread structures allocated by InitThread */
870 vout_SysEnd( p_vout );
871 vout_SysDestroy( p_vout );
875 *pi_status = THREAD_OVER;
878 /*******************************************************************************
879 * RenderPicture: render a picture
880 *******************************************************************************
881 * This function convert a picture from a video heap to a pixel-encoded image
882 * and copy it to the current rendering buffer. No lock is required, since the
883 * rendered picture has been determined as existant, and will only be destroyed
884 * by the vout thread later.
885 * ???? 24 and 32 bpp should probably be separated
886 *******************************************************************************/
887 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
890 /* Send picture informations */
891 intf_DbgMsg("picture %p\n", p_pic );
893 /* Store rendering start date */
894 p_vout->picture_render_time = mdate();
897 switch( p_pic->i_type )
899 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
900 case YUV_422_PICTURE:
901 case YUV_444_PICTURE:
902 if( p_vout->b_grayscale ) /* grayscale */
904 RenderYUVGrayPicture( p_vout, p_pic );
906 else if( p_vout->i_bytes_per_pixel == 2 ) /* color 15 or 16 bpp */
908 RenderYUV16Picture( p_vout, p_pic );
910 else /* color 24 or 32 bpp */
912 RenderYUV32Picture( p_vout, p_pic );
917 intf_DbgMsg("error: unknown picture type %d\n", p_pic->i_type );
923 /* Computes rendering time */
924 p_vout->picture_render_time = mdate() - p_vout->picture_render_time;
928 /*******************************************************************************
929 * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale
930 *******************************************************************************
931 * Performs the YUV convertion. The picture sent to this function should only
932 * have YUV_420, YUV_422 or YUV_444 types.
933 *******************************************************************************/
934 static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic )
936 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
937 int i_width, i_height; /* picture size */
938 int i_eol_offset; /* pixels from end of line to next line */
939 yuv_data_t *p_y; /* Y data base adress */
940 yuv_data_t i_y; /* Y sample */
941 u16 * pi_pic16; /* destination picture, 15 or 16 bpp */
942 u32 * pi_pic32; /* destination picture, 24 or 32 bpp */
943 u16 * pi_trans16_red; /* red transformation table */
944 u16 * pi_trans16_green; /* green transformation table */
945 u16 * pi_trans16_blue; /* blue transformation table */
946 u32 * pi_trans32_red; /* red transformation table */
947 u32 * pi_trans32_green; /* green transformation table */
948 u32 * pi_trans32_blue; /* blue transformation table */
950 /* Set the base pointers and transformation parameters */
952 i_width = p_pic->i_width;
953 i_height = p_pic->i_height;
954 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
956 /* Get base adress for destination image and translation tables, then
958 switch( p_vout->i_screen_depth )
962 pi_trans16_red = p_vout->pi_trans16_red;
963 pi_trans16_green = p_vout->pi_trans16_green;
964 pi_trans16_blue = p_vout->pi_trans16_blue;
965 pi_pic16 = (u16 *) vout_SysGetPicture( p_vout );
967 YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue,
972 pi_trans32_red = p_vout->pi_trans32_red;
973 pi_trans32_green = p_vout->pi_trans32_green;
974 pi_trans32_blue = p_vout->pi_trans32_blue;
975 pi_pic32 = (u32 *) vout_SysGetPicture( p_vout );
977 YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue,
982 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
989 /*******************************************************************************
990 * RenderYUV16Picture: render a 15 or 16 bpp YUV picture
991 *******************************************************************************
992 * Performs the YUV convertion. The picture sent to this function should only
993 * have YUV_420, YUV_422 or YUV_444 types.
994 *******************************************************************************/
995 static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic )
997 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
998 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
999 int i_y, i_u, i_v; /* Y, U and V samples */
1000 int i_width, i_height; /* picture size */
1001 int i_chroma_width; /* chroma width */
1002 int i_eol_offset; /* pixels from end of line to next line */
1003 yuv_data_t *p_y; /* Y data base adress */
1004 yuv_data_t *p_u; /* U data base adress */
1005 yuv_data_t *p_v; /* V data base adress */
1006 u16 * pi_pic; /* base adress for destination picture */
1007 u16 * pi_trans_red; /* red transformation table */
1008 u16 * pi_trans_green; /* green transformation table */
1009 u16 * pi_trans_blue; /* blue transformation table */
1011 /* Choose transformation matrix coefficients */
1012 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1013 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1014 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1015 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1017 /* Choose the conversions tables */
1018 pi_trans_red = p_vout->pi_trans16_red;
1019 pi_trans_green = p_vout->pi_trans16_green;
1020 pi_trans_blue = p_vout->pi_trans16_blue;
1022 /* Set the base pointers and transformation parameters */
1026 i_width = p_pic->i_width;
1027 i_height = p_pic->i_height;
1028 i_chroma_width = i_width / 2;
1029 i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width;
1031 /* Get base adress for destination image */
1032 pi_pic = (u16 *)vout_SysGetPicture( p_vout );
1034 /* Do YUV transformation - the loops are repeated for optimization */
1035 switch( p_pic->i_type )
1037 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
1039 vout_YUV420_16_MMX( p_y, p_u, p_v,
1041 i_width, i_chroma_width,
1043 0, 0, p_vout->i_bytes_per_line,
1044 p_vout->i_screen_depth == 15 );
1053 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
1060 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
1070 /*******************************************************************************
1071 * RenderYUV32Picture: render a 24 or 32 bpp YUV picture
1072 *******************************************************************************
1073 * Performs the YUV convertion. The picture sent to this function should only
1074 * have YUV_420, YUV_422 or YUV_444 types.
1075 *******************************************************************************/
1076 static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic )
1078 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
1079 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
1080 int i_y, i_u, i_v; /* Y, U and V samples */
1081 int i_width, i_height; /* picture size */
1082 int i_chroma_width; /* chroma width */
1083 int i_eol_offset; /* pixels from end of line to next line */
1084 yuv_data_t *p_y; /* Y data base adress */
1085 yuv_data_t *p_u; /* U data base adress */
1086 yuv_data_t *p_v; /* V data base adress */
1087 u32 * pi_pic; /* base adress for destination picture */
1088 u32 * pi_trans_red; /* red transformation table */
1089 u32 * pi_trans_green; /* green transformation table */
1090 u32 * pi_trans_blue; /* blue transformation table */
1092 /* Choose transformation matrix coefficients */
1093 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1094 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1095 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1096 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1098 /* Choose the conversions tables */
1099 pi_trans_red = p_vout->pi_trans32_red;
1100 pi_trans_green = p_vout->pi_trans32_green;
1101 pi_trans_blue = p_vout->pi_trans32_blue;
1103 /* Set the base pointers and transformation parameters */
1107 i_width = p_pic->i_width;
1108 i_height = p_pic->i_height;
1109 i_chroma_width = i_width / 2;
1110 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
1112 /* Get base adress for destination image */
1113 pi_pic = (u32 *)vout_SysGetPicture( p_vout );
1115 /* Do YUV transformation - the loops are repeated for optimization */
1116 switch( p_pic->i_type )
1118 case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */
1125 case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */
1132 case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */
1142 /*******************************************************************************
1143 * RenderInfo: print additionnal informations on a picture
1144 *******************************************************************************
1145 * This function will add informations such as fps and buffer size on a picture
1146 *******************************************************************************/
1147 static void RenderInfo( vout_thread_t *p_vout )
1149 char psz_buffer[256]; /* string buffer */
1152 /* Print FPS rate */
1153 if( p_vout->c_pictures > VOUT_FPS_SAMPLES )
1155 sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 /
1156 ( p_vout->fps_sample[ (p_vout->i_fps_index + (VOUT_FPS_SAMPLES - 1)) %
1157 VOUT_FPS_SAMPLES ] -
1158 p_vout->fps_sample[ p_vout->i_fps_index ] ) );
1159 vout_SysPrint( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer );
1162 /* Print statistics */
1163 sprintf( psz_buffer, "%ld pictures, %.1f %% idle loops", p_vout->c_pictures,
1164 (double) p_vout->c_idle_loops * 100 / p_vout->c_loops );
1165 vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
1169 /* Print heap size */
1170 sprintf( psz_buffer, "video heap size: %d (%.1f %%)", p_vout->i_pictures,
1171 (double) p_vout->i_pictures * 100 / VOUT_MAX_PICTURES );
1172 vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
1176 /* Print rendering statistics */
1177 sprintf( psz_buffer, "picture rendering time: %lu us",
1178 (unsigned long) p_vout->picture_render_time );
1179 vout_SysPrint( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );