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 */
181 p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
182 VOUT_GRAYSCALE_DEFAULT );
183 p_vout->i_width = i_width;
184 p_vout->i_height = i_height;
185 p_vout->i_bytes_per_line = i_width * 2;
186 p_vout->i_screen_depth = 15;
187 p_vout->i_bytes_per_pixel = 2;
188 p_vout->f_x_ratio = 1;
189 p_vout->f_y_ratio = 1;
190 intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
191 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
192 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
193 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
195 /* Create and initialize system-dependant method - this function issues its
196 * own error messages */
197 if( vout_SysCreate( p_vout
198 #if defined(VIDEO_X11)
199 , psz_display, root_window
206 intf_DbgMsg("actual configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
207 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
208 p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
209 p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
211 /* Terminate the initialization */
214 p_vout->b_active = 0;
215 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
216 *p_vout->pi_status = THREAD_CREATE;
219 p_vout->c_idle_loops = 0;
220 p_vout->c_pictures = 0;
223 /* Create thread and set locks */
224 vlc_mutex_init( &p_vout->lock );
225 if( vlc_thread_create( &p_vout->thread_id, "video output",
226 (void *) RunThread, (void *) p_vout) )
228 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
229 vout_SysDestroy( p_vout );
234 intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
235 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
237 /* If status is NULL, wait until the thread is created */
238 if( pi_status == NULL )
242 msleep( THREAD_SLEEP );
243 }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
244 && (i_status != THREAD_FATAL) );
245 if( i_status != THREAD_READY )
253 /*******************************************************************************
254 * vout_DestroyThread: destroys a previously created thread
255 *******************************************************************************
256 * Destroy a terminated thread.
257 * The function will request a destruction of the specified thread. If pi_error
258 * is NULL, it will return once the thread is destroyed. Else, it will be
259 * update using one of the THREAD_* constants.
260 *******************************************************************************/
261 void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
263 int i_status; /* thread status */
266 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
267 *p_vout->pi_status = THREAD_DESTROY;
269 /* Request thread destruction */
272 /* If status is NULL, wait until thread has been destroyed */
273 if( pi_status == NULL )
277 msleep( THREAD_SLEEP );
278 }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
279 && (i_status != THREAD_FATAL) );
283 /*******************************************************************************
284 * vout_DisplayPicture: display a picture
285 *******************************************************************************
286 * Remove the reservation flag of a picture, which will cause it to be ready for
288 *******************************************************************************/
289 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
292 char psz_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
295 vlc_mutex_lock( &p_vout->lock );
298 /* Check if picture status is valid */
299 if( p_pic->i_status != RESERVED_PICTURE )
301 intf_DbgMsg("error: picture %d has invalid status %d\n",
302 p_pic, p_pic->i_status );
306 /* Remove reservation flag */
307 p_pic->i_status = READY_PICTURE;
311 p_vout->c_pictures++;
315 /* Send picture informations */
316 intf_DbgMsg("picture %p: type=%d, %dx%d, date=%s\n", p_pic, p_pic->i_type,
317 p_pic->i_width,p_pic->i_height, mstrtime( psz_date, p_pic->date ) );
320 vlc_mutex_unlock( &p_vout->lock );
323 /*******************************************************************************
324 * vout_CreatePicture: allocate a picture in the video output heap.
325 *******************************************************************************
326 * This function create a reserved image in the video output heap.
327 * A null pointer is returned if the function fails. This method provides an
328 * already allocated zone of memory in the picture data fields.
329 *******************************************************************************/
330 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
331 int i_width, int i_height, int i_bytes_per_line )
333 int i_picture; /* picture index */
334 picture_t * p_free_picture = NULL; /* first free picture */
335 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
338 vlc_mutex_lock( &p_vout->lock );
341 * Look for an empty place
344 i_picture < VOUT_MAX_PICTURES;
347 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
349 /* Picture is marked for destruction, but is still allocated */
350 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
351 (p_vout->p_picture[i_picture].i_height == i_height) &&
352 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
354 /* Memory size do match : memory will not be reallocated, and function
355 * can end immediately - this is the best possible case, since no
356 * memory allocation needs to be done */
357 p_vout->p_picture[i_picture].i_width = i_width;
358 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
360 intf_DbgMsg("picture %p (in destroyed picture slot)\n",
361 &p_vout->p_picture[i_picture] );
363 vlc_mutex_unlock( &p_vout->lock );
364 return( &p_vout->p_picture[i_picture] );
366 else if( p_destroyed_picture == NULL )
368 /* Memory size do not match, but picture index will be kept in
369 * case no other place are left */
370 p_destroyed_picture = &p_vout->p_picture[i_picture];
373 else if( (p_free_picture == NULL) &&
374 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
376 /* Picture is empty and ready for allocation */
377 p_free_picture = &p_vout->p_picture[i_picture];
381 /* If no free picture is available, use a destroyed picture */
382 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
384 /* No free picture or matching destroyed picture has been found, but
385 * a destroyed picture is still avalaible */
386 free( p_destroyed_picture->p_data );
387 p_free_picture = p_destroyed_picture;
393 if( p_free_picture != NULL )
395 /* Allocate memory */
398 case YUV_420_PICTURE: /* YUV picture: bits per pixel */
399 case YUV_422_PICTURE:
400 case YUV_444_PICTURE:
401 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
402 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
403 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
404 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
408 intf_DbgMsg("error: unknown picture type %d\n", i_type );
409 p_free_picture->p_data = NULL;
414 if( p_free_picture->p_data != NULL )
416 /* Copy picture informations */
417 p_free_picture->i_type = i_type;
418 p_free_picture->i_status = RESERVED_PICTURE;
419 p_free_picture->i_width = i_width;
420 p_free_picture->i_height = i_height;
421 p_free_picture->i_bytes_per_line = i_bytes_per_line;
422 p_free_picture->i_refcount = 0;
423 p_free_picture->i_matrix_coefficients = 1;
427 /* Memory allocation failed : set picture as empty */
428 p_free_picture->i_type = EMPTY_PICTURE;
429 p_free_picture->i_status = FREE_PICTURE;
430 p_free_picture = NULL;
431 intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
435 intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture );
437 vlc_mutex_unlock( &p_vout->lock );
438 return( p_free_picture );
441 // No free or destroyed picture could be found
442 intf_DbgMsg( "warning: heap is full\n" );
443 vlc_mutex_unlock( &p_vout->lock );
447 /*******************************************************************************
448 * vout_DestroyPicture: remove a permanent or reserved picture from the heap
449 *******************************************************************************
450 * This function frees a previously reserved picture or a permanent
451 * picture. It is meant to be used when the construction of a picture aborted.
452 * Note that the picture will be destroyed even if it is linked !
453 *******************************************************************************/
454 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
456 vlc_mutex_lock( &p_vout->lock );
459 /* Check if picture status is valid */
460 if( p_pic->i_status != RESERVED_PICTURE )
462 intf_DbgMsg("error: picture %d has invalid status %d\n",
463 p_pic, p_pic->i_status );
467 p_pic->i_status = DESTROYED_PICTURE;
470 intf_DbgMsg("picture %p\n", p_pic);
473 vlc_mutex_unlock( &p_vout->lock );
476 /*******************************************************************************
477 * vout_LinkPicture: increment reference counter of a picture
478 *******************************************************************************
479 * This function increment the reference counter of a picture in the video
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 is the only operation requiring
683 * the lock on the picture, since once a READY_PICTURE has been found,
684 * it can't be modified by the other threads (except if it is unliked,
685 * but its data remains)
688 vlc_mutex_lock( &p_vout->lock );
689 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
691 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
693 (p_vout->p_picture[i_picture].date < pic_date) ) )
695 p_pic = &p_vout->p_picture[i_picture];
696 pic_date = p_pic->date;
699 vlc_mutex_unlock( &p_vout->lock );
702 * Render picture if any
707 /* Computes FPS rate */
708 p_vout->fps_sample[ p_vout->i_fps_index++ ] = pic_date;
709 if( p_vout->i_fps_index == VOUT_FPS_SAMPLES )
711 p_vout->i_fps_index = 0;
714 current_date = mdate();
715 if( pic_date < current_date )
717 /* Picture is late: it will be destroyed and the thread will go
718 * immediately to next picture */
719 vlc_mutex_lock( &p_vout->lock );
720 if( p_pic->i_refcount )
722 p_pic->i_status = DISPLAYED_PICTURE;
726 p_pic->i_status = DESTROYED_PICTURE;
730 intf_DbgMsg( "warning: late picture %p skipped\n", p_pic );
732 vlc_mutex_unlock( &p_vout->lock );
735 else if( pic_date > current_date + VOUT_DISPLAY_DELAY )
737 /* A picture is ready to be rendered, but its rendering date is
738 * far from the current one so the thread will perform an empty loop
739 * as if no picture were found. The picture state is unchanged */
744 /* Picture has not yet been displayed, and has a valid display
745 * date : render it, then forget it */
746 RenderPicture( p_vout, p_pic );
747 vlc_mutex_lock( &p_vout->lock );
748 if( p_pic->i_refcount )
750 p_pic->i_status = DISPLAYED_PICTURE;
754 p_pic->i_status = DESTROYED_PICTURE;
756 vlc_mutex_unlock( &p_vout->lock );
758 /* Print additional informations */
761 RenderInfo( p_vout );
767 * Check events, sleep and display picture
769 i_err = vout_SysManage( p_vout );
772 /* A fatal error occured, and the thread must terminate immediately,
773 * without displaying anything - setting b_error to 1 cause the
774 * immediate end of the main while() loop. */
781 /* A picture is ready to be displayed : sleep until its display date */
786 vout_SysDisplay( p_vout );
791 /* Sleep to wait for new pictures */
792 msleep( VOUT_IDLE_SLEEP );
794 /* Update counters */
795 p_vout->c_idle_loops++;
801 /* Update counters */
809 if( p_vout->b_error )
811 ErrorThread( p_vout );
816 intf_DbgMsg( "thread end\n" );
819 /*******************************************************************************
820 * ErrorThread: RunThread() error loop
821 *******************************************************************************
822 * This function is called when an error occured during thread main's loop. The
823 * thread can still receive feed, but must be ready to terminate as soon as
825 *******************************************************************************/
826 static void ErrorThread( vout_thread_t *p_vout )
828 /* Wait until a `die' order */
829 while( !p_vout->b_die )
832 msleep( VOUT_IDLE_SLEEP );
836 /*******************************************************************************
837 * EndThread: thread destruction
838 *******************************************************************************
839 * This function is called when the thread ends after a sucessfull
841 *******************************************************************************/
842 static void EndThread( vout_thread_t *p_vout )
844 int * pi_status; /* thread status */
848 pi_status = p_vout->pi_status;
849 *pi_status = THREAD_END;
851 /* Destroy all remaining pictures */
852 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
854 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
856 free( p_vout->p_picture[i_picture].p_data );
860 /* Destroy translation tables - remeber these tables are translated */
861 free( p_vout->pi_trans16_red - 384 );
862 free( p_vout->pi_trans16_green - 384 );
863 free( p_vout->pi_trans16_blue - 384 );
865 /* Destroy thread structures allocated by InitThread */
866 vout_SysEnd( p_vout );
867 vout_SysDestroy( p_vout );
871 *pi_status = THREAD_OVER;
874 /*******************************************************************************
875 * RenderPicture: render a picture
876 *******************************************************************************
877 * This function convert a picture from a video heap to a pixel-encoded image
878 * and copy it to the current rendering buffer. No lock is required, since the
879 * rendered picture has been determined as existant, and will only be destroyed
880 * by the vout thread later.
881 * ???? 24 and 32 bpp should probably be separated
882 *******************************************************************************/
883 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
886 /* Send picture informations */
887 intf_DbgMsg("picture %p\n", p_pic );
889 /* Store rendering start date */
890 p_vout->picture_render_time = mdate();
893 switch( p_pic->i_type )
895 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
896 case YUV_422_PICTURE:
897 case YUV_444_PICTURE:
898 if( p_vout->b_grayscale ) /* grayscale */
900 RenderYUVGrayPicture( p_vout, p_pic );
902 else if( p_vout->i_bytes_per_pixel == 2 ) /* color 15 or 16 bpp */
904 RenderYUV16Picture( p_vout, p_pic );
906 else /* color 24 or 32 bpp */
908 RenderYUV32Picture( p_vout, p_pic );
913 intf_DbgMsg("error: unknown picture type %d\n", p_pic->i_type );
919 /* Computes rendering time */
920 p_vout->picture_render_time = mdate() - p_vout->picture_render_time;
924 /*******************************************************************************
925 * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale
926 *******************************************************************************
927 * Performs the YUV convertion. The picture sent to this function should only
928 * have YUV_420, YUV_422 or YUV_444 types.
929 *******************************************************************************/
930 static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic )
932 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
933 int i_width, i_height; /* picture size */
934 int i_eol_offset; /* pixels from end of line to next line */
935 yuv_data_t *p_y; /* Y data base adress */
936 yuv_data_t i_y; /* Y sample */
937 u16 * pi_pic16; /* destination picture, 15 or 16 bpp */
938 u32 * pi_pic32; /* destination picture, 24 or 32 bpp */
939 u16 * pi_trans16_red; /* red transformation table */
940 u16 * pi_trans16_green; /* green transformation table */
941 u16 * pi_trans16_blue; /* blue transformation table */
942 u32 * pi_trans32_red; /* red transformation table */
943 u32 * pi_trans32_green; /* green transformation table */
944 u32 * pi_trans32_blue; /* blue transformation table */
946 /* Set the base pointers and transformation parameters */
948 i_width = p_pic->i_width;
949 i_height = p_pic->i_height;
950 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
952 /* Get base adress for destination image and translation tables, then
954 switch( p_vout->i_screen_depth )
958 pi_trans16_red = p_vout->pi_trans16_red;
959 pi_trans16_green = p_vout->pi_trans16_green;
960 pi_trans16_blue = p_vout->pi_trans16_blue;
961 pi_pic16 = (u16 *) vout_SysGetPicture( p_vout );
963 YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue,
968 pi_trans32_red = p_vout->pi_trans32_red;
969 pi_trans32_green = p_vout->pi_trans32_green;
970 pi_trans32_blue = p_vout->pi_trans32_blue;
971 pi_pic32 = (u32 *) vout_SysGetPicture( p_vout );
973 YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue,
978 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
985 /*******************************************************************************
986 * RenderYUV16Picture: render a 15 or 16 bpp YUV picture
987 *******************************************************************************
988 * Performs the YUV convertion. The picture sent to this function should only
989 * have YUV_420, YUV_422 or YUV_444 types.
990 *******************************************************************************/
991 static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic )
993 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
994 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
995 int i_y, i_u, i_v; /* Y, U and V samples */
996 int i_width, i_height; /* picture size */
997 int i_chroma_width; /* chroma width */
998 int i_eol_offset; /* pixels from end of line to next line */
999 yuv_data_t *p_y; /* Y data base adress */
1000 yuv_data_t *p_u; /* U data base adress */
1001 yuv_data_t *p_v; /* V data base adress */
1002 u16 * pi_pic; /* base adress for destination picture */
1003 u16 * pi_trans_red; /* red transformation table */
1004 u16 * pi_trans_green; /* green transformation table */
1005 u16 * pi_trans_blue; /* blue transformation table */
1007 /* Choose transformation matrix coefficients */
1008 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1009 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1010 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1011 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1013 /* Choose the conversions tables */
1014 pi_trans_red = p_vout->pi_trans16_red;
1015 pi_trans_green = p_vout->pi_trans16_green;
1016 pi_trans_blue = p_vout->pi_trans16_blue;
1018 /* Set the base pointers and transformation parameters */
1022 i_width = p_pic->i_width;
1023 i_height = p_pic->i_height;
1024 i_chroma_width = i_width / 2;
1025 i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width;
1027 /* Get base adress for destination image */
1028 pi_pic = (u16 *)vout_SysGetPicture( p_vout );
1030 /* Do YUV transformation - the loops are repeated for optimization */
1031 switch( p_pic->i_type )
1033 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
1035 vout_YUV420_16_MMX( p_y, p_u, p_v,
1037 i_width, i_chroma_width,
1039 0, 0, p_vout->i_bytes_per_line,
1040 p_vout->i_screen_depth == 15 );
1049 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
1056 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
1066 /*******************************************************************************
1067 * RenderYUV32Picture: render a 24 or 32 bpp YUV picture
1068 *******************************************************************************
1069 * Performs the YUV convertion. The picture sent to this function should only
1070 * have YUV_420, YUV_422 or YUV_444 types.
1071 *******************************************************************************/
1072 static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic )
1074 int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
1075 int i_pic_x, i_pic_y; /* x,y coordinates in picture */
1076 int i_y, i_u, i_v; /* Y, U and V samples */
1077 int i_width, i_height; /* picture size */
1078 int i_chroma_width; /* chroma width */
1079 int i_eol_offset; /* pixels from end of line to next line */
1080 yuv_data_t *p_y; /* Y data base adress */
1081 yuv_data_t *p_u; /* U data base adress */
1082 yuv_data_t *p_v; /* V data base adress */
1083 u32 * pi_pic; /* base adress for destination picture */
1084 u32 * pi_trans_red; /* red transformation table */
1085 u32 * pi_trans_green; /* green transformation table */
1086 u32 * pi_trans_blue; /* blue transformation table */
1088 /* Choose transformation matrix coefficients */
1089 i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
1090 i_cbu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][1];
1091 i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
1092 i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
1094 /* Choose the conversions tables */
1095 pi_trans_red = p_vout->pi_trans32_red;
1096 pi_trans_green = p_vout->pi_trans32_green;
1097 pi_trans_blue = p_vout->pi_trans32_blue;
1099 /* Set the base pointers and transformation parameters */
1103 i_width = p_pic->i_width;
1104 i_height = p_pic->i_height;
1105 i_chroma_width = i_width / 2;
1106 i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
1108 /* Get base adress for destination image */
1109 pi_pic = (u32 *)vout_SysGetPicture( p_vout );
1111 /* Do YUV transformation - the loops are repeated for optimization */
1112 switch( p_pic->i_type )
1114 case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */
1121 case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */
1128 case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */
1138 /*******************************************************************************
1139 * RenderInfo: print additionnal informations on a picture
1140 *******************************************************************************
1141 * This function will add informations such as fps and buffer size on a picture
1142 *******************************************************************************/
1143 static void RenderInfo( vout_thread_t *p_vout )
1145 char psz_buffer[256]; /* string buffer */
1148 /* Print FPS rate */
1149 if( p_vout->c_pictures > VOUT_FPS_SAMPLES )
1151 sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 /
1152 ( p_vout->fps_sample[ (p_vout->i_fps_index + (VOUT_FPS_SAMPLES - 1)) %
1153 VOUT_FPS_SAMPLES ] -
1154 p_vout->fps_sample[ p_vout->i_fps_index ] ) );
1155 vout_SysPrint( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer );
1158 /* Print statistics */
1159 sprintf( psz_buffer, "%ld pictures, %.1f %% idle loops", p_vout->c_pictures,
1160 (double) p_vout->c_idle_loops * 100 / p_vout->c_loops );
1161 vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
1165 /* Print heap size */
1166 sprintf( psz_buffer, "video heap size: %d (%.1f %%)", p_vout->i_pictures,
1167 (double) p_vout->i_pictures * 100 / VOUT_MAX_PICTURES );
1168 vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
1172 /* Print rendering statistics */
1173 sprintf( psz_buffer, "picture rendering time: %lu us",
1174 (unsigned long) p_vout->picture_render_time );
1175 vout_SysPrint( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );