Mercurial > mplayer.hg
view dec_audio.c @ 4513:2e3800da1ceb
Switched from libmp1e to libavcodec, at least for me it runs helluva lot faster than libmp1e
(high quality divx movies that before ran very poor now plays perfectly). Also includes some
minor fixes to the osd support. Since libmp1e has issues with non-mmx system I think this move
is a smart one...
author | mswitch |
---|---|
date | Sun, 03 Feb 2002 14:55:27 +0000 |
parents | d3aedd7db02c |
children | 4a6dde59834c |
line wrap: on
line source
#define USE_G72X //#define USE_LIBAC3 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "config.h" #include "mp_msg.h" #include "help_mp.h" extern int verbose; // defined in mplayer.c #include "stream.h" #include "demuxer.h" #include "codec-cfg.h" #include "stheader.h" #include "dec_audio.h" #include "roqav.h" //========================================================================== #include "libao2/afmt.h" #include "dll_init.h" #include "mp3lib/mp3.h" #ifdef USE_LIBAC3 #include "libac3/ac3.h" #endif #include "liba52/a52.h" #include "liba52/mm_accel.h" static sample_t * a52_samples; static a52_state_t a52_state; static uint32_t a52_accel=0; static uint32_t a52_flags=0; #ifdef USE_G72X #include "g72x/g72x.h" static G72x_DATA g72x_data; #endif #include "alaw.h" #include "xa/xa_gsm.h" #include "ac3-iec958.h" #include "adpcm.h" #include "cpudetect.h" /* used for ac3surround decoder - set using -channels option */ int audio_output_channels = 2; #ifdef USE_FAKE_MONO int fakemono=0; #endif #ifdef USE_DIRECTSHOW #include "loader/dshow/DS_AudioDecoder.h" static DS_AudioDecoder* ds_adec=NULL; #endif #ifdef HAVE_OGGVORBIS /* XXX is math.h really needed? - atmos */ #include <math.h> #include <vorbis/codec.h> typedef struct ov_struct_st { ogg_sync_state oy; /* sync and verify incoming physical bitstream */ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the bitstream user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ } ov_struct_t; #endif #ifdef USE_LIBAVCODEC #ifdef USE_LIBAVCODEC_SO #include <libffmpeg/avcodec.h> #else #include "libavcodec/avcodec.h" #endif static AVCodec *lavc_codec=NULL; static AVCodecContext lavc_context; extern int avcodec_inited; #endif #ifdef USE_LIBMAD #include <mad.h> #define MAD_SINGLE_BUFFER_SIZE 8192 #define MAD_TOTAL_BUFFER_SIZE ((MAD_SINGLE_BUFFER_SIZE)*3) static struct mad_stream mad_stream; static struct mad_frame mad_frame; static struct mad_synth mad_synth; static char* mad_in_buffer = 0; /* base pointer of buffer */ // ensure buffer is filled with some data static void mad_prepare_buffer(sh_audio_t* sh_audio, struct mad_stream* ms, int length) { if(sh_audio->a_in_buffer_len < length) { int len = demux_read_data(sh_audio->ds, sh_audio->a_in_buffer+sh_audio->a_in_buffer_len, length-sh_audio->a_in_buffer_len); sh_audio->a_in_buffer_len += len; // printf("mad_prepare_buffer: read %d bytes\n", len); } } static void mad_postprocess_buffer(sh_audio_t* sh_audio, struct mad_stream* ms) { /* rotate buffer while possible, in order to reduce the overhead of endless memcpy */ int delta = (unsigned char*)ms->next_frame - (unsigned char *)sh_audio->a_in_buffer; if((unsigned long)(sh_audio->a_in_buffer) - (unsigned long)mad_in_buffer < (MAD_TOTAL_BUFFER_SIZE - MAD_SINGLE_BUFFER_SIZE - delta)) { sh_audio->a_in_buffer += delta; sh_audio->a_in_buffer_len -= delta; } else { sh_audio->a_in_buffer = mad_in_buffer; sh_audio->a_in_buffer_len -= delta; memcpy(sh_audio->a_in_buffer, ms->next_frame, sh_audio->a_in_buffer_len); } } static inline signed short mad_scale(mad_fixed_t sample) { /* round */ sample += (1L << (MAD_F_FRACBITS - 16)); /* clip */ if (sample >= MAD_F_ONE) sample = MAD_F_ONE - 1; else if (sample < -MAD_F_ONE) sample = -MAD_F_ONE; /* quantize */ return sample >> (MAD_F_FRACBITS + 1 - 16); } static void mad_sync(sh_audio_t* sh_audio, struct mad_stream* ms) { int len; #if 1 int skipped = 0; // printf("buffer len: %d\n", sh_audio->a_in_buffer_len); while(sh_audio->a_in_buffer_len - skipped) { len = mp_decode_mp3_header(sh_audio->a_in_buffer+skipped); if (len != -1) { // printf("Frame len=%d\n", len); break; } else skipped++; } if (skipped) { printf("Audio synced, skipped bytes: %d\n", skipped); // ms->skiplen += skipped; // printf("skiplen: %d (skipped: %d)\n", ms->skiplen, skipped); // if (sh_audio->a_in_buffer_len - skipped < MAD_BUFFER_GUARD) // printf("Mad reports: too small buffer\n"); // mad_stream_buffer(ms, sh_audio->a_in_buffer+skipped, sh_audio->a_in_buffer_len-skipped); // mad_prepare_buffer(sh_audio, ms, sh_audio->a_in_buffer_len-skipped); /* move frame to the beginning of the buffer and fill up to a_in_buffer_size */ sh_audio->a_in_buffer_len -= skipped; memcpy(sh_audio->a_in_buffer, sh_audio->a_in_buffer+skipped, sh_audio->a_in_buffer_len); mad_prepare_buffer(sh_audio, ms, sh_audio->a_in_buffer_size); mad_stream_buffer(ms, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len); // printf("bufflen: %d\n", sh_audio->a_in_buffer_len); // len = mp_decode_mp3_header(sh_audio->a_in_buffer); // printf("len: %d\n", len); ms->md_len = len; } #else len = mad_stream_sync(&ms); if (len == -1) { printf("Mad sync failed\n"); } #endif } static void mad_print_error(struct mad_stream *mad_stream) { printf("error (0x%x): ", mad_stream->error); switch(mad_stream->error) { case MAD_ERROR_BUFLEN: printf("buffer too small"); break; case MAD_ERROR_BUFPTR: printf("invalid buffer pointer"); break; case MAD_ERROR_NOMEM: printf("not enought memory"); break; case MAD_ERROR_LOSTSYNC: printf("lost sync"); break; case MAD_ERROR_BADLAYER: printf("bad layer"); break; case MAD_ERROR_BADBITRATE: printf("bad bitrate"); break; case MAD_ERROR_BADSAMPLERATE: printf("bad samplerate"); break; case MAD_ERROR_BADEMPHASIS: printf("bad emphasis"); break; case MAD_ERROR_BADCRC: printf("bad crc"); break; case MAD_ERROR_BADBITALLOC: printf("forbidden bit alloc val"); break; case MAD_ERROR_BADSCALEFACTOR: printf("bad scalefactor index"); break; case MAD_ERROR_BADFRAMELEN: printf("bad frame length"); break; case MAD_ERROR_BADBIGVALUES: printf("bad bigvalues count"); break; case MAD_ERROR_BADBLOCKTYPE: printf("reserved blocktype"); break; case MAD_ERROR_BADSCFSI: printf("bad scalefactor selinfo"); break; case MAD_ERROR_BADDATAPTR: printf("bad maindatabegin ptr"); break; case MAD_ERROR_BADPART3LEN: printf("bad audio data len"); break; case MAD_ERROR_BADHUFFTABLE: printf("bad huffman table sel"); break; case MAD_ERROR_BADHUFFDATA: printf("huffman data overrun"); break; case MAD_ERROR_BADSTEREO: printf("incomp. blocktype for JS"); break; default: printf("unknown error"); } printf("\n"); } #endif static int a52_fillbuff(sh_audio_t *sh_audio){ int length=0; int flags=0; int sample_rate=0; int bit_rate=0; sh_audio->a_in_buffer_len=0; // sync frame: while(1){ while(sh_audio->a_in_buffer_len<7){ int c=demux_getc(sh_audio->ds); if(c<0) return -1; // EOF sh_audio->a_in_buffer[sh_audio->a_in_buffer_len++]=c; } length = a52_syncinfo (sh_audio->a_in_buffer, &flags, &sample_rate, &bit_rate); if(length>=7 && length<=3840) break; // we're done. // bad file => resync memcpy(sh_audio->a_in_buffer,sh_audio->a_in_buffer+1,6); --sh_audio->a_in_buffer_len; } 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; demux_read_data(sh_audio->ds,sh_audio->a_in_buffer+7,length-7); if(crc16_block(sh_audio->a_in_buffer+2,length-2)!=0) mp_msg(MSGT_DECAUDIO,MSGL_STATUS,"a52: CRC check failed! \n"); return length; } // returns: number of available channels static int a52_printinfo(sh_audio_t *sh_audio){ int flags, sample_rate, bit_rate; char* mode="unknown"; int channels=0; a52_syncinfo (sh_audio->a_in_buffer, &flags, &sample_rate, &bit_rate); switch(flags&A52_CHANNEL_MASK){ case A52_CHANNEL: mode="channel"; channels=2; break; case A52_MONO: mode="mono"; channels=1; break; case A52_STEREO: mode="stereo"; channels=2; break; case A52_3F: mode="3f";channels=3;break; case A52_2F1R: mode="2f+1r";channels=3;break; case A52_3F1R: mode="3f+1r";channels=4;break; case A52_2F2R: mode="2f+2r";channels=4;break; case A52_3F2R: mode="3f+2r";channels=5;break; case A52_CHANNEL1: mode="channel1"; channels=2; break; case A52_CHANNEL2: mode="channel2"; channels=2; break; case A52_DOLBY: mode="dolby"; channels=2; break; } mp_msg(MSGT_DECAUDIO,MSGL_INFO,"AC3: %d.%d (%s%s) %d Hz %3.1f kbit/s\n", channels, (flags&A52_LFE)?1:0, mode, (flags&A52_LFE)?"+lfe":"", sample_rate, bit_rate*0.001f); return (flags&A52_LFE) ? (channels+1) : channels; } int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen); static sh_audio_t* dec_audio_sh=NULL; #ifdef USE_LIBAC3 // AC3 decoder buffer callback: static void ac3_fill_buffer(uint8_t **start,uint8_t **end){ int len=ds_get_packet(dec_audio_sh->ds,start); //printf("<ac3:%d>\n",len); if(len<0) *start = *end = NULL; else *end = *start + len; } #endif // MP3 decoder buffer callback: int mplayer_audio_read(char *buf,int size){ int len; len=demux_read_data(dec_audio_sh->ds,buf,size); return len; } int init_audio(sh_audio_t *sh_audio){ int driver=sh_audio->codec->driver; sh_audio->samplesize=2; #ifdef WORDS_BIGENDIAN sh_audio->sample_format=AFMT_S16_BE; #else sh_audio->sample_format=AFMT_S16_LE; #endif sh_audio->samplerate=0; //sh_audio->pcm_bswap=0; sh_audio->o_bps=0; sh_audio->a_buffer_size=0; sh_audio->a_buffer=NULL; sh_audio->a_in_buffer_len=0; // setup required min. in/out buffer size: sh_audio->audio_out_minsize=8192;// default size, maybe not enough for Win32/ACM switch(driver){ case AFM_ACM: #ifndef USE_WIN32DLL mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_NoACMSupport); driver=0; #else // 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->audio_out_minsize>16384) sh_audio->audio_out_minsize=16384; // sh_audio->a_buffer_size=sh_audio->audio_out_minsize; // if(sh_audio->a_buffer_size<sh_audio->audio_out_minsize+MAX_OUTBURST) // sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST; } else { mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_ACMiniterror); driver=0; } #endif break; case AFM_DSHOW: #ifndef USE_DIRECTSHOW mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_NoDShowAudio); driver=0; #else // Win32 DShow audio codec: // printf("DShow_audio: channs=%d rate=%d\n",sh_audio->channels,sh_audio->samplerate); if(!(ds_adec=DS_AudioDecoder_Open(sh_audio->codec->dll,&sh_audio->codec->guid,sh_audio->wf))){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_MissingDLLcodec,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; if(sh_audio->audio_in_minsize<8192) sh_audio->audio_in_minsize=8192; sh_audio->a_in_buffer_size=sh_audio->audio_in_minsize; sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size); sh_audio->a_in_buffer_len=0; sh_audio->audio_out_minsize=16384; } #endif break; case AFM_VORBIS: #ifndef HAVE_OGGVORBIS mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_NoOggVorbis); driver=0; #else /* OggVorbis audio via libvorbis, compatible with files created by nandub and zorannt codec */ sh_audio->audio_out_minsize=1024*4; // 1024 samples/frame #endif break; case AFM_PCM: case AFM_DVDPCM: case AFM_ALAW: // PCM, aLaw sh_audio->audio_out_minsize=2048; break; case AFM_AC3: case AFM_A52: // Dolby AC3 audio: // however many channels, 2 bytes in a word, 256 samples in a block, 6 blocks in a frame sh_audio->audio_out_minsize=audio_output_channels*2*256*6; break; case AFM_HWAC3: // Dolby AC3 audio: sh_audio->audio_out_minsize=4*256*6; // sh_audio->sample_format = AFMT_AC3; // sh_audio->sample_format = AFMT_S16_LE; sh_audio->channels=2; break; case AFM_GSM: // MS-GSM audio codec: sh_audio->audio_out_minsize=4*320; break; case AFM_IMAADPCM: sh_audio->audio_out_minsize=4096; sh_audio->ds->ss_div=IMA_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul=IMA_ADPCM_BLOCK_SIZE; break; case AFM_MSADPCM: sh_audio->audio_out_minsize=sh_audio->wf->nBlockAlign * 8; sh_audio->ds->ss_div = MS_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; break; case AFM_FOX61ADPCM: sh_audio->audio_out_minsize=FOX61_ADPCM_SAMPLES_PER_BLOCK * 4; sh_audio->ds->ss_div=FOX61_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul=FOX61_ADPCM_BLOCK_SIZE; break; case AFM_FOX62ADPCM: sh_audio->audio_out_minsize=FOX62_ADPCM_SAMPLES_PER_BLOCK * 4; sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE; break; case AFM_ROQAUDIO: // minsize was stored in wf->nBlockAlign by the RoQ demuxer sh_audio->audio_out_minsize=sh_audio->wf->nBlockAlign; sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE; sh_audio->context = roq_decode_audio_init(); break; case AFM_MPEG: // MPEG Audio: sh_audio->audio_out_minsize=4608; break; #ifdef USE_G72X case AFM_G72X: // g72x_reader_init(&g72x_data,G723_16_BITS_PER_SAMPLE); g72x_reader_init(&g72x_data,G723_24_BITS_PER_SAMPLE); // g72x_reader_init(&g72x_data,G721_32_BITS_PER_SAMPLE); // g72x_reader_init(&g72x_data,G721_40_BITS_PER_SAMPLE); sh_audio->audio_out_minsize=g72x_data.samplesperblock*4; break; #endif case AFM_FFMPEG: #ifndef USE_LIBAVCODEC mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_NoLAVCsupport); return 0; #else // FFmpeg Audio: sh_audio->audio_out_minsize=AVCODEC_MAX_AUDIO_FRAME_SIZE; break; #endif #ifdef USE_LIBMAD case AFM_MAD: printf(__FILE__ ":%d:mad: setting minimum outputsize\n", __LINE__); sh_audio->audio_out_minsize=4608; if(sh_audio->audio_in_minsize<MAD_SINGLE_BUFFER_SIZE) sh_audio->audio_in_minsize=MAD_SINGLE_BUFFER_SIZE; sh_audio->a_in_buffer_size=sh_audio->audio_in_minsize; mad_in_buffer = sh_audio->a_in_buffer = malloc(MAD_TOTAL_BUFFER_SIZE); sh_audio->a_in_buffer_len=0; break; #endif } if(!driver) return 0; // allocate audio out buffer: sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST; // worst case calc. mp_msg(MSGT_DECAUDIO,MSGL_V,"dec_audio: Allocating %d + %d = %d bytes for output buffer\n", sh_audio->audio_out_minsize,MAX_OUTBURST,sh_audio->a_buffer_size); sh_audio->a_buffer=malloc(sh_audio->a_buffer_size); if(!sh_audio->a_buffer){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantAllocAudioBuf); return 0; } memset(sh_audio->a_buffer,0,sh_audio->a_buffer_size); sh_audio->a_buffer_len=0; switch(driver){ #ifdef USE_WIN32DLL case AFM_ACM: { int ret=acm_decode_audio(sh_audio,sh_audio->a_buffer,4096,sh_audio->a_buffer_size); if(ret<0){ mp_msg(MSGT_DECAUDIO,MSGL_INFO,"ACM decoding error: %d\n",ret); driver=0; } sh_audio->a_buffer_len=ret; break; } #endif case AFM_PCM: { // 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; switch(sh_audio->format){ // hardware formats: case 0x6: sh_audio->sample_format=AFMT_A_LAW;break; case 0x7: sh_audio->sample_format=AFMT_MU_LAW;break; case 0x11: sh_audio->sample_format=AFMT_IMA_ADPCM;break; case 0x50: sh_audio->sample_format=AFMT_MPEG;break; case 0x736F7774: sh_audio->sample_format=AFMT_S16_LE;sh_audio->codec->driver=AFM_DVDPCM;break; // case 0x2000: sh_audio->sample_format=AFMT_AC3; default: sh_audio->sample_format=(sh_audio->samplesize==2)?AFMT_S16_LE:AFMT_U8; } break; } case AFM_DVDPCM: { // DVD PCM Audio: sh_audio->channels=2; sh_audio->samplerate=48000; sh_audio->i_bps=2*2*48000; // sh_audio->pcm_bswap=1; break; } case AFM_AC3: { #ifndef USE_LIBAC3 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"WARNING: libac3 support is disabled. (hint: upgrade codecs.conf)\n"); driver=0; #else // Dolby AC3 audio: dec_audio_sh=sh_audio; // save sh_audio for the callback: ac3_config.fill_buffer_callback = ac3_fill_buffer; ac3_config.num_output_ch = audio_output_channels; ac3_config.flags = 0; if(gCpuCaps.hasMMX){ ac3_config.flags |= AC3_MMX_ENABLE; } if(gCpuCaps.has3DNow){ ac3_config.flags |= AC3_3DNOW_ENABLE; } ac3_init(); sh_audio->ac3_frame = ac3_decode_frame(); if(sh_audio->ac3_frame){ ac3_frame_t* fr=(ac3_frame_t*)sh_audio->ac3_frame; sh_audio->samplerate=fr->sampling_rate; sh_audio->channels=ac3_config.num_output_ch; // 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 } #endif break; } case AFM_A52: { sample_t level=1, bias=384; int flags=0; // Dolby AC3 audio: if(gCpuCaps.hasSSE) a52_accel|=MM_ACCEL_X86_SSE; if(gCpuCaps.hasMMX) a52_accel|=MM_ACCEL_X86_MMX; if(gCpuCaps.hasMMX2) a52_accel|=MM_ACCEL_X86_MMXEXT; if(gCpuCaps.has3DNow) a52_accel|=MM_ACCEL_X86_3DNOW; if(gCpuCaps.has3DNowExt) a52_accel|=MM_ACCEL_X86_3DNOWEXT; a52_samples=a52_init (a52_accel); if (a52_samples == NULL) { mp_msg(MSGT_DECAUDIO,MSGL_ERR,"A52 init failed\n"); driver=0;break; } sh_audio->a_in_buffer_size=3840; sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size); sh_audio->a_in_buffer_len=0; if(a52_fillbuff(sh_audio)<0){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,"A52 sync failed\n"); driver=0;break; } // 'a52 cannot upmix' hotfix: a52_printinfo(sh_audio); // if(audio_output_channels<sh_audio->channels) // sh_audio->channels=audio_output_channels; // channels setup: sh_audio->channels=audio_output_channels; while(sh_audio->channels>0){ switch(sh_audio->channels){ case 1: a52_flags=A52_MONO; break; // case 2: a52_flags=A52_STEREO; break; case 2: a52_flags=A52_DOLBY; break; // case 3: a52_flags=A52_3F; break; case 3: a52_flags=A52_2F1R; break; case 4: a52_flags=A52_2F2R; break; // 2+2 case 5: a52_flags=A52_3F2R; break; case 6: a52_flags=A52_3F2R|A52_LFE; break; // 5.1 } // test: flags=a52_flags|A52_ADJUST_LEVEL; mp_msg(MSGT_DECAUDIO,MSGL_V,"A52 flags before a52_frame: 0x%X\n",flags); if (a52_frame (&a52_state, sh_audio->a_in_buffer, &flags, &level, bias)){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,"a52: error decoding frame -> nosound\n"); driver=0;break; } mp_msg(MSGT_DECAUDIO,MSGL_V,"A52 flags after a52_frame: 0x%X\n",flags); // frame decoded, let's init resampler: if(a52_resample_init(a52_accel,flags,sh_audio->channels)) break; --sh_audio->channels; // try to decrease no. of channels } if(sh_audio->channels<=0){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,"a52: no resampler. try different channel setup!\n"); driver=0;break; } break; } case AFM_HWAC3: { // Dolby AC3 passthrough: a52_samples=a52_init (a52_accel); if (a52_samples == NULL) { mp_msg(MSGT_DECAUDIO,MSGL_ERR,"A52 init failed\n"); driver=0;break; } sh_audio->a_in_buffer_size=3840; sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size); sh_audio->a_in_buffer_len=0; if(a52_fillbuff(sh_audio)<0) { mp_msg(MSGT_DECAUDIO,MSGL_ERR,"A52 sync failed\n"); driver=0;break; } //sh_audio->samplerate=ai.samplerate; // SET by a52_fillbuff() //sh_audio->samplesize=ai.framesize; //sh_audio->i_bps=ai.bitrate*(1000/8); // SET by a52_fillbuff() //sh_audio->ac3_frame=malloc(6144); //sh_audio->o_bps=sh_audio->i_bps; // XXX FIXME!!! XXX // o_bps is calculated from samplesize*channels*samplerate // a single ac3 frame is always translated to 6144 byte packet. (zero padding) sh_audio->channels=2; sh_audio->samplesize=2; // 2*2*(6*256) = 6144 (very TRICKY!) break; } case AFM_ALAW: { // aLaw audio codec: 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; } #ifdef USE_G72X case AFM_G72X: { // GSM 723 audio codec: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps=(sh_audio->samplerate/g72x_data.samplesperblock)*g72x_data.blocksize; break; } #endif #ifdef USE_LIBAVCODEC case AFM_FFMPEG: { int x; mp_msg(MSGT_DECAUDIO,MSGL_V,"FFmpeg's libavcodec audio codec\n"); if(!avcodec_inited){ avcodec_init(); avcodec_register_all(); avcodec_inited=1; } lavc_codec = (AVCodec *)avcodec_find_decoder_by_name(sh_audio->codec->dll); if(!lavc_codec){ mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_MissingLAVCcodec,sh_audio->codec->dll); return 0; } memset(&lavc_context, 0, sizeof(lavc_context)); /* open it */ if (avcodec_open(&lavc_context, lavc_codec) < 0) { mp_msg(MSGT_DECAUDIO,MSGL_ERR, MSGTR_CantOpenCodec); return 0; } mp_msg(MSGT_DECAUDIO,MSGL_V,"INFO: libavcodec init OK!\n"); // Decode at least 1 byte: (to get header filled) x=decode_audio(sh_audio,sh_audio->a_buffer,1,sh_audio->a_buffer_size); if(x>0) sh_audio->a_buffer_len=x; #if 1 sh_audio->channels=lavc_context.channels; sh_audio->samplerate=lavc_context.sample_rate; sh_audio->i_bps=lavc_context.bit_rate/8; #else sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; #endif break; } #endif case AFM_GSM: { // MS-GSM audio codec: 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 AFM_IMAADPCM: // IMA-ADPCM 4:1 audio codec: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; // decodes 34 byte -> 64 short sh_audio->i_bps=IMA_ADPCM_BLOCK_SIZE*(sh_audio->channels*sh_audio->samplerate)/IMA_ADPCM_SAMPLES_PER_BLOCK; // 1:4 break; case AFM_MSADPCM: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps = sh_audio->wf->nBlockAlign * (sh_audio->channels*sh_audio->samplerate) / MS_ADPCM_SAMPLES_PER_BLOCK; break; case AFM_FOX61ADPCM: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps=FOX61_ADPCM_BLOCK_SIZE* (sh_audio->channels*sh_audio->samplerate) / FOX61_ADPCM_SAMPLES_PER_BLOCK; break; case AFM_FOX62ADPCM: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps=FOX62_ADPCM_BLOCK_SIZE* (sh_audio->channels*sh_audio->samplerate) / FOX62_ADPCM_SAMPLES_PER_BLOCK; break; case AFM_ROQAUDIO: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->i_bps = (sh_audio->channels * 22050) / 2; break; case AFM_MPEG: { // MPEG Audio: dec_audio_sh=sh_audio; // save sh_audio for the callback: #ifdef USE_FAKE_MONO MP3_Init(fakemono); #else MP3_Init(); #endif MP3_samplerate=MP3_channels=0; sh_audio->a_buffer_len=MP3_DecodeFrame(sh_audio->a_buffer,-1); sh_audio->channels=2; // hack sh_audio->samplerate=MP3_samplerate; sh_audio->i_bps=MP3_bitrate*(1000/8); MP3_PrintHeader(); break; } #ifdef HAVE_OGGVORBIS case AFM_VORBIS: { // OggVorbis Audio: #if 0 /* just here for reference - atmos */ ogg_sync_state oy; /* sync and verify incoming physical bitstream */ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the bitstream user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ #else /* nix, nada, rien, nothing, nem, nüx */ #endif uint32_t hdrsizes[3];/* stores vorbis header sizes from AVI audio header, maybe use ogg_uint32_t */ //int i; int ret; char *buffer; ogg_packet hdr; //ov_struct_t *s=&sh_audio->ov; sh_audio->ov=malloc(sizeof(ov_struct_t)); //s=&sh_audio->ov; vorbis_info_init(&sh_audio->ov->vi); vorbis_comment_init(&sh_audio->ov->vc); mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OggVorbis: cbsize: %i\n", sh_audio->wf->cbSize); memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX), 3*sizeof(uint32_t)); mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OggVorbis: Read header sizes: initial: %i comment: %i codebook: %i\n", hdrsizes[0], hdrsizes[1], hdrsizes[2]); /*for(i=12; i <= 40; i+=2) { // header bruteforce :) memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+i, 3*sizeof(uint32_t)); printf("OggVorbis: Read header sizes (%i): %ld %ld %ld\n", i, hdrsizes[0], hdrsizes[1], hdrsizes[2]); }*/ /* read headers */ // FIXME disable sound on errors here, we absolutely need this headers! - atmos hdr.packet=NULL; hdr.b_o_s = 1; /* beginning of stream for first packet */ hdr.bytes = hdrsizes[0]; hdr.packet = realloc(hdr.packet,hdr.bytes); memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t),hdr.bytes); if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0) mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: initial (identification) header broken!\n"); hdr.b_o_s = 0; hdr.bytes = hdrsizes[1]; hdr.packet = realloc(hdr.packet,hdr.bytes); memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0],hdr.bytes); if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0) mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: comment header broken!\n"); hdr.bytes = hdrsizes[2]; hdr.packet = realloc(hdr.packet,hdr.bytes); memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0]+hdrsizes[1],hdr.bytes); if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0) mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n"); hdr.bytes=0; hdr.packet = realloc(hdr.packet,hdr.bytes); /* free */ /* done with the headers */ /* Throw the comments plus a few lines about the bitstream we're decoding */ { char **ptr=sh_audio->ov->vc.user_comments; while(*ptr){ mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr); ++ptr; } mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel, %ldHz, %ldkbit/s %cBR\n",sh_audio->ov->vi.channels,sh_audio->ov->vi.rate,sh_audio->ov->vi.bitrate_nominal/1000, (sh_audio->ov->vi.bitrate_lower!=sh_audio->ov->vi.bitrate_nominal)||(sh_audio->ov->vi.bitrate_upper!=sh_audio->ov->vi.bitrate_nominal)?'V':'C'); mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",sh_audio->ov->vc.vendor); } sh_audio->channels=sh_audio->ov->vi.channels; sh_audio->samplerate=sh_audio->ov->vi.rate; sh_audio->i_bps=sh_audio->ov->vi.bitrate_nominal/8; // printf("[\n"); // sh_audio->a_buffer_len=sh_audio->audio_out_minsize;///ov->vi.channels; // printf("]\n"); /* OK, got and parsed all three headers. Initialize the Vorbis packet->PCM decoder. */ vorbis_synthesis_init(&sh_audio->ov->vd,&sh_audio->ov->vi); /* central decode state */ vorbis_block_init(&sh_audio->ov->vd,&sh_audio->ov->vb); /* local state for most of the decode so multiple block decodes can proceed in parallel. We could init multiple vorbis_block structures for vd here */ //printf("OggVorbis: synthesis and block init done.\n"); ogg_sync_init(&sh_audio->ov->oy); /* Now we can read pages */ while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) { if(ret == -1) mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: Pageout: not properly synced, had to skip some bytes.\n"); else if(ret == 0) { mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: need more data to verify page, reading more data.\n"); /* submit a a_buffer_len block to libvorbis' Ogg layer */ buffer=ogg_sync_buffer(&sh_audio->ov->oy,256); ogg_sync_wrote(&sh_audio->ov->oy,demux_read_data(sh_audio->ds,buffer,256)); } } mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: successfull.\n"); ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og); /* we can ignore any errors here as they'll also become apparent at packetout */ /* Get the serial number and set up the rest of decode. */ /* serialno first; use it to set up a logical stream */ ogg_stream_init(&sh_audio->ov->os,ogg_page_serialno(&sh_audio->ov->og)); mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n"); break; } #endif #ifdef USE_LIBMAD case AFM_MAD: { printf("%s %s %s (%s)\n", mad_version, mad_copyright, mad_author, mad_build); printf(__FILE__ ":%d:mad: initialising\n", __LINE__); mad_frame_init(&mad_frame); mad_stream_init(&mad_stream); printf(__FILE__ ":%d:mad: preparing buffer\n", __LINE__); mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size); mad_stream_buffer(&mad_stream, (unsigned char*)(sh_audio->a_in_buffer), sh_audio->a_in_buffer_len); // mad_stream_sync(&mad_stream); mad_sync(sh_audio, &mad_stream); mad_synth_init(&mad_synth); if(mad_frame_decode(&mad_frame, &mad_stream) == 0) { printf(__FILE__ ":%d:mad: post processing buffer\n", __LINE__); mad_postprocess_buffer(sh_audio, &mad_stream); } else { printf(__FILE__ ":%d:mad: frame decoding failed\n", __LINE__); mad_print_error(&mad_stream); } switch (mad_frame.header.mode) { case MAD_MODE_SINGLE_CHANNEL: sh_audio->channels=1; break; case MAD_MODE_DUAL_CHANNEL: case MAD_MODE_JOINT_STEREO: case MAD_MODE_STEREO: sh_audio->channels=2; break; default: mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "mad: unknown number of channels\n"); } mp_msg(MSGT_DECAUDIO, MSGL_HINT, "mad: channels: %d (mad channel mode: %d)\n", sh_audio->channels, mad_frame.header.mode); /* var. name changed in 0.13.0 (beta) (libmad/CHANGES) -- alex */ #if (MAD_VERSION_MAJOR >= 0) && (MAD_VERSION_MINOR >= 13) sh_audio->samplerate=mad_frame.header.samplerate; #else sh_audio->samplerate=mad_frame.header.sfreq; #endif sh_audio->i_bps=mad_frame.header.bitrate; printf(__FILE__ ":%d:mad: continuing\n", __LINE__); break; } #endif } if(!sh_audio->channels || !sh_audio->samplerate){ mp_msg(MSGT_DECAUDIO,MSGL_WARN,MSGTR_UnknownAudio); driver=0; } if(!driver){ if(sh_audio->a_buffer) free(sh_audio->a_buffer); sh_audio->a_buffer=NULL; return 0; } if(!sh_audio->o_bps) sh_audio->o_bps=sh_audio->channels*sh_audio->samplerate*sh_audio->samplesize; return driver; } // Audio decoding: // 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){ #ifdef USE_LIBAVCODEC case AFM_FFMPEG: { unsigned char *start=NULL; int y; while(len<minlen){ int len2=0; int x=ds_get_packet(sh_audio->ds,&start); if(x<=0) break; // error y=avcodec_decode_audio(&lavc_context,(INT16*)buf,&len2,start,x); if(y<0){ mp_msg(MSGT_DECAUDIO,MSGL_V,"lavc_audio: error\n");break; } if(y<x) sh_audio->ds->buffer_pos+=y-x; // put back data (HACK!) if(len2>0){ //len=len2;break; if(len<0) len=len2; else len+=len2; buf+=len2; } mp_dbg(MSGT_DECAUDIO,MSGL_DBG2,"Decoded %d -> %d \n",y,len2); } } break; #endif case AFM_MPEG: // MPEG layer 2 or 3 len=MP3_DecodeFrame(buf,-1); // len=MP3_DecodeFrame(buf,3); break; #ifdef HAVE_OGGVORBIS case AFM_VORBIS: { // OggVorbis /* note: good minlen would be 4k or 8k IMHO - atmos */ int ret; char *buffer; int bytes; int samples; float **pcm; //ogg_int16_t convbuffer[4096]; // int convsize; int readlen=1024; len=0; // convsize=minlen/sh_audio->ov->vi.channels; while(len < minlen) { /* double loop allows for break in inner loop */ while(len < minlen) { /* without aborting the outer loop - atmos */ ret=ogg_stream_packetout(&sh_audio->ov->os,&sh_audio->ov->op); if(ret==0) { int xxx=0; //printf("OggVorbis: Packetout: need more data, paging!\n"); while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) { if(ret == -1) mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: not properly synced, had to skip some bytes.\n"); else if(ret == 0) { //printf("OggVorbis: Pageout: need more data to verify page, reading more data.\n"); /* submit a readlen k block to libvorbis' Ogg layer */ buffer=ogg_sync_buffer(&sh_audio->ov->oy,readlen); bytes=demux_read_data(sh_audio->ds,buffer,readlen); xxx+=bytes; ogg_sync_wrote(&sh_audio->ov->oy,bytes); if(bytes==0) mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: 0Bytes written, possible End of Stream\n"); } } mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[sync: %d ]\n",xxx); //printf("OggVorbis: Pageout: successfull, pagin in.\n"); if(ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og)<0) mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pagein failed!\n"); break; } else if(ret<0) { mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Packetout: missing or corrupt data, skipping packet!\n"); break; } else { /* we have a packet. Decode it */ if(vorbis_synthesis(&sh_audio->ov->vb,&sh_audio->ov->op)==0) /* test for success! */ vorbis_synthesis_blockin(&sh_audio->ov->vd,&sh_audio->ov->vb); /* **pcm is a multichannel float vector. In stereo, for example, pcm[0] is left, and pcm[1] is right. samples is the size of each channel. Convert the float values (-1.<=range<=1.) to whatever PCM format and write it out */ while((samples=vorbis_synthesis_pcmout(&sh_audio->ov->vd,&pcm))>0){ int i,j; int clipflag=0; int convsize=(maxlen-len)/(2*sh_audio->ov->vi.channels); // max size! int bout=(samples<convsize?samples:convsize); if(bout<=0) break; /* convert floats to 16 bit signed ints (host order) and interleave */ for(i=0;i<sh_audio->ov->vi.channels;i++){ ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]); ogg_int16_t *ptr=convbuffer+i; float *mono=pcm[i]; for(j=0;j<bout;j++){ #if 1 int val=mono[j]*32767.f; #else /* optional dither */ int val=mono[j]*32767.f+drand48()-0.5f; #endif /* might as well guard against clipping */ if(val>32767){ val=32767; clipflag=1; } if(val<-32768){ val=-32768; clipflag=1; } *ptr=val; ptr+=sh_audio->ov->vi.channels; } } if(clipflag) mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(sh_audio->ov->vd.sequence)); //fwrite(convbuffer,2*sh_audio->ov->vi.channels,bout,stderr); //dump pcm to file for debugging //memcpy(buf+len,convbuffer,2*sh_audio->ov->vi.channels*bout); len+=2*sh_audio->ov->vi.channels*bout; mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples); vorbis_synthesis_read(&sh_audio->ov->vd,bout); /* tell libvorbis how many samples we actually consumed */ } } // from else, packetout ok } // while len } // outer while len if(ogg_page_eos(&sh_audio->ov->og)) mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: End of Stream reached!\n"); // FIXME clearup decoder, notify mplayer - atmos mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[len: %d ]\n",len); break; } #endif case AFM_PCM: // AVI PCM len=demux_read_data(sh_audio->ds,buf,minlen); break; case AFM_DVDPCM: // DVD PCM { int j; 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;j<len;j+=2){ char x=buf[j]; buf[j]=buf[j+1]; buf[j+1]=x; } break; } case AFM_ALAW: // aLaw decoder { int l=demux_read_data(sh_audio->ds,buf,minlen/2); unsigned short *d=(unsigned short *) buf; unsigned char *s=buf; len=2*l; if(sh_audio->format==6){ // aLaw while(l>0){ --l; d[l]=alaw2short[s[l]]; } } else { // uLaw while(l>0){ --l; d[l]=ulaw2short[s[l]]; } } break; } case AFM_GSM: // MS-GSM decoder { unsigned char ibuf[65]; // 65 bytes / frame if(demux_read_data(sh_audio->ds,ibuf,65)!=65) break; // EOF XA_MSGSM_Decoder(ibuf,(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; } #ifdef USE_G72X case AFM_G72X: // GSM 723 decoder { if(demux_read_data(sh_audio->ds,g72x_data.block, g72x_data.blocksize)!=g72x_data.blocksize) break; // EOF g72x_decode_block(&g72x_data); len=2*g72x_data.samplesperblock; memcpy(buf,g72x_data.samples,len); break; } #endif case AFM_IMAADPCM: { unsigned char ibuf[IMA_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame if (demux_read_data(sh_audio->ds, ibuf, IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) break; // EOF len=2*ima_adpcm_decode_block((unsigned short*)buf,ibuf, sh_audio->wf->nChannels); break; } case AFM_MSADPCM: { static unsigned char *ibuf = NULL; if (!ibuf) ibuf = (unsigned char *)malloc (sh_audio->wf->nBlockAlign * sh_audio->wf->nChannels); if (demux_read_data(sh_audio->ds, ibuf, sh_audio->wf->nBlockAlign) != sh_audio->wf->nBlockAlign) break; // EOF len= 2 * ms_adpcm_decode_block( (unsigned short*)buf,ibuf, sh_audio->wf->nChannels, sh_audio->wf->nBlockAlign); break; } case AFM_FOX61ADPCM: { unsigned char ibuf[FOX61_ADPCM_BLOCK_SIZE]; // bytes / stereo frame if (demux_read_data(sh_audio->ds, ibuf, FOX61_ADPCM_BLOCK_SIZE) != FOX61_ADPCM_BLOCK_SIZE) break; // EOF len=2*fox61_adpcm_decode_block((unsigned short*)buf,ibuf); break; } case AFM_FOX62ADPCM: { unsigned char ibuf[FOX62_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame if (demux_read_data(sh_audio->ds, ibuf, FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) break; // EOF len = 2 * fox62_adpcm_decode_block( (unsigned short*)buf,ibuf); break; } case AFM_ROQAUDIO: { static unsigned char *ibuf = NULL; unsigned char header_data[6]; int read_len; if (!ibuf) ibuf = (unsigned char *)malloc(sh_audio->audio_out_minsize / 2); // figure out how much data to read if (demux_read_data(sh_audio->ds, header_data, 6) != 6) break; // EOF read_len = (header_data[5] << 24) | (header_data[4] << 16) | (header_data[3] << 8) | header_data[2]; read_len += 2; // 16-bit arguments if (demux_read_data(sh_audio->ds, ibuf, read_len) != read_len) break; len = 2 * roq_decode_audio((unsigned short *)buf, ibuf, read_len, sh_audio->channels, sh_audio->context); break; } #ifdef USE_LIBAC3 case AFM_AC3: // AC3 decoder //printf("{1:%d}",avi_header.idx_pos);fflush(stdout); if(!sh_audio->ac3_frame) sh_audio->ac3_frame=ac3_decode_frame(); //printf("{2:%d}",avi_header.idx_pos);fflush(stdout); if(sh_audio->ac3_frame){ len = 256 * 6 *sh_audio->channels*sh_audio->samplesize; memcpy(buf,((ac3_frame_t*)sh_audio->ac3_frame)->audio_data,len); sh_audio->ac3_frame=NULL; } //printf("{3:%d}",avi_header.idx_pos);fflush(stdout); break; #endif case AFM_A52: { // AC3 decoder sample_t level=1, bias=384; int flags=a52_flags|A52_ADJUST_LEVEL; int i; if(!sh_audio->a_in_buffer_len) if(a52_fillbuff(sh_audio)<0) break; // EOF sh_audio->a_in_buffer_len=0; if (a52_frame (&a52_state, sh_audio->a_in_buffer, &flags, &level, bias)){ mp_msg(MSGT_DECAUDIO,MSGL_WARN,"a52: error decoding frame\n"); break; } // a52_dynrng (&state, NULL, NULL); // disable dynamic range compensation // frame decoded, let's resample: //a52_resample_init(a52_accel,flags,sh_audio->channels); len=0; for (i = 0; i < 6; i++) { if (a52_block (&a52_state, a52_samples)){ mp_msg(MSGT_DECAUDIO,MSGL_WARN,"a52: error at resampling\n"); break; } len+=2*a52_resample(a52_samples,&buf[len]); } // printf("len = %d \n",len); // 6144 on all vobs I tried so far... (5.1 and 2.0) ::atmos break; } case AFM_HWAC3: // AC3 through SPDIF if(!sh_audio->a_in_buffer_len) if((len=a52_fillbuff(sh_audio))<0) break; //EOF sh_audio->a_in_buffer_len=0; len = ac3_iec958_build_burst(len, 0x01, 1, sh_audio->a_in_buffer, buf); // len = 6144 = 4*(6*256) break; #ifdef USE_WIN32DLL case AFM_ACM: // len=sh_audio->audio_out_minsize; // optimal decoded fragment size // if(len<minlen) len=minlen; else // if(len>maxlen) len=maxlen; // len=acm_decode_audio(sh_audio,buf,len); len=acm_decode_audio(sh_audio,buf,minlen,maxlen); break; #endif #ifdef USE_DIRECTSHOW case AFM_DSHOW: // DirectShow { int size_in=0; int size_out=0; int srcsize=DS_AudioDecoder_GetSrcSize(ds_adec, maxlen); mp_msg(MSGT_DECAUDIO,MSGL_DBG3,"DShow says: srcsize=%d (buffsize=%d) out_size=%d\n",srcsize,sh_audio->a_in_buffer_size,maxlen); if(srcsize>sh_audio->a_in_buffer_size) srcsize=sh_audio->a_in_buffer_size; // !!!!!! if(sh_audio->a_in_buffer_len<srcsize){ sh_audio->a_in_buffer_len+= demux_read_data(sh_audio->ds,&sh_audio->a_in_buffer[sh_audio->a_in_buffer_len], srcsize-sh_audio->a_in_buffer_len); } DS_AudioDecoder_Convert(ds_adec, sh_audio->a_in_buffer,sh_audio->a_in_buffer_len, buf,maxlen, &size_in,&size_out); mp_dbg(MSGT_DECAUDIO,MSGL_DBG2,"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 { sh_audio->a_in_buffer_len-=size_in; memcpy(sh_audio->a_in_buffer,&sh_audio->a_in_buffer[size_in],sh_audio->a_in_buffer_len); } len=size_out; break; } #endif #ifdef USE_LIBMAD case AFM_MAD: { mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size); mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len); // mad_stream_sync(&mad_stream); mad_sync(sh_audio, &mad_stream); if(mad_frame_decode(&mad_frame, &mad_stream) == 0) { mad_synth_frame(&mad_synth, &mad_frame); mad_postprocess_buffer(sh_audio, &mad_stream); /* and fill buffer */ { int i; int end_size = mad_synth.pcm.length; signed short* samples = (signed short*)buf; if(end_size > maxlen/4) end_size=maxlen/4; for(i=0; i<mad_synth.pcm.length; ++i) { *samples++ = mad_scale(mad_synth.pcm.samples[0][i]); *samples++ = mad_scale(mad_synth.pcm.samples[0][i]); // *buf++ = mad_scale(mad_synth.pcm.sampAles[1][i]); } len = end_size*4; } } else { printf(__FILE__ ":%d:mad: frame decoding failed (error: %d)\n", __LINE__, mad_stream.error); mad_print_error(&mad_stream); } break; } #endif } return len; } void resync_audio_stream(sh_audio_t *sh_audio){ switch(sh_audio->codec->driver){ case AFM_MPEG: MP3_DecodeFrame(NULL,-2); // resync MP3_DecodeFrame(NULL,-2); // resync MP3_DecodeFrame(NULL,-2); // resync break; #ifdef HAVE_OGGVORBIS case AFM_VORBIS: //printf("OggVorbis: resetting stream.\n"); ogg_sync_reset(&sh_audio->ov->oy); ogg_stream_reset(&sh_audio->ov->os); break; #endif #ifdef USE_LIBAC3 case AFM_AC3: ac3_bitstream_reset(); // reset AC3 bitstream buffer // if(verbose){ printf("Resyncing AC3 audio...");fflush(stdout);} sh_audio->ac3_frame=ac3_decode_frame(); // resync // if(verbose) printf(" OK!\n"); break; #endif case AFM_A52: case AFM_ACM: case AFM_DSHOW: case AFM_HWAC3: sh_audio->a_in_buffer_len=0; // reset ACM/DShow audio buffer break; #ifdef USE_LIBMAD case AFM_MAD: mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size); mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len); // mad_stream_sync(&mad_stream); mad_sync(sh_audio, &mad_stream); mad_postprocess_buffer(sh_audio, &mad_stream); break; #endif } } void skip_audio_frame(sh_audio_t *sh_audio){ switch(sh_audio->codec->driver){ case AFM_MPEG: MP3_DecodeFrame(NULL,-2);break; // skip MPEG frame #ifdef USE_LIBAC3 case AFM_AC3: sh_audio->ac3_frame=ac3_decode_frame();break; // skip AC3 frame #endif case AFM_HWAC3: case AFM_A52: a52_fillbuff(sh_audio);break; // skip AC3 frame case AFM_ACM: case AFM_DSHOW: { int skip=sh_audio->wf->nBlockAlign; if(skip<16){ skip=(sh_audio->wf->nAvgBytesPerSec/16)&(~7); if(skip<16) skip=16; } demux_read_data(sh_audio->ds,NULL,skip); break; } case AFM_PCM: case AFM_DVDPCM: case AFM_ALAW: { int skip=sh_audio->i_bps/16; skip=skip&(~3); demux_read_data(sh_audio->ds,NULL,skip); break; } #ifdef USE_LIBMAD case AFM_MAD: { mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size); mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len); mad_stream_skip(&mad_stream, 2); // mad_stream_sync(&mad_stream); mad_sync(sh_audio, &mad_stream); mad_postprocess_buffer(sh_audio, &mad_stream); break; } #endif default: ds_fill_buffer(sh_audio->ds); // skip PCM frame } }