mp3rtp.c

Go to the documentation of this file.
00001 /* $Id: mp3rtp.c,v 1.25 2005/11/29 21:21:01 robert Exp $ */
00002 
00003 /* Still under work ..., need a client for test, where can I get one? */
00004 
00005 /* 
00006  *  experimental translation:
00007  *
00008  *  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
00009  *
00010  *  wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
00011  */
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 /* std int types already defined in config.h */
00016 #define _STDINT_H
00017 #endif
00018 
00019 #ifdef STDC_HEADERS
00020 # include <stdlib.h>
00021 # include <string.h>
00022 #else
00023 # ifndef HAVE_STRCHR
00024 #  define strchr index
00025 #  define strrchr rindex
00026 # endif
00027 char   *strchr(), *strrchr();
00028 # ifndef HAVE_MEMCPY
00029 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
00030 #  define memmove(d, s, n) bcopy ((s), (d), (n))
00031 # endif
00032 #endif
00033 
00034 #include <time.h>
00035 
00036 #ifdef HAVE_UNISTD_H
00037 # include <unistd.h>
00038 #endif
00039 
00040 #include "lame.h"
00041 #include "main.h"
00042 #include "parse.h"
00043 #include "lametime.h"
00044 #include "timestatus.h"
00045 #include "get_audio.h"
00046 #include "rtp.h"
00047 #include "console.h"
00048 
00049 #ifdef WITH_DMALLOC
00050 #include <dmalloc.h>
00051 #endif
00052 
00053 /*
00054  * Encode (via LAME) to mp3 with RTP streaming of the output.
00055  *
00056  * Author: Felix von Leitner <leitner@vim.org>
00057  *
00058  *   mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile
00059  *
00060  * examples:
00061  *   arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null
00062  *   arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
00063  *
00064  */
00065 
00066 struct rtpheader RTPheader;
00067 struct sockaddr_in rtpsi;
00068 int     rtpsocket;
00069 
00070 void
00071 rtp_output(const char *mp3buffer, const int mp3size)
00072 {
00073     sendrtp(rtpsocket, &rtpsi, &RTPheader, mp3buffer, mp3size);
00074     RTPheader.timestamp += 5;
00075     RTPheader.b.sequence++;
00076 }
00077 
00078 #if 0
00079 struct rtpheader RTPheader;
00080 SOCKET  rtpsocket;
00081 
00082 void
00083 rtp_output(char *mp3buffer, int mp3size)
00084 {
00085     rtp_send(rtpsocket, &RTPheader, mp3buffer, mp3size);
00086     RTPheader.timestamp += 5;
00087     RTPheader.b.sequence++;
00088 }
00089 #endif
00090 
00091 
00092 
00093 
00094 static unsigned int
00095 maxvalue(int Buffer[2][1152])
00096 {
00097     unsigned int max = 0;
00098     int     i;
00099 
00100     for (i = 0; i < 1152; i++) {
00101         if (abs(Buffer[0][i]) > max)
00102             max = abs(Buffer[0][i]);
00103         if (abs(Buffer[1][i]) > max)
00104             max = abs(Buffer[1][i]);
00105     }
00106     return max >> 16;
00107 }
00108 
00109 static void
00110 levelmessage(unsigned int maxv)
00111 {
00112     char    buff[] = "|  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  \r";
00113     static unsigned int max = 0;
00114     static unsigned int tmp = 0;
00115 
00116     buff[tmp] = '+';
00117     tmp = (maxv * 61 + 16384) / (32767 + 16384 / 61);
00118     if (tmp > sizeof(buff) - 2)
00119         tmp = sizeof(buff) - 2;
00120     if (max < tmp)
00121         max = tmp;
00122     buff[max] = 'x';
00123     buff[tmp] = '#';
00124     console_printf(buff);
00125     console_flush();
00126 }
00127 
00128 
00129 /************************************************************************
00130 *
00131 * main
00132 *
00133 * PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO 
00134 * psychoacoustic model.
00135 *
00136 ************************************************************************/
00137 
00138 int
00139 main(int argc, char **argv)
00140 {
00141     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
00142     char    inPath[PATH_MAX + 1];
00143     char    outPath[PATH_MAX + 1];
00144     int     Buffer[2][1152];
00145 
00146     lame_global_flags *gf;
00147 
00148     int     ret;
00149     int     wavsamples;
00150     int     mp3bytes;
00151     FILE   *outf;
00152 
00153     char    ip[16];
00154     unsigned port = 5004;
00155     unsigned ttl = 2;
00156     char    dummy;
00157 
00158     int     enc_delay = -1;
00159     int     enc_padding = -1;
00160 
00161     frontend_open_console();
00162     if (argc <= 2) {
00163         console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n"
00164                        "\n"
00165                        "    mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n"
00166                        "\n"
00167                        "    examples:\n"
00168                        "      arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n"
00169                        "      arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n"
00170                        "\n");
00171         frontend_close_console();
00172         return 1;
00173     }
00174 
00175     switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) {
00176     case 1:
00177     case 2:
00178     case 3:
00179         break;
00180     default:
00181         error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]);
00182         frontend_close_console();
00183         return -1;
00184     }
00185 
00186     rtpsocket = makesocket(ip, port, ttl, &rtpsi);
00187     srand(getpid() ^ time(NULL));
00188     initrtp(&RTPheader);
00189 
00190     /* initialize encoder */
00191     gf = lame_init();
00192     if (NULL == gf) {
00193         error_printf("fatal error during initialization\n");
00194         frontend_close_console();
00195         return 1;
00196     }
00197     lame_set_errorf(gf, &frontend_errorf);
00198     lame_set_debugf(gf, &frontend_debugf);
00199     lame_set_msgf(gf, &frontend_msgf);
00200 
00201     /* Remove the argumets that are rtp related, and then 
00202      * parse the command line arguments, setting various flags in the
00203      * struct pointed to by 'gf'.  If you want to parse your own arguments,
00204      * or call libmp3lame from a program which uses a GUI to set arguments,
00205      * skip this call and set the values of interest in the gf struct.  
00206      * (see lame.h for documentation about these parameters)
00207      */
00208 
00209     argv[1] = argv[0];
00210     parse_args(gf, argc - 1, argv + 1, inPath, outPath, NULL, NULL);
00211 
00212     /* open the output file.  Filename parsed into gf.inPath */
00213     if (0 == strcmp(outPath, "-")) {
00214         lame_set_stream_binary_mode(outf = stdout);
00215     }
00216     else {
00217         if ((outf = fopen(outPath, "wb+")) == NULL) {
00218             error_printf("Could not create \"%s\".\n", outPath);
00219             frontend_close_console();
00220             return 1;
00221         }
00222     }
00223 
00224 
00225     /* open the wav/aiff/raw pcm or mp3 input file.  This call will
00226      * open the file with name gf.inFile, try to parse the headers and
00227      * set gf.samplerate, gf.num_channels, gf.num_samples.
00228      * if you want to do your own file input, skip this call and set
00229      * these values yourself.  
00230      */
00231     init_infile(gf, inPath, &enc_delay, &enc_padding);
00232 
00233 
00234     /* Now that all the options are set, lame needs to analyze them and
00235      * set some more options 
00236      */
00237     ret = lame_init_params(gf);
00238     if (ret < 0) {
00239         if (ret == -1)
00240             display_bitrates(stderr);
00241         error_printf("fatal error during initialization\n");
00242         frontend_close_console();
00243         return -1;
00244     }
00245 
00246     lame_print_config(gf); /* print useful information about options being used */
00247 
00248     if (update_interval < 0.)
00249         update_interval = 2.;
00250 
00251     /* encode until we hit EOF */
00252     while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */
00253         levelmessage(maxvalue(Buffer));
00254         mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */
00255                                           Buffer[0], Buffer[1], wavsamples,
00256                                           mp3buffer, sizeof(mp3buffer));
00257 
00258         rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */
00259         fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */
00260     }
00261 
00262     mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */
00263                                  mp3buffer, sizeof(mp3buffer));
00264     rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */
00265     fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */
00266 
00267     lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
00268 
00269     lame_close(gf);
00270     fclose(outf);
00271     close_infile();     /* close the sound input file */
00272     frontend_close_console();
00273     return 0;
00274 }
00275 
00276 /* end of mp3rtp.c */

Generated on Sun Dec 2 11:34:18 2007 for LAME by  doxygen 1.5.2