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: parametric macro for YUV transformation.
40 * Due to the high performance need of this loop, all possible conditions
41 * evaluations are made outside the transformation loop. However, the code does
42 * not change much for two different loops. This macro allows to change slightly
43 * the content of the loop without having to copy and paste code. It is used in
44 * 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 );
104 static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
105 static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic );
107 /*******************************************************************************
108 * vout_CreateThread: creates a new video output thread
109 *******************************************************************************
110 * This function creates a new video output thread, and returns a pointer
111 * to its description. On error, it returns NULL.
112 * If pi_status is NULL, then the function will block until the thread is ready.
113 * If not, it will be updated using one of the THREAD_* constants.
114 *******************************************************************************/
115 vout_thread_t * vout_CreateThread (
117 char *psz_display, Window root_window,
119 int i_width, int i_height, int *pi_status
122 vout_thread_t * p_vout; /* thread descriptor */
123 int i_status; /* thread status */
125 /* Allocate descriptor */
126 p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
129 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
133 /* Initialize some fields used by the system-dependant method - these fields will
134 * probably be modified by the method */
135 p_vout->i_width = i_width;
136 p_vout->i_height = i_height;
137 p_vout->i_screen_depth = 15;
138 p_vout->i_bytes_per_pixel = 2;
139 p_vout->f_x_ratio = 1;
140 p_vout->f_y_ratio = 1;
141 intf_DbgMsg("wished configuration: %dx%dx%d (%d bytes per pixel), ratio %f:%f\n",
142 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
143 p_vout->i_bytes_per_pixel, p_vout->f_x_ratio, p_vout->f_y_ratio );
145 /* Create and initialize system-dependant method - this function issues its
146 * own error messages */
147 if( vout_SysCreate( p_vout
148 #if defined(VIDEO_X11)
149 , psz_display, root_window
156 intf_DbgMsg("actual configuration: %dx%dx%d (%d bytes per pixel), ratio %f:%f\n",
157 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
158 p_vout->i_bytes_per_pixel, p_vout->f_x_ratio, p_vout->f_y_ratio );
160 /* Terminate the initialization */
163 p_vout->b_active = 0;
164 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
165 *p_vout->pi_status = THREAD_CREATE;
168 p_vout->c_idle_loops = 0;
169 p_vout->c_pictures = 0;
172 /* Create thread and set locks */
173 vlc_mutex_init( &p_vout->lock );
174 if( vlc_thread_create( &p_vout->thread_id, "video output",
175 (void *) RunThread, (void *) p_vout) )
177 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
178 vout_SysDestroy( p_vout );
183 intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
184 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
186 /* If status is NULL, wait until the thread is created */
187 if( pi_status == NULL )
191 msleep( THREAD_SLEEP );
192 }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
193 && (i_status != THREAD_FATAL) );
194 if( i_status != THREAD_READY )
202 /*******************************************************************************
203 * vout_DestroyThread: destroys a previously created thread
204 *******************************************************************************
205 * Destroy a terminated thread.
206 * The function will request a destruction of the specified thread. If pi_error
207 * is NULL, it will return once the thread is destroyed. Else, it will be
208 * update using one of the THREAD_* constants.
209 *******************************************************************************/
210 void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
212 int i_status; /* thread status */
215 p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
216 *p_vout->pi_status = THREAD_DESTROY;
218 /* Request thread destruction */
221 /* If status is NULL, wait until thread has been destroyed */
222 if( pi_status == NULL )
226 msleep( THREAD_SLEEP );
227 }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
228 && (i_status != THREAD_FATAL) );
232 /*******************************************************************************
233 * vout_DisplayPicture: display a picture
234 *******************************************************************************
235 * Remove the reservation flag of a picture, which will cause it to be ready for
237 *******************************************************************************/
238 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
240 vlc_mutex_lock( &p_vout->lock );
242 /* Remove reservation flag */
243 p_pic->i_status = READY_PICTURE;
247 p_vout->c_pictures++;
250 vlc_mutex_unlock( &p_vout->lock );
253 /*******************************************************************************
254 * vout_CreatePicture: allocate a picture in the video output heap.
255 *******************************************************************************
256 * This function create a reserved image in the video output heap.
257 * A null pointer is returned if the function fails. This method provides an
258 * already allocated zone of memory in the picture data fields.
259 *******************************************************************************/
260 picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
261 int i_width, int i_height, int i_bytes_per_line )
263 int i_picture; /* picture index */
264 picture_t * p_free_picture = NULL; /* first free picture */
265 picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
268 vlc_mutex_lock( &p_vout->lock );
271 * Look for an empty place
274 i_picture < VOUT_MAX_PICTURES;
277 if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
279 /* Picture is marked for destruction, but is still allocated */
280 if( (p_vout->p_picture[i_picture].i_type == i_type) &&
281 (p_vout->p_picture[i_picture].i_height == i_height) &&
282 (p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
284 /* Memory size do match : memory will not be reallocated, and function
285 * can end immediately - this is the best possible case, since no
286 * memory allocation needs to be done */
287 p_vout->p_picture[i_picture].i_width = i_width;
288 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
289 vlc_mutex_unlock( &p_vout->lock );
290 return( &p_vout->p_picture[i_picture] );
292 else if( p_destroyed_picture == NULL )
294 /* Memory size do not match, but picture index will be kept in
295 * case no other place are left */
296 p_destroyed_picture = &p_vout->p_picture[i_picture];
299 else if( (p_free_picture == NULL) &&
300 (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
302 /* Picture is empty and ready for allocation */
303 p_free_picture = &p_vout->p_picture[i_picture];
307 /* If no free picture is available, use a destroyed picture */
308 if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
310 /* No free picture or matching destroyed picture has been found, but
311 * a destroyed picture is still avalaible */
312 free( p_destroyed_picture->p_data );
313 p_free_picture = p_destroyed_picture;
319 if( p_free_picture != NULL )
321 /* Allocate memory */
324 case YUV_420_PICTURE: /* YUV picture: bits per pixel */
325 case YUV_422_PICTURE:
326 case YUV_444_PICTURE:
327 p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
328 p_free_picture->p_y = (yuv_data_t *) p_free_picture->p_data;
329 p_free_picture->p_u = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line);
330 p_free_picture->p_v = (yuv_data_t *)(p_free_picture->p_data + i_height * i_bytes_per_line * 2);
334 intf_DbgMsg("unknown picture type %d\n", i_type );
335 p_free_picture->p_data = NULL;
340 if( p_free_picture->p_data != NULL )
342 /* Copy picture informations */
343 p_free_picture->i_type = i_type;
344 p_free_picture->i_status = RESERVED_PICTURE;
345 p_free_picture->i_width = i_width;
346 p_free_picture->i_height = i_height;
347 p_free_picture->i_bytes_per_line = i_bytes_per_line;
348 p_free_picture->i_refcount = 0;
349 p_free_picture->i_matrix_coefficients = 1; // ?? default value
353 /* Memory allocation failed : set picture as empty */
354 p_free_picture->i_type = EMPTY_PICTURE;
355 p_free_picture->i_status = FREE_PICTURE;
356 p_free_picture = NULL;
357 intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
360 vlc_mutex_unlock( &p_vout->lock );
361 return( p_free_picture );
364 // No free or destroyed picture could be found
365 intf_DbgMsg( "heap is full\n" );
366 vlc_mutex_unlock( &p_vout->lock );
370 /*******************************************************************************
371 * vout_RemovePicture: remove a permanent or reserved picture from the heap
372 *******************************************************************************
373 * This function frees a previously reserved picture or a permanent
374 * picture. It is meant to be used when the construction of a picture aborted.
375 * Note that the picture will be destroyed even if it is linked !
376 *******************************************************************************/
377 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
379 vlc_mutex_lock( &p_vout->lock );
380 p_pic->i_status = DESTROYED_PICTURE;
381 vlc_mutex_unlock( &p_vout->lock );
384 /*******************************************************************************
385 * vout_LinkPicture: increment reference counter of a picture
386 *******************************************************************************
387 * This function increment the reference counter of a picture in the video
389 *******************************************************************************/
390 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
392 vlc_mutex_lock( &p_vout->lock );
394 vlc_mutex_unlock( &p_vout->lock );
397 /*******************************************************************************
398 * vout_UnlinkPicture: decrement reference counter of a picture
399 *******************************************************************************
400 * This function decrement the reference counter of a picture in the video heap.
401 *******************************************************************************/
402 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
404 vlc_mutex_lock( &p_vout->lock );
406 if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
408 p_pic->i_status = DESTROYED_PICTURE;
410 vlc_mutex_unlock( &p_vout->lock );
413 /* following functions are local */
415 /*******************************************************************************
416 * InitThread: initialize video output thread
417 *******************************************************************************
418 * This function is called from RunThread and performs the second step of the
419 * initialization. It returns 0 on success. Note that the thread's flag are not
420 * modified inside this function.
421 *******************************************************************************/
422 static int InitThread( vout_thread_t *p_vout )
424 int i_index; /* generic index */
425 int i_pixel_size; /* pixel size, in bytes, for translations tables */
428 *p_vout->pi_status = THREAD_START;
430 /* Initialize pictures */
431 p_vout->i_pictures = 0;
432 for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
434 p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
435 p_vout->p_picture[i_index].i_status= FREE_PICTURE;
438 /* Initialize output method - this function issues its own error messages */
439 if( vout_SysInit( p_vout ) )
441 *p_vout->pi_status = THREAD_ERROR;
445 /* Allocate translation tables */
446 switch( p_vout->i_bytes_per_pixel )
448 case 2: /* 15 or 16 bpp, use 16 bits translations tables */
449 i_pixel_size = sizeof( u16 );
451 case 3: /* 24 or 32 bpp, use 32 bits translations tables */
456 i_pixel_size = sizeof( u32 );
460 intf_DbgMsg("invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel );
461 i_pixel_size = sizeof( u32 );
465 p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
466 (u16 *)malloc( 1024 * i_pixel_size );
467 p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
468 (u16 *)malloc( 1024 * i_pixel_size );
469 p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
470 (u16 *)malloc( 1024 * i_pixel_size );
471 if( (p_vout->pi_trans16_red == NULL) ||
472 (p_vout->pi_trans16_green == NULL ) ||
473 (p_vout->pi_trans16_blue == NULL ) )
475 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
476 *p_vout->pi_status = THREAD_ERROR;
477 if( p_vout->pi_trans16_red != NULL )
479 free( p_vout->pi_trans16_red );
481 if( p_vout->pi_trans16_green != NULL )
483 free( p_vout->pi_trans16_green );
485 if( p_vout->pi_trans16_blue != NULL )
487 free( p_vout->pi_trans16_blue );
492 /* Translate translation tables */
493 p_vout->pi_trans16_red += 384;
494 p_vout->pi_trans16_green += 384;
495 p_vout->pi_trans16_blue += 384;
496 p_vout->pi_trans32_red += 384;
497 p_vout->pi_trans32_green += 384;
498 p_vout->pi_trans32_blue += 384;
500 /* Build translation tables */
501 switch( p_vout->i_screen_depth )
504 for( i_index = -384; i_index < 640; i_index++)
506 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
507 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
508 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
512 for( i_index = -384; i_index < 640; i_index++)
514 p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
515 p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<3;
516 p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
521 for( i_index = -384; i_index < 640; i_index++)
523 p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
524 p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
525 p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
530 intf_DbgMsg("invalid screen depth %d\n", p_vout->i_screen_depth );
535 /* Mark thread as running and return */
536 p_vout->b_active = 1;
537 *p_vout->pi_status = THREAD_READY;
538 intf_DbgMsg("thread ready");
542 /*******************************************************************************
543 * RunThread: video output thread
544 *******************************************************************************
545 * Video output thread. This function does only returns when the thread is
546 * terminated. It handles the pictures arriving in the video heap and the
547 * display device events.
548 *******************************************************************************/
549 static void RunThread( vout_thread_t *p_vout)
551 int i_picture; /* picture index */
552 int i_err; /* error code */
553 mtime_t current_date; /* current date */
554 picture_t * p_pic = NULL; /* picture pointer */
557 * Initialize thread and free configuration
559 p_vout->b_error = InitThread( p_vout );
560 if( p_vout->b_error )
562 free( p_vout ); /* destroy descriptor */
567 * Main loop - it is not executed if an error occured during
570 while( (!p_vout->b_die) && (!p_vout->b_error) )
573 * Find the picture to display - this is the only operation requiring
574 * the lock on the picture, since once a READY_PICTURE has been found,
575 * it can't be modified by the other threads (except if it is unliked,
576 * but its data remains)
578 vlc_mutex_lock( &p_vout->lock );
580 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
582 if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
584 (p_vout->p_picture[i_picture].date < p_pic->date) ) )
586 p_pic = &p_vout->p_picture[i_picture];
590 vlc_mutex_unlock( &p_vout->lock );
593 * Render picture if any
597 current_date = mdate();
598 if( p_pic->date < current_date )
600 /* Picture is late: it will be destroyed and the thread will go
601 * immediately to next picture */
602 vlc_mutex_lock( &p_vout->lock );
603 if( p_pic->i_refcount )
605 p_pic->i_status = DISPLAYED_PICTURE;
609 p_pic->i_status = DESTROYED_PICTURE;
611 vlc_mutex_unlock( &p_vout->lock );
612 intf_ErrMsg( "warning: late picture skipped\n" );
615 else if( p_pic->date > current_date + VOUT_DISPLAY_DELAY )
617 /* A picture is ready to be rendered, but its rendering date is
618 * far from the current one so the thread will perform an empty loop
619 * as if no picture were found. The picture state is unchanged */
624 /* Picture has not yet been displayed, and has a valid display
625 * date : render it */
626 RenderPicture( p_vout, p_pic );
631 * Check events, sleep and display picture
633 i_err = vout_SysManage( p_vout );
636 /* A fatal error occured, and the thread must terminate immediately,
637 * without displaying anything - setting b_error to 1 cause the
638 * immediate end of the main while() loop. */
645 /* A picture is ready to be displayed : sleep until its display date */
646 mwait( p_pic->date );
650 vout_SysDisplay( p_vout );
653 /* Picture has been displayed : destroy it */
654 vlc_mutex_lock( &p_vout->lock );
655 if( p_pic->i_refcount )
657 p_pic->i_status = DISPLAYED_PICTURE;
661 p_pic->i_status = DESTROYED_PICTURE;
663 vlc_mutex_unlock( &p_vout->lock );
667 /* Sleep to wait for new pictures */
668 msleep( VOUT_IDLE_SLEEP );
670 /* Update counters */
671 p_vout->c_idle_loops++;
677 /* Update counters */
685 if( p_vout->b_error )
687 ErrorThread( p_vout );
692 intf_DbgMsg( "thread end\n" );
695 /*******************************************************************************
696 * ErrorThread: RunThread() error loop
697 *******************************************************************************
698 * This function is called when an error occured during thread main's loop. The
699 * thread can still receive feed, but must be ready to terminate as soon as
701 *******************************************************************************/
702 static void ErrorThread( vout_thread_t *p_vout )
704 /* Wait until a `die' order */
705 while( !p_vout->b_die )
708 msleep( VOUT_IDLE_SLEEP );
712 /*******************************************************************************
713 * EndThread: thread destruction
714 *******************************************************************************
715 * This function is called when the thread ends after a sucessfull
717 *******************************************************************************/
718 static void EndThread( vout_thread_t *p_vout )
720 int * pi_status; /* thread status */
724 pi_status = p_vout->pi_status;
725 *pi_status = THREAD_END;
727 /* Destroy all remaining pictures */
728 for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
730 if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
732 free( p_vout->p_picture[i_picture].p_data );
736 /* Destroy translation tables - remeber these tables are translated */
737 free( p_vout->pi_trans16_red - 384 );
738 free( p_vout->pi_trans16_green - 384 );
739 free( p_vout->pi_trans16_blue - 384 );
741 /* Destroy thread structures allocated by InitThread */
742 vout_SysEnd( p_vout );
743 vout_SysDestroy( p_vout );
747 *pi_status = THREAD_OVER;
750 /*******************************************************************************
751 * RenderPicture: render a picture
752 *******************************************************************************
753 * This function convert a picture from a video heap to a pixel-encoded image
754 * and copy it to the current rendering buffer. No lock is required, since the
755 * rendered picture has been determined as existant, and will only be destroyed
756 * by the vout thread later.
757 *******************************************************************************/
758 static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
760 switch( p_pic->i_type )
762 case YUV_420_PICTURE: /* YUV picture: YUV transformation */
763 case YUV_422_PICTURE:
764 case YUV_444_PICTURE:
765 RenderYUVPicture( p_vout, p_pic );
769 intf_DbgMsg("unknown picture type %d\n", p_pic->i_type );
775 /*******************************************************************************
776 * RenderYUVPicture: render a YUV picture
777 *******************************************************************************
778 * Performs the YUV convertion. The picture sent to this function should only
779 * have YUV_420, YUV_422 or YUV_444 types.
780 *******************************************************************************/
781 static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic )
787 int i_pic_x; /* x coordinate in picture */
788 int i_pic_y; /* y coordinate in picture */
789 yuv_data_t *p_y; /* Y data base adress */
790 yuv_data_t *p_u; /* U data base adress */
791 yuv_data_t *p_v; /* V data base adress */
792 yuv_data_t i_y; /* Y sample */
793 yuv_data_t i_u; /* U sample */
794 yuv_data_t i_v; /* V sample */
795 u16 *pi_pic16; /* base adress for destination picture */
796 u32 *pi_pic32; /* base adress for destination picture */
797 int i_pic_eol_offset; /* end of line offset */
799 /* Choose transformation matrix coefficients */
800 i_crv = matrix_coefficients_table[p_pic->i_matrix_coefficients][0];
801 i_cbu = matrix_coefficients_table[p_pic->i_matrix_coefficients][1];
802 i_cgu = matrix_coefficients_table[p_pic->i_matrix_coefficients][2];
803 i_cgv = matrix_coefficients_table[p_pic->i_matrix_coefficients][3];
805 /* Set the base pointers */
810 /* Get base adress for destination image */
811 pi_pic32 = (u32 *)pi_pic16 =
812 (u16 *)vout_SysGetPicture( p_vout, &i_pic_eol_offset );
814 //?? copy used values (translation, height, width) to local variables ?
816 /* Do YUV transformation - the loops are repeated for optimization */
817 switch( p_vout->i_screen_depth )
821 switch( p_pic->i_type )
823 case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
828 p_vout->pi_trans16_red,
829 p_vout->pi_trans16_green,
830 p_vout->pi_trans16_blue,
834 case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
836 p_vout->pi_trans16_red,
837 p_vout->pi_trans16_green,
838 p_vout->pi_trans16_blue,
841 case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
843 p_vout->pi_trans16_red,
844 p_vout->pi_trans16_green,
845 p_vout->pi_trans16_blue,
850 case 24: // ?? probably wrong !
851 switch( p_pic->i_type )
853 case YUV_420_PICTURE: /* 24 bpp 420 transformation */
855 p_vout->pi_trans32_red,
856 p_vout->pi_trans32_green,
857 p_vout->pi_trans32_blue,
860 case YUV_422_PICTURE: /* 24 bpp 422 transformation */
862 p_vout->pi_trans32_red,
863 p_vout->pi_trans32_green,
864 p_vout->pi_trans32_blue,
867 case YUV_444_PICTURE: /* 24 bpp 444 transformation */
869 p_vout->pi_trans32_red,
870 p_vout->pi_trans32_green,
871 p_vout->pi_trans32_blue,
877 switch( p_pic->i_type )
879 case YUV_420_PICTURE: /* 32 bpp 420 transformation */
881 p_vout->pi_trans32_red,
882 p_vout->pi_trans32_green,
883 p_vout->pi_trans32_blue,
886 case YUV_422_PICTURE: /* 32 bpp 422 transformation */
888 p_vout->pi_trans32_red,
889 p_vout->pi_trans32_green,
890 p_vout->pi_trans32_blue,
893 case YUV_444_PICTURE: /* 32 bpp 444 transformation */
895 p_vout->pi_trans32_red,
896 p_vout->pi_trans32_green,
897 p_vout->pi_trans32_blue,
904 intf_DbgMsg("invalid screen depth %d\n", p_vout->i_screen_depth );