From 62ee3e006812818f41fb448887ed2870bc6cbd16 Mon Sep 17 00:00:00 2001 From: Jean-Marc Dressler Date: Thu, 17 Feb 2000 00:43:58 +0000 Subject: [PATCH] =?UTF-8?q?Corrections=20de=20quelques=20petits=20bugs=20e?= =?UTF-8?q?t=20surtout=20nouvelle=20synchro=20qui=20ne=20semble=20pas=20tr?= =?UTF-8?q?op=20mal=20marcher=20sur=20ma=20machine=20mais=20qui=20j'en=20s?= =?UTF-8?q?uis=20s=EF=BF=BDr=20ne=20marchera=20pas=20du=20tout=20sur=20la?= =?UTF-8?q?=20votre.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A noter qu'il existe maintenant 3 synchros que l'on peut choisir en changeant le define dans vpar_synchro.h (POLUX_SYNCHRO, SAM_SYNCHRO, MEUUH_SYNCHRO) --- include/config.h | 8 ++ include/video_output.h | 8 +- include/vpar_synchro.h | 27 +++++- src/input/input.c | 9 +- src/video_output/video_output.c | 131 +++++++++++++++++++++++++--- src/video_parser/video_parser.c | 15 +++- src/video_parser/vpar_blocks.c | 51 +++++++++-- src/video_parser/vpar_headers.c | 26 ++++-- src/video_parser/vpar_synchro.c | 146 +++++++++++++++++++++++++++++++- 9 files changed, 385 insertions(+), 36 deletions(-) diff --git a/include/config.h b/include/config.h index d4db0df099..f306145a6b 100644 --- a/include/config.h +++ b/include/config.h @@ -376,3 +376,11 @@ /* Maximal number of commands which can be saved in history list */ #define INTF_CONSOLE_MAX_HISTORY 20 + +/***************************************************************************** + * Synchro configuration + *****************************************************************************/ + +#define VOUT_SYNCHRO_LEVEL_START 5 +#define VOUT_SYNCHRO_LEVEL_MAX 15 +#define VOUT_SYNCHRO_HEAP_IDEAL_SIZE 5 diff --git a/include/video_output.h b/include/video_output.h index d054908d8d..00b2ca0e2d 100644 --- a/include/video_output.h +++ b/include/video_output.h @@ -159,22 +159,26 @@ typedef struct vout_thread_s * good indication of the thread status */ mtime_t render_time; /* last picture render time */ count_t c_fps_samples; /* picture counts */ - mtime_t p_fps_sample[ VOUT_FPS_SAMPLES ];/* FPS samples dates */ + mtime_t p_fps_sample[VOUT_FPS_SAMPLES]; /* FPS samples dates */ #endif /* Rendering buffers */ int i_buffer_index; /* buffer index */ vout_buffer_t p_buffer[2]; /* buffers properties */ - /* Videos heap and translation tables */ + /* Videos heap and translation tables */ picture_t p_picture[VOUT_MAX_PICTURES]; /* pictures */ subpicture_t p_subpicture[VOUT_MAX_PICTURES]; /* subpictures */ + int i_pictures; /* current heap size */ vout_yuv_t yuv; /* translation tables */ /* Bitmap fonts */ p_vout_font_t p_default_font; /* default font */ p_vout_font_t p_large_font; /* large font */ + /* Synchronisation informations - synchro level is updated by the vout + * thread and read by decoder threads */ + int i_synchro_level; /* trashing level */ } vout_thread_t; /* Output methods */ diff --git a/include/vpar_synchro.h b/include/vpar_synchro.h index 7a0eae4184..bde125bfc7 100644 --- a/include/vpar_synchro.h +++ b/include/vpar_synchro.h @@ -15,7 +15,7 @@ * "video_fifo.h" *****************************************************************************/ -#define SAM_SYNCHRO +#define POLUX_SYNCHRO /***************************************************************************** * video_synchro_t and video_synchro_tab_s : timers for the video synchro @@ -80,7 +80,9 @@ typedef struct video_synchro_s double actual_fps; } video_synchro_t; -#else +#endif + +#ifdef MEUUH_SYNCHRO typedef struct video_synchro_s { int kludge_level, kludge_p, kludge_b, kludge_nbp, kludge_nbb; @@ -93,6 +95,27 @@ typedef struct video_synchro_s #define SYNC_DELAY 500000 #endif +#ifdef POLUX_SYNCHRO + +typedef struct video_synchro_s +{ + /* Date Section */ + + /* Dates needed to compute the date of the current frame + * We also use the stream frame rate (sequence.r_frame_rate) */ + mtime_t i_current_frame_date; + mtime_t i_backward_frame_date; + + /* Frame Trashing Section */ + + int i_b_nb, i_p_nb; /* number of decoded P and B between two I */ + int i_b_count, i_p_count, i_i_count; + int i_b_trasher; /* used for brensenham algorithm */ + +} video_synchro_t; + +#endif + /***************************************************************************** * Prototypes *****************************************************************************/ diff --git a/src/input/input.c b/src/input/input.c index 54a2ab6b71..615bbc4f96 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -893,11 +893,12 @@ static __inline__ void input_DemuxPES( input_thread_t *p_input, /* This part of the header does not fit in the current TS packet: copy the part of the header we are interested in to the p_pes_header_save buffer. The buffer is dynamicly allocated if - needed so it's time expensive but this situation almost never - occur. */ + needed so it's time expensive but this situation almost never occur. */ intf_DbgMsg("Code never tested encountered, WARNING ! (benny)\n"); - if( !p_pes->p_pes_header_save ) - p_pes->p_pes_header_save = malloc(PES_HEADER_SIZE); + if( !p_pes->p_pes_header_save ) + { + p_pes->p_pes_header_save = malloc(PES_HEADER_SIZE); + } do { diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index c82a0fd4ba..679ca814ac 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -50,6 +50,7 @@ static void RenderSubPicture ( vout_thread_t *p_vout, 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 void Synchronize ( vout_thread_t *p_vout, s64 i_delay ); 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, @@ -210,6 +211,10 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE; p_vout->p_subpicture[i_index].i_status= FREE_SUBPICTURE; } + p_vout->i_pictures = 0; + + /* Initialize synchronization informations */ + p_vout->i_synchro_level = VOUT_SYNCHRO_LEVEL_START; /* Create and initialize system-dependant method - this function issues its * own error messages */ @@ -599,6 +604,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, * can end immediately - this is the best possible case, since no * 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", &p_vout->p_picture[i_picture] ); @@ -682,6 +688,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, p_free_picture->i_display_height = i_height; p_free_picture->i_aspect_ratio = AR_SQUARE_PICTURE; p_free_picture->i_refcount = 0; + p_vout->i_pictures++; } else { @@ -711,11 +718,11 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, * This function frees a previously reserved picture or a permanent * picture. It is meant to be used when the construction of a picture aborted. * Note that the picture will be destroyed even if it is linked ! - * This function does not need locking since reserved pictures are ignored by - * the output thread. *****************************************************************************/ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) { + vlc_mutex_lock( &p_vout->picture_lock ); + #ifdef DEBUG /* Check if picture status is valid */ if( (p_pic->i_status != RESERVED_PICTURE) && @@ -726,11 +733,13 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) } #endif - p_pic->i_status = DESTROYED_PICTURE; + p_pic->i_status = DESTROYED_PICTURE; + p_vout->i_pictures--; #ifdef DEBUG_VIDEO - intf_DbgMsg("picture %p\n", p_pic); + intf_DbgMsg("picture %p\n", p_pic); #endif + vlc_mutex_unlock( &p_vout->picture_lock ); } /***************************************************************************** @@ -772,6 +781,7 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) ) { p_pic->i_status = DESTROYED_PICTURE; + p_vout->i_pictures--; } #ifdef DEBUG_VIDEO @@ -981,18 +991,35 @@ static void RunThread( vout_thread_t *p_vout) /* Computes FPS rate */ p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = display_date; #endif +#if 0 if( display_date < current_date ) { /* Picture is late: it will be destroyed and the thread will sleep and * go to next picture */ + vlc_mutex_lock( &p_vout->picture_lock ); - p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE; - intf_DbgMsg( "warning: late picture %p skipped refcount=%d\n", p_pic, p_pic->i_refcount ); + 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 ); + p_pic = NULL; display_date = 0; + + /* Update synchronization information as if display delay + * was 0 */ + Synchronize( p_vout, 0 ); } - else if( display_date > current_date + VOUT_DISPLAY_DELAY ) + 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 @@ -1000,6 +1027,12 @@ static void RunThread( vout_thread_t *p_vout) p_pic = NULL; display_date = 0; } + else + { + /* Picture will be displayed, update synchronization + * information */ + Synchronize( p_vout, display_date - current_date ); + } } /* @@ -1033,7 +1066,15 @@ static void RunThread( vout_thread_t *p_vout) /* Remove picture from heap */ vlc_mutex_lock( &p_vout->picture_lock ); - p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE; + 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 */ @@ -1767,8 +1808,8 @@ static void RenderInfo( vout_thread_t *p_vout ) break; } } - sprintf( psz_buffer, "pic: %d/%d/%d", - i_reserved_pic, i_ready_pic, VOUT_MAX_PICTURES ); + sprintf( psz_buffer, "pic: %d (%d/%d)/%d", + p_vout->i_pictures, i_reserved_pic, i_ready_pic, VOUT_MAX_PICTURES ); Print( p_vout, 0, 0, LEFT_RALIGN, BOTTOM_RALIGN, psz_buffer ); #endif } @@ -1865,6 +1906,76 @@ static void RenderInterface( vout_thread_t *p_vout ) SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height ); } +/***************************************************************************** + * Synchronize: update synchro level depending of heap state + ***************************************************************************** + * This function is called during the main vout loop. + *****************************************************************************/ +static void Synchronize( vout_thread_t *p_vout, s64 i_delay ) +{ + int i_synchro_inc = 0; + //???? gore following + static int i_panic_count = 0; + static int i_last_synchro_inc = 0; + static float r_synchro_level = VOUT_SYNCHRO_LEVEL_START; + static int i_truc = 1; + + //?? heap size is p_vout->i_pictures + //?? + if( i_delay < 0 ) + { +// intf_Msg("PANIC %d\n", i_panic_count++); + } +/* + if( p_vout->i_pictures > VOUT_SYNCHRO_HEAP_IDEAL_SIZE+1 ) + { + i_synchro_inc++; + } + else if( p_vout->i_pictures < VOUT_SYNCHRO_HEAP_IDEAL_SIZE ) + { + i_synchro_inc--; + } +*/ + if( i_delay < 10000 ) + { + i_truc = 4; + } + + if( i_delay < 20000 ) + { + i_synchro_inc--; + } + else if( i_delay > 50000 ) + { + i_synchro_inc++; + } + + if( i_synchro_inc*i_last_synchro_inc < 0 ) + { + i_truc = 2; + } + else + { + i_truc *= 2; + } + if( i_truc > VOUT_SYNCHRO_LEVEL_MAX || i_delay == 0 ) + { + i_truc = 2; + } + + r_synchro_level += (float)i_synchro_inc / i_truc; + p_vout->i_synchro_level = (int) r_synchro_level; + + if( r_synchro_level > VOUT_SYNCHRO_LEVEL_MAX ) + { + r_synchro_level = VOUT_SYNCHRO_LEVEL_MAX; + } + +// printf( "synchro level : %d, (%d, %d) (%d, %f) - %Ld\n", p_vout->i_synchro_level, +// i_last_synchro_inc, i_synchro_inc, i_truc, r_synchro_level, i_delay ); + i_last_synchro_inc = i_synchro_inc; +} + /***************************************************************************** * Manage: manage thread ***************************************************************************** diff --git a/src/video_parser/video_parser.c b/src/video_parser/video_parser.c index 1bc525264c..898de5c832 100644 --- a/src/video_parser/video_parser.c +++ b/src/video_parser/video_parser.c @@ -292,7 +292,9 @@ static int InitThread( vpar_thread_t *p_vpar ) p_vpar->synchro.tab_b[i_dummy].mean = 6; p_vpar->synchro.tab_b[i_dummy].deviation = .5; } -#else +#endif + +#ifdef MEUUH_SYNCHRO p_vpar->synchro.kludge_level = 5; p_vpar->synchro.kludge_nbp = p_vpar->synchro.kludge_p = 5; p_vpar->synchro.kludge_nbb = p_vpar->synchro.kludge_b = 6; @@ -300,6 +302,17 @@ static int InitThread( vpar_thread_t *p_vpar ) p_vpar->synchro.kludge_prevdate = 0; #endif +#ifdef POLUX_SYNCHRO + p_vpar->synchro.i_current_frame_date = 0; + p_vpar->synchro.i_backward_frame_date = 0; + + p_vpar->synchro.i_p_nb = 5; + p_vpar->synchro.i_b_nb = 6; + p_vpar->synchro.i_p_count = 0; + p_vpar->synchro.i_b_count = 0; + p_vpar->synchro.i_i_count = 0; +#endif + /* Mark thread as running and return */ intf_DbgMsg("vpar debug: InitThread(%p) succeeded\n", p_vpar); return( 0 ); diff --git a/src/video_parser/vpar_blocks.c b/src/video_parser/vpar_blocks.c index 70e13d3542..395efb8343 100644 --- a/src/video_parser/vpar_blocks.c +++ b/src/video_parser/vpar_blocks.c @@ -37,6 +37,19 @@ #include "video_parser.h" #include "video_fifo.h" + + + + + + +static int i_count = 0; + + + + + + /* * Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing * task is done. This file is divided in several parts : @@ -530,9 +543,11 @@ void vpar_InitDCTTables( vpar_thread_t * p_vpar ) p_vpar->pppl_dct_dc_size[1][0] = pl_dct_dc_chrom_init_table_1; p_vpar->pppl_dct_dc_size[1][1] = pl_dct_dc_chrom_init_table_2; - memset( p_vpar->ppl_dct_coef[0], MB_ERROR, 16 ); - memset( p_vpar->ppl_dct_coef[1], MB_ERROR, 16 ); - + /* ??? MB_ERROR is replaced by 0 because if we use -1 we + * can block in DecodeMPEG2Intra and others */ + memset( p_vpar->ppl_dct_coef[0], 0, 16 ); + memset( p_vpar->ppl_dct_coef[1], 0, 16 ); + /* For table B14 & B15, we have a pointer to tables */ /* We fill the table thanks to the fonction defined above */ FillDCTTable( p_vpar->ppl_dct_coef[0], pl_DCT_tab0, 256, 60, 4 ); @@ -1614,14 +1629,24 @@ static __inline__ void ParseMacroblock( static int pi_x[12] = {0,8,0,8,0,0,0,0,8,8,8,8}; static int pi_y[2][12] = { {0,0,8,8,0,0,8,8,0,0,8,8}, {0,0,1,1,0,0,1,1,0,0,1,1} }; - int i_mb, i_b, i_mask; + int i_inc; macroblock_t * p_mb; yuv_data_t * p_data1; yuv_data_t * p_data2; - *pi_mb_address += MacroblockAddressIncrement( p_vpar ); +i_count++; + i_inc = MacroblockAddressIncrement( p_vpar ); + *pi_mb_address += i_inc; + + if( i_inc < 0 ) + { + fprintf( stderr, "vpar error: bad address increment (%d)\n", i_inc ); + p_vpar->picture.b_error = 1; + return; + } + if( *pi_mb_address - i_mb_previous - 1 ) { /* Skipped macroblock (ISO/IEC 13818-2 7.6.6). */ @@ -1833,9 +1858,16 @@ static __inline__ void SliceHeader( vpar_thread_t * p_vpar, { RemoveBits( &p_vpar->bit_stream, 8 ); } - } + } *pi_mb_address = (i_vert_code - 1)*p_vpar->sequence.i_mb_width; + if( *pi_mb_address < i_mb_address_save ) + { + fprintf( stderr, "vpar error: slices do not follow, maybe a PES has been trashed\n" ); + p_vpar->picture.b_error = 1; + return; + } + /* Reset DC coefficients predictors (ISO/IEC 13818-2 7.2.1). */ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1] = p_vpar->mb.pi_dc_dct_pred[2] @@ -1851,9 +1883,12 @@ static __inline__ void SliceHeader( vpar_thread_t * p_vpar, i_chroma_format, i_structure, b_second_field ); i_mb_address_save = *pi_mb_address; + if( p_vpar->picture.b_error ) + { + return; + } } - while( ShowBits( &p_vpar->bit_stream, 23 ) && !p_vpar->picture.b_error - && !p_vpar->b_die ); + while( ShowBits( &p_vpar->bit_stream, 23 ) && !p_vpar->b_die ); NextStartCode( p_vpar ); } diff --git a/src/video_parser/vpar_headers.c b/src/video_parser/vpar_headers.c index 78fee08e7b..b2c61e74ea 100644 --- a/src/video_parser/vpar_headers.c +++ b/src/video_parser/vpar_headers.c @@ -156,10 +156,15 @@ static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar, vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward ); if( p_vpar->sequence.p_backward != NULL ) { +#ifdef POLUX_SYNCHRO + vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward, + vpar_SynchroDate( p_vpar ) ); +#endif #ifdef SAM_SYNCHRO vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward, vpar_SynchroDate( p_vpar ) ); -#else +#endif +#ifdef MEUUH_SYNCHRO mtime_t date; date = vpar_SynchroDate( p_vpar ); vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward, @@ -172,15 +177,14 @@ static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar, p_vpar->sequence.p_backward = p_newref; if( p_newref != NULL ) vout_LinkPicture( p_vpar->p_vout, p_newref ); -#ifndef SAM_SYNCHRO +#ifdef MEUUH_SYNCHRO p_vpar->synchro.i_coding_type = i_coding_type; #endif } else if( p_newref != NULL ) { /* Put date immediately. */ - vout_DatePicture( p_vpar->p_vout, p_newref, - vpar_SynchroDate( p_vpar ) ); + vout_DatePicture( p_vpar->p_vout, p_newref, vpar_SynchroDate(p_vpar) ); } } @@ -525,7 +529,7 @@ static void PictureHeader( vpar_thread_t * p_vpar ) RemoveBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */ p_vpar->picture.i_coding_type = GetBits( &p_vpar->bit_stream, 3 ); RemoveBits( &p_vpar->bit_stream, 16 ); /* vbv_delay */ - + if( p_vpar->picture.i_coding_type == P_CODING_TYPE || p_vpar->picture.i_coding_type == B_CODING_TYPE ) { @@ -646,15 +650,21 @@ static void PictureHeader( vpar_thread_t * p_vpar ) p_vpar->picture.i_coding_type, i_structure ); } } - +#ifdef POLUX_SYNCHRO + else if( !p_vpar->picture.i_current_structure ) + { + vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure ); + } +#endif + if( !b_parsable ) { /* Update the reference pointers. */ ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, NULL ); - +#ifndef POLUX_SYNCHRO /* Warn Synchro we have trashed a picture. */ vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure ); - +#endif /* Update context. */ if( i_structure != FRAME_STRUCTURE ) p_vpar->picture.i_current_structure = i_structure; diff --git a/src/video_parser/vpar_synchro.c b/src/video_parser/vpar_synchro.c index 55aa5d7cb8..05c6758e36 100644 --- a/src/video_parser/vpar_synchro.c +++ b/src/video_parser/vpar_synchro.c @@ -399,7 +399,9 @@ mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar ) return i_displaydate; } -#else +#endif + +#ifdef MEUUH_SYNCHRO /* synchro a deux balles backportee du decodeur de reference. NE MARCHE PAS AVEC LES IMAGES MONOTRAMES */ @@ -516,3 +518,145 @@ void vpar_SynchroKludge( vpar_thread_t * p_vpar, mtime_t date ) } #endif + + +#ifdef POLUX_SYNCHRO + +void vpar_SynchroSetCurrentDate( vpar_thread_t * p_vpar, int i_coding_type ) +{ + pes_packet_t * p_pes = + p_vpar->bit_stream.p_decoder_fifo->buffer[p_vpar->bit_stream.p_decoder_fifo->i_start]; + + + switch( i_coding_type ) + { + case B_CODING_TYPE: + if( p_pes->b_has_pts ) + { + if( p_pes->i_pts < p_vpar->synchro.i_current_frame_date ) + { + fprintf( stderr, "vpar warning: pts_date < current_date\n" ); + } + p_vpar->synchro.i_current_frame_date = p_pes->i_pts; + p_pes->b_has_pts = 0; + } + else + { + p_vpar->synchro.i_current_frame_date += 1000000/(1+p_vpar->sequence.r_frame_rate); + } + break; + + default: + + if( p_vpar->synchro.i_backward_frame_date == 0 ) + { + p_vpar->synchro.i_current_frame_date += 1000000/(1+p_vpar->sequence.r_frame_rate); + } + else + { + if( p_vpar->synchro.i_backward_frame_date < p_vpar->synchro.i_current_frame_date ) + { + fprintf( stderr, "vpar warning: backward_date < current_date (%Ld)\n", + p_vpar->synchro.i_backward_frame_date - p_vpar->synchro.i_current_frame_date ); + } + p_vpar->synchro.i_current_frame_date = p_vpar->synchro.i_backward_frame_date; + p_vpar->synchro.i_backward_frame_date = 0; + } + + if( p_pes->b_has_pts ) + { + p_vpar->synchro.i_backward_frame_date = p_pes->i_pts; + p_pes->b_has_pts = 0; + } + break; + } +} + +boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, + int i_structure ) +{ + boolean_t b_result = 1; + int i_synchro_level = p_vpar->p_vout->i_synchro_level; + + vpar_SynchroSetCurrentDate( p_vpar, i_coding_type ); + + /* + * The synchro level is updated by the video input (see SynchroLevelUpdate) + * so we just use the synchro_level to decide which frame to trash + */ + + switch( i_coding_type ) + { + case I_CODING_TYPE: + if( p_vpar->synchro.i_i_count != 0 ) + { + p_vpar->synchro.i_p_nb = p_vpar->synchro.i_p_count; + p_vpar->synchro.i_b_nb = p_vpar->synchro.i_b_count; + } + p_vpar->synchro.i_p_count = p_vpar->synchro.i_b_count = 0; + p_vpar->synchro.i_b_trasher = p_vpar->synchro.i_b_nb / 2; + p_vpar->synchro.i_i_count++; + break; + + case P_CODING_TYPE: + p_vpar->synchro.i_p_count++; + if( p_vpar->synchro.i_p_count > i_synchro_level ) + { + b_result = 0; + } + break; + + case B_CODING_TYPE: + p_vpar->synchro.i_b_count++; + if( p_vpar->synchro.i_p_nb >= i_synchro_level ) + { + /* We must trash all the B */ + b_result = 0; + } + else + { + /* We use the brensenham algorithm to decide which B to trash */ + p_vpar->synchro.i_b_trasher += + p_vpar->synchro.i_b_nb - (i_synchro_level-p_vpar->synchro.i_p_nb); + if( p_vpar->synchro.i_b_trasher >= p_vpar->synchro.i_b_nb ) + { + b_result = 0; + p_vpar->synchro.i_b_trasher -= p_vpar->synchro.i_b_nb; + } + } + break; + } + + return( b_result ); +} + +void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type, + int i_structure ) +{ + vpar_SynchroChoose( p_vpar, i_coding_type, i_structure ); +} + +void vpar_SynchroUpdateLevel() +{ + //vlc_mutex_lock( &level_lock ); + //vlc_mutex_unlock( &level_lock ); +} + +mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar ) +{ +//fprintf( stderr, "delay : %Ld\n" , mdate() - p_vpar->synchro.i_current_frame_date ); + return( p_vpar->synchro.i_current_frame_date ); +} + +/* functions with no use */ + +void vpar_SynchroEnd( vpar_thread_t * p_vpar ) +{ +} + +void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type, + int i_structure ) +{ +} + +#endif