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: mp3rtp.c,v 1.37 2017/08/24 20:43:10 robert Exp $ */
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
85 static unsigned int
maxvalue(int Buffer[2][1152])86 maxvalue(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
100 static void
levelmessage(unsigned int maxv,int * maxx,int * tmpx)101 levelmessage(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
130 int
lame_main(lame_t gf,int argc,char ** argv)131 lame_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