X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_parser%2Fvpar_synchro.c;h=bca1d29f5dc06dfc78d91c63568b5001a56c9ecc;hb=b25b4229c62f9ffbc9ecd016a4416dae91550dea;hp=46a0ea34fff2b0e4ed2290a0657ee0b826d49ab4;hpb=cf49edcd645674ee51fdfbecc70b1690ca456633;p=vlc diff --git a/src/video_parser/vpar_synchro.c b/src/video_parser/vpar_synchro.c index 46a0ea34ff..bca1d29f5d 100644 --- a/src/video_parser/vpar_synchro.c +++ b/src/video_parser/vpar_synchro.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include "config.h" #include "common.h" @@ -35,9 +33,9 @@ #include "vpar_blocks.h" #include "vpar_headers.h" -#include "video_fifo.h" #include "vpar_synchro.h" #include "video_parser.h" +#include "video_fifo.h" #define MAX_COUNT 3 @@ -51,8 +49,9 @@ float vpar_SynchroUpdateTab( video_synchro_tab_t * tab, int count ) { - tab->mean = ( tab->mean + 3 * count ) / 4; - tab->deviation = ( tab->deviation + 3 * abs (tab->mean - count) ) / 4; + tab->mean = ( tab->mean + MAX_COUNT * count ) / ( MAX_COUNT + 1 ); + tab->deviation = ( tab->deviation + MAX_COUNT * abs (tab->mean - count) ) + / ( MAX_COUNT + 1 ); return tab->deviation; } @@ -61,28 +60,100 @@ float vpar_SynchroUpdateTab( video_synchro_tab_t * tab, int count ) * vpar_SynchroUpdateStructures : Update the synchro structures *****************************************************************************/ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, - int i_coding_type ) + int i_coding_type, int dropped ) { float candidate_deviation; float optimal_deviation; float predict; + mtime_t i_current_pts; + mtime_t i_delay; + mtime_t i_displaydate; + decoder_fifo_t * decoder_fifo = p_vpar->bit_stream.p_decoder_fifo; + + /* interpolate the current _decode_ PTS */ + i_current_pts = decoder_fifo->buffer[decoder_fifo->i_start]->b_has_pts ? + decoder_fifo->buffer[decoder_fifo->i_start]->i_pts : + 0; + if( !i_current_pts ) + { + i_current_pts = p_vpar->synchro.i_last_decode_pts + + 1000000.0 / (1 + p_vpar->synchro.actual_fps); + } + p_vpar->synchro.i_last_decode_pts = i_current_pts; + + /* see if the current image has a pts - if not, set to 0 */ + p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_stop].i_pts + = i_current_pts; + + /* update display time */ + i_displaydate = decoder_fifo->buffer[decoder_fifo->i_start]->b_has_pts ? + decoder_fifo->buffer[decoder_fifo->i_start]->i_pts : + 0; + if( !i_displaydate /* || i_coding_type != I_CODING_TYPE */ ) + { + if (!p_vpar->synchro.i_images_since_pts ) + p_vpar->synchro.i_images_since_pts = 10; + + i_displaydate = p_vpar->synchro.i_last_display_pts + + 1000000.0 / (p_vpar->synchro.theorical_fps); + //fprintf (stderr, " "); + } + + /* else fprintf (stderr, "R "); + if (dropped) fprintf (stderr, " "); else fprintf (stderr, "* "); + fprintf (stderr, "%i ", i_coding_type); + fprintf (stderr, "pts %lli delta %lli\n", i_displaydate, i_displaydate - p_vpar->synchro.i_last_display_pts); */ + p_vpar->synchro.i_images_since_pts--; + p_vpar->synchro.i_last_display_pts = i_displaydate; + + + + /* update structures */ switch(i_coding_type) { case P_CODING_TYPE: + p_vpar->synchro.current_p_count++; + if( !dropped ) p_vpar->synchro.nondropped_p_count++; break; + case B_CODING_TYPE: p_vpar->synchro.current_b_count++; + if( !dropped ) p_vpar->synchro.nondropped_b_count++; break; + case I_CODING_TYPE: + /* update information about images we can decode */ + if (i_current_pts != p_vpar->synchro.i_last_i_pts) + { + if ( p_vpar->synchro.i_last_i_pts && i_current_pts != p_vpar->synchro.i_last_i_pts) + { + p_vpar->synchro.theorical_fps = (p_vpar->synchro.theorical_fps + 1000000.0 * (1 + p_vpar->synchro.current_b_count + p_vpar->synchro.current_p_count) / (i_current_pts - p_vpar->synchro.i_last_i_pts)) / 2; + } + p_vpar->synchro.i_last_i_pts = i_current_pts; + } + + if( !dropped ) + { + if ( p_vpar->synchro.i_last_nondropped_i_pts && i_current_pts != p_vpar->synchro.i_last_nondropped_i_pts) + { + p_vpar->synchro.actual_fps = (p_vpar->synchro.actual_fps + 1000000.0 * (1 + p_vpar->synchro.nondropped_b_count + p_vpar->synchro.nondropped_p_count) / (i_current_pts - p_vpar->synchro.i_last_nondropped_i_pts)) / 2; + } + + } + + /* update all the structures for P images */ + + /* period == 1 */ optimal_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_p[0], p_vpar->synchro.current_p_count); predict = p_vpar->synchro.tab_p[0].mean; + /* period == 2 */ candidate_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_p[1 + (p_vpar->synchro.modulo & 0x1)], p_vpar->synchro.current_p_count); @@ -92,6 +163,7 @@ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, predict = p_vpar->synchro.tab_p[1 + (p_vpar->synchro.modulo & 0x1)].mean; } + /* period == 3 */ candidate_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_p[3 + (p_vpar->synchro.modulo % 3)], p_vpar->synchro.current_p_count); @@ -106,11 +178,14 @@ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, /* update all the structures for B images */ + + /* period == 1 */ optimal_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_b[0], p_vpar->synchro.current_b_count); predict = p_vpar->synchro.tab_b[0].mean; + /* period == 2 */ candidate_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_b[1 + (p_vpar->synchro.modulo & 0x1)], p_vpar->synchro.current_b_count); @@ -120,6 +195,7 @@ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, predict = p_vpar->synchro.tab_b[1 + (p_vpar->synchro.modulo & 0x1)].mean; } + /* period == 3 */ candidate_deviation = vpar_SynchroUpdateTab( &p_vpar->synchro.tab_b[3 + (p_vpar->synchro.modulo % 3)], p_vpar->synchro.current_b_count); @@ -131,12 +207,66 @@ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, p_vpar->synchro.b_count_predict = predict; p_vpar->synchro.current_b_count = 0; - + + /* now we calculated all statistics, it's time to + * decide what we have the time to display + */ + i_delay = i_current_pts - p_vpar->synchro.i_last_nondropped_i_pts; + + p_vpar->synchro.can_display_i + = ( p_vpar->synchro.i_mean_decode_time < i_delay ); + + p_vpar->synchro.can_display_p + = ( p_vpar->synchro.i_mean_decode_time + * (1 + p_vpar->synchro.p_count_predict) < i_delay ); + + if( !p_vpar->synchro.can_display_p ) + { + p_vpar->synchro.displayable_p + = -1 + i_delay / p_vpar->synchro.i_mean_decode_time; + if( p_vpar->synchro.displayable_p < 0 ) + p_vpar->synchro.displayable_p = 0; + } + else + p_vpar->synchro.displayable_p = 0; + + if( p_vpar->synchro.can_display_p + && !(p_vpar->synchro.can_display_b + = ( p_vpar->synchro.i_mean_decode_time + * (1 + p_vpar->synchro.b_count_predict + + p_vpar->synchro.p_count_predict)) < i_delay) ) + { + p_vpar->synchro.displayable_b + = -2.0 + i_delay / p_vpar->synchro.i_mean_decode_time + - p_vpar->synchro.can_display_p; + } + else + p_vpar->synchro.displayable_b = 0; + +#if 0 + fprintf( stderr, + "I %i P %i (%f) B %i (%f)\n", + p_vpar->synchro.can_display_i, + p_vpar->synchro.can_display_p, + p_vpar->synchro.displayable_p, + p_vpar->synchro.can_display_b, + p_vpar->synchro.displayable_b ); +#endif + + /* update some values */ + if( !dropped ) + { + p_vpar->synchro.i_last_nondropped_i_pts = i_current_pts; + p_vpar->synchro.nondropped_p_count = 0; + p_vpar->synchro.nondropped_b_count = 0; + } break; + } p_vpar->synchro.modulo++; + } /***************************************************************************** @@ -145,13 +275,51 @@ void vpar_SynchroUpdateStructures( vpar_thread_t * p_vpar, boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, int i_structure ) { -// return( 1 ); - return( i_coding_type == I_CODING_TYPE || i_coding_type == P_CODING_TYPE ); - intf_DbgMsg("vpar debug: synchro image %i - modulo is %i\n", i_coding_type, p_vpar->synchro.modulo); - intf_DbgMsg("vpar debug: synchro predict P %e - predict B %e\n", p_vpar->synchro.p_count_predict, p_vpar->synchro.b_count_predict); + mtime_t i_delay = p_vpar->synchro.i_last_decode_pts - mdate(); + + switch( i_coding_type ) + { + case I_CODING_TYPE: + + return( p_vpar->synchro.can_display_i ); + + case P_CODING_TYPE: + + if( p_vpar->synchro.can_display_p ) + return( 1 ); + + if( p_vpar->synchro.displayable_p * i_delay + < p_vpar->synchro.i_mean_decode_time ) + { + //fprintf( stderr, "trashed a P\n"); + return( 0 ); + } + + p_vpar->synchro.displayable_p--; + return( 1 ); + + case B_CODING_TYPE: + + if( p_vpar->synchro.can_display_b ) + return( 1 ); + + /* modulo & 0x3 is here to add some randomness */ + if( i_delay < (1 + (p_vpar->synchro.modulo & 0x3)) + * p_vpar->synchro.i_mean_decode_time ) + { + //fprintf( stderr, "trashed a B\n"); + return( 0 ); + } + + if( p_vpar->synchro.displayable_b <= 0 ) + return( 0 ); + + p_vpar->synchro.displayable_b--; + return( 1 ); + } + + return( 0 ); - return(0); - return( i_coding_type == I_CODING_TYPE ); } /***************************************************************************** @@ -160,7 +328,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type, int i_structure ) { - vpar_SynchroUpdateStructures (p_vpar, i_coding_type); + vpar_SynchroUpdateStructures (p_vpar, i_coding_type, 1); } @@ -170,7 +338,13 @@ void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type, void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type, int i_structure ) { - vpar_SynchroUpdateStructures (p_vpar, i_coding_type); + vpar_SynchroUpdateStructures (p_vpar, i_coding_type, 0); + + p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_stop].i_decode_date = mdate(); + p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_stop].i_image_type + = i_coding_type; + + p_vpar->synchro.i_fifo_stop = (p_vpar->synchro.i_fifo_stop + 1) & 0xf; } @@ -179,12 +353,46 @@ void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type, *****************************************************************************/ void vpar_SynchroEnd( vpar_thread_t * p_vpar ) { - -// return mdate() + 700000; + mtime_t i_decode_time; + + i_decode_time = (mdate() - + p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_start].i_decode_date) + / (p_vpar->synchro.i_fifo_stop - p_vpar->synchro.i_fifo_start & 0x0f); + + p_vpar->synchro.i_mean_decode_time = + ( 7 * p_vpar->synchro.i_mean_decode_time + i_decode_time ) / 8; + + /* fprintf (stderr, + "decoding time was %lli\n", + p_vpar->synchro.i_mean_decode_time); */ + + p_vpar->synchro.i_fifo_start = (p_vpar->synchro.i_fifo_start + 1) & 0xf; + } +/***************************************************************************** + * vpar_SynchroDate : When an image has been decoded, ask for its date + *****************************************************************************/ mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar ) { - return mdate() + 700000; + mtime_t i_displaydate = p_vpar->synchro.i_last_display_pts; + +#if 0 + static mtime_t i_delta = 0; + + fprintf( stderr, + "displaying type %i with delay %lli and delta %lli\n", + p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_start].i_image_type, + i_displaydate - mdate(), + i_displaydate - i_delta ); + + fprintf (stderr, + "theorical fps: %f - actual fps: %f \n", + p_vpar->synchro.theorical_fps, p_vpar->synchro.actual_fps ); + + i_delta = i_displaydate; +#endif + + return i_displaydate; }