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"
31 /*******************************************************************************
33 *******************************************************************************/
35 /* CLIP_BYTE: return value if between 0 and 255, else return nearest boundary
37 #define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
39 /* YUV_TRANSFORM_16: parametric macro. Due to the high performance need of this
40 * loop, all possible conditions evaluations are made outside the transformation
41 * loop. However, the code does not change much for two different loops. This
42 * macro allows to change slightly the content of the loop without having to
43 * copy and paste code. It is used in RenderYUVPicture function.
45 #define YUV_TRANSFORM( CHROMA, TRANS_RED, TRANS_GREEN, TRANS_BLUE, P_PIC ) \
47 for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \
49 for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2) \
51 /* First sample (complete) */ \
52 i_y = 76309 * *p_y++ - 1188177; \
56 TRANS_RED [(i_y+i_crv*i_v) >>16] | \
57 TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
58 TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
59 i_y = 76309 * *p_y++ - 1188177; \
60 /* Second sample (partial) */ \
67 TRANS_RED [(i_y+i_crv*i_v) >>16] | \
68 TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
69 TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
71 if( (CHROMA == 420) && !(i_pic_y & 0x1) ) \
73 p_u -= p_pic->i_width; \
74 p_v -= p_pic->i_width; \
76 /* Skip until beginning of next line */ \
77 P_PIC += i_pic_eol_offset - p_pic->i_width; \
80 /*******************************************************************************
82 *******************************************************************************/
84 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
85 int matrix_coefficients_table[8][4] =
87 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
88 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
89 {104597, 132201, 25675, 53279}, /* unspecified */
90 {104597, 132201, 25675, 53279}, /* reserved */
91 {104448, 132798, 24759, 53109}, /* FCC */
92 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
93 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
94 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
97 /*******************************************************************************
99 *******************************************************************************/
100 static int InitThread ( vout_thread_t *p_vout );
101 static void RunThread ( vout_thread_t *p_vout );
102 static void ErrorThread ( vout_thread_t *p_vout );
103 static void EndThread ( vout_thread_t *p_vout );
105 static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
106 static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic );
108 /*******************************************************************************
109 * vout_CreateThread: creates a new video output thread
110 *******************************************************************************
111 * This function creates a new video output thread, and returns a pointer
112 * to its description. On error, it returns NULL.
113 * Following configuration properties are used:
114 * VIDEO_CFG_SIZE video heap maximal size
115 * VIDEO_CFG_WIDTH window width
116 * VIDEO_CFG_HEIGHT window height
117 * Using X11 display method (the only one supported yet):
118 * VIDEO_CFG_DISPLAY display used
119 * VIDEO_CFG_TITLE window title
120 * VIDEO_CFG_SHM_EXT try to use XShm extension
121 * If pi_status is NULL, then the function will block until the thread is ready.
122 * If not, pi_error will be updated using one of the THREAD_* constants.
123 *******************************************************************************/
124 vout_thread_t * vout_CreateThread (
125 #if defined(VIDEO_X11)
126 char *psz_display, Window root_window,
127 #elif defined(VIDEO_FB)
130 int i_width, int i_height, int *pi_status
133 vout_thread_t * p_vout; /* thread descriptor */
134 int i_status; /* thread status */
136 /* Allocate descriptor and create method */
137 p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
138 if( p_vout == NULL ) /* error */
142 intf_DbgMsg( "%p\n", p_vout );
143 if( vout_SysCreate( p_vout
144 #if defined(VIDEO_X11)
145 , psz_display, root_window
146 #elif defined(VIDEO_FB)
156 p_vout->i_width = i_width;
157 p_vout->i_height = i_height;
158 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
159 *p_vout->pi_status = THREAD_CREATE;
162 p_vout->b_active = 0;
164 /* Create thread and set locks */
165 vlc_mutex_init( &p_vout->lock );
166 if( vlc_thread_create( &p_vout->thread_id, "video output",
167 (void *) RunThread, (void *) p_vout) )
169 intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
170 vout_SysDestroy( p_vout );
175 /* If status is NULL, wait until the thread is created */
176 if( pi_status == NULL )
180 msleep( THREAD_SLEEP );
181 }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
182 && (i_status != THREAD_FATAL) );
183 if( i_status != THREAD_READY )
192 /*******************************************************************************
193 * vout_DestroyThread: destroys a previously created thread
194 *******************************************************************************
195 * Destroy a terminated thread.
196 * The function will request a destruction of the specified thread. If pi_error
197 * is NULL, it will return once the thread is destroyed. Else, it will be
198 * update using one of the THREAD_* constants.
199 *******************************************************************************/
200 void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
202 int i_status; /* thread status */
204 intf_DbgMsg( "%p\n", p_vout );
207 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
208 *p_vout->pi_status = THREAD_DESTROY;
210 /* Request thread destruction */
213 /* If status is NULL, wait until thread has been destroyed */
214 if( pi_status == NULL )
218 msleep( THREAD_SLEEP );
219 }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
220 && (i_status != THREAD_FATAL) );
224 /*******************************************************************************
225 * vout_DisplayPicture: display a picture
226 *******************************************************************************
227 * Remove the reservation flag of a picture, which will cause it to be ready for
229 *******************************************************************************/
230 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
232 vlc_mutex_lock( &p_vout->lock );
234 /* Remove reservation flag */
235 p_pic->i_status = READY_PICTURE;
239 p_vout->c_pictures++;
242 vlc_mutex_unlock( &p_vout->lock );
245 /*******************************************************************************
246 * vout_CreatePicture: allocate a picture in the video output heap.
247 *******************************************************************************
248 * This function create a reserved image in the video output heap.
249 * A null pointer is returned if the function fails. This method provides an
250 * already allocated zone of memory in the picture data fields.
251 *******************************************************************************/
252 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
253 int i_width, int i_height, int i_bytes_per_line )
255 int i_picture; /* picture index */
256 picture_t * p_free_picture = NULL; /* first free picture */
257 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
260 vlc_mutex_lock( &p_vout->lock );
263 * Look for an empty place
266 i_picture < VOUT_MAX_PICTURES;
269 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
271 /* Picture is marked for destruction, but is still allocated */
272 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
273 (p_vout->p_picture[i_picture].i_height == i_height) &&
274 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
276 /* Memory size do match : memory will not be reallocated, and function
277 * can end immediately - this is the best possible case, since no
278 * memory allocation needs to be done */
279 p_vout->p_picture[i_picture].i_width = i_width;
280 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
281 vlc_mutex_unlock( &p_vout->lock );
282 return( &p_vout->p_picture[i_picture] );
284 else if( p_destroyed_picture == NULL )
286 /* Memory size do not match, but picture index will be kept in
287 * case no other place are left */
288 p_destroyed_picture = &p_vout->p_picture[i_picture];
291 else if( (p_free_picture == NULL) &&
292 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
294 /* Picture is empty and ready for allocation */
295 p_free_picture = &p_vout->p_picture[i_picture];
299 /* If no free picture is available, use a destroyed picture */
300 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
302 /* No free picture or matching destroyed picture has been found, but
303 * a destroyed picture is still avalaible */
304 free( p_destroyed_picture->p_data );
305 p_free_picture = p_destroyed_picture;
311 if( p_free_picture != NULL )
313 /* Allocate memory */
316 case YUV_420_PICTURE: /* YUV picture: 3*16 ?? bits per pixel */
317 case YUV_422_PICTURE:
318 case YUV_444_PICTURE:
319 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
320 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
321 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
322 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
326 intf_DbgMsg("%p error: unknown picture type %d\n", p_vout, i_type );
327 p_free_picture->p_data = NULL;
331 if( p_free_picture->p_data != NULL )
333 /* Copy picture informations */
334 p_free_picture->i_type = i_type;
335 p_free_picture->i_status = RESERVED_PICTURE;
336 p_free_picture->i_width = i_width;
337 p_free_picture->i_height = i_height;
338 p_free_picture->i_bytes_per_line = i_bytes_per_line;
339 p_free_picture->i_refcount = 0;
340 p_free_picture->i_matrix_coefficients = 1; // ?? default value
344 /* Memory allocation failed : set picture as empty */
345 p_free_picture->i_type = EMPTY_PICTURE;
346 p_free_picture->i_status = FREE_PICTURE;
347 p_free_picture = NULL;
348 intf_DbgMsg("%p malloc for new picture failed\n", p_vout );
351 vlc_mutex_unlock( &p_vout->lock );
352 return( p_free_picture );
355 // No free or destroyed picture could be found
356 intf_DbgMsg("%p no picture available\n", p_vout );
357 vlc_mutex_unlock( &p_vout->lock );
361 /*******************************************************************************
362 * vout_RemovePicture: remove a permanent or reserved picture from the heap
363 *******************************************************************************
364 * This function frees a previously reserved picture or a permanent
365 * picture. It is meant to be used when the construction of a picture aborted.
366 * Note that the picture will be destroyed even if it is linked !
367 *******************************************************************************/
368 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
370 vlc_mutex_lock( &p_vout->lock );
372 /* Mark picture for destruction */
373 p_pic->i_status = DESTROYED_PICTURE;
374 intf_DbgMsg("%p picture %p destroyed\n", p_vout, p_pic );
376 vlc_mutex_unlock( &p_vout->lock );
379 /*******************************************************************************
380 * vout_LinkPicture: increment reference counter of a picture
381 *******************************************************************************
382 * This function increment the reference counter of a picture in the video
384 *******************************************************************************/
385 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
387 vlc_mutex_lock( &p_vout->lock );
389 vlc_mutex_unlock( &p_vout->lock );
392 /*******************************************************************************
393 * vout_UnlinkPicture: decrement reference counter of a picture
394 *******************************************************************************
395 * This function decrement the reference counter of a picture in the video heap.
396 *******************************************************************************/
397 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
399 vlc_mutex_lock( &p_vout->lock );
401 if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
403 p_pic->i_status = DESTROYED_PICTURE;
405 vlc_mutex_unlock( &p_vout->lock );
408 /* following functions are local */
410 /*******************************************************************************
411 * InitThread: initialize video output thread
412 *******************************************************************************
413 * This function is called from RunThread and performs the second step of the
414 * initialization. It returns 0 on success. Note that the thread's flag are not
415 * modified inside this function.
416 *******************************************************************************/
417 static int InitThread( vout_thread_t *p_vout )
419 int i_index; /* generic index */
420 int i_pixel_size; /* pixel size, in bytes, for translations tables */
423 *p_vout->pi_status = THREAD_START;
425 /* Initialize pictures */
426 for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
428 p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
429 p_vout->p_picture[i_index].i_status= FREE_PICTURE;
432 /* Initialize other properties */
433 p_vout->i_pictures = 0;
436 p_vout->c_idle_loops = 0;
437 p_vout->c_pictures = 0;
438 p_vout->c_rendered_pictures = 0;
441 /* Initialize output method - width, height, screen depth and bytes per
442 * pixel are initialized by this call. */
443 if( vout_SysInit( p_vout ) ) /* error */
445 *p_vout->pi_status = THREAD_ERROR;
449 /* Allocate translation tables */
450 switch( p_vout->i_bytes_per_pixel )
452 case 2: /* 15 or 16 bpp, use 16 bits translations tables */
453 i_pixel_size = sizeof( u16 );
455 case 3: /* 24 or 32 bpp, use 32 bits translations tables */
458 i_pixel_size = sizeof( u32 );
461 p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
462 (u16 *)malloc( 1024 * i_pixel_size );
463 p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
464 (u16 *)malloc( 1024 * i_pixel_size );
465 p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
466 (u16 *)malloc( 1024 * i_pixel_size );
467 if( (p_vout->pi_trans16_red == NULL) ||
468 (p_vout->pi_trans16_green == NULL ) ||
469 (p_vout->pi_trans16_blue == NULL ) )
471 intf_ErrMsg("vout error: %s\n", strerror(ENOMEM) );
472 *p_vout->pi_status = THREAD_ERROR;
473 if( p_vout->pi_trans16_red != NULL )
475 free( p_vout->pi_trans16_red );
477 if( p_vout->pi_trans16_green != NULL )
479 free( p_vout->pi_trans16_green );
481 if( p_vout->pi_trans16_blue != NULL )
483 free( p_vout->pi_trans16_blue );
488 /* Translate translation tables */
489 p_vout->pi_trans16_red += 384;
490 p_vout->pi_trans16_green += 384;
491 p_vout->pi_trans16_blue += 384;
492 p_vout->pi_trans32_red += 384;
493 p_vout->pi_trans32_green += 384;
494 p_vout->pi_trans32_blue += 384;
496 /* Build translation tables */
497 switch( p_vout->i_screen_depth )
500 for( i_index = -384; i_index < 640; i_index++)
502 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
503 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
504 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
508 for( i_index = -384; i_index < 640; i_index++)
510 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
511 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<3;
512 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
517 for( i_index = -384; i_index < 640; i_index++)
519 p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
520 p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
521 p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
526 /* Mark thread as running and return */
527 *p_vout->pi_status = THREAD_READY;
528 intf_DbgMsg("%p -> succeeded\n", p_vout);
532 /*******************************************************************************
533 * RunThread: video output thread
534 *******************************************************************************
535 * Video output thread. This function does only returns when the thread is
536 * terminated. It handles the pictures arriving in the video heap and the
537 * display device events.
538 *******************************************************************************/
539 static void RunThread( vout_thread_t *p_vout)
541 int i_picture; /* picture index */
542 int i_err; /* error code */
543 mtime_t current_date; /* current date */
544 picture_t * p_pic = NULL;
546 char sz_date[MSTRTIME_MAX_SIZE]; /* date buffer */
550 * Initialize thread and free configuration
552 intf_DbgMsg( "%p begin\n", p_vout );
553 p_vout->b_error = InitThread( p_vout );
554 if( p_vout->b_error )
556 free( p_vout ); /* destroy descriptor */
561 * Main loop - it is not executed if an error occured during
564 while( (!p_vout->b_die) && (!p_vout->b_error) )
567 * Find the picture to display - this is the only operation requiring
568 * the lock on the picture, since once a READY_PICTURE has been found,
569 * it can't be modified by the other threads (except if it is unliked,
570 * but its data remains)
572 vlc_mutex_lock( &p_vout->lock );
574 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
576 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
578 (p_vout->p_picture[i_picture].date < p_pic->date) ) )
580 p_pic = &p_vout->p_picture[i_picture];
584 vlc_mutex_unlock( &p_vout->lock );
587 * Render picture if any
591 current_date = mdate();
592 if( p_pic->date < current_date )
594 /* Picture is late: it will be destroyed and the thread will go
595 * immediately to next picture */
596 vlc_mutex_lock( &p_vout->lock );
597 if( p_pic->i_refcount )
599 p_pic->i_status = DISPLAYED_PICTURE;
603 p_pic->i_status = DESTROYED_PICTURE;
605 vlc_mutex_unlock( &p_vout->lock );
606 intf_ErrMsg( "vout error: picture %p was late - skipped\n", p_pic );
609 else if( p_pic->date > current_date + VOUT_DISPLAY_DELAY )
611 /* A picture is ready to be rendered, but its rendering date is
612 * far from the current one so the thread will perform an empty loop
613 * as if no picture were found. The picture state is unchanged */
618 /* Picture has not yet been displayed, and has a valid display
619 * date : render it */
620 RenderPicture( p_vout, p_pic );
625 * Check events, sleep and display picture
627 i_err = vout_SysManage( p_vout );
630 /* A fatal error occured, and the thread must terminate immediately,
631 * without displaying anything - setting b_error to 1 cause the
632 * immediate end of the main while() loop. */
639 /* A picture is ready to be displayed : sleep until its display date */
640 mwait( p_pic->date );
644 vout_SysDisplay( p_vout );
647 /* Picture has been displayed : destroy it */
648 vlc_mutex_lock( &p_vout->lock );
649 if( p_pic->i_refcount )
651 p_pic->i_status = DISPLAYED_PICTURE;
655 p_pic->i_status = DESTROYED_PICTURE;
657 vlc_mutex_unlock( &p_vout->lock );
661 /* Sleep to wait for new pictures */
662 msleep( VOUT_IDLE_SLEEP );
664 /* Update counters */
665 p_vout->c_idle_loops++;
671 /* Update counters */
679 if( p_vout->b_error )
681 ErrorThread( p_vout );
686 intf_DbgMsg( "%p end\n", p_vout );
689 /*******************************************************************************
690 * ErrorThread: RunThread() error loop
691 *******************************************************************************
692 * This function is called when an error occured during thread main's loop. The
693 * thread can still receive feed, but must be ready to terminate as soon as
695 *******************************************************************************/
696 static void ErrorThread( vout_thread_t *p_vout )
698 /* Wait until a `die' order */
699 while( !p_vout->b_die )
702 msleep( VOUT_IDLE_SLEEP );
706 /*******************************************************************************
707 * EndThread: thread destruction
708 *******************************************************************************
709 * This function is called when the thread ends after a sucessfull
711 *******************************************************************************/
712 static void EndThread( vout_thread_t *p_vout )
714 int * pi_status; /* thread status */
718 pi_status = p_vout->pi_status;
719 *pi_status = THREAD_END;
721 /* Destroy all remaining pictures */
722 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
724 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
726 free( p_vout->p_picture[i_picture].p_data );
730 /* Destroy translation tables - remeber these tables are translated */
731 free( p_vout->pi_trans16_red - 384 );
732 free( p_vout->pi_trans16_green - 384 );
733 free( p_vout->pi_trans16_blue - 384 );
735 /* Destroy thread structures allocated by InitThread */
736 vout_SysEnd( p_vout );
737 vout_SysDestroy( p_vout ); /* destroy output method */
741 *pi_status = THREAD_OVER;
742 intf_DbgMsg("%p\n", p_vout);
745 /*******************************************************************************
746 * RenderPicture: render a picture
747 *******************************************************************************
748 * This function convert a picture from a video heap to a pixel-encoded image
749 * and copy it to the current rendering buffer. No lock is required, since the
750 * rendered picture has been determined as existant, and will only be destroyed
751 * by the vout thread later.
752 *******************************************************************************/
753 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
755 switch( p_pic->i_type )
757 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
758 case YUV_422_PICTURE:
759 case YUV_444_PICTURE:
760 RenderYUVPicture( p_vout, p_pic );
764 intf_DbgMsg("%p Picture %p type=%d, %dx%d\n",
765 p_vout, p_pic, p_pic->i_type, p_pic->i_width, p_pic->i_height );
770 /*******************************************************************************
771 * RenderYUVPicture: render a YUV picture
772 *******************************************************************************
773 * Performs the YUV convertion.
774 *******************************************************************************/
775 static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic )
781 int i_pic_x; /* x coordinate in picture */
782 int i_pic_y; /* y coordinate in picture */
783 yuv_data_t *p_y; /* Y data base adress */
784 yuv_data_t *p_u; /* U data base adress */
785 yuv_data_t *p_v; /* V data base adress */
786 yuv_data_t i_y; /* Y sample */
787 yuv_data_t i_u; /* U sample */
788 yuv_data_t i_v; /* V sample */
789 u16 *pi_pic16; /* base adress for destination picture */
790 u32 *pi_pic32; /* base adress for destination picture */
791 int i_pic_eol_offset; /* end of line offset */
793 /* Choose transformation matrix coefficients */
794 i_crv = matrix_coefficients_table[p_pic->i_matrix_coefficients][0];
795 i_cbu = matrix_coefficients_table[p_pic->i_matrix_coefficients][1];
796 i_cgu = matrix_coefficients_table[p_pic->i_matrix_coefficients][2];
797 i_cgv = matrix_coefficients_table[p_pic->i_matrix_coefficients][3];
799 /* Set the base pointers */
804 /* Get base adress for destination image */
805 pi_pic32 = (u32 *)pi_pic16 =
806 (u16 *)vout_SysGetPicture( p_vout, &i_pic_eol_offset );
808 //?? copy used values (translation, height, width) to local variables ?
810 /* Do YUV transformation - the loops are repeated for optimization */
811 switch( p_vout->i_screen_depth )
815 switch( p_pic->i_type )
817 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
822 p_vout->pi_trans16_red,
823 p_vout->pi_trans16_green,
824 p_vout->pi_trans16_blue,
828 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
830 p_vout->pi_trans16_red,
831 p_vout->pi_trans16_green,
832 p_vout->pi_trans16_blue,
835 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
837 p_vout->pi_trans16_red,
838 p_vout->pi_trans16_green,
839 p_vout->pi_trans16_blue,
844 case 24: // ?? probably wrong !
845 switch( p_pic->i_type )
847 case YUV_420_PICTURE: /* 24 bpp 420 transformation */
849 p_vout->pi_trans32_red,
850 p_vout->pi_trans32_green,
851 p_vout->pi_trans32_blue,
854 case YUV_422_PICTURE: /* 24 bpp 422 transformation */
856 p_vout->pi_trans32_red,
857 p_vout->pi_trans32_green,
858 p_vout->pi_trans32_blue,
861 case YUV_444_PICTURE: /* 24 bpp 444 transformation */
863 p_vout->pi_trans32_red,
864 p_vout->pi_trans32_green,
865 p_vout->pi_trans32_blue,
871 switch( p_pic->i_type )
873 case YUV_420_PICTURE: /* 32 bpp 420 transformation */
875 p_vout->pi_trans32_red,
876 p_vout->pi_trans32_green,
877 p_vout->pi_trans32_blue,
880 case YUV_422_PICTURE: /* 32 bpp 422 transformation */
882 p_vout->pi_trans32_red,
883 p_vout->pi_trans32_green,
884 p_vout->pi_trans32_blue,
887 case YUV_444_PICTURE: /* 32 bpp 444 transformation */
889 p_vout->pi_trans32_red,
890 p_vout->pi_trans32_green,
891 p_vout->pi_trans32_blue,