Index: libmpcodecs/ad_liba52.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ad_liba52.c,v retrieving revision 1.14 diff -u -p -r1.14 ad_liba52.c --- libmpcodecs/ad_liba52.c 21 Sep 2004 20:34:46 -0000 1.14 +++ libmpcodecs/ad_liba52.c 23 Feb 2005 20:33:01 -0000 @@ -2,6 +2,7 @@ #include #include #include +#include #include "config.h" #ifdef USE_LIBA52 @@ -13,17 +14,21 @@ #include "cpudetect.h" +#include "../libaf/af_format.h" + #include "../liba52/a52.h" #include "../liba52/mm_accel.h" static sample_t * a52_samples; static a52_state_t a52_state; static uint32_t a52_flags=0; +static uint32_t channel_map; #define DRC_NO_ACTION 0 #define DRC_NO_COMPRESSION 1 #define DRC_CALLBACK 2 +static sample_t a52_level = 1; float a52_drc_level = 1.0; static int a52_drc_action = DRC_NO_ACTION; @@ -67,7 +72,7 @@ while(1){ mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"a52: len=%d flags=0x%X %d Hz %d bit/s\n",length,flags,sample_rate,bit_rate); sh_audio->samplerate=sample_rate; sh_audio->i_bps=bit_rate/8; - sh_audio->samplesize=2; + sh_audio->samplesize=sh_audio->sample_format==AF_FORMAT_FLOAT_NE ? 4 : 2; demux_read_data(sh_audio->ds,sh_audio->a_in_buffer+8,length-8); if(sh_audio->format!=0x2000) swab(sh_audio->a_in_buffer+8,sh_audio->a_in_buffer+8,length-8); @@ -114,15 +119,34 @@ static int preinit(sh_audio_t *sh) { /* Dolby AC3 audio: */ /* however many channels, 2 bytes in a word, 256 samples in a block, 6 blocks in a frame */ - sh->audio_out_minsize=audio_output_channels*2*256*6; + sh->audio_out_minsize=audio_output_channels*sh->samplesize*256*6; sh->audio_in_minsize=3840; + a52_level = 1.0; return 1; } +static int a52_resample_float(float *in, int16_t *out) +{ + unsigned long i; + float *p = (float*) out; + for (i = 0; i != 256; i++) { + unsigned long map = channel_map; + do { + unsigned long ch = map & 15; + if (ch == 15) + *p = 0; + else + *p = in[i + ((ch-1)<<8)]; + p++; + } while ((map >>= 4)); + } + return (int16_t*) p - out; +} + static int init(sh_audio_t *sh_audio) { uint32_t a52_accel=0; - sample_t level=1, bias=384; + sample_t level=a52_level, bias=384; int flags=0; /* Dolby AC3 audio:*/ if(gCpuCaps.hasSSE) a52_accel|=MM_ACCEL_X86_SSE; @@ -178,6 +202,36 @@ while(sh_audio->channels>0){ } mp_msg(MSGT_DECAUDIO,MSGL_V,"A52 flags after a52_frame: 0x%X\n",flags); /* frame decoded, let's init resampler:*/ + channel_map = 0; + if (sh_audio->sample_format == AF_FORMAT_FLOAT_NE) { + if (!(flags & A52_LFE)) { + switch ((flags<<3) | sh_audio->channels) { + case (A52_MONO << 3) | 1: channel_map = 0x1; break; + case (A52_CHANNEL << 3) | 2: + case (A52_STEREO << 3) | 2: + case (A52_DOLBY << 3) | 2: channel_map = 0x21; break; + case (A52_2F1R << 3) | 3: channel_map = 0x321; break; + case (A52_2F2R << 3) | 4: channel_map = 0x4321; break; + case (A52_3F << 3) | 5: channel_map = 0x2ff31; break; + case (A52_3F2R << 3) | 5: channel_map = 0x25431; break; + } + } else if (sh_audio->channels == 6) { + switch (flags & ~A52_LFE) { + case A52_MONO : channel_map = 0x12ffff; break; + case A52_CHANNEL: + case A52_STEREO : + case A52_DOLBY : channel_map = 0x1fff32; break; + case A52_3F : channel_map = 0x13ff42; break; + case A52_2F1R : channel_map = 0x1f4432; break; + case A52_2F2R : channel_map = 0x1f5432; break; + case A52_3F2R : channel_map = 0x136542; break; + } + } + if (channel_map) { + a52_resample = a52_resample_float; + break; + } + } else if(a52_resample_init(a52_accel,flags,sh_audio->channels)) break; --sh_audio->channels; /* try to decrease no. of channels*/ } @@ -199,15 +253,28 @@ static int control(sh_audio_t *sh,int cm case ADCTRL_SKIP_FRAME: a52_fillbuff(sh); break; // skip AC3 frame return CONTROL_TRUE; + case ADCTRL_SET_VOLUME: { + float vol = *(float*)arg; + if (vol > 60.0) vol = 60.0; + a52_level = vol <= -200.0 ? 0 : pow(10.0,vol/20.0); + return CONTROL_TRUE; + } + case ADCTRL_QUERY_FORMAT: + if (*(int*)arg == AF_FORMAT_S16_NE || + *(int*)arg == AF_FORMAT_FLOAT_NE) + return CONTROL_TRUE; + return CONTROL_FALSE; } return CONTROL_UNKNOWN; } static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) { - sample_t level=1, bias=384; + sample_t level=a52_level, bias=384; int flags=a52_flags|A52_ADJUST_LEVEL; int i,len=-1; + if (sh_audio->sample_format == AF_FORMAT_FLOAT_NE) + bias = 0; if(!sh_audio->a_in_buffer_len) if(a52_fillbuff(sh_audio)<0) return len; /* EOF */ sh_audio->a_in_buffer_len=0; @@ -232,6 +299,7 @@ static int decode_audio(sh_audio_t *sh_a } len+=2*a52_resample(a52_samples,(int16_t *)&buf[len]); } + assert(len <= maxlen); return len; } #endif Index: libmpcodecs/dec_audio.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/dec_audio.c,v retrieving revision 1.35 diff -u -p -r1.35 dec_audio.c --- libmpcodecs/dec_audio.c 17 Jan 2005 17:27:39 -0000 1.35 +++ libmpcodecs/dec_audio.c 23 Feb 2005 20:33:01 -0000 @@ -29,8 +29,6 @@ int fakemono=0; int audio_output_channels = 2; af_cfg_t af_cfg; // Configuration for audio filters -static ad_functions_t* mpadec; - void afm_help(){ int i; mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_AvailableAudioFm); @@ -49,7 +47,15 @@ void afm_help(){ int init_audio_codec(sh_audio_t *sh_audio) { - if(!mpadec->preinit(sh_audio)) + if ((af_cfg.force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) { + int fmt = AF_FORMAT_FLOAT_NE; + if (sh_audio->ad_driver->control(sh_audio, ADCTRL_QUERY_FORMAT, + &fmt) == CONTROL_TRUE) { + sh_audio->sample_format = fmt; + sh_audio->samplesize = 4; + } + } + if(!sh_audio->ad_driver->preinit(sh_audio)) { mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_ADecoderPreinitFailed); return 0; @@ -79,7 +85,7 @@ int init_audio_codec(sh_audio_t *sh_audi memset(sh_audio->a_buffer,0,sh_audio->a_buffer_size); sh_audio->a_buffer_len=0; - if(!mpadec->init(sh_audio)){ + if(!sh_audio->ad_driver->init(sh_audio)){ mp_msg(MSGT_DECAUDIO,MSGL_WARN,MSGTR_ADecoderInitFailed); uninit_audio(sh_audio); // free buffers return 0; @@ -112,7 +118,9 @@ int init_audio(sh_audio_t *sh_audio,char unsigned int orig_fourcc=sh_audio->wf?sh_audio->wf->wFormatTag:0; sh_audio->codec=NULL; while(1){ + ad_functions_t* mpadec; int i; + sh_audio->ad_driver = 0; // restore original fourcc: if(sh_audio->wf) sh_audio->wf->wFormatTag=i=orig_fourcc; if(!(sh_audio->codec=find_codec(sh_audio->format, @@ -169,6 +177,7 @@ int init_audio(sh_audio_t *sh_audio,char // it's available, let's try to init! // init() mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_OpeningAudioDecoder,mpadec->info->short_name,mpadec->info->name); + sh_audio->ad_driver = mpadec; if(!init_audio_codec(sh_audio)){ mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_ADecoderInitFailed); continue; // try next... @@ -239,7 +248,7 @@ void uninit_audio(sh_audio_t *sh_audio) } if(sh_audio->inited){ mp_msg(MSGT_DECAUDIO,MSGL_V,MSGTR_UninitAudioStr,sh_audio->codec->drv); - mpadec->uninit(sh_audio); + sh_audio->ad_driver->uninit(sh_audio); #ifdef DYNAMIC_PLUGINS if (sh_audio->dec_handle) dlclose(sh_audio->dec_handle); @@ -360,6 +369,7 @@ int decode_audio(sh_audio_t *sh_audio,un int declen; af_data_t afd; // filter input af_data_t* pafd; // filter output + ad_functions_t* mpadec = sh_audio->ad_driver; if(!sh_audio->inited) return -1; // no codec if(!sh_audio->afilter){ @@ -441,13 +451,13 @@ void resync_audio_stream(sh_audio_t *sh_ { sh_audio->a_in_buffer_len=0; // clear audio input buffer if(!sh_audio->inited) return; - mpadec->control(sh_audio,ADCTRL_RESYNC_STREAM,NULL); + sh_audio->ad_driver->control(sh_audio,ADCTRL_RESYNC_STREAM,NULL); } void skip_audio_frame(sh_audio_t *sh_audio) { if(!sh_audio->inited) return; - if(mpadec->control(sh_audio,ADCTRL_SKIP_FRAME,NULL)==CONTROL_TRUE) return; + if(sh_audio->ad_driver->control(sh_audio,ADCTRL_SKIP_FRAME,NULL)==CONTROL_TRUE) return; // default skip code: ds_fill_buffer(sh_audio->ds); // skip block } Index: libmpdemux/stheader.h =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/stheader.h,v retrieving revision 1.40 diff -u -p -r1.40 stheader.h --- libmpdemux/stheader.h 28 Apr 2004 10:18:33 -0000 1.40 +++ libmpdemux/stheader.h 23 Feb 2005 20:33:01 -0000 @@ -35,6 +35,7 @@ typedef struct { int a_out_buffer_size; // void* audio_out; // the audio_out handle, used for this audio stream void* afilter; // the audio filter stream + struct ad_functions_s* ad_driver; #ifdef DYNAMIC_PLUGINS void *dec_handle; #endif