[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[285] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2012-11-02 17:03:12
|
Revision: 285 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=285&view=rev Author: nickols_k Date: 2012-11-02 17:03:04 +0000 (Fri, 02 Nov 2012) Log Message: ----------- split XP_CORE into separate files Modified Paths: -------------- mplayerxp/Makefile mplayerxp/mplayer.c mplayerxp/mplayer.h mplayerxp/xmp_core.c mplayerxp/xmp_core.h mplayerxp/xmp_vplayer.c Added Paths: ----------- mplayerxp/xmp_adecoder.c mplayerxp/xmp_adecoder.h mplayerxp/xmp_aplayer.c mplayerxp/xmp_aplayer.h mplayerxp/xmp_vdecoder.c mplayerxp/xmp_vdecoder.h Modified: mplayerxp/Makefile =================================================================== --- mplayerxp/Makefile 2012-11-02 16:03:16 UTC (rev 284) +++ mplayerxp/Makefile 2012-11-02 17:03:04 UTC (rev 285) @@ -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 xmp_vplayer.c +SRCS_MPLAYER+= xmp_core.c xmp_aplayer.c xmp_vplayer.c xmp_vdecoder.c xmp_adecoder.c OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) Modified: mplayerxp/mplayer.c =================================================================== --- mplayerxp/mplayer.c 2012-11-02 16:03:16 UTC (rev 284) +++ mplayerxp/mplayer.c 2012-11-02 17:03:04 UTC (rev 285) @@ -74,6 +74,7 @@ #include "xmp_core.h" #include "xmp_vplayer.h" +#include "xmp_adecoder.h" #define MSGT_CLASS MSGT_CPLAYER #include "mp_msg.h" @@ -236,362 +237,6 @@ mp_uninit_malloc(mp_conf.verbose); } -/************************************************************************ - AUDIO XP-CORE! ToDo: rewrite it in packet-mode -************************************************************************/ -/* XP audio buffer */ -pthread_mutex_t audio_timer_mutex=PTHREAD_MUTEX_INITIALIZER; -typedef struct audio_buffer_index_s { - float pts; - int index; -} audio_buffer_index_t; - -typedef struct audio_buffer_s { - unsigned char* buffer; - int head; - int tail; - unsigned len; - unsigned size; - int min_reserv; - int min_len; - int eof; - int HasReset; - int blocked_readers; - pthread_mutex_t head_mutex; - pthread_mutex_t tail_mutex; - pthread_cond_t wait_buffer_cond; - sh_audio_t *sh_audio; - - audio_buffer_index_t *indices; - int index_head; - int index_tail; - int index_len; -} audio_buffer_t; - -audio_buffer_t audio_buffer; - -int init_audio_buffer( int size, int min_reserv, int indices, sh_audio_t *sha ) -{ - MSG_V("Using audio buffer %i bytes (min reserve = %i, indices %i)\n",size,min_reserv, indices); - if( !(audio_buffer.buffer = mp_malloc(size)) ) - return ENOMEM; - if( !(audio_buffer.indices = mp_malloc(indices*sizeof(audio_buffer_index_t))) ) { - mp_free(audio_buffer.buffer); - audio_buffer.buffer=NULL; - return ENOMEM; - } - audio_buffer.index_len=indices; - audio_buffer.index_head=0; - audio_buffer.index_tail=0; - audio_buffer.head = 0; - audio_buffer.tail = 0; - audio_buffer.len = size; - audio_buffer.size = size; - audio_buffer.min_reserv = min_reserv; - audio_buffer.min_len = size/indices+1; - audio_buffer.eof = 0; - audio_buffer.HasReset = 0; - audio_buffer.blocked_readers = 0; - pthread_mutex_init( &audio_buffer.head_mutex, NULL); - pthread_mutex_init( &audio_buffer.tail_mutex, NULL); - pthread_cond_init( &audio_buffer.wait_buffer_cond, NULL); - audio_buffer.sh_audio = sha; - return 0; -} - -void uninit_audio_buffer(void) -{ - audio_buffer.eof = 1; - - if( audio_buffer.blocked_readers > 0 ) { /* Make blocked reader exit */ - int loops = 10; - pthread_cond_broadcast( &audio_buffer.wait_buffer_cond ); - while( audio_buffer.blocked_readers > 0 && loops > 0 ) { - usleep(1); - loops--; - } - if( audio_buffer.blocked_readers > 0 ) - MSG_V("uninit_audio_buffer: %d blocked readers did not wake up\n", - audio_buffer.blocked_readers); - } - - audio_buffer.index_len=0; - audio_buffer.index_head=0; - audio_buffer.index_tail=0; - audio_buffer.head = 0; - audio_buffer.tail = 0; - audio_buffer.len = 0; - audio_buffer.size = 0; - audio_buffer.min_reserv = 0; - audio_buffer.min_len = 0; - audio_buffer.HasReset = 0; - audio_buffer.blocked_readers = 0; - - pthread_mutex_lock( &audio_buffer.head_mutex ); - pthread_mutex_unlock( &audio_buffer.head_mutex ); - pthread_mutex_destroy( &audio_buffer.head_mutex ); - - pthread_mutex_lock( &audio_buffer.tail_mutex ); - pthread_mutex_unlock( &audio_buffer.tail_mutex ); - pthread_mutex_destroy( &audio_buffer.tail_mutex ); - - pthread_cond_destroy( &audio_buffer.wait_buffer_cond ); - - if( audio_buffer.buffer ) - mp_free( audio_buffer.buffer ); - audio_buffer.buffer = NULL; - - if( audio_buffer.indices ) - mp_free( audio_buffer.indices ); - audio_buffer.indices = NULL; - /* audio_buffer.sh_audio = ?; */ -} - -int read_audio_buffer( sh_audio_t *audio, unsigned char *buffer, unsigned minlen, unsigned maxlen, float *pts ) -{ - unsigned len = 0; - int l = 0; - int next_idx; - int head_idx; - int head_pos; - int head; - UNUSED(audio); - pthread_mutex_lock( &audio_buffer.tail_mutex ); - - while( len < minlen ) { - if( audio_buffer.tail == audio_buffer.head ) { - if( audio_buffer.eof ) { - break; - } - audio_buffer.blocked_readers++; - dec_ahead_can_aseek=1; /* Safe to seek while we wait for data */ - pthread_cond_wait(&audio_buffer.wait_buffer_cond, &audio_buffer.tail_mutex ); - dec_ahead_can_aseek=0; - audio_buffer.blocked_readers--; - if( audio_buffer.HasReset ) { - audio_buffer.HasReset = 0; - len = 0; - l =0; - } - continue; - } - - l = min( (int)(maxlen - len), audio_buffer.head - audio_buffer.tail ); - if(l<0) { - l = min( maxlen - len, audio_buffer.len - audio_buffer.tail ); - if( l == 0 ) { - if( audio_buffer.head != audio_buffer.tail ) - audio_buffer.tail = 0; - continue; - } - } - - memcpy( &buffer[len], &audio_buffer.buffer[audio_buffer.tail], l ); - len += l; - audio_buffer.tail += l; - if( audio_buffer.tail >= audio_buffer.len && audio_buffer.tail != audio_buffer.head ) - audio_buffer.tail = 0; - } - - if( len > 0 ) { /* get pts to return and calculate next pts */ - next_idx = (audio_buffer.index_tail+1)%audio_buffer.index_len; - head_idx = audio_buffer.index_head; - head_pos = audio_buffer.indices[(head_idx-1+audio_buffer.index_len)%audio_buffer.index_len].index; - head = audio_buffer.head; - if( next_idx != head_idx && audio_buffer.indices[next_idx].index == audio_buffer.indices[audio_buffer.index_tail].index ) { - audio_buffer.index_tail = next_idx; /* Buffer was empty */ - next_idx = (audio_buffer.index_tail+1)%audio_buffer.index_len; - } - *pts = audio_buffer.indices[audio_buffer.index_tail].pts; - - MSG_DBG3("audio_ahead: len %i, tail %i pts %.3f tail_idx %3i head_idx %3i head_pos %3i\n", len,audio_buffer.tail,*pts, audio_buffer.index_tail, head_idx, head_pos ); - while( next_idx != head_idx && - ((audio_buffer.tail <= head && - (audio_buffer.indices[next_idx].index <= audio_buffer.tail || - head_pos < audio_buffer.indices[next_idx].index)) || - (head < audio_buffer.indices[next_idx].index && - audio_buffer.indices[next_idx].index <= audio_buffer.tail))) { - MSG_DBG3("audio_ahead: next_idx %3i index %3i \n", next_idx, audio_buffer.indices[next_idx].index); - next_idx=(next_idx+1)%audio_buffer.index_len; - } - audio_buffer.index_tail = (next_idx-1+audio_buffer.index_len)%audio_buffer.index_len; - if( audio_buffer.indices[audio_buffer.index_tail].index != audio_buffer.tail ) { - int buff_len = audio_buffer.len; - MSG_DBG3("audio_ahead: orig idx %3i pts %.3f pos %i \n",audio_buffer.index_tail, audio_buffer.indices[audio_buffer.index_tail].pts,audio_buffer.indices[audio_buffer.index_tail].index ); - audio_buffer.indices[audio_buffer.index_tail].pts += (float)((audio_buffer.tail - audio_buffer.indices[audio_buffer.index_tail].index + buff_len) % buff_len) / (float)audio_buffer.sh_audio->af_bps; - audio_buffer.indices[audio_buffer.index_tail].index = audio_buffer.tail; - MSG_DBG3("audio_ahead: read next_idx %3i next_pts %.3f pos %i \n", audio_buffer.index_tail,audio_buffer.indices[audio_buffer.index_tail].pts,audio_buffer.indices[audio_buffer.index_tail].index ); - } - } - - pthread_mutex_unlock( &audio_buffer.tail_mutex ); - - return len; -} - -float get_delay_audio_buffer(void) -{ - int delay = audio_buffer.head - audio_buffer.tail; - if( delay < 0 ) - delay += audio_buffer.len; - return (float)delay / (float)audio_buffer.sh_audio->af_bps; -} - -int decode_audio_buffer(unsigned len) -{ - priv_t*priv=mp_data->priv; - demux_stream_t *d_audio=priv->demuxer->audio; - int ret, blen, l, l2; - int next_idx; - unsigned int t; - - pthread_mutex_lock( &audio_buffer.head_mutex ); - - t = GetTimer(); - if (len < audio_buffer.sh_audio->audio_out_minsize) - len = audio_buffer.sh_audio->audio_out_minsize; - - if( audio_buffer.size - audio_buffer.head <= audio_buffer.min_reserv ) { - if( audio_buffer.tail == 0 ) { - pthread_mutex_unlock( &audio_buffer.head_mutex ); - return 0; - } - audio_buffer.len = audio_buffer.head; - audio_buffer.head = 0; - len = min( len, audio_buffer.tail - audio_buffer.head - audio_buffer.min_reserv); - if( len < audio_buffer.sh_audio->audio_out_minsize ) { - pthread_mutex_unlock( &audio_buffer.head_mutex ); - return 0; - } - } - - blen = audio_buffer.size - audio_buffer.head; - if( (l = (blen - audio_buffer.min_reserv)) < len ) { - len = max(l,audio_buffer.sh_audio->audio_out_minsize); - } - - if( (l = (audio_buffer.tail - audio_buffer.head)) > 0 ) { - blen = l; - l -= audio_buffer.min_reserv; - if( l < len ) { - len = l; - if( len < audio_buffer.sh_audio->audio_out_minsize ) { - pthread_mutex_unlock( &audio_buffer.head_mutex ); - return 0; - } - } - } - MSG_DBG3("decode audio %d h %d, t %d, l %d \n", len, audio_buffer.head, audio_buffer.tail, audio_buffer.len); - - for( l = 0, l2 = len, ret = 0; l < len && l2 >= audio_buffer.sh_audio->audio_out_minsize; ) { - float pts; - ret = mpca_decode( audio_buffer.sh_audio, &audio_buffer.buffer[audio_buffer.head], audio_buffer.min_len, l2,blen,&pts); - if( ret <= 0 ) - break; - - next_idx = (audio_buffer.index_head+1)%audio_buffer.index_len; - if( next_idx != audio_buffer.index_tail ) { - MSG_DBG3("decode audio idx %3i tail %3i next pts %.3f %i\n",audio_buffer.index_head, audio_buffer.index_tail, pts, audio_buffer.head ); - audio_buffer.indices[audio_buffer.index_head].pts = pts; - audio_buffer.indices[audio_buffer.index_head].index = audio_buffer.head; - audio_buffer.index_head = next_idx; - } - audio_buffer.head+=ret; - MSG_DBG3("new head %6d \n", audio_buffer.head); - l += ret; - l2 -= ret; - blen -= ret; - } - MSG_DBG2("decoded audio %d diff %d\n", l, l - len); - - if( ret <= 0 && d_audio->eof) { - MSG_V("audio eof\n"); - audio_buffer.eof=1; - pthread_mutex_unlock( &audio_buffer.head_mutex ); - pthread_mutex_lock( &audio_buffer.tail_mutex ); - pthread_cond_broadcast( &audio_buffer.wait_buffer_cond ); - pthread_mutex_unlock( &audio_buffer.tail_mutex ); - return 0; - } - - if( audio_buffer.head > audio_buffer.len ) - audio_buffer.len=audio_buffer.head; - if( audio_buffer.head >= audio_buffer.size && audio_buffer.tail > 0 ) - audio_buffer.head = 0; - - pthread_cond_signal( &audio_buffer.wait_buffer_cond ); - - t=GetTimer()-t; - mp_data->bench->audio_decode+=t*0.000001f; - mp_data->bench->audio_decode-=mp_data->bench->audio_decode_correction; - if(mp_conf.benchmark) - { - if(t > mp_data->bench->max_audio_decode) mp_data->bench->max_audio_decode = t; - if(t < mp_data->bench->min_audio_decode) mp_data->bench->min_audio_decode = t; - } - - pthread_mutex_unlock( &audio_buffer.head_mutex ); - - - blen = audio_buffer.head - audio_buffer.tail; - if( blen < 0 ) - blen += audio_buffer.len; - if( blen < MAX_OUTBURST ) { - return 2; - } - return 1; -} - -void reset_audio_buffer(void) -{ - pthread_mutex_lock( &audio_buffer.head_mutex ); - pthread_mutex_lock( &audio_buffer.tail_mutex ); - - audio_buffer.tail = audio_buffer.head; - audio_buffer.len = audio_buffer.size; - audio_buffer.eof = 0; - audio_buffer.HasReset = 1; - audio_buffer.index_tail = audio_buffer.index_head; - - pthread_mutex_unlock( &audio_buffer.tail_mutex ); - pthread_mutex_unlock( &audio_buffer.head_mutex ); -} - -int get_len_audio_buffer(void) -{ - int len = audio_buffer.head - audio_buffer.tail; - if( len < 0 ) - len += audio_buffer.len; - return len; -} - -int get_free_audio_buffer(void) -{ - int len; - - if( audio_buffer.eof ) - return -1; - - if( audio_buffer.size - audio_buffer.head < audio_buffer.min_reserv && - audio_buffer.tail > 0 ) { - pthread_mutex_lock( &audio_buffer.head_mutex ); - audio_buffer.len = audio_buffer.head; - audio_buffer.head = 0; - pthread_mutex_unlock( &audio_buffer.head_mutex ); - } - - len = audio_buffer.tail - audio_buffer.head; - if( len <= 0 ) - len += audio_buffer.size; - len -= audio_buffer.min_reserv; - - if( len <= 0 ) - return 0; - - return len; -} - - void uninit_player(unsigned int mask){ priv_t*priv=mp_data->priv; stream_t* stream=NULL; @@ -713,7 +358,6 @@ return; /* Still try coredump!!!*/ } - static void soft_exit_player(void) { priv_t*priv=mp_data->priv; @@ -973,119 +617,6 @@ list_codecs(1); } -int decore_audio( unsigned _xp_id ) -{ - 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; - int eof = 0; -/*========================== PLAY AUDIO ============================*/ -while(sh_audio){ - unsigned int t; - double tt; - int playsize; - float pts=HUGE; - int ret=0; - - ao_data->pts=sh_audio->timer*90000.0; - playsize=ao_get_space(ao_data); - - if(!playsize) { - if(sh_video) - break; // buffer is full, do not block here!!! - usec_sleep(10000); // Wait a tick before retry - continue; - } - - if(playsize>MAX_OUTBURST) playsize=MAX_OUTBURST; // we shouldn't exceed it! - //if(playsize>outburst) playsize=outburst; - - // Update buffer if needed - MP_UNIT("mpca_decode"); // Enter AUDIO decoder module - t=GetTimer(); - while(sh_audio->a_buffer_len<playsize && !xp_core->audio->eof){ - if(mp_conf.xp>=XP_VideoAudio) { - ret=read_audio_buffer(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len], - playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,&pts); - } else - { - ret=mpca_decode(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len], - playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,&pts); - } - if(ret>0) sh_audio->a_buffer_len+=ret; - else { - if(!d_audio->eof) - break; - if(!sh_video) - eof = PT_NEXT_ENTRY; - else - { - MSG_V("audio_stream_eof\n"); - priv->inited_flags&=~INITED_AO; - MP_UNIT("uninit_ao"); - ao_uninit(ao_data); - } - xp_core->audio->eof=1; - break; - } - } - MP_UNIT("play_audio"); // Leave AUDIO decoder module - t=GetTimer()-t; - tt = t*0.000001f; - mp_data->bench->audio+=tt; - if(mp_conf.benchmark) - { - if(tt > mp_data->bench->max_audio) mp_data->bench->max_audio = tt; - if(tt < mp_data->bench->min_audio) mp_data->bench->min_audio = tt; - mp_data->bench->cur_audio=tt; - } - if(playsize>sh_audio->a_buffer_len) playsize=sh_audio->a_buffer_len; - - if(mp_conf.xp>=XP_VAPlay) dec_ahead_audio_delay=ao_get_delay(ao_data); - - playsize=ao_play(ao_data,sh_audio->a_buffer,playsize,0); - - if(playsize>0){ - sh_audio->a_buffer_len-=playsize; - memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[playsize],sh_audio->a_buffer_len); - if(!mp_conf.av_sync_pts && mp_conf.xp>=XP_VAPlay) - pthread_mutex_lock(&audio_timer_mutex); - if(mp_data->use_pts_fix2) { - if(sh_audio->a_pts != HUGE) { - sh_audio->a_pts_pos-=playsize; - if(sh_audio->a_pts_pos > -ao_get_delay(ao_data)*sh_audio->af_bps) { - sh_audio->timer+=playsize/(float)(sh_audio->af_bps); - } else { - sh_audio->timer=sh_audio->a_pts-(float)sh_audio->a_pts_pos/(float)sh_audio->af_bps; - MSG_V("Audio chapter change detected\n"); - sh_audio->chapter_change=1; - sh_audio->a_pts = HUGE; - } - } else if(pts != HUGE) { - if(pts < 1.0 && sh_audio->timer > 2.0) { - sh_audio->timer+=playsize/(float)(sh_audio->af_bps); - sh_audio->a_pts=pts; - sh_audio->a_pts_pos=sh_audio->a_buffer_len-ret; - } else { - sh_audio->timer=pts+(ret-sh_audio->a_buffer_len)/(float)(sh_audio->af_bps); - sh_audio->a_pts=HUGE; - } - } else - sh_audio->timer+=playsize/(float)(sh_audio->af_bps); - } else if(mp_conf.av_sync_pts && pts!=HUGE) - sh_audio->timer=pts+(ret-sh_audio->a_buffer_len)/(float)(sh_audio->af_bps); - else - sh_audio->timer+=playsize/(float)(sh_audio->af_bps); - if(!mp_conf.av_sync_pts && mp_conf.xp>=XP_VAPlay) - pthread_mutex_unlock(&audio_timer_mutex); - } - - break; - } // if(sh_audio) - return eof; -} - #ifdef USE_OSD //================= Update OSD ==================== @@ -2484,8 +2015,7 @@ if(mp_conf.play_n_frames<0) eof = PT_NEXT_ENTRY; } - if( mp_conf.xp < XP_VAPlay ) - eof |= decore_audio(main_id); + eof |= xp_core->audio->eof; /*========================== UPDATE TIMERS ============================*/ MP_UNIT("Update timers"); if(!sh_video) { Modified: mplayerxp/mplayer.h =================================================================== --- mplayerxp/mplayer.h 2012-11-02 16:03:16 UTC (rev 284) +++ mplayerxp/mplayer.h 2012-11-02 17:03:04 UTC (rev 285) @@ -114,7 +114,6 @@ 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); Added: mplayerxp/xmp_adecoder.c =================================================================== --- mplayerxp/xmp_adecoder.c (rev 0) +++ mplayerxp/xmp_adecoder.c 2012-11-02 17:03:04 UTC (rev 285) @@ -0,0 +1,520 @@ +#include "mplayer.h" +#include "mp_msg.h" +#include "sig_hand.h" +#include "xmp_core.h" +#include "xmp_adecoder.h" +#include "osdep/mplib.h" +#include "osdep/timer.h" +#include "libmpcodecs/dec_audio.h" + +#include <errno.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 int get_free_audio_buffer(void); + +/************************************************************************ + AUDIO XP-CORE! ToDo: rewrite it in packet-mode +************************************************************************/ +/* XP audio buffer */ +pthread_mutex_t audio_timer_mutex=PTHREAD_MUTEX_INITIALIZER; +typedef struct audio_buffer_index_s { + float pts; + int index; +} audio_buffer_index_t; + +typedef struct audio_buffer_s { + unsigned char* buffer; + int head; + int tail; + unsigned len; + unsigned size; + int min_reserv; + int min_len; + int eof; + int HasReset; + int blocked_readers; + pthread_mutex_t head_mutex; + pthread_mutex_t tail_mutex; + pthread_cond_t wait_buffer_cond; + sh_audio_t *sh_audio; + + audio_buffer_index_t *indices; + int index_head; + int index_tail; + int index_len; +} audio_buffer_t; + +audio_buffer_t audio_buffer; + +int init_audio_buffer( int size, int min_reserv, int indices, sh_audio_t *sha ) +{ + MSG_V("Using audio buffer %i bytes (min reserve = %i, indices %i)\n",size,min_reserv, indices); + if( !(audio_buffer.buffer = mp_malloc(size)) ) + return ENOMEM; + if( !(audio_buffer.indices = mp_malloc(indices*sizeof(audio_buffer_index_t))) ) { + mp_free(audio_buffer.buffer); + audio_buffer.buffer=NULL; + return ENOMEM; + } + audio_buffer.index_len=indices; + audio_buffer.index_head=0; + audio_buffer.index_tail=0; + audio_buffer.head = 0; + audio_buffer.tail = 0; + audio_buffer.len = size; + audio_buffer.size = size; + audio_buffer.min_reserv = min_reserv; + audio_buffer.min_len = size/indices+1; + audio_buffer.eof = 0; + audio_buffer.HasReset = 0; + audio_buffer.blocked_readers = 0; + pthread_mutex_init( &audio_buffer.head_mutex, NULL); + pthread_mutex_init( &audio_buffer.tail_mutex, NULL); + pthread_cond_init( &audio_buffer.wait_buffer_cond, NULL); + audio_buffer.sh_audio = sha; + return 0; +} + +void uninit_audio_buffer(void) +{ + audio_buffer.eof = 1; + + if( audio_buffer.blocked_readers > 0 ) { /* Make blocked reader exit */ + int loops = 10; + pthread_cond_broadcast( &audio_buffer.wait_buffer_cond ); + while( audio_buffer.blocked_readers > 0 && loops > 0 ) { + usleep(1); + loops--; + } + if( audio_buffer.blocked_readers > 0 ) + MSG_V("uninit_audio_buffer: %d blocked readers did not wake up\n", + audio_buffer.blocked_readers); + } + + audio_buffer.index_len=0; + audio_buffer.index_head=0; + audio_buffer.index_tail=0; + audio_buffer.head = 0; + audio_buffer.tail = 0; + audio_buffer.len = 0; + audio_buffer.size = 0; + audio_buffer.min_reserv = 0; + audio_buffer.min_len = 0; + audio_buffer.HasReset = 0; + audio_buffer.blocked_readers = 0; + + pthread_mutex_lock( &audio_buffer.head_mutex ); + pthread_mutex_unlock( &audio_buffer.head_mutex ); + pthread_mutex_destroy( &audio_buffer.head_mutex ); + + pthread_mutex_lock( &audio_buffer.tail_mutex ); + pthread_mutex_unlock( &audio_buffer.tail_mutex ); + pthread_mutex_destroy( &audio_buffer.tail_mutex ); + + pthread_cond_destroy( &audio_buffer.wait_buffer_cond ); + + if( audio_buffer.buffer ) + mp_free( audio_buffer.buffer ); + audio_buffer.buffer = NULL; + + if( audio_buffer.indices ) + mp_free( audio_buffer.indices ); + audio_buffer.indices = NULL; + /* audio_buffer.sh_audio = ?; */ +} + +int read_audio_buffer( sh_audio_t *audio, unsigned char *buffer, unsigned minlen, unsigned maxlen, float *pts ) +{ + unsigned len = 0; + int l = 0; + int next_idx; + int head_idx; + int head_pos; + int head; + UNUSED(audio); + pthread_mutex_lock( &audio_buffer.tail_mutex ); + + while( len < minlen ) { + if( audio_buffer.tail == audio_buffer.head ) { + if( audio_buffer.eof ) { + break; + } + audio_buffer.blocked_readers++; + dec_ahead_can_aseek=1; /* Safe to seek while we wait for data */ + pthread_cond_wait(&audio_buffer.wait_buffer_cond, &audio_buffer.tail_mutex ); + dec_ahead_can_aseek=0; + audio_buffer.blocked_readers--; + if( audio_buffer.HasReset ) { + audio_buffer.HasReset = 0; + len = 0; + l =0; + } + continue; + } + + l = min( (int)(maxlen - len), audio_buffer.head - audio_buffer.tail ); + if(l<0) { + l = min( maxlen - len, audio_buffer.len - audio_buffer.tail ); + if( l == 0 ) { + if( audio_buffer.head != audio_buffer.tail ) + audio_buffer.tail = 0; + continue; + } + } + + memcpy( &buffer[len], &audio_buffer.buffer[audio_buffer.tail], l ); + len += l; + audio_buffer.tail += l; + if( audio_buffer.tail >= audio_buffer.len && audio_buffer.tail != audio_buffer.head ) + audio_buffer.tail = 0; + } + + if( len > 0 ) { /* get pts to return and calculate next pts */ + next_idx = (audio_buffer.index_tail+1)%audio_buffer.index_len; + head_idx = audio_buffer.index_head; + head_pos = audio_buffer.indices[(head_idx-1+audio_buffer.index_len)%audio_buffer.index_len].index; + head = audio_buffer.head; + if( next_idx != head_idx && audio_buffer.indices[next_idx].index == audio_buffer.indices[audio_buffer.index_tail].index ) { + audio_buffer.index_tail = next_idx; /* Buffer was empty */ + next_idx = (audio_buffer.index_tail+1)%audio_buffer.index_len; + } + *pts = audio_buffer.indices[audio_buffer.index_tail].pts; + + MSG_DBG3("audio_ahead: len %i, tail %i pts %.3f tail_idx %3i head_idx %3i head_pos %3i\n", len,audio_buffer.tail,*pts, audio_buffer.index_tail, head_idx, head_pos ); + while( next_idx != head_idx && + ((audio_buffer.tail <= head && + (audio_buffer.indices[next_idx].index <= audio_buffer.tail || + head_pos < audio_buffer.indices[next_idx].index)) || + (head < audio_buffer.indices[next_idx].index && + audio_buffer.indices[next_idx].index <= audio_buffer.tail))) { + MSG_DBG3("audio_ahead: next_idx %3i index %3i \n", next_idx, audio_buffer.indices[next_idx].index); + next_idx=(next_idx+1)%audio_buffer.index_len; + } + audio_buffer.index_tail = (next_idx-1+audio_buffer.index_len)%audio_buffer.index_len; + if( audio_buffer.indices[audio_buffer.index_tail].index != audio_buffer.tail ) { + int buff_len = audio_buffer.len; + MSG_DBG3("audio_ahead: orig idx %3i pts %.3f pos %i \n",audio_buffer.index_tail, audio_buffer.indices[audio_buffer.index_tail].pts,audio_buffer.indices[audio_buffer.index_tail].index ); + audio_buffer.indices[audio_buffer.index_tail].pts += (float)((audio_buffer.tail - audio_buffer.indices[audio_buffer.index_tail].index + buff_len) % buff_len) / (float)audio_buffer.sh_audio->af_bps; + audio_buffer.indices[audio_buffer.index_tail].index = audio_buffer.tail; + MSG_DBG3("audio_ahead: read next_idx %3i next_pts %.3f pos %i \n", audio_buffer.index_tail,audio_buffer.indices[audio_buffer.index_tail].pts,audio_buffer.indices[audio_buffer.index_tail].index ); + } + } + + pthread_mutex_unlock( &audio_buffer.tail_mutex ); + + return len; +} + +float get_delay_audio_buffer(void) +{ + int delay = audio_buffer.head - audio_buffer.tail; + if( delay < 0 ) + delay += audio_buffer.len; + return (float)delay / (float)audio_buffer.sh_audio->af_bps; +} + +int decode_audio_buffer(demux_stream_t *d_audio,unsigned len) +{ + int ret, blen, l, l2; + int next_idx; + unsigned int t; + + pthread_mutex_lock( &audio_buffer.head_mutex ); + + t = GetTimer(); + if (len < audio_buffer.sh_audio->audio_out_minsize) + len = audio_buffer.sh_audio->audio_out_minsize; + + if( audio_buffer.size - audio_buffer.head <= audio_buffer.min_reserv ) { + if( audio_buffer.tail == 0 ) { + pthread_mutex_unlock( &audio_buffer.head_mutex ); + return 0; + } + audio_buffer.len = audio_buffer.head; + audio_buffer.head = 0; + len = min( len, audio_buffer.tail - audio_buffer.head - audio_buffer.min_reserv); + if( len < audio_buffer.sh_audio->audio_out_minsize ) { + pthread_mutex_unlock( &audio_buffer.head_mutex ); + return 0; + } + } + + blen = audio_buffer.size - audio_buffer.head; + if( (l = (blen - audio_buffer.min_reserv)) < len ) { + len = max(l,audio_buffer.sh_audio->audio_out_minsize); + } + + if( (l = (audio_buffer.tail - audio_buffer.head)) > 0 ) { + blen = l; + l -= audio_buffer.min_reserv; + if( l < len ) { + len = l; + if( len < audio_buffer.sh_audio->audio_out_minsize ) { + pthread_mutex_unlock( &audio_buffer.head_mutex ); + return 0; + } + } + } + MSG_DBG3("decode audio %d h %d, t %d, l %d \n", len, audio_buffer.head, audio_buffer.tail, audio_buffer.len); + + for( l = 0, l2 = len, ret = 0; l < len && l2 >= audio_buffer.sh_audio->audio_out_minsize; ) { + float pts; + ret = mpca_decode( audio_buffer.sh_audio, &audio_buffer.buffer[audio_buffer.head], audio_buffer.min_len, l2,blen,&pts); + if( ret <= 0 ) + break; + + next_idx = (audio_buffer.index_head+1)%audio_buffer.index_len; + if( next_idx != audio_buffer.index_tail ) { + MSG_DBG3("decode audio idx %3i tail %3i next pts %.3f %i\n",audio_buffer.index_head, audio_buffer.index_tail, pts, audio_buffer.head ); + audio_buffer.indices[audio_buffer.index_head].pts = pts; + audio_buffer.indices[audio_buffer.index_head].index = audio_buffer.head; + audio_buffer.index_head = next_idx; + } + audio_buffer.head+=ret; + MSG_DBG3("new head %6d \n", audio_buffer.head); + l += ret; + l2 -= ret; + blen -= ret; + } + MSG_DBG2("decoded audio %d diff %d\n", l, l - len); + + if( ret <= 0 && d_audio->eof) { + MSG_V("audio eof\n"); + audio_buffer.eof=1; + pthread_mutex_unlock( &audio_buffer.head_mutex ); + pthread_mutex_lock( &audio_buffer.tail_mutex ); + pthread_cond_broadcast( &audio_buffer.wait_buffer_cond ); + pthread_mutex_unlock( &audio_buffer.tail_mutex ); + return 0; + } + + if( audio_buffer.head > audio_buffer.len ) + audio_buffer.len=audio_buffer.head; + if( audio_buffer.head >= audio_buffer.size && audio_buffer.tail > 0 ) + audio_buffer.head = 0; + + pthread_cond_signal( &audio_buffer.wait_buffer_cond ); + + t=GetTimer()-t; + mp_data->bench->audio_decode+=t*0.000001f; + mp_data->bench->audio_decode-=mp_data->bench->audio_decode_correction; + if(mp_conf.benchmark) + { + if(t > mp_data->bench->max_audio_decode) mp_data->bench->max_audio_decode = t; + if(t < mp_data->bench->min_audio_decode) mp_data->bench->min_audio_decode = t; + } + + pthread_mutex_unlock( &audio_buffer.head_mutex ); + + + blen = audio_buffer.head - audio_buffer.tail; + if( blen < 0 ) + blen += audio_buffer.len; + if( blen < MAX_OUTBURST ) { + return 2; + } + return 1; +} + +void reset_audio_buffer(void) +{ + pthread_mutex_lock( &audio_buffer.head_mutex ); + pthread_mutex_lock( &audio_buffer.tail_mutex ); + + audio_buffer.tail = audio_buffer.head; + audio_buffer.len = audio_buffer.size; + audio_buffer.eof = 0; + audio_buffer.HasReset = 1; + audio_buffer.index_tail = audio_buffer.index_head; + + pthread_mutex_unlock( &audio_buffer.tail_mutex ); + pthread_mutex_unlock( &audio_buffer.head_mutex ); +} + +int get_len_audio_buffer(void) +{ + int len = audio_buffer.head - audio_buffer.tail; + if( len < 0 ) + len += audio_buffer.len; + return len; +} + +int get_free_audio_buffer(void) +{ + int len; + + if( audio_buffer.eof ) + return -1; + + if( audio_buffer.size - audio_buffer.head < audio_buffer.min_reserv && + audio_buffer.tail > 0 ) { + pthread_mutex_lock( &audio_buffer.head_mutex ); + audio_buffer.len = audio_buffer.head; + audio_buffer.head = 0; + pthread_mutex_unlock( &audio_buffer.head_mutex ); + } + + len = audio_buffer.tail - audio_buffer.head; + if( len <= 0 ) + len += audio_buffer.size; + len -= audio_buffer.min_reserv; + + if( len <= 0 ) + return 0; + + return len; +} + + +/* Audio stuff */ +volatile float dec_ahead_audio_delay; +int xp_thread_decode_audio(demux_stream_t *d_audio) +{ + sh_audio_t* sh_audio=xp_core->audio->sh; + sh_video_t* sh_video=NULL; + if(xp_core->video) sh_video=xp_core->video->sh; + int free_buf, vbuf_size, pref_buf; + unsigned len=0; + + free_buf = get_free_audio_buffer(); + + if( free_buf == -1 ) { /* End of file */ + xp_core->audio->eof = 1; + return 0; + } + if( free_buf < (int)sh_audio->audio_out_minsize ) /* full */ + return 0; + + len = get_len_audio_buffer(); + + if( len < MAX_OUTBURST ) /* Buffer underrun */ + return decode_audio_buffer(d_audio,MAX_OUTBURST); + + if(xp_core->video) { + /* Match video buffer */ + vbuf_size = dae_get_decoder_outrun(xp_core->video); + pref_buf = vbuf_size / sh_video->fps * sh_audio->af_bps; + pref_buf -= len; + if( pref_buf > 0 ) { + len = min( pref_buf, free_buf ); + if( len > sh_audio->audio_out_minsize ) { + return decode_audio_buffer(d_audio,len); + } + } + } else + return decode_audio_buffer(d_audio,min(free_buf,MAX_OUTBURST)); + + return 0; +} + +static volatile int dec_ahead_can_adseek=1; /* It is safe to seek audio buffer thread */ +/* this routine decodes audio only */ +any_t* a_dec_ahead_routine( any_t* arg ) +{ + mpxp_thread_t* priv=arg; + sh_audio_t* sh_audio=priv->dae->sh; + demux_stream_t *d_audio=sh_audio->ds; + + int ret, retval; + struct timeval now; + struct timespec timeout; + float d; + + priv->state=Pth_Run; + if(xp_core->video) xp_core->video->eof=0; + xp_core->audio->eof=0; + MSG_T("\nDEC_AHEAD: entering...\n"); + priv->pid = getpid(); + __MP_UNIT(priv->p_idx,"dec_ahead"); + + dec_ahead_can_adseek=0; + while(priv->state!=Pth_Canceling) { + if(priv->state==Pth_Sleep) { + priv->state=Pth_ASleep; + while(priv->state==Pth_ASleep) usleep(0); + continue; + } + __MP_UNIT(priv->p_idx,"decode audio"); + while((ret = xp_thread_decode_audio(d_audio)) == 2) {/* Almost empty buffer */ + if(xp_core->audio->eof) break; + } + dec_ahead_can_adseek=1; + + if(priv->state==Pth_Canceling) break; + + __MP_UNIT(priv->p_idx,"sleep"); + LOCK_AUDIO_DECODE(); + if(priv->state!=Pth_Canceling) { + if(xp_core->audio->eof) { + __MP_UNIT(priv->p_idx,"wait end of work"); + pthread_cond_wait( &audio_decode_cond, &audio_decode_mutex ); + } else if(ret==0) { /* Full buffer or end of file */ + if(audio_play_in_sleep) { /* Sleep a little longer than player thread */ + timeout.tv_nsec = audio_play_timeout.tv_nsec + 10000; + if( timeout.tv_nsec > 1000000000l ) { + timeout.tv_nsec-=1000000000l; + timeout.tv_sec = audio_play_timeout.tv_sec; + } else + timeout.tv_sec = audio_play_timeout.tv_sec; + } else { + if(xp_core->in_pause) + d = 1.0; + else + d = 0.1; + gettimeofday(&now,NULL); + timeout.tv_nsec = now.tv_usec * 1000 + d*1000000000l; + if( timeout.tv_nsec > 1000000000l ) { + timeout.tv_nsec-=1000000000l; + timeout.tv_sec = now.tv_sec + 1; + } else + timeout.tv_sec = now.tv_sec; + } + pthread_cond_timedwait( &audio_decode_cond, &audio_decode_mutex, &timeout ); + } else + usleep(1); + } + UNLOCK_AUDIO_DECODE(); + + if(priv->state==Pth_Canceling) break; + + __MP_UNIT(priv->p_idx,"seek"); + LOCK_AUDIO_DECODE(); +#if 0 + while(priv->state==Pth_Sleep && priv->state!=Pth_Canceling) { + gettimeofday(&now,NULL); + timeout.tv_nsec = now.tv_usec * 1000; + timeout.tv_sec = now.tv_sec + 1; + retval = pthread_cond_timedwait( &audio_decode_cond, &audio_decode_mutex, &timeout ); + if( retval == ETIMEDOUT ) + MSG_V("Audio decode seek timeout\n"); + } +#endif + dec_ahead_can_adseek = 0; /* Not safe to seek */ + UNLOCK_AUDIO_DECODE(); + } + __MP_UNIT(priv->p_idx,"exit"); + dec_ahead_can_adseek = 1; + priv->state=Pth_Stand; + return arg; /* terminate thread here !!! */ +} + +void sig_audio_decode( void ) +{ + MSG_T("sig_audio_decode\n"); + mp_msg_flush(); + + dec_ahead_can_adseek=1; + + UNLOCK_AUDIO_DECODE(); + + xmp_killall_threads(pthread_self()); + __exit_sighandler(); +} Property changes on: mplayerxp/xmp_adecoder.c ___________________________________________________________________ Added: svn:eol-style + native Added: mplayerxp/xmp_adecoder.h =================================================================== --- mplayerxp/xmp_adecoder.h (rev 0) +++ mplayerxp/xmp_adecoder.h 2012-11-02 17:03:04 UTC (rev 285) @@ -0,0 +1,14 @@ +#ifndef XMP_ADECODER_H_INCLUDED +#define XMP_ADECODER_H_INCLUDED 1 + +extern int get_len_audio_buffer(void); +extern float get_delay_audio_buffer(void); +extern int init_audio_buffer(int size, int min_reserv, int indices, sh_audio_t *sh_audio); +extern void uninit_audio_buffer(void); +extern void reset_audio_buffer(void); +extern int read_audio_buffer(sh_audio_t *audio, unsigned char *buffer, unsigned minlen, unsigned maxlen, float *pts ); + +extern any_t* a_dec_ahead_routine( any_t* arg ); +extern void sig_audio_decode( void ); +extern int xp_thread_decode_audio(demux_stream_t *d_audio); +#endif Property changes on: mplayerxp/xmp_adecoder.h ___________________________________________________________________ Added: svn:eol-style + native Added: mplayerxp/xmp_aplayer.c =================================================================== --- mplayerxp/xmp_aplayer.c (rev 0) +++ mplayerxp/xmp_aplayer.c 2012-11-02 17:03:04 UTC (rev 285) @@ -0,0 +1,297 @@ +#include "mplayer.h" +#include "mp_msg.h" +#include "sig_hand.h" +#include "xmp_core.h" +#include "xmp_aplayer.h" +#include "xmp_adecoder.h" +#include "osdep/timer.h" +#include "libmpcodecs/dec_audio.h" + +#include "libao2/audio_out.h" + +#include <stdio.h> +#include <unistd.h> // for usleep() +#include <pthread.h> +#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 + +#define MIN_AUDIO_TIME 0.05 +#define NOTHING_PLAYED (-1.0) +#define XP_MIN_TIMESLICE 0.010 /* under Linux on x86 min time_slice = 10 ms */ + +extern ao_data_t*ao_data; + +static int decore_audio(demux_stream_t *d_audio,sh_audio_t* sh_audio,sh_video_t*sh_video,unsigned _xp_id ) +{ + int eof = 0; +/*========================== PLAY AUDIO ============================*/ +while(sh_audio){ + unsigned int t; + double tt; + int playsize; + float pts=HUGE; + int ret=0; + + ao_data->pts=sh_audio->timer*90000.0; + playsize=ao_get_space(ao_data); + + if(!playsize) { + if(sh_video) + break; // buffer is full, do not block here!!! + usec_sleep(10000); // Wait a tick before retry + continue; + } + + if(playsize>MAX_OUTBURST) playsize=MAX_OUTBURST; // we shouldn't exceed it! + //if(playsize>outburst) playsize=outburst; + + // Update buffer if needed + MP_UNIT("mpca_decode"); // Enter AUDIO decoder module + t=GetTimer(); + while(sh_audio->a_buffer_len<playsize && !xp_core->audio->eof){ + if(mp_conf.xp>=XP_VideoAudio) { + ret=read_audio_buffer(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len], + playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,&pts); + } else + { + ret=mpca_decode(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len], + playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len,&pts); + } + if(ret>0) sh_audio->a_buffer_len+=ret; + else { + if(!d_audio->eof) break; + xp_core->audio->eof=1; + break; + } + } + MP_UNIT("play_audio"); // Leave AUDIO decoder module + t=GetTimer()-t; + tt = t*0.000001f; + mp_data->bench->audio+=tt; + if(mp_conf.benchmark) + { + if(tt > mp_data->bench->max_audio) mp_data->bench->max_audio = tt; + if(tt < mp_data->bench->min_audio) mp_data->bench->min_audio = tt; + mp_data->bench->cur_audio=tt; + } + if(playsize>sh_audio->a_buffer_len) playsize=sh_audio->a_buffer_len; + + if(mp_conf.xp>=XP_VAPlay) dec_ahead_audio_delay=ao_get_delay(ao_data); + + playsize=ao_play(ao_data,sh_audio->a_buffer,playsize,0); + + if(playsize>0){ + sh_audio->a_buffer_len-=playsize; + memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[playsize],sh_audio->a_buffer_len); + if(!mp_conf.av_sync_pts && mp_conf.xp>=XP_VAPlay) + pthread_mutex_lock(&audio_timer_mutex); + if(mp_data->use_pts_fix2) { + if(sh_audio->a_pts != HUGE) { + sh_audio->a_pts_pos-=playsize; + if(sh_audio->a_pts_pos > -ao_get_delay(ao_data)*sh_audio->af_bps) { + sh_audio->timer+=playsize/(float)(sh_audio->af_bps); + } else { + sh_audio->timer=sh_audio->a_pts-(float)sh_audio->a_pts_pos/(float)sh_audio->af_bps; + MSG_V("Audio chapter change detected\n"); + sh_audio->chapter_change=1; + sh_audio->a_pts = HUGE; + } + } else if(pts != HUGE) { + if(pts < 1.0 && sh_audio->timer > 2.0) { + sh_audio->timer+=playsize/(float)(sh_audio->af_bps); + sh_audio->a_pts=pts; + sh_audio->a_pts_pos=sh_audio->a_buffer_len-ret; + } else { + sh_audio->timer=pts+(ret-sh_audio->a_buffer_len)/(float)(sh_audio->af_bps); + sh_audio->a_pts=HUGE; + } + } else + sh_audio->timer+=playsize/(float)(sh_audio->af_bps); + } else if(mp_conf.av_sync_pts && pts!=HUGE) + sh_audio->timer=pts+(ret-sh_audio->a_buffer_len)/(float)(sh_audio->af_bps); + else + sh_audio->timer+=playsize/(float)(sh_audio->af_bps); + if(!mp_conf.av_sync_pts && mp_conf.xp>=XP_VAPlay) + pthread_mutex_unlock(&audio_timer_mutex); + } + + break; + } // if(sh_audio) + return eof; +} + + +extern ao_data_t* ao_data; +any_t* audio_play_routine( any_t* arg ) +{ + mpxp_thread_t* priv=arg; + sh_audio_t* sh_audio=priv->dae->sh; + demux_stream_t *d_audio=sh_audio->ds; + demuxer_t *demuxer=d_audio->demuxer; + sh_video_t* sh_video=demuxer->video->sh; + + int eof = 0; + struct timeval now; + struct timespec timeout; + float d; + int retval; + const float MAX_AUDIO_TIME = (float)ao_get_space(ao_data) / sh_audio->af_bps + ao_get_delay(ao_data); + float min_audio_time = MAX_AUDIO_TIME; + float min_audio, max_audio; + int samples, collect_samples; + float audio_buff_max, audio_buff_norm, audio_buff_min, audio_buff_alert; + + audio_buff_alert = max(XP_MIN_TIMESLICE, min(MIN_AUDIO_TIME,MAX_AUDIO_TIME/4)); + audio_buff_max = max(audio_buff_alert, min(MAX_AUDIO_TIME-XP_MIN_TIMESLICE, audio_buff_alert*4)); + audio_buff_min = min(audio_buff_max, audio_buff_alert*2); + audio_buff_norm = (audio_buff_max + audio_buff_min) / 2; + + MSG_DBG2("alert %f, min %f, norm %f, max %f \n", audio_buff_alert, audio_buff_min, audio_buff_norm, audio_buff_max ); + + samples = 5; + collect_samples = 1; + min_audio = MAX_AUDIO_TIME; + max_audio = 0; + + priv->pid = getpid(); + __MP_UNIT(priv->p_idx,"audio_play_routine"); + priv->state=Pth_Run; + dec_ahead_can_aseek=0; + + while(priv->state!=Pth_Canceling) { + if(priv->state==Pth_Sleep) { + priv->state=Pth_ASleep; + while(priv->state==Pth_ASleep) usleep(0); + continue; + } + __MP_UNIT(priv->p_idx,"audio decore_audio"); + dec_ahead_audio_delay = NOTHING_PLAYED; + eof = decore_audio(d_audio,sh_audio,sh_video,priv->p_idx); + + if(priv->state==Pth_Canceling) break; + + __MP_UNIT(priv->p_idx,"audio sleep"); + + dec_ahead_can_aseek = 1; /* Safe for other threads to seek */ + + if( dec_ahead_audio_delay == NOTHING_PLAYED ) { /* To fast, we can sleep longer */ + if( min_audio_time > audio_buff_alert ) { + min_audio_time *= 0.75; + MSG_DBG2("To fast, set min_audio_time %.5f (delay %5f) \n", min_audio_time, dec_ahead_audio_delay ); + } + collect_samples = 1; + samples = 5; + min_audio = MAX_AUDIO_TIME; + max_audio = 0; + } else if( dec_ahead_audio_delay <= audio_buff_alert ) { /* To slow, sleep shorter */ + if ( min_audio_time < MAX_AUDIO_TIME ) { + min_audio_time *= 2.0; + MSG_DBG2("To slow, set min_audio_time %.5f (delay %5f) \n", min_audio_time, dec_ahead_audio_delay ); + } + collect_samples = 1; + samples = 10; + min_audio = MAX_AUDIO_TIME; + max_audio = 0; + } else if( !xp_core->audio->eof && collect_samples) { + if( dec_ahead_audio_delay < min_audio ) + min_audio = dec_ahead_audio_delay; + if( dec_ahead_audio_delay > max_audio ) + max_audio = dec_ahead_audio_delay; + samples--; + + if( samples <= 0 ) { + if( min_audio > audio_buff_max ) { + min_audio_time -= min_audio-audio_buff_norm; + collect_samples = 1; + MSG_DBG2("Decrease min_audio_time %.5f (min %.5f max %.5f) \n", min_audio_time, min_audio, max_audio ); + } else if( max_audio < audio_buff_min ) { + min_audio_time *= 1.25; + collect_samples = 1; + MSG_DBG2("Increase min_audio_time %.5f (min %.5f max %.5f) \n", min_audio_time, min_audio, max_audio ); + } else { + collect_samples = 0; /* No change, stop */ + MSG_DBG2("Stop collecting samples time %.5f (min %.5f max %.5f) \n", min_audio_time, min_audio, max_audio ); + } + if(collect_samples) { + samples = 5; + min_audio = MAX_AUDIO_TIME; + max_audio = 0; + } + } + } + + LOCK_AUDIO_PLAY(); + d = ao_get_delay(ao_data) - min_audio_time; + if( d > 0 ) { + gettimeofday(&now,NULL); + audio_play_timeout.tv_nsec = now.tv_usec * 1000 + d*1000000000l; + if( audio_play_timeout.tv_nsec > 1000000000l ) { + audio_play_timeout.tv_nsec-=1000000000l; + audio_play_timeout.tv_sec = now.tv_sec + 1; + } else + audio_play_timeout.tv_sec = now.tv_sec; + audio_play_in_sleep=1; + pthread_cond_timedwait( &audio_play_cond, &audio_play_mutex, &audio_play_timeout ); + audio_play_in_sleep=0; + } + UNLOCK_AUDIO_PLAY(); + + if(priv->state==Pth_Canceling) break; + + LOCK_AUDIO_PLAY(); + if(eof && priv->state!=Pth_Canceling) { + __MP_UNIT(priv->p_idx,"wait end of work"); + pthread_cond_wait( &audio_play_cond, &audio_play_mutex ); + } + UNLOCK_AUDIO_PLAY(); + + if(priv->state==Pth_Canceling) break; + + __MP_UNIT(priv->p_idx,"audio pause"); + LOCK_AUDIO_PLAY(); + while( xp_core->in_pause && priv->state!=Pth_Canceling) { + pthread_cond_wait( &audio_play_cond, &audio_play_mutex ); + } + UNLOCK_AUDIO_PLAY(); + + if(priv->state==Pth_Canceling) break; + + __MP_UNIT(priv->p_idx,"audio seek"); + LOCK_AUDIO_PLAY(); +#if 0 + while( priv->state==Pth_Sleep && priv->state!=Pth_Canceling) { + gettimeofday(&now,NULL); + timeout.tv_nsec = now.tv_usec * 1000; + timeout.tv_sec = now.tv_sec + 1; + retval = pthread_cond_timedwait( &audio_play_cond, &audio_play_mutex, &timeout ); + if( retval == ETIMEDOUT ) + MSG_V("Audio seek timeout\n"); + } +#endif + dec_ahead_can_aseek = 0; /* Not safe to seek */ + UNLOCK_AUDIO_PLAY(); + } + fflush(stdout); + __MP_UNIT(priv->p_idx,"audio exit"); + dec_ahead_can_aseek=1; + priv->state=Pth_Stand; + return arg; +} + +void sig_audio_play( void ) +{ + MSG_T("sig_audio_play\n"); + mp_msg_flush(); + + dec_ahead_can_aseek=1; + + UNLOCK_AUDIO_PLAY(); + + xmp_killall_threads(pthread_self()); + __exit_sighandler(); +} Property changes on: mplayerxp/xmp_aplayer.c ___________________________________________________________________ Added: svn:eol-style + native Added: mplayerxp/xmp_aplayer.h =================================================================== --- mplayerxp/xmp_aplayer.h (rev 0) +++ mplayerxp/xmp_aplayer.h 2012-11-02 17:03:04 UTC (rev 285) @@ -0,0 +1,6 @@ +#ifndef XMP_APLAYER_H_INCLUDED +#define XMP_APLAYER_H_INCLUDED 1 + +extern any_t* audio_play_routine( any_t* arg ); +extern void sig_audio_play( void ); +#endif Property changes on: mplayerxp/xmp_aplayer.h ___________________________________________________________________ Added: svn:eol-style + native Modified: mplayerxp/xmp_core.c =================================================================== --- mplayerxp/xmp_core.c 2012-11-02 16:03:16 UTC (rev 284) +++ mplayerxp/xmp_core.c 2012-11-02 17:03:04 UTC (rev 285) @@ -20,7 +20,10 @@ #include "mp_msg.h" #include "xmp_core.h" +#include "xmp_aplayer.h" #include "xmp_vplayer.h" +#include "xmp_adecoder.h" +#include "xmp_vdecoder.h" #include "mplayer.h" #include "libao2/audio_out.h" @@ -198,418 +201,11 @@ pthread_cond_t audio_decode_cond=PTHREAD_COND_INITIALIZER; 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 */ -extern int decore_audio( int xp_id ); -extern void update_osd( float v_pts ); - /* To let audio decoder thread sleep as long as player */ -static struct timespec audio_play_timeout; -static int audio_play_in_sleep=0; +struct timespec audio_play_timeout; +int audio_play_in_sleep=0; -extern int init_audio_buffer(int size, int min_reserv, int indices, sh_audio_t *sh_audio); -extern void uninit_audio_buffer(void); -extern int read_audio_buffer(sh_audio_t *audio, unsigned char *buffer, unsigned minlen, unsigned maxlen ); -extern float get_delay_audio_buffer(void); -extern int decode_audio_buffer(unsigned len); -extern void reset_audio_buffer(void); -extern int get_len_audio_buffer(void); -extern int get_free_audio_buffer(void); - -any_t* audio_play_routine( any_t* arg ); - -/* Audio stuff */ -volatile float dec_ahead_audio_delay; -static int xp_thread_decode_audio(void) -{ - sh_audio_t* sh_audio=xp_core->audio->sh; - sh_video_t* sh_video=NULL; - if(xp_core->video) sh_video=xp_core->video->sh; - int free_buf, vbuf_size, pref_buf; - unsigned len=0; - - free_buf = get_free_audio_buffer(); - - if( free_buf == -1 ) { /* End of file */ - xp_core->audio->eof = 1; - return 0; - } - if( free_buf < (int)sh_audio->audio_out_minsize ) /* full */ - return 0; - - len = get_len_audio_buffer(); - - if( len < MAX_OUTBURST ) /* Buffer underrun */ - return decode_audio_buffer(MAX_OUTBURST); - - if(xp_core->video) { - /* Match video buffer */ - vbuf_size = dae_get_decoder_outrun(xp_core->video); - pref_buf = vbuf_size / sh_video->fps * sh_audio->af_bps; - pref_buf -= len; - if( pref_buf > 0 ) { - len = min( pref_buf, free_buf ); - if( len > sh_audio->audio_out_minsize ) { - return decode_audio_buffer(len); - } - } - } else - return decode_audio_buffer(min(free_buf,MAX_OUTBURST)); - - return 0; -} - - -/* this routine decodes video+audio but intends to be video only */ - -static void show_warn_cant_sync(sh_video_t*sh_video,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_core->num_v_buffs,(unsigned)(max_frame_delay*3*sh_video->fps)+3); - prev_warn_delay=max_frame_delay; - } -} - -static unsigned compute_frame_dropping(sh_video_t* sh_video,float v_pts,float drop_barrier) { - unsigned rc=0; - float screen_pts=dae_played_frame(xp_core->video).v_pts-(mp_conf.av_sync_pts?0:xp_core->initial_apts); - static float prev_delta=64; - float delta,max_frame_delay;/* delay for decoding of top slow frame */ - max_frame_delay = mp_data->bench->max_video+mp_data->bench->max_vout; - - /* - TODO: - Replace the constants with some values which are depended on - xp_core->num_v_buffs 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-screen_pts; - if(max_frame_delay*3 > drop_barrier) { - if(drop_barrier < (float)(xp_core->num_v_buffs-2)/sh_video->fps) drop_barrier += 1/sh_video->fps; - else - if(mp_conf.verbose) show_warn_cant_sync(sh_video,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(xp_core)%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(xp_core); - idx2 = dae_prev_vdecoded(xp_core); - xmp_frame_t* fra=xp_core->video->frame; - while( dae_curr_vplayed(xp_core) != 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[idx2].duration = fra[idx1].v_pts - fra[idx2].v_pts; - - idx3=(idx2-1)%xp_core->num_v_buffs; - 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(xp_core)) fra[idx1].duration = fra[idx0].v_pts - fra[idx1].v_pts; - - idx0 = idx1; - idx1 = idx2; - idx2=(idx2-1)%xp_core->num_v_buffs; - } -} - -any_t* Va_dec_ahead_routine( any_t* arg ) -{ - mpxp_thread_t* priv=arg; - sh_video_t* sh_video=priv->dae->sh; - demux_stream_t *d_video=sh_video->ds; - - float duration=0; - float drop_barrier; - int blit_frame=0; - int drop_param=0; - unsigned xp_n_frame_to_drop; - float v_pts,mpeg_timer=HUGE; - - 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(); - if(!(xp_core->audio && mp_conf.xp < XP_VAFull)) - priv->name = "video decoder+vf"; - drop_barrier=(float)(xp_core->num_v_buffs/2)*(1/sh_video->fps); - if(mp_conf.av_sync_pts == -1 && !mp_data->use_pts_fix2) - xp_core->bad_pts = d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_ES || - d_video->demuxer->file_format == DEMUXER_TYPE_MPEG4_ES || - d_video->demuxer->file_format == DEMUXER_TYPE_H264_ES || - d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS || - d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS; - else - xp_core->bad_pts = mp_conf.av_sync_pts?0:1; -while(!priv->dae->eof){ - unsigned char* start=NULL; - int in_size; - if(priv->state==Pth_Canceling) break; - if(priv->state==Pth_Sleep) { -pt_sleep: - priv->state=Pth_ASleep; - while(priv->state==Pth_ASleep) usleep(0); - if(xp_core->bad_pts) mpeg_timer=HUGE; - continue; - } - __MP_UNIT(priv->p_idx,"dec_ahead 1"); - -/* get it! */ -#if 0 - /* prevent reent access to non-reent demuxer */ - //if(sh_video->num_frames>200) *((char*)0x100) = 1; // Testing crash - if(xp_core->audio && mp_conf.xp<XP_VAFull) { - __MP_UNIT(priv->p_idx,"decode audio"); - while(2==xp_thread_decode_audio()) ; - __MP_UNIT(priv->p_idx,"dec_ahead 2"); - } -#endif -/*-------------------- Decode a frame: -----------------------*/ - in_size=video_read_frame_r(sh_video,&duration,&v_pts,&start,sh_video->fps); - if(in_size<0) { - dae_decoded_mark_eof(xp_core->video); - priv->dae->eof=1; - break; - } - /* in_size==0: it's or broken stream or demuxer's bug */ - if(in_size==0 && priv->state!=Pth_Canceling) continue; - /* frame was decoded into current decoder_idx */ - if(xp_core->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; - } - /* compute frame dropping */ - xp_n_frame_to_drop=0; - if(mp_conf.frame_dropping) { - int cur_time; - cur_time = GetTimerMS(); - /* Ugly solution: disable frame dropping right after seeking! */ - if(cur_time - mp_data->seek_time > (xp_core->num_v_buffs/sh_video->fps)*100) xp_n_frame_to_drop=compute_frame_dropping(sh_video,v_pts,drop_barrier); - } /* if( mp_conf.frame_dropping ) */ - if(!finite(v_pts)) MSG_WARN("Bug of demuxer! Value of video pts=%f\n",v_pts); -#if 0 -/* - We can't seriously examine question of too slow machines - by motivation reasons -*/ -if(ada_active_frame) /* don't emulate slow systems until xp_players are not started */ -{ - int i,delay; /* sleeping 200 ms is far enough for 25 fps */ - delay=xp_n_frame_to_drop?0:20; - for(i=0;i<delay;i++) usleep(0); -} -#endif - if(xp_n_frame_to_drop) drop_param=mp_conf.frame_dropping; - else drop_param=0; - /* decode: */ - if(mp_data->output_quality) { - unsigned total = xp_core->num_v_buffs/2; - unsigned distance = dae_get_decoder_outrun(xp_core->video); - int our_quality; - our_quality = mp_data->output_quality*distance/total; - if(drop_param) mpcv_set_quality(sh_video,0); - else - if(mp_conf.autoq) mpcv_set_quality(sh_video,our_quality>0?our_quality:0); - } - blit_frame=mpcv_decode(sh_video,start,in_size,drop_param,v_pts); -MSG_DBG2("DECODER: %i[%i] %f\n",dae_curr_vdecoded(xp_core),in_size,v_pts); - if(mp_data->output_quality) { - if(drop_param) mpcv_set_quality(sh_video,mp_data->output_quality); - } - if(!blit_frame && drop_param) priv->dae->num_dropped_frames++; - if(blit_frame) { - unsigned idx=dae_curr_vdecoded(xp_core); - if(xp_core->bad_pts) - xp_core->video->frame[idx].v_pts=mpeg_timer; - else - xp_core->video->frame[idx].v_pts = v_pts; - xp_core->video->frame[idx].duration=duration; - dae_decoded_clear_eof(xp_core->video); - if(!xp_core->bad_pts) { - int _idx = dae_prev_vdecoded(xp_core); - xp_core->video->frame[_idx].duration=v_pts-xp_core->video->frame[_idx].v_pts; - } - if(mp_conf.frame_reorder) reorder_pts_in_mpeg(); - } /* if (blit_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(priv->state==Pth_Canceling) goto pt_exit; - if(priv->state==Pth_Sleep) goto pt_sleep; - if(xp_core->audio && mp_conf.xp<XP_VAFull) { - __MP_UNIT(priv->p_idx,"decode audio"); - xp_thread_decode_audio(); - __MP_UNIT(priv->p_idx,"dec_ahead 5"); - } - usleep(1); - } -/*------------------------ frame decoded. --------------------*/ -} /* while(!priv->dae->eof)*/ - -if(xp_core->audio && mp_conf.xp<XP_VAFull) { - while(!xp_core->audio->eof && priv->state!=Pth_Canceling && priv->state!=Pth_Sleep) { - __MP_UNIT(priv->p_idx,"decode audio"); - if(!xp_thread_decode_audio()) usleep(1); - __MP_UNIT(priv->p_idx,NULL); - } -} - pt_exit: - MSG_T("\nDEC_AHEAD: leaving...\n"); - priv->state=Pth_Stand; - return arg; /* terminate thread here !!! */ -} - -/* this routine decodes audio only */ -any_t* a_dec_ahead_routine( any_t* arg ) -{ - mpxp_thread_... [truncated message content] |