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