diff options
author | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2001-10-23 12:03:41 +0000 |
---|---|---|
committer | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2001-10-23 12:03:41 +0000 |
commit | dac324322af86902eac3283e9dabf19aa0f68305 (patch) | |
tree | 5006a42a20bafc87134aa1ad4e724ca94e902c48 /dec_audio.c | |
parent | 0ec7285e2636149f1891a079c66ca7715d6f2bf6 (diff) | |
download | mpv-dac324322af86902eac3283e9dabf19aa0f68305.tar.bz2 mpv-dac324322af86902eac3283e9dabf19aa0f68305.tar.xz |
libmad (ARM) patch by jeroen.dobbelaere@acunia.com
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2416 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'dec_audio.c')
-rw-r--r-- | dec_audio.c | 149 |
1 files changed, 148 insertions, 1 deletions
diff --git a/dec_audio.c b/dec_audio.c index c6605886bc..439e93c6e7 100644 --- a/dec_audio.c +++ b/dec_audio.c @@ -63,6 +63,55 @@ typedef struct ov_struct_st { extern int avcodec_inited; #endif + + +#ifdef USE_LIBMAD +#include <mad.h> +static struct mad_stream mad_stream; +static struct mad_frame mad_frame; +static struct mad_synth mad_synth; + + +// 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; + } +} + +static void mad_postprocess_buffer(sh_audio_t* sh_audio, struct mad_stream* ms) +{ + int delta = (unsigned char*)ms->next_frame - (unsigned char *)sh_audio->a_in_buffer; + if(delta != 0) { + 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); +} +#endif + + + + + int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen); @@ -191,6 +240,17 @@ case AFM_FFMPEG: 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<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; + break; +#endif } if(!driver) return 0; @@ -488,6 +548,37 @@ case AFM_VORBIS: { break; } #endif + +#ifdef USE_LIBMAD + case AFM_MAD: + { + 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_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__); + } + + sh_audio->channels=2; // hack + sh_audio->samplerate=mad_frame.header.sfreq; + sh_audio->i_bps=mad_frame.header.bitrate; + printf(__FILE__ ":%d:mad: continuing\n", __LINE__); + break; + } +#endif } if(!sh_audio->channels || !sh_audio->samplerate){ @@ -741,6 +832,42 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){ 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); + 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\n", __LINE__); + } + + break; + } +#endif } return len; } @@ -770,8 +897,16 @@ void resync_audio_stream(sh_audio_t *sh_audio){ 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_postprocess_buffer(sh_audio, &mad_stream); + break; } - +#endif } void skip_audio_frame(sh_audio_t *sh_audio){ @@ -796,6 +931,18 @@ void skip_audio_frame(sh_audio_t *sh_audio){ 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_postprocess_buffer(sh_audio, &mad_stream); + break; + } +#endif + default: ds_fill_buffer(sh_audio->ds); // skip PCM frame } } |