[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[172] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2012-10-19 12:33:18
|
Revision: 172 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=172&view=rev Author: nickols_k Date: 2012-10-19 12:33:03 +0000 (Fri, 19 Oct 2012) Log Message: ----------- new version of XP-CORE Modified Paths: -------------- mplayerxp/dec_ahead.c mplayerxp/dec_ahead.h mplayerxp/libmpcodecs/dec_video.c mplayerxp/libmpcodecs/vd.c mplayerxp/libmpdemux/demux_audio.c mplayerxp/libmpdemux/demux_ty.c mplayerxp/libmpdemux/demuxer_r.c mplayerxp/libmpdemux/demuxer_r.h mplayerxp/libvo/screenshot.c mplayerxp/libvo/screenshot.h mplayerxp/libvo/sub.c mplayerxp/libvo/sub.h mplayerxp/libvo/video_out.c mplayerxp/libvo/video_out.h mplayerxp/libvo/video_out_internal.h mplayerxp/libvo/vo_dga.c mplayerxp/libvo/vo_fbdev.c mplayerxp/libvo/vo_null.c mplayerxp/libvo/vo_opengl.c mplayerxp/libvo/vo_sdl.c mplayerxp/libvo/vo_vesa.c mplayerxp/libvo/vo_x11.c mplayerxp/libvo/vo_xv.c mplayerxp/libvo/vo_xvidix.c mplayerxp/libvo/vosub_vidix.c mplayerxp/libvo/vosub_vidix.h mplayerxp/mp_image.c mplayerxp/mplayer.c mplayerxp/postproc/vf.c mplayerxp/postproc/vf.h mplayerxp/postproc/vf_1bpp.c mplayerxp/postproc/vf_2xsai.c mplayerxp/postproc/vf_delogo.c mplayerxp/postproc/vf_denoise3d.c mplayerxp/postproc/vf_dint.c mplayerxp/postproc/vf_down3dright.c mplayerxp/postproc/vf_eq.c mplayerxp/postproc/vf_expand.c mplayerxp/postproc/vf_framestep.c mplayerxp/postproc/vf_il.c mplayerxp/postproc/vf_menu.c mplayerxp/postproc/vf_mirror.c mplayerxp/postproc/vf_noise.c mplayerxp/postproc/vf_ow.c mplayerxp/postproc/vf_palette.c mplayerxp/postproc/vf_panscan.c mplayerxp/postproc/vf_perspective.c mplayerxp/postproc/vf_pp.c mplayerxp/postproc/vf_raw.c mplayerxp/postproc/vf_rectangle.c mplayerxp/postproc/vf_rgb2bgr.c mplayerxp/postproc/vf_rotate.c mplayerxp/postproc/vf_scale.c mplayerxp/postproc/vf_smartblur.c mplayerxp/postproc/vf_softpulldown.c mplayerxp/postproc/vf_swapuv.c mplayerxp/postproc/vf_test.c mplayerxp/postproc/vf_unsharp.c mplayerxp/postproc/vf_vo.c mplayerxp/postproc/vf_yuvcsp.c mplayerxp/postproc/vf_yuy2.c mplayerxp/postproc/vf_yvu9.c mplayerxp/spudec.c Modified: mplayerxp/dec_ahead.c =================================================================== --- mplayerxp/dec_ahead.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/dec_ahead.c 2012-10-19 12:33:03 UTC (rev 172) @@ -33,25 +33,82 @@ #else #define MSG_T(args...) #endif -pthread_mutex_t vdecoding_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t vreading_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t vdec_active_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t vdec_locked_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t vdeca_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t seek_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t seek_cond_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t seek_cond=PTHREAD_COND_INITIALIZER; +xp_core_t xp_core; +void xp_core_init(void) { + pthread_mutexattr_t attr; + memset(&xp_core,0,sizeof(xp_core_t)); + xp_core.in_lseek=NoSeek; + pthread_mutexattr_init(&attr); + pthread_mutex_init(&xp_core.seek_mutex, &attr); +} + +void xp_core_uninit(void) {} + +void xp_core_lock_seeking(void) { pthread_mutex_lock(&xp_core.seek_mutex); } +void xp_core_unlock_seeking(void) { pthread_mutex_unlock(&xp_core.seek_mutex); } + +void dae_reset(dec_ahead_engine_t* it) { + it->player_idx=0; + it->decoder_idx=0; + it->num_slow_frames=0; + it->num_played_frames=0; + it->num_decoded_frames=0; +} + +void dae_init(dec_ahead_engine_t* it,unsigned nframes) +{ + it->nframes=nframes; + it->fra = malloc(sizeof(frame_attr_t)*nframes); + dae_reset(it); +} + +void dae_uninit(dec_ahead_engine_t* it) { free(it->fra); it->fra=0; } + +/* returns 1 - on success 0 - if busy */ +int dae_inc_played(dec_ahead_engine_t* it) { + unsigned new_idx; + new_idx=(it->player_idx+1)%it->nframes; + if(new_idx==it->decoder_idx) { + it->num_slow_frames++; + return 0; + } + it->player_idx=new_idx; + it->num_slow_frames=0; + it->num_played_frames++; + return 1; +} +/* returns 1 - on success 0 - if busy */ +int dae_inc_decoded(dec_ahead_engine_t* it) { + unsigned new_idx; + new_idx=(it->decoder_idx+1)%it->nframes; + if(new_idx==it->player_idx) return 0; + it->decoder_idx=new_idx; + it->num_decoded_frames++; + return 1; +} + +unsigned dae_prev_played(const dec_ahead_engine_t* it) { return (it->player_idx-1)%it->nframes; } +unsigned dae_prev_decoded(const dec_ahead_engine_t* it) { return (it->decoder_idx-1)%it->nframes; } +unsigned dae_next_played(const dec_ahead_engine_t* it) { return (it->player_idx+1)%it->nframes; } +unsigned dae_next_decoded(const dec_ahead_engine_t* it) { return (it->decoder_idx+1)%it->nframes; } + +frame_attr_t dae_played_fra(const dec_ahead_engine_t* it) { + unsigned idx=it->player_idx; + return it->fra[idx]; +} +frame_attr_t dae_decoded_fra(const dec_ahead_engine_t* it) { + unsigned idx=it->decoder_idx; + return it->fra[idx]; +} + pthread_mutex_t audio_play_mutex=PTHREAD_MUTEX_INITIALIZER; pthread_cond_t audio_play_cond=PTHREAD_COND_INITIALIZER; pthread_mutex_t audio_decode_mutex=PTHREAD_MUTEX_INITIALIZER; pthread_cond_t audio_decode_cond=PTHREAD_COND_INITIALIZER; -pthread_mutex_t video_decode_mutex=PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t video_decode_cond=PTHREAD_COND_INITIALIZER; - extern volatile int xp_drop_frame; extern volatile unsigned xp_drop_frame_cnt; extern int output_quality; @@ -59,21 +116,11 @@ int ao_da_buffs; -volatile int dec_ahead_locked_frame=0; -volatile unsigned abs_dec_ahead_locked_frame=0; -volatile unsigned abs_dec_ahead_blitted_frame=0; -extern volatile unsigned abs_dec_ahead_active_frame; -extern volatile unsigned dec_ahead_active_frame; -extern volatile unsigned loc_dec_ahead_active_frame; extern volatile float xp_screen_pts; -volatile int dec_ahead_in_lseek=NoSeek; volatile int dec_ahead_can_aseek=0; /* It is safe to seek audio */ volatile int dec_ahead_can_adseek=1; /* It is safe to seek audio buffer thread */ -volatile int dec_ahead_in_pause=0; -volatile int dec_ahead_in_resize=0; volatile float dec_ahead_seek_num_frames=0; /* frames played after seek */ volatile int dec_ahead_seek_num_frames_decoded=0; /* frames decoded after seek */ -volatile int dec_ahead_num_frames_decoded=0; /* frames decoded by thread */ static pthread_t pthread_id=0; static pthread_attr_t our_attr; @@ -96,11 +143,8 @@ pthread_t dec_ahead_pth_id; extern void update_osd( float v_pts ); -shva_t *shva; volatile int xp_eof=0; int xp_audio_eof=0; -int has_xp_audio=0; -int has_xp_video=0; #define NORM_FRAME(a) ((a)%xp_num_frames) /* To let audio decoder thread sleep as long as player */ @@ -127,17 +171,111 @@ int xp_is_bad_pts=0; /* this routine decodes video+audio but intends to be video only */ + +static void show_warn_cant_sync(float max_frame_delay) { + static int warned=0; + static float prev_warn_delay=0; + if(!warned || max_frame_delay > prev_warn_delay) { + warned=1; + MSG_WARN("*********************************************\n" + "** Can't stabilize A-V sync!!! **\n" + "*********************************************\n" + "Try increase number of buffer for decoding ahead\n" + "Exist: %u, need: %u\n" + ,xp_num_frames,(unsigned)(max_frame_delay*3*vo.fps)+3); + prev_warn_delay=max_frame_delay; + } +} + +static unsigned compute_frame_dropping(float v_pts,float drop_barrier) { + unsigned rc=0; + static float prev_delta=64; + float delta,max_frame_delay;/* delay for decoding of top slow frame */ + /* + ada_active_frame - abs frame num. which is being displayed + abs_dec_ahead_locked_frame - abs frame num. which is being decoded + */ + max_frame_delay = max_video_time_usage+max_vout_time_usage; + + /* + TODO: + Replace the constants with some values which are depended on + xp_num_frames and max_frame_delay to find out the smoothest way + to display frames on slow machines. + MAYBE!!!: (won't work with some realmedia streams for example) + Try to borrow avifile's logic (btw, GPL'ed ;) for very slow systems: + - fill a full buffer (is not always reachable) + - while(video.pts < audio.pts) + video.seek_to_key_frame(video.get_next_key_frame(video.get_cur_pos())) + */ + delta=v_pts-xp_screen_pts; + if(max_frame_delay*3 > drop_barrier) { + if(drop_barrier < (float)(xp_num_frames-2)/vo.fps) drop_barrier += 1/vo.fps; + else + if(verbose) show_warn_cant_sync(max_frame_delay); + } + if(delta > drop_barrier) rc=0; + else if(delta < max_frame_delay*3) rc=1; + else { + unsigned fr_skip_divisor; + /* + if(delta < drop_barrier/4) fr_skip_divisor=1; -- drop every frame is not smooth thing + else + */ + if(delta < drop_barrier/2) fr_skip_divisor=2; + else + if(delta < drop_barrier*2/3) fr_skip_divisor=3; + else + fr_skip_divisor=4; /* delta < drop_barrier */ + rc = (dae_curr_vdecoded()%fr_skip_divisor)?0:1; + if(delta>prev_delta) rc=0; + } + MSG_D("DEC_AHEAD: max_frame_delay*3=%f drop_barrier=%f prev_delta=%f delta=%f(v_pts=%f screen_pts=%f) n_fr_to_drop=%u\n",max_frame_delay*3,drop_barrier,prev_delta,delta,v_pts,xp_screen_pts,xp_n_frame_to_drop); + prev_delta=delta; + return rc; +} + +static void reorder_pts_in_mpeg(void) { + unsigned idx0=0, idx1, idx2, idx3; + + idx1 = dae_curr_vdecoded(); + idx2 = dae_prev_vdecoded(); + frame_attr_t* fra=xp_core.video->fra; + while( dae_curr_vplayed() != idx2 && + fra[idx2].v_pts > fra[idx1].v_pts && + fra[idx2].v_pts < fra[idx1].v_pts+1.0 ) { + float tmp; + tmp = fra[idx1].v_pts; + fra[idx1].v_pts = fra[idx2].v_pts; + fra[idx2].v_pts = tmp; + + fra[idx1].stream_pts = fra[idx1].v_pts; + fra[idx2].stream_pts = fra[idx2].v_pts; + fra[idx2].duration = fra[idx1].v_pts - fra[idx2].v_pts; + + idx3=(idx2-1)%xp_num_frames; + if(fra[idx2].v_pts > fra[idx3].v_pts && + fra[idx2].v_pts - fra[idx3].v_pts < 1.0) + fra[idx3].duration = fra[idx2].v_pts - fra[idx3].v_pts; + + if(idx1 != dae_curr_vdecoded()) fra[idx1].duration = fra[idx0].v_pts - fra[idx1].v_pts; + + idx0 = idx1; + idx1 = idx2; + idx2=(idx2-1)%xp_num_frames; + } +} + any_t* Va_dec_ahead_routine( any_t* arg ) { float duration=0; float drop_barrier; int blit_frame=0; int drop_param=0; - volatile unsigned da_active_frame,lda_active_frame,ada_active_frame; unsigned xp_n_frame_to_drop; int _xp_id; - static float prev_delta=0; float v_pts,mpeg_timer=HUGE; + pthread_is_living=1; xp_eof = 0; xp_audio_eof=0; @@ -148,8 +286,7 @@ pinfo[_xp_id].pid = getpid(); /* Only for testing */ dec_ahead_pth_id = pinfo[_xp_id].pth_id = pthread_self(); - pinfo[_xp_id].thread_name = (has_xp_audio && enable_xp < XP_VAFull) ? "video+audio decoding+filtering ahead" : "video decoding+vf ahead"; - prev_delta=xp_num_frames; + pinfo[_xp_id].thread_name = (xp_core.has_audio && enable_xp < XP_VAFull) ? "video+audio decoding+filtering ahead" : "video decoding+vf ahead"; drop_barrier=(float)(xp_num_frames/2)*(1/vo.fps); if(av_sync_pts == -1 && !use_pts_fix2) xp_is_bad_pts = d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_ES || @@ -160,196 +297,75 @@ else xp_is_bad_pts = av_sync_pts?0:1; while(!xp_eof){ + unsigned char* start=NULL; + int in_size; if(pthread_end_of_work) break; - /*-------------------- Decode a frame: -----------------------*/ - { unsigned char* start=NULL; - int in_size; - if(dec_ahead_in_lseek==PreSeek) { - pinfo[_xp_id].current_module = "Pre seek"; - LOCK_VIDEO_DECODE(); - dec_ahead_in_lseek=Seek; - pthread_cond_wait( &video_decode_cond, &video_decode_mutex ); - UNLOCK_VIDEO_DECODE(); - } - pinfo[_xp_id].current_module = "dec_ahead 1"; - /* get it! */ - LOCK_VREADING(); - if(dec_ahead_in_lseek==Seek) - { /* Get info from player after a seek */ - //*((char*)0x100) = 1; // Testing crash - sh_video->num_frames = dec_ahead_seek_num_frames; - sh_video->num_frames_decoded = dec_ahead_seek_num_frames_decoded; - } - /* prevent reent access to non-reent demuxer */ - //if(sh_video->num_frames>200) *((char*)0x100) = 1; // Testing crash - if(has_xp_audio && enable_xp<XP_VAFull) { - pinfo[_xp_id].current_module = "decode audio"; - while(2==xp_thread_decode_audio()) ; - pinfo[_xp_id].current_module = "dec_ahead 2"; - } - in_size=video_read_frame_r(sh_video,&duration,&v_pts,&start,vo.fps); - UNLOCK_VREADING(); - if(dec_ahead_in_lseek==Seek) - { - pinfo[_xp_id].current_module = "Post seek"; - /* reset counters */ - vo_get_active_frame(&dec_ahead_locked_frame); - LOCK_VDEC_ACTIVE(); - LOCK_VDEC_LOCKED(); - abs_dec_ahead_locked_frame = abs_dec_ahead_active_frame; - abs_dec_ahead_blitted_frame = loc_dec_ahead_active_frame; - dec_ahead_locked_frame = dec_ahead_active_frame; - UNLOCK_VDEC_LOCKED(); - UNLOCK_VDEC_ACTIVE(); - if(xp_is_bad_pts) mpeg_timer=HUGE; - dec_ahead_in_lseek=NoSeek; - MSG_T("\nDEC_AHEAD: reset counters to (%u %u) due lseek\n",dec_ahead_locked_frame,abs_dec_ahead_locked_frame); - pinfo[_xp_id].current_module = "dec_ahead 3"; - } - if(in_size<0) - { - __MP_SYNCHRONIZE(vdeca_mutex,shva[dec_ahead_locked_frame].eof=1); - xp_eof=1; - if(has_xp_audio && enable_xp<XP_VAFull) { - while(!xp_audio_eof && !dec_ahead_in_lseek && !pthread_end_of_work) { - pinfo[_xp_id].current_module = "decode audio"; - if(!xp_thread_decode_audio()) - usleep(1); - pinfo[_xp_id].current_module = NULL; - } - if(dec_ahead_in_lseek) { - xp_eof=0; - continue; - } - } - LOCK_VIDEO_DECODE(); - if(!pthread_end_of_work) { - pinfo[_xp_id].current_module = "wait for end of work"; - pthread_cond_wait(&video_decode_cond,&video_decode_mutex); - } - UNLOCK_VIDEO_DECODE(); - if(dec_ahead_in_lseek) { - xp_eof=0; - continue; - } - break; - } - /* in_size==0: it's or broken stream or demuxer's bug */ - if(in_size==0 && !pthread_end_of_work) { - dec_ahead_in_lseek=NoSeek; + if(xp_core.in_lseek==PreSeek) { + pinfo[_xp_id].current_module = "Pre seek"; + xp_core.in_lseek=Seek; + } + pinfo[_xp_id].current_module = "dec_ahead 1"; + if(xp_core.in_lseek==Seek) { + /* Get info from player after a seek */ + //*((char*)0x100) = 1; // Testing crash + sh_video->num_frames = dec_ahead_seek_num_frames; + sh_video->num_frames_decoded = dec_ahead_seek_num_frames_decoded; + } +/* get it! */ + xp_core_lock_seeking(); +#if 0 + /* prevent reent access to non-reent demuxer */ + //if(sh_video->num_frames>200) *((char*)0x100) = 1; // Testing crash + if(xp_core.has_audio && enable_xp<XP_VAFull) { + pinfo[_xp_id].current_module = "decode audio"; + while(2==xp_thread_decode_audio()) ; + pinfo[_xp_id].current_module = "dec_ahead 2"; + } +#endif +/*-------------------- Decode a frame: -----------------------*/ + in_size=video_read_frame_r(sh_video,&duration,&v_pts,&start,vo.fps); + xp_core_unlock_seeking(); + if(xp_core.in_lseek==Seek) { + pinfo[_xp_id].current_module = "Post seek"; + /* reset counters */ + dae_reset(xp_core.video); + if(xp_is_bad_pts) mpeg_timer=HUGE; + xp_core.in_lseek=NoSeek; + MSG_T("\nDEC_AHEAD: reset counters to (%u %u) due lseek\n",dec_ahead_locked_frame,abs_dec_ahead_locked_frame); + pinfo[_xp_id].current_module = "dec_ahead 3"; + } + if(in_size<0) { + xp_core.video->fra[xp_core.video->decoder_idx].eof=1; + xp_eof=1; + if(xp_core.in_lseek) { + xp_eof=0; continue; } - if(xp_is_bad_pts) - { - if(mpeg_timer==HUGE)mpeg_timer=v_pts; - else if( mpeg_timer-duration<v_pts ) { - mpeg_timer=v_pts; - MSG_DBG2("Sync mpeg pts %f\n", mpeg_timer); - } else mpeg_timer+=duration; + break; + } + /* in_size==0: it's or broken stream or demuxer's bug */ + if(in_size==0 && !pthread_end_of_work) { + xp_core.in_lseek=NoSeek; + continue; + } + /* frame was decoded into current decoder_idx */ + if(xp_is_bad_pts) { + if(mpeg_timer==HUGE) mpeg_timer=v_pts; + else if( mpeg_timer-duration<v_pts ) { + mpeg_timer=v_pts; + MSG_DBG2("Sync mpeg pts %f\n", mpeg_timer); } - vo_set_decoding_frame_num(&dec_ahead_locked_frame); - /* ----------- compute frame dropping ------------- */ - LOCK_VDEC_ACTIVE(); - ada_active_frame= abs_dec_ahead_active_frame; - lda_active_frame= loc_dec_ahead_active_frame; - da_active_frame = dec_ahead_active_frame; - UNLOCK_VDEC_ACTIVE(); - xp_n_frame_to_drop=0; - if(frame_dropping) - { - int cur_time; - cur_time = GetTimerMS(); - /* Ugly solution: disable frame dropping right after seeking! */ - if(cur_time - mpxp_seek_time > (xp_num_frames/vo.fps)*100 && - ada_active_frame>=xp_num_frames) - { - float delta,max_frame_delay;/* delay for decoding of top slow frame */ - /* - ada_active_frame - abs frame num. which is being displayed - abs_dec_ahead_locked_frame - abs frame num. which is being decoded - */ - max_frame_delay = max_video_time_usage+max_vout_time_usage; - - /* - TODO: - Replace the constants with some values which are depended on - xp_num_frames and max_frame_delay to find out the smoothest way - to display frames on slow machines. - MAYBE!!!: (won't work with some realmedia streams for example) - Try to borrow avifile's logic (btw, GPL'ed ;) for very slow systems: - - fill a full buffer (is not always reachable) - - while(video.pts < audio.pts) - video.seek_to_key_frame(video.get_next_key_frame(video.get_cur_pos())) - */ - delta=v_pts-xp_screen_pts; - if(max_frame_delay*3 > drop_barrier) - { - if(drop_barrier < (float)(xp_num_frames-2)/vo.fps) drop_barrier += 1/vo.fps; - else - if(verbose) - { - static int warned=0; - static float prev_warn_delay=0; - if(!warned || max_frame_delay > prev_warn_delay) - { - warned=1; - MSG_WARN("*********************************************\n" - "** Can't stabilize A-V sync!!! **\n" - "*********************************************\n" - "Try increase number of buffer for decoding ahead\n" - "Exist: %u, need: %u\n" - ,xp_num_frames,(unsigned)(max_frame_delay*3*vo.fps)+3); - prev_warn_delay=max_frame_delay; - } - } - } - if(delta > drop_barrier) xp_n_frame_to_drop=0; - else - if(delta < max_frame_delay*3) xp_n_frame_to_drop=1; - else - { - unsigned fr_skip_divisor; - /* - if(delta < drop_barrier/4) fr_skip_divisor=1; -- drop every frame is not smooth thing - else - */ - if(delta < drop_barrier/2) fr_skip_divisor=2; - else - if(delta < drop_barrier*2/3) fr_skip_divisor=3; - else - fr_skip_divisor=4; /* delta < drop_barrier */ - xp_n_frame_to_drop = (abs_dec_ahead_locked_frame%fr_skip_divisor)?0:1; - if(delta>prev_delta) xp_n_frame_to_drop=0; - } - MSG_D("DEC_AHEAD: max_frame_delay*3=%f drop_barrier=%f prev_delta=%f delta=%f(v_pts=%f screen_pts=%f) n_fr_to_drop=%u\n",max_frame_delay*3,drop_barrier,prev_delta,delta,v_pts,xp_screen_pts,xp_n_frame_to_drop); - prev_delta=delta; - } - } - /* ------------ sleep --------------- */ - /* sleep if thread is too fast ;) */ - while(abs_dec_ahead_blitted_frame >= lda_active_frame+xp_num_frames-2) - { - MSG_T("DEC_AHEAD: sleep (abs (blitted(%u)>=active+xp-2(%u)))\n" - ,abs_dec_ahead_blitted_frame,lda_active_frame+xp_num_frames-2); - if(pthread_end_of_work) goto pt_exit; - if(dec_ahead_in_lseek!=NoSeek) break; - if(has_xp_audio && enable_xp<XP_VAFull) { - pinfo[_xp_id].current_module = "decode audio"; - xp_thread_decode_audio(); - pinfo[_xp_id].current_module = "dec_ahead 5"; - } - usleep(1); - LOCK_VDEC_ACTIVE(); - lda_active_frame= loc_dec_ahead_active_frame; - da_active_frame = dec_ahead_active_frame; - UNLOCK_VDEC_ACTIVE(); - } - if(dec_ahead_in_lseek!=NoSeek) continue; - LOCK_VDECODING(); - if(dec_ahead_in_lseek!=NoSeek) { - UNLOCK_VDECODING(); - continue; - } + else mpeg_timer+=duration; + } + /* compute frame dropping */ + xp_n_frame_to_drop=0; + if(frame_dropping) { + int cur_time; + cur_time = GetTimerMS(); + /* Ugly solution: disable frame dropping right after seeking! */ + if(cur_time - mpxp_seek_time > (xp_num_frames/vo.fps)*100) xp_n_frame_to_drop=compute_frame_dropping(v_pts,drop_barrier); + } /* if( frame_dropping ) */ + if(xp_core.in_lseek!=NoSeek) continue; #if 0 /* We can't seriously examine question of too slow machines @@ -362,105 +378,74 @@ for(i=0;i<delay;i++) usleep(0); } #endif - if(xp_n_frame_to_drop) drop_param=frame_dropping; - else drop_param=0; - /* decode: */ - MSG_T("\nDEC_AHEAD: decode to %u (abs (blitted(%u)>=active+xp-2(%u)))\n" + if(xp_n_frame_to_drop) drop_param=frame_dropping; + else drop_param=0; + /* decode: */ + MSG_T("\nDEC_AHEAD: decode to %u (abs (blitted(%u)>=active+xp-2(%u)))\n" ,abs_dec_ahead_blitted_frame,abs_dec_ahead_locked_frame,lda_active_frame+xp_num_frames-2); - if(output_quality) - { - unsigned total = xp_num_frames/2; - unsigned distance = abs_dec_ahead_blitted_frame-lda_active_frame; - int our_quality; - our_quality = output_quality*distance/total; - if(drop_param) set_video_quality(sh_video,0); - else - if(auto_quality) set_video_quality(sh_video,our_quality>0?our_quality:0); - } - blit_frame=decode_video(sh_video,start,in_size,drop_param,v_pts); - if(output_quality) - { - if(drop_param) set_video_quality(sh_video,output_quality); - } - if(!blit_frame && drop_param) xp_drop_frame_cnt++; - UNLOCK_VDECODING(); - if(dec_ahead_in_resize) - { - dec_ahead_in_resize=0; - } + if(output_quality) { + unsigned total = xp_num_frames/2; + unsigned distance = dae_curr_vdecoded()-dae_curr_vplayed(); + int our_quality; + our_quality = output_quality*distance/total; + if(drop_param) set_video_quality(sh_video,0); + else + if(auto_quality) set_video_quality(sh_video,our_quality>0?our_quality:0); + } + blit_frame=decode_video(sh_video,start,in_size,drop_param,v_pts); + if(output_quality) { + if(drop_param) set_video_quality(sh_video,output_quality); + } + if(!blit_frame && drop_param) xp_drop_frame_cnt++; #ifdef ENABLE_DEC_AHEAD_DEBUG - if(verbose) - { + if(verbose) { MSG_T("\nDEC_AHEAD: frame %u decoded (blit=%u blit_param=%u size=%i)\n" ,abs_dec_ahead_locked_frame,blit_frame,drop_param,in_size); - } + } #endif - LOCK_VDEC_LOCKED(); - abs_dec_ahead_locked_frame++; - if(blit_frame) - { - LOCK_VDECA(); - if(xp_is_bad_pts) - shva[dec_ahead_locked_frame].v_pts=mpeg_timer; - else - shva[dec_ahead_locked_frame].v_pts = v_pts; - shva[dec_ahead_locked_frame].stream_pts = v_pts; - shva[dec_ahead_locked_frame].duration=duration; - shva[dec_ahead_locked_frame].eof=0; - shva[dec_ahead_locked_frame].num_frames = sh_video->num_frames; - shva[dec_ahead_locked_frame].num_frames_decoded = sh_video->num_frames_decoded; - if(!xp_is_bad_pts) { - int idx = dec_ahead_locked_frame>0?dec_ahead_locked_frame-1:xp_num_frames-1; - shva[idx].duration=v_pts-shva[idx].v_pts; - } - if(frame_reorder) { /* Reorder pts in mpeg streams */ - int idx0=0, idx1, idx2, idx3; - - idx1 = dec_ahead_locked_frame; - idx2 = dec_ahead_locked_frame>0?dec_ahead_locked_frame-1:xp_num_frames-1; - while( dec_ahead_active_frame != idx2 && - shva[idx2].v_pts > shva[idx1].v_pts && - shva[idx2].v_pts < shva[idx1].v_pts+1.0 ) { - float tmp; - tmp = shva[idx1].v_pts; - shva[idx1].v_pts = shva[idx2].v_pts; - shva[idx2].v_pts = tmp; + if(blit_frame) { + unsigned idx=dae_curr_vdecoded(); + if(xp_is_bad_pts) + xp_core.video->fra[idx].v_pts=mpeg_timer; + else + xp_core.video->fra[idx].v_pts = v_pts; + xp_core.video->fra[idx].stream_pts = v_pts; + xp_core.video->fra[idx].duration=duration; + xp_core.video->fra[idx].eof=0; + xp_core.video->fra[idx].num_frames = sh_video->num_frames; + xp_core.video->fra[idx].frame_no = sh_video->num_frames_decoded; + if(!xp_is_bad_pts) { + int _idx = dae_prev_vdecoded(); + xp_core.video->fra[_idx].duration=v_pts-xp_core.video->fra[_idx].v_pts; + } + if(frame_reorder) reorder_pts_in_mpeg(); + } /* if (blit_frame) */ - shva[idx1].stream_pts = shva[idx1].v_pts; - shva[idx2].stream_pts = shva[idx2].v_pts; - shva[idx2].duration = shva[idx1].v_pts - shva[idx2].v_pts; - - idx3=idx2-1; - if(idx3<0) - idx3 = xp_num_frames-1; - if(shva[idx2].v_pts > shva[idx3].v_pts && - shva[idx2].v_pts - shva[idx3].v_pts < 1.0) - shva[idx3].duration = shva[idx2].v_pts - shva[idx3].v_pts; - - if(idx1 != dec_ahead_locked_frame) - shva[idx1].duration = shva[idx0].v_pts - shva[idx1].v_pts; - - idx0 = idx1; - idx1 = idx2; - idx2--; - if(idx2<0) - idx2 = xp_num_frames-1; - } - } - - dec_ahead_num_frames_decoded = sh_video->num_frames_decoded; - UNLOCK_VDECA(); - dec_ahead_locked_frame=(dec_ahead_locked_frame+1)%xp_num_frames; - abs_dec_ahead_blitted_frame++; + /* ------------ sleep --------------- */ + /* sleep if thread is too fast ;) */ + if(blit_frame) + while(!dae_inc_decoded(xp_core.video)) { + MSG_T("DEC_AHEAD: sleep: player=%i decoder=%i)\n" + ,dae_curr_vplayed(),dae_curr_vdecoded()); + if(pthread_end_of_work) goto pt_exit; + if(xp_core.in_lseek!=NoSeek) break; + if(xp_core.has_audio && enable_xp<XP_VAFull) { + pinfo[_xp_id].current_module = "decode audio"; + xp_thread_decode_audio(); + pinfo[_xp_id].current_module = "dec_ahead 5"; } - else - if(in_size && !drop_param) - /* do not count broken frames */ - abs_dec_ahead_locked_frame--; - UNLOCK_VDEC_LOCKED(); + usleep(1); } - /*------------------------ frame decoded. --------------------*/ +/*------------------------ frame decoded. --------------------*/ } /* while(!xp_eof)*/ + +if(xp_core.has_audio && enable_xp<XP_VAFull) { + while(!xp_audio_eof && !xp_core.in_lseek && !pthread_end_of_work) { + pinfo[_xp_id].current_module = "decode audio"; + if(!xp_thread_decode_audio()) usleep(1); + pinfo[_xp_id].current_module = NULL; + } +} pt_exit: MSG_T("\nDEC_AHEAD: leaving...\n"); pthread_is_living=0; @@ -499,7 +484,7 @@ pinfo[xp_id].current_module = "sleep"; LOCK_AUDIO_DECODE(); - if( !dec_ahead_in_lseek && !a_pthread_end_of_work) { + if( !xp_core.in_lseek && !a_pthread_end_of_work) { if(xp_audio_eof) { pinfo[xp_id].current_module = "wait end of work"; pthread_cond_wait( &audio_decode_cond, &audio_decode_mutex ); @@ -512,7 +497,7 @@ } else timeout.tv_sec = audio_play_timeout.tv_sec; } else { - if(dec_ahead_in_pause) + if(xp_core.in_pause) d = 1.0; else d = 0.1; @@ -535,7 +520,7 @@ pinfo[xp_id].current_module = "seek"; LOCK_AUDIO_DECODE(); - while( dec_ahead_in_lseek!=NoSeek && !a_pthread_end_of_work) { + while( xp_core.in_lseek!=NoSeek && !a_pthread_end_of_work) { gettimeofday(&now,NULL); timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec = now.tv_sec + 1; @@ -556,19 +541,17 @@ void uninit_dec_ahead( int force ) { - if(pthread_id && pthread_is_living && has_xp_video) + if(pthread_id && pthread_is_living && xp_core.has_video) { pthread_end_of_work=1; - __MP_SYNCHRONIZE(video_decode_mutex,pthread_cond_signal(&video_decode_cond)); while(pthread_is_living && !force) usleep(0); pthread_is_living=0; pthread_attr_destroy(&our_attr); - free(shva); - shva=NULL; - has_xp_video=0; + dae_uninit(xp_core.video); + xp_core.has_video=0; } - if(has_xp_audio && !force) { /* audio state doesn't matter on segfault :( */ + if(xp_core.has_audio && !force) { /* audio state doesn't matter on segfault :( */ a_pthread_end_of_work=1; xp_audio_eof=1; if(a_pthread_is_living) { @@ -581,18 +564,19 @@ LOCK_AUDIO_PLAY(); pthread_cond_signal(&audio_play_cond); uninit_audio_buffer(); - has_xp_audio=0; + xp_core.has_audio=0; UNLOCK_AUDIO_PLAY(); while(pthread_audio_is_living && !force) usleep(0); pthread_audio_is_living=0; pthread_attr_destroy(&audio_attr); } - if(has_xp_audio) { + if(xp_core.has_audio) { uninit_audio_buffer(); - has_xp_audio=0; + xp_core.has_audio=0; } } + xp_core_uninit(); } /* Min audio buffer to keep free, used to tell differ between full and empty buffer */ @@ -601,29 +585,29 @@ int init_dec_ahead(sh_video_t *shv, sh_audio_t *sha) { pthread_attr_init(&our_attr); - if(shv) { sh_video = shv; has_xp_video=1; } + xp_core_init(); + if(shv) { + sh_video = shv; + xp_core.has_video=1; + xp_core.video=malloc(sizeof(dec_ahead_engine_t)); + dae_init(xp_core.video,xp_num_frames); + } else {/* if (enable_xp >= XP_VAFull) enable_xp = XP_VAPlay;*/ } - if(!(shva = malloc(sizeof(shva_t)*xp_num_frames))) return ENOMEM; if(sha) sh_audio = sha; /* currently is unused */ - dec_ahead_locked_frame=0; - abs_dec_ahead_locked_frame=0; - abs_dec_ahead_blitted_frame=0; - dec_ahead_in_lseek=NoSeek; - dec_ahead_in_resize=0; if(enable_xp>=XP_VideoAudio && sha) { int asize; unsigned o_bps; unsigned min_reserv; o_bps=sh_audio->afilter_inited?sh_audio->af_bps:sh_audio->o_bps; - if(has_xp_video) asize = max(3*sha->audio_out_minsize,max(3*MAX_OUTBURST,o_bps*xp_num_frames/vo.fps))+MIN_BUFFER_RESERV; + if(xp_core.has_video) asize = max(3*sha->audio_out_minsize,max(3*MAX_OUTBURST,o_bps*xp_num_frames/vo.fps))+MIN_BUFFER_RESERV; else asize = o_bps*ao_da_buffs; /* FIXME: get better indices from asize/real_audio_packet_size */ min_reserv = sha->audio_out_minsize; if (o_bps > sha->o_bps) min_reserv = (float)min_reserv * (float)o_bps / (float)sha->o_bps; init_audio_buffer(asize+min_reserv,min_reserv+MIN_BUFFER_RESERV,asize/(sha->audio_out_minsize<10000?sha->audio_out_minsize:4000)+100,sha); - has_xp_audio=1; + xp_core.has_audio=1; if( enable_xp >= XP_VAPlay ) pthread_attr_init(&audio_attr); } @@ -642,7 +626,7 @@ } pthread_attr_setscope(&our_attr,PTHREAD_SCOPE_SYSTEM); - if( has_xp_audio && enable_xp >= XP_VAPlay ) { + if( xp_core.has_audio && enable_xp >= XP_VAPlay ) { retval = pthread_attr_setdetachstate(&audio_attr,PTHREAD_CREATE_DETACHED); if(retval) { if(verbose) printf("running audio thread: attr_setdetachstate fault!!!\n"); @@ -655,13 +639,13 @@ /* requires root privelegies */ pthread_attr_setschedpolicy(&our_attr,SCHED_FIFO); #endif - if( (has_xp_audio && enable_xp >= XP_VAFull) || !has_xp_video ) + if( (xp_core.has_audio && enable_xp >= XP_VAFull) || !xp_core.has_video ) { retval = pthread_create(&pthread_id,&audio_attr,a_dec_ahead_routine,NULL); if( retval ) return retval; while(!a_pthread_is_living) usleep(0); } - if( has_xp_video ) { + if( xp_core.has_video ) { retval = pthread_create(&pthread_id,&our_attr,Va_dec_ahead_routine,NULL); if(retval) return retval; while(!pthread_is_living) usleep(0); @@ -672,7 +656,7 @@ int run_xp_players(void) { int retval; - if( has_xp_audio && enable_xp >= XP_VAPlay ) + if( xp_core.has_audio && enable_xp >= XP_VAPlay ) { retval = pthread_create(&pthread_id,&audio_attr,audio_play_routine,NULL); if( retval ) return retval; @@ -685,7 +669,7 @@ /* Halt threads before seek */ void dec_ahead_halt_threads(int is_reset_vcache) { - dec_ahead_in_lseek = PreSeek; + xp_core.in_lseek = PreSeek; if(pthread_audio_is_living) { LOCK_AUDIO_PLAY(); @@ -701,14 +685,11 @@ UNLOCK_AUDIO_DECODE(); } - if (is_reset_vcache) - UNLOCK_VDECODING(); /* Release lock from vo_x11 */ if(pthread_is_living) { - __MP_SYNCHRONIZE(video_decode_mutex,pthread_cond_signal(&video_decode_cond)); - while(dec_ahead_in_lseek==PreSeek) + while(xp_core.in_lseek==PreSeek) usleep(1); } - dec_ahead_in_lseek = Seek; + xp_core.in_lseek = Seek; } /* Restart threads after seek */ @@ -719,23 +700,21 @@ initial_audio_pts=HUGE; if(enable_xp && !pthread_is_living && !a_pthread_is_living) { - dec_ahead_in_lseek = NoSeek; /* Threads not started, do nothing */ + xp_core.in_lseek = NoSeek; /* Threads not started, do nothing */ return; } - if(!has_xp_audio) + if(!xp_core.has_audio) decore_audio(xp_id); else xp_thread_decode_audio(); if(pthread_is_living) { - __MP_SYNCHRONIZE(video_decode_mutex,pthread_cond_signal(&video_decode_cond)); - while(dec_ahead_in_lseek==Seek) - usleep(1); - while(abs_dec_ahead_locked_frame == abs_dec_ahead_active_frame && !xp_eof) + while(xp_core.in_lseek==Seek) usleep(1); + while(dae_curr_vdecoded() == dae_curr_vplayed() && !xp_eof) usleep(1); /* Wait for thread to decode first frame */ } - dec_ahead_in_lseek = NoSeek; + xp_core.in_lseek = NoSeek; if(a_pthread_is_living) __MP_SYNCHRONIZE(audio_decode_mutex,pthread_cond_signal(&audio_decode_cond)); @@ -751,7 +730,7 @@ int free_buf, vbuf_size, pref_buf; unsigned len=0; - if(dec_ahead_in_lseek) { + if(xp_core.in_lseek) { xp_audio_eof = 0; reset_audio_buffer(); decode_audio_buffer(MAX_OUTBURST); @@ -772,9 +751,9 @@ if( len < MAX_OUTBURST ) /* Buffer underrun */ return decode_audio_buffer(MAX_OUTBURST); - if(has_xp_video) { + if(xp_core.has_video) { /* Match video buffer */ - vbuf_size = abs_dec_ahead_locked_frame - abs_dec_ahead_active_frame; + vbuf_size = dae_curr_vdecoded() - dae_curr_vplayed(); pref_buf = vbuf_size / vo.fps * sh_audio->af_bps; pref_buf -= len; if( pref_buf > 0 ) { @@ -885,7 +864,7 @@ LOCK_AUDIO_PLAY(); d = ao_get_delay() - min_audio_time; - if( !dec_ahead_in_lseek && d > 0 ) { + if( !xp_core.in_lseek && d > 0 ) { gettimeofday(&now,NULL); audio_play_timeout.tv_nsec = now.tv_usec * 1000 + d*1000000000l; if( audio_play_timeout.tv_nsec > 1000000000l ) { @@ -914,7 +893,7 @@ pinfo[xp_id].current_module = "audio pause"; LOCK_AUDIO_PLAY(); - while( dec_ahead_in_pause && !pthread_audio_end_of_work ) { + while( xp_core.in_pause && !pthread_audio_end_of_work ) { pthread_cond_wait( &audio_play_cond, &audio_play_mutex ); } UNLOCK_AUDIO_PLAY(); @@ -924,7 +903,7 @@ pinfo[xp_id].current_module = "audio seek"; LOCK_AUDIO_PLAY(); - while( dec_ahead_in_lseek!=NoSeek && !pthread_audio_end_of_work) { + while( xp_core.in_lseek!=NoSeek && !pthread_audio_end_of_work) { gettimeofday(&now,NULL); timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec = now.tv_sec + 1; @@ -957,20 +936,15 @@ mp_msg_flush(); xp_eof = 1; - shva[dec_ahead_locked_frame].eof=1; + xp_core.video->fra[dae_curr_vdecoded()].eof=1; /* Unlock all mutex ( man page says it may deadlock, but what is worse deadlock here or later? ) */ - UNLOCK_VREADING(); - UNLOCK_VDEC_LOCKED(); - UNLOCK_VDEC_ACTIVE(); - UNLOCK_VDECA(); - UNLOCK_VDECODING(); - UNLOCK_VIDEO_DECODE(); + xp_core_unlock_seeking(); pthread_is_living=0; - dec_ahead_in_lseek=NoSeek; + xp_core.in_lseek=NoSeek; killall_threads(pthread_self()); __exit_sighandler(); } Modified: mplayerxp/dec_ahead.h =================================================================== --- mplayerxp/dec_ahead.h 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/dec_ahead.h 2012-10-19 12:33:03 UTC (rev 172) @@ -20,14 +20,70 @@ enum seek_states { NoSeek=0, PreSeek, Seek }; -enum xp_modes { XP_Old=0, XP_Video, XP_VideoAudio, XP_VAPlay, XP_VAFull }; +enum xp_modes { XP_NA=0, XP_Video, XP_VideoAudio, XP_VAPlay, XP_VAFull }; -extern pthread_mutex_t vdec_active_mutex; /* it's related with video decoding (main process) */ -extern pthread_mutex_t vdec_locked_mutex; /* it's related with video decoding (thread) */ -extern pthread_mutex_t vreading_mutex; /* it's related with reading of video stream */ -extern pthread_mutex_t vdecoding_mutex; /* it's related with video decoding process */ -extern pthread_mutex_t vdeca_mutex; /* it's related with video decoding attributes */ +typedef struct frame_attr_s +{ + int eof; /* indicates last frame in stream */ + float duration; /* frame duration */ + float v_pts; /* presentation time-stamp from input stream */ + float stream_pts; /* real stream's PTS mainly for OSD */ + float num_frames; /* ??? is it really needed */ + long long int frame_no; /* total number of frame */ +}frame_attr_t; +typedef struct dec_ahead_engine_s { + volatile unsigned player_idx; /* index of frame which is currently played */ + volatile unsigned decoder_idx; /* index of frame which is currently decoded */ + unsigned nframes; /* number of frames in buffer */ + frame_attr_t* fra; /* frame related attributes */ + /* for statistics */ + unsigned num_slow_frames;/* number of frames which were delayed due slow computer */ + long long int num_played_frames; + long long int num_decoded_frames; /* for frame dropping */ +}dec_ahead_engine_t; + +typedef struct xp_core_s { + int has_video; + int has_audio; + dec_ahead_engine_t* video; + pthread_mutex_t seek_mutex; + volatile enum seek_states in_lseek; + volatile int in_pause; + volatile int in_resize; +}xp_core_t; +extern xp_core_t xp_core; + +extern void xp_core_init(void); +extern void xp_core_uninit(void); + +extern void xp_core_lock_seeking(void); +extern void xp_core_unlock_seeking(void); + +extern void dae_init(dec_ahead_engine_t* it,unsigned nframes); +extern void dae_uninit(dec_ahead_engine_t* it); +extern void dae_reset(dec_ahead_engine_t* it); /* after mpxp_seek */ + +/* returns 1 - on success 0 - if busy */ +extern int dae_inc_played(dec_ahead_engine_t* it); +extern int dae_inc_decoded(dec_ahead_engine_t* it); + +extern unsigned dae_prev_played(const dec_ahead_engine_t* it); +extern unsigned dae_prev_decoded(const dec_ahead_engine_t* it); +extern unsigned dae_next_played(const dec_ahead_engine_t* it); +extern unsigned dae_next_decoded(const dec_ahead_engine_t* it); + +static inline unsigned dae_curr_vplayed() { return xp_core.video->player_idx; } +static inline unsigned dae_curr_vdecoded() { return xp_core.video->decoder_idx; } +static inline unsigned dae_prev_vplayed() { return dae_prev_played(xp_core.video); } +static inline unsigned dae_prev_vdecoded() { return dae_prev_decoded(xp_core.video); } +static inline unsigned dae_next_vplayed() { return dae_next_played(xp_core.video); } +static inline unsigned dae_next_vdecoded() { return dae_next_decoded(xp_core.video); } + +extern frame_attr_t dae_played_fra(const dec_ahead_engine_t* it); +extern frame_attr_t dae_decoded_fra(const dec_ahead_engine_t* it); + + extern pthread_mutex_t audio_play_mutex; extern pthread_cond_t audio_play_cond; @@ -43,63 +99,25 @@ #else #define MSG_D(args...) #endif -#define LOCK_VDEC_ACTIVE() { MSG_D(DA_PREFIX"LOCK_VDEC_ACTIVE\n"); pthread_mutex_lock(&vdec_active_mutex); } -#define UNLOCK_VDEC_ACTIVE() { MSG_D(DA_PREFIX"UNLOCK_VDEC_ACTIVE\n"); pthread_mutex_unlock(&vdec_active_mutex); } -#define LOCK_VDEC_LOCKED() { MSG_D(DA_PREFIX"LOCK_VDEC_LOCKED\n"); pthread_mutex_lock(&vdec_locked_mutex); } -#define UNLOCK_VDEC_LOCKED() { MSG_D(DA_PREFIX"UNLOCK_VDEC_LOCKED\n"); pthread_mutex_unlock(&vdec_locked_mutex); } - -#define LOCK_VDECODING() { MSG_D(DA_PREFIX"LOCK_VDECODING\n"); pthread_mutex_lock(&vdecoding_mutex); } -#define UNLOCK_VDECODING() { MSG_D(DA_PREFIX"UNLOCK_VDECODING\n"); pthread_mutex_unlock(&vdecoding_mutex); } - -#define LOCK_VREADING() { MSG_D(DA_PREFIX"LOCK_VREADING\n"); pthread_mutex_lock(&vreading_mutex); } -#define UNLOCK_VREADING() { MSG_D(DA_PREFIX"UNLOCK_VREADING\n"); pthread_mutex_unlock(&vreading_mutex); } - -#define LOCK_VDECA() { MSG_D(DA_PREFIX"LOCK_VDECA\n"); pthread_mutex_lock(&vdeca_mutex); } -#define UNLOCK_VDECA() { MSG_D(DA_PREFIX"UNLOCK_VDECA\n"); pthread_mutex_unlock(&vdeca_mutex); } - #define LOCK_AUDIO_PLAY() { MSG_D(DA_PREFIX"LOCK_AUDIO_PLAY\n"); pthread_mutex_lock(&audio_play_mutex); } #define UNLOCK_AUDIO_PLAY() { MSG_D(DA_PREFIX"UNLOCK_AUDIO_PLAY\n"); pthread_mutex_unlock(&audio_play_mutex); } #define LOCK_AUDIO_DECODE() { MSG_D(DA_PREFIX"LOCK_AUDIO_DECODE\n"); pthread_mutex_lock(&audio_decode_mutex); } #define UNLOCK_AUDIO_DECODE() { MSG_D(DA_PREFIX"UNLOCK_AUDIO_DECODE\n"); pthread_mutex_unlock(&audio_decode_mutex); } -#define LOCK_VIDEO_DECODE() { MSG_D(DA_PREFIX"LOCK_VIDEO_DECODE\n"); pthread_mutex_lock(&video_decode_mutex); } -#define UNLOCK_VIDEO_DECODE() { MSG_D(DA_PREFIX"UNLOCK_VIDEO_DECODE\n"); pthread_mutex_unlock(&video_decode_mutex); } - #define __MP_ATOMIC(OP) { static pthread_mutex_t loc_mutex; pthread_mutex_lock(&loc_mutex); OP; pthread_mutex_unlock(&loc_mutex); } #define __MP_SYNCHRONIZE(mtx,OP) { pthread_mutex_lock(&mtx); OP; pthread_mutex_unlock(&mtx); } -typedef struct sh_video_attr -{ - int eof; /* indicates last frame in stream */ - float duration; /* frame duration */ - float v_pts; /* presentation time-stamp from input stream */ - float stream_pts; /* real stream's PTS mainly for OSD */ - float num_frames; /* number of frames played */ - int num_frames_decoded; /* number of frames decoded */ -}shva_t; - -extern shva_t* shva; - extern volatile int xp_eof; extern int xp_audio_eof; -extern int has_xp_audio; -extern int has_xp_video; extern int xp_is_bad_pts; -extern volatile int dec_ahead_locked_frame; -extern volatile unsigned abs_dec_ahead_locked_frame; -extern volatile unsigned abs_dec_ahead_blitted_frame; -extern volatile int dec_ahead_in_lseek; -extern volatile int dec_ahead_in_pause; -extern volatile int dec_ahead_in_resize; extern volatile float dec_ahead_seek_num_frames; // frames played after seek extern volatile int dec_ahead_seek_num_frames_decoded; // frames decoded after seek -extern volatile int dec_ahead_num_frames_decoded; // frames decoded by thread extern volatile int dec_ahead_can_aseek; extern int ao_da_buffs; - /* + /* stream - pointer to openned stream astream - pointer to audio stream */ Modified: mplayerxp/libmpcodecs/dec_video.c =================================================================== --- mplayerxp/libmpcodecs/dec_video.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpcodecs/dec_video.c 2012-10-19 12:33:03 UTC (rev 172) @@ -28,6 +28,7 @@ #include "stheader.h" #include "vd.h" +#include "dec_ahead.h" #include "dec_video.h" // =================================================================== vf_cfg_t vf_cfg; // Configuration for audio filters @@ -115,10 +116,8 @@ for (i=0; mpcodecs_vd_drivers[i] != NULL; i++) if(strcmp(mpcodecs_vd_drivers[i]->info->driver_name,sh_video->codec->driver_name)==0) break; mpvdec=mpcodecs_vd_drivers[i]; - if(!mpvdec) { - MSG_DBG3("init_video: mpcodecs_vd_drivers[%s]->mpvdec==0\n",mpcodecs_vd_drivers[i]->info->driver_name); - continue; - } + if(!mpvdec) continue; + else MSG_DBG3("init_video: mpcodecs_vd_drivers[%s]->mpvdec==0\n",mpcodecs_vd_drivers[i]->info->driver_name); // it's available, let's try to init! if(!mpvdec->init(sh_video)){ MSG_ERR(MSGTR_CODEC_CANT_INITV); @@ -184,6 +183,7 @@ const unsigned h_step=16; unsigned num_slices = mpi->h/h_step; vf=sh->vfilter; + if(!(mpi->flags&(MP_IMGFLAG_DRAW_CALLBACK))){ if(mpi->h%h_step) num_slices++; if(sh->vf_flags&VF_FLAGS_SLICES) @@ -219,7 +219,7 @@ { /* execute slices instead of whole frame make faster multiple filters */ for(i=0;i<num_slices;i++) { - MSG_DBG2("dec_video.put_slice[%ux%u] %i %i %i %i\n",ampi[i].width,ampi[i].height,ampi[i].x,ampi[i].y,ampi[i].w,ampi[i].h); + MSG_DBG2("dec_video.put_slice[%ux%u] %i %i %i %i -> [%i]\n",ampi[i].width,ampi[i].height,ampi[i].x,ampi[i].y,ampi[i].w,ampi[i].h,ampi[i].xp_idx); vf->put_slice(vf,&i[i]); } } @@ -263,7 +263,7 @@ if(drop_frame) return 0; update_subtitle(pts); - vo_flush_pages(); + vo_flush_page(dae_curr_vdecoded()); t2=GetTimer()-t2; tt=t2*0.000001f; Modified: mplayerxp/libmpcodecs/vd.c =================================================================== --- mplayerxp/libmpcodecs/vd.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpcodecs/vd.c 2012-10-19 12:33:03 UTC (rev 172) @@ -9,6 +9,7 @@ #include <malloc.h> #endif +#include "dec_ahead.h" #include "codec-cfg.h" #include "../libvo/img_format.h" @@ -166,7 +167,7 @@ goto csp_again; } else { // sws failed, if the last filter (vf_vo) support MPEGPES try to append vf_lavc - vf_instance_t* vo, *vp = NULL, *ve; + vf_instance_t* voi, *vp = NULL, *ve; // Remove the scale filter if we added it ourself if(vf == sc) { ve = vf; @@ -174,8 +175,8 @@ vf_uninit_filter(ve); } // Find the last filter (vf_vo) - for(vo = vf ; vo->next ; vo = vo->next) - vp = vo; + for(voi = vf ; voi->next ; voi = voi->next) + vp = voi; } MSG_WARN(MSGTR_VOincompCodec); sh->vfilter_inited=-1; @@ -226,17 +227,17 @@ } } if(sh->aspect>0.01){ - int w; + int _w; MSG_V("Movie-Aspect is %.2f:1 - prescaling to correct movie aspect.\n", sh->aspect); - w=(int)((float)screen_size_y*sh->aspect); w+=w%2; // round + _w=(int)((float)screen_size_y*sh->aspect); _w+=_w%2; // round // we don't like horizontal downscale || user forced width: - if(w<screen_size_x || vo.screen_size_xy>8){ + if(_w<screen_size_x || vo.screen_size_xy>8){ screen_size_y=(int)((float)screen_size_x*(1.0/sh->aspect)); screen_size_y+=screen_size_y%2; // round if(screen_size_y<sh->disp_h) // Do not downscale verticaly screen_size_y=sh->disp_h; - } else screen_size_x=w; // keep new width + } else screen_size_x=_w; // keep new width } else { MSG_V("Movie-Aspect is undefined - no prescaling applied.\n"); } @@ -260,7 +261,7 @@ MSG_DBG2("vf->config(%dx%d->%dx%d,flags=%d,'%s',%p)\n", sh->disp_w,sh->disp_h, screen_size_x,screen_size_y, - fullscreen|(vidmode<<1)|(softzoom<<2)|(flip<<3), + vo.fullscreen|(vo.vidmode<<1)|(vo.softzoom<<2)|(vo.flip<<3), vo_format_name(out_fmt),tune); return 1; } @@ -271,7 +272,7 @@ // Note: buffer allocation may be moved to mpcodecs_config_vo() later... mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag,int w, int h){ MSG_DBG2("mpcodecs_get_image(vf_%s,%i,%i,%i,%i) was called\n",((vf_instance_t *)(sh->vfilter))->info->name,mp_imgtype,mp_imgflag,w,h); - mp_image_t* mpi=vf_get_image(sh->vfilter,sh->codec->outfmt[sh->outfmtidx],mp_imgtype,mp_imgflag,w,h); + mp_image_t* mpi=vf_get_image(sh->vfilter,sh->codec->outfmt[sh->outfmtidx],mp_imgtype,mp_imgflag,w,h,dae_curr_vdecoded()); mpi->x=mpi->y=0; if(mpi->xp_idx==XP_IDX_INVALID) MSG_V("[mpcodecs_get_image] Incorrect mpi->xp_idx. Be ready for segfault!\n"); Modified: mplayerxp/libmpdemux/demux_audio.c =================================================================== --- mplayerxp/libmpdemux/demux_audio.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpdemux/demux_audio.c 2012-10-19 12:33:03 UTC (rev 172) @@ -1675,7 +1675,7 @@ npercents=(seeka->flags&DEMUX_SEEK_SET)?percents:cpercents+percents; if(npercents>100) npercents=100; newpos=demuxer->movi_start+(off_t)(((float)priv->toc[npercents]/256.0)*priv->nbytes); - MSG_DBG2("xing seeking: secs=%f prcnts=%u cprcnts=%u spos=%llu newpos=%llu\n",rel_seek_secs,npercents,cpercents,spos,newpos); + MSG_DBG2("xing seeking: secs=%f prcnts=%u cprcnts=%u spos=%llu newpos=%llu\n",seeka->secs,npercents,cpercents,spos,newpos); stream_seek(demuxer->stream,newpos); priv->last_pts=(((float)demuxer->movi_length*npercents)/100.)*1000.; return; Modified: mplayerxp/libmpdemux/demux_ty.c =================================================================== --- mplayerxp/libmpdemux/demux_ty.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpdemux/demux_ty.c 2012-10-19 12:33:03 UTC (rev 172) @@ -754,7 +754,7 @@ off_t res; TiVoInfo *tivo = demuxer->priv; - MSG_DBG3( "ty:Seeking to %7.1f\n", rel_seek_secs ); + MSG_DBG3( "ty:Seeking to %7.1f\n", seeka->secs ); tivo->lastAudioEnd = 0; tivo->lastAudioPTS = -1; Modified: mplayerxp/libmpdemux/demuxer_r.c =================================================================== --- mplayerxp/libmpdemux/demuxer_r.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpdemux/demuxer_r.c 2012-10-19 12:33:03 UTC (rev 172) @@ -12,6 +12,8 @@ #include "../dec_ahead.h" pthread_mutex_t demuxer_mutex=PTHREAD_MUTEX_INITIALIZER; +#define LOCK_DEMUXER() { pthread_mutex_lock(&demuxer_mutex); } +#define UNLOCK_DEMUXER() { pthread_mutex_unlock(&demuxer_mutex); } static float get_ds_stream_pts(demux_stream_t *ds,int nbytes) { Modified: mplayerxp/libmpdemux/demuxer_r.h =================================================================== --- mplayerxp/libmpdemux/demuxer_r.h 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libmpdemux/demuxer_r.h 2012-10-19 12:33:03 UTC (rev 172) @@ -11,10 +11,6 @@ extern "C" { #endif -extern pthread_mutex_t demuxer_mutex; -#define LOCK_DEMUXER() { pthread_mutex_lock(&demuxer_mutex); } -#define UNLOCK_DEMUXER() { pthread_mutex_unlock(&demuxer_mutex); } - #define ds_tell_pts_r(ds) ds_tell_pts(ds) extern int demux_getc_r(demux_stream_t *ds,float *pts); Modified: mplayerxp/libvo/screenshot.c =================================================================== --- mplayerxp/libvo/screenshot.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libvo/screenshot.c 2012-10-19 12:33:03 UTC (rev 172) @@ -43,7 +43,7 @@ FILE * fp; png_structp png_ptr; png_infop info_ptr; - enum {OK,ERROR} status; + enum {OK,ERROR} status; }; static struct pngdata create_png (char * fname) @@ -68,22 +68,22 @@ png.status = ERROR; return png; } - + if (setjmp(png.png_ptr->jmpbuf)) { - MSG_V("PNG Internal error!\n"); + MSG_V("PNG Internal error!\n"); png_destroy_write_struct(&png.png_ptr, &png.info_ptr); fclose(png.fp); png.status = ERROR; return png; } - + png.fp = fopen (fname, "wb"); if (png.fp == NULL) { MSG_ERR("\nPNG Error opening %s for writing!\n", strerror(errno)); - png.status = ERROR; - return png; - } - + png.status = ERROR; + return png; + } + MSG_V("PNG Init IO\n"); png_init_io(png.png_ptr, png.fp); @@ -93,28 +93,28 @@ png_set_IHDR(png.png_ptr, png.info_ptr, sshot.image_width, sshot.image_height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - + MSG_V("PNG Write Info\n"); png_write_info(png.png_ptr, png.info_ptr); - + if(sshot.cspace) { MSG_V("PNG Set BGR Conversion\n"); png_set_bgr(png.png_ptr); - } + } png.status = OK; return png; - -} - + +} + static uint8_t destroy_png(struct pngdata png) { - + MSG_V("PNG Write End\n"); png_write_end(png.png_ptr, png.info_ptr); MSG_V("PNG Destroy Write Struct\n"); png_destroy_write_struct(&png.png_ptr, &png.info_ptr); - + fclose (png.fp); return 0; @@ -177,7 +177,7 @@ } #endif -int gr_screenshot(const char *fname,uint8_t *planes[],int *strides,uint32_t fourcc,unsigned w,unsigned h) +int gr_screenshot(const char *fname,uint8_t *planes[],unsigned *strides,uint32_t fourcc,unsigned w,unsigned h) { unsigned k; char buf[256]; @@ -186,7 +186,7 @@ #endif uint8_t *image_data=NULL; uint8_t *dst[3]; - int dstStride[3],bpp = 24; + unsigned dstStride[3],bpp = 24; struct SwsContext * sws = NULL; @@ -215,9 +215,9 @@ MSG_HINT("PNG Warning: compression level set to 0, compression disabled!\n"); MSG_HINT("PNG Info: Use the -z <n> switch to set compression level from 0 to 9.\n"); MSG_HINT("PNG Info: (0 = no compression, 1 = fastest, lowest - 9 best, slowest compression)\n"); - } + } } - else { + else { MSG_WARN("PNG Warning: compression level out of range setting to 1!\n"); MSG_WARN("PNG Info: Use the -z <n> switch to set compression level from 0 to 9.\n"); MSG_WARN("PNG Info: (0 = no compression, 1 = fastest, lowest - 9 best, slowest compression)\n"); @@ -243,7 +243,7 @@ if(png.status){ MSG_ERR("PNG Error in create_png\n"); - } + } { png_byte *row_pointers[sshot.image_height]; @@ -251,7 +251,7 @@ for ( k = 0; k < sshot.image_height; k++ ) row_pointers[k] = &image_data[sshot.image_width*k*bppmul]; png_write_image(png.png_ptr, row_pointers); } - + destroy_png(png); #else write_bmp(buf,w,h,image_data); Modified: mplayerxp/libvo/screenshot.h =================================================================== --- mplayerxp/libvo/screenshot.h 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libvo/screenshot.h 2012-10-19 12:33:03 UTC (rev 172) @@ -3,6 +3,6 @@ #ifndef __VO_SCREENSHOT #define __VO_SCREENSHOT 1 -extern int gr_screenshot(const char *fname,uint8_t *planes[],int *strides,uint32_t fourcc,unsigned w,unsigned h); +extern int gr_screenshot(const char *fname,uint8_t *planes[],unsigned *strides,uint32_t fourcc,unsigned w,unsigned h); #endif Modified: mplayerxp/libvo/sub.c =================================================================== --- mplayerxp/libvo/sub.c 2012-10-18 14:27:24 UTC (rev 171) +++ mplayerxp/libvo/sub.c 2012-10-19 12:33:03 UTC (rev 172) @@ -17,7 +17,6 @@ #include "../libmpdemux/stream.h" #define MSGT_CLASS MSGT_OSD #include "../__mp_msg.h" -#define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */ static const char * __sub_osd_names[]={ "Seekbar", @@ -68,9 +67,10 @@ } // renders the buffer -inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,draw_osd_f draw_alpha){ +inline static void vo_draw_text_from_buffer(unsigned idx,mp_osd_obj_t* obj,draw_osd_f draw_alpha){ if (obj->allocated > 0) { - draw_alpha(obj->bbox.x1,obj->bbox.y1, + draw_alpha(idx, + obj->bbox.x1,obj->bbox.y1, obj->bbox.x2-obj->bbox.x1, obj->bbox.y2-obj->bbox.y1, obj->bitmap_buffer, @@ -131,7 +131,7 @@ } -inline static void __FASTCALL__ vo_draw_text_osd(mp_osd_obj_t* obj,draw_osd_f draw_alpha){ +inline static void __FASTCALL__ vo_draw_text_osd(unsigned idx,mp_osd_obj_t* obj,draw_osd_f draw_alpha){ unsigned char *cp=(unsigned char *)vo.osd_text; int font; int x=obj->x; @@ -139,13 +139,14 @@ while (*cp){ int c=*cp++; if ((font=vo.font->font[c])>=0 && c != ' ') - draw_alpha(x,obj->y, - vo.font->width[c], - vo.font->pic_a[font]->h, - vo.font->pic_b[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->w); - x+=vo.font->width[c]+vo.font->charspace; + draw_alpha( idx, + x,obj->y, + vo.font->width[c], + vo.font->pic_a[font]->h, + vo.font->pic_b[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->w); + x+=vo.font->width[c]+vo.font->charspace; } } @@ -189,7 +190,7 @@ } -inline static void __FASTCALL__ vo_draw_text_progbar(mp_osd_obj_t* obj,draw_osd_f draw_alpha){ +inline static void __FASTCALL__ vo_draw_text_progbar(unsigned idx,mp_osd_obj_t* obj,draw_osd_f draw_alpha){ unsigned char *s; unsigned char *sa; int i,w,h,st,mark; @@ -208,41 +209,41 @@ if (mark>elems) mark=elems; } - c=vo.osd_progbar_type; - if(vo.osd_progbar_type>0 && (font=vo.font->font[c])>=0) { + c=vo.osd_progbar_type; + if(vo.osd_progbar_type>0 && (font=vo.font->font[c])>=0) { int xp=x-vo.font->width[c]-vo.font->spacewidth; - draw_alpha((xp<0?0:xp),y, - vo.font->width[c], - vo.font->pic_a[font]->h, - vo.font->pic_b[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->w); + draw_alpha(idx,(xp<0?0:xp),y, + vo.font->width[c], + vo.font->pic_a[font]->h, + vo.font->pic_b[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->w); } - c=OSD_PB_START; - if ((font=vo.font->font[c])>=0) - draw_alpha(x,y, - vo.font->width[c], - vo.font->pic_a[font]->h, - vo.font->pic_b[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->w); - x+=vo.font->width[c]+vo.font->charspace; + c=OSD_PB_START; + if ((font=vo.font->font[c])>=0) + draw_alpha(idx,x,y, + vo.font->width[c], + vo.font->pic_a[font]->h, + vo.font->pic_b[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->w); + x+=vo.font->width[c]+vo.font->charspace; - c=OSD_PB_0; - if ((font=vo.font->font[c])>=0){ + c=OSD_PB_0; + if ((font=vo.font->font[c])>=0){ w=vo.font->width[c]; h=vo.font->pic_a[font]->h; s=vo.font->pic_b[font]->bmp+vo.font->start[c]; sa=vo.font->pic_a[font]->bmp+vo.font->start[c]; st=vo.font->pic_a[font]->w; if ((i=mark)) do { - draw_alpha(x,y,w,h,s,sa,st); + draw_alpha(idx,x,y,w,h,s,sa,st); x+=charw; } while(--i); } - c=OSD_PB_1; + c=OSD_PB_1; if ((font=vo.font->font[c])>=0){ w=vo.font->width[c]; h=vo.font->pic_a[font]->h; @@ -250,19 +251,19 @@ sa=vo.font->pic_a[font]->bmp+vo.font->start[c]; st=vo.font->pic_a[font]->w; if ((i=elems-mark)) do { - draw_alpha(x,y,w,h,s,sa,st); + draw_alpha(idx,x,y,w,h,s,sa,st); x+=charw; } while(--i); } - c=OSD_PB_END; - if ((font=vo.font->font[c])>=0) - draw_alpha(x,y, - vo.font->width[c], - vo.font->pic_a[font]->h, - vo.font->pic_b[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->bmp+vo.font->start[c], - vo.font->pic_a[font]->w); + c=OSD_PB_END; + if ((font=vo.font->font[c])>=0) + draw_alpha(idx,x,y, + vo.font->width[c], + vo.font->pic_a[font]->h, + vo.font->pic_b[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->bmp+vo.font->start[c], + vo.font->pic_a[font]->w); // x+=vo.font->width[c]+vo.font->charspace; @@ -379,7 +380,7 @@ } -inline static void __FASTCALL__ vo_draw_text_sub(mp_osd_obj_t* obj,draw_osd_f draw_alpha){ +inline static void __FASTCALL__ vo_draw_text_sub(unsigned idx,mp_osd_obj_t* obj,draw_osd_f draw_alpha){ int i,j,c,x,l,font; int y=obj->y; @@ -388,7 +389,7 @@ x=obj->params.subtitle.xtbl[i++]; while ((c=obj->params.subtitle.utbl[j++])){ if ((font=vo.font->font[c])>=0) - draw_alpha(x,y, + draw_alpha(idx,x,y, vo.font->width[c], vo.font->pic_a[font]->h+y<obj->dys ? vo.font->pic_a[font]->h : obj->dys-y, vo.font->pic_b[font]->bmp+vo.font->start[c], @@ -506,7 +507,7 @@ new_osd_obj(OSDTYPE_DVDNAV); } -void __FASTCALL__ vo_remove_text(int dxs,int dys,clear_osd_f remove){ +void __FASTCALL__ vo_remove_text(unsigned idx,int dxs,int dys,clear_osd_f f_remove){ mp_osd_obj_t* obj=vo_osd_list; vo_update_osd(dxs,dys); while(obj){ @@ -517,7 +518,7 @@ int h=obj->old_bbox.y2-obj->old_bbox.y1; if(w>0 && h>0){ vo.osd_changed_flag=obj->flags&OSDFLAG_CHANGED; // temp hack - remove(obj->old_bbox.x1,obj->old_bbox.y1,w,h); + f_remove(idx,obj->old_bbox.x1,obj->old_bbox.y1,w,h); } // obj->flags&=~OSDFLAG_OLD_BBOX; if(obj->cleared_frames>=0) { @@ -530,7 +531,7 @@ } } -void __FASTCALL__ vo_draw_text(... [truncated message content] |