# HG changeset patch # User arpi_esp # Date 989465994 0 # Node ID cd1f0d4de0b8e4b220f2a08a2d1ab9f6417adbee # Parent c653430f078932cc676ce53047d880476e2e7f2c new audio playback and A-V sync code diff -r c653430f0789 -r cd1f0d4de0b8 DOCS/codecs.conf --- a/DOCS/codecs.conf Wed May 09 23:41:01 2001 +0000 +++ b/DOCS/codecs.conf Thu May 10 03:39:54 2001 +0000 @@ -88,12 +88,12 @@ videocodec indeo4 info "Intel Indeo 4.1" - status buggy - comment "upside-down" + status working +; comment "upside-down" fourcc IV41,iv41 driver vfw dll "ir41_32.dll" - out BGR24,BGR15 flip + out BGR24,BGR15 videocodec indeo3 info "Intel Indeo 3.1/3.2" diff -r c653430f0789 -r cd1f0d4de0b8 TOOLS/audio-block2.c --- a/TOOLS/audio-block2.c Wed May 09 23:41:01 2001 +0000 +++ b/TOOLS/audio-block2.c Thu May 10 03:39:54 2001 +0000 @@ -50,16 +50,18 @@ } // ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); -// print_info(audio_fd); - ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); +// ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); r=AFMT_S16_LE;ioctl (audio_fd, SNDCTL_DSP_SETFMT, &r); r=1; ioctl (audio_fd, SNDCTL_DSP_STEREO, &r); r=44100; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1) printf("audio_setup: your card doesn't support %d Hz samplerate\n",r); -// print_info(audio_fd); + r=0; ioctl (audio_fd, SNDCTL_DSP_GETBLKSIZE, &r); + printf("fragment size = %d\n",r); + + print_info(audio_fd); t0=t1=GetTimer(); diff -r c653430f0789 -r cd1f0d4de0b8 configure --- a/configure Wed May 09 23:41:01 2001 +0000 +++ b/configure Thu May 10 03:39:54 2001 +0000 @@ -1058,6 +1058,7 @@ #define XMMP_AUDIO_DRIVER PLUGINDIR "/Sound/oss.so" /* set up audio OUTBURST. Do not change this! */ +#define MAX_OUTBURST 32768 #ifdef USE_XMMP_AUDIO #define OUTBURST 4096 #else diff -r c653430f0789 -r cd1f0d4de0b8 dec_audio.c --- a/dec_audio.c Wed May 09 23:41:01 2001 +0000 +++ b/dec_audio.c Thu May 10 03:39:54 2001 +0000 @@ -52,16 +52,19 @@ sh_audio->samplerate=0; //sh_audio->pcm_bswap=0; -sh_audio->a_buffer_size=16384; // default size, maybe not enough for Win32/ACM +sh_audio->a_buffer_size=2*MAX_OUTBURST; // default size, maybe not enough for Win32/ACM sh_audio->a_buffer=NULL; +sh_audio->a_in_buffer_len=0; + if(driver==4){ // Win32 ACM audio codec: if(init_acm_audio_codec(sh_audio)){ + sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; sh_audio->channels=sh_audio->o_wf.nChannels; sh_audio->samplerate=sh_audio->o_wf.nSamplesPerSec; - if(sh_audio->a_buffer_sizeaudio_out_minsize+OUTBURST) - sh_audio->a_buffer_size=sh_audio->audio_out_minsize+OUTBURST; + if(sh_audio->a_buffer_sizeaudio_out_minsize+MAX_OUTBURST) + sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST; } else { printf("Could not load/initialize Win32/ACM AUDIO codec (missing DLL file?)\n"); driver=0; @@ -80,6 +83,7 @@ printf("ERROR: Could not load/initialize Win32/DirctShow AUDIO codec: %s\n",sh_audio->codec->dll); driver=0; } else { + sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->audio_in_minsize=2*sh_audio->wf->nBlockAlign; @@ -111,6 +115,7 @@ case 2: { // AVI PCM Audio: WAVEFORMATEX *h=sh_audio->wf; + sh_audio->i_bps=h->nAvgBytesPerSec; sh_audio->channels=h->nChannels; sh_audio->samplerate=h->nSamplesPerSec; sh_audio->samplesize=(h->wBitsPerSample+7)/8; @@ -120,6 +125,7 @@ // DVD PCM Audio: sh_audio->channels=2; sh_audio->samplerate=48000; + sh_audio->i_bps=2*2*48000; // sh_audio->pcm_bswap=1; break; } @@ -138,8 +144,12 @@ ac3_init(); sh_audio->ac3_frame = ac3_decode_frame(); if(sh_audio->ac3_frame){ - sh_audio->samplerate=((ac3_frame_t*)sh_audio->ac3_frame)->sampling_rate; + ac3_frame_t* fr=(ac3_frame_t*)sh_audio->ac3_frame; + sh_audio->samplerate=fr->sampling_rate; sh_audio->channels=2; + // 1 frame: 6*256 samples 1 sec: sh_audio->samplerate samples + //sh_audio->i_bps=fr->frame_size*fr->sampling_rate/(6*256); + sh_audio->i_bps=fr->bit_rate*(1000/8); } else { driver=0; // bad frame -> disable audio } @@ -150,6 +160,7 @@ Gen_aLaw_2_Signed(); // init table sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; + sh_audio->i_bps=sh_audio->channels*sh_audio->samplerate; break; } case 6: { @@ -157,6 +168,10 @@ GSM_Init(); sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; + // decodes 65 byte -> 320 short + // 1 sec: sh_audio->channels*sh_audio->samplerate samples + // 1 frame: 320 samples + sh_audio->i_bps=65*(sh_audio->channels*sh_audio->samplerate)/320; // 1:10 break; } case 1: { @@ -172,6 +187,7 @@ // printf("]\n"); sh_audio->channels=2; // hack sh_audio->samplerate=MP3_samplerate; + sh_audio->i_bps=MP3_bitrate*(1000/8); break; } } @@ -191,9 +207,12 @@ return driver; } -// Audio decoding +// Audio decoding: -int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){ +// Decode a single frame (mp3,acm etc) or 'minlen' bytes (pcm/alaw etc) +// buffer length is 'maxlen' bytes, it shouldn't be exceeded... + +int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){ int len=-1; switch(sh_audio->codec->driver){ case 1: // MPEG layer 2 or 3 @@ -201,13 +220,14 @@ sh_audio->channels=2; // hack break; case 2: // AVI PCM - { len=demux_read_data(sh_audio->ds,buf,OUTBURST); + { len=demux_read_data(sh_audio->ds,buf,minlen); break; } case 8: // DVD PCM { int j; - len=demux_read_data(sh_audio->ds,buf,OUTBURST); + len=demux_read_data(sh_audio->ds,buf,minlen); //if(i&1){ printf("Warning! pcm_audio_size&1 !=0 (%d)\n",i);i&=~1; } + // swap endian: for(j=0;jds,buf,OUTBURST/2); + { int l=demux_read_data(sh_audio->ds,buf,minlen/2); unsigned short *d=(unsigned short *) buf; unsigned char *s=buf; len=2*l; @@ -228,13 +248,10 @@ } case 6: // MS-GSM decoder { unsigned char buf[65]; // 65 bytes / frame - len=0; - while(lends,buf,65)!=65) break; // EOF - XA_MSGSM_Decoder(buf,(unsigned short *) buf); // decodes 65 byte -> 320 short -// XA_GSM_Decoder(buf,(unsigned short *) &sh_audio->a_buffer[sh_audio->a_buffer_len]); // decodes 33 byte -> 160 short - len+=2*320; - } + if(demux_read_data(sh_audio->ds,buf,65)!=65) break; // EOF + XA_MSGSM_Decoder(buf,(unsigned short *) buf); // decodes 65 byte -> 320 short +// XA_GSM_Decoder(buf,(unsigned short *) &sh_audio->a_buffer[sh_audio->a_buffer_len]); // decodes 33 byte -> 160 short + len=2*320; break; } case 3: // AC3 decoder @@ -249,9 +266,10 @@ //printf("{3:%d}",avi_header.idx_pos);fflush(stdout); break; case 4: - { len=acm_decode_audio(sh_audio,buf,maxlen); + len=acm_decode_audio(sh_audio,buf,maxlen); +// len=acm_decode_audio(sh_audio,buf,minlen); break; - } + #ifdef USE_DIRECTSHOW case 7: // DirectShow { int ret; @@ -267,7 +285,8 @@ } DS_AudioDecoder_Convert(sh_audio->a_in_buffer,sh_audio->a_in_buffer_len, buf,maxlen, &size_in,&size_out); - if(verbose>2)printf("DShow: audio %d -> %d converted (in_buf_len=%d of %d)\n",size_in,size_out,sh_audio->a_in_buffer_len,sh_audio->a_in_buffer_size); + //if(verbose>2) + printf("DShow: audio %d -> %d converted (in_buf_len=%d of %d) %d\n",size_in,size_out,sh_audio->a_in_buffer_len,sh_audio->a_in_buffer_size,ds_tell_pts(sh_audio->ds)); if(size_in>=sh_audio->a_in_buffer_len){ sh_audio->a_in_buffer_len=0; } else { diff -r c653430f0789 -r cd1f0d4de0b8 demuxer.c --- a/demuxer.c Wed May 09 23:41:01 2001 +0000 +++ b/demuxer.c Thu May 10 03:39:54 2001 +0000 @@ -13,6 +13,7 @@ ds->buffer_pos=ds->buffer_size=0; ds->buffer=NULL; ds->pts=0; + ds->pts_bytes=0; ds->eof=0; ds->pos=0; ds->dpos=0; @@ -120,7 +121,11 @@ ds->buffer_size=p->len; ds->pos=p->pos; ds->dpos+=p->len; // !!! - ds->pts=p->pts; + if(p->pts){ + ds->pts=p->pts; + ds->pts_bytes=0; + } + ds->pts_bytes+=p->len; // !!! // free packet: ds->bytes-=p->len; ds->first=p->next; @@ -164,6 +169,24 @@ return bytes; } +int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len){ +int x; +int bytes=0; +while(len>0){ + x=ds->buffer_size-ds->buffer_pos; + if(x==0){ + if(!ds_fill_buffer(ds)) return bytes; + } else { + if(x>len) x=len; + if(mem) memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x); + bytes+=x;len-=x;ds->buffer_pos+=x; + return bytes; // stop at end of package! (for correct timestamping) + } +} +return bytes; +} + + void ds_free_packs(demux_stream_t *ds){ demux_packet_t *dp=ds->first; while(dp){ diff -r c653430f0789 -r cd1f0d4de0b8 demuxer.h --- a/demuxer.h Wed May 09 23:41:01 2001 +0000 +++ b/demuxer.h Thu May 10 03:39:54 2001 +0000 @@ -29,6 +29,7 @@ int buffer_size; // current buffer size unsigned char* buffer; // current buffer float pts; // current buffer's pts + int pts_bytes; // number of bytes read after last pts stamp int eof; // end of demuxed stream? (true if all buffer empty) int pos; // position in the input stream (file) int dpos; // position in the demuxed stream @@ -106,7 +107,12 @@ return (ds->dpos-ds->buffer_size)+ds->buffer_pos; } +inline static int ds_tell_pts(demux_stream_t *ds){ + return (ds->pts_bytes-ds->buffer_size)+ds->buffer_pos; +} + int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len); +int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len); #if 1 #define demux_getc(ds) (\ diff -r c653430f0789 -r cd1f0d4de0b8 dll_init.c --- a/dll_init.c Wed May 09 23:41:01 2001 +0000 +++ b/dll_init.c Thu May 10 03:39:54 2001 +0000 @@ -60,11 +60,12 @@ if(verbose) printf("Audio codec opened OK! ;-)\n"); acmStreamSize(sh_audio->srcstream, in_fmt->nBlockAlign, &srcsize, ACM_STREAMSIZEF_SOURCE); - if(srcsizeaudio_out_minsize=srcsize; // audio output min. size if(verbose) printf("Audio ACM output buffer min. size: %ld\n",srcsize); - acmStreamSize(sh_audio->srcstream, 2*srcsize, &srcsize, ACM_STREAMSIZEF_DESTINATION); + acmStreamSize(sh_audio->srcstream, srcsize, &srcsize, ACM_STREAMSIZEF_DESTINATION); sh_audio->audio_in_minsize=srcsize; // audio input min. size if(verbose) printf("Audio ACM input buffer min. size: %ld\n",srcsize); @@ -106,11 +107,12 @@ } hr=acmStreamConvert(sh_audio->srcstream,&ash,0); if(hr){ - printf("ACM_Decoder: acmStreamConvert error %d\n",(int)hr); + if(verbose>=2) printf("ACM_Decoder: acmStreamConvert error %d\n",(int)hr); // return -1; } - if(verbose>=3) printf("acm converted %d -> %d\n",ash.cbSrcLengthUsed,ash.cbDstLengthUsed); + //if(verbose>=3) + printf("acm converted %d -> %d\n",ash.cbSrcLengthUsed,ash.cbDstLengthUsed); if(ash.cbSrcLengthUsed>=sh_audio->a_in_buffer_len){ sh_audio->a_in_buffer_len=0; } else { @@ -138,8 +140,8 @@ sh_video->o_bih.biSize = sizeof(BITMAPINFOHEADER); win32_codec_name = sh_video->codec->dll; - sh_video->hic = ICOpen( 0x63646976, sh_video->bih->biCompression, ICMODE_FASTDECOMPRESS); -// sh_video->hic = ICOpen( 0x63646976, sh_video->bih.biCompression, ICMODE_DECOMPRESS); +// sh_video->hic = ICOpen( 0x63646976, sh_video->bih->biCompression, ICMODE_FASTDECOMPRESS); + sh_video->hic = ICOpen( 0x63646976, sh_video->bih->biCompression, ICMODE_DECOMPRESS); if(!sh_video->hic){ printf("ICOpen failed! unknown codec / wrong parameters?\n"); return 0; @@ -260,19 +262,6 @@ return 0; } -#if 0 - -//sh_video->hic -//ICSendMessage(HIC hic,unsigned int msg,long lParam1,long lParam2) -{ int i; - for(i=73;i<256;i++){ - printf("Calling ICM_USER+%d function...",i);fflush(stdout); - ret = ICSendMessage(sh_video->hic,ICM_USER+i,NULL,NULL); - printf(" ret=%d\n",ret); - } -} -#endif - sh_video->our_out_buffer = shmem_alloc(sh_video->o_bih.biSizeImage); if(!sh_video->our_out_buffer){ printf("not enough memory for decoded picture buffer (%ld bytes)\n", sh_video->o_bih.biSizeImage); diff -r c653430f0789 -r cd1f0d4de0b8 mplayer.c --- a/mplayer.c Wed May 09 23:41:01 2001 +0000 +++ b/mplayer.c Thu May 10 03:39:54 2001 +0000 @@ -27,7 +27,7 @@ #include "version.h" #include "config.h" -#ifndef OUTBURST +#ifndef MAX_OUTBURST #error "=============================================" #error "Please re-run ./configure and then try again!" #error "=============================================" @@ -254,7 +254,6 @@ return len; } - //#include "dec_audio.c" //**************************************************************************// @@ -304,6 +303,31 @@ } } #endif + +//**************************************************************************// + +int audio_delay_method=2; +int audio_buffer_size=-1; + +int get_audio_delay(int audio_fd){ + if(audio_delay_method==2){ + // + int r=0; + if(ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &r)!=-1) + return r; + audio_delay_method=1; // fallback if not supported + } + if(audio_delay_method==1){ + // SNDCTL_DSP_GETOSPACE + audio_buf_info zz; + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1) + return audio_buffer_size-zz.bytes; + audio_delay_method=0; // fallback if not supported + } + return audio_buffer_size; +} + + //**************************************************************************// // AVI file header reader/parser/writer: @@ -401,7 +425,7 @@ extern void mpeg2_allocate_image_buffers(picture_t * picture); extern void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height); extern int vo_init(void); -extern int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen); +extern int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen); char* filename=NULL; //"MI2-Trailer.avi"; int i; @@ -424,7 +448,6 @@ #else int alsa=0; #endif -int audio_buffer_size=-1; int audio_id=-1; int video_id=-1; int dvdsub_id=-1; @@ -1031,7 +1054,8 @@ printf("Couldn't initialize audio codec! -> nosound\n"); has_audio=0; } else { - printf("AUDIO: samplerate=%d channels=%d bps=%d\n",sh_audio->samplerate,sh_audio->channels,sh_audio->samplesize); + printf("AUDIO: samplerate=%d channels=%d bps=%d ratio: %d->%d\n",sh_audio->samplerate,sh_audio->channels,sh_audio->samplesize, + sh_audio->i_bps,sh_audio->o_bps); } } @@ -1282,7 +1306,10 @@ //================== MAIN: ========================== { int audio_fd=-1; -float buffer_delay=0; +int outburst=OUTBURST; +float audio_buffer_delay=0; + +//float buffer_delay=0; float frame_correction=0; // A-V timestamp kulonbseg atlagolas int frame_corr_num=0; // float a_frame=0; // Audio @@ -1362,24 +1389,38 @@ #ifdef USE_XMMP_AUDIO if(audio_buffer_size==-1){ // Measuring buffer size: - buffer_delay=pSound->QueryDelay(pSound, 0); + audio_buffer_delay=pSound->QueryDelay(pSound, 0); } else { // -abs commandline option - buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps); + audio_buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps); } #else int r; + audio_buf_info zz; + r=(sh_audio->samplesize==2)?AFMT_S16_LE:AFMT_U8;ioctl (audio_fd, SNDCTL_DSP_SETFMT, &r); r=sh_audio->channels-1; ioctl (audio_fd, SNDCTL_DSP_STEREO, &r); - r=sh_audio->samplerate; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1) - printf("audio_setup: your card doesn't support %d Hz samplerate\n",r); + r=sh_audio->samplerate; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1){ + printf("audio_setup: your card doesn't support %d Hz samplerate => nosound\n",r); + has_audio=0; + } else + printf("audio_setup: using %d Hz samplerate (requested: %d)\n",r,sh_audio->samplerate); -#if 0 -// r = (64 << 16) + 1024; - r = (65536 << 16) + 512; - if(ioctl (audio_fd, SNDCTL_DSP_SETFRAGMENT, &r)==-1) - printf("audio_setup: your card doesn't support setting fragments\n",r); -#endif + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){ + printf("audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n"); + r=0; + if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r)==-1){ + printf("audio_setup: %d bytes/frag (config.h)\n",outburst); + } else { + outburst=r; + printf("audio_setup: %d bytes/frag (GETBLKSIZE)\n",outburst); + } + } else { + printf("audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n", + zz.fragments, zz.fragstotal, zz.fragsize, zz.bytes); + if(audio_buffer_size==-1) audio_buffer_size=zz.bytes; + outburst=zz.fragsize; + } if(audio_buffer_size==-1){ // Measuring buffer size: @@ -1391,8 +1432,8 @@ FD_ZERO(&rfds); FD_SET(audio_fd,&rfds); tv.tv_sec=0; tv.tv_usec = 0; if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break; - write(audio_fd,&sh_audio->a_buffer[sh_audio->a_buffer_len],OUTBURST); - audio_buffer_size+=OUTBURST; + write(audio_fd,&sh_audio->a_buffer[sh_audio->a_buffer_len],outburst); + audio_buffer_size+=outburst; } if(audio_buffer_size==0){ printf("\n *** Your audio driver DOES NOT support select() ***\n"); @@ -1401,10 +1442,12 @@ } #endif } - buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps); + audio_buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps); #endif - a_frame=-(buffer_delay); - printf("Audio buffer size: %d bytes, delay: %5.3fs\n",audio_buffer_size,buffer_delay); + printf("Audio buffer size: %d bytes, delay: %5.3fs\n",audio_buffer_size,audio_buffer_delay); + +// a_frame=-(audio_buffer_delay); + a_frame=0; // RESET_AUDIO(audio_fd); } @@ -1428,13 +1471,13 @@ //==================== START PLAYING ======================= if(file_format==DEMUXER_TYPE_AVI){ - a_pts=d_audio->pts-(buffer_delay+audio_delay); + a_pts=d_audio->pts; audio_delay-=(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)*sh_video->frametime; // audio_delay-=(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)/default_fps; if(verbose){ printf("AVI Initial frame delay: %5.3f\n",(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)*sh_video->frametime); printf("v: audio_delay=%5.3f buffer_delay=%5.3f a_pts=%5.3f a_frame=%5.3f\n", - audio_delay,buffer_delay,a_pts,a_frame); + audio_delay,audio_buffer_delay,a_pts,a_frame); printf("START: a_pts=%5.3f v_pts=%5.3f \n",d_audio->pts,d_video->pts); } delay_corrected=0; // has to correct PTS diffs @@ -1452,39 +1495,69 @@ while(!eof){ /*========================== PLAY AUDIO ============================*/ +if(!has_audio){ + int playsize=512; + a_frame+=playsize/(float)(sh_audio->o_bps); + a_pts+=playsize/(float)(sh_audio->o_bps); + //time_frame+=playsize/(float)(sh_audio->o_bps); +} else while(has_audio){ + unsigned int t; + int playsize=outburst; + audio_buf_info zz; + int use_select=1; + + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1){ + // calculate exact buffer space: + playsize=zz.fragments*zz.fragsize; + if(!playsize) break; // buffer is full, do not block here!!! + use_select=0; + } + + if(playsize>MAX_OUTBURST) playsize=MAX_OUTBURST; // we shouldn't exceed it! + //if(playsize>outburst) playsize=outburst; // Update buffer if needed - unsigned int t=GetTimer(); + t=GetTimer(); current_module="decode_audio"; // Enter AUDIO decoder module - //sh_audio->codec->driver=has_audio; // FIXME! - while(sh_audio->a_buffer_leneof){ - int ret=decode_audio(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len],sh_audio->a_buffer_size-sh_audio->a_buffer_len); + while(sh_audio->a_buffer_leneof){ + int ret=decode_audio(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); if(ret>0) sh_audio->a_buffer_len+=ret; else break; } current_module=NULL; // Leave AUDIO decoder module t=GetTimer()-t;audio_time_usage+=t*0.000001; - + + if(playsize>sh_audio->a_buffer_len) playsize=sh_audio->a_buffer_len; + playsize/=outburst; playsize*=outburst; // rounding to fragment boundary + +// printf("play %d bytes of %d [max: %d]\n",playsize,sh_audio->a_buffer_len,sh_audio->a_buffer_size); // Play sound from the buffer: - if(sh_audio->a_buffer_len>=OUTBURST){ // if not EOF + if(playsize>0){ // if not EOF #ifdef USE_XMMP_AUDIO - pSound->Write( pSound, sh_audio->a_buffer, OUTBURST ); + pSound->Write( pSound, sh_audio->a_buffer, playsize ); #else #ifdef SIMULATE_ALSA - fake_ALSA_write(audio_fd,sh_audio->a_buffer,OUTBURST); // for testing purposes + fake_ALSA_write(audio_fd,sh_audio->a_buffer,playsize); // for testing purposes #else - write(audio_fd,sh_audio->a_buffer,OUTBURST); + playsize=write(audio_fd,sh_audio->a_buffer,playsize); #endif #endif - sh_audio->a_buffer_len-=OUTBURST; - memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[OUTBURST],sh_audio->a_buffer_len); + if(playsize>0){ + sh_audio->a_buffer_len-=playsize; + memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[playsize],sh_audio->a_buffer_len); + a_frame+=playsize/(float)(sh_audio->o_bps); + //a_pts+=playsize/(float)(sh_audio->o_bps); +// time_frame+=playsize/(float)(sh_audio->o_bps); + } #ifndef USE_XMMP_AUDIO #ifndef SIMULATE_ALSA // check buffer #ifdef HAVE_AUDIO_SELECT - { fd_set rfds; + if(use_select){ // do not use this code if SNDCTL_DSP_GETOSPACE works + fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(audio_fd, &rfds); @@ -1492,7 +1565,7 @@ tv.tv_usec = 0; if(select(audio_fd+1, NULL, &rfds, NULL, &tv)){ a_frame+=OUTBURST/(float)(sh_audio->o_bps); - a_pts+=OUTBURST/(float)(sh_audio->o_bps); +// a_pts+=OUTBURST/(float)(sh_audio->o_bps); // printf("Filling audio buffer...\n"); continue; // } else { @@ -1508,13 +1581,9 @@ } // if(has_audio) /*========================== UPDATE TIMERS ============================*/ - - a_frame+=OUTBURST/(float)(sh_audio->o_bps); - a_pts+=OUTBURST/(float)(sh_audio->o_bps); - +#if 0 if(alsa){ // Use system timer for sync, not audio card/driver - time_frame+=OUTBURST/(float)(sh_audio->o_bps); time_frame-=GetRelativeTime(); if(time_frame<-0.1 || time_frame>0.1){ time_frame=0; @@ -1529,19 +1598,19 @@ } } } - +#endif /*========================== PLAY VIDEO ============================*/ if(1) - while(v_framepts; current_module="decode_video"; - if(!force_redraw && v_frame+0.1o_bps; + } else { + if(time_frame<-0.1 || time_frame>0.1) time_frame=0; + } + + if(verbose)printf("sleep: %5.3f a:%6.3f v:%6.3f \n",stime,a_frame,v_frame); + + while(time_frame>0.005){ + if(time_frame<=0.020) + usleep(0); // sleep 10ms + else + usleep(1000000*(time_frame-0.002)); + time_frame-=GetRelativeTime(); + } if(!drop_frame){ current_module="flip_page"; @@ -1726,6 +1818,7 @@ if(force_redraw){ --force_redraw; if(!force_redraw) osd_function=OSD_PLAY; + continue; } // printf("A:%6.1f V:%6.1f A-V:%7.3f frame=%5.2f \r",d_audio->pts,d_video->pts,d_audio->pts-d_video->pts,a_frame); @@ -1734,34 +1827,45 @@ #if 1 /*================ A-V TIMESTAMP CORRECTION: =========================*/ if(has_audio){ + // unplayed bytes in our and soundcard/dma buffer: + int delay_bytes=get_audio_delay(audio_fd)+sh_audio->a_buffer_len; + float delay=(float)delay_bytes/(float)sh_audio->o_bps; + if(pts_from_bps && (file_format==DEMUXER_TYPE_AVI)){ // a_pts=(float)ds_tell(d_audio)/sh_audio->wf.nAvgBytesPerSec-(buffer_delay+audio_delay); - a_pts=(float)ds_tell(d_audio)/sh_audio->wf->nAvgBytesPerSec-(buffer_delay); + a_pts=(float)ds_tell(d_audio)/sh_audio->wf->nAvgBytesPerSec; delay_corrected=1; // hack } else if(d_audio->pts){ // printf("\n=== APTS a_pts=%5.3f v_pts=%5.3f === \n",d_audio->pts,d_video->pts); #if 1 if(!delay_corrected){ - float x=d_audio->pts-d_video->pts-(buffer_delay+audio_delay); - float y=-(buffer_delay+audio_delay); + float x=d_audio->pts-d_video->pts-(delay+audio_delay); + float y=-(delay+audio_delay); printf("Initial PTS delay: %5.3f sec (calculated: %5.3f)\n",x,y); audio_delay+=x; //a_pts-=x; delay_corrected=1; if(verbose) printf("v: audio_delay=%5.3f buffer_delay=%5.3f a.pts=%5.3f v.pts=%5.3f\n", - audio_delay,buffer_delay,d_audio->pts,d_video->pts); + audio_delay,delay,d_audio->pts,d_video->pts); } #endif - a_pts=d_audio->pts-(buffer_delay+audio_delay); - d_audio->pts=0; +// a_pts=(ds_tell_pts(d_audio)+sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; +// printf("a_pts+=%6.3f \n",a_pts); +// a_pts=d_audio->pts-a_pts; + + a_pts=d_audio->pts; + a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + + //a_pts=d_audio->pts; d_audio->pts=0; } if(d_video->pts) v_pts=d_video->pts; if(frame_corr_num==5){ float x=(frame_correction/5.0f); if(delay_corrected){ - printf("A:%6.1f V:%6.1f A-V:%7.3f",a_pts,v_pts,x); +// printf("A:%6.1f V:%6.1f A-V:%7.3f",a_pts-audio_delay-delay,v_pts,x); + printf("A:%6.1f (%6.1f) V:%6.1f A-V:%7.3f",a_pts,a_pts-audio_delay-delay,v_pts,x); x*=0.5f; if(x<-max_pts_correction) x=-max_pts_correction; else if(x> max_pts_correction) x= max_pts_correction; @@ -1779,7 +1883,7 @@ } frame_corr_num=0; frame_correction=0; } - if(frame_corr_num>=0) frame_correction+=a_pts-v_pts; + if(frame_corr_num>=0) frame_correction+=(a_pts-delay-audio_delay)-v_pts; } else { // No audio: if(d_video->pts) v_pts=d_video->pts; @@ -1825,6 +1929,8 @@ #endif } + + if(!force_redraw) break; } // while(v_frame