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
291 * display. The picture does not need to be locked, since it is ignored by
292 * the output thread if is reserved.
293 *******************************************************************************/
294 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
297 char psz_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
301 /* Check if picture status is valid */
302 if( p_pic->i_status != RESERVED_PICTURE )
304 intf_DbgMsg("error: picture %d has invalid status %d\n",
305 p_pic, p_pic->i_status );
309 /* Remove reservation flag */
310 p_pic->i_status = READY_PICTURE;
314 p_vout->c_pictures++;
318 /* Send picture informations */
319 intf_DbgMsg("picture %p: type=%d, %dx%d, date=%s\n", p_pic, p_pic->i_type,
320 p_pic->i_width,p_pic->i_height, mstrtime( psz_date, p_pic->date ) );
324 /*******************************************************************************
325 * vout_CreatePicture: allocate a picture in the video output heap.
326 *******************************************************************************
327 * This function create a reserved image in the video output heap.
328 * A null pointer is returned if the function fails. This method provides an
329 * already allocated zone of memory in the picture data fields. It needs locking
330 * since several pictures can be created by several producers threads.
331 *******************************************************************************/
332 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
333 int i_width, int i_height, int i_bytes_per_line )
335 int i_picture; /* picture index */
336 picture_t * p_free_picture = NULL; /* first free picture */
337 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
340 vlc_mutex_lock( &p_vout->lock );
343 * Look for an empty place
346 i_picture < VOUT_MAX_PICTURES;
349 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
351 /* Picture is marked for destruction, but is still allocated */
352 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
353 (p_vout->p_picture[i_picture].i_height == i_height) &&
354 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
356 /* Memory size do match : memory will not be reallocated, and function
357 * can end immediately - this is the best possible case, since no
358 * memory allocation needs to be done */
359 p_vout->p_picture[i_picture].i_width = i_width;
360 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
362 intf_DbgMsg("picture %p (in destroyed picture slot)\n",
363 &p_vout->p_picture[i_picture] );
365 vlc_mutex_unlock( &p_vout->lock );
366 return( &p_vout->p_picture[i_picture] );
368 else if( p_destroyed_picture == NULL )
370 /* Memory size do not match, but picture index will be kept in
371 * case no other place are left */
372 p_destroyed_picture = &p_vout->p_picture[i_picture];
375 else if( (p_free_picture == NULL) &&
376 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
378 /* Picture is empty and ready for allocation */
379 p_free_picture = &p_vout->p_picture[i_picture];
383 /* If no free picture is available, use a destroyed picture */
384 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
386 /* No free picture or matching destroyed picture has been found, but
387 * a destroyed picture is still avalaible */
388 free( p_destroyed_picture->p_data );
389 p_free_picture = p_destroyed_picture;
395 if( p_free_picture != NULL )
397 /* Allocate memory */
400 case YUV_420_PICTURE: /* YUV picture: bits per pixel */
401 case YUV_422_PICTURE:
402 case YUV_444_PICTURE:
403 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
404 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
405 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
406 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
410 intf_DbgMsg("error: unknown picture type %d\n", i_type );
411 p_free_picture->p_data = NULL;
416 if( p_free_picture->p_data != NULL )
418 /* Copy picture informations */
419 p_free_picture->i_type = i_type;
420 p_free_picture->i_status = RESERVED_PICTURE;
421 p_free_picture->i_width = i_width;
422 p_free_picture->i_height = i_height;
423 p_free_picture->i_bytes_per_line = i_bytes_per_line;
424 p_free_picture->i_refcount = 0;
425 p_free_picture->i_matrix_coefficients = 1;
429 /* Memory allocation failed : set picture as empty */
430 p_free_picture->i_type = EMPTY_PICTURE;
431 p_free_picture->i_status = FREE_PICTURE;
432 p_free_picture = NULL;
433 intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
437 intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture );
439 vlc_mutex_unlock( &p_vout->lock );
440 return( p_free_picture );
443 // No free or destroyed picture could be found
444 intf_DbgMsg( "warning: heap is full\n" );
445 vlc_mutex_unlock( &p_vout->lock );
449 /*******************************************************************************
450 * vout_DestroyPicture: remove a permanent or reserved picture from the heap
451 *******************************************************************************
452 * This function frees a previously reserved picture or a permanent
453 * picture. It is meant to be used when the construction of a picture aborted.
454 * Note that the picture will be destroyed even if it is linked !
455 * This function does not need locking since reserved pictures are ignored by
457 *******************************************************************************/
458 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
461 /* Check if picture status is valid */
462 if( p_pic->i_status != RESERVED_PICTURE )
464 intf_DbgMsg("error: picture %d has invalid status %d\n",
465 p_pic, p_pic->i_status );
469 p_pic->i_status = DESTROYED_PICTURE;
472 intf_DbgMsg("picture %p\n", p_pic);
476 /*******************************************************************************
477 * vout_LinkPicture: increment reference counter of a picture
478 *******************************************************************************
479 * This function increment the reference counter of a picture in the video
480 * heap. It needs a lock since several producer threads can access the picture.
481 *******************************************************************************/
482 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
484 vlc_mutex_lock( &p_vout->lock );
488 intf_DbgMsg("picture %p\n", p_pic);
491 vlc_mutex_unlock( &p_vout->lock );
494 /*******************************************************************************
495 * vout_UnlinkPicture: decrement reference counter of a picture
496 *******************************************************************************
497 * This function decrement the reference counter of a picture in the video heap.
498 *******************************************************************************/
499 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
501 vlc_mutex_lock( &p_vout->lock );
503 if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
505 p_pic->i_status = DESTROYED_PICTURE;
509 intf_DbgMsg("picture %p\n", p_pic);
512 vlc_mutex_unlock( &p_vout->lock );
515 /* following functions are local */
517 /*******************************************************************************
518 * InitThread: initialize video output thread
519 *******************************************************************************
520 * This function is called from RunThread and performs the second step of the
521 * initialization. It returns 0 on success. Note that the thread's flag are not
522 * modified inside this function.
523 *******************************************************************************/
524 static int InitThread( vout_thread_t *p_vout )
526 int i_index; /* generic index */
527 int i_pixel_size; /* pixel size, in bytes, for translations tables */
530 *p_vout->pi_status = THREAD_START;
532 /* Initialize pictures */
533 p_vout->i_pictures = 0;
534 for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
536 p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
537 p_vout->p_picture[i_index].i_status= FREE_PICTURE;
541 /* Initialize FPS index - since samples won't be used until a minimum of
542 * pictures, they don't need to be initialized */
543 p_vout->i_fps_index = 0;
546 /* Initialize output method - this function issues its own error messages */
547 if( vout_SysInit( p_vout ) )
549 *p_vout->pi_status = THREAD_ERROR;
553 /* Allocate translation tables */
554 switch( p_vout->i_bytes_per_pixel )
556 case 2: /* 15 or 16 bpp, use 16 bits translations tables */
557 i_pixel_size = sizeof( u16 );
559 case 3: /* 24 or 32 bpp, use 32 bits translations tables */
564 i_pixel_size = sizeof( u32 );
568 intf_DbgMsg("error: invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel );
569 i_pixel_size = sizeof( u32 );
573 p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
574 (u16 *)malloc( 1024 * i_pixel_size );
575 p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
576 (u16 *)malloc( 1024 * i_pixel_size );
577 p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
578 (u16 *)malloc( 1024 * i_pixel_size );
579 if( (p_vout->pi_trans16_red == NULL) ||
580 (p_vout->pi_trans16_green == NULL ) ||
581 (p_vout->pi_trans16_blue == NULL ) )
583 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
584 *p_vout->pi_status = THREAD_ERROR;
585 if( p_vout->pi_trans16_red != NULL )
587 free( p_vout->pi_trans16_red );
589 if( p_vout->pi_trans16_green != NULL )
591 free( p_vout->pi_trans16_green );
593 if( p_vout->pi_trans16_blue != NULL )
595 free( p_vout->pi_trans16_blue );
600 /* Translate translation tables */
601 p_vout->pi_trans16_red += 384;
602 p_vout->pi_trans16_green += 384;
603 p_vout->pi_trans16_blue += 384;
604 p_vout->pi_trans32_red += 384;
605 p_vout->pi_trans32_green += 384;
606 p_vout->pi_trans32_blue += 384;
608 /* Build translation tables */
609 switch( p_vout->i_screen_depth )
612 for( i_index = -384; i_index < 640; i_index++)
614 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
615 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
616 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
620 for( i_index = -384; i_index < 640; i_index++)
622 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
623 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xfc)<<3;
624 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
629 for( i_index = -384; i_index < 640; i_index++)
631 p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
632 p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
633 p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
638 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
643 /* Mark thread as running and return */
644 p_vout->b_active = 1;
645 *p_vout->pi_status = THREAD_READY;
646 intf_DbgMsg("thread ready\n");
650 /*******************************************************************************
651 * RunThread: video output thread
652 *******************************************************************************
653 * Video output thread. This function does only returns when the thread is
654 * terminated. It handles the pictures arriving in the video heap and the
655 * display device events.
656 *******************************************************************************/
657 static void RunThread( vout_thread_t *p_vout)
659 int i_picture; /* picture index */
660 int i_err; /* error code */
661 mtime_t current_date; /* current date */
662 picture_t * p_pic; /* picture pointer */
663 mtime_t pic_date = 0; /* picture date */
666 * Initialize thread and free configuration
668 p_vout->b_error = InitThread( p_vout );
669 if( p_vout->b_error )
671 free( p_vout ); /* destroy descriptor */
676 * Main loop - it is not executed if an error occured during
679 while( (!p_vout->b_die) && (!p_vout->b_error) )
682 * Find the picture to display - this operation does not need lock,
683 * since only READY_PICTURES are handled
686 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
688 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
690 (p_vout->p_picture[i_picture].date < pic_date) ) )
692 p_pic = &p_vout->p_picture[i_picture];
693 pic_date = p_pic->date;
698 * Render picture if any
703 /* Computes FPS rate */
704 p_vout->fps_sample[ p_vout->i_fps_index++ ] = pic_date;
705 if( p_vout->i_fps_index == VOUT_FPS_SAMPLES )
707 p_vout->i_fps_index = 0;
710 current_date = mdate();
711 if( pic_date < current_date )
713 /* Picture is late: it will be destroyed and the thread will go
714 * immediately to next picture */
715 if( p_pic->i_refcount )
717 p_pic->i_status = DISPLAYED_PICTURE;
721 p_pic->i_status = DESTROYED_PICTURE;
725 intf_DbgMsg( "warning: late picture %p skipped\n", p_pic );
729 else if( pic_date > current_date + VOUT_DISPLAY_DELAY )
731 /* A picture is ready to be rendered, but its rendering date is
732 * far from the current one so the thread will perform an empty loop
733 * as if no picture were found. The picture state is unchanged */
738 /* Picture has not yet been displayed, and has a valid display
739 * date : render it, then forget it */
740 RenderPicture( p_vout, p_pic );
741 if( p_pic->i_refcount )
743 p_pic->i_status = DISPLAYED_PICTURE;
747 p_pic->i_status = DESTROYED_PICTURE;
750 /* Print additional informations */
753 RenderInfo( p_vout );
759 * Check events, sleep and display picture
761 i_err = vout_SysManage( p_vout );
764 /* A fatal error occured, and the thread must terminate immediately,
765 * without displaying anything - setting b_error to 1 cause the
766 * immediate end of the main while() loop. */
773 /* A picture is ready to be displayed : sleep until its display date */
778 vout_SysDisplay( p_vout );
783 /* Sleep to wait for new pictures */
784 msleep( VOUT_IDLE_SLEEP );
786 /* Update counters */
787 p_vout->c_idle_loops++;
793 /* Update counters */
801 if( p_vout->b_error )
803 ErrorThread( p_vout );
808 intf_DbgMsg( "thread end\n" );
811 /*******************************************************************************
812 * ErrorThread: RunThread() error loop
813 *******************************************************************************
814 * This function is called when an error occured during thread main's loop. The
815 * thread can still receive feed, but must be ready to terminate as soon as
817 *******************************************************************************/
818 static void ErrorThread( vout_thread_t *p_vout )
820 /* Wait until a `die' order */
821 while( !p_vout->b_die )
824 msleep( VOUT_IDLE_SLEEP );
828 /*******************************************************************************
829 * EndThread: thread destruction
830 *******************************************************************************
831 * This function is called when the thread ends after a sucessfull
833 *******************************************************************************/
834 static void EndThread( vout_thread_t *p_vout )
836 int * pi_status; /* thread status */
840 pi_status = p_vout->pi_status;
841 *pi_status = THREAD_END;
843 /* Destroy all remaining pictures */
844 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
846 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
848 free( p_vout->p_picture[i_picture].p_data );
852 /* Destroy translation tables - remeber these tables are translated */
853 free( p_vout->pi_trans16_red - 384 );
854 free( p_vout->pi_trans16_green - 384 );
855 free( p_vout->pi_trans16_blue - 384 );
857 /* Destroy thread structures allocated by InitThread */
858 vout_SysEnd( p_vout );
859 vout_SysDestroy( p_vout );
863 *pi_status = THREAD_OVER;
866 /*******************************************************************************
867 * RenderPicture: render a picture
868 *******************************************************************************
869 * This function convert a picture from a video heap to a pixel-encoded image
870 * and copy it to the current rendering buffer. No lock is required, since the
871 * rendered picture has been determined as existant, and will only be destroyed
872 * by the vout thread later.
873 * ???? 24 and 32 bpp should probably be separated
874 *******************************************************************************/
875 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
878 /* Send picture informations */
879 intf_DbgMsg("picture %p\n", p_pic );
881 /* Store rendering start date */
882 p_vout->picture_render_time = mdate();
885 switch( p_pic->i_type )
887 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
888 case YUV_422_PICTURE:
889 case YUV_444_PICTURE:
890 if( p_vout->b_grayscale ) /* grayscale */
892 RenderYUVGrayPicture( p_vout, p_pic );
894 else if( p_vout->i_bytes_per_pixel == 2 ) /* color 15 or 16 bpp */
896 RenderYUV16Picture( p_vout, p_pic );
898 else /* color 24 or 32 bpp */
900 RenderYUV32Picture( p_vout, p_pic );
905 intf_DbgMsg("error: unknown picture type %d\n", p_pic->i_type );
911 /* Computes rendering time */
912 p_vout->picture_render_time = mdate() - p_vout->picture_render_time;
916 /*******************************************************************************
917 * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale
918 *******************************************************************************
919 * Performs the YUV convertion. The picture sent to this function should only
920 * have YUV_420, YUV_422 or YUV_444 types.
921 *******************************************************************************/
922 static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic )
924 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
925 int i_width, i_height; /* picture size */
926 int i_eol_offset; /* pixels from end of line to next line */
927 yuv_data_t *p_y; /* Y data base adress */
928 yuv_data_t i_y; /* Y sample */
929 u16 * pi_pic16; /* destination picture, 15 or 16 bpp */
930 u32 * pi_pic32; /* destination picture, 24 or 32 bpp */
931 u16 * pi_trans16_red; /* red transformation table */
932 u16 * pi_trans16_green; /* green transformation table */
933 u16 * pi_trans16_blue; /* blue transformation table */
934 u32 * pi_trans32_red; /* red transformation table */
935 u32 * pi_trans32_green; /* green transformation table */
936 u32 * pi_trans32_blue; /* blue transformation table */
938 /* Set the base pointers and transformation parameters */
940 i_width = p_pic->i_width;
941 i_height = p_pic->i_height;
942 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
944 /* Get base adress for destination image and translation tables, then
946 switch( p_vout->i_screen_depth )
950 pi_trans16_red = p_vout->pi_trans16_red;
951 pi_trans16_green = p_vout->pi_trans16_green;
952 pi_trans16_blue = p_vout->pi_trans16_blue;
953 pi_pic16 = (u16 *) vout_SysGetPicture( p_vout );
955 YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue,
960 pi_trans32_red = p_vout->pi_trans32_red;
961 pi_trans32_green = p_vout->pi_trans32_green;
962 pi_trans32_blue = p_vout->pi_trans32_blue;
963 pi_pic32 = (u32 *) vout_SysGetPicture( p_vout );
965 YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue,
970 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
977 /*******************************************************************************
978 * RenderYUV16Picture: render a 15 or 16 bpp YUV picture
979 *******************************************************************************
980 * Performs the YUV convertion. The picture sent to this function should only
981 * have YUV_420, YUV_422 or YUV_444 types.
982 *******************************************************************************/
983 static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic )
985 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
986 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
987 int i_y, i_u, i_v; /* Y, U and V samples */
988 int i_width, i_height; /* picture size */
989 int i_chroma_width; /* chroma width */
990 int i_eol_offset; /* pixels from end of line to next line */
991 yuv_data_t *p_y; /* Y data base adress */
992 yuv_data_t *p_u; /* U data base adress */
993 yuv_data_t *p_v; /* V data base adress */
994 u16 * pi_pic; /* base adress for destination picture */
995 u16 * pi_trans_red; /* red transformation table */
996 u16 * pi_trans_green; /* green transformation table */
997 u16 * pi_trans_blue; /* blue transformation table */
999 /* Choose transformation matrix coefficients */
1000 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1001 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1002 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1003 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1005 /* Choose the conversions tables */
1006 pi_trans_red = p_vout->pi_trans16_red;
1007 pi_trans_green = p_vout->pi_trans16_green;
1008 pi_trans_blue = p_vout->pi_trans16_blue;
1010 /* Set the base pointers and transformation parameters */
1014 i_width = p_pic->i_width;
1015 i_height = p_pic->i_height;
1016 i_chroma_width = i_width / 2;
1017 i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width;
1019 /* Get base adress for destination image */
1020 pi_pic = (u16 *)vout_SysGetPicture( p_vout );
1022 /* Do YUV transformation - the loops are repeated for optimization */
1023 switch( p_pic->i_type )
1025 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
1027 vout_YUV420_16_MMX( p_y, p_u, p_v,
1029 i_width, i_chroma_width,
1031 0, 0, p_vout->i_bytes_per_line,
1032 p_vout->i_screen_depth == 15 );
1041 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
1048 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
1058 /*******************************************************************************
1059 * RenderYUV32Picture: render a 24 or 32 bpp YUV picture
1060 *******************************************************************************
1061 * Performs the YUV convertion. The picture sent to this function should only
1062 * have YUV_420, YUV_422 or YUV_444 types.
1063 *******************************************************************************/
1064 static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic )
1066 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
1067 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
1068 int i_y, i_u, i_v; /* Y, U and V samples */
1069 int i_width, i_height; /* picture size */
1070 int i_chroma_width; /* chroma width */
1071 int i_eol_offset; /* pixels from end of line to next line */
1072 yuv_data_t *p_y; /* Y data base adress */
1073 yuv_data_t *p_u; /* U data base adress */
1074 yuv_data_t *p_v; /* V data base adress */
1075 u32 * pi_pic; /* base adress for destination picture */
1076 u32 * pi_trans_red; /* red transformation table */
1077 u32 * pi_trans_green; /* green transformation table */
1078 u32 * pi_trans_blue; /* blue transformation table */
1080 /* Choose transformation matrix coefficients */
1081 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1082 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1083 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1084 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1086 /* Choose the conversions tables */
1087 pi_trans_red = p_vout->pi_trans32_red;
1088 pi_trans_green = p_vout->pi_trans32_green;
1089 pi_trans_blue = p_vout->pi_trans32_blue;
1091 /* Set the base pointers and transformation parameters */
1095 i_width = p_pic->i_width;
1096 i_height = p_pic->i_height;
1097 i_chroma_width = i_width / 2;
1098 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
1100 /* Get base adress for destination image */
1101 pi_pic = (u32 *)vout_SysGetPicture( p_vout );
1103 /* Do YUV transformation - the loops are repeated for optimization */
1104 switch( p_pic->i_type )
1106 case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */
1113 case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */
1120 case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */
1130 /*******************************************************************************
1131 * RenderInfo: print additionnal informations on a picture
1132 *******************************************************************************
1133 * This function will add informations such as fps and buffer size on a picture
1134 *******************************************************************************/
1135 static void RenderInfo( vout_thread_t *p_vout )
1137 char psz_buffer[256]; /* string buffer */
1140 /* Print FPS rate */
1141 if( p_vout->c_pictures > VOUT_FPS_SAMPLES )
1143 sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 /
1144 ( p_vout->fps_sample[ (p_vout->i_fps_index + (VOUT_FPS_SAMPLES - 1)) %
1145 VOUT_FPS_SAMPLES ] -
1146 p_vout->fps_sample[ p_vout->i_fps_index ] ) );
1147 vout_SysPrint( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer );
1150 /* Print statistics */
1151 sprintf( psz_buffer, "%ld pictures, %.1f %% idle loops", p_vout->c_pictures,
1152 (double) p_vout->c_idle_loops * 100 / p_vout->c_loops );
1153 vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
1157 /* Print heap size */
1158 sprintf( psz_buffer, "video heap size: %d (%.1f %%)", p_vout->i_pictures,
1159 (double) p_vout->i_pictures * 100 / VOUT_MAX_PICTURES );
1160 vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
1164 /* Print rendering statistics */
1165 sprintf( psz_buffer, "picture rendering time: %lu us",
1166 (unsigned long) p_vout->picture_render_time );
1167 vout_SysPrint( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );