/* $Id: mp3rtp.c,v 1.22 2004/12/31 11:26:25 takehiro Exp $ */
/* Still under work ..., need a client for test, where can I get one? */
/*
* experimental translation:
*
* gcc -I..\include -I..\libmp3lame -o mp3rtp mp3rtp.c ../libmp3lame/libmp3lame.a lametime.c get_audio.c portableio.c ieeefloat.c timestatus.c parse.c rtp.c -lm
*
* wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else
# ifndef HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr (), *strrchr ();
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#include <time.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "lame.h"
#include "main.h"
#include "parse.h"
#include "lametime.h"
#include "timestatus.h"
#include "get_audio.h"
#include "rtp.h"
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif
/*
* Encode (via LAME) to mp3 with RTP streaming of the output.
*
* Author: Felix von Leitner <leitner@vim.org>
*
* mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile
*
* examples:
* arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null
* arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
*
*/
struct rtpheader RTPheader;
struct sockaddr_in rtpsi;
int rtpsocket;
void rtp_output ( const char* mp3buffer, const int mp3size )
{
sendrtp (rtpsocket, &rtpsi, &RTPheader, mp3buffer, mp3size);
RTPheader.timestamp += 5;
RTPheader.b.sequence++;
}
#if 0
struct rtpheader RTPheader;
SOCKET rtpsocket;
void rtp_output (char *mp3buffer, int mp3size)
{
rtp_send (rtpsocket, &RTPheader,mp3buffer,mp3size) ;
RTPheader.timestamp+=5;
RTPheader.b.sequence++;
}
#endif
unsigned int maxvalue ( int Buffer [2] [1152] )
{
unsigned int max = 0;
int i;
for ( i = 0; i < 1152; i++ ) {
if ( abs (Buffer[0][i]) > max ) max = abs (Buffer[0][i]);
if ( abs (Buffer[1][i]) > max ) max = abs (Buffer[1][i]);
}
return max;
}
void levelmessage ( unsigned int maxvalue )
{
char buff[] = "| . | . | . | . | . | . | . | . | . | . | \r";
static int max = 0;
static int tmp = 0;
buff [tmp] = '+';
tmp = (maxvalue*61 + 16384) / (32767 + 16384/61);
if (tmp > sizeof(buff)-2)
tmp = sizeof(buff)-2;
if (max < tmp)
max = tmp;
buff [max] = 'x';
buff [tmp] = '#';
fwrite ( buff, 1, sizeof(buff)-1, stderr );
}
/************************************************************************
*
* main
*
* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO
* psychoacoustic model.
*
************************************************************************/
int main ( int argc, char **argv )
{
unsigned char mp3buffer [LAME_MAXMP3BUFFER];
char inPath [PATH_MAX + 1];
char outPath [PATH_MAX + 1];
int Buffer [2] [1152];
lame_global_flags *gf;
int ret;
int wavsamples;
int mp3bytes;
FILE* outf;
char ip [16];
unsigned port = 5004;
unsigned ttl = 2;
char dummy;
if ( argc <= 2 ) {
fprintf ( stderr,
"Encode (via LAME) to mp3 with RTP streaming of the output\n"
"\n"
" mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n"
"\n"
" examples:\n"
" arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n"
" arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n"
"\n" );
return 1;
}
switch (sscanf ( argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy )) {
case 1:
case 2:
case 3:
break;
default:
fprintf (stderr, "Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1] );
return -1;
}
rtpsocket = makesocket ( ip, port, ttl, &rtpsi );
srand ( getpid () ^ time (NULL) );
initrtp ( &RTPheader );
/* initialize encoder */
gf=lame_init();
/* Remove the argumets that are rtp related, and then
* parse the command line arguments, setting various flags in the
* struct pointed to by 'gf'. If you want to parse your own arguments,
* or call libmp3lame from a program which uses a GUI to set arguments,
* skip this call and set the values of interest in the gf struct.
* (see lame.h for documentation about these parameters)
*/
argv[1] = argv[0];
parse_args(gf, argc - 1, argv + 1, inPath, outPath,NULL,NULL);
/* open the output file. Filename parsed into gf.inPath */
if ( 0 == strcmp ( outPath, "-" ) ) {
lame_set_stream_binary_mode (outf = stdout);
}
else {
if ((outf = fopen (outPath, "wb+")) == NULL) {
fprintf (stderr, "Could not create \"%s\".\n", outPath);
return 1;
}
}
/* open the wav/aiff/raw pcm or mp3 input file. This call will
* open the file with name gf.inFile, try to parse the headers and
* set gf.samplerate, gf.num_channels, gf.num_samples.
* if you want to do your own file input, skip this call and set
* these values yourself.
*/
init_infile(gf,inPath);
/* Now that all the options are set, lame needs to analyze them and
* set some more options
*/
ret = lame_init_params(gf);
if ( ret < 0 ) {
if (ret == -1) display_bitrates (stderr);
fprintf (stderr, "fatal error during initialization\n");
return -1;
}
lame_print_config(gf); /* print useful information about options being used */
if (update_interval < 0.)
update_interval = 2.;
/* encode until we hit EOF */
while ( (wavsamples = get_audio(gf, Buffer)) > 0 ) { /* read in 'wavsamples' samples */
levelmessage ( maxvalue (Buffer) );
mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */
Buffer[0], Buffer[1], wavsamples,
mp3buffer, sizeof (mp3buffer) );
rtp_output ( mp3buffer, mp3bytes ); /* write MP3 output to RTP port */
fwrite ( mp3buffer, 1, mp3bytes, outf ); /* write the MP3 output to file */
}
mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */
mp3buffer, sizeof (mp3buffer) );
rtp_output ( mp3buffer, mp3bytes ); /* write MP3 output to RTP port */
fwrite ( mp3buffer, 1, mp3bytes, outf ); /* write the MP3 output to file */
lame_mp3_tags_fid(gf, outf ); /* add VBR tags to mp3 file */
lame_close(gf);
fclose(outf);
close_infile(); /* close the sound input file */
return 0;
}
/* end of mp3rtp.c */