1159b3361Sopenharmony_ci/* 2159b3361Sopenharmony_ci * mp3rtp command line frontend program 3159b3361Sopenharmony_ci * 4159b3361Sopenharmony_ci * initially contributed by Felix von Leitner 5159b3361Sopenharmony_ci * 6159b3361Sopenharmony_ci * Copyright (c) 2000 Mark Taylor 7159b3361Sopenharmony_ci * 2010 Robert Hegemann 8159b3361Sopenharmony_ci * 9159b3361Sopenharmony_ci * This library is free software; you can redistribute it and/or 10159b3361Sopenharmony_ci * modify it under the terms of the GNU Library General Public 11159b3361Sopenharmony_ci * License as published by the Free Software Foundation; either 12159b3361Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 13159b3361Sopenharmony_ci * 14159b3361Sopenharmony_ci * This library is distributed in the hope that it will be useful, 15159b3361Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16159b3361Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17159b3361Sopenharmony_ci * Library General Public License for more details. 18159b3361Sopenharmony_ci * 19159b3361Sopenharmony_ci * You should have received a copy of the GNU Library General Public 20159b3361Sopenharmony_ci * License along with this library; if not, write to the 21159b3361Sopenharmony_ci * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22159b3361Sopenharmony_ci * Boston, MA 02111-1307, USA. 23159b3361Sopenharmony_ci */ 24159b3361Sopenharmony_ci 25159b3361Sopenharmony_ci/* $Id$ */ 26159b3361Sopenharmony_ci 27159b3361Sopenharmony_ci/* Still under work ..., need a client for test, where can I get one? */ 28159b3361Sopenharmony_ci 29159b3361Sopenharmony_ci/* An audio player named Zinf (aka freeamp) can play rtp streams */ 30159b3361Sopenharmony_ci 31159b3361Sopenharmony_ci/* 32159b3361Sopenharmony_ci * experimental translation: 33159b3361Sopenharmony_ci * 34159b3361Sopenharmony_ci * 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 35159b3361Sopenharmony_ci * 36159b3361Sopenharmony_ci * wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 37159b3361Sopenharmony_ci */ 38159b3361Sopenharmony_ci 39159b3361Sopenharmony_ci#ifdef HAVE_CONFIG_H 40159b3361Sopenharmony_ci# include <config.h> 41159b3361Sopenharmony_ci#endif 42159b3361Sopenharmony_ci 43159b3361Sopenharmony_ci#ifdef HAVE_STDINT_H 44159b3361Sopenharmony_ci# include <stdint.h> 45159b3361Sopenharmony_ci#endif 46159b3361Sopenharmony_ci 47159b3361Sopenharmony_ci#ifdef STDC_HEADERS 48159b3361Sopenharmony_ci# include <stdlib.h> 49159b3361Sopenharmony_ci# include <string.h> 50159b3361Sopenharmony_ci#endif 51159b3361Sopenharmony_ci 52159b3361Sopenharmony_ci#include <time.h> 53159b3361Sopenharmony_ci 54159b3361Sopenharmony_ci#ifdef HAVE_UNISTD_H 55159b3361Sopenharmony_ci# include <unistd.h> 56159b3361Sopenharmony_ci#endif 57159b3361Sopenharmony_ci 58159b3361Sopenharmony_ci#include "lame.h" 59159b3361Sopenharmony_ci#include "main.h" 60159b3361Sopenharmony_ci#include "parse.h" 61159b3361Sopenharmony_ci#include "lametime.h" 62159b3361Sopenharmony_ci#include "timestatus.h" 63159b3361Sopenharmony_ci#include "get_audio.h" 64159b3361Sopenharmony_ci#include "rtp.h" 65159b3361Sopenharmony_ci#include "console.h" 66159b3361Sopenharmony_ci 67159b3361Sopenharmony_ci#ifdef WITH_DMALLOC 68159b3361Sopenharmony_ci#include <dmalloc.h> 69159b3361Sopenharmony_ci#endif 70159b3361Sopenharmony_ci 71159b3361Sopenharmony_ci/* 72159b3361Sopenharmony_ci * Encode (via LAME) to mp3 with RTP streaming of the output. 73159b3361Sopenharmony_ci * 74159b3361Sopenharmony_ci * Author: Felix von Leitner <leitner@vim.org> 75159b3361Sopenharmony_ci * 76159b3361Sopenharmony_ci * mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile 77159b3361Sopenharmony_ci * 78159b3361Sopenharmony_ci * examples: 79159b3361Sopenharmony_ci * arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null 80159b3361Sopenharmony_ci * arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 81159b3361Sopenharmony_ci * 82159b3361Sopenharmony_ci */ 83159b3361Sopenharmony_ci 84159b3361Sopenharmony_ci 85159b3361Sopenharmony_cistatic unsigned int 86159b3361Sopenharmony_cimaxvalue(int Buffer[2][1152]) 87159b3361Sopenharmony_ci{ 88159b3361Sopenharmony_ci int max = 0; 89159b3361Sopenharmony_ci int i; 90159b3361Sopenharmony_ci 91159b3361Sopenharmony_ci for (i = 0; i < 1152; i++) { 92159b3361Sopenharmony_ci if (abs(Buffer[0][i]) > max) 93159b3361Sopenharmony_ci max = abs(Buffer[0][i]); 94159b3361Sopenharmony_ci if (abs(Buffer[1][i]) > max) 95159b3361Sopenharmony_ci max = abs(Buffer[1][i]); 96159b3361Sopenharmony_ci } 97159b3361Sopenharmony_ci return max >> 16; 98159b3361Sopenharmony_ci} 99159b3361Sopenharmony_ci 100159b3361Sopenharmony_cistatic void 101159b3361Sopenharmony_cilevelmessage(unsigned int maxv, int* maxx, int* tmpx) 102159b3361Sopenharmony_ci{ 103159b3361Sopenharmony_ci char buff[] = "| . | . | . | . | . | . | . | . | . | . | \r"; 104159b3361Sopenharmony_ci int tmp = *tmpx, max = *maxx; 105159b3361Sopenharmony_ci 106159b3361Sopenharmony_ci buff[tmp] = '+'; 107159b3361Sopenharmony_ci tmp = (maxv * 61 + 16384) / (32767 + 16384 / 61); 108159b3361Sopenharmony_ci if (tmp > sizeof(buff) - 2) 109159b3361Sopenharmony_ci tmp = sizeof(buff) - 2; 110159b3361Sopenharmony_ci if (max < tmp) 111159b3361Sopenharmony_ci max = tmp; 112159b3361Sopenharmony_ci buff[max] = 'x'; 113159b3361Sopenharmony_ci buff[tmp] = '#'; 114159b3361Sopenharmony_ci console_printf(buff); 115159b3361Sopenharmony_ci console_flush(); 116159b3361Sopenharmony_ci *maxx = max; 117159b3361Sopenharmony_ci *tmpx = tmp; 118159b3361Sopenharmony_ci} 119159b3361Sopenharmony_ci 120159b3361Sopenharmony_ci 121159b3361Sopenharmony_ci/************************************************************************ 122159b3361Sopenharmony_ci* 123159b3361Sopenharmony_ci* main 124159b3361Sopenharmony_ci* 125159b3361Sopenharmony_ci* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO 126159b3361Sopenharmony_ci* psychoacoustic model. 127159b3361Sopenharmony_ci* 128159b3361Sopenharmony_ci************************************************************************/ 129159b3361Sopenharmony_ci 130159b3361Sopenharmony_ciint 131159b3361Sopenharmony_cilame_main(lame_t gf, int argc, char **argv) 132159b3361Sopenharmony_ci{ 133159b3361Sopenharmony_ci unsigned char mp3buffer[LAME_MAXMP3BUFFER]; 134159b3361Sopenharmony_ci char inPath[PATH_MAX + 1]; 135159b3361Sopenharmony_ci char outPath[PATH_MAX + 1]; 136159b3361Sopenharmony_ci int Buffer[2][1152]; 137159b3361Sopenharmony_ci 138159b3361Sopenharmony_ci int maxx = 0, tmpx = 0; 139159b3361Sopenharmony_ci int ret; 140159b3361Sopenharmony_ci int wavsamples; 141159b3361Sopenharmony_ci int mp3bytes; 142159b3361Sopenharmony_ci FILE *outf; 143159b3361Sopenharmony_ci 144159b3361Sopenharmony_ci char ip[16]; 145159b3361Sopenharmony_ci unsigned int port = 5004; 146159b3361Sopenharmony_ci unsigned int ttl = 2; 147159b3361Sopenharmony_ci char dummy; 148159b3361Sopenharmony_ci 149159b3361Sopenharmony_ci if (argc <= 2) { 150159b3361Sopenharmony_ci console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n" 151159b3361Sopenharmony_ci "\n" 152159b3361Sopenharmony_ci " mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n" 153159b3361Sopenharmony_ci "\n" 154159b3361Sopenharmony_ci " examples:\n" 155159b3361Sopenharmony_ci " arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n" 156159b3361Sopenharmony_ci " arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n" 157159b3361Sopenharmony_ci "\n"); 158159b3361Sopenharmony_ci return 1; 159159b3361Sopenharmony_ci } 160159b3361Sopenharmony_ci 161159b3361Sopenharmony_ci switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) { 162159b3361Sopenharmony_ci case 1: 163159b3361Sopenharmony_ci case 2: 164159b3361Sopenharmony_ci case 3: 165159b3361Sopenharmony_ci break; 166159b3361Sopenharmony_ci default: 167159b3361Sopenharmony_ci error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]); 168159b3361Sopenharmony_ci return -1; 169159b3361Sopenharmony_ci } 170159b3361Sopenharmony_ci rtp_initialization(); 171159b3361Sopenharmony_ci if (rtp_socket(ip, port, ttl)) { 172159b3361Sopenharmony_ci rtp_deinitialization(); 173159b3361Sopenharmony_ci error_printf("fatal error during initialization\n"); 174159b3361Sopenharmony_ci return 1; 175159b3361Sopenharmony_ci } 176159b3361Sopenharmony_ci 177159b3361Sopenharmony_ci lame_set_errorf(gf, &frontend_errorf); 178159b3361Sopenharmony_ci lame_set_debugf(gf, &frontend_debugf); 179159b3361Sopenharmony_ci lame_set_msgf(gf, &frontend_msgf); 180159b3361Sopenharmony_ci 181159b3361Sopenharmony_ci /* Remove the argumets that are rtp related, and then 182159b3361Sopenharmony_ci * parse the command line arguments, setting various flags in the 183159b3361Sopenharmony_ci * struct pointed to by 'gf'. If you want to parse your own arguments, 184159b3361Sopenharmony_ci * or call libmp3lame from a program which uses a GUI to set arguments, 185159b3361Sopenharmony_ci * skip this call and set the values of interest in the gf struct. 186159b3361Sopenharmony_ci * (see lame.h for documentation about these parameters) 187159b3361Sopenharmony_ci */ 188159b3361Sopenharmony_ci { 189159b3361Sopenharmony_ci int i; 190159b3361Sopenharmony_ci int argc_mod = argc-1; /* leaving out exactly one argument */ 191159b3361Sopenharmony_ci char** argv_mod = calloc(argc_mod, sizeof(char*)); 192159b3361Sopenharmony_ci argv_mod[0] = argv[0]; 193159b3361Sopenharmony_ci for (i = 2; i < argc; ++i) { /* leaving out argument number 1, parsed above */ 194159b3361Sopenharmony_ci argv_mod[i-1] = argv[i]; 195159b3361Sopenharmony_ci } 196159b3361Sopenharmony_ci parse_args(gf, argc_mod, argv_mod, inPath, outPath, NULL, NULL); 197159b3361Sopenharmony_ci free(argv_mod); 198159b3361Sopenharmony_ci } 199159b3361Sopenharmony_ci 200159b3361Sopenharmony_ci /* open the output file. Filename parsed into gf.inPath */ 201159b3361Sopenharmony_ci if (0 == strcmp(outPath, "-")) { 202159b3361Sopenharmony_ci lame_set_stream_binary_mode(outf = stdout); 203159b3361Sopenharmony_ci } 204159b3361Sopenharmony_ci else { 205159b3361Sopenharmony_ci if ((outf = lame_fopen(outPath, "wb+")) == NULL) { 206159b3361Sopenharmony_ci rtp_deinitialization(); 207159b3361Sopenharmony_ci error_printf("Could not create \"%s\".\n", outPath); 208159b3361Sopenharmony_ci return 1; 209159b3361Sopenharmony_ci } 210159b3361Sopenharmony_ci } 211159b3361Sopenharmony_ci 212159b3361Sopenharmony_ci 213159b3361Sopenharmony_ci /* open the wav/aiff/raw pcm or mp3 input file. This call will 214159b3361Sopenharmony_ci * open the file with name gf.inFile, try to parse the headers and 215159b3361Sopenharmony_ci * set gf.samplerate, gf.num_channels, gf.num_samples. 216159b3361Sopenharmony_ci * if you want to do your own file input, skip this call and set 217159b3361Sopenharmony_ci * these values yourself. 218159b3361Sopenharmony_ci */ 219159b3361Sopenharmony_ci if (init_infile(gf, inPath) < 0) { 220159b3361Sopenharmony_ci rtp_deinitialization(); 221159b3361Sopenharmony_ci fclose(outf); 222159b3361Sopenharmony_ci error_printf("Can't init infile '%s'\n", inPath); 223159b3361Sopenharmony_ci return 1; 224159b3361Sopenharmony_ci } 225159b3361Sopenharmony_ci 226159b3361Sopenharmony_ci 227159b3361Sopenharmony_ci /* Now that all the options are set, lame needs to analyze them and 228159b3361Sopenharmony_ci * set some more options 229159b3361Sopenharmony_ci */ 230159b3361Sopenharmony_ci ret = lame_init_params(gf); 231159b3361Sopenharmony_ci if (ret < 0) { 232159b3361Sopenharmony_ci if (ret == -1) 233159b3361Sopenharmony_ci display_bitrates(stderr); 234159b3361Sopenharmony_ci rtp_deinitialization(); 235159b3361Sopenharmony_ci fclose(outf); 236159b3361Sopenharmony_ci close_infile(); 237159b3361Sopenharmony_ci error_printf("fatal error during initialization\n"); 238159b3361Sopenharmony_ci return -1; 239159b3361Sopenharmony_ci } 240159b3361Sopenharmony_ci 241159b3361Sopenharmony_ci lame_print_config(gf); /* print useful information about options being used */ 242159b3361Sopenharmony_ci 243159b3361Sopenharmony_ci if (global_ui_config.update_interval < 0.) 244159b3361Sopenharmony_ci global_ui_config.update_interval = 2.; 245159b3361Sopenharmony_ci 246159b3361Sopenharmony_ci /* encode until we hit EOF */ 247159b3361Sopenharmony_ci while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */ 248159b3361Sopenharmony_ci levelmessage(maxvalue(Buffer), &maxx, &tmpx); 249159b3361Sopenharmony_ci mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */ 250159b3361Sopenharmony_ci Buffer[0], Buffer[1], wavsamples, 251159b3361Sopenharmony_ci mp3buffer, sizeof(mp3buffer)); 252159b3361Sopenharmony_ci rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ 253159b3361Sopenharmony_ci fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ 254159b3361Sopenharmony_ci } 255159b3361Sopenharmony_ci 256159b3361Sopenharmony_ci mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */ 257159b3361Sopenharmony_ci mp3buffer, sizeof(mp3buffer)); 258159b3361Sopenharmony_ci rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ 259159b3361Sopenharmony_ci fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ 260159b3361Sopenharmony_ci 261159b3361Sopenharmony_ci lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */ 262159b3361Sopenharmony_ci 263159b3361Sopenharmony_ci rtp_deinitialization(); 264159b3361Sopenharmony_ci fclose(outf); 265159b3361Sopenharmony_ci close_infile(); /* close the sound input file */ 266159b3361Sopenharmony_ci return 0; 267159b3361Sopenharmony_ci} 268159b3361Sopenharmony_ci 269159b3361Sopenharmony_ci/* end of mp3rtp.c */ 270