You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sems/apps/mp3/mp3.c

414 lines
12 KiB

/*
* $Id$
*
* Copyright (C) 2002-2003 Fhg Fokus
*
* This file is part of sems, a free SIP media server.
*
* sems 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
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* sems 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
*/
#include "amci.h"
#include "codecs.h"
#include "log.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "lame.h"
#ifdef WITH_MPG123DECODER
#include "mpg123.h"
#endif
/**
* @file apps/mp3/mp3.c
* lame-MP3 support
* This plug-in writes MP3 files using lame encoder.
*
* See http://lame.sourceforge.net/ .
*
* If WITH_MPG123DECODER=yes (default), mpg123 mp3 decoding is supported as well.
*
*/
#define MP3_phone 1
static int MP3_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf,
unsigned int size, unsigned int channels, unsigned int rate,
long h_codec );
static int MP3_ModuleLoad(void);
static void MP3_ModuleDestroy(void);
static int Pcm16_2_MP3( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
unsigned int channels, unsigned int rate, long h_codec );
static long MP3_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
static void MP3_destroy(long h_inst);
static int MP3_open(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec);
static int MP3_close(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec,
struct amci_codec_t *codec);
static unsigned int mp3_bytes2samples(long h_codec, unsigned int num_bytes);
static unsigned int mp3_samples2bytes(long h_codec, unsigned int num_samples);
BEGIN_EXPORTS( "mp3", MP3_ModuleLoad, MP3_ModuleDestroy )
BEGIN_CODECS
CODEC( CODEC_MP3, Pcm16_2_MP3, MP3_2_Pcm16, (amci_plc_t)0, (amci_codec_init_t)MP3_create, (amci_codec_destroy_t)MP3_destroy, mp3_bytes2samples, mp3_samples2bytes)
END_CODECS
BEGIN_PAYLOADS
END_PAYLOADS
BEGIN_FILE_FORMATS
BEGIN_FILE_FORMAT( "MP3", "mp3", "audio/x-mp3", MP3_open, MP3_close, 0, 0)
BEGIN_SUBTYPES
SUBTYPE( MP3_phone, "MP3", 8000, 1, CODEC_MP3 )
END_SUBTYPES
END_FILE_FORMAT
END_FILE_FORMATS
END_EXPORTS
int MP3_ModuleLoad(void) {
#ifdef WITH_MPG123DECODER
int res;
if ((res = mpg123_init()) != MPG123_OK) {
ERROR("initializing mpg123 failed: %d\n", res);
return -1;
}
#endif
DBG("MP3 module loaded.\n");
return 0;
}
void MP3_ModuleDestroy(void) {
#ifdef WITH_MPG123DECODER
mpg123_exit();
#endif
DBG("MP3 module destroyed.\n");
}
#define MP3_FRAMESAMPLES 1152
/* for 128kbit 44.1 khz FrameSize = 144 * BitRate / (SampleRate + Padding) */
#define MP3_MAXFRAMEBYTES 417
#define DECODED_BUF_SIZE MP3_FRAMESAMPLES * 2 * 2 // space for two decoded frames
#define CODED_BUF_SIZE MP3_MAXFRAMEBYTES * 2 // space for two encoded frames
typedef struct {
lame_global_flags* gfp;
#ifdef WITH_MPG123DECODER
mpg123_handle* mpg123_h;
long rate;
int channels, enc;
/* unsigned char decoded_buf[DECODED_BUF_SIZE]; */
/* size_t decoded_begin; */
/* size_t decoded_end; */
/* unsigned char coded_buf[CODED_BUF_SIZE]; */
/* size_t coded_pos; */
#endif
} mp3_coder_state;
void no_output(const char *format, va_list ap)
{
return;
// (void) vfprintf(stdout, format, ap);
}
long MP3_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) {
mp3_coder_state* coder_state;
int ret_code;
coder_state = malloc(sizeof(mp3_coder_state));
if (!coder_state) {
ERROR("no memory for allocating mp3 coder state\n");
return -1;
}
DBG("MP3: creating lame %s\n", get_lame_version());
format_description[0].id = 0;
coder_state->gfp = lame_init();
if (!coder_state->gfp) {
ERROR("initialiting lame\n");
free(coder_state);
return -1;
}
lame_set_errorf(coder_state->gfp, &no_output);
lame_set_debugf(coder_state->gfp, &no_output);
lame_set_msgf(coder_state->gfp, &no_output);
lame_set_num_channels(coder_state->gfp,1);
lame_set_in_samplerate(coder_state->gfp,8000);
lame_set_brate(coder_state->gfp,16);
lame_set_mode(coder_state->gfp,3); // mono
lame_set_quality(coder_state->gfp,2); /* 2=high 5 = medium 7=low */
id3tag_init(coder_state->gfp);
id3tag_set_title(coder_state->gfp, "mp3 voicemail by iptel.org");
ret_code = lame_init_params(coder_state->gfp);
if (ret_code < 0) {
ERROR("lame encoder init failed: return code is %d\n", ret_code);
free(coder_state);
return -1;
}
#ifdef WITH_MPG123DECODER
coder_state->mpg123_h = mpg123_new(NULL, NULL);
if (!coder_state->mpg123_h) {
ERROR("initializing mpg123 decoder instance\n");
return -1;
}
/* suppress output */
mpg123_param(coder_state->mpg123_h, MPG123_FLAGS, MPG123_QUIET /* | MPG123_FORCE_MONO */,0);
/* mpg123_param(coder_state->mpg123_h, MPG123_VERBOSE, 0, 0); */
#endif
return (long)coder_state;
}
void MP3_destroy(long h_inst) {
if (h_inst){
if (((mp3_coder_state*)h_inst)->gfp)
lame_close(((mp3_coder_state*)h_inst)->gfp);
#ifdef WITH_MPG123DECODER
mpg123_delete(((mp3_coder_state*)h_inst)->mpg123_h);
#endif
free((mp3_coder_state*)h_inst);
}
}
static int Pcm16_2_MP3( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
unsigned int channels, unsigned int rate, long h_codec )
{
if (!h_codec){
ERROR("MP3 codec not initialized.\n");
return 0;
}
if ((channels!=1)||(rate!=8000)) {
ERROR("Unsupported input format for MP3 encoder.\n");
return 0;
}
/* DBG("h_codec=0x%lx; in_buf=0x%lx; size=%i\n", */
/* (unsigned long)h_codec,(unsigned long)in_buf,size); */
int ret = lame_encode_buffer(((mp3_coder_state*)h_codec)->gfp,
(short*) in_buf, // left channel
/* (short*) in_buf */0, // right channel
size / 2 , // no of samples (size is in bytes!)
out_buf,
AUDIO_BUFFER_SIZE);
switch(ret){
// 0 is valid: if not enough samples for an mp3
//frame lame will not return anything
case 0: /*DBG("lame_encode_buffer returned 0\n");*/ break;
case -1: ERROR("mp3buf was too small\n"); break;
case -2: ERROR("malloc() problem\n"); break;
case -3: ERROR("lame_init_params() not called\n"); break;
case -4: ERROR("psycho acoustic problems. uh!\n"); break;
}
return ret;
}
static unsigned int mp3_samples2bytes(long h_codec, unsigned int num_samples)
{
#ifndef WITH_MPG123DECODER
return num_samples;
#else
/*
* 150 bytes is about one frame as produced by the mp3 writer.
* for higher bitrate files this will only introduce the small performance
* penalty of multiple read() calls per frame-decode.
*/
return 150;
/* or a full frame? */
/* we don't know bitrate - so use 128000 as max bitrate */
/* 144 * BitRate / (SampleRate + Padding) */
/* unsigned int res = 144 * 128000 / (((mp3_coder_state*)h_codec)->rate + 1); */
/* if (res > AUDIO_BUFFER_SIZE) */
/* res = AUDIO_BUFFER_SIZE; */
/* return res; */
#endif
}
static int MP3_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
unsigned int channels, unsigned int rate,
long h_codec )
{
#ifndef WITH_MPG123DECODER
ERROR("MP3 decoding support not compiled in.\n");
return -1;
#else
int res;
size_t decoded_size;
mp3_coder_state* coder_state;
if (!h_codec) {
ERROR("mp3 decoder not initialized!\n");
return -1;
}
coder_state = (mp3_coder_state*)h_codec;
res = mpg123_decode(coder_state->mpg123_h, in_buf, size,
out_buf, AUDIO_BUFFER_SIZE, &decoded_size);
if (res == MPG123_NEW_FORMAT) {
WARN("intermediate mp3 file format change!\n");
}
if (res == MPG123_ERR) {
ERROR("decoding mp3: '%s'\n",
mpg123_strerror(coder_state->mpg123_h));
return -1;
}
/* DBG("mp3: decoded %d\n", decoded_size); */
return decoded_size;
#endif
}
#define SAFE_READ(buf,s,fp,sr) \
sr = fread(buf,s,1,fp);\
if((sr != 1) || ferror(fp)) return -1;
#define SAFE_WRITE(buf,s,fp) \
fwrite(buf,s,1,fp);\
if(ferror(fp)) return -1;
static int MP3_open(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec)
{
#ifdef WITH_MPG123DECODER
unsigned char mp_rd_buf[20];
size_t sr, decoded_size;
mp3_coder_state* coder_state;
int res;
DBG("mp3_open.\n");
#endif
if(options == AMCI_RDONLY){
#ifndef WITH_MPG123DECODER
ERROR("MP3 decoding support not compiled in.\n");
return -1;
#else
if (!h_codec) {
ERROR("mp3 decoder not initialized!\n");
return -1;
}
coder_state = (mp3_coder_state*)h_codec;
DBG("Initializing mpg123 codec state.\n");
res = mpg123_open_feed(coder_state->mpg123_h);
if (MPG123_ERR == res) {
ERROR("mpg123_open_feed returned mpg123 error '%s'\n",
mpg123_strerror(coder_state->mpg123_h));
return -1;
}
/* read until we know the format */
while (res!= MPG123_NEW_FORMAT) {
SAFE_READ(mp_rd_buf, 20, fp, sr);
res = mpg123_decode(coder_state->mpg123_h, mp_rd_buf, 20,
mp_rd_buf, 0, &decoded_size);
if (res == MPG123_ERR) {
ERROR("trying to determine MP3 file format: '%s'\n",
mpg123_strerror(coder_state->mpg123_h));
return -1;
}
}
mpg123_getformat(coder_state->mpg123_h,
&coder_state->rate, &coder_state->channels, &coder_state->enc);
DBG("mpg123: New format: %li Hz, %i channels, encoding value %i\n",
coder_state->rate, coder_state->channels, coder_state->enc);
fmt_desc->subtype = 1; // ?
fmt_desc->rate = coder_state->rate;
fmt_desc->channels = coder_state->channels;
fmt_desc->data_size = -1;
/* set buffering parameters */
fmt_desc->buffer_size = MP3_FRAMESAMPLES * 8;
fmt_desc->buffer_thresh = MP3_FRAMESAMPLES;
fmt_desc->buffer_full_thresh = MP3_FRAMESAMPLES * 3;
return 0;
#endif
}
return 0;
}
static int MP3_close(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec,
struct amci_codec_t *codec)
{
int final_samples;
unsigned char mp3buffer[7200];
DBG("MP3: close. \n");
if(options == AMCI_WRONLY) {
if (!h_codec || !((mp3_coder_state*)h_codec)->gfp) {
ERROR("no valid codec handle!\n");
return -1;
}
if ((final_samples = lame_encode_flush(((mp3_coder_state*)h_codec)->gfp,mp3buffer, 7200))) {
fwrite(mp3buffer, 1, final_samples, fp);
DBG("MP3: flushing %d bytes from MP3 encoder.\n", final_samples);
}
lame_mp3_tags_fid(((mp3_coder_state*)h_codec)->gfp,fp);
}
return 0;
}
static unsigned int mp3_bytes2samples(long h_codec, unsigned int num_bytes)
{
// even though we are using CBR (16kbps) and encoding
// 128kbps to 16kbps would give num_samples/8 (or num_bytes*8)
// as MP3 is not used as payload calculating this would make no
// sense. The whole frame is encoded anyway.
// WARN("size calculation not possible with MP3 codec.\n");
return num_bytes;
}