📄 video_output.c
字号:
#if 1 if( display_date < current_date && i_trash_count > 4 ) { /* Picture is late: it will be destroyed and the thread * will sleep and go to next picture */ vlc_mutex_lock( &p_vout->picture_lock ); if( p_pic->i_refcount ) { p_pic->i_status = DISPLAYED_PICTURE; } else { p_pic->i_status = DESTROYED_PICTURE; p_vout->i_pictures--; } intf_DbgMsg( "warning: late picture %p skipped refcount=%d\n", p_pic, p_pic->i_refcount ); vlc_mutex_unlock( &p_vout->picture_lock ); /* Update synchronization information as if display delay * was 0 */ Synchronize( p_vout, display_date - current_date ); p_pic = NULL; display_date = 0; i_trash_count = 0; } else#endif if( display_date > current_date + VOUT_DISPLAY_DELAY ) { /* A picture is ready to be rendered, but its rendering date * is far from the current one so the thread will perform an * empty loop as if no picture were found. The picture state * is unchanged */ p_pic = NULL; display_date = 0; } else { /* Picture will be displayed, update synchronization * information */ Synchronize( p_vout, display_date - current_date ); } } /* * Find the subpictures to display - this operation does not need * lock, since only READY_SUBPICTURE are handled. If no picture * has been selected, display_date will depend on the subpicture. * We get an easily parsable chained list of subpictures which * ends with NULL since p_subpic was initialized to NULL. */ for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ ) { if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE ) { p_vout->p_subpicture[i_index].p_next = p_subpic; p_subpic = &p_vout->p_subpicture[i_index]; } } /* * Perform rendering, sleep and display rendered picture */ if( p_pic ) /* picture and perhaps subpicture */ { b_display = p_vout->b_active; p_vout->last_display_date = display_date; if( b_display ) { /* Set picture dimensions and clear buffer */ SetBufferPicture( p_vout, p_pic ); /* Render picture and informations */ RenderPicture( p_vout, p_pic ); if( p_vout->b_info ) { RenderPictureInfo( p_vout, p_pic ); RenderInfo( p_vout ); } if( p_subpic ) { RenderSubPicture( p_vout, p_subpic ); } } /* Remove picture from heap */ vlc_mutex_lock( &p_vout->picture_lock ); if( p_pic->i_refcount ) { p_pic->i_status = DISPLAYED_PICTURE; } else { p_pic->i_status = DESTROYED_PICTURE; p_vout->i_pictures--; } vlc_mutex_unlock( &p_vout->picture_lock ); /* Render interface and subpicture */ if( b_display && p_vout->b_interface ) { RenderInterface( p_vout ); } } else if( p_vout->b_active ) /* idle or interface screen alone */ { if( p_vout->b_interface && 0 /* && XXX?? intf_change */ ) { /* Interface has changed, so a new rendering is required - force * it by setting last idle date to 0 */ p_vout->last_idle_date = 0; } /* Render idle screen and update idle date, then render interface if * required */ b_display = RenderIdle( p_vout ); if( b_display ) { p_vout->last_idle_date = current_date; if( p_vout->b_interface ) { RenderInterface( p_vout ); } } } else { b_display = 0; } /* * Sleep, wake up and display rendered picture */#ifdef STATS /* Store render time */ p_vout->render_time = mdate() - current_date;#endif /* Give back change lock */ vlc_mutex_unlock( &p_vout->change_lock ); /* Sleep a while or until a given date */ if( display_date != 0 ) { mwait( display_date ); } else { msleep( VOUT_IDLE_SLEEP ); } /* On awakening, take back lock and send immediately picture to display, * then swap buffers */ vlc_mutex_lock( &p_vout->change_lock );#ifdef DEBUG_VIDEO 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) ) { p_vout->p_sys_display( p_vout );#ifndef SYS_BEOS p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1;#endif } /* * Check events and manage thread */ if( p_vout->p_sys_manage( p_vout ) | Manage( p_vout ) ) { /* A fatal error occured, and the thread must terminate immediately, * without displaying anything - setting b_error to 1 cause the * immediate end of the main while() loop. */ p_vout->b_error = 1; } } /* * Error loop - wait until the thread destruction is requested */ if( p_vout->b_error ) { ErrorThread( p_vout ); } /* End of thread */ EndThread( p_vout ); DestroyThread( p_vout, THREAD_OVER ); intf_DbgMsg( "thread end\n" );}/***************************************************************************** * ErrorThread: RunThread() error loop ***************************************************************************** * This function is called when an error occured during thread main's loop. The * thread can still receive feed, but must be ready to terminate as soon as * possible. *****************************************************************************/static void ErrorThread( vout_thread_t *p_vout ){ /* Wait until a `die' order */ intf_DbgMsg("\n"); while( !p_vout->b_die ) { /* Sleep a while */ msleep( VOUT_IDLE_SLEEP ); }}/***************************************************************************** * EndThread: thread destruction ***************************************************************************** * This function is called when the thread ends after a sucessful * initialization. It frees all ressources allocated by InitThread. *****************************************************************************/static void EndThread( vout_thread_t *p_vout ){ int i_index; /* index in heap */ /* Store status */ intf_DbgMsg("\n"); *p_vout->pi_status = THREAD_END; /* Destroy all remaining pictures and subpictures */ for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ ) { if( p_vout->p_picture[i_index].i_status != FREE_PICTURE ) { free( p_vout->p_picture[i_index].p_data ); } } for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ ) { if( p_vout->p_subpicture[i_index].i_status != FREE_SUBPICTURE ) { free( p_vout->p_subpicture[i_index].p_data ); } } /* Destroy translation tables */ vout_EndYUV( p_vout ); p_vout->p_sys_end( p_vout );}/***************************************************************************** * DestroyThread: thread destruction ***************************************************************************** * This function is called when the thread ends. It frees all ressources * allocated by CreateThread. Status is available at this stage. *****************************************************************************/static void DestroyThread( vout_thread_t *p_vout, int i_status ){ int *pi_status; /* status adress */ /* Store status adress */ intf_DbgMsg("\n"); pi_status = p_vout->pi_status; /* Destroy thread structures allocated by Create and InitThread */ vout_UnloadFont( p_vout->p_default_font ); vout_UnloadFont( p_vout->p_large_font ); p_vout->p_sys_destroy( p_vout ); /* Close plugin */ TrashPlugin( p_vout->vout_plugin ); /* Free structure */ free( p_vout ); *pi_status = i_status;}/***************************************************************************** * Print: print simple text on a picture ***************************************************************************** * This function will print a simple text on the picture. It is designed to * print debugging or general informations. *****************************************************************************/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 ){ int i_text_height; /* total text height */ int i_text_width; /* total text width */ /* Update upper left coordinates according to alignment */ vout_TextSize( p_vout->p_default_font, 0, psz_text, &i_text_width, &i_text_height ); if( !Align( p_vout, &i_x, &i_y, i_text_width, i_text_height, i_h_align, i_v_align ) ) { /* Set area and print text */ SetBufferArea( p_vout, i_x, i_y, i_text_width, i_text_height ); 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, p_vout->i_white_pixel, 0, 0, 0, psz_text ); }}/***************************************************************************** * SetBufferArea: activate an area in current buffer ***************************************************************************** * This function is called when something is rendered on the current buffer. * It set the area as active and prepare it to be cleared on next rendering. * Pay attention to the fact that in this functions, i_h is in fact the end y * coordinate of the new area. *****************************************************************************/static void SetBufferArea( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int i_h ){ vout_buffer_t * p_buffer; /* current buffer */ int i_area_begin, i_area_end; /* area vertical extension */ int i_area, i_area_copy; /* area index */ int i_area_shift; /* shift distance for areas */ /* Choose buffer and modify h to end of area position */ p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ]; i_h += i_y - 1; /* * Remove part of the area which is inside the picture - this is done * by calling again SetBufferArea with the correct areas dimensions. */ if( (i_x >= p_buffer->i_pic_x) && (i_x + i_w <= p_buffer->i_pic_x + p_buffer->i_pic_width) ) { i_area_begin = p_buffer->i_pic_y; i_area_end = i_area_begin + p_buffer->i_pic_height - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -