1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-07 10:02:50 +00:00

new audio playback and A-V sync code

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@747 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi_esp 2001-05-10 03:39:54 +00:00
parent c92a2dfa97
commit dda6708094
9 changed files with 249 additions and 102 deletions

View File

@ -88,12 +88,12 @@ videocodec indeo5
videocodec indeo4 videocodec indeo4
info "Intel Indeo 4.1" info "Intel Indeo 4.1"
status buggy status working
comment "upside-down" ; comment "upside-down"
fourcc IV41,iv41 fourcc IV41,iv41
driver vfw driver vfw
dll "ir41_32.dll" dll "ir41_32.dll"
out BGR24,BGR15 flip out BGR24,BGR15
videocodec indeo3 videocodec indeo3
info "Intel Indeo 3.1/3.2" info "Intel Indeo 3.1/3.2"

View File

@ -50,16 +50,18 @@ int main(){
} }
// ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); // 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=AFMT_S16_LE;ioctl (audio_fd, SNDCTL_DSP_SETFMT, &r);
r=1; ioctl (audio_fd, SNDCTL_DSP_STEREO, &r); r=1; ioctl (audio_fd, SNDCTL_DSP_STEREO, &r);
r=44100; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1) r=44100; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1)
printf("audio_setup: your card doesn't support %d Hz samplerate\n",r); 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(); t0=t1=GetTimer();

1
configure vendored
View File

@ -1058,6 +1058,7 @@ $_xmmpaudio
#define XMMP_AUDIO_DRIVER PLUGINDIR "/Sound/oss.so" #define XMMP_AUDIO_DRIVER PLUGINDIR "/Sound/oss.so"
/* set up audio OUTBURST. Do not change this! */ /* set up audio OUTBURST. Do not change this! */
#define MAX_OUTBURST 32768
#ifdef USE_XMMP_AUDIO #ifdef USE_XMMP_AUDIO
#define OUTBURST 4096 #define OUTBURST 4096
#else #else

View File

@ -52,16 +52,19 @@ sh_audio->samplesize=2;
sh_audio->samplerate=0; sh_audio->samplerate=0;
//sh_audio->pcm_bswap=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_buffer=NULL;
sh_audio->a_in_buffer_len=0;
if(driver==4){ if(driver==4){
// Win32 ACM audio codec: // Win32 ACM audio codec:
if(init_acm_audio_codec(sh_audio)){ 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->channels=sh_audio->o_wf.nChannels;
sh_audio->samplerate=sh_audio->o_wf.nSamplesPerSec; sh_audio->samplerate=sh_audio->o_wf.nSamplesPerSec;
if(sh_audio->a_buffer_size<sh_audio->audio_out_minsize+OUTBURST) if(sh_audio->a_buffer_size<sh_audio->audio_out_minsize+MAX_OUTBURST)
sh_audio->a_buffer_size=sh_audio->audio_out_minsize+OUTBURST; sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST;
} else { } else {
printf("Could not load/initialize Win32/ACM AUDIO codec (missing DLL file?)\n"); printf("Could not load/initialize Win32/ACM AUDIO codec (missing DLL file?)\n");
driver=0; driver=0;
@ -80,6 +83,7 @@ if(driver==7){
printf("ERROR: Could not load/initialize Win32/DirctShow AUDIO codec: %s\n",sh_audio->codec->dll); printf("ERROR: Could not load/initialize Win32/DirctShow AUDIO codec: %s\n",sh_audio->codec->dll);
driver=0; driver=0;
} else { } else {
sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;
sh_audio->channels=sh_audio->wf->nChannels; sh_audio->channels=sh_audio->wf->nChannels;
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
sh_audio->audio_in_minsize=2*sh_audio->wf->nBlockAlign; sh_audio->audio_in_minsize=2*sh_audio->wf->nBlockAlign;
@ -111,6 +115,7 @@ case 4: {
case 2: { case 2: {
// AVI PCM Audio: // AVI PCM Audio:
WAVEFORMATEX *h=sh_audio->wf; WAVEFORMATEX *h=sh_audio->wf;
sh_audio->i_bps=h->nAvgBytesPerSec;
sh_audio->channels=h->nChannels; sh_audio->channels=h->nChannels;
sh_audio->samplerate=h->nSamplesPerSec; sh_audio->samplerate=h->nSamplesPerSec;
sh_audio->samplesize=(h->wBitsPerSample+7)/8; sh_audio->samplesize=(h->wBitsPerSample+7)/8;
@ -120,6 +125,7 @@ case 8: {
// DVD PCM Audio: // DVD PCM Audio:
sh_audio->channels=2; sh_audio->channels=2;
sh_audio->samplerate=48000; sh_audio->samplerate=48000;
sh_audio->i_bps=2*2*48000;
// sh_audio->pcm_bswap=1; // sh_audio->pcm_bswap=1;
break; break;
} }
@ -138,8 +144,12 @@ case 3: {
ac3_init(); ac3_init();
sh_audio->ac3_frame = ac3_decode_frame(); sh_audio->ac3_frame = ac3_decode_frame();
if(sh_audio->ac3_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; 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 { } else {
driver=0; // bad frame -> disable audio driver=0; // bad frame -> disable audio
} }
@ -150,6 +160,7 @@ case 5: {
Gen_aLaw_2_Signed(); // init table Gen_aLaw_2_Signed(); // init table
sh_audio->channels=sh_audio->wf->nChannels; sh_audio->channels=sh_audio->wf->nChannels;
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
sh_audio->i_bps=sh_audio->channels*sh_audio->samplerate;
break; break;
} }
case 6: { case 6: {
@ -157,6 +168,10 @@ case 6: {
GSM_Init(); GSM_Init();
sh_audio->channels=sh_audio->wf->nChannels; sh_audio->channels=sh_audio->wf->nChannels;
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; 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; break;
} }
case 1: { case 1: {
@ -172,6 +187,7 @@ case 1: {
// printf("]\n"); // printf("]\n");
sh_audio->channels=2; // hack sh_audio->channels=2; // hack
sh_audio->samplerate=MP3_samplerate; sh_audio->samplerate=MP3_samplerate;
sh_audio->i_bps=MP3_bitrate*(1000/8);
break; break;
} }
} }
@ -191,9 +207,12 @@ if(!sh_audio->channels || !sh_audio->samplerate){
return driver; 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; int len=-1;
switch(sh_audio->codec->driver){ switch(sh_audio->codec->driver){
case 1: // MPEG layer 2 or 3 case 1: // MPEG layer 2 or 3
@ -201,13 +220,14 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){
sh_audio->channels=2; // hack sh_audio->channels=2; // hack
break; break;
case 2: // AVI PCM case 2: // AVI PCM
{ len=demux_read_data(sh_audio->ds,buf,OUTBURST); { len=demux_read_data(sh_audio->ds,buf,minlen);
break; break;
} }
case 8: // DVD PCM case 8: // DVD PCM
{ int j; { 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; } //if(i&1){ printf("Warning! pcm_audio_size&1 !=0 (%d)\n",i);i&=~1; }
// swap endian:
for(j=0;j<len;j+=2){ for(j=0;j<len;j+=2){
char x=buf[j]; char x=buf[j];
buf[j]=buf[j+1]; buf[j]=buf[j+1];
@ -216,7 +236,7 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){
break; break;
} }
case 5: // aLaw decoder case 5: // aLaw decoder
{ int l=demux_read_data(sh_audio->ds,buf,OUTBURST/2); { int l=demux_read_data(sh_audio->ds,buf,minlen/2);
unsigned short *d=(unsigned short *) buf; unsigned short *d=(unsigned short *) buf;
unsigned char *s=buf; unsigned char *s=buf;
len=2*l; len=2*l;
@ -228,13 +248,10 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){
} }
case 6: // MS-GSM decoder case 6: // MS-GSM decoder
{ unsigned char buf[65]; // 65 bytes / frame { unsigned char buf[65]; // 65 bytes / frame
len=0; if(demux_read_data(sh_audio->ds,buf,65)!=65) break; // EOF
while(len<OUTBURST){ XA_MSGSM_Decoder(buf,(unsigned short *) buf); // decodes 65 byte -> 320 short
if(demux_read_data(sh_audio->ds,buf,65)!=65) break; // EOF // XA_GSM_Decoder(buf,(unsigned short *) &sh_audio->a_buffer[sh_audio->a_buffer_len]); // decodes 33 byte -> 160 short
XA_MSGSM_Decoder(buf,(unsigned short *) buf); // decodes 65 byte -> 320 short len=2*320;
// XA_GSM_Decoder(buf,(unsigned short *) &sh_audio->a_buffer[sh_audio->a_buffer_len]); // decodes 33 byte -> 160 short
len+=2*320;
}
break; break;
} }
case 3: // AC3 decoder case 3: // AC3 decoder
@ -249,9 +266,10 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){
//printf("{3:%d}",avi_header.idx_pos);fflush(stdout); //printf("{3:%d}",avi_header.idx_pos);fflush(stdout);
break; break;
case 4: 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; break;
}
#ifdef USE_DIRECTSHOW #ifdef USE_DIRECTSHOW
case 7: // DirectShow case 7: // DirectShow
{ int ret; { int ret;
@ -267,7 +285,8 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int maxlen){
} }
DS_AudioDecoder_Convert(sh_audio->a_in_buffer,sh_audio->a_in_buffer_len, DS_AudioDecoder_Convert(sh_audio->a_in_buffer,sh_audio->a_in_buffer_len,
buf,maxlen, &size_in,&size_out); 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){ if(size_in>=sh_audio->a_in_buffer_len){
sh_audio->a_in_buffer_len=0; sh_audio->a_in_buffer_len=0;
} else { } else {

View File

@ -13,6 +13,7 @@ demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id){
ds->buffer_pos=ds->buffer_size=0; ds->buffer_pos=ds->buffer_size=0;
ds->buffer=NULL; ds->buffer=NULL;
ds->pts=0; ds->pts=0;
ds->pts_bytes=0;
ds->eof=0; ds->eof=0;
ds->pos=0; ds->pos=0;
ds->dpos=0; ds->dpos=0;
@ -120,7 +121,11 @@ int ds_fill_buffer(demux_stream_t *ds){
ds->buffer_size=p->len; ds->buffer_size=p->len;
ds->pos=p->pos; ds->pos=p->pos;
ds->dpos+=p->len; // !!! 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: // free packet:
ds->bytes-=p->len; ds->bytes-=p->len;
ds->first=p->next; ds->first=p->next;
@ -164,6 +169,24 @@ while(len>0){
return bytes; 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){ void ds_free_packs(demux_stream_t *ds){
demux_packet_t *dp=ds->first; demux_packet_t *dp=ds->first;
while(dp){ while(dp){

View File

@ -29,6 +29,7 @@ typedef struct {
int buffer_size; // current buffer size int buffer_size; // current buffer size
unsigned char* buffer; // current buffer unsigned char* buffer; // current buffer
float pts; // current buffer's pts 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 eof; // end of demuxed stream? (true if all buffer empty)
int pos; // position in the input stream (file) int pos; // position in the input stream (file)
int dpos; // position in the demuxed stream int dpos; // position in the demuxed stream
@ -106,7 +107,12 @@ inline static int ds_tell(demux_stream_t *ds){
return (ds->dpos-ds->buffer_size)+ds->buffer_pos; 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(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 #if 1
#define demux_getc(ds) (\ #define demux_getc(ds) (\

View File

@ -60,11 +60,12 @@ int init_acm_audio_codec(sh_audio_t *sh_audio){
if(verbose) printf("Audio codec opened OK! ;-)\n"); if(verbose) printf("Audio codec opened OK! ;-)\n");
acmStreamSize(sh_audio->srcstream, in_fmt->nBlockAlign, &srcsize, ACM_STREAMSIZEF_SOURCE); acmStreamSize(sh_audio->srcstream, in_fmt->nBlockAlign, &srcsize, ACM_STREAMSIZEF_SOURCE);
if(srcsize<OUTBURST) srcsize=OUTBURST; srcsize*=2;
if(srcsize<MAX_OUTBURST) srcsize=MAX_OUTBURST;
sh_audio->audio_out_minsize=srcsize; // audio output min. size sh_audio->audio_out_minsize=srcsize; // audio output min. size
if(verbose) printf("Audio ACM output buffer min. size: %ld\n",srcsize); 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 sh_audio->audio_in_minsize=srcsize; // audio input min. size
if(verbose) printf("Audio ACM input buffer min. size: %ld\n",srcsize); if(verbose) printf("Audio ACM input buffer min. size: %ld\n",srcsize);
@ -106,11 +107,12 @@ int acm_decode_audio(sh_audio_t *sh_audio, void* a_buffer,int len){
} }
hr=acmStreamConvert(sh_audio->srcstream,&ash,0); hr=acmStreamConvert(sh_audio->srcstream,&ash,0);
if(hr){ 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; // 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){ if(ash.cbSrcLengthUsed>=sh_audio->a_in_buffer_len){
sh_audio->a_in_buffer_len=0; sh_audio->a_in_buffer_len=0;
} else { } else {
@ -138,8 +140,8 @@ int init_video_codec(sh_video_t *sh_video){
sh_video->o_bih.biSize = sizeof(BITMAPINFOHEADER); sh_video->o_bih.biSize = sizeof(BITMAPINFOHEADER);
win32_codec_name = sh_video->codec->dll; 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_FASTDECOMPRESS);
// sh_video->hic = ICOpen( 0x63646976, sh_video->bih.biCompression, ICMODE_DECOMPRESS); sh_video->hic = ICOpen( 0x63646976, sh_video->bih->biCompression, ICMODE_DECOMPRESS);
if(!sh_video->hic){ if(!sh_video->hic){
printf("ICOpen failed! unknown codec / wrong parameters?\n"); printf("ICOpen failed! unknown codec / wrong parameters?\n");
return 0; return 0;
@ -260,19 +262,6 @@ int init_video_codec(sh_video_t *sh_video){
return 0; 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); sh_video->our_out_buffer = shmem_alloc(sh_video->o_bih.biSizeImage);
if(!sh_video->our_out_buffer){ if(!sh_video->our_out_buffer){
printf("not enough memory for decoded picture buffer (%ld bytes)\n", sh_video->o_bih.biSizeImage); printf("not enough memory for decoded picture buffer (%ld bytes)\n", sh_video->o_bih.biSizeImage);

216
mplayer.c
View File

@ -27,7 +27,7 @@
#include "version.h" #include "version.h"
#include "config.h" #include "config.h"
#ifndef OUTBURST #ifndef MAX_OUTBURST
#error "=============================================" #error "============================================="
#error "Please re-run ./configure and then try again!" #error "Please re-run ./configure and then try again!"
#error "=============================================" #error "============================================="
@ -254,7 +254,6 @@ int mplayer_audio_read(char *buf,int size){
return len; return len;
} }
//#include "dec_audio.c" //#include "dec_audio.c"
//**************************************************************************// //**************************************************************************//
@ -304,6 +303,31 @@ while(len>0){
} }
} }
#endif #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: // AVI file header reader/parser/writer:
@ -401,7 +425,7 @@ extern int init_video_codec(sh_video_t *sh_video);
extern void mpeg2_allocate_image_buffers(picture_t * picture); 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 void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height);
extern int vo_init(void); 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"; char* filename=NULL; //"MI2-Trailer.avi";
int i; int i;
@ -424,7 +448,6 @@ int alsa=1;
#else #else
int alsa=0; int alsa=0;
#endif #endif
int audio_buffer_size=-1;
int audio_id=-1; int audio_id=-1;
int video_id=-1; int video_id=-1;
int dvdsub_id=-1; int dvdsub_id=-1;
@ -1031,7 +1054,8 @@ if(has_audio){
printf("Couldn't initialize audio codec! -> nosound\n"); printf("Couldn't initialize audio codec! -> nosound\n");
has_audio=0; has_audio=0;
} else { } 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 @@ if(verbose) printf("vo_debug3: out_fmt=0x%08X\n",out_fmt);
//================== MAIN: ========================== //================== MAIN: ==========================
{ {
int audio_fd=-1; 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 float frame_correction=0; // A-V timestamp kulonbseg atlagolas
int frame_corr_num=0; // int frame_corr_num=0; //
float a_frame=0; // Audio float a_frame=0; // Audio
@ -1362,24 +1389,38 @@ if(has_audio){
#ifdef USE_XMMP_AUDIO #ifdef USE_XMMP_AUDIO
if(audio_buffer_size==-1){ if(audio_buffer_size==-1){
// Measuring buffer size: // Measuring buffer size:
buffer_delay=pSound->QueryDelay(pSound, 0); audio_buffer_delay=pSound->QueryDelay(pSound, 0);
} else { } else {
// -abs commandline option // -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 #else
int r; 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->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->channels-1; ioctl (audio_fd, SNDCTL_DSP_STEREO, &r);
r=sh_audio->samplerate; if(ioctl (audio_fd, SNDCTL_DSP_SPEED, &r)==-1) 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); 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 if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
// r = (64 << 16) + 1024; printf("audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n");
r = (65536 << 16) + 512; r=0;
if(ioctl (audio_fd, SNDCTL_DSP_SETFRAGMENT, &r)==-1) if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r)==-1){
printf("audio_setup: your card doesn't support setting fragments\n",r); printf("audio_setup: %d bytes/frag (config.h)\n",outburst);
#endif } 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){ if(audio_buffer_size==-1){
// Measuring buffer size: // Measuring buffer size:
@ -1391,8 +1432,8 @@ if(has_audio){
FD_ZERO(&rfds); FD_SET(audio_fd,&rfds); FD_ZERO(&rfds); FD_SET(audio_fd,&rfds);
tv.tv_sec=0; tv.tv_usec = 0; tv.tv_sec=0; tv.tv_usec = 0;
if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break; if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break;
write(audio_fd,&sh_audio->a_buffer[sh_audio->a_buffer_len],OUTBURST); write(audio_fd,&sh_audio->a_buffer[sh_audio->a_buffer_len],outburst);
audio_buffer_size+=OUTBURST; audio_buffer_size+=outburst;
} }
if(audio_buffer_size==0){ if(audio_buffer_size==0){
printf("\n *** Your audio driver DOES NOT support select() ***\n"); printf("\n *** Your audio driver DOES NOT support select() ***\n");
@ -1401,10 +1442,12 @@ if(has_audio){
} }
#endif #endif
} }
buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps); audio_buffer_delay=audio_buffer_size/(float)(sh_audio->o_bps);
#endif #endif
a_frame=-(buffer_delay); printf("Audio buffer size: %d bytes, delay: %5.3fs\n",audio_buffer_size,audio_buffer_delay);
printf("Audio buffer size: %d bytes, delay: %5.3fs\n",audio_buffer_size,buffer_delay);
// a_frame=-(audio_buffer_delay);
a_frame=0;
// RESET_AUDIO(audio_fd); // RESET_AUDIO(audio_fd);
} }
@ -1428,13 +1471,13 @@ if(!has_audio){
//==================== START PLAYING ======================= //==================== START PLAYING =======================
if(file_format==DEMUXER_TYPE_AVI){ 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)*sh_video->frametime;
// audio_delay-=(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)/default_fps; // audio_delay-=(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)/default_fps;
if(verbose){ if(verbose){
printf("AVI Initial frame delay: %5.3f\n",(float)(sh_audio->audio.dwInitialFrames-sh_video->video.dwInitialFrames)*sh_video->frametime); 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", 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); 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 delay_corrected=0; // has to correct PTS diffs
@ -1452,39 +1495,69 @@ InitTimer();
while(!eof){ while(!eof){
/*========================== PLAY AUDIO ============================*/ /*========================== 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){ 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 // Update buffer if needed
unsigned int t=GetTimer(); t=GetTimer();
current_module="decode_audio"; // Enter AUDIO decoder module current_module="decode_audio"; // Enter AUDIO decoder module
//sh_audio->codec->driver=has_audio; // FIXME! while(sh_audio->a_buffer_len<playsize && !d_audio->eof){
while(sh_audio->a_buffer_len<OUTBURST && !d_audio->eof){ int ret=decode_audio(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len],
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); 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; if(ret>0) sh_audio->a_buffer_len+=ret; else break;
} }
current_module=NULL; // Leave AUDIO decoder module current_module=NULL; // Leave AUDIO decoder module
t=GetTimer()-t;audio_time_usage+=t*0.000001; 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: // 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 #ifdef USE_XMMP_AUDIO
pSound->Write( pSound, sh_audio->a_buffer, OUTBURST ); pSound->Write( pSound, sh_audio->a_buffer, playsize );
#else #else
#ifdef SIMULATE_ALSA #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 #else
write(audio_fd,sh_audio->a_buffer,OUTBURST); playsize=write(audio_fd,sh_audio->a_buffer,playsize);
#endif #endif
#endif #endif
sh_audio->a_buffer_len-=OUTBURST; if(playsize>0){
memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[OUTBURST],sh_audio->a_buffer_len); 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 USE_XMMP_AUDIO
#ifndef SIMULATE_ALSA #ifndef SIMULATE_ALSA
// check buffer // check buffer
#ifdef HAVE_AUDIO_SELECT #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; struct timeval tv;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(audio_fd, &rfds); FD_SET(audio_fd, &rfds);
@ -1492,7 +1565,7 @@ while(has_audio){
tv.tv_usec = 0; tv.tv_usec = 0;
if(select(audio_fd+1, NULL, &rfds, NULL, &tv)){ if(select(audio_fd+1, NULL, &rfds, NULL, &tv)){
a_frame+=OUTBURST/(float)(sh_audio->o_bps); 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"); // printf("Filling audio buffer...\n");
continue; continue;
// } else { // } else {
@ -1508,13 +1581,9 @@ while(has_audio){
} // if(has_audio) } // if(has_audio)
/*========================== UPDATE TIMERS ============================*/ /*========================== UPDATE TIMERS ============================*/
#if 0
a_frame+=OUTBURST/(float)(sh_audio->o_bps);
a_pts+=OUTBURST/(float)(sh_audio->o_bps);
if(alsa){ if(alsa){
// Use system timer for sync, not audio card/driver // Use system timer for sync, not audio card/driver
time_frame+=OUTBURST/(float)(sh_audio->o_bps);
time_frame-=GetRelativeTime(); time_frame-=GetRelativeTime();
if(time_frame<-0.1 || time_frame>0.1){ if(time_frame<-0.1 || time_frame>0.1){
time_frame=0; time_frame=0;
@ -1529,19 +1598,19 @@ while(has_audio){
} }
} }
} }
#endif
/*========================== PLAY VIDEO ============================*/ /*========================== PLAY VIDEO ============================*/
if(1) if(1)
while(v_frame<a_frame || force_redraw){ while(1){
float frame_time=1; float frame_time=1;
float pts1=d_video->pts; float pts1=d_video->pts;
current_module="decode_video"; current_module="decode_video";
if(!force_redraw && v_frame+0.1<a_frame) drop_frame=1; else drop_frame=0; // if(!force_redraw && v_frame+0.1<a_frame) drop_frame=1; else drop_frame=0;
drop_frame_cnt+=drop_frame; drop_frame_cnt+=drop_frame;
//-------------------- Decode a frame: ----------------------- //-------------------- Decode a frame: -----------------------
@ -1714,6 +1783,29 @@ switch(sh_video->codec->driver){
} }
v_frame+=frame_time; v_frame+=frame_time;
v_pts+=frame_time; v_pts+=frame_time;
time_frame+=frame_time; // for nosound
// It's time to sleep...
time_frame-=GetRelativeTime(); // reset timer
if(has_audio){
int delay=get_audio_delay(audio_fd);
if(verbose)printf("delay=%d\n",delay);
time_frame=v_frame;
time_frame-=a_frame-(float)delay/(float)sh_audio->o_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){ if(!drop_frame){
current_module="flip_page"; current_module="flip_page";
@ -1726,6 +1818,7 @@ switch(sh_video->codec->driver){
if(force_redraw){ if(force_redraw){
--force_redraw; --force_redraw;
if(!force_redraw) osd_function=OSD_PLAY; 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); // 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 @@ switch(sh_video->codec->driver){
#if 1 #if 1
/*================ A-V TIMESTAMP CORRECTION: =========================*/ /*================ A-V TIMESTAMP CORRECTION: =========================*/
if(has_audio){ 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)){ 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+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 delay_corrected=1; // hack
} else } else
if(d_audio->pts){ if(d_audio->pts){
// printf("\n=== APTS a_pts=%5.3f v_pts=%5.3f === \n",d_audio->pts,d_video->pts); // printf("\n=== APTS a_pts=%5.3f v_pts=%5.3f === \n",d_audio->pts,d_video->pts);
#if 1 #if 1
if(!delay_corrected){ if(!delay_corrected){
float x=d_audio->pts-d_video->pts-(buffer_delay+audio_delay); float x=d_audio->pts-d_video->pts-(delay+audio_delay);
float y=-(buffer_delay+audio_delay); float y=-(delay+audio_delay);
printf("Initial PTS delay: %5.3f sec (calculated: %5.3f)\n",x,y); printf("Initial PTS delay: %5.3f sec (calculated: %5.3f)\n",x,y);
audio_delay+=x; audio_delay+=x;
//a_pts-=x; //a_pts-=x;
delay_corrected=1; delay_corrected=1;
if(verbose) if(verbose)
printf("v: audio_delay=%5.3f buffer_delay=%5.3f a.pts=%5.3f v.pts=%5.3f\n", 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 #endif
a_pts=d_audio->pts-(buffer_delay+audio_delay); // a_pts=(ds_tell_pts(d_audio)+sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
d_audio->pts=0; // 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(d_video->pts) v_pts=d_video->pts;
if(frame_corr_num==5){ if(frame_corr_num==5){
float x=(frame_correction/5.0f); float x=(frame_correction/5.0f);
if(delay_corrected){ 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; x*=0.5f;
if(x<-max_pts_correction) x=-max_pts_correction; else if(x<-max_pts_correction) x=-max_pts_correction; else
if(x> max_pts_correction) x= max_pts_correction; if(x> max_pts_correction) x= max_pts_correction;
@ -1779,7 +1883,7 @@ switch(sh_video->codec->driver){
} }
frame_corr_num=0; frame_correction=0; 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 { } else {
// No audio: // No audio:
if(d_video->pts) v_pts=d_video->pts; if(d_video->pts) v_pts=d_video->pts;
@ -1825,6 +1929,8 @@ switch(sh_video->codec->driver){
#endif #endif
} }
if(!force_redraw) break;
} // while(v_frame<a_frame || force_redraw) } // while(v_frame<a_frame || force_redraw)
@ -1857,11 +1963,11 @@ switch(sh_video->codec->driver){
rel_seek_secs-=600;break; rel_seek_secs-=600;break;
// delay correction: // delay correction:
case '+': case '+':
buffer_delay+=0.1; // increase audio buffer delay audio_delay+=0.1; // increase audio buffer delay
a_frame-=0.1; a_frame-=0.1;
break; break;
case '-': case '-':
buffer_delay-=0.1; // decrease audio buffer delay audio_delay-=0.1; // decrease audio buffer delay
a_frame+=0.1; a_frame+=0.1;
break; break;
// quit // quit
@ -1986,7 +2092,7 @@ switch(file_format){
#else #else
avi_video_pts=v_pts; avi_video_pts=v_pts;
#endif #endif
a_pts=avi_video_pts-(buffer_delay); a_pts=avi_video_pts;
//a_pts=v_pts; //-(buffer_delay+audio_delay); //a_pts=v_pts; //-(buffer_delay+audio_delay);
if(has_audio){ if(has_audio){
@ -2189,7 +2295,7 @@ switch(file_format){
max_pts_correction=0.1; max_pts_correction=0.1;
frame_corr_num=-5; frame_correction=0; frame_corr_num=-5; frame_correction=0;
force_redraw=5; force_redraw=5;
a_frame=-buffer_delay-skip_audio_secs; a_frame=-skip_audio_secs;
// a_frame=-audio_delay-buffer_delay-skip_audio_secs; // a_frame=-audio_delay-buffer_delay-skip_audio_secs;
v_frame=0; // !!!!!! v_frame=0; // !!!!!!
audio_time_usage=0; video_time_usage=0; vout_time_usage=0; audio_time_usage=0; video_time_usage=0; vout_time_usage=0;

View File

@ -15,7 +15,8 @@ typedef struct {
int samplerate; int samplerate;
int samplesize; int samplesize;
int channels; int channels;
int o_bps; // == samplerate*samplesize*channels int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec)
int i_bps; // == bitrate (compressed bytes/sec)
// in buffers: // in buffers:
char* a_in_buffer; char* a_in_buffer;
int a_in_buffer_len; int a_in_buffer_len;