/* XMPS - X MPEG Player System * Copyright (C) 1999 Damien Chavarria * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public Licensse as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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. */ /* * * mpg123_codec.c * * MPG123 Video Codec. * @Author Chavarria Damien. * Copyright 1999-2000 */ /********************************************************************* * INCLUDES * *********************************************************************/ #include "mpg123_codec.h" extern long freqs[9]; typedef struct { int our_stream_id; xmps_system_plugin_t *our_system; xmps_audio_info_t *audio_info; int channels; int format; int bit_count; int sample_size; int frequency; int last_result; int real_size; char out[16384]; char buffer[16384]; struct mpstr mp; } mpg123_t; /* * some functions * */ unsigned int decompress_mp3(xmps_audio_decoder_plugin_t *audio_decoder, char *outmemory, int outmemsize, int *done) { mpg123_t *data; if(audio_decoder == NULL) { return MP3_ERR; } data = (mpg123_t *) audio_decoder->data; if(data == NULL) { XMPS_DEBUG("problem!"); return MP3_ERR; } if(data->last_result == MP3_OK) { data->last_result = decodeMP3(&data->mp, NULL, 0, outmemory, outmemsize, done); if(data->last_result == MP3_NEED_MORE) { if( data->our_system->read(data->our_system, data->our_stream_id, data->buffer, 16384) != -1) { data->last_result = decodeMP3(&data->mp, data->buffer, 16384, outmemory, outmemsize, done); return 1; } else { return 0; } } else { return 1; } } else { if( data->our_system->read(data->our_system, data->our_stream_id, data->buffer, 16384) != -1) { data->last_result = decodeMP3(&data->mp, data->buffer, 16384, outmemory, outmemsize, done); return 1; } else { return 0; } } } /* * get_audio_codec_info : MANDATORY * * Used by scanplugins to get a pointer to the codec. * */ xmps_audio_decoder_plugin_t *get_audio_decoder_info(void) { xmps_audio_decoder_plugin_t *decoder; decoder = (xmps_audio_decoder_plugin_t *) malloc(sizeof(xmps_audio_decoder_plugin_t)); decoder->name = "MPG123"; decoder->data = (void *) malloc(sizeof(mpg123_t)); decoder->open = mpg123_open; decoder->get = mpg123_get; decoder->set = mpg123_set; decoder->decompress = mpg123_decompress; decoder->close = mpg123_close; ((mpg123_t *) decoder->data)->audio_info = (xmps_audio_info_t *) malloc(sizeof(xmps_audio_info_t)); return decoder; } /********************************************************************* * FUNCTIONS * *********************************************************************/ unsigned int mpg123_open(xmps_audio_decoder_plugin_t *audio_decoder) { if(audio_decoder == NULL) { return 0; } return 1; } void* mpg123_get(xmps_audio_decoder_plugin_t *audio_decoder, unsigned int flag, void *arg) { mpg123_t *data; if(audio_decoder == NULL) { return NULL; } data = (mpg123_t *) audio_decoder->data; if(data == NULL) { return NULL; } switch(flag) { case XMPS_FLAG_AUDIO_FORMAT_LIST: { GList *list = NULL; switch(data->bit_count) { case 8: data->audio_info->format.type = XMPS_AUDIO_FORMAT_U8; break; case 16: default: data->audio_info->format.type = XMPS_AUDIO_FORMAT_S16; break; } data->audio_info->format.bit_count = data->bit_count; list = g_list_prepend(list, (void *) &data->audio_info->format); return list; } break; case XMPS_FLAG_AUDIO_INFO: { data->audio_info->channels = data->channels; data->audio_info->frequency = data->frequency; switch(data->bit_count) { case 8: data->audio_info->format.type = XMPS_AUDIO_FORMAT_U8; break; case 16: default: data->audio_info->format.type = XMPS_AUDIO_FORMAT_S16; break; } data->audio_info->format.bit_count = data->bit_count; data->audio_info->sample_size = ((data->bit_count + 7) / 8)*data->channels; return data->audio_info; } break; default: break; } return NULL; } unsigned int mpg123_set(xmps_audio_decoder_plugin_t *audio_decoder, unsigned int flag, void *arg) { mpg123_t *data; if(audio_decoder == NULL) { return MP3_ERR; } data = (mpg123_t *) audio_decoder->data; if(data == NULL) { return MP3_ERR; } switch(flag) { case XMPS_FLAG_INPUT: { xmps_data_t *data_stream; XMPS_DEBUG("setting input"); data_stream = (xmps_data_t *) arg; if(data_stream == NULL) { XMPS_DEBUG("null data stream"); return 0; } if(data_stream->plugin_type != XMPS_PLUGIN_SYSTEM) { XMPS_DEBUG("wrong plugin type"); return 0; } if(data_stream->type == XMPS_DATA_AUDIO_COMP && strstr(data_stream->audio_compression, "MPG3") != NULL) { InitMP3(&data->mp); data->our_system = data_stream->plugin; data->our_stream_id = data_stream->id; data->last_result = MP3_NEED_MORE; ring_init(); /* * we bufferize some data * * */ if(decompress_mp3(audio_decoder, data->out, 16384, &data->real_size) == 0) { return 0; } switch(data->mp.fr.lay) { case 1: XMPS_DEBUG("stream is MPEG-1 Audio Layer 1"); break; case 2: XMPS_DEBUG("stream is MPEG-1 Audio Layer 2"); break; case 3: XMPS_DEBUG("stream id MPEG-1 Audio Layer 3"); break; default: XMPS_DEBUG("unknown layer!"); return 0; break; } data->frequency = freqs[data->mp.fr.sampling_frequency]; data->channels = data->mp.fr.stereo ? 2 : 1; data->bit_count = 16; XMPS_DEBUG("creating real_size (%d) buffer" , data->real_size); while(!ring_full(data->real_size)) { XMPS_DEBUG("buffering (1 frame)"); decompress_mp3(audio_decoder, data->out, 16384, &data->real_size); ring_write(data->out, data->real_size); } XMPS_DEBUG("buffering ok!"); return 1; } else { /* * try to see from the data * if we really can play it * */ XMPS_DEBUG("trying to guess from content!"); InitMP3(&data->mp); // FIX THAT data->our_system = data_stream->plugin; data->our_stream_id = data_stream->id; data->our_system->seek(data->our_system, data->our_stream_id, 0, XMPS_SEEK_SET); data->last_result = MP3_NEED_MORE; ring_init(); /* * we bufferize some data * * */ decompress_mp3(audio_decoder, data->out, 8192, &data->real_size); /* * test it * */ if(data->last_result != MP3_ERR) { switch(data->mp.fr.lay) { case 1: XMPS_DEBUG("layer 1 not supported!"); return 0; break; case 2: XMPS_DEBUG("stream is MPEG-1 Audio Layer 2"); break; case 3: XMPS_DEBUG("stream id MPEG-1 Audio Layer 3"); break; default: XMPS_DEBUG("unknown layer!"); return 0; break; } data->frequency = freqs[data->mp.fr.sampling_frequency]; data->channels = data->mp.fr.stereo ? 2 : 1; data->bit_count = 16; XMPS_DEBUG("creating real_size (%d) buffer" , data->real_size); while(!ring_full(data->real_size)) { XMPS_DEBUG("buffering (1 frame)"); decompress_mp3(audio_decoder, data->out, 16384, &data->real_size); if(data->last_result == 0) { XMPS_DEBUG("stream is not mpeg!"); return 0; } ring_write(data->out, data->real_size); } XMPS_DEBUG("buffering ok!"); } else { XMPS_DEBUG("not a mp3 data stream"); return 0; } } } break; case XMPS_FLAG_EMPTY_BUFFERS: ExitMP3(&data->mp); InitMP3(&data->mp); data->last_result = MP3_NEED_MORE; ring_init(); XMPS_DEBUG("emptying buffers"); break; default: break; } return 1; } unsigned int mpg123_decompress(xmps_audio_decoder_plugin_t *audio_decoder, void *in_buffer, void *out_buffer, unsigned int size) { mpg123_t *data; if(audio_decoder == NULL) { return MP3_ERR; } data = (mpg123_t *) audio_decoder->data; if(data == NULL) { return MP3_ERR; } if(data->our_system == NULL) { XMPS_DEBUG("null system"); return 0; } while(!ring_full(data->real_size)) { if(decompress_mp3(audio_decoder, data->out, 16384, &data->real_size) == 1) { ring_write(data->out, data->real_size); } else return 0; } /* * and give it what it wants * */ ring_read(out_buffer, size); return 1; } unsigned int mpg123_close(xmps_audio_decoder_plugin_t *audio_decoder) { mpg123_t *data; if(audio_decoder == NULL) { return MP3_ERR; } data = (mpg123_t *) audio_decoder->data; if(data == NULL) { return MP3_ERR; } data->our_system = NULL; data->our_stream_id = 0; ExitMP3(&data->mp); return 0; }