[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[284] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2012-11-02 16:03:23
|
Revision: 284 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=284&view=rev Author: nickols_k Date: 2012-11-02 16:03:16 +0000 (Fri, 02 Nov 2012) Log Message: ----------- always run video player as parallel thread Modified Paths: -------------- mplayerxp/Makefile mplayerxp/mplayer.c mplayerxp/mplayer.h mplayerxp/xmp_core.c Added Paths: ----------- mplayerxp/xmp_vplayer.c mplayerxp/xmp_vplayer.h Modified: mplayerxp/Makefile =================================================================== --- mplayerxp/Makefile 2012-11-02 15:05:24 UTC (rev 283) +++ mplayerxp/Makefile 2012-11-02 16:03:16 UTC (rev 284) @@ -25,7 +25,7 @@ SRCS_COMMON = mp_msg.c mp_image.c SRCS_MPLAYER = mplayer.c fifo.c $(SRCS_COMMON) mixer.c mp-opt-reg.c sig_hand.c dump.c -SRCS_MPLAYER+= xmp_core.c +SRCS_MPLAYER+= xmp_core.c xmp_vplayer.c OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) Modified: mplayerxp/mplayer.c =================================================================== --- mplayerxp/mplayer.c 2012-11-02 15:05:24 UTC (rev 283) +++ mplayerxp/mplayer.c 2012-11-02 16:03:16 UTC (rev 284) @@ -73,6 +73,7 @@ #include "mixer.h" #include "xmp_core.h" +#include "xmp_vplayer.h" #define MSGT_CLASS MSGT_CPLAYER #include "mp_msg.h" @@ -129,14 +130,8 @@ unsigned inited_flags; int vo_inited; int ao_inited; - unsigned mpxp_after_seek; int osd_show_framedrop; int osd_function; -/* mp_conf.benchmark: */ - unsigned bench_dropped_frames; - float max_av_resync; -// A-V sync: - float c_total; // priv data demuxer_t* demuxer; play_tree_t*playtree; @@ -197,6 +192,7 @@ mp_data->seek_time=-1; mp_data->bench=mp_mallocz(sizeof(time_usage_t)); mp_data->use_pts_fix2=-1; + mp_data->rtc_fd=-1; mp_data->priv=mp_mallocz(sizeof(priv_t)); priv_t*priv=mp_data->priv; priv->osd_function=OSD_PLAY; @@ -244,7 +240,7 @@ AUDIO XP-CORE! ToDo: rewrite it in packet-mode ************************************************************************/ /* XP audio buffer */ -static pthread_mutex_t audio_timer_mutex=PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t audio_timer_mutex=PTHREAD_MUTEX_INITIALIZER; typedef struct audio_buffer_index_s { float pts; int index; @@ -1092,6 +1088,7 @@ #ifdef USE_OSD +//================= Update OSD ==================== void update_osd( float v_pts ) { priv_t*priv=mp_data->priv; @@ -1102,7 +1099,7 @@ int pts=(mp_conf.osd_level==3&&priv->demuxer->movi_length!=UINT_MAX)?priv->demuxer->movi_length-v_pts:v_pts; int addon=(mp_conf.osd_level==3&&priv->demuxer->movi_length!=UINT_MAX)?-1:1; char osd_text_tmp[64]; - if(pts==osd_last_pts-addon) + if(pts==osd_last_pts-addon) { if(mp_conf.osd_level==3&&priv->demuxer->movi_length!=UINT_MAX) ++pts; else --pts; @@ -1131,284 +1128,11 @@ } } #endif - -//================= Update OSD ==================== -static void __show_status_line(float a_pts,float v_pts,float delay,float AV_delay) { - priv_t*priv=mp_data->priv; - MSG_STATUS("A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d [frms: [%i]]\n", - a_pts-delay,v_pts,AV_delay,priv->c_total - ,xp_core->video->num_played_frames,xp_core->video->num_decoded_frames - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 - ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 - ,mp_data->output_quality - ,dae_curr_vplayed(xp_core) - ); - fflush(stdout); -} - -static void show_status_line_no_apts(float v_pts) { - priv_t*priv=mp_data->priv; - sh_audio_t* sh_audio=priv->demuxer->audio->sh; - if(mp_conf.av_sync_pts && sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data))) { - float a_pts = sh_audio->timer-ao_get_delay(ao_data); - MSG_STATUS("A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d\r" - ,a_pts - ,v_pts - ,a_pts-v_pts - ,0.0 - ,xp_core->video->num_played_frames,xp_core->video->num_decoded_frames - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 - ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 - ,mp_data->output_quality - ); - } else - MSG_STATUS("V:%6.1f %3d %2d%% %2d%% %4.1f%% %d\r" - ,v_pts - ,xp_core->video->num_played_frames - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 - ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 - ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 - ,mp_data->output_quality - ); - fflush(stdout); -} - -static void vplayer_check_chapter_change(xmp_frame_t* shva_prev,float v_pts) -{ - priv_t*priv=mp_data->priv; - sh_audio_t* sh_audio=priv->demuxer->audio->sh; - sh_video_t* sh_video=priv->demuxer->video->sh; - if(mp_data->use_pts_fix2 && sh_audio) { - if(sh_video->chapter_change == -1) { /* First frame after seek */ - while(v_pts < 1.0 && sh_audio->timer==0.0 && ao_get_delay(ao_data)==0.0) - usleep(0); /* Wait for audio to start play */ - if(sh_audio->timer > 2.0 && v_pts < 1.0) { - MSG_V("Video chapter change detected\n"); - sh_video->chapter_change=1; - } else { - sh_video->chapter_change=0; - } - } else if(v_pts < 1.0 && shva_prev->v_pts > 2.0) { - MSG_V("Video chapter change detected\n"); - sh_video->chapter_change=1; - } - if(sh_video->chapter_change && sh_audio->chapter_change) { - MSG_V("Reset chapter change\n"); - sh_video->chapter_change=0; - sh_audio->chapter_change=0; - } - } -} - -static float vplayer_compute_sleep_time(xmp_frame_t* shva_prev,float screen_pts) -{ - priv_t*priv=mp_data->priv; - sh_audio_t* sh_audio=priv->demuxer->audio->sh; - sh_video_t* sh_video=priv->demuxer->video->sh; - float sleep_time=0; - if(sh_audio && xp_core->audio) { - /* FIXME!!! need the same technique to detect xp_core->audio->eof as for video_eof! - often ao_get_delay() never returns 0 :( */ - if(xp_core->audio->eof && !get_delay_audio_buffer()) goto nosound_model; - if((!xp_core->audio->eof || ao_get_delay(ao_data)) && - (!mp_data->use_pts_fix2 || (!sh_audio->chapter_change && !sh_video->chapter_change))) - sleep_time=screen_pts-((sh_audio->timer-ao_get_delay(ao_data)) - +(mp_conf.av_sync_pts?0:xp_core->initial_apts)); - else if(mp_data->use_pts_fix2 && sh_audio->chapter_change) - sleep_time=0; - else - goto nosound_model; - } else { - nosound_model: - sleep_time=shva_prev->duration/mp_conf.playbackspeed_factor; - } - return sleep_time; -} - -static int vplayer_do_sleep(int rtc_fd,float sleep_time) -{ - priv_t*priv=mp_data->priv; - sh_audio_t* sh_audio=priv->demuxer->audio->sh; -#define XP_MIN_TIMESLICE 0.010 /* under Linux on x86 min time_slice = 10 ms */ -#define XP_MIN_AUDIOBUFF 0.05 -#define XP_MAX_TIMESLICE 0.1 - if(!xp_core->audio) sh_audio=NULL; - if(sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data)) && sleep_time>XP_MAX_TIMESLICE) { - float t; - - if( mp_conf.xp < XP_VAPlay ) { - t=ao_get_delay(ao_data)-XP_MIN_AUDIOBUFF; - if(t>XP_MAX_TIMESLICE) - t=XP_MAX_TIMESLICE; - } else - t = XP_MAX_TIMESLICE; - - usleep(t*1000000); - sleep_time-=GetRelativeTime(); - if(mp_conf.xp >= XP_VAPlay || t<XP_MAX_TIMESLICE || sleep_time>XP_MAX_TIMESLICE) { - // exit due no sound in soundcard - return 0; - } - } - - while(sleep_time>XP_MIN_TIMESLICE) { - /* mp_free cpu for threads */ - usleep(1); - sleep_time-=GetRelativeTime(); - } - MP_UNIT("sleep_usleep"); - sleep_time=SleepTime(rtc_fd,mp_conf.softsleep,sleep_time); - return 1; -} - typedef struct osd_args_s { int visible; int info_factor; }osd_args_t; -static float max_pts_correction=0; -int mpxp_play_video( int rtc_fd ) -{ - priv_t*priv=mp_data->priv; - sh_audio_t* sh_audio=priv->demuxer->audio->sh; - sh_video_t* sh_video=priv->demuxer->video->sh; - demux_stream_t *d_audio=priv->demuxer->audio; - float v_pts=0; - float sleep_time=0; - int can_blit=0; - int delay_corrected=1; - int final_frame=0; - xmp_frame_t shva_prev,shva; - - shva_prev=dae_played_frame(xp_core->video); - final_frame = dae_played_eof(xp_core->video); - if(xp_core->video->eof && final_frame) return 1; - - can_blit=dae_try_inc_played(xp_core->video); /* <-- TRY SWITCH TO NEXT FRAME */ - shva=dae_next_played_frame(xp_core->video); - v_pts = shva.v_pts; - /*------------------------ frame decoded. --------------------*/ -/* blit frame */ - - if(xp_core->video->eof) can_blit=1; /* force blitting until end of stream will be reached */ - vplayer_check_chapter_change(&shva_prev,v_pts); -#if 0 -MSG_INFO("xp_core->initial_apts=%f a_eof=%i a_pts=%f sh_audio->timer=%f v_pts=%f stream_pts=%f duration=%f\n" -,xp_core->initial_apts -,xp_core->audio->eof -,sh_audio && !xp_core->audio->eof?d_audio->pts+(ds_tell_pts_r(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps:0 -,sh_audio && !xp_core->audio->eof?sh_audio->timer-ao_get_delay(ao_data):0 -,shva.v_pts -,shva.stream_pts -,shva.duration); -#endif - /*--------- add OSD to the next frame contents ---------*/ - if(can_blit) { -#ifdef USE_OSD - MSG_D("dec_ahead_main: draw_osd to %u\n",player_idx); - MP_UNIT("draw_osd"); - update_osd(shva.v_pts); - vo_draw_osd(vo_data,dae_next_played(xp_core->video)); -#endif - } - MP_UNIT("change_frame2"); - /* don't flip if there is nothing new to display */ - if(!can_blit) { - static int drop_message=0; - if(!drop_message && xp_core->video->num_slow_frames > 50) { - drop_message=1; - if(priv->mpxp_after_seek) priv->mpxp_after_seek--; - else MSG_WARN(MSGTR_SystemTooSlow); - } - MSG_D("\ndec_ahead_main: stalling: %i %i\n",dae_cuurr_vplayed(),dae_curr_decoded()); - /* Don't burn CPU here! With using of v_pts for A-V sync we will enter - xp_decore_video without any delay (like while(1);) - Sleeping for 10 ms doesn't matter with frame dropping */ - usleep(0); - } else { - unsigned int t2=GetTimer(); - double tt; - unsigned player_idx; - - /* It's time to sleep ;)...*/ - MP_UNIT("sleep"); - GetRelativeTime(); /* reset timer */ - sleep_time=vplayer_compute_sleep_time(&shva_prev,v_pts); - if(mp_conf.benchmark && sleep_time < 0 && sleep_time < priv->max_av_resync) priv->max_av_resync=sleep_time; - if(!(vo_data->flags&256)){ /* flag 256 means: libvo driver does its timing (dvb card) */ - if(!vplayer_do_sleep(rtc_fd,sleep_time)) return 0; - } - - player_idx=dae_next_played(xp_core->video); - vo_select_frame(vo_data,player_idx); - dae_inc_played(xp_core->video); - MSG_D("\ndec_ahead_main: schedule %u on screen\n",player_idx); - t2=GetTimer()-t2; - tt = t2*0.000001f; - mp_data->bench->vout+=tt; - if(mp_conf.benchmark) { - /* we need compute draw_slice+change_frame here */ - mp_data->bench->cur_vout+=tt; - if((mp_data->bench->cur_video+mp_data->bench->cur_vout+mp_data->bench->cur_audio)*sh_video->fps > 1) - priv->bench_dropped_frames ++; - } - } - MP_UNIT(NULL); - -/*================ A-V TIMESTAMP CORRECTION: =========================*/ - /* FIXME: this block was added to fix A-V resync caused by some strange things - like playing 48KHz audio on 44.1KHz soundcard and other. - Now we know PTS of every audio frame so don't need to have it */ - if(!xp_core->audio) sh_audio=NULL; - if(sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data)) && !mp_conf.av_sync_pts) { - float a_pts=0; - - // unplayed bytes in our and soundcard/dma buffer: - float delay=ao_get_delay(ao_data)+(float)sh_audio->a_buffer_len/(float)sh_audio->af_bps; - if(mp_conf.xp>=XP_VideoAudio) - delay += get_delay_audio_buffer(); - - if(pts_from_bps){ - unsigned int samples=(sh_audio->audio.dwSampleSize)? - ((ds_tell(d_audio)-sh_audio->a_in_buffer_len)/sh_audio->audio.dwSampleSize) : - (d_audio->pack_no); // <- used for VBR audio - samples+=sh_audio->audio.dwStart; // offset - a_pts=samples*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate; - delay_corrected=1; - } else { - // PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec) - a_pts=d_audio->pts; - if(!delay_corrected) if(a_pts) delay_corrected=1; - a_pts+=(ds_tell_pts_r(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - } - - MSG_DBG2("### A:%8.3f (%8.3f) V:%8.3f A-V:%7.4f \n",a_pts,a_pts-delay,v_pts,(a_pts-delay)-*v_pts); - - if(delay_corrected && can_blit){ - float AV_delay=0; /* average of A-V timestamp differences */ - float x; - AV_delay=(a_pts-delay)-v_pts; - x=AV_delay*0.1f; - if(x<-max_pts_correction) x=-max_pts_correction; - else if(x> max_pts_correction) x= max_pts_correction; - max_pts_correction=shva.duration*0.10; // +-10% of time - if(mp_conf.xp>=XP_VAPlay) - pthread_mutex_lock(&audio_timer_mutex); - sh_audio->timer+=x; - if(mp_conf.xp>=XP_VAPlay) - pthread_mutex_unlock(&audio_timer_mutex); - priv->c_total+=x; - if(mp_conf.benchmark && mp_conf.verbose) __show_status_line(a_pts,v_pts,delay,AV_delay); - } - } else { - // No audio or pts: - if(mp_conf.benchmark && mp_conf.verbose) show_status_line_no_apts(v_pts); - } - return 0; -} - void mpxp_seek( osd_args_t *osd,const seek_args_t* seek) { priv_t*priv=mp_data->priv; @@ -1419,7 +1143,7 @@ xp_core->audio->eof=0; if(seek->secs || seek->flags&DEMUX_SEEK_SET) { seek_rval=demux_seek_r(priv->demuxer,seek); - priv->mpxp_after_seek=25; /* 1 sec delay */ + mp_data->mpxp_after_seek=25; /* 1 sec delay */ } if(seek_rval){ mp_data->seek_time = GetTimerMS(); @@ -1466,7 +1190,6 @@ } #endif if(sh_video) { - priv->c_total=0; max_pts_correction=0.1; if(osd) osd->visible=sh_video->fps<=60?sh_video->fps:25; // to rewert to PLAY pointer after 1 sec mp_data->bench->audio=0; mp_data->bench->audio_decode=0; mp_data->bench->video=0; mp_data->bench->vout=0; @@ -1510,7 +1233,6 @@ mp_data->bench->min_audio_decode=HUGE; mp_data->bench->max_audio_decode=0; - priv->bench_dropped_frames=0; mp_data->bench->max_demux=0; mp_data->bench->demux=0; @@ -1519,8 +1241,6 @@ mp_data->bench->cur_video=0; mp_data->bench->cur_vout=0; mp_data->bench->cur_audio=0; - - priv->max_av_resync=0; } static void show_benchmark(void) @@ -1546,7 +1266,6 @@ unsigned nframes=xp_core->video->num_played_frames; MSG_INFO("\nREAL RESULTS: from %u was dropped=%u\n" ,nframes,xp_core->video->num_dropped_frames); - MSG_INFO("\nMax. A-V resync is: %f\n",fabs(priv->max_av_resync)); } static void show_benchmark_status(void) @@ -2401,7 +2120,6 @@ // movie info: int eof=0; osd_args_t osd = { 100, 9 }; - int rtc_fd=-1; int forced_subs_only=0; seek_args_t seek_args = { 0, DEMUX_SEEK_CUR|DEMUX_SEEK_SECONDS }; @@ -2719,9 +2437,9 @@ } /* Init timers and benchmarking */ - rtc_fd=InitTimer(); - if(!mp_conf.nortc && rtc_fd>0) { close(rtc_fd); rtc_fd=-1; } - MSG_V("Using %s timing\n",rtc_fd>0?"rtc":mp_conf.softsleep?"software":"usleep()"); + mp_data->rtc_fd=InitTimer(); + if(!mp_conf.nortc && mp_data->rtc_fd>0) { close(mp_data->rtc_fd); mp_data->rtc_fd=-1; } + MSG_V("Using %s timing\n",mp_data->rtc_fd>0?"rtc":mp_conf.softsleep?"software":"usleep()"); mp_data->bench->total_start=GetTimer(); mp_data->bench->audio=0; mp_data->bench->audio_decode=0; mp_data->bench->video=0; @@ -2786,7 +2504,9 @@ usleep(0); } else { repaint: - l_eof = mpxp_play_video(rtc_fd); + usleep(100000); + l_eof = dae_played_eof(xp_core->video); + //mpxp_play_video(rtc_fd); eof |= l_eof; if(eof) goto do_loop; } Modified: mplayerxp/mplayer.h =================================================================== --- mplayerxp/mplayer.h 2012-11-02 15:05:24 UTC (rev 283) +++ mplayerxp/mplayer.h 2012-11-02 16:03:16 UTC (rev 284) @@ -98,8 +98,10 @@ /* non-configurable through command line stuff */ typedef struct mp_data_s { + int rtc_fd; int seek_time; int output_quality; + unsigned mpxp_after_seek; int use_pts_fix2; unsigned mplayer_accel; any_t* subtitles; @@ -110,7 +112,11 @@ }mp_data_t; extern mp_data_t* mp_data; +extern void update_osd( float v_pts ); +extern float get_delay_audio_buffer(void); +extern pthread_mutex_t audio_timer_mutex; + extern void exit_player(char* how); extern void mpxp_resync_audio_stream(void); extern void mpxp_reset_vcache(void); Modified: mplayerxp/xmp_core.c =================================================================== --- mplayerxp/xmp_core.c 2012-11-02 15:05:24 UTC (rev 283) +++ mplayerxp/xmp_core.c 2012-11-02 16:03:16 UTC (rev 284) @@ -20,6 +20,8 @@ #include "mp_msg.h" #include "xmp_core.h" +#include "xmp_vplayer.h" + #include "mplayer.h" #include "libao2/audio_out.h" #include "libvo/video_out.h" @@ -689,6 +691,10 @@ if((rc=xmp_register_thread(xp_core->audio,sig_audio_play,audio_play_routine,"audio player"))==UINT_MAX) return rc; while(xp_core->mpxp_threads[rc]->state!=Pth_Run) usleep(0); } + if( xp_core->video ) { + if((rc=xmp_register_thread(xp_core->video,sig_video_play,xmp_video_player,"video player"))==UINT_MAX) return rc; + while(xp_core->mpxp_threads[rc]->state!=Pth_Run) usleep(0); + } return 0; } Added: mplayerxp/xmp_vplayer.c =================================================================== --- mplayerxp/xmp_vplayer.c (rev 0) +++ mplayerxp/xmp_vplayer.c 2012-11-02 16:03:16 UTC (rev 284) @@ -0,0 +1,321 @@ +#include "mplayer.h" +#include "xmp_vplayer.h" +#include "xmp_core.h" +#include "help_mp.h" +#include "mp_msg.h" +#include "sig_hand.h" + +#include "libao2/audio_out.h" +#include "libvo/video_out.h" +#include "osdep/timer.h" +#include "libmpdemux/demuxer.h" + +#include <stdio.h> +#include <unistd.h> // for usleep() +#include <math.h> + +#ifdef ENABLE_DEC_AHEAD_DEBUG +#define MSG_T(args...) mp_msg(MSGT_GLOBAL, MSGL_DBG2,__FILE__,__LINE__, ## args ) +#else +#define MSG_T(args...) +#endif + +extern ao_data_t* ao_data; +extern vo_data_t* vo_data; + +static void __show_status_line(float a_pts,float v_pts,float delay,float AV_delay) { + MSG_STATUS("A:%6.1f V:%6.1f A-V:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d [frms: [%i]]\n", + a_pts-delay,v_pts,AV_delay + ,xp_core->video->num_played_frames,xp_core->video->num_decoded_frames + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 + ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 + ,mp_data->output_quality + ,dae_curr_vplayed(xp_core) + ); + fflush(stdout); +} + +static void show_status_line_no_apts(sh_audio_t* sh_audio,float v_pts) { + if(mp_conf.av_sync_pts && sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data))) { + float a_pts = sh_audio->timer-ao_get_delay(ao_data); + MSG_STATUS("A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d\r" + ,a_pts + ,v_pts + ,a_pts-v_pts + ,0.0 + ,xp_core->video->num_played_frames,xp_core->video->num_decoded_frames + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 + ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 + ,mp_data->output_quality + ); + } else + MSG_STATUS("V:%6.1f %3d %2d%% %2d%% %4.1f%% %d\r" + ,v_pts + ,xp_core->video->num_played_frames + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->video/(double)v_pts):0 + ,(v_pts>0.5)?(int)(100.0*mp_data->bench->vout/(double)v_pts):0 + ,(v_pts>0.5)?(100.0*(mp_data->bench->audio+mp_data->bench->audio_decode)/(double)v_pts):0 + ,mp_data->output_quality + ); + fflush(stdout); +} + +static void vplayer_check_chapter_change(sh_audio_t* sh_audio,sh_video_t* sh_video,xmp_frame_t* shva_prev,float v_pts) +{ + if(mp_data->use_pts_fix2 && sh_audio) { + if(sh_video->chapter_change == -1) { /* First frame after seek */ + while(v_pts < 1.0 && sh_audio->timer==0.0 && ao_get_delay(ao_data)==0.0) + usleep(0); /* Wait for audio to start play */ + if(sh_audio->timer > 2.0 && v_pts < 1.0) { + MSG_V("Video chapter change detected\n"); + sh_video->chapter_change=1; + } else { + sh_video->chapter_change=0; + } + } else if(v_pts < 1.0 && shva_prev->v_pts > 2.0) { + MSG_V("Video chapter change detected\n"); + sh_video->chapter_change=1; + } + if(sh_video->chapter_change && sh_audio->chapter_change) { + MSG_V("Reset chapter change\n"); + sh_video->chapter_change=0; + sh_audio->chapter_change=0; + } + } +} + +static float vplayer_compute_sleep_time(sh_audio_t* sh_audio,sh_video_t* sh_video,xmp_frame_t* shva_prev,float screen_pts) +{ + float sleep_time=0; + if(sh_audio && xp_core->audio) { + /* FIXME!!! need the same technique to detect xp_core->audio->eof as for video_eof! + often ao_get_delay() never returns 0 :( */ + if(xp_core->audio->eof && !get_delay_audio_buffer()) goto nosound_model; + if((!xp_core->audio->eof || ao_get_delay(ao_data)) && + (!mp_data->use_pts_fix2 || (!sh_audio->chapter_change && !sh_video->chapter_change))) + sleep_time=screen_pts-((sh_audio->timer-ao_get_delay(ao_data)) + +(mp_conf.av_sync_pts?0:xp_core->initial_apts)); + else if(mp_data->use_pts_fix2 && sh_audio->chapter_change) + sleep_time=0; + else + goto nosound_model; + } else { + nosound_model: + sleep_time=shva_prev->duration/mp_conf.playbackspeed_factor; + } + return sleep_time; +} + +static int vplayer_do_sleep(sh_audio_t* sh_audio,int rtc_fd,float sleep_time) +{ +#define XP_MIN_TIMESLICE 0.010 /* under Linux on x86 min time_slice = 10 ms */ +#define XP_MIN_AUDIOBUFF 0.05 +#define XP_MAX_TIMESLICE 0.1 + if(!xp_core->audio) sh_audio=NULL; + if(sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data)) && sleep_time>XP_MAX_TIMESLICE) { + float t; + + if( mp_conf.xp < XP_VAPlay ) { + t=ao_get_delay(ao_data)-XP_MIN_AUDIOBUFF; + if(t>XP_MAX_TIMESLICE) + t=XP_MAX_TIMESLICE; + } else + t = XP_MAX_TIMESLICE; + + usleep(t*1000000); + sleep_time-=GetRelativeTime(); + if(mp_conf.xp >= XP_VAPlay || t<XP_MAX_TIMESLICE || sleep_time>XP_MAX_TIMESLICE) { + // exit due no sound in soundcard + return 0; + } + } + + while(sleep_time>XP_MIN_TIMESLICE) { + /* mp_free cpu for threads */ + usleep(1); + sleep_time-=GetRelativeTime(); + } + MP_UNIT("sleep_usleep"); + sleep_time=SleepTime(rtc_fd,mp_conf.softsleep,sleep_time); + return 1; +} + +float max_pts_correction=0; +static int mpxp_play_video(demuxer_t* demuxer,sh_audio_t* sh_audio,sh_video_t*sh_video) +{ + demux_stream_t *d_audio=demuxer->audio; + float v_pts=0; + float sleep_time=0; + int can_blit=0; + int delay_corrected=1; + int final_frame=0; + xmp_frame_t shva_prev,shva; + + shva_prev=dae_played_frame(xp_core->video); + final_frame = dae_played_eof(xp_core->video); + if(xp_core->video->eof && final_frame) return 1; + + can_blit=dae_try_inc_played(xp_core->video); /* <-- TRY SWITCH TO NEXT FRAME */ + shva=dae_next_played_frame(xp_core->video); + v_pts = shva.v_pts; + /*------------------------ frame decoded. --------------------*/ +/* blit frame */ + + if(xp_core->video->eof) can_blit=1; /* force blitting until end of stream will be reached */ + vplayer_check_chapter_change(sh_audio,sh_video,&shva_prev,v_pts); +#if 0 +MSG_INFO("xp_core->initial_apts=%f a_eof=%i a_pts=%f sh_audio->timer=%f v_pts=%f stream_pts=%f duration=%f\n" +,xp_core->initial_apts +,xp_core->audio->eof +,sh_audio && !xp_core->audio->eof?d_audio->pts+(ds_tell_pts_r(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps:0 +,sh_audio && !xp_core->audio->eof?sh_audio->timer-ao_get_delay(ao_data):0 +,shva.v_pts +,shva.stream_pts +,shva.duration); +#endif + /*--------- add OSD to the next frame contents ---------*/ + if(can_blit) { +#ifdef USE_OSD + MSG_D("dec_ahead_main: draw_osd to %u\n",player_idx); + MP_UNIT("draw_osd"); + update_osd(shva.v_pts); + vo_draw_osd(vo_data,dae_next_played(xp_core->video)); +#endif + } + MP_UNIT("change_frame2"); + /* don't flip if there is nothing new to display */ + if(!can_blit) { + static int drop_message=0; + if(!drop_message && xp_core->video->num_slow_frames > 50) { + drop_message=1; + if(mp_data->mpxp_after_seek) mp_data->mpxp_after_seek--; + else MSG_WARN(MSGTR_SystemTooSlow); + } + MSG_D("\ndec_ahead_main: stalling: %i %i\n",dae_cuurr_vplayed(),dae_curr_decoded()); + /* Don't burn CPU here! With using of v_pts for A-V sync we will enter + xp_decore_video without any delay (like while(1);) + Sleeping for 10 ms doesn't matter with frame dropping */ + usleep(0); + } else { + unsigned int t2=GetTimer(); + double tt; + unsigned player_idx; + + /* It's time to sleep ;)...*/ + MP_UNIT("sleep"); + GetRelativeTime(); /* reset timer */ + sleep_time=vplayer_compute_sleep_time(sh_audio,sh_video,&shva_prev,v_pts); + + if(!(vo_data->flags&256)){ /* flag 256 means: libvo driver does its timing (dvb card) */ + if(!vplayer_do_sleep(sh_audio,mp_data->rtc_fd,sleep_time)) return 0; + } + + player_idx=dae_next_played(xp_core->video); + vo_select_frame(vo_data,player_idx); + dae_inc_played(xp_core->video); + MSG_D("\ndec_ahead_main: schedule %u on screen\n",player_idx); + t2=GetTimer()-t2; + tt = t2*0.000001f; + mp_data->bench->vout+=tt; + if(mp_conf.benchmark) { + /* we need compute draw_slice+change_frame here */ + mp_data->bench->cur_vout+=tt; + } + } + MP_UNIT(NULL); + +/*================ A-V TIMESTAMP CORRECTION: =========================*/ + /* FIXME: this block was added to fix A-V resync caused by some strange things + like playing 48KHz audio on 44.1KHz soundcard and other. + Now we know PTS of every audio frame so don't need to have it */ + if(!xp_core->audio) sh_audio=NULL; + if(sh_audio && (!xp_core->audio->eof || ao_get_delay(ao_data)) && !mp_conf.av_sync_pts) { + float a_pts=0; + + // unplayed bytes in our and soundcard/dma buffer: + float delay=ao_get_delay(ao_data)+(float)sh_audio->a_buffer_len/(float)sh_audio->af_bps; + if(mp_conf.xp>=XP_VideoAudio) + delay += get_delay_audio_buffer(); + + if(pts_from_bps){ + unsigned int samples=(sh_audio->audio.dwSampleSize)? + ((ds_tell(d_audio)-sh_audio->a_in_buffer_len)/sh_audio->audio.dwSampleSize) : + (d_audio->pack_no); // <- used for VBR audio + samples+=sh_audio->audio.dwStart; // offset + a_pts=samples*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate; + delay_corrected=1; + } else { + // PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec) + a_pts=d_audio->pts; + if(!delay_corrected) if(a_pts) delay_corrected=1; + a_pts+=(ds_tell_pts_r(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + } + + MSG_DBG2("### A:%8.3f (%8.3f) V:%8.3f A-V:%7.4f \n",a_pts,a_pts-delay,v_pts,(a_pts-delay)-*v_pts); + + if(delay_corrected && can_blit){ + float AV_delay=0; /* average of A-V timestamp differences */ + float x; + AV_delay=(a_pts-delay)-v_pts; + x=AV_delay*0.1f; + if(x<-max_pts_correction) x=-max_pts_correction; + else if(x> max_pts_correction) x= max_pts_correction; + max_pts_correction=shva.duration*0.10; // +-10% of time + if(mp_conf.xp>=XP_VAPlay) + pthread_mutex_lock(&audio_timer_mutex); + sh_audio->timer+=x; + if(mp_conf.xp>=XP_VAPlay) + pthread_mutex_unlock(&audio_timer_mutex); + if(mp_conf.benchmark && mp_conf.verbose) __show_status_line(a_pts,v_pts,delay,AV_delay); + } + } else { + // No audio or pts: + if(mp_conf.benchmark && mp_conf.verbose) show_status_line_no_apts(sh_audio,v_pts); + } + return 0; +} + +any_t* xmp_video_player( any_t* arg ) +{ + mpxp_thread_t* priv=arg; + sh_video_t* sh_video=priv->dae->sh; + demux_stream_t *d_video=sh_video->ds; + demuxer_t *demuxer=d_video->demuxer; + sh_audio_t* sh_audio=demuxer->audio->sh; + + priv->state=Pth_Run; + priv->dae->eof = 0; + if(xp_core->audio) xp_core->audio->eof=0; + MSG_T("\nDEC_AHEAD: entering...\n"); + __MP_UNIT(priv->p_idx,"dec_ahead"); + priv->pid = getpid(); + +while(!priv->dae->eof){ + if(priv->state==Pth_Canceling) break; + if(priv->state==Pth_Sleep) { + priv->state=Pth_ASleep; + while(priv->state==Pth_ASleep) usleep(0); + continue; + } + __MP_UNIT(priv->p_idx,"play video"); + + priv->dae->eof=mpxp_play_video(demuxer,sh_audio,sh_video); +/*------------------------ frame decoded. --------------------*/ +} /* while(!priv->dae->eof)*/ + MSG_T("\nDEC_AHEAD: leaving...\n"); + priv->state=Pth_Stand; + return arg; /* terminate thread here !!! */ +} + +void sig_video_play( void ) +{ + MSG_T("sig_audio_play\n"); + mp_msg_flush(); + + dec_ahead_can_aseek=1; + + xmp_killall_threads(pthread_self()); + __exit_sighandler(); +} Property changes on: mplayerxp/xmp_vplayer.c ___________________________________________________________________ Added: svn:eol-style + native Added: mplayerxp/xmp_vplayer.h =================================================================== --- mplayerxp/xmp_vplayer.h (rev 0) +++ mplayerxp/xmp_vplayer.h 2012-11-02 16:03:16 UTC (rev 284) @@ -0,0 +1,8 @@ +#ifndef XMP_VPLAYER_H_INCLUDED +#define XMP_VPLAYER_H_INCLUDED 1 + +extern float max_pts_correction; + +extern any_t* xmp_video_player( any_t* arg ); +extern void sig_video_play( void ); +#endif Property changes on: mplayerxp/xmp_vplayer.h ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |