X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvideo_output.c;h=ec4fa366996a3485a10b1453c25230a8c8844db3;hb=4351c7ef81d385e21bdbc1d95b933504c8d75310;hp=bf706405d5f4ad01d2e8e095abff7b7106ae15c7;hpb=3a45b93f119ea9a918d9057a954912af5386d761;p=vlc diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index bf706405d5..ec4fa36699 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -30,24 +30,30 @@ /****************************************************************************** * Local prototypes ******************************************************************************/ -static int InitThread ( vout_thread_t *p_vout ); -static void RunThread ( vout_thread_t *p_vout ); -static void ErrorThread ( vout_thread_t *p_vout ); -static void EndThread ( vout_thread_t *p_vout ); -static void DestroyThread ( vout_thread_t *p_vout, int i_status ); -static void Print ( vout_thread_t *p_vout, int i_x, int i_y, - int i_h_align, int i_v_align, unsigned char *psz_text ); -static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int i_h ); -static void SetBufferPicture ( vout_thread_t *p_vout, picture_t *p_pic ); -static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic ); -static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic ); -static void RenderSubPicture ( vout_thread_t *p_vout, subpicture_t *p_subpic ); -static void RenderInterface ( vout_thread_t *p_vout ); -static int RenderIdle ( vout_thread_t *p_vout ); -static void RenderInfo ( vout_thread_t *p_vout ); -static int Manage ( vout_thread_t *p_vout ); -static int Align ( vout_thread_t *p_vout, int *pi_x, int *pi_y, - int i_width, int i_height, int i_h_align, int i_v_align ); +static int BinaryLog ( u32 i ); +static void MaskToShift ( int *pi_left, int *pi_right, u32 i_mask ); +static int InitThread ( vout_thread_t *p_vout ); +static void RunThread ( vout_thread_t *p_vout ); +static void ErrorThread ( vout_thread_t *p_vout ); +static void EndThread ( vout_thread_t *p_vout ); +static void DestroyThread ( vout_thread_t *p_vout, int i_status ); +static void Print ( vout_thread_t *p_vout, int i_x, int i_y, + int i_h_align, int i_v_align, + unsigned char *psz_text ); +static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y, + int i_w, int i_h ); +static void SetBufferPicture ( vout_thread_t *p_vout, picture_t *p_pic ); +static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic ); +static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic ); +static void RenderSubPicture ( vout_thread_t *p_vout, + subpicture_t *p_subpic ); +static void RenderInterface ( vout_thread_t *p_vout ); +static int RenderIdle ( vout_thread_t *p_vout ); +static void RenderInfo ( vout_thread_t *p_vout ); +static int Manage ( vout_thread_t *p_vout ); +static int Align ( vout_thread_t *p_vout, int *pi_x, + int *pi_y, int i_width, int i_height, + int i_h_align, int i_v_align ); /****************************************************************************** * vout_CreateThread: creates a new video output thread @@ -62,7 +68,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ { vout_thread_t * p_vout; /* thread descriptor */ int i_status; /* thread status */ - int i_index; /* index for array initialization */ + int i_index; /* index for array initialization */ /* Allocate descriptor */ intf_DbgMsg("\n"); @@ -91,15 +97,14 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ p_vout->i_bytes_per_pixel = 2; p_vout->f_gamma = VOUT_GAMMA; - p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, - VOUT_GRAYSCALE_DEFAULT ); + p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT ); p_vout->b_info = 0; p_vout->b_interface = 0; p_vout->b_scale = 0; - intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line)\n", + intf_DbgMsg("wished configuration: %dx%d, %d/%d bpp (%d Bpl)\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, - p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line ); + p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line ); /* Initialize idle screen */ p_vout->last_display_date = mdate(); @@ -131,9 +136,21 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ free( p_vout ); return( NULL ); } - intf_DbgMsg("actual configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line)\n", + intf_DbgMsg("actual configuration: %dx%d, %d/%d bpp (%d Bpl), masks: 0x%x/0x%x/0x%x\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, - p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line ); + p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line, + p_vout->i_red_mask, p_vout->i_green_mask, p_vout->i_blue_mask ); + + /* Calculate shifts from system-updated masks */ + MaskToShift( &p_vout->i_red_lshift, &p_vout->i_red_rshift, p_vout->i_red_mask ); + MaskToShift( &p_vout->i_green_lshift, &p_vout->i_green_rshift, p_vout->i_green_mask ); + MaskToShift( &p_vout->i_blue_lshift, &p_vout->i_blue_rshift, p_vout->i_blue_mask ); + + /* Set some usefull colors */ + p_vout->i_white_pixel = RGB2PIXEL( p_vout, 255, 255, 255 ); + p_vout->i_black_pixel = RGB2PIXEL( p_vout, 0, 0, 0 ); + p_vout->i_gray_pixel = RGB2PIXEL( p_vout, 128, 128, 128 ); + p_vout->i_blue_pixel = RGB2PIXEL( p_vout, 0, 0, 50 ); /* Load fonts - fonts must be initialized after the systme method since * they may be dependant of screen depth and other thread properties */ @@ -168,8 +185,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ return( NULL ); } - intf_Msg("Video display initialized (%dx%d, %d bpp)\n", - p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth ); + intf_Msg("Video display initialized (%dx%d, %d/%d bpp)\n", p_vout->i_width, + p_vout->i_height, p_vout->i_screen_depth, p_vout->i_bytes_per_pixel * 8 ); /* If status is NULL, wait until the thread is created */ if( pi_status == NULL ) @@ -713,8 +730,82 @@ void vout_SetBuffers( vout_thread_t *p_vout, void *p_buf1, void *p_buf2 ) p_vout->p_buffer[1].p_data = p_buf2; } +/***************************************************************************** + * vout_Pixel2RGB: return red, green and blue from pixel value + ***************************************************************************** + * Return color values, in 0-255 range, of the decomposition of a pixel. This + * is a slow routine and should only be used for initialization phase. + *****************************************************************************/ +void vout_Pixel2RGB( vout_thread_t *p_vout, u32 i_pixel, int *pi_red, int *pi_green, int *pi_blue ) +{ + *pi_red = i_pixel & p_vout->i_red_mask; + *pi_green = i_pixel & p_vout->i_green_mask; + *pi_blue = i_pixel & p_vout->i_blue_mask; +} + /* following functions are local */ +/***************************************************************************** + * BinaryLog: computes the base 2 log of a binary value + ***************************************************************************** + * This functions is used by MaskToShift, to get a bit index from a binary + * value. + *****************************************************************************/ +static int BinaryLog(u32 i) +{ + int i_log; + + i_log = 0; + if (i & 0xffff0000) + { + i_log = 16; + } + if (i & 0xff00ff00) + { + i_log += 8; + } + if (i & 0xf0f0f0f0) + { + i_log += 4; + } + if (i & 0xcccccccc) + { + i_log += 2; + } + if (i & 0xaaaaaaaa) + { + i_log++; + } + if (i != ((u32)1 << i_log)) + { + intf_ErrMsg("internal error: binary log overflow\n"); + } + + return( i_log ); +} + +/***************************************************************************** + * MaskToShift: transform a color mask into right and left shifts + ***************************************************************************** + * This function is used for obtaining color shifts from masks. + *****************************************************************************/ +static void MaskToShift( int *pi_left, int *pi_right, u32 i_mask ) +{ + u32 i_low, i_high; /* lower hand higher bits of the mask */ + + /* Get bits */ + i_low = i_mask & (- i_mask); /* lower bit of the mask */ + i_high = i_mask + i_low; /* higher bit of the mask */ + + /* Transform bits into an index */ + i_low = BinaryLog (i_low); + i_high = BinaryLog (i_high); + + /* Update pointers and return */ + *pi_left = i_low; + *pi_right = (8 - i_high + i_low); +} + /****************************************************************************** * InitThread: initialize video output thread ****************************************************************************** @@ -962,7 +1053,8 @@ static void RunThread( vout_thread_t *p_vout) * then swap buffers */ vlc_mutex_lock( &p_vout->change_lock ); #ifdef DEBUG_VIDEO - intf_DbgMsg( "picture %p, subpicture %p\n", p_pic, p_subpic ); + intf_DbgMsg( "picture %p, subpicture %p in buffer %d, display=%d\n", p_pic, p_subpic, + p_vout->i_buffer_index, b_display && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) ); #endif if( b_display && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) ) { @@ -1088,7 +1180,8 @@ void Print( vout_thread_t *p_vout, int i_x, int i_y, int i_h_align, int i_v_alig vout_Print( p_vout->p_default_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data + i_y * p_vout->i_bytes_per_line + i_x * p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, - 0xffffffff, 0x00000000, 0x00000000, 0, psz_text ); + p_vout->i_white_pixel, 0, 0, + 0, psz_text ); } } @@ -1255,7 +1348,8 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) int i_area; /* area index */ int i_data_index; /* area data index */ int i_data_size; /* area data size, in 256 bytes blocs */ - u64 * p_data; /* area data */ + u64 * p_data; /* area data, for clearing */ + byte_t * p_data8; /* area data, for clearing (slow) */ /* Choose buffer and set display dimensions */ p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ]; @@ -1357,13 +1451,12 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) for( i_area = 0; i_area < p_buffer->i_areas; i_area++ ) { #ifdef DEBUG_VIDEO - intf_DbgMsg("clearing picture %p area: %d-%d\n", p_pic, - p_buffer->pi_area_begin[i_area], p_buffer->pi_area_end[i_area]); + intf_DbgMsg("clearing picture %p area in buffer %d: %d-%d\n", p_pic, + p_vout->i_buffer_index, p_buffer->pi_area_begin[i_area], p_buffer->pi_area_end[i_area] ); #endif + i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) * p_vout->i_bytes_per_line; p_data = (u64*) (p_buffer->p_data + p_vout->i_bytes_per_line * p_buffer->pi_area_begin[i_area]); - i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) * - p_vout->i_bytes_per_line / 256; - for( i_data_index = 0; i_data_index < i_data_size; i_data_index++ ) + for( i_data_index = i_data_size / 256; i_data_index-- ; ) { /* Clear 256 bytes block */ *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; @@ -1375,12 +1468,16 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; } - i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) * - p_vout->i_bytes_per_line % 256 / 4; - for( i_data_index = 0; i_data_index < i_data_size; i_data_index++ ) + for( i_data_index = (i_data_size % 256) / 16; i_data_index--; ) { - /* Clear remaining 4 bytes blocks */ - *p_data++ = 0; + /* Clear remaining 16 bytes blocks */ + *p_data++ = 0; *p_data++ = 0; + } + p_data8 = (byte_t *)p_data; + for( i_data_index = i_data_size % 16; i_data_index--; ) + { + /* Clear remaining bytes */ + *p_data8++ = 0; } } @@ -1388,34 +1485,6 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) * Clear areas array */ p_buffer->i_areas = 0; - -#ifdef DEBUG_VIDEO - /* - * In DEBUG_VIDEO mode, draw white pixels at the beginning and the end of - * the picture area. These pixels should not be erased by rendering functions, - * otherwise segmentation fault is menacing ! - */ - if( i_pic_x > 0 ) - { - *(u16*)(p_buffer->p_data + p_vout->i_bytes_per_line * i_pic_y + - p_vout->i_bytes_per_pixel * (i_pic_x - 1)) = 0xffff; - } - if( i_pic_y > 0 ) - { - *(u16*)(p_buffer->p_data + p_vout->i_bytes_per_line * (i_pic_y - 1) + - p_vout->i_bytes_per_pixel * i_pic_x ) = 0xffff; - } - if( i_pic_x + i_pic_width < p_vout->i_width ) - { - *(u16*)(p_buffer->p_data + p_vout->i_bytes_per_line * (i_pic_y + i_pic_height - 1) + - p_vout->i_bytes_per_pixel * (i_pic_x + i_pic_width) ) = 0xffff; - } - if( i_pic_y + i_pic_height < p_vout->i_height ) - { - *(u16*)(p_buffer->p_data + p_vout->i_bytes_per_line * (i_pic_y + i_pic_height) + - p_vout->i_bytes_per_pixel * (i_pic_x + i_pic_width - 1) ) = 0xffff; - } -#endif } /****************************************************************************** @@ -1482,8 +1551,9 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) #ifdef DEBUG_VIDEO /* Print picture date and rendering time */ - intf_DbgMsg("picture %p rendered (%ld us), display date: %s\n", p_pic, - (long) (mdate() - render_time), mstrtime( psz_date, p_pic->date )); + intf_DbgMsg("picture %p rendered in buffer %d (%ld us), display date: %s\n", p_pic, + p_vout->i_buffer_index, (long) (mdate() - render_time), + mstrtime( psz_date, p_pic->date )); #endif } @@ -1573,7 +1643,7 @@ static int RenderIdle( vout_thread_t *p_vout ) p_vout->p_buffer[ p_vout->i_buffer_index ].p_data + i_x * p_vout->i_bytes_per_pixel + i_y * p_vout->i_bytes_per_line, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, - 0xffffffff, 0x33333333, 0, + p_vout->i_white_pixel, p_vout->i_gray_pixel, 0, WIDE_TEXT | OUTLINED_TEXT, psz_text ); SetBufferArea( p_vout, i_x, i_y, i_width, i_height ); } @@ -1673,7 +1743,7 @@ static void RenderInterface( vout_thread_t *p_vout ) { int i_height, i_text_height; /* total and text height */ int i_width_1, i_width_2; /* text width */ - int i_byte; /* byte index */ + int i_byte; /* byte index */ const char *psz_text_1 = "[1-9] Channel [i]nfo [c]olor [g/G]amma"; const char *psz_text_2 = "[+/-] Volume [m]ute [s]caling [Q]uit"; @@ -1682,13 +1752,13 @@ static void RenderInterface( vout_thread_t *p_vout ) vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_2, &i_width_2, &i_text_height ); i_height += i_text_height; - /* Render background - effective background color will depend of the screen - * depth */ + /* Render background */ for( i_byte = (p_vout->i_height - i_height) * p_vout->i_bytes_per_line; i_byte < p_vout->i_height * p_vout->i_bytes_per_line; i_byte++ ) { - p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = 0x33; + //?? noooo ! + p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = p_vout->i_blue_pixel; } /* Render text, if not larger than screen */ @@ -1697,7 +1767,7 @@ static void RenderInterface( vout_thread_t *p_vout ) vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data + (p_vout->i_height - i_height) * p_vout->i_bytes_per_line, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, - 0xffffffff, 0x00000000, 0x00000000, + p_vout->i_white_pixel, p_vout->i_black_pixel, 0, OUTLINED_TEXT, psz_text_1 ); } if( i_width_2 < p_vout->i_width ) @@ -1705,7 +1775,7 @@ static void RenderInterface( vout_thread_t *p_vout ) vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data + (p_vout->i_height - i_height + i_text_height) * p_vout->i_bytes_per_line, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, - 0xffffffff, 0x00000000, 0x00000000, + p_vout->i_white_pixel, p_vout->i_black_pixel, 0, OUTLINED_TEXT, psz_text_2 ); }