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 *******************************************************************************/
19 #include <X11/Xlib.h> /* for video_sys.h in X11 mode */
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
37 * (0 or 255), used to build translations tables */
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 );
151 static int RenderIdle ( vout_thread_t *p_vout, int i_level );
153 /*******************************************************************************
154 * vout_CreateThread: creates a new video output thread
155 *******************************************************************************
156 * This function creates a new video output thread, and returns a pointer
157 * to its description. On error, it returns NULL.
158 * If pi_status is NULL, then the function will block until the thread is ready.
159 * If not, it will be updated using one of the THREAD_* constants.
160 *******************************************************************************/
161 vout_thread_t * vout_CreateThread (
163 char *psz_display, Window root_window,
165 int i_width, int i_height, int *pi_status
168 vout_thread_t * p_vout; /* thread descriptor */
169 int i_status; /* thread status */
171 /* Allocate descriptor */
172 p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
175 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
179 /* Initialize some fields used by the system-dependant method - these fields will
180 * probably be modified by the method */
186 p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
187 VOUT_GRAYSCALE_DEFAULT );
188 p_vout->i_width = i_width;
189 p_vout->i_height = i_height;
190 p_vout->i_bytes_per_line = i_width * 2;
191 p_vout->i_screen_depth = 15;
192 p_vout->i_bytes_per_pixel = 2;
193 p_vout->f_x_ratio = 1;
194 p_vout->f_y_ratio = 1;
195 intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
196 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
197 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
198 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
200 /* Create and initialize system-dependant method - this function issues its
201 * own error messages */
202 if( vout_SysCreate( p_vout
203 #if defined(VIDEO_X11)
204 , psz_display, root_window
211 intf_DbgMsg("actual configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
212 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
213 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
214 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
216 /* Terminate the initialization */
219 p_vout->b_active = 0;
220 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
221 *p_vout->pi_status = THREAD_CREATE;
224 p_vout->c_idle_loops = 0;
225 p_vout->c_fps_samples = 0;
228 /* Create thread and set locks */
229 vlc_mutex_init( &p_vout->lock );
230 if( vlc_thread_create( &p_vout->thread_id, "video output",
231 (void *) RunThread, (void *) p_vout) )
233 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
234 vout_SysDestroy( p_vout );
239 intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
240 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
242 /* If status is NULL, wait until the thread is created */
243 if( pi_status == NULL )
247 msleep( THREAD_SLEEP );
248 }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
249 && (i_status != THREAD_FATAL) );
250 if( i_status != THREAD_READY )
258 /*******************************************************************************
259 * vout_DestroyThread: destroys a previously created thread
260 *******************************************************************************
261 * Destroy a terminated thread.
262 * The function will request a destruction of the specified thread. If pi_error
263 * is NULL, it will return once the thread is destroyed. Else, it will be
264 * update using one of the THREAD_* constants.
265 *******************************************************************************/
266 void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
268 int i_status; /* thread status */
271 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
272 *p_vout->pi_status = THREAD_DESTROY;
274 /* Request thread destruction */
277 /* If status is NULL, wait until thread has been destroyed */
278 if( pi_status == NULL )
282 msleep( THREAD_SLEEP );
283 }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
284 && (i_status != THREAD_FATAL) );
288 /*******************************************************************************
289 * vout_DisplayPicture: display a picture
290 *******************************************************************************
291 * Remove the reservation flag of a picture, which will cause it to be ready for
292 * display. The picture does not need to be locked, since it is ignored by
293 * the output thread if is reserved.
294 *******************************************************************************/
295 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
298 char psz_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
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", p_pic, p_pic->i_status );
309 /* Remove reservation flag */
310 p_pic->i_status = READY_PICTURE;
313 /* Send picture informations */
314 intf_DbgMsg("picture %p: type=%d, %dx%d, date=%s\n", p_pic, p_pic->i_type,
315 p_pic->i_width,p_pic->i_height, mstrtime( psz_date, p_pic->date ) );
319 /*******************************************************************************
320 * vout_CreatePicture: allocate a picture in the video output heap.
321 *******************************************************************************
322 * This function create a reserved image in the video output heap.
323 * A null pointer is returned if the function fails. This method provides an
324 * already allocated zone of memory in the picture data fields. It needs locking
325 * since several pictures can be created by several producers threads.
326 *******************************************************************************/
327 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
328 int i_width, int i_height, int i_bytes_per_line )
330 int i_picture; /* picture index */
331 picture_t * p_free_picture = NULL; /* first free picture */
332 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
335 vlc_mutex_lock( &p_vout->lock );
338 * Look for an empty place
341 i_picture < VOUT_MAX_PICTURES;
344 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
346 /* Picture is marked for destruction, but is still allocated */
347 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
348 (p_vout->p_picture[i_picture].i_height == i_height) &&
349 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
351 /* Memory size do match : memory will not be reallocated, and function
352 * can end immediately - this is the best possible case, since no
353 * memory allocation needs to be done */
354 p_vout->p_picture[i_picture].i_width = i_width;
355 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
357 intf_DbgMsg("picture %p (in destroyed picture slot)\n",
358 &p_vout->p_picture[i_picture] );
360 vlc_mutex_unlock( &p_vout->lock );
361 return( &p_vout->p_picture[i_picture] );
363 else if( p_destroyed_picture == NULL )
365 /* Memory size do not match, but picture index will be kept in
366 * case no other place are left */
367 p_destroyed_picture = &p_vout->p_picture[i_picture];
370 else if( (p_free_picture == NULL) &&
371 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
373 /* Picture is empty and ready for allocation */
374 p_free_picture = &p_vout->p_picture[i_picture];
378 /* If no free picture is available, use a destroyed picture */
379 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
381 /* No free picture or matching destroyed picture has been found, but
382 * a destroyed picture is still avalaible */
383 free( p_destroyed_picture->p_data );
384 p_free_picture = p_destroyed_picture;
390 if( p_free_picture != NULL )
392 /* Allocate memory */
395 case YUV_420_PICTURE: /* YUV picture: bits per pixel */
396 case YUV_422_PICTURE:
397 case YUV_444_PICTURE:
398 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
399 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
400 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
401 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
405 intf_DbgMsg("error: unknown picture type %d\n", i_type );
406 p_free_picture->p_data = NULL;
411 if( p_free_picture->p_data != NULL )
413 /* Copy picture informations */
414 p_free_picture->i_type = i_type;
415 p_free_picture->i_status = RESERVED_PICTURE;
416 p_free_picture->i_width = i_width;
417 p_free_picture->i_height = i_height;
418 p_free_picture->i_bytes_per_line = i_bytes_per_line;
419 p_free_picture->i_refcount = 0;
420 p_free_picture->i_matrix_coefficients = 1;
424 /* Memory allocation failed : set picture as empty */
425 p_free_picture->i_type = EMPTY_PICTURE;
426 p_free_picture->i_status = FREE_PICTURE;
427 p_free_picture = NULL;
428 intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
432 intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture );
434 vlc_mutex_unlock( &p_vout->lock );
435 return( p_free_picture );
438 // No free or destroyed picture could be found
439 intf_DbgMsg( "warning: heap is full\n" );
440 vlc_mutex_unlock( &p_vout->lock );
444 /*******************************************************************************
445 * vout_DestroyPicture: remove a permanent or reserved picture from the heap
446 *******************************************************************************
447 * This function frees a previously reserved picture or a permanent
448 * picture. It is meant to be used when the construction of a picture aborted.
449 * Note that the picture will be destroyed even if it is linked !
450 * This function does not need locking since reserved pictures are ignored by
452 *******************************************************************************/
453 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
456 /* Check if picture status is valid */
457 if( p_pic->i_status != RESERVED_PICTURE )
459 intf_DbgMsg("error: picture %d has invalid status %d\n", p_pic, p_pic->i_status );
463 p_pic->i_status = DESTROYED_PICTURE;
466 intf_DbgMsg("picture %p\n", p_pic);
470 /*******************************************************************************
471 * vout_LinkPicture: increment reference counter of a picture
472 *******************************************************************************
473 * This function increment the reference counter of a picture in the video
474 * heap. It needs a lock since several producer threads can access the picture.
475 *******************************************************************************/
476 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
478 vlc_mutex_lock( &p_vout->lock );
480 vlc_mutex_unlock( &p_vout->lock );
483 intf_DbgMsg("picture %p\n", p_pic);
487 /*******************************************************************************
488 * vout_UnlinkPicture: decrement reference counter of a picture
489 *******************************************************************************
490 * This function decrement the reference counter of a picture in the video heap.
491 *******************************************************************************/
492 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
494 vlc_mutex_lock( &p_vout->lock );
496 if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
498 p_pic->i_status = DESTROYED_PICTURE;
500 vlc_mutex_unlock( &p_vout->lock );
503 intf_DbgMsg("picture %p\n", p_pic);
507 /* following functions are local */
509 /*******************************************************************************
510 * InitThread: initialize video output thread
511 *******************************************************************************
512 * This function is called from RunThread and performs the second step of the
513 * initialization. It returns 0 on success. Note that the thread's flag are not
514 * modified inside this function.
515 *******************************************************************************/
516 static int InitThread( vout_thread_t *p_vout )
518 int i_index; /* generic index */
519 int i_pixel_size; /* pixel size, in bytes, for translations tables */
522 *p_vout->pi_status = THREAD_START;
524 /* Initialize pictures */
525 for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
527 p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
528 p_vout->p_picture[i_index].i_status= FREE_PICTURE;
531 /* Initialize output method - this function issues its own error messages */
532 if( vout_SysInit( p_vout ) )
534 *p_vout->pi_status = THREAD_ERROR;
538 /* Allocate translation tables */
539 switch( p_vout->i_bytes_per_pixel )
541 case 2: /* 15 or 16 bpp, use 16 bits translations tables */
542 i_pixel_size = sizeof( u16 );
544 case 3: /* 24 or 32 bpp, use 32 bits translations tables */
549 i_pixel_size = sizeof( u32 );
553 intf_DbgMsg("error: invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel );
554 i_pixel_size = sizeof( u32 );
558 p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
559 (u16 *)malloc( 1024 * i_pixel_size );
560 p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
561 (u16 *)malloc( 1024 * i_pixel_size );
562 p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
563 (u16 *)malloc( 1024 * i_pixel_size );
564 if( (p_vout->pi_trans16_red == NULL) ||
565 (p_vout->pi_trans16_green == NULL ) ||
566 (p_vout->pi_trans16_blue == NULL ) )
568 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
569 *p_vout->pi_status = THREAD_ERROR;
570 if( p_vout->pi_trans16_red != NULL )
572 free( p_vout->pi_trans16_red );
574 if( p_vout->pi_trans16_green != NULL )
576 free( p_vout->pi_trans16_green );
578 if( p_vout->pi_trans16_blue != NULL )
580 free( p_vout->pi_trans16_blue );
585 /* Translate translation tables */
586 p_vout->pi_trans16_red += 384;
587 p_vout->pi_trans16_green += 384;
588 p_vout->pi_trans16_blue += 384;
589 p_vout->pi_trans32_red += 384;
590 p_vout->pi_trans32_green += 384;
591 p_vout->pi_trans32_blue += 384;
593 /* Build translation tables */
594 switch( p_vout->i_screen_depth )
597 for( i_index = -384; i_index < 640; i_index++)
599 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
600 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
601 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
605 for( i_index = -384; i_index < 640; i_index++)
607 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
608 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xfc)<<3;
609 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
614 for( i_index = -384; i_index < 640; i_index++)
616 p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
617 p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
618 p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
623 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
628 /* Mark thread as running and return */
629 p_vout->b_active = 1;
630 *p_vout->pi_status = THREAD_READY;
631 intf_DbgMsg("thread ready\n");
635 /*******************************************************************************
636 * RunThread: video output thread
637 *******************************************************************************
638 * Video output thread. This function does only returns when the thread is
639 * terminated. It handles the pictures arriving in the video heap and the
640 * display device events.
641 *******************************************************************************/
642 static void RunThread( vout_thread_t *p_vout)
644 int i_picture; /* picture index */
645 int i_err; /* error code */
646 int i_idle_level = 0; /* idle level */
647 mtime_t current_date; /* current date */
648 mtime_t pic_date = 0; /* picture date */
649 mtime_t last_date = 0; /* last picture date */
650 boolean_t b_display; /* display flag */
651 picture_t * p_pic; /* picture pointer */
654 * Initialize thread and free configuration
656 p_vout->b_error = InitThread( p_vout );
657 if( p_vout->b_error )
659 free( p_vout ); /* destroy descriptor */
664 * Main loop - it is not executed if an error occured during
667 while( (!p_vout->b_die) && (!p_vout->b_error) )
670 * Find the picture to display - this operation does not need lock,
671 * since only READY_PICTURES are handled
674 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
676 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
678 (p_vout->p_picture[i_picture].date < pic_date) ) )
680 p_pic = &p_vout->p_picture[i_picture];
681 pic_date = p_pic->date;
684 current_date = mdate();
687 * Render picture if any
692 /* Computes FPS rate */
693 p_vout->fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = pic_date;
695 if( pic_date < current_date )
697 /* Picture is late: it will be destroyed and the thread will sleep and
698 * go to next picture */
699 vlc_mutex_lock( &p_vout->lock );
700 p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
701 vlc_mutex_unlock( &p_vout->lock );
703 intf_DbgMsg( "warning: late picture %p skipped\n", p_pic );
707 else if( pic_date > current_date + VOUT_DISPLAY_DELAY )
709 /* A picture is ready to be rendered, but its rendering date is
710 * far from the current one so the thread will perform an empty loop
711 * as if no picture were found. The picture state is unchanged */
716 /* Picture has not yet been displayed, and has a valid display
717 * date : render it, then mark it as displayed */
718 if( p_vout->b_active )
720 RenderPicture( p_vout, p_pic );
722 vlc_mutex_lock( &p_vout->lock );
723 p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
724 vlc_mutex_unlock( &p_vout->lock );
729 * Check events, sleep and display picture
731 i_err = vout_SysManage( p_vout );
734 /* A fatal error occured, and the thread must terminate immediately,
735 * without displaying anything - setting b_error to 1 cause the
736 * immediate end of the main while() loop. */
743 /* A picture is ready to be displayed : remove blank screen flag */
744 last_date = pic_date;
748 /* Render additionnal informations */
749 if( p_vout->b_active && p_vout->b_info )
751 RenderInfo( p_vout );
754 /* Sleep until its display date */
759 /* If last picture was a long time ago, increase idle level, reset
760 * date and render idle screen */
761 if( !i_err && (current_date - last_date > VOUT_IDLE_DELAY) )
763 last_date = current_date;
764 b_display = p_vout->b_active && RenderIdle( p_vout, i_idle_level++ );
772 /* Update counters */
773 p_vout->c_idle_loops++;
776 /* Sleep to wait for new pictures */
777 msleep( VOUT_IDLE_SLEEP );
780 /* On awakening, send immediately picture to display */
781 if( b_display && p_vout->b_active )
783 vout_SysDisplay( p_vout );
788 /* Update counters */
796 if( p_vout->b_error )
798 ErrorThread( p_vout );
803 intf_DbgMsg( "thread end\n" );
806 /*******************************************************************************
807 * ErrorThread: RunThread() error loop
808 *******************************************************************************
809 * This function is called when an error occured during thread main's loop. The
810 * thread can still receive feed, but must be ready to terminate as soon as
812 *******************************************************************************/
813 static void ErrorThread( vout_thread_t *p_vout )
815 /* Wait until a `die' order */
816 while( !p_vout->b_die )
819 msleep( VOUT_IDLE_SLEEP );
823 /*******************************************************************************
824 * EndThread: thread destruction
825 *******************************************************************************
826 * This function is called when the thread ends after a sucessfull
828 *******************************************************************************/
829 static void EndThread( vout_thread_t *p_vout )
831 int * pi_status; /* thread status */
835 pi_status = p_vout->pi_status;
836 *pi_status = THREAD_END;
838 /* Destroy all remaining pictures */
839 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
841 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
843 free( p_vout->p_picture[i_picture].p_data );
847 /* Destroy translation tables - remeber these tables are translated */
848 free( p_vout->pi_trans16_red - 384 );
849 free( p_vout->pi_trans16_green - 384 );
850 free( p_vout->pi_trans16_blue - 384 );
852 /* Destroy thread structures allocated by InitThread */
853 vout_SysEnd( p_vout );
854 vout_SysDestroy( p_vout );
858 *pi_status = THREAD_OVER;
861 /*******************************************************************************
862 * RenderPicture: render a picture
863 *******************************************************************************
864 * This function convert a picture from a video heap to a pixel-encoded image
865 * and copy it to the current rendering buffer. No lock is required, since the
866 * rendered picture has been determined as existant, and will only be destroyed
867 * by the vout thread later.
868 * ???? 24 and 32 bpp should probably be separated
869 *******************************************************************************/
870 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
873 /* Send picture informations */
874 intf_DbgMsg("picture %p\n", p_pic );
876 /* Store rendering start date */
877 p_vout->picture_render_time = mdate();
880 switch( p_pic->i_type )
882 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
883 case YUV_422_PICTURE:
884 case YUV_444_PICTURE:
885 if( p_vout->b_grayscale ) /* grayscale */
887 RenderYUVGrayPicture( p_vout, p_pic );
889 else if( p_vout->i_bytes_per_pixel == 2 ) /* color 15 or 16 bpp */
891 RenderYUV16Picture( p_vout, p_pic );
893 else /* color 24 or 32 bpp */
895 RenderYUV32Picture( p_vout, p_pic );
900 intf_DbgMsg("error: unknown picture type %d\n", p_pic->i_type );
906 /* Computes rendering time */
907 p_vout->picture_render_time = mdate() - p_vout->picture_render_time;
911 /*******************************************************************************
912 * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale
913 *******************************************************************************
914 * Performs the YUV convertion. The picture sent to this function should only
915 * have YUV_420, YUV_422 or YUV_444 types.
916 *******************************************************************************/
917 static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic )
919 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
920 int i_width, i_height; /* picture size */
921 int i_eol_offset; /* pixels from end of line to next line */
922 yuv_data_t *p_y; /* Y data base adress */
923 yuv_data_t i_y; /* Y sample */
924 u16 * pi_pic16; /* destination picture, 15 or 16 bpp */
925 u32 * pi_pic32; /* destination picture, 24 or 32 bpp */
926 u16 * pi_trans16_red; /* red transformation table */
927 u16 * pi_trans16_green; /* green transformation table */
928 u16 * pi_trans16_blue; /* blue transformation table */
929 u32 * pi_trans32_red; /* red transformation table */
930 u32 * pi_trans32_green; /* green transformation table */
931 u32 * pi_trans32_blue; /* blue transformation table */
933 /* Set the base pointers and transformation parameters */
935 i_width = p_pic->i_width;
936 i_height = p_pic->i_height;
937 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
939 /* Get base adress for destination image and translation tables, then
941 switch( p_vout->i_screen_depth )
945 pi_trans16_red = p_vout->pi_trans16_red;
946 pi_trans16_green = p_vout->pi_trans16_green;
947 pi_trans16_blue = p_vout->pi_trans16_blue;
948 pi_pic16 = (u16 *) vout_SysGetPicture( p_vout );
950 YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue,
955 pi_trans32_red = p_vout->pi_trans32_red;
956 pi_trans32_green = p_vout->pi_trans32_green;
957 pi_trans32_blue = p_vout->pi_trans32_blue;
958 pi_pic32 = (u32 *) vout_SysGetPicture( p_vout );
960 YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue,
965 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
972 /*******************************************************************************
973 * RenderYUV16Picture: render a 15 or 16 bpp YUV picture
974 *******************************************************************************
975 * Performs the YUV convertion. The picture sent to this function should only
976 * have YUV_420, YUV_422 or YUV_444 types.
977 *******************************************************************************/
978 static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic )
980 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
981 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
982 int i_y, i_u, i_v; /* Y, U and V samples */
983 int i_width, i_height; /* picture size */
984 int i_chroma_width; /* chroma width */
985 int i_eol_offset; /* pixels from end of line to next line */
986 yuv_data_t *p_y; /* Y data base adress */
987 yuv_data_t *p_u; /* U data base adress */
988 yuv_data_t *p_v; /* V data base adress */
989 u16 * pi_pic; /* base adress for destination picture */
990 u16 * pi_trans_red; /* red transformation table */
991 u16 * pi_trans_green; /* green transformation table */
992 u16 * pi_trans_blue; /* blue transformation table */
994 /* Choose transformation matrix coefficients */
995 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
996 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
997 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
998 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1000 /* Choose the conversions tables */
1001 pi_trans_red = p_vout->pi_trans16_red;
1002 pi_trans_green = p_vout->pi_trans16_green;
1003 pi_trans_blue = p_vout->pi_trans16_blue;
1005 /* Set the base pointers and transformation parameters */
1009 i_width = p_pic->i_width;
1010 i_height = p_pic->i_height;
1011 i_chroma_width = i_width / 2;
1012 i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width;
1014 /* Get base adress for destination image */
1015 pi_pic = (u16 *)vout_SysGetPicture( p_vout );
1017 /* Do YUV transformation - the loops are repeated for optimization */
1018 switch( p_pic->i_type )
1020 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
1022 vout_YUV420_16_MMX( p_y, p_u, p_v,
1024 i_width, i_chroma_width,
1026 0, 0, p_vout->i_bytes_per_line,
1027 p_vout->i_screen_depth == 15 );
1036 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
1043 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
1053 /*******************************************************************************
1054 * RenderYUV32Picture: render a 24 or 32 bpp YUV picture
1055 *******************************************************************************
1056 * Performs the YUV convertion. The picture sent to this function should only
1057 * have YUV_420, YUV_422 or YUV_444 types.
1058 *******************************************************************************/
1059 static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic )
1061 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
1062 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
1063 int i_y, i_u, i_v; /* Y, U and V samples */
1064 int i_width, i_height; /* picture size */
1065 int i_chroma_width; /* chroma width */
1066 int i_eol_offset; /* pixels from end of line to next line */
1067 yuv_data_t *p_y; /* Y data base adress */
1068 yuv_data_t *p_u; /* U data base adress */
1069 yuv_data_t *p_v; /* V data base adress */
1070 u32 * pi_pic; /* base adress for destination picture */
1071 u32 * pi_trans_red; /* red transformation table */
1072 u32 * pi_trans_green; /* green transformation table */
1073 u32 * pi_trans_blue; /* blue transformation table */
1075 /* Choose transformation matrix coefficients */
1076 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1077 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1078 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1079 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1081 /* Choose the conversions tables */
1082 pi_trans_red = p_vout->pi_trans32_red;
1083 pi_trans_green = p_vout->pi_trans32_green;
1084 pi_trans_blue = p_vout->pi_trans32_blue;
1086 /* Set the base pointers and transformation parameters */
1090 i_width = p_pic->i_width;
1091 i_height = p_pic->i_height;
1092 i_chroma_width = i_width / 2;
1093 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
1095 /* Get base adress for destination image */
1096 pi_pic = (u32 *)vout_SysGetPicture( p_vout );
1098 /* Do YUV transformation - the loops are repeated for optimization */
1099 switch( p_pic->i_type )
1101 case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */
1108 case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */
1115 case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */
1125 /*******************************************************************************
1126 * RenderInfo: print additionnal informations on a picture
1127 *******************************************************************************
1128 * This function will add informations such as fps and buffer size on a picture
1129 *******************************************************************************/
1130 static void RenderInfo( vout_thread_t *p_vout )
1132 char psz_buffer[256]; /* string buffer */
1134 int i_ready_pic = 0; /* ready pictures */
1135 int i_reserved_pic = 0; /* reserved pictures */
1136 int i_picture; /* picture index */
1140 /* Print FPS rate in upper right corner */
1141 if( p_vout->c_fps_samples > VOUT_FPS_SAMPLES )
1143 sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 /
1144 ( p_vout->fps_sample[ (p_vout->c_fps_samples - 1) % VOUT_FPS_SAMPLES ] -
1145 p_vout->fps_sample[ p_vout->c_fps_samples % VOUT_FPS_SAMPLES ] ) );
1146 vout_SysPrint( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer );
1149 /* Print statistics in upper left corner */
1150 sprintf( psz_buffer, "%ld frames (%.1f %% idle)", p_vout->c_fps_samples,
1152 (double ) p_vout->c_idle_loops * 100 / p_vout->c_loops : 100. );
1153 vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
1157 /* Print heap state in lower left corner */
1158 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
1160 switch( p_vout->p_picture[i_picture].i_status )
1162 case RESERVED_PICTURE:
1170 sprintf( psz_buffer, "video heap: %d/%d/%d", i_reserved_pic, i_ready_pic,
1171 VOUT_MAX_PICTURES );
1172 vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
1176 /* Print rendering statistics in lower right corner */
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 );
1183 /*******************************************************************************
1184 * RenderIdle: render idle picture
1185 *******************************************************************************
1186 * This function will clear the display or print a logo. Level will vary from 0
1187 * to a very high value that noone should never reach. It returns non 0 if
1188 * something needs to be displayed and 0 if the previous picture can be kept.
1189 *******************************************************************************/
1190 static int RenderIdle( vout_thread_t *p_vout, int i_level )
1192 byte_t *pi_pic; /* pointer to picture data */
1194 /* Get frame pointer and clear display */
1195 pi_pic = vout_SysGetPicture( p_vout );
1200 case 0: /* level 0: clear screen */
1201 memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
1203 case 1: /* level 1: "no stream" */
1204 memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
1205 vout_SysPrint( p_vout, p_vout->i_width / 2, p_vout->i_height / 2,
1206 0, 0, "no stream" );
1208 case 50: /* level 50: copyright message */
1209 memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
1210 vout_SysPrint( p_vout, p_vout->i_width / 2, p_vout->i_height / 2,
1211 0, 0, COPYRIGHT_MESSAGE );
1213 default: /* other levels: keep previous picture */