X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvideo_output.c;h=f2fb320576478b288524e9391672843dee0ed9c0;hb=7d2f6de57c4def2f33ff81c1f602621255c63a3c;hp=f0754e22f542b304cea4e4d1a46203ece90fc08d;hpb=2f4af9df225ddce911dce0c0fb388da4f4c7ac65;p=vlc diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index f0754e22f5..f2fb320576 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -5,7 +5,7 @@ * thread, and destroy a previously oppened video output thread. ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: video_output.c,v 1.167 2002/03/16 23:03:19 sam Exp $ + * $Id: video_output.c,v 1.191 2002/08/29 23:53:22 massiot Exp $ * * Authors: Vincent Seguin * @@ -32,7 +32,7 @@ #include /* sprintf() */ #include /* strerror() */ -#include +#include #ifdef HAVE_SYS_TIMES_H # include @@ -41,90 +41,85 @@ #include "video.h" #include "video_output.h" +#if defined( SYS_DARWIN ) +#include "darwin_specific.h" +#endif + /***************************************************************************** * 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 int InitThread ( vout_thread_t * ); +static void RunThread ( vout_thread_t * ); +static void ErrorThread ( vout_thread_t * ); +static void EndThread ( vout_thread_t * ); +static void DestroyThread ( vout_thread_t * ); static int ReduceHeight ( int ); static int BinaryLog ( u32 ); static void MaskToShift ( int *, int *, u32 ); - -/***************************************************************************** - * vout_InitBank: initialize the video output bank. - *****************************************************************************/ -void vout_InitBank ( void ) -{ - p_vout_bank->i_count = 0; - - vlc_mutex_init( &p_vout_bank->lock ); -} - -/***************************************************************************** - * vout_EndBank: empty the video output bank. - ***************************************************************************** - * This function ends all unused video outputs and empties the bank in - * case of success. - *****************************************************************************/ -void vout_EndBank ( void ) -{ - /* Ask all remaining video outputs to die */ - while( p_vout_bank->i_count ) - { - vout_DestroyThread( - p_vout_bank->pp_vout[ --p_vout_bank->i_count ], NULL ); - } - - vlc_mutex_destroy( &p_vout_bank->lock ); -} +static void InitWindowSize ( vout_thread_t *, int *, int * ); /***************************************************************************** * vout_CreateThread: creates a new video output thread ***************************************************************************** * This function creates a new video output thread, and returns a pointer * to its description. On error, it returns NULL. - * If pi_status is NULL, then the function will block until the thread is ready. - * If not, it will be updated using one of the THREAD_* constants. *****************************************************************************/ -vout_thread_t * vout_CreateThread ( int *pi_status, +vout_thread_t * __vout_CreateThread ( vlc_object_t *p_parent, int i_width, int i_height, - u32 i_chroma, int i_aspect ) + vlc_fourcc_t i_chroma, int i_aspect ) { vout_thread_t * p_vout; /* thread descriptor */ - int i_status; /* thread status */ int i_index; /* loop variable */ char * psz_plugin; /* Allocate descriptor */ - p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) ); + p_vout = vlc_object_create( p_parent, VLC_OBJECT_VOUT ); if( p_vout == NULL ) { - intf_ErrMsg( "vout error: vout thread creation returned %s", - strerror(ENOMEM) ); + msg_Err( p_parent, "out of memory" ); return( NULL ); } - /* Choose the best module */ - if( !(psz_plugin = config_GetPszVariable( "filter" )) ) + /* If the parent is not a VOUT object, that means we are at the start of + * the video output pipe */ + if( p_parent->i_object_type != VLC_OBJECT_VOUT ) { - psz_plugin = config_GetPszVariable( "vout" ); + /* look for the default filter configuration */ + p_vout->psz_filter_chain = config_GetPsz( p_parent, "filter" ); } + else + { + /* continue the parent's filter chain */ + char *psz_end; - /* Initialize thread properties - thread id and locks will be initialized - * later */ - p_vout->b_die = 0; - p_vout->b_error = 0; - p_vout->b_active = 0; - p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status; - *p_vout->pi_status = THREAD_CREATE; + psz_end = strchr( ((vout_thread_t *)p_parent)->psz_filter_chain, ':' ); + if( psz_end && *(psz_end+1) ) + p_vout->psz_filter_chain = strdup( psz_end+1 ); + else p_vout->psz_filter_chain = NULL; + } + + /* Choose the video output module */ + if( !p_vout->psz_filter_chain ) + { + psz_plugin = config_GetPsz( p_parent, "vout" ); + } + else + { + /* the filter chain is a string list of filters separated by double + * colons */ + char *psz_end; + + psz_end = strchr( p_vout->psz_filter_chain, ':' ); + if( psz_end ) + psz_plugin = strndup( p_vout->psz_filter_chain, + psz_end - p_vout->psz_filter_chain ); + else psz_plugin = strdup( p_vout->psz_filter_chain ); + } /* Initialize pictures and subpictures - translation tables and functions * will be initialized later in InitThread */ - for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++) + for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES; i_index++) { p_vout->p_picture[i_index].i_status = FREE_PICTURE; p_vout->p_picture[i_index].i_type = EMPTY_PICTURE; @@ -172,61 +167,51 @@ vout_thread_t * vout_CreateThread ( int *pi_status, p_vout->render_time = 10; p_vout->c_fps_samples= 0; + p_vout->i_mouse_x = 0; + p_vout->i_mouse_y = 0; + p_vout->i_mouse_button = 0; + /* user requested fullscreen? */ - if( config_GetIntVariable( "fullscreen" ) ) + if( config_GetInt( p_vout, "fullscreen" ) ) + { p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; + } + + /* Initialize the dimensions of the video window */ + InitWindowSize( p_vout, &p_vout->i_window_width, + &p_vout->i_window_height ); + - p_vout->p_module - = module_Need( MODULE_CAPABILITY_VOUT, psz_plugin, (void *)p_vout ); + p_vout->p_module = module_Need( p_vout, + ( p_vout->psz_filter_chain ) ? + "video filter" : "video output", + psz_plugin ); if( psz_plugin ) free( psz_plugin ); if( p_vout->p_module == NULL ) { - intf_ErrMsg( "vout error: no suitable vout module" ); - free( p_vout ); + msg_Err( p_vout, "no suitable vout module" ); + vlc_object_destroy( p_vout ); return( NULL ); } -#define f p_vout->p_module->p_functions->vout.functions.vout - p_vout->pf_create = f.pf_create; - p_vout->pf_init = f.pf_init; - p_vout->pf_end = f.pf_end; - p_vout->pf_destroy = f.pf_destroy; - p_vout->pf_manage = f.pf_manage; - p_vout->pf_render = f.pf_render; - p_vout->pf_display = f.pf_display; -#undef f - /* Create thread and set locks */ - vlc_mutex_init( &p_vout->picture_lock ); - vlc_mutex_init( &p_vout->subpicture_lock ); - vlc_mutex_init( &p_vout->change_lock ); + vlc_mutex_init( p_vout, &p_vout->picture_lock ); + vlc_mutex_init( p_vout, &p_vout->subpicture_lock ); + vlc_mutex_init( p_vout, &p_vout->change_lock ); - if( vlc_thread_create( &p_vout->thread_id, "video output", - (void *) RunThread, (void *) p_vout) ) - { - intf_ErrMsg("vout error: %s", strerror(ENOMEM)); - p_vout->pf_destroy( p_vout ); - module_Unneed( p_vout->p_module ); - free( p_vout ); - return( NULL ); - } + vlc_object_attach( p_vout, p_parent ); - /* If status is NULL, wait until the thread is created */ - if( pi_status == NULL ) + if( vlc_thread_create( p_vout, "video output", RunThread, + VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) ) { - do - { - msleep( THREAD_SLEEP ); - }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR) - && (i_status != THREAD_FATAL) ); - if( i_status != THREAD_READY ) - { - return( NULL ); - } + msg_Err( p_vout, "%s", strerror(ENOMEM) ); + module_Unneed( p_vout, p_vout->p_module ); + vlc_object_destroy( p_vout ); + return NULL; } - return( p_vout ); + return p_vout; } /***************************************************************************** @@ -237,26 +222,14 @@ vout_thread_t * vout_CreateThread ( int *pi_status, * is NULL, it will return once the thread is destroyed. Else, it will be * update using one of the THREAD_* constants. *****************************************************************************/ -void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status ) +void vout_DestroyThread( vout_thread_t *p_vout ) { - int i_status; /* thread status */ - - /* Set status */ - p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status; - *p_vout->pi_status = THREAD_DESTROY; - /* Request thread destruction */ p_vout->b_die = 1; + vlc_thread_join( p_vout ); - /* If status is NULL, wait until thread has been destroyed */ - if( pi_status == NULL ) - { - do - { - msleep( THREAD_SLEEP ); - } while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR) - && (i_status != THREAD_FATAL) ); - } + /* Free structure */ + vlc_object_destroy( p_vout ); } /***************************************************************************** @@ -270,9 +243,6 @@ static int InitThread( vout_thread_t *p_vout ) { int i, i_pgcd; - /* Update status */ - *p_vout->pi_status = THREAD_START; - vlc_mutex_lock( &p_vout->change_lock ); #ifdef STATS @@ -288,30 +258,28 @@ static int InitThread( vout_thread_t *p_vout ) if( !I_OUTPUTPICTURES ) { - intf_ErrMsg( "vout error: plugin was unable to allocate at least " - "one direct buffer" ); + msg_Err( p_vout, "plugin was unable to allocate at least " + "one direct buffer" ); p_vout->pf_end( p_vout ); vlc_mutex_unlock( &p_vout->change_lock ); return( 1 ); } - intf_WarnMsg( 1, "vout info: got %i direct buffer(s)", I_OUTPUTPICTURES ); + msg_Dbg( p_vout, "got %i direct buffer(s)", I_OUTPUTPICTURES ); i_pgcd = ReduceHeight( p_vout->render.i_aspect ); - intf_WarnMsg( 1, "vout info: picture in %ix%i, chroma 0x%.8x (%4.4s), " - "aspect ratio %i:%i", - p_vout->render.i_width, p_vout->render.i_height, - p_vout->render.i_chroma, (char*)&p_vout->render.i_chroma, - p_vout->render.i_aspect / i_pgcd, - VOUT_ASPECT_FACTOR / i_pgcd ); + msg_Dbg( p_vout, + "picture in %ix%i, chroma 0x%.8x (%4.4s), aspect ratio %i:%i", + p_vout->render.i_width, p_vout->render.i_height, + p_vout->render.i_chroma, (char*)&p_vout->render.i_chroma, + p_vout->render.i_aspect / i_pgcd, VOUT_ASPECT_FACTOR / i_pgcd ); i_pgcd = ReduceHeight( p_vout->output.i_aspect ); - intf_WarnMsg( 1, "vout info: picture out %ix%i, chroma 0x%.8x (%4.4s), " - "aspect ratio %i:%i", - p_vout->output.i_width, p_vout->output.i_height, - p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma, - p_vout->output.i_aspect / i_pgcd, - VOUT_ASPECT_FACTOR / i_pgcd ); + msg_Dbg( p_vout, + "picture out %ix%i, chroma 0x%.8x (%4.4s), aspect ratio %i:%i", + p_vout->output.i_width, p_vout->output.i_height, + p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma, + p_vout->output.i_aspect / i_pgcd, VOUT_ASPECT_FACTOR / i_pgcd ); /* Calculate shifts from system-updated masks */ MaskToShift( &p_vout->output.i_lrshift, &p_vout->output.i_rrshift, @@ -334,9 +302,9 @@ static int InitThread( vout_thread_t *p_vout ) * for memcpy operations */ p_vout->b_direct = 1; - intf_WarnMsg( 2, "vout info: direct render, mapping " - "render pictures 0-%i to system pictures 1-%i", - VOUT_MAX_PICTURES - 2, VOUT_MAX_PICTURES - 1 ); + msg_Dbg( p_vout, "direct render, mapping " + "render pictures 0-%i to system pictures 1-%i", + VOUT_MAX_PICTURES - 2, VOUT_MAX_PICTURES - 1 ); for( i = 1; i < VOUT_MAX_PICTURES; i++ ) { @@ -352,48 +320,34 @@ static int InitThread( vout_thread_t *p_vout ) p_vout->b_direct = 0; /* Choose the best module */ - p_vout->chroma.p_module - = module_Need( MODULE_CAPABILITY_CHROMA, NULL, (void *)p_vout ); + p_vout->chroma.p_module = module_Need( p_vout, "chroma", NULL ); if( p_vout->chroma.p_module == NULL ) { - intf_ErrMsg( "vout error: no chroma module for %4.4s to %4.4s", - &p_vout->render.i_chroma, &p_vout->output.i_chroma ); - p_vout->pf_end( p_vout ); - vlc_mutex_unlock( &p_vout->change_lock ); - return( 1 ); - } - -#define f p_vout->chroma.p_module->p_functions->chroma.functions.chroma - p_vout->chroma.pf_init = f.pf_init; - p_vout->chroma.pf_end = f.pf_end; -#undef f - - if( p_vout->chroma.pf_init( p_vout ) ) - { - intf_ErrMsg( "vout error: could not initialize chroma module" ); - module_Unneed( p_vout->chroma.p_module ); + msg_Err( p_vout, "no chroma module for %4.4s to %4.4s", + &p_vout->render.i_chroma, &p_vout->output.i_chroma ); p_vout->pf_end( p_vout ); vlc_mutex_unlock( &p_vout->change_lock ); return( 1 ); } - if( I_OUTPUTPICTURES < VOUT_MAX_PICTURES ) + if( I_OUTPUTPICTURES < 2 * VOUT_MAX_PICTURES ) { - intf_WarnMsg( 2, "vout info: indirect render, mapping " - "render pictures %i-%i to system pictures %i-%i", - I_OUTPUTPICTURES - 1, VOUT_MAX_PICTURES - 2, - I_OUTPUTPICTURES, VOUT_MAX_PICTURES - 1 ); + msg_Dbg( p_vout, "indirect render, mapping " + "render pictures %i-%i to system pictures %i-%i", + I_OUTPUTPICTURES - 1, 2 * VOUT_MAX_PICTURES - 2, + I_OUTPUTPICTURES, 2 * VOUT_MAX_PICTURES - 1 ); } else { - intf_WarnMsg( 2, "vout info: indirect render, no system " - "pictures needed, we have %i directbuffers", - I_OUTPUTPICTURES ); + /* FIXME: if this happens, we don't have any render pictures left */ + msg_Dbg( p_vout, "indirect render, no system pictures needed," + " we have %i directbuffers", I_OUTPUTPICTURES ); + msg_Err( p_vout, "this is a bug!" ); } /* Append render buffers after the direct buffers */ - for( i = I_OUTPUTPICTURES; i < VOUT_MAX_PICTURES; i++ ) + for( i = I_OUTPUTPICTURES; i < 2 * VOUT_MAX_PICTURES; i++ ) { PP_RENDERPICTURE[ I_RENDERPICTURES ] = &p_vout->p_picture[ i ]; I_RENDERPICTURES++; @@ -411,10 +365,7 @@ static int InitThread( vout_thread_t *p_vout ) PP_OUTPUTPICTURE[ i ]->p_heap = &p_vout->output; } - /* Mark thread as running and return */ - p_vout->b_active = 1; - *p_vout->pi_status = THREAD_READY; - +/* XXX XXX mark thread ready */ return( 0 ); } @@ -428,10 +379,12 @@ static int InitThread( vout_thread_t *p_vout ) static void RunThread( vout_thread_t *p_vout) { int i_index; /* index in heap */ + int i_idle_loops = 0; /* loops without displaying a picture */ mtime_t current_date; /* current date */ mtime_t display_date; /* display date */ picture_t * p_picture; /* picture pointer */ + picture_t * p_last_picture = NULL; /* last picture */ picture_t * p_directbuffer; /* direct buffer to display */ subpicture_t * p_subpic; /* subpicture pointer */ @@ -443,9 +396,7 @@ static void RunThread( vout_thread_t *p_vout) if( p_vout->b_error ) { /* Destroy thread structures allocated by Create and InitThread */ - p_vout->pf_destroy( p_vout ); - - DestroyThread( p_vout, THREAD_ERROR ); + DestroyThread( p_vout ); return; } @@ -463,8 +414,8 @@ static void RunThread( vout_thread_t *p_vout) p_vout->c_loops++; if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) ) { - intf_Msg( "vout stats: picture heap: %d/%d", - I_RENDERPICTURES, p_vout->i_heap_size ); + msg_Dbg( p_vout, "picture heap: %d/%d", + I_RENDERPICTURES, p_vout->i_heap_size ); } #endif @@ -474,9 +425,7 @@ static void RunThread( vout_thread_t *p_vout) */ p_picture = NULL; - for( i_index = 0; - i_index < I_RENDERPICTURES; - i_index++ ) + for( i_index = 0; i_index < I_RENDERPICTURES; i_index++ ) { if( (PP_RENDERPICTURE[i_index]->i_status == READY_PICTURE) && ( (p_picture == NULL) || @@ -489,11 +438,47 @@ static void RunThread( vout_thread_t *p_vout) if( p_picture != NULL ) { + /* If we met the last picture, parse again to see whether there is + * a more appropriate one. */ + if( p_picture == p_last_picture ) + { + for( i_index = 0; i_index < I_RENDERPICTURES; i_index++ ) + { + if( (PP_RENDERPICTURE[i_index]->i_status == READY_PICTURE) + && (PP_RENDERPICTURE[i_index] != p_last_picture) + && ((p_picture == p_last_picture) || + (PP_RENDERPICTURE[i_index]->date < display_date)) ) + { + p_picture = PP_RENDERPICTURE[i_index]; + display_date = p_picture->date; + } + } + } + + /* If we found better than the last picture, destroy it */ + if( p_last_picture && p_picture != p_last_picture ) + { + vlc_mutex_lock( &p_vout->picture_lock ); + if( p_last_picture->i_refcount ) + { + p_last_picture->i_status = DISPLAYED_PICTURE; + } + else + { + p_last_picture->i_status = DESTROYED_PICTURE; + p_vout->i_heap_size--; + } + vlc_mutex_unlock( &p_vout->picture_lock ); + p_last_picture = NULL; + } + /* Compute FPS rate */ p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = display_date; - if( display_date < current_date + p_vout->render_time ) + if( !p_picture->b_force && + p_picture != p_last_picture && + display_date < current_date + p_vout->render_time ) { /* Picture is late: it will be destroyed and the thread * will directly choose the next picture */ @@ -510,13 +495,38 @@ static void RunThread( vout_thread_t *p_vout) p_picture->i_status = DESTROYED_PICTURE; p_vout->i_heap_size--; } - intf_WarnMsg( 1, "vout warning: late picture skipped (%p)", - p_picture ); + msg_Warn( p_vout, "late picture skipped (%lld)", + current_date - display_date ); vlc_mutex_unlock( &p_vout->picture_lock ); continue; } - else if( display_date > current_date + VOUT_DISPLAY_DELAY ) +#if 0 + /* Removed because it causes problems for some people --Meuuh */ + if( display_date > current_date + VOUT_BOGUS_DELAY ) + { + /* Picture is waaay too early: it will be destroyed */ + vlc_mutex_lock( &p_vout->picture_lock ); + if( p_picture->i_refcount ) + { + /* Pretend we displayed the picture, but don't destroy + * it since the decoder might still need it. */ + p_picture->i_status = DISPLAYED_PICTURE; + } + else + { + /* Destroy the picture without displaying it */ + p_picture->i_status = DESTROYED_PICTURE; + p_vout->i_heap_size--; + } + intf_WarnMsg( 1, "vout warning: early picture skipped (%lld)", + display_date - current_date ); + vlc_mutex_unlock( &p_vout->picture_lock ); + + continue; + } +#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 @@ -525,6 +535,25 @@ static void RunThread( vout_thread_t *p_vout) p_picture = NULL; display_date = 0; } + else if( p_picture == p_last_picture ) + { + /* We are asked to repeat the previous picture, but we first + * wait for a couple of idle loops */ + if( i_idle_loops < 4 ) + { + p_picture = NULL; + display_date = 0; + } + else + { + /*intf_WarnMsg( 6, "vout info: duplicating picture" );*/ + } + } + } + + if( p_picture == NULL ) + { + i_idle_loops++; } /* @@ -538,9 +567,9 @@ static void RunThread( vout_thread_t *p_vout) p_directbuffer = vout_RenderPicture( p_vout, p_picture, p_subpic ); /* - * Call the plugin-specific rendering method + * Call the plugin-specific rendering method if there is one */ - if( p_picture != NULL ) + if( p_picture != NULL && p_vout->pf_render ) { /* Render the direct buffer returned by vout_RenderPicture */ p_vout->pf_render( p_vout, p_directbuffer ); @@ -579,32 +608,58 @@ static void RunThread( vout_thread_t *p_vout) if( p_picture != NULL ) { /* Display the direct buffer returned by vout_RenderPicture */ - p_vout->pf_display( p_vout, p_directbuffer ); - - /* Remove picture from heap */ - vlc_mutex_lock( &p_vout->picture_lock ); - if( p_picture->i_refcount ) + if( p_vout->pf_display ) { - p_picture->i_status = DISPLAYED_PICTURE; + p_vout->pf_display( p_vout, p_directbuffer ); } - else - { - p_picture->i_status = DESTROYED_PICTURE; - p_vout->i_heap_size--; - } - vlc_mutex_unlock( &p_vout->picture_lock ); + + /* Reinitialize idle loop count */ + i_idle_loops = 0; + + /* Tell the vout this was the last picture and that it does not + * need to be forced anymore. */ + p_last_picture = p_picture; + p_last_picture->b_force = 0; } /* * Check events and manage thread */ - if( p_vout->pf_manage( p_vout ) ) + if( p_vout->pf_manage && p_vout->pf_manage( p_vout ) ) { - /* A fatal error occured, and the thread must terminate immediately, - * without displaying anything - setting b_error to 1 causes the - * immediate end of the main while() loop. */ + /* A fatal error occured, and the thread must terminate + * immediately, without displaying anything - setting b_error to 1 + * causes the immediate end of the main while() loop. */ p_vout->b_error = 1; } + + if( p_vout->i_changes & VOUT_SIZE_CHANGE ) + { + /* this must only happen when the vout plugin is incapable of + * rescaling the picture itself. In this case we need to destroy + * the current picture buffers and recreate new ones with the right + * dimensions */ + int i; + + p_vout->i_changes &= ~VOUT_SIZE_CHANGE; + + p_vout->pf_end( p_vout ); + for( i = 0; i < I_OUTPUTPICTURES; i++ ) + p_vout->p_picture[ i ].i_status = FREE_PICTURE; + + I_OUTPUTPICTURES = 0; + if( p_vout->pf_init( p_vout ) ) + { + msg_Err( p_vout, "cannot resize display" ); + /* FIXME: pf_end will be called again in EndThread() */ + p_vout->b_error = 1; + } + + /* Need to reinitialise the chroma plugin */ + p_vout->chroma.p_module->pf_deactivate( VLC_OBJECT(p_vout) ); + p_vout->chroma.p_module->pf_activate( VLC_OBJECT(p_vout) ); + } + } /* @@ -618,11 +673,8 @@ static void RunThread( vout_thread_t *p_vout) /* End of thread */ EndThread( p_vout ); - /* Destroy method-dependant resources */ - p_vout->pf_destroy( p_vout ); - /* Destroy thread structures allocated by CreateThread */ - DestroyThread( p_vout, THREAD_OVER ); + DestroyThread( p_vout ); } /***************************************************************************** @@ -652,31 +704,27 @@ static void EndThread( vout_thread_t *p_vout ) { int i_index; /* index in heap */ - /* Store status */ - *p_vout->pi_status = THREAD_END; - #ifdef STATS { struct tms cpu_usage; times( &cpu_usage ); - intf_Msg( "vout stats: cpu usage (user: %d, system: %d)", - cpu_usage.tms_utime, cpu_usage.tms_stime ); + msg_Dbg( p_vout, "cpu usage (user: %d, system: %d)", + cpu_usage.tms_utime, cpu_usage.tms_stime ); } #endif if( !p_vout->b_direct ) { - p_vout->chroma.pf_end( p_vout ); - module_Unneed( p_vout->chroma.p_module ); + module_Unneed( p_vout, p_vout->chroma.p_module ); } /* Destroy all remaining pictures */ - for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ ) + for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES; i_index++ ) { if ( p_vout->p_picture[i_index].i_type == MEMORY_PICTURE ) { - free( p_vout->p_picture[i_index].p_data ); + free( p_vout->p_picture[i_index].p_data_orig ); } } @@ -702,24 +750,15 @@ static void EndThread( vout_thread_t *p_vout ) * 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 ) +static void DestroyThread( vout_thread_t *p_vout ) { - int *pi_status; /* status adress */ - - /* Store status adress */ - pi_status = p_vout->pi_status; - /* Destroy the locks */ vlc_mutex_destroy( &p_vout->picture_lock ); vlc_mutex_destroy( &p_vout->subpicture_lock ); vlc_mutex_destroy( &p_vout->change_lock ); /* Release the module */ - module_Unneed( p_vout->p_module ); - - /* Free structure */ - free( p_vout ); - *pi_status = i_status; + module_Unneed( p_vout, p_vout->p_module ); } /* following functions are local */ @@ -769,16 +808,13 @@ static int BinaryLog(u32 i) { int 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 += 1; + if( i == 0 ) return -31337; - if (i != ((u32)1 << i_log)) - { - intf_ErrMsg( "vout error: binary log overflow for %i", i ); - } + 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 += 1; return( i_log ); } @@ -811,3 +847,54 @@ static void MaskToShift( int *pi_left, int *pi_right, u32 i_mask ) *pi_right = (8 - i_high + i_low); } +/***************************************************************************** + * InitWindowSize: find the initial dimensions the video window should have. + ***************************************************************************** + * This function will check the "width", "height" and "zoom" config options and + * will calculate the size that the video window should have. + *****************************************************************************/ +static void InitWindowSize( vout_thread_t *p_vout, int *pi_width, + int *pi_height ) +{ + int i_width, i_height; + double f_zoom; + + i_width = config_GetInt( p_vout, "width" ); + i_height = config_GetInt( p_vout, "height" ); + f_zoom = config_GetFloat( p_vout, "zoom" ); + + if( (i_width >= 0) && (i_height >= 0)) + { + *pi_width = i_width * f_zoom; + *pi_height = i_height * f_zoom; + return; + } + else if( i_width >= 0 ) + { + *pi_width = i_width * f_zoom; + *pi_height = i_width * f_zoom * VOUT_ASPECT_FACTOR / + p_vout->render.i_aspect; + return; + } + else if( i_height >= 0 ) + { + *pi_height = i_height * f_zoom; + *pi_width = i_height * f_zoom * p_vout->render.i_aspect / + VOUT_ASPECT_FACTOR; + return; + } + + if( p_vout->render.i_height * p_vout->render.i_aspect + >= p_vout->render.i_width * VOUT_ASPECT_FACTOR ) + { + *pi_width = p_vout->render.i_height * f_zoom + * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR; + *pi_height = p_vout->render.i_height * f_zoom; + } + else + { + *pi_width = p_vout->render.i_width * f_zoom; + *pi_height = p_vout->render.i_width * f_zoom + * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect; + } +}