X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvideo_output.c;h=fcae25b41492a2738a6bd159ff0039f8287d7269;hb=a70f8bb371466209770c4c3bcdb7137b94acef66;hp=f34bc685aef5eedcc7db538761c8fb891e8b4831;hpb=bad6f235822f3b32f5d9cc52ed272fab6cde0e69;p=vlc diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index f34bc685ae..fcae25b414 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -5,8 +5,9 @@ * thread, and destroy a previously oppened video output thread. ***************************************************************************** * Copyright (C) 2000 VideoLAN + * $Id: video_output.c,v 1.122 2001/05/01 04:18:18 sam Exp $ * - * Authors: + * Authors: Vincent Seguin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,11 +34,16 @@ #include /* sprintf() */ #include /* strerror() */ +#ifdef STATS +# include +#endif + #include "config.h" #include "common.h" #include "threads.h" #include "mtime.h" -#include "plugins.h" +#include "modules.h" + #include "video.h" #include "video_output.h" #include "video_text.h" @@ -45,10 +51,8 @@ #include "video_yuv.h" #include "intf_msg.h" -#include "main.h" -#include "vdec_idct.h" -#include "video_decoder.h" +#include "main.h" /***************************************************************************** * Local prototypes @@ -89,56 +93,45 @@ static void SetPalette ( p_vout_thread_t p_vout, u16 *red, * 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 ( char *psz_display, int i_root_window, - int i_width, int i_height, int *pi_status, - int i_method, void *p_data ) +vout_thread_t * vout_CreateThread ( int *pi_status ) { vout_thread_t * p_vout; /* thread descriptor */ - typedef void ( vout_getplugin_t ) ( vout_thread_t * p_vout ); int i_status; /* thread status */ int i_index; /* index for array initialization */ - int i_best_index = 0, i_best_score = 0; /* Allocate descriptor */ - intf_DbgMsg("\n"); p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) ); if( p_vout == NULL ) { - intf_ErrMsg( "error: %s\n", strerror(ENOMEM) ); + intf_ErrMsg( "vout error: vout thread creation returned %s", + strerror(ENOMEM) ); return( NULL ); } - p_vout->p_set_palette = SetPalette; - - /* Get a suitable video plugin */ - for( i_index = 0 ; i_index < p_main->p_bank->i_plugin_count ; i_index++ ) - { - /* If there's a plugin in p_info ... */ - if( p_main->p_bank->p_info[ i_index ] != NULL ) - { - /* ... and if this plugin provides the functions we want ... */ - if( p_main->p_bank->p_info[ i_index ]->vout_GetPlugin != NULL ) - { - /* ... and if this plugin has a good score ... */ - if( p_main->p_bank->p_info[ i_index ]->i_score > i_best_score ) - { - /* ... then take it */ - i_best_score = p_main->p_bank->p_info[ i_index ]->i_score; - i_best_index = i_index; - } - } - } - } + /* Choose the best module */ + p_vout->p_module = module_Need( MODULE_CAPABILITY_VOUT, NULL ); - if( i_best_score == 0 ) + if( p_vout->p_module == NULL ) { + intf_ErrMsg( "vout error: no suitable vout module" ); free( p_vout ); return( NULL ); } - /* Get the plugin functions */ - ( (vout_getplugin_t *) - p_main->p_bank->p_info[ i_best_index ]->vout_GetPlugin )( p_vout ); +#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_display = f.pf_display; + p_vout->pf_setpalette = f.pf_setpalette; +#undef f + + if( p_vout->pf_setpalette == NULL ) + { + p_vout->pf_setpalette = SetPalette; + } /* Initialize thread properties - thread id and locks will be initialized * later */ @@ -152,23 +145,26 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, * fields will probably be modified by the method, and are only * preferences */ p_vout->i_changes = 0; - p_vout->i_width = i_width; - p_vout->i_height = i_height; - p_vout->i_bytes_per_line = i_width * 2; + p_vout->i_width = main_GetIntVariable( VOUT_WIDTH_VAR, + VOUT_WIDTH_DEFAULT ); + p_vout->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR, + VOUT_HEIGHT_DEFAULT ); + p_vout->i_bytes_per_line = p_vout->i_width * 2; p_vout->i_screen_depth = 15; p_vout->i_bytes_per_pixel = 2; p_vout->f_gamma = VOUT_GAMMA; - + p_vout->b_need_render = 1; + p_vout->b_YCbr = 0; + p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, - VOUT_GRAYSCALE_DEFAULT ); - p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockC; + VOUT_GRAYSCALE_DEFAULT ); p_vout->b_info = 0; p_vout->b_interface = 0; p_vout->b_scale = 1; - 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 * 8, p_vout->i_bytes_per_line ); + intf_WarnMsg( 1, "wished configuration: %dx%d, %d/%d bpp (%d Bpl)", + p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, + p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line ); /* Initialize idle screen */ p_vout->last_display_date = 0; @@ -176,10 +172,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, p_vout->init_display_date = mdate(); p_vout->render_time = 10000; -#ifdef STATS /* Initialize statistics fields */ p_vout->c_fps_samples = 0; -#endif /* Initialize buffer index */ p_vout->i_buffer_index = 0; @@ -200,17 +194,18 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, /* Create and initialize system-dependant method - this function issues its * own error messages */ - if( p_vout->p_sys_create( p_vout, psz_display, i_root_window, p_data ) ) + if( p_vout->pf_create( p_vout ) ) { + module_Unneed( p_vout->p_module ); free( p_vout ); return( NULL ); } - 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 * 8, p_vout->i_bytes_per_line, - p_vout->i_red_mask, p_vout->i_green_mask, - p_vout->i_blue_mask ); + intf_WarnMsg( 1, "actual configuration: %dx%d, %d/%d bpp (%d Bpl), " + "masks: 0x%x/0x%x/0x%x", + p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, + 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, @@ -228,50 +223,36 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, /* Load fonts - fonts must be initialized after the system method since * they may be dependant on screen depth and other thread properties */ - p_vout->p_default_font = vout_LoadFont( DATA_PATH "/" VOUT_DEFAULT_FONT ); - if( p_vout->p_default_font == NULL ) - { - p_vout->p_default_font = vout_LoadFont( "share/" VOUT_DEFAULT_FONT ); - } + p_vout->p_default_font = vout_LoadFont( VOUT_DEFAULT_FONT ); if( p_vout->p_default_font == NULL ) { - intf_ErrMsg( "vout error: could not load default font\n" ); - p_vout->p_sys_destroy( p_vout ); - free( p_vout ); - return( NULL ); - } - p_vout->p_large_font = vout_LoadFont( DATA_PATH "/" VOUT_LARGE_FONT ); - if( p_vout->p_large_font == NULL ) - { - p_vout->p_large_font = vout_LoadFont( "share/" VOUT_LARGE_FONT ); + intf_ErrMsg( "vout error: could not load default font" ); } + + p_vout->p_large_font = vout_LoadFont( VOUT_LARGE_FONT ); if( p_vout->p_large_font == NULL ) { - intf_ErrMsg( "vout error: could not load large font\n" ); - vout_UnloadFont( p_vout->p_default_font ); - p_vout->p_sys_destroy( p_vout ); - free( p_vout ); - return( NULL ); + intf_ErrMsg( "vout error: could not load large font" ); } /* 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_lock( &p_vout->change_lock ); + if( vlc_thread_create( &p_vout->thread_id, "video output", (void *) RunThread, (void *) p_vout) ) { - intf_ErrMsg("error: %s\n", strerror(ENOMEM)); + intf_ErrMsg("vout error: %s", strerror(ENOMEM)); vout_UnloadFont( p_vout->p_default_font ); vout_UnloadFont( p_vout->p_large_font ); - p_vout->p_sys_destroy( p_vout ); + p_vout->pf_destroy( p_vout ); free( p_vout ); return( NULL ); } - intf_Msg( "Video display initialized (%dx%d, %d/%d bpp)\n", p_vout->i_width, - p_vout->i_height, p_vout->i_screen_depth, + intf_Msg( "vout: video display initialized (%dx%d, %d/%d bpp)", + 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 */ @@ -303,7 +284,7 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status ) int i_status; /* thread status */ /* Set status */ - intf_DbgMsg("\n"); + intf_DbgMsg(""); p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status; *p_vout->pi_status = THREAD_DESTROY; @@ -330,7 +311,7 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status ) *****************************************************************************/ void vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) { -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT char psz_begin_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */ char psz_end_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */ #endif @@ -339,7 +320,7 @@ void vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) /* Check if status is valid */ if( p_subpic->i_status != RESERVED_SUBPICTURE ) { - intf_DbgMsg("error: subpicture %p has invalid status %d\n", p_subpic, + intf_ErrMsg("error: subpicture %p has invalid status %d", p_subpic, p_subpic->i_status ); } #endif @@ -347,9 +328,9 @@ void vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) /* Remove reservation flag */ p_subpic->i_status = READY_SUBPICTURE; -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT /* Send subpicture information */ - intf_DbgMsg("subpicture %p: type=%d, begin date=%s, end date=%s\n", + intf_DbgMsg("subpicture %p: type=%d, begin date=%s, end date=%s", p_subpic, p_subpic->i_type, mstrtime( psz_begin_date, p_subpic->begin_date ), mstrtime( psz_end_date, p_subpic->end_date ) ); @@ -390,8 +371,8 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type, * the best possible case, since no memory allocation needs * to be done */ p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE; -#ifdef DEBUG_VIDEO - intf_DbgMsg("subpicture %p (in destroyed subpicture slot)\n", +#ifdef TRACE_VOUT + intf_DbgMsg("subpicture %p (in destroyed subpicture slot)", &p_vout->p_subpicture[i_subpic] ); #endif vlc_mutex_unlock( &p_vout->subpicture_lock ); @@ -437,7 +418,7 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type, break; #ifdef DEBUG default: - intf_DbgMsg("error: unknown subpicture type %d\n", i_type ); + intf_ErrMsg("error: unknown subpicture type %d", i_type ); p_free_subpic->p_data = NULL; break; #endif @@ -462,18 +443,19 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type, p_free_subpic->i_type = EMPTY_SUBPICTURE; p_free_subpic->i_status = FREE_SUBPICTURE; p_free_subpic = NULL; - intf_ErrMsg("spu warning: %s\n", strerror( ENOMEM ) ); + intf_ErrMsg( "vout error: spu allocation returned %s", + strerror( ENOMEM ) ); } -#ifdef DEBUG_VIDEO - intf_DbgMsg("subpicture %p (in free subpicture slot)\n", p_free_subpic ); +#ifdef TRACE_VOUT + intf_DbgMsg("subpicture %p (in free subpicture slot)", p_free_subpic ); #endif vlc_mutex_unlock( &p_vout->subpicture_lock ); return( p_free_subpic ); } /* No free or destroyed subpicture could be found */ - intf_DbgMsg( "warning: subpicture heap is full\n" ); + intf_DbgMsg( "warning: subpicture heap is full" ); vlc_mutex_unlock( &p_vout->subpicture_lock ); return( NULL ); } @@ -492,15 +474,15 @@ void vout_DestroySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) /* Check if status is valid */ if( p_subpic->i_status != RESERVED_SUBPICTURE ) { - intf_DbgMsg("error: subpicture %p has invalid status %d\n", + intf_ErrMsg("error: subpicture %p has invalid status %d", p_subpic, p_subpic->i_status ); } #endif p_subpic->i_status = DESTROYED_SUBPICTURE; -#ifdef DEBUG_VIDEO - intf_DbgMsg("subpicture %p\n", p_subpic); +#ifdef TRACE_VOUT + intf_DbgMsg("subpicture %p", p_subpic); #endif } @@ -524,13 +506,13 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) break; #ifdef DEBUG default: - intf_DbgMsg("error: picture %p has invalid status %d\n", p_pic, p_pic->i_status ); + intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status ); break; #endif } -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p\n", p_pic); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p", p_pic); #endif vlc_mutex_unlock( &p_vout->picture_lock ); } @@ -544,7 +526,7 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) *****************************************************************************/ void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date ) { -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT char psz_date[MSTRTIME_MAX_SIZE]; /* date */ #endif @@ -560,13 +542,13 @@ void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date ) break; #ifdef DEBUG default: - intf_DbgMsg("error: picture %p has invalid status %d\n", p_pic, p_pic->i_status ); + intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status ); break; #endif } -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p, display date: %s\n", p_pic, mstrtime( psz_date, p_pic->date) ); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p, display date: %s", p_pic, mstrtime( psz_date, p_pic->date) ); #endif vlc_mutex_unlock( &p_vout->picture_lock ); } @@ -609,8 +591,8 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, * memory allocation needs to be done */ p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE; p_vout->i_pictures++; -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p (in destroyed picture slot)\n", +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p (in destroyed picture slot)", &p_vout->p_picture[i_picture] ); #endif vlc_mutex_unlock( &p_vout->picture_lock ); @@ -671,7 +653,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, break; #ifdef DEBUG default: - intf_DbgMsg("error: unknown picture type %d\n", i_type ); + intf_ErrMsg("error: unknown picture type %d", i_type ); p_free_picture->p_data = NULL; break; #endif @@ -686,6 +668,9 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, p_free_picture->i_width = i_width; p_free_picture->i_height = i_height; p_free_picture->i_chroma_width = i_chroma_width; + p_free_picture->i_size = i_width * i_height; + p_free_picture->i_chroma_size = i_chroma_width + * i_height; p_free_picture->i_display_horizontal_offset = 0; p_free_picture->i_display_vertical_offset = 0; p_free_picture->i_display_width = i_width; @@ -700,18 +685,23 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, p_free_picture->i_type = EMPTY_PICTURE; p_free_picture->i_status = FREE_PICTURE; p_free_picture = NULL; - intf_ErrMsg("vout warning: %s\n", strerror( ENOMEM ) ); + intf_ErrMsg( "vout error: picture allocation returned %s", + strerror( ENOMEM ) ); } -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture ); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p (in free picture slot)", p_free_picture ); #endif vlc_mutex_unlock( &p_vout->picture_lock ); + + /* Initialize mutex */ + vlc_mutex_init( &(p_free_picture->lock_deccount) ); + return( p_free_picture ); } /* No free or destroyed picture could be found */ - intf_DbgMsg( "warning: picture heap is full\n" ); + intf_DbgMsg( "warning: picture heap is full" ); vlc_mutex_unlock( &p_vout->picture_lock ); return( NULL ); } @@ -725,25 +715,29 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, *****************************************************************************/ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) { - vlc_mutex_lock( &p_vout->picture_lock ); + vlc_mutex_lock( &p_vout->picture_lock ); #ifdef DEBUG - /* Check if picture status is valid */ - if( (p_pic->i_status != RESERVED_PICTURE) && - (p_pic->i_status != RESERVED_DATED_PICTURE) && - (p_pic->i_status != RESERVED_DISP_PICTURE) ) - { - intf_DbgMsg("error: picture %p has invalid status %d\n", p_pic, p_pic->i_status ); - } + /* Check if picture status is valid */ + if( (p_pic->i_status != RESERVED_PICTURE) && + (p_pic->i_status != RESERVED_DATED_PICTURE) && + (p_pic->i_status != RESERVED_DISP_PICTURE) ) + { + intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status ); + } #endif - p_pic->i_status = DESTROYED_PICTURE; - p_vout->i_pictures--; + p_pic->i_status = DESTROYED_PICTURE; + p_vout->i_pictures--; -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p\n", p_pic); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p", p_pic); #endif - vlc_mutex_unlock( &p_vout->picture_lock ); + + /* destroy the lock that had been initialized in CreatePicture */ + vlc_mutex_destroy( &(p_pic->lock_deccount) ); + + vlc_mutex_unlock( &p_vout->picture_lock ); } /***************************************************************************** @@ -757,8 +751,8 @@ void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) vlc_mutex_lock( &p_vout->picture_lock ); p_pic->i_refcount++; -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p refcount=%d\n", p_pic, p_pic->i_refcount ); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p refcount=%d", p_pic, p_pic->i_refcount ); #endif vlc_mutex_unlock( &p_vout->picture_lock ); @@ -774,10 +768,10 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) vlc_mutex_lock( &p_vout->picture_lock ); p_pic->i_refcount--; -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT if( p_pic->i_refcount < 0 ) { - intf_DbgMsg("error: refcount < 0\n"); + intf_DbgMsg("error: refcount < 0"); p_pic->i_refcount = 0; } #endif @@ -788,8 +782,8 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) p_vout->i_pictures--; } -#ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p refcount=%d\n", p_pic, p_pic->i_refcount ); +#ifdef TRACE_VOUT + intf_DbgMsg("picture %p refcount=%d", p_pic, p_pic->i_refcount ); #endif vlc_mutex_unlock( &p_vout->picture_lock ); @@ -849,32 +843,32 @@ void vout_Pixel2RGB( vout_thread_t *p_vout, u32 i_pixel, int *pi_red, int *pi_gr *****************************************************************************/ static int BinaryLog(u32 i) { - int i_log; + int i_log = 0; - i_log = 0; - if (i & 0xffff0000) + if(i & 0xffff0000) { - i_log = 16; + i_log += 16; } - if (i & 0xff00ff00) + if(i & 0xff00ff00) { i_log += 8; } - if (i & 0xf0f0f0f0) + if(i & 0xf0f0f0f0) { i_log += 4; } - if (i & 0xcccccccc) + if(i & 0xcccccccc) { i_log += 2; } - if (i & 0xaaaaaaaa) + if(i & 0xaaaaaaaa) { - i_log++; + i_log += 1; } + if (i != ((u32)1 << i_log)) { - intf_DbgMsg("internal error: binary log overflow\n"); + intf_DbgMsg("internal error: binary log overflow"); } return( i_log ); @@ -912,11 +906,16 @@ static void MaskToShift( int *pi_left, int *pi_right, u32 i_mask ) static int InitThread( vout_thread_t *p_vout ) { /* Update status */ - intf_DbgMsg("\n"); *p_vout->pi_status = THREAD_START; + vlc_mutex_lock( &p_vout->change_lock ); + +#ifdef STATS + p_vout->c_loops = 0; +#endif + /* Initialize output method - this function issues its own error messages */ - if( p_vout->p_sys_init( p_vout ) ) + if( p_vout->pf_init( p_vout ) ) { return( 1 ); } @@ -924,7 +923,7 @@ static int InitThread( vout_thread_t *p_vout ) /* Initialize convertion tables and functions */ if( vout_InitYUV( p_vout ) ) { - intf_ErrMsg("error: can't allocate YUV translation tables\n"); + intf_ErrMsg("vout error: can't allocate YUV translation tables"); return( 1 ); } @@ -933,7 +932,7 @@ static int InitThread( vout_thread_t *p_vout ) *p_vout->pi_status = THREAD_READY; - intf_DbgMsg("thread ready\n"); + intf_DbgMsg("thread ready"); return( 0 ); } @@ -962,7 +961,6 @@ static void RunThread( vout_thread_t *p_vout) DestroyThread( p_vout, THREAD_ERROR ); return; } - intf_DbgMsg("\n"); /* * Main loop - it is not executed if an error occured during @@ -975,6 +973,14 @@ static void RunThread( vout_thread_t *p_vout) p_subpic = NULL; display_date = 0; current_date = mdate(); +#ifdef STATS + p_vout->c_loops++; + if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) ) + { + intf_Msg("vout stats: picture heap: %d/%d", + p_vout->i_pictures, VOUT_MAX_PICTURES); + } +#endif /* * Find the picture to display - this operation does not need lock, @@ -993,11 +999,10 @@ static void RunThread( vout_thread_t *p_vout) if( p_pic ) { -#ifdef STATS /* Computes FPS rate */ p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = display_date; -#endif - if( display_date < current_date ) + + if( display_date < current_date - p_vout->render_time ) { /* Picture is late: it will be destroyed and the thread * will sleep and go to next picture */ @@ -1012,10 +1017,11 @@ static void RunThread( vout_thread_t *p_vout) p_pic->i_status = DESTROYED_PICTURE; p_vout->i_pictures--; } - intf_ErrMsg( "warning: late picture skipped (%p)\n", p_pic ); + intf_WarnMsg( 3, + "warning: late picture skipped (%p)", p_pic ); vlc_mutex_unlock( &p_vout->picture_lock ); - continue; + continue; } else if( display_date > current_date + VOUT_DISPLAY_DELAY ) { @@ -1050,12 +1056,19 @@ static void RunThread( vout_thread_t *p_vout) { b_display = p_vout->b_active; p_vout->last_display_date = display_date; + p_vout->p_rendered_pic = p_pic; - if( b_display ) - { - /* Set picture dimensions and clear buffer */ - SetBufferPicture( p_vout, p_pic ); + + + /* Set picture dimensions and clear buffer */ + SetBufferPicture( p_vout, p_pic ); + + /* FIXME: if b_need_render == 0 we need to do something with + * the subpictures one day. */ + + if( p_vout->b_need_render && b_display ) + { /* Render picture and information */ RenderPicture( p_vout, p_pic ); if( p_vout->b_info ) @@ -1069,28 +1082,18 @@ static void RunThread( vout_thread_t *p_vout) } } - /* 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 ) + if( b_display && p_vout->b_interface && p_vout->b_need_render ) { RenderInterface( p_vout ); } } - else if( p_vout->b_active && p_vout->init_display_date == 0) /* idle or interface screen alone */ + else if( p_vout->b_active && p_vout->b_need_render + && p_vout->init_display_date == 0) { + /* Idle or interface screen alone */ + if( p_vout->b_interface && 0 /* && XXX?? intf_change */ ) { /* Interface has changed, so a new rendering is required - force @@ -1118,10 +1121,10 @@ static void RunThread( vout_thread_t *p_vout) /* - * chech for the current time and + * Check for the current time and * display splash screen if everything is on time */ - if( p_vout->init_display_date > 0) + if( p_vout->init_display_date > 0 && p_vout->b_need_render ) { if( p_vout->b_active && mdate()-p_vout->init_display_date < 5000000) @@ -1132,21 +1135,18 @@ static void RunThread( vout_thread_t *p_vout) } else { /* no splash screen ! */ - intf_ErrMsgImm("End of splash screen\n"); p_vout->init_display_date=0; } } - - /* * Sleep, wake up and display rendered picture */ if( display_date != 0 ) { - /* Store render time */ + /* Store render time using Bresenham algorithm */ p_vout->render_time += mdate() - current_date; p_vout->render_time >>= 1; } @@ -1154,14 +1154,6 @@ static void RunThread( vout_thread_t *p_vout) /* Give back change lock */ vlc_mutex_unlock( &p_vout->change_lock ); -#ifdef DEBUG_VIDEO - { - char psz_date[MSTRTIME_MAX_SIZE]; - intf_DbgMsg( "picture %p waiting until %s\n", p_pic, - mstrtime(psz_date, display_date), - } -#endif - /* Sleep a while or until a given date */ if( display_date != 0 ) { @@ -1175,22 +1167,39 @@ static void RunThread( vout_thread_t *p_vout) /* 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, +#ifdef TRACE_VOUT + intf_DbgMsg( "picture %p, subpicture %p in buffer %d, display=%d", 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 ); + p_vout->pf_display( p_vout ); #ifndef SYS_BEOS p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1; #endif } + if( p_pic ) + { + /* 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 ); + } + + /* * Check events and manage thread */ - if( p_vout->p_sys_manage( p_vout ) | Manage( p_vout ) ) + if( p_vout->pf_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 @@ -1210,7 +1219,7 @@ static void RunThread( vout_thread_t *p_vout) /* End of thread */ EndThread( p_vout ); DestroyThread( p_vout, THREAD_OVER ); - intf_DbgMsg( "thread end\n" ); + intf_DbgMsg( "thread end" ); } /***************************************************************************** @@ -1223,7 +1232,6 @@ static void RunThread( vout_thread_t *p_vout) static void ErrorThread( vout_thread_t *p_vout ) { /* Wait until a `die' order */ - intf_DbgMsg("\n"); while( !p_vout->b_die ) { /* Sleep a while */ @@ -1242,9 +1250,18 @@ 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; +#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 ); + } +#endif + /* Destroy all remaining pictures and subpictures */ for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ ) { @@ -1253,6 +1270,7 @@ static void EndThread( vout_thread_t *p_vout ) 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 ) @@ -1263,7 +1281,10 @@ static void EndThread( vout_thread_t *p_vout ) /* Destroy translation tables */ vout_EndYUV( p_vout ); - p_vout->p_sys_end( p_vout ); + p_vout->pf_end( p_vout ); + + /* Release the change lock */ + vlc_mutex_unlock( &p_vout->change_lock ); } /***************************************************************************** @@ -1277,13 +1298,20 @@ 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 ); + p_vout->pf_destroy( p_vout ); + + /* 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 ); @@ -1382,8 +1410,8 @@ static void SetBufferArea( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int } else { -#ifdef DEBUG_VIDEO - intf_DbgMsg("area overflow\n"); +#ifdef TRACE_VOUT + intf_DbgMsg("area overflow"); #endif p_buffer->pi_area_end[VOUT_MAX_AREAS - 1] = i_h; } @@ -1406,8 +1434,8 @@ static void SetBufferArea( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int * move all old areas down */ if( p_buffer->i_areas == VOUT_MAX_AREAS ) { -#ifdef DEBUG_VIDEO - intf_DbgMsg("areas overflow\n"); +#ifdef TRACE_VOUT + intf_DbgMsg("areas overflow"); #endif p_buffer->pi_area_end[VOUT_MAX_AREAS - 2] = p_buffer->pi_area_end[VOUT_MAX_AREAS - 1]; } @@ -1440,7 +1468,7 @@ static void SetBufferArea( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int if( i_area_copy != i_area ) { /* Merge with last possible areas */ - p_buffer->pi_area_end[i_area] = MAX( i_h, p_buffer->pi_area_end[i_area_copy] ); + //p_buffer->pi_area_end[i_area] = MAX( i_h, p_buffer->pi_area_end[i_area_copy] ); /* Shift lower areas upward */ i_area_shift = i_area_copy - i_area; @@ -1543,6 +1571,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) /* Set picture position */ i_pic_x = (p_vout->i_width - i_pic_width) / 2; i_pic_y = (p_vout->i_height - i_pic_height) / 2; + } else { @@ -1580,12 +1609,13 @@ 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 in buffer %d: %d-%d\n", p_pic, +#ifdef TRACE_VOUT + intf_DbgMsg("clearing picture %p area in buffer %d: %d-%d", 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]); + for( i_data_index = i_data_size / 256; i_data_index-- ; ) { /* Clear 256 bytes block */ @@ -1627,7 +1657,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) *****************************************************************************/ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) { -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT char psz_date[MSTRTIME_MAX_SIZE]; /* picture date */ mtime_t render_time; /* picture rendering time */ #endif @@ -1639,49 +1669,51 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) p_pic_data = p_buffer->p_data + p_buffer->i_pic_x * p_vout->i_bytes_per_pixel + p_buffer->i_pic_y * p_vout->i_bytes_per_line; -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT render_time = mdate(); #endif + + /* * Choose appropriate rendering function and render picture */ switch( p_pic->i_type ) { case YUV_420_PICTURE: - p_vout->yuv.p_Convert420( p_vout, p_pic_data, - p_pic->p_y, p_pic->p_u, p_pic->p_v, - p_pic->i_width, p_pic->i_height, - p_buffer->i_pic_width, p_buffer->i_pic_height, - p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, - p_pic->i_matrix_coefficients ); + p_vout->yuv.pf_yuv420( p_vout, p_pic_data, + p_pic->p_y, p_pic->p_u, p_pic->p_v, + p_pic->i_width, p_pic->i_height, + p_buffer->i_pic_width, p_buffer->i_pic_height, + p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, + p_pic->i_matrix_coefficients ); break; case YUV_422_PICTURE: - p_vout->yuv.p_Convert422( p_vout, p_pic_data, - p_pic->p_y, p_pic->p_u, p_pic->p_v, - p_pic->i_width, p_pic->i_height, - p_buffer->i_pic_width, p_buffer->i_pic_height, - p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, - p_pic->i_matrix_coefficients ); + p_vout->yuv.pf_yuv422( p_vout, p_pic_data, + p_pic->p_y, p_pic->p_u, p_pic->p_v, + p_pic->i_width, p_pic->i_height, + p_buffer->i_pic_width, p_buffer->i_pic_height, + p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, + p_pic->i_matrix_coefficients ); break; case YUV_444_PICTURE: - p_vout->yuv.p_Convert444( p_vout, p_pic_data, - p_pic->p_y, p_pic->p_u, p_pic->p_v, - p_pic->i_width, p_pic->i_height, - p_buffer->i_pic_width, p_buffer->i_pic_height, - p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, - p_pic->i_matrix_coefficients ); + p_vout->yuv.pf_yuv444( p_vout, p_pic_data, + p_pic->p_y, p_pic->p_u, p_pic->p_v, + p_pic->i_width, p_pic->i_height, + p_buffer->i_pic_width, p_buffer->i_pic_height, + p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, + p_pic->i_matrix_coefficients ); break; #ifdef DEBUG default: - intf_DbgMsg("error: unknown picture type %d\n", p_pic->i_type ); + intf_ErrMsg("error: unknown picture type %d", p_pic->i_type ); break; #endif } -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT /* Print picture date and rendering time */ - intf_DbgMsg("picture %p rendered in buffer %d (%ld us), display date: %s\n", p_pic, + intf_DbgMsg("picture %p rendered in buffer %d (%ld us), display date: %s", p_pic, p_vout->i_buffer_index, (long) (mdate() - render_time), mstrtime( psz_date, p_pic->date )); #endif @@ -1695,11 +1727,8 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) *****************************************************************************/ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic ) { -#if defined(STATS) || defined(DEBUG) char psz_buffer[256]; /* string buffer */ -#endif -#ifdef STATS /* * Print FPS rate in upper right corner */ @@ -1720,9 +1749,8 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic ) sprintf( psz_buffer, "%ld frames, render: %ldus", (long) p_vout->c_fps_samples, (long) p_vout->render_time ); Print( p_vout, 0, 0, LEFT_RALIGN, TOP_RALIGN, psz_buffer ); -#endif -#ifdef DEBUG +#ifdef STATS /* * Print picture information in lower right corner */ @@ -1793,12 +1821,14 @@ int RenderSplash( vout_thread_t *p_vout ) *****************************************************************************/ int RenderIdle( vout_thread_t *p_vout ) { +#if 0 int i_x = 0, i_y = 0; /* text position */ int i_width, i_height; /* text size */ - mtime_t current_date; /* current date */ int i_amount = 0; /* amount to draw */ char *psz_text = "Waiting for stream"; /* text to display */ char *psz_wtext = "[................]"; +#endif + mtime_t current_date; /* current date */ memset( p_vout->p_buffer[ p_vout->i_buffer_index ].p_data, @@ -1810,6 +1840,8 @@ int RenderIdle( vout_thread_t *p_vout ) // && (current_date - p_vout->last_idle_date) > VOUT_IDLE_DELAY ) { + /* FIXME: idle screen disabled */ +#if 0 SetBufferPicture( p_vout, NULL ); vout_TextSize( p_vout->p_large_font, WIDE_TEXT | OUTLINED_TEXT, psz_text, &i_width, &i_height ); @@ -1833,6 +1865,7 @@ int RenderIdle( vout_thread_t *p_vout ) SetBufferArea( p_vout, i_x, i_y, i_width, i_height * 2 ); } +#endif return( 1 ); } return( 0 ); @@ -1940,7 +1973,7 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) #ifdef DEBUG default: - intf_DbgMsg( "error: unknown subpicture %p type %d\n", + intf_ErrMsg( "error: unknown subpicture %p type %d", p_subpic, p_subpic->i_type ); #endif } @@ -2005,10 +2038,10 @@ static void RenderInterface( vout_thread_t *p_vout ) *****************************************************************************/ static int Manage( vout_thread_t *p_vout ) { -#ifdef DEBUG_VIDEO +#ifdef TRACE_VOUT if( p_vout->i_changes ) { - intf_DbgMsg("changes: 0x%x (no display: 0x%x)\n", p_vout->i_changes, + intf_DbgMsg("changes: 0x%x (no display: 0x%x)", p_vout->i_changes, 0 /* p_vout->i_changes & VOUT_NODISPLAY_CHANGE */ ); } #endif @@ -2017,34 +2050,26 @@ static int Manage( vout_thread_t *p_vout ) if( p_vout->i_changes & (VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE | VOUT_YUV_CHANGE) ) { - /* Change vdec_DecodeMacroblock when switching between BW and C */ - if( !p_vout->b_grayscale ) - { - p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockC; - } - else if( p_vout->b_grayscale) - { - p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockBW; - } if( vout_ResetYUV( p_vout ) ) { - intf_ErrMsg("error: can't rebuild convertion tables\n"); + intf_ErrMsg( "vout error: can't rebuild conversion tables" ); return( 1 ); } } /* Clear changes flags which does not need management or have been * handled */ - p_vout->i_changes &= ~(VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE | - VOUT_YUV_CHANGE | VOUT_INFO_CHANGE | - VOUT_INTF_CHANGE | VOUT_SCALE_CHANGE ); + p_vout->i_changes &= ~(VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE | + VOUT_YUV_CHANGE | VOUT_INFO_CHANGE | + VOUT_INTF_CHANGE | VOUT_SCALE_CHANGE | + VOUT_CURSOR_CHANGE | VOUT_FULLSCREEN_CHANGE ); /* Detect unauthorized changes */ if( p_vout->i_changes ) { - /* Some changes were not acknowledged by p_vout->p_sys_manage or this + /* Some changes were not acknowledged by p_vout->pf_manage or this * function, it means they should not be authorized */ - intf_ErrMsg( "error: unauthorized changes in the video output thread\n" ); + intf_ErrMsg( "vout error: unauthorized changes in the vout thread" ); return( 1 ); } @@ -2113,6 +2138,6 @@ static int Align( vout_thread_t *p_vout, int *pi_x, int *pi_y, static void SetPalette ( p_vout_thread_t p_vout, u16 *red, u16 *green, u16 *blue, u16 *transp ) { - intf_ErrMsg( "SetPalette: method does not support palette changing\n" ); + intf_ErrMsg( "vout error: method does not support palette changing" ); }