diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audio_out/audio_oss_out.c | 164 | ||||
-rw-r--r-- | src/audio_out/resample.c | 149 | ||||
-rw-r--r-- | src/libac3/ac3.h | 6 | ||||
-rw-r--r-- | src/libac3/decode.c | 35 | ||||
-rw-r--r-- | src/libac3/downmix.c | 255 | ||||
-rw-r--r-- | src/libac3/downmix.h | 3 | ||||
-rw-r--r-- | src/libac3/xine_decoder.c | 121 | ||||
-rw-r--r-- | src/libmpeg2/decode.c | 3 | ||||
-rw-r--r-- | src/libmpg123/Makefile.am | 37 | ||||
-rw-r--r-- | src/libmpg123/interface.c | 30 | ||||
-rw-r--r-- | src/libmpg123/layer1.c | 8 | ||||
-rw-r--r-- | src/libmpg123/layer2.c | 10 | ||||
-rw-r--r-- | src/libmpg123/layer3.c | 10 | ||||
-rw-r--r-- | src/libmpg123/mpg123.h | 6 | ||||
-rw-r--r-- | src/libmpg123/mpglib.h | 10 | ||||
-rw-r--r-- | src/libmpg123/xine_decoder.c | 106 | ||||
-rw-r--r-- | src/xine-engine/Makefile.am | 1 | ||||
-rw-r--r-- | src/xine-engine/load_plugins.c | 37 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 20 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 3 |
20 files changed, 842 insertions, 172 deletions
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c index 0bb47ffbb..e8a9eacca 100644 --- a/src/audio_out/audio_oss_out.c +++ b/src/audio_out/audio_oss_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_oss_out.c,v 1.6 2001/05/08 11:31:39 f1rmb Exp $ + * $Id: audio_oss_out.c,v 1.7 2001/05/27 23:48:12 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -60,6 +60,10 @@ # endif #endif +#ifndef AFMT_AC3 +# define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */ +#endif + #define AO_OUT_OSS_IFACE_VERSION 1 #define AUDIO_NUM_FRAGMENTS 15 @@ -82,6 +86,8 @@ typedef struct oss_functions_s { char audio_dev[20]; int audio_fd; + int capabilities; + int mode; int32_t output_sample_rate, input_sample_rate; int32_t output_rate_correction; @@ -111,23 +117,23 @@ static int ao_open(ao_functions_t *this_gen, { oss_functions_t *this = (oss_functions_t *) this_gen; int tmp; - int fsize; printf ("audio_oss_out: ao_open rate=%d, mode=%d\n", rate, mode); - if (((mode & AO_CAP_MODE_STEREO) == 0) && ((mode & AO_CAP_MODE_MONO) == 0)) { - printf ("OSS Driver only supports mono/stereo output modes at the moment\n"); + if ( (mode & this->capabilities) == 0 ) { + printf ("audio_oss_out: unsupported mode %08x\n", mode); return -1; } if (this->audio_fd > -1) { - if (rate == this->input_sample_rate) + if ( (mode == this->mode) && (rate == this->input_sample_rate) ) return 1; close (this->audio_fd); } - + + this->mode = mode; this->input_sample_rate = rate; this->bytes_in_buffer = 0; this->last_vpts = 0; @@ -157,8 +163,6 @@ static int ao_open(ao_functions_t *this_gen, tmp = (mode & AO_CAP_MODE_STEREO) ? 1 : 0; ioctl(this->audio_fd,SNDCTL_DSP_STEREO,&tmp); - this->num_channels = tmp+1; - xprintf (VERBOSE|AUDIO, "audio_oss_out: %d channels\n",this->num_channels); tmp = bits; ioctl(this->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp); @@ -170,12 +174,47 @@ static int ao_open(ao_functions_t *this_gen, xprintf (VERBOSE|AUDIO, "audio_oss_out: audio rate : %d requested, %d provided by device/sec\n", this->input_sample_rate, this->output_sample_rate); + /* + * set number of channels / ac3 throughput + */ + + switch (mode) { + case AO_CAP_MODE_MONO: + tmp = 1; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; + break; + case AO_CAP_MODE_STEREO: + tmp = 2; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; + break; + case AO_CAP_MODE_4CHANNEL: + tmp = 4; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; + break; + case AO_CAP_MODE_5CHANNEL: + tmp = 5; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; + break; + case AO_CAP_MODE_AC3: + tmp = AFMT_AC3; + ioctl(this->audio_fd,SNDCTL_DSP_SETFMT,&tmp); + this->num_channels = 2; /* FIXME: is this correct ? */ + break; + } + + printf ("audio_oss_out : %d channels output\n",this->num_channels); + this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate; this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 / this->input_sample_rate; this->bytes_per_kpts = this->output_sample_rate * this->num_channels * 2 * 1024 / 90000; xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 samples\n", this->audio_step); + printf ("audio_out : audio_step %d pts per 32768 samples\n", this->audio_step); this->metronom->set_audio_rate(this->metronom, this->audio_step); @@ -183,6 +222,7 @@ static int ao_open(ao_functions_t *this_gen, * audio buffer size handling */ + /* WARNING: let's hope for good defaults here... tmp=0 ; fsize = AUDIO_FRAGMENT_SIZE; while (fsize>0) { @@ -196,7 +236,7 @@ static int ao_open(ao_functions_t *this_gen, xprintf (VERBOSE|AUDIO, "Audio buffer fragment info : %x\n",tmp); ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp); - + */ return 1; } @@ -231,7 +271,7 @@ static void ao_fill_gap (oss_functions_t *this, uint32_t pts_len) { int num_bytes = pts_len * this->bytes_per_kpts / 1024; - num_bytes = (num_bytes / 4) * 4; + num_bytes = (num_bytes / (2*this->num_channels)) * (2*this->num_channels); printf ("audio_oss_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len); @@ -263,11 +303,11 @@ static void ao_write_audio_data(ao_functions_t *this_gen, int bDropPackage; uint16_t sample_buffer[8192]; - + if (this->audio_fd<0) return; - vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples); + vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples); xprintf (VERBOSE|AUDIO, "audio_oss_out: got %d samples, vpts=%d, last_vpts=%d\n", num_samples, vpts, this->last_vpts); @@ -306,6 +346,7 @@ static void ao_write_audio_data(ao_functions_t *this_gen, printf ("audio_oss_out: audio_vpts=%d <=> master_vpts=%d (diff=%d)\n", audio_vpts, master_vpts, diff); */ + /* * method 1 : resampling */ @@ -349,11 +390,34 @@ static void ao_write_audio_data(ao_functions_t *this_gen, if (!bDropPackage) { int num_output_samples = num_samples * (this->output_sample_rate + this->output_rate_correction) / this->input_sample_rate; - - audio_out_resample_stereo (output_samples, num_samples, + switch (this->mode) { + case AO_CAP_MODE_MONO: + audio_out_resample_mono (output_samples, num_samples, sample_buffer, num_output_samples); - - write(this->audio_fd, sample_buffer, num_output_samples * 2 * this->num_channels); + write(this->audio_fd, sample_buffer, num_output_samples * 2); + break; + case AO_CAP_MODE_STEREO: + audio_out_resample_stereo (output_samples, num_samples, + sample_buffer, num_output_samples); + write(this->audio_fd, sample_buffer, num_output_samples * 4); + break; + case AO_CAP_MODE_4CHANNEL: + audio_out_resample_4channel (output_samples, num_samples, + sample_buffer, num_output_samples); + write(this->audio_fd, sample_buffer, num_output_samples * 8); + break; + case AO_CAP_MODE_5CHANNEL: + audio_out_resample_5channel (output_samples, num_samples, + sample_buffer, num_output_samples); + write(this->audio_fd, sample_buffer, num_output_samples * 10); + break; + case AO_CAP_MODE_AC3: + + write(this->audio_fd, sample_buffer, num_output_samples * 2); + num_output_samples = num_samples; + + break; + } xprintf (AUDIO|VERBOSE, "audio_oss_out :audio package written\n"); @@ -386,8 +450,9 @@ static void ao_close(ao_functions_t *this_gen) this->audio_fd = -1; } -static uint32_t ao_get_capabilities (ao_functions_t *this) { - return AO_CAP_MODE_STEREO | AO_CAP_MODE_MONO; +static uint32_t ao_get_capabilities (ao_functions_t *this_gen) { + oss_functions_t *this = (oss_functions_t *) this_gen; + return this->capabilities; } static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) { @@ -457,6 +522,7 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) { int rate ; int devnum; int audio_fd; + int num_channels, status, arg; this = (oss_functions_t *) malloc (sizeof (oss_functions_t)); @@ -505,6 +571,19 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) { } else xprintf (VERBOSE|AUDIO, " %s\n", this->audio_dev); + /* + * set up driver to reasonable values for capabilities tests + */ + + arg = AFMT_S16_NE; + status = ioctl(audio_fd, SOUND_PCM_SETFMT, &arg); + arg = 44100; + status = ioctl(audio_fd, SOUND_PCM_WRITE_RATE, &arg); + + /* + * get capabilities + */ + ioctl (audio_fd, SNDCTL_DSP_GETCAPS, &caps); if ((caps & DSP_CAP_REALTIME) > 0) { @@ -513,13 +592,50 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) { xprintf (VERBOSE|AUDIO, "audio_oss_out : realtime check: *FAILED* :-(((((\n\n"); } - /* - if ((caps & DSP_CAP_TRIGGER) > 0) { - xprintf (VERBOSE|AUDIO, "audio_out : trigger check : passed :-)\n"); - } else { - xprintf (VERBOSE|AUDIO, "audio_out : trigger check : *FAILED* :-(((((\n"); + this->capabilities = 0; + + printf ("audio_oss_out : supported modes are "); + num_channels = 1; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + if ( (status != -1) && (num_channels==1) ) { + this->capabilities |= AO_CAP_MODE_MONO; + printf ("mono "); } - */ + num_channels = 2; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + if ( (status != -1) && (num_channels==2) ) { + this->capabilities |= AO_CAP_MODE_STEREO; + printf ("stereo "); + } + num_channels = 4; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + if ( (status != -1) && (num_channels==4) ) { + if (config->lookup_int (config, "four_channel", 0)) { + this->capabilities |= AO_CAP_MODE_4CHANNEL; + printf ("4-channel "); + } else + printf ("(4-channel not enabled in .xinerc) " ); + } + num_channels = 5; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + if ( (status != -1) && (num_channels==5) ) { + if (config->lookup_int (config, "five_channel", 0)) { + this->capabilities |= AO_CAP_MODE_5CHANNEL; + printf ("5-channel "); + } else + printf ("(5-channel not enabled in .xinerc) " ); + } + + ioctl(audio_fd,SNDCTL_DSP_GETFMTS,&caps); + if (caps & AFMT_AC3) { + if (config->lookup_int (config, "ac3_pass_through", 0)) { + this->capabilities |= AO_CAP_MODE_AC3; + printf ("ac3-pass-through "); + } else + printf ("(ac3-pass-through not enabled in .xinerc)"); + } + + printf ("\n"); close (audio_fd); diff --git a/src/audio_out/resample.c b/src/audio_out/resample.c index 9f464b276..158b17c59 100644 --- a/src/audio_out/resample.c +++ b/src/audio_out/resample.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: resample.c,v 1.1 2001/04/24 20:53:00 f1rmb Exp $ + * $Id: resample.c,v 1.2 2001/05/27 23:48:12 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -28,6 +28,37 @@ /* contributed by paul flinders */ +void audio_out_resample_mono(int16_t* input_samples, uint32_t in_samples, + int16_t* output_samples, uint32_t out_samples) +{ + int osample; + /* 16+16 fixed point math */ + uint32_t isample = 0; + uint32_t istep = (in_samples << 16)/out_samples; + +#ifdef VERBOSE + printf ("Audio : resample %d samples to %d\n", + in_samples, out_samples); +#endif + + for (osample = 0; osample < out_samples - 1; osample++) { + int s1; + int s2; + int16_t os; + uint32_t t = isample&0xffff; + + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ + s1 = input_samples[(isample >> 16)]; + s2 = input_samples[(isample >> 16)+1]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[osample] = os; + + isample += istep; + } + output_samples[out_samples-1] = input_samples[in_samples-1]; +} + void audio_out_resample_stereo(int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { @@ -65,3 +96,119 @@ void audio_out_resample_stereo(int16_t* input_samples, uint32_t in_samples, output_samples[out_samples*2-1] = input_samples[in_samples*2-1]; } + +void audio_out_resample_4channel(int16_t* input_samples, uint32_t in_samples, + int16_t* output_samples, uint32_t out_samples) +{ + int osample; + /* 16+16 fixed point math */ + uint32_t isample = 0; + uint32_t istep = (in_samples << 16)/out_samples; + +#ifdef VERBOSE + printf ("Audio : resample %d samples to %d\n", + in_samples, out_samples); +#endif + + for (osample = 0; osample < out_samples - 1; osample++) { + int s1; + int s2; + int16_t os; + uint32_t t = isample&0xffff; + + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ + s1 = input_samples[(isample >> 16)*4]; + s2 = input_samples[(isample >> 16)*4+4]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[osample * 4] = os; + + s1 = input_samples[(isample >> 16)*4+1]; + s2 = input_samples[(isample >> 16)*4+5]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 4 )+1] = os; + + s1 = input_samples[(isample >> 16)*4+2]; + s2 = input_samples[(isample >> 16)*4+6]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 4 )+2] = os; + + s1 = input_samples[(isample >> 16)*4+3]; + s2 = input_samples[(isample >> 16)*4+7]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 4 )+3] = os; + + isample += istep; + } + output_samples[out_samples*4-4] = input_samples[in_samples*4-4]; + output_samples[out_samples*4-3] = input_samples[in_samples*4-3]; + output_samples[out_samples*4-2] = input_samples[in_samples*4-2]; + output_samples[out_samples*4-1] = input_samples[in_samples*4-1]; + +} + + +void audio_out_resample_5channel(int16_t* input_samples, uint32_t in_samples, + int16_t* output_samples, uint32_t out_samples) +{ + int osample; + /* 16+16 fixed point math */ + uint32_t isample = 0; + uint32_t istep = (in_samples << 16)/out_samples; + +#ifdef VERBOSE + printf ("Audio : resample %d samples to %d\n", + in_samples, out_samples); +#endif + + for (osample = 0; osample < out_samples - 1; osample++) { + int s1; + int s2; + int16_t os; + uint32_t t = isample&0xffff; + + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ + s1 = input_samples[(isample >> 16)*5]; + s2 = input_samples[(isample >> 16)*5+5]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[osample * 5] = os; + + s1 = input_samples[(isample >> 16)*5+1]; + s2 = input_samples[(isample >> 16)*5+6]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 5 )+1] = os; + + s1 = input_samples[(isample >> 16)*5+2]; + s2 = input_samples[(isample >> 16)*5+7]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 5 )+2] = os; + + s1 = input_samples[(isample >> 16)*5+3]; + s2 = input_samples[(isample >> 16)*5+8]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 5 )+3] = os; + + s1 = input_samples[(isample >> 16)*5+4]; + s2 = input_samples[(isample >> 16)*5+9]; + + os = (s1 * (0x10000-t)+ s2 * t) >> 16; + output_samples[(osample * 5 )+4] = os; + + isample += istep; + } + + output_samples[out_samples*5-5] = input_samples[in_samples*5-5]; + output_samples[out_samples*5-4] = input_samples[in_samples*5-4]; + output_samples[out_samples*5-3] = input_samples[in_samples*5-3]; + output_samples[out_samples*5-2] = input_samples[in_samples*5-2]; + output_samples[out_samples*5-1] = input_samples[in_samples*5-1]; +} + + diff --git a/src/libac3/ac3.h b/src/libac3/ac3.h index 07f41c0a0..69c11b9ed 100644 --- a/src/libac3/ac3.h +++ b/src/libac3/ac3.h @@ -40,10 +40,12 @@ typedef struct ac3_config_s typedef struct ac3_frame_s { - uint32_t sampling_rate; + uint32_t sampling_rate; int16_t * audio_data; + int num_channels; } ac3_frame_t; void ac3_init(void); int ac3_frame_length(uint8_t * buf); -ac3_frame_t* ac3_decode_frame(uint8_t * buf); +int ac3_sampling_rate(uint8_t * buf); +ac3_frame_t* ac3_decode_frame(uint8_t * buf, int max_num_channels); diff --git a/src/libac3/decode.c b/src/libac3/decode.c index db0068b8d..c859525e8 100644 --- a/src/libac3/decode.c +++ b/src/libac3/decode.c @@ -53,9 +53,9 @@ static ac3_frame_t frame; //the floating point samples for one audblk static stream_samples_t samples; -//the integer samples for the entire frame (with enough space for 2 ch out) +//the integer samples for the entire frame (with enough space for 5 ch out) //if this size change, be sure to change the size when muting -static int16_t s16_samples[2 * 6 * 256]; +static int16_t s16_samples[5 * 6 * 256]; void ac3_init(void) @@ -73,11 +73,20 @@ int ac3_frame_length(uint8_t * buf) return parse_syncinfo (buf, &dummy, &dummy); } +int ac3_sampling_rate(uint8_t * buf) +{ + int dummy, rate; + + parse_syncinfo (buf, &rate, &dummy); + return rate; +} + ac3_frame_t* -ac3_decode_frame(uint8_t * buf) +ac3_decode_frame(uint8_t * buf, int max_num_channels) { uint32_t i; int dummy; + int num_channels; if (!parse_syncinfo (buf, &frame.sampling_rate, &dummy)) goto error; @@ -87,6 +96,22 @@ ac3_decode_frame(uint8_t * buf) if (parse_bsi (&state, buf)) goto error; + switch (state.acmod) { + case 7 : + case 5 : + /* case 3 : FIXME : implement downmix functions*/ + num_channels = (max_num_channels<5) ? max_num_channels : 5; + break; + case 4 : + case 6 : + num_channels = (max_num_channels<4) ? max_num_channels : 4; + break; + default: + num_channels = 2; + } + + frame.num_channels = num_channels; + if (!done_banner) { stats_print_banner (&state); done_banner = 1; @@ -118,13 +143,15 @@ ac3_decode_frame(uint8_t * buf) // Downmix into the requested number of channels // and convert floating point to int16_t - downmix(&state,samples,&s16_samples[i * 2 * 256]); + downmix(&state,samples,&s16_samples[i * num_channels * 256], + num_channels); sanity_check(&state,&audblk); if(error_flag) goto error; } + return &frame; error: diff --git a/src/libac3/downmix.c b/src/libac3/downmix.c index a50b045be..fd801308d 100644 --- a/src/libac3/downmix.c +++ b/src/libac3/downmix.c @@ -42,6 +42,54 @@ static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 }; static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0 , 0.2071 }; static void +downmix_3f_2r_to_5ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + + for (j = 0; j < 256; j++) + { + s16_samples[j * 5 ] = (int16_t) (*left++ * 32767.0f); + s16_samples[j * 5 + 1] = (int16_t) (*right++ * 32767.0f); + s16_samples[j * 5 + 2] = (int16_t) (*left_sur++ * 32767.0f); + s16_samples[j * 5 + 3] = (int16_t) (*right_sur++ * 32767.0f); + s16_samples[j * 5 + 4] = (int16_t) (*centre++ * 32767.0f); + } +} + +static void +downmix_3f_2r_to_4ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float right_tmp; + float left_tmp; + float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.5000f * *left++ + 0.500f * *centre ; + right_tmp= 0.5000f * *right++ + 0.500f * *centre++ ; + + s16_samples[j * 4 ] = (int16_t) (left_tmp * 32767.0f); + s16_samples[j * 4 + 1] = (int16_t) (right_tmp * 32767.0f); + s16_samples[j * 4 + 2] = (int16_t) (*left_sur++ * 32767.0f); + s16_samples[j * 4 + 3] = (int16_t) (*right_sur++ * 32767.0f); + } +} + +static void downmix_3f_2r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) { uint32_t j; @@ -70,6 +118,29 @@ downmix_3f_2r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_ } static void +downmix_2f_2r_to_4ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float slev; + float *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + right = samples[1]; + left_sur = samples[2]; + right_sur = samples[3]; + + slev = smixlev_lut[state->surmixlev]; + + for (j = 0; j < 256; j++) + { + s16_samples[j * 5 ] = (int16_t) (*left++ * 32767.0f); + s16_samples[j * 5 + 1] = (int16_t) (*right++ * 32767.0f); + s16_samples[j * 5 + 2] = (int16_t) (*left_sur++ * 32767.0f); + s16_samples[j * 5 + 3] = (int16_t) (*right_sur++ * 32767.0f); + } +} + +static void downmix_2f_2r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) { uint32_t j; @@ -96,6 +167,58 @@ downmix_2f_2r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_ } static void +downmix_3f_1r_to_5ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float *centre = 0, *left = 0, *right = 0, *sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + //Mono surround + sur = samples[3]; + + for (j = 0; j < 256; j++) + { + s16_samples[j * 5 ] = (int16_t) (*left++ * 32767.0f); + s16_samples[j * 5 + 1] = (int16_t) (*right++ * 32767.0f); + s16_samples[j * 5 + 2] = (int16_t) (*sur * 32767.0f); + s16_samples[j * 5 + 3] = (int16_t) (*sur++ * 32767.0f); + s16_samples[j * 5 + 4] = (int16_t) (*centre++ * 32767.0f); + } +} + +static void +downmix_3f_1r_to_4ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float right_tmp; + float left_tmp; + float clev,slev; + float *centre = 0, *left = 0, *right = 0, *sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + //Mono surround + sur = samples[3]; + + clev = cmixlev_lut[state->cmixlev]; + slev = smixlev_lut[state->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.5000f * *left++ + 0.500f * *centre ; + right_tmp= 0.5000f * *right++ + 0.500f * *centre++ ; + + s16_samples[j * 4 ] = (int16_t) (left_tmp * 32767.0f); + s16_samples[j * 4 + 1] = (int16_t) (right_tmp * 32767.0f); + s16_samples[j * 4 + 2] = (int16_t) (*sur * 32767.0f); + s16_samples[j * 4 + 3] = (int16_t) (*sur++ * 32767.0f); + } +} + +static void downmix_3f_1r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) { uint32_t j; @@ -125,6 +248,26 @@ downmix_3f_1r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_ static void +downmix_2f_1r_to_4ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +{ + uint32_t j; + float *left = 0, *right = 0, *sur = 0; + + left = samples[0]; + right = samples[1]; + //Mono surround + sur = samples[2]; + + for (j = 0; j < 256; j++) + { + s16_samples[j * 4 ] = (int16_t) (*left++ * 32767.0f); + s16_samples[j * 4 + 1] = (int16_t) (*right++ * 32767.0f); + s16_samples[j * 4 + 2] = (int16_t) (*sur * 32767.0f); + s16_samples[j * 4 + 3] = (int16_t) (*sur++ * 32767.0f); + } +} + +static void downmix_2f_1r_to_2ch(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) { uint32_t j; @@ -208,19 +351,19 @@ downmix_1f_0r_to_2ch(float *centre,int16_t *s16_samples) } // -// Downmix into 2 or 4 channels (4 ch isn't in quite yet) +// Downmix into 2 or 4 or 5 channels (4 ch isn't in quite yet) // // The downmix function names have the following format // -// downmix_Xf_Yr_to_[2|4]ch[_dolby] +// downmix_Xf_Yr_to_[2|4|5]ch[_dolby] // // where X = number of front channels // Y = number of rear channels -// [2|4] = number of output channels +// [2|4|5] = number of output channels // [_dolby] = with or without dolby surround mix // -void downmix(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) +void downmix(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples, int num_channels) { if(state->acmod > 7) dprintf("(downmix) invalid acmod number\n"); @@ -239,46 +382,74 @@ void downmix(ac3_state_t * state, stream_samples_t samples,int16_t *s16_samples) //Non-Dolby surround downmixes switch(state->acmod) { - // 3/2 - case 7: - downmix_3f_2r_to_2ch(state, samples,s16_samples); - break; - - // 2/2 - case 6: - downmix_2f_2r_to_2ch(state, samples,s16_samples); - break; - - // 3/1 - case 5: - downmix_3f_1r_to_2ch(state, samples,s16_samples); - break; - - // 2/1 - case 4: - downmix_2f_1r_to_2ch(state, samples,s16_samples); - break; - - // 3/0 - case 3: - downmix_3f_0r_to_2ch(state, samples,s16_samples); - break; - - case 2: - downmix_2f_0r_to_2ch(state, samples,s16_samples); - break; - - // 1/0 - case 1: - downmix_1f_0r_to_2ch(samples[0],s16_samples); - break; - - // 1+1 - case 0: + // 3/2 + case 7: + switch (num_channels) { + case 5: + downmix_3f_2r_to_5ch(state, samples,s16_samples); + break; + case 4: + downmix_3f_2r_to_4ch(state, samples,s16_samples); + break; + case 2: + downmix_3f_2r_to_2ch(state, samples,s16_samples); + break; + } + break; + + // 2/2 + case 6: + if (num_channels == 4) + downmix_2f_2r_to_4ch(state, samples,s16_samples); + else + downmix_2f_2r_to_2ch(state, samples,s16_samples); + break; + + // 3/1 + case 5: + + switch (num_channels) { + case 5: + downmix_3f_1r_to_5ch(state, samples,s16_samples); + break; + case 4: + downmix_3f_1r_to_4ch(state, samples,s16_samples); + break; + case 2: + downmix_3f_1r_to_2ch(state, samples,s16_samples); + break; + } + + break; + + // 2/1 + case 4: + if (num_channels == 4) + downmix_2f_1r_to_4ch(state, samples,s16_samples); + else + downmix_2f_1r_to_2ch(state, samples,s16_samples); + break; + + // 3/0 + case 3: + downmix_3f_0r_to_2ch(state, samples,s16_samples); + break; + + case 2: + downmix_2f_0r_to_2ch(state, samples,s16_samples); + break; + + // 1/0 + case 1: + downmix_1f_0r_to_2ch(samples[0],s16_samples); + break; + + // 1+1 + case 0: #if 0 - downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples); + downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples); #endif - break; + break; } } diff --git a/src/libac3/downmix.h b/src/libac3/downmix.h index 525980afb..28c6aea15 100644 --- a/src/libac3/downmix.h +++ b/src/libac3/downmix.h @@ -25,4 +25,5 @@ * */ -void downmix(ac3_state_t * state, stream_samples_t stream_samples,int16_t *s16_samples); +void downmix(ac3_state_t * state, stream_samples_t stream_samples,int16_t *s16_samples, + int num_channels); diff --git a/src/libac3/xine_decoder.c b/src/libac3/xine_decoder.c index b11987299..5b9ab7ef6 100644 --- a/src/libac3/xine_decoder.c +++ b/src/libac3/xine_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_decoder.c,v 1.2 2001/05/26 15:07:18 guenter Exp $ + * $Id: xine_decoder.c,v 1.3 2001/05/27 23:48:12 guenter Exp $ * * stuff needed to turn libac3 into a xine decoder plugin */ @@ -48,8 +48,12 @@ typedef struct ac3dec_decoder_s { uint16_t syncword; ao_functions_t *audio_out; + int audio_caps; + int bypass_mode; + int max_num_channels; int output_sampling_rate; int output_open; + int output_mode; } ac3dec_decoder_t; @@ -62,11 +66,36 @@ void ac3dec_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) { ac3dec_decoder_t *this = (ac3dec_decoder_t *) this_gen; - this->audio_out = audio_out; - ac3_init (); + this->audio_out = audio_out; + this->audio_caps = audio_out->get_capabilities(audio_out); this->syncword = 0; this->sync_todo = 6; this->output_open = 0; + + ac3_init (); + + /* + * find out if this driver supports ac3 output + * or, if not, how many channels we've got + */ + + if (this->audio_caps & AO_CAP_MODE_AC3) + this->bypass_mode = 1; + else { + this->bypass_mode = 0; + + /* find best mode */ + if (this->audio_caps & AO_CAP_MODE_5CHANNEL) + this->max_num_channels = 5; + else if (this->audio_caps & AO_CAP_MODE_4CHANNEL) + this->max_num_channels = 4; + else if (this->audio_caps & AO_CAP_MODE_STEREO) + this->max_num_channels = 2; + else { + printf ("HELP! a mono-only audio driver?!\n"); + this->max_num_channels = 1; + } + } } void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { @@ -77,6 +106,7 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { uint8_t *end = buf->content + buf->size; ac3_frame_t *ac3_frame; int sampling_rate; + int output_mode; uint8_t byte; @@ -125,30 +155,79 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { return ; } - /* now, decode this frame */ + /* + * do we want to decode this frame in software? + */ - ac3_frame = ac3_decode_frame (this->frame_buffer); + if (!this->bypass_mode) { + + /* oki, decode this frame in software*/ + + ac3_frame = ac3_decode_frame (this->frame_buffer, this->max_num_channels); + + /* determine output mode */ + switch (ac3_frame->num_channels) { + case 1: + output_mode = AO_CAP_MODE_MONO; + break; + case 2: + output_mode = AO_CAP_MODE_STEREO; + break; + case 4: + output_mode = AO_CAP_MODE_4CHANNEL; + break; + case 5: + output_mode = AO_CAP_MODE_5CHANNEL; + break; + } - /* output audio */ + /* output decoded samples */ - if (!this->output_open - || (ac3_frame->sampling_rate != this->output_sampling_rate) ) { + if (!this->output_open + || (ac3_frame->sampling_rate != this->output_sampling_rate) + || (output_mode != this->output_mode)) { - if (this->output_open) - this->audio_out->close (this->audio_out); + if (this->output_open) + this->audio_out->close (this->audio_out); + + + this->output_open = (this->audio_out->open (this->audio_out, 16, + ac3_frame->sampling_rate, + output_mode) == 1); + this->output_sampling_rate = ac3_frame->sampling_rate; + this->output_mode = output_mode; + } + + if (this->output_open) { + this->audio_out->write_audio_data (this->audio_out, + ac3_frame->audio_data, + 256*6, + this->pts); + this->pts = 0; + } + } else { + + /* + * loop through ac3 data + */ + + if (!this->output_open) { + this->output_open = (this->audio_out->open (this->audio_out, 16, + ac3_sampling_rate(this->frame_buffer), + AO_CAP_MODE_AC3) == 1); + this->output_mode - AO_CAP_MODE_AC3; + } + + + if (this->output_open) { + this->audio_out->write_audio_data (this->audio_out, + this->frame_buffer, + this->frame_length, + this->pts); + this->pts = 0; + } - this->output_open = (this->audio_out->open (this->audio_out, 16, - ac3_frame->sampling_rate, - AO_CAP_MODE_STEREO) == 1); - this->output_sampling_rate = ac3_frame->sampling_rate; - } - if (this->output_open) { - this->audio_out->write_audio_data (this->audio_out, - ac3_frame->audio_data, - 256*6, - this->pts); - this->pts = 0; } /* done with frame, prepare for next one */ diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 044f235f3..847227ebb 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -93,6 +93,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->current_frame->bFrameBad = mpeg2dec->drop_frame; if (picture->picture_coding_type == B_TYPE) { + if (picture->mpeg1) + picture->current_frame->PTS = 0; mpeg2dec->frames_to_drop = picture->current_frame->draw (picture->current_frame); picture->current_frame->free (picture->current_frame); picture->current_frame = NULL; @@ -223,6 +225,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, } picture->current_frame->PTS = mpeg2dec->pts; mpeg2dec->pts = 0; + } } diff --git a/src/libmpg123/Makefile.am b/src/libmpg123/Makefile.am index 854b992b1..04238af92 100644 --- a/src/libmpg123/Makefile.am +++ b/src/libmpg123/Makefile.am @@ -1,16 +1,41 @@ -CFLAGS = @BUILD_LIB_STATIC@ @GLOBAL_CFLAGS@ +CFLAGS = @GLOBAL_CFLAGS@ -EXTRA_DIST = main.c +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic -noinst_LTLIBRARIES = libmpg123.la +libdir = $(XINE_PLUGINDIR) -libmpg123_la_SOURCES = common.c decode_i386.c layer1.c layer3.c tabinit.c \ - dct64_i386.c interface.c layer2.c -libmpg123_la_LIBADD = -lm +lib_LTLIBRARIES = xineplug_decode_mpg123.la +xineplug_decode_mpg123_la_SOURCES = common.c decode_i386.c layer1.c layer3.c tabinit.c \ + dct64_i386.c interface.c layer2.c xine_decoder.c +xineplug_decode_mpg123_la_LDFLAGS = -avoid-version -module noinst_HEADERS = huffman.h mpg123.h mpglib.h l2tables.h + +## +## Install header files (default=$includedir/xine) +## +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(includedir)/xine + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p; \ + done + + +## +## Remove them +## +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(include_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(includedir)/xine/$$p; \ + done + + debug: $(MAKE) CFLAGS="$(DEBUG_CFLAGS)" diff --git a/src/libmpg123/interface.c b/src/libmpg123/interface.c index f02bca63b..199c89479 100644 --- a/src/libmpg123/interface.c +++ b/src/libmpg123/interface.c @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: interface.c,v 1.3 2001/05/06 16:56:01 guenter Exp $ + * $Id: interface.c,v 1.4 2001/05/27 23:48:12 guenter Exp $ */ #include <stdlib.h> @@ -53,9 +53,17 @@ mpgaudio_t *mpg_audio_init (ao_functions_t *ao_output) mp->ao_output = ao_output; + mpg_audio_reset (mp); + return mp; } +void mpg_audio_close (mpgaudio_t *mpg) { + + free (mpg); + +} + int head_check(struct mpstr *mp) { if( (mp->header & 0xffe00000) != 0xffe00000) @@ -69,16 +77,10 @@ int head_check(struct mpstr *mp) return 1; } -void mpg_audio_decode_data (metronom_t *metronom, - mpgaudio_t *mp, uint8_t *data, uint8_t *data_end, +void mpg_audio_decode_data (mpgaudio_t *mp, uint8_t *data, uint8_t *data_end, uint32_t pts) { - /* printf ("mpg123: decoding package\n"); */ - - uint32_t pts_for_package = 0; - /* pts = 0; */ - while (1) { /* sync */ if(mp->framesize == 0) { @@ -103,12 +105,10 @@ void mpg_audio_decode_data (metronom_t *metronom, mpg123_wordpointer = mp->bsspace[mp->bsnum] + 512; mp->bsnum = (mp->bsnum + 1) & 0x1; mpg123_bitindex = 0; - pts_for_package = pts; + mp->pts = pts; pts = 0; } - - /* printf ("mpg123: copying data\n"); */ /* copy data to bsspace */ while (mp->bsize<mp->framesize) { @@ -123,23 +123,21 @@ void mpg_audio_decode_data (metronom_t *metronom, if(mp->fr.error_protection) getbits(16); - /* printf ("layer : %d\n",mp->fr.lay); */ switch(mp->fr.lay) { case 1: - do_layer1(metronom, mp, pts_for_package); + do_layer1(mp); break; case 2: - do_layer2(metronom, mp, pts_for_package); + do_layer2(mp); break; case 3: - do_layer3(metronom, mp, pts_for_package); + do_layer3(mp); break; } mp->framesize_old = mp->framesize; mp->framesize = 0; mp->header = 0; - pts_for_package = 0; } } diff --git a/src/libmpg123/layer1.c b/src/libmpg123/layer1.c index b10c938fd..4db905947 100644 --- a/src/libmpg123/layer1.c +++ b/src/libmpg123/layer1.c @@ -10,8 +10,6 @@ #include "mpg123.h" -#include "metronom.h" - void I_step_one(unsigned int balloc[], unsigned int scale_index[2][SBLIMIT],struct frame *fr) { unsigned int *ba=balloc; @@ -113,7 +111,7 @@ void I_step_two(real fraction[2][SBLIMIT],unsigned int balloc[2*SBLIMIT], } } -void do_layer1(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) +void do_layer1(mpgaudio_t *mp) { int clip=0; struct frame *fr = &mp->fr; @@ -159,7 +157,9 @@ void do_layer1(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) printf ("layer1\n"); } - mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), pts); + mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), + mp->pts); + mp->pts = 0; } diff --git a/src/libmpg123/layer2.c b/src/libmpg123/layer2.c index ee5a95cef..c4230ad5d 100644 --- a/src/libmpg123/layer2.c +++ b/src/libmpg123/layer2.c @@ -8,8 +8,6 @@ #include "mpg123.h" #include "l2tables.h" -#include "metronom.h" - static int grp_3tab[32 * 3] = { 0, }; /* used: 27 */ static int grp_5tab[128 * 3] = { 0, }; /* used: 125 */ static int grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ @@ -249,7 +247,7 @@ static void II_select_table(struct frame *fr) fr->II_sblimit = sblim; } -void do_layer2(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) +void do_layer2(mpgaudio_t *mp) { int clip=0; int i,j; @@ -295,11 +293,11 @@ void do_layer2(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) stereo-1 ? AO_CAP_MODE_STEREO: AO_CAP_MODE_MONO); mp->is_output_initialized = 1; mp->sample_rate_device = fr->sample_rate; - - printf ("layer2\n"); } - mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), pts); + mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), + mp->pts); + mp->pts = 0; } diff --git a/src/libmpg123/layer3.c b/src/libmpg123/layer3.c index 89b11776d..54eacdb01 100644 --- a/src/libmpg123/layer3.c +++ b/src/libmpg123/layer3.c @@ -10,8 +10,6 @@ #include "mpglib.h" #include "huffman.h" -#include "metronom.h" - #define MPEG1 @@ -1448,7 +1446,7 @@ static void III_hybrid(mpgaudio_t *mp, /* * main layer3 handler */ -void do_layer3(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) +void do_layer3(mpgaudio_t *mp) { int gr, ch, ss,clip=0; struct frame *fr = &mp->fr; @@ -1596,6 +1594,8 @@ void do_layer3(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) } } + printf ("audio output...mp3\n"); + if ((!mp->is_output_initialized) || (mp->sample_rate_device != fr->sample_rate)) { if (mp->is_output_initialized) @@ -1609,5 +1609,7 @@ void do_layer3(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts) printf ("layer3\n"); } - mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), pts); + mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2), + mp->pts); + mp->pts = 0; } diff --git a/src/libmpg123/mpg123.h b/src/libmpg123/mpg123.h index fc7709201..61166e85e 100644 --- a/src/libmpg123/mpg123.h +++ b/src/libmpg123/mpg123.h @@ -110,9 +110,9 @@ extern unsigned char *mpg123_wordpointer; extern int mpg123_bitindex; extern void make_decode_tables(long scaleval); -extern void do_layer3(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts); -extern void do_layer2(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts); -extern void do_layer1(metronom_t *metronom, mpgaudio_t *mp, uint32_t pts); +extern void do_layer3(mpgaudio_t *mp); +extern void do_layer2(mpgaudio_t *mp); +extern void do_layer1(mpgaudio_t *mp); extern int decode_header(struct frame *fr,unsigned long newhead); diff --git a/src/libmpg123/mpglib.h b/src/libmpg123/mpglib.h index 961851235..94d412893 100644 --- a/src/libmpg123/mpglib.h +++ b/src/libmpg123/mpglib.h @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mpglib.h,v 1.3 2001/05/06 16:56:01 guenter Exp $ + * $Id: mpglib.h,v 1.4 2001/05/27 23:48:12 guenter Exp $ */ #ifndef HAVE_MPGLIB_H @@ -27,7 +27,6 @@ #include <inttypes.h> #include "audio_out.h" -#include "metronom.h" typedef struct mpstr { unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ @@ -47,6 +46,8 @@ typedef struct mpstr { int sample_rate_device; ao_functions_t *ao_output; unsigned char osspace[8192]; + + uint32_t pts; } mpgaudio_t; #ifndef BOOL @@ -61,10 +62,11 @@ mpgaudio_t *mpg_audio_init (ao_functions_t *ao_output); void mpg_audio_reset (mpgaudio_t *mp); -void mpg_audio_decode_data (metronom_t *metronom, - mpgaudio_t *mp, uint8_t *data, uint8_t *data_end, +void mpg_audio_decode_data (mpgaudio_t *mp, uint8_t *data, uint8_t *data_end, uint32_t pts); +void mpg_audio_close (mpgaudio_t *mp); + #ifdef __cplusplus } #endif diff --git a/src/libmpg123/xine_decoder.c b/src/libmpg123/xine_decoder.c new file mode 100644 index 000000000..8508dcd24 --- /dev/null +++ b/src/libmpg123/xine_decoder.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_decoder.c,v 1.1 2001/05/27 23:48:12 guenter Exp $ + * + * stuff needed to turn libmpg123 into a xine decoder plugin + */ + +/* + * FIXME: libmpg123 uses global variables (that are written to) + */ + + +#include <stdlib.h> + +#include "audio_out.h" +#include "mpg123.h" +#include "mpglib.h" +#include "buffer.h" +#include "xine_internal.h" + +#define FRAME_SIZE 4096 + +typedef struct mpgdec_decoder_s { + audio_decoder_t audio_decoder; + + uint32_t pts; + + mpgaudio_t *mpg; + + ao_functions_t *audio_out; + int output_sampling_rate; + int output_open; + +} mpgdec_decoder_t; + +int mpgdec_can_handle (audio_decoder_t *this_gen, int buf_type) { + return ((buf_type & 0xFFFF0000) == BUF_AUDIO_MPEG) ; +} + + +void mpgdec_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) { + + mpgdec_decoder_t *this = (mpgdec_decoder_t *) this_gen; + + this->audio_out = audio_out; + this->mpg = mpg_audio_init (audio_out); +} + +void mpgdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { + + mpgdec_decoder_t *this = (mpgdec_decoder_t *) this_gen; + + mpg_audio_decode_data (this->mpg, buf->content, buf->content + buf->size, + buf->PTS); +} + +void mpgdec_close (audio_decoder_t *this_gen) { + + mpgdec_decoder_t *this = (mpgdec_decoder_t *) this_gen; + + mpg_audio_close (this->mpg); + + if (this->output_open) + this->audio_out->close (this->audio_out); +} + +static char *mpgdec_get_id(void) { + return "mpgdec"; +} + +audio_decoder_t *init_audio_decoder_plugin (int iface_version, config_values_t *cfg) { + + mpgdec_decoder_t *this ; + + if (iface_version != 1) + return NULL; + + this = (mpgdec_decoder_t *) malloc (sizeof (mpgdec_decoder_t)); + + this->audio_decoder.interface_version = 1; + this->audio_decoder.can_handle = mpgdec_can_handle; + this->audio_decoder.init = mpgdec_init; + this->audio_decoder.decode_data = mpgdec_decode_data; + this->audio_decoder.close = mpgdec_close; + this->audio_decoder.get_identifier = mpgdec_get_id; + + return (audio_decoder_t *) this; +} + diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 915e33677..b2442c571 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -11,7 +11,6 @@ libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c monitor.c \ audio_decoder.c video_out.c libxine_la_DEPENDENCIES = libsdeps libxine_la_LIBADD = \ - $(top_srcdir)/src/libmpg123/libmpg123.la \ ## $(top_srcdir)/src/libspudec/libspudec.la \ $(THREAD_LIBS) \ $(DYNAMIC_LD_LIBS) diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 79e7486ae..0b073881a 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: load_plugins.c,v 1.18 2001/05/03 00:02:42 f1rmb Exp $ + * $Id: load_plugins.c,v 1.19 2001/05/27 23:48:12 guenter Exp $ * * * Load input/demux/audio_out/video_out/codec plugins @@ -87,8 +87,8 @@ void load_demux_plugins (xine_t *this, sprintf (str, "%s/%s", XINE_PLUGINDIR, pEntry->d_name); if(!(plugin = dlopen (str, RTLD_LAZY))) { - fprintf(stderr, "%s(%d): %s doesn't seem to be installed (%s)\n", - __FILE__, __LINE__, str, dlerror()); + fprintf(stderr, "load_plugins: cannot open demux plugin %s:\n%s\n", + str, dlerror()); exit(1); } else { @@ -100,10 +100,8 @@ void load_demux_plugins (xine_t *this, dxp = (demux_plugin_t *) initplug(iface_version, config); this->demuxer_plugins[this->num_demuxer_plugins] = dxp; - printf("demux plugin found : %s(ID: %s, iface: %d)\n", - str, - this->demuxer_plugins[this->num_demuxer_plugins]->get_identifier(), - this->demuxer_plugins[this->num_demuxer_plugins]->interface_version); + printf("load_plugins: demux plugin found : %s\n", + this->demuxer_plugins[this->num_demuxer_plugins]->get_identifier()); this->num_demuxer_plugins++; } @@ -164,10 +162,8 @@ void load_input_plugins (xine_t *this, sprintf (str, "%s/%s", XINE_PLUGINDIR, pEntry->d_name); - printf ("load_plugins: trying to load input plugin >%s<\n",str); - if(!(plugin = dlopen (str, RTLD_LAZY))) { - printf("load_plugins: cannot open input plugin %s: %s\n", + printf("load_plugins: cannot open input plugin %s:\n%s\n", str, dlerror()); } else { void *(*initplug) (int, config_values_t *); @@ -178,10 +174,8 @@ void load_input_plugins (xine_t *this, ip = (input_plugin_t *) initplug(iface_version, config); this->input_plugins[this->num_input_plugins] = ip; - printf("load_plugins: input plugin found : %s(ID: %s, iface: %d)\n", - str, - this->input_plugins[this->num_input_plugins]->get_identifier(this->input_plugins[this->num_input_plugins]), - this->input_plugins[this->num_input_plugins]->interface_version); + printf("load_plugins: input plugin found : %s\n", + this->input_plugins[this->num_input_plugins]->get_identifier(this->input_plugins[this->num_input_plugins])); this->num_input_plugins++; } else { @@ -435,9 +429,8 @@ void load_decoder_plugins (xine_t *this, this->video_decoder_plugins[streamtype] = vdp; } - printf("video decoder plugin found : %s (ID: %s, iface: %d)\n", - pEntry->d_name, vdp->get_identifier(), - vdp->interface_version); + printf("video decoder plugin found : %s\n", + vdp->get_identifier()); } @@ -514,8 +507,8 @@ char **xine_list_video_output_plugins (int visual_type) { if(!(plugin = dlopen (str, RTLD_LAZY))) { - /* printf("load_plugins: cannot load plugin %s (%s)\n", - str, dlerror()); */ + printf("load_plugins: cannot load plugin %s:\n%s\n", + str, dlerror()); } else { @@ -585,7 +578,7 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config, sprintf (str, "%s/%s", XINE_PLUGINDIR, dir_entry->d_name); if(!(plugin = dlopen (str, RTLD_LAZY))) { - printf("load_plugins: video output plugin %s failed to link: %s\n", + printf("load_plugins: video output plugin %s failed to link:\n%s\n", str, dlerror()); return NULL; } else { @@ -604,7 +597,7 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config, if (vod) printf("load_plugins: video output plugin %s successfully" - " loaded.\n", str); + " loaded.\n", id); else printf("load_plugins: video output plugin %s: " "init_video_out_plugin failed.\n", str); @@ -750,7 +743,7 @@ ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, if (aod) printf("load_plugins: audio output plugin %s successfully" - " loaded.\n", str); + " loaded.\n", id); else printf("load_plugins: audio output plugin %s: " "init_audio_out_plugin failed.\n", str); diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index bcb4b80fd..24adfba3f 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: metronom.c,v 1.5 2001/05/24 21:41:28 guenter Exp $ + * $Id: metronom.c,v 1.6 2001/05/27 23:48:12 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -36,9 +36,9 @@ #include "metronom.h" #include "utils.h" -#define MAX_PTS_TOLERANCE 5000 -#define MAX_VIDEO_DELTA 1600 -#define AUDIO_SAMPLE_NUM 32768 +#define MAX_PTS_TOLERANCE 5000 +#define MAX_VIDEO_DELTA 1600 +#define AUDIO_SAMPLE_NUM 32768 #define MAX_WRAP_TOLERANCE 180000 static void metronom_reset (metronom_t *this) { @@ -106,6 +106,8 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { pthread_mutex_lock (&this->lock); + /* pts = 0; */ + if (pts) { /* @@ -142,7 +144,6 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { this->video_pts_delta = 0; this->num_video_vpts_guessed = 0; - /* printf ("delta: %d\n", this->video_pts_delta); */ } /* @@ -163,11 +164,12 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { this->video_vpts, synced_vpts, vpts_diff, this->video_pts_delta); if (abs(vpts_diff)>MAX_PTS_TOLERANCE) { - if (synced_vpts>this->video_vpts) { + if ( synced_vpts>this->video_vpts ) { this->video_vpts = synced_vpts; } - } else + } else { xprintf (METRONOM | VERBOSE, "metronom: video tolerating diff\n"); + } } else xprintf (METRONOM | VERBOSE, "metronom: video not synced on this one\n"); @@ -314,7 +316,7 @@ static uint32_t metronom_get_current_time (metronom_t *this) { pts += this->start_pts; if (this->stopped || (this->last_pts > pts)) { - //printf("tm_current_pts(): timer STOPPED!\n"); + /* printf("metronom: get_current_time(): timer STOPPED!\n"); */ pts = this->last_pts; } @@ -355,7 +357,7 @@ static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts) delta = desired_pts; delta -= current_time; this->start_pts += delta; - /* printf("adjusting start_pts to %d\n", this->start_pts); */ + printf("adjusting start_pts to %d\n", this->start_pts); pthread_mutex_unlock (&this->lock); } diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 543e141fb..ce6092a0d 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.9 2001/05/26 00:48:47 guenter Exp $ + * $Id: video_out.c,v 1.10 2001/05/27 23:48:12 guenter Exp $ * */ @@ -360,7 +360,6 @@ static int vo_frame_draw (vo_frame_t *img) { xprintf (VERBOSE|VIDEO,"video_out: got image. vpts for picture is %d\n", pic_vpts); - /* printf ("video_out: got image. vpts for picture is %d\n", pic_vpts); */ cur_vpts = this->metronom->get_current_time(this->metronom); |