xref: /third_party/lame/frontend/mp3rtp.c (revision 159b3361)
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