1/* 2 * mp3rtp command line frontend program 3 * 4 * initially contributed by Felix von Leitner 5 * 6 * Copyright (c) 2000 Mark Taylor 7 * 2010 Robert Hegemann 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public 20 * License along with this library; if not, write to the 21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 * Boston, MA 02111-1307, USA. 23 */ 24 25/* $Id$ */ 26 27/* Still under work ..., need a client for test, where can I get one? */ 28 29/* An audio player named Zinf (aka freeamp) can play rtp streams */ 30 31/* 32 * experimental translation: 33 * 34 * gcc -I..\include -I..\libmp3lame -o mp3rtp mp3rtp.c ../libmp3lame/libmp3lame.a lametime.c get_audio.c ieeefloat.c timestatus.c parse.c rtp.c -lm 35 * 36 * wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 37 */ 38 39#ifdef HAVE_CONFIG_H 40# include <config.h> 41#endif 42 43#ifdef HAVE_STDINT_H 44# include <stdint.h> 45#endif 46 47#ifdef STDC_HEADERS 48# include <stdlib.h> 49# include <string.h> 50#endif 51 52#include <time.h> 53 54#ifdef HAVE_UNISTD_H 55# include <unistd.h> 56#endif 57 58#include "lame.h" 59#include "main.h" 60#include "parse.h" 61#include "lametime.h" 62#include "timestatus.h" 63#include "get_audio.h" 64#include "rtp.h" 65#include "console.h" 66 67#ifdef WITH_DMALLOC 68#include <dmalloc.h> 69#endif 70 71/* 72 * Encode (via LAME) to mp3 with RTP streaming of the output. 73 * 74 * Author: Felix von Leitner <leitner@vim.org> 75 * 76 * mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile 77 * 78 * examples: 79 * arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null 80 * arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 81 * 82 */ 83 84 85static unsigned int 86maxvalue(int Buffer[2][1152]) 87{ 88 int max = 0; 89 int i; 90 91 for (i = 0; i < 1152; i++) { 92 if (abs(Buffer[0][i]) > max) 93 max = abs(Buffer[0][i]); 94 if (abs(Buffer[1][i]) > max) 95 max = abs(Buffer[1][i]); 96 } 97 return max >> 16; 98} 99 100static void 101levelmessage(unsigned int maxv, int* maxx, int* tmpx) 102{ 103 char buff[] = "| . | . | . | . | . | . | . | . | . | . | \r"; 104 int tmp = *tmpx, max = *maxx; 105 106 buff[tmp] = '+'; 107 tmp = (maxv * 61 + 16384) / (32767 + 16384 / 61); 108 if (tmp > sizeof(buff) - 2) 109 tmp = sizeof(buff) - 2; 110 if (max < tmp) 111 max = tmp; 112 buff[max] = 'x'; 113 buff[tmp] = '#'; 114 console_printf(buff); 115 console_flush(); 116 *maxx = max; 117 *tmpx = tmp; 118} 119 120 121/************************************************************************ 122* 123* main 124* 125* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO 126* psychoacoustic model. 127* 128************************************************************************/ 129 130int 131lame_main(lame_t gf, int argc, char **argv) 132{ 133 unsigned char mp3buffer[LAME_MAXMP3BUFFER]; 134 char inPath[PATH_MAX + 1]; 135 char outPath[PATH_MAX + 1]; 136 int Buffer[2][1152]; 137 138 int maxx = 0, tmpx = 0; 139 int ret; 140 int wavsamples; 141 int mp3bytes; 142 FILE *outf; 143 144 char ip[16]; 145 unsigned int port = 5004; 146 unsigned int ttl = 2; 147 char dummy; 148 149 if (argc <= 2) { 150 console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n" 151 "\n" 152 " mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n" 153 "\n" 154 " examples:\n" 155 " arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n" 156 " arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n" 157 "\n"); 158 return 1; 159 } 160 161 switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) { 162 case 1: 163 case 2: 164 case 3: 165 break; 166 default: 167 error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]); 168 return -1; 169 } 170 rtp_initialization(); 171 if (rtp_socket(ip, port, ttl)) { 172 rtp_deinitialization(); 173 error_printf("fatal error during initialization\n"); 174 return 1; 175 } 176 177 lame_set_errorf(gf, &frontend_errorf); 178 lame_set_debugf(gf, &frontend_debugf); 179 lame_set_msgf(gf, &frontend_msgf); 180 181 /* Remove the argumets that are rtp related, and then 182 * parse the command line arguments, setting various flags in the 183 * struct pointed to by 'gf'. If you want to parse your own arguments, 184 * or call libmp3lame from a program which uses a GUI to set arguments, 185 * skip this call and set the values of interest in the gf struct. 186 * (see lame.h for documentation about these parameters) 187 */ 188 { 189 int i; 190 int argc_mod = argc-1; /* leaving out exactly one argument */ 191 char** argv_mod = calloc(argc_mod, sizeof(char*)); 192 argv_mod[0] = argv[0]; 193 for (i = 2; i < argc; ++i) { /* leaving out argument number 1, parsed above */ 194 argv_mod[i-1] = argv[i]; 195 } 196 parse_args(gf, argc_mod, argv_mod, inPath, outPath, NULL, NULL); 197 free(argv_mod); 198 } 199 200 /* open the output file. Filename parsed into gf.inPath */ 201 if (0 == strcmp(outPath, "-")) { 202 lame_set_stream_binary_mode(outf = stdout); 203 } 204 else { 205 if ((outf = lame_fopen(outPath, "wb+")) == NULL) { 206 rtp_deinitialization(); 207 error_printf("Could not create \"%s\".\n", outPath); 208 return 1; 209 } 210 } 211 212 213 /* open the wav/aiff/raw pcm or mp3 input file. This call will 214 * open the file with name gf.inFile, try to parse the headers and 215 * set gf.samplerate, gf.num_channels, gf.num_samples. 216 * if you want to do your own file input, skip this call and set 217 * these values yourself. 218 */ 219 if (init_infile(gf, inPath) < 0) { 220 rtp_deinitialization(); 221 fclose(outf); 222 error_printf("Can't init infile '%s'\n", inPath); 223 return 1; 224 } 225 226 227 /* Now that all the options are set, lame needs to analyze them and 228 * set some more options 229 */ 230 ret = lame_init_params(gf); 231 if (ret < 0) { 232 if (ret == -1) 233 display_bitrates(stderr); 234 rtp_deinitialization(); 235 fclose(outf); 236 close_infile(); 237 error_printf("fatal error during initialization\n"); 238 return -1; 239 } 240 241 lame_print_config(gf); /* print useful information about options being used */ 242 243 if (global_ui_config.update_interval < 0.) 244 global_ui_config.update_interval = 2.; 245 246 /* encode until we hit EOF */ 247 while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */ 248 levelmessage(maxvalue(Buffer), &maxx, &tmpx); 249 mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */ 250 Buffer[0], Buffer[1], wavsamples, 251 mp3buffer, sizeof(mp3buffer)); 252 rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ 253 fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ 254 } 255 256 mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */ 257 mp3buffer, sizeof(mp3buffer)); 258 rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ 259 fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ 260 261 lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */ 262 263 rtp_deinitialization(); 264 fclose(outf); 265 close_infile(); /* close the sound input file */ 266 return 0; 267} 268 269/* end of mp3rtp.c */ 270