Blame frontend/mp3rtp.c

Packit 47f805
/*
Packit 47f805
 *      mp3rtp command line frontend program
Packit 47f805
 *
Packit 47f805
 *      initially contributed by Felix von Leitner
Packit 47f805
 *
Packit 47f805
 *      Copyright (c) 2000 Mark Taylor
Packit 47f805
 *                    2010 Robert Hegemann
Packit 47f805
 *
Packit 47f805
 * This library is free software; you can redistribute it and/or
Packit 47f805
 * modify it under the terms of the GNU Library General Public
Packit 47f805
 * License as published by the Free Software Foundation; either
Packit 47f805
 * version 2 of the License, or (at your option) any later version.
Packit 47f805
 *
Packit 47f805
 * This library is distributed in the hope that it will be useful,
Packit 47f805
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 47f805
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 47f805
 * Library General Public License for more details.
Packit 47f805
 *
Packit 47f805
 * You should have received a copy of the GNU Library General Public
Packit 47f805
 * License along with this library; if not, write to the
Packit 47f805
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 47f805
 * Boston, MA 02111-1307, USA.
Packit 47f805
 */
Packit 47f805
Packit 47f805
/* $Id: mp3rtp.c,v 1.37 2017/08/24 20:43:10 robert Exp $ */
Packit 47f805
Packit 47f805
/* Still under work ..., need a client for test, where can I get one? */
Packit 47f805
Packit 47f805
/* An audio player named Zinf (aka freeamp) can play rtp streams */
Packit 47f805
Packit 47f805
/* 
Packit 47f805
 *  experimental translation:
Packit 47f805
 *
Packit 47f805
 *  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
Packit 47f805
 *
Packit 47f805
 *  wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
Packit 47f805
 */
Packit 47f805
Packit 47f805
#ifdef HAVE_CONFIG_H
Packit 47f805
# include <config.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef HAVE_STDINT_H
Packit 47f805
# include <stdint.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef STDC_HEADERS
Packit 47f805
# include <stdlib.h>
Packit 47f805
# include <string.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include <time.h>
Packit 47f805
Packit 47f805
#ifdef HAVE_UNISTD_H
Packit 47f805
# include <unistd.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include "lame.h"
Packit 47f805
#include "main.h"
Packit 47f805
#include "parse.h"
Packit 47f805
#include "lametime.h"
Packit 47f805
#include "timestatus.h"
Packit 47f805
#include "get_audio.h"
Packit 47f805
#include "rtp.h"
Packit 47f805
#include "console.h"
Packit 47f805
Packit 47f805
#ifdef WITH_DMALLOC
Packit 47f805
#include <dmalloc.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
/*
Packit 47f805
 * Encode (via LAME) to mp3 with RTP streaming of the output.
Packit 47f805
 *
Packit 47f805
 * Author: Felix von Leitner <leitner@vim.org>
Packit 47f805
 *
Packit 47f805
 *   mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile
Packit 47f805
 *
Packit 47f805
 * examples:
Packit 47f805
 *   arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null
Packit 47f805
 *   arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3
Packit 47f805
 *
Packit 47f805
 */
Packit 47f805
Packit 47f805
Packit 47f805
static unsigned int
Packit 47f805
maxvalue(int Buffer[2][1152])
Packit 47f805
{
Packit 47f805
    int     max = 0;
Packit 47f805
    int     i;
Packit 47f805
Packit 47f805
    for (i = 0; i < 1152; i++) {
Packit 47f805
        if (abs(Buffer[0][i]) > max)
Packit 47f805
            max = abs(Buffer[0][i]);
Packit 47f805
        if (abs(Buffer[1][i]) > max)
Packit 47f805
            max = abs(Buffer[1][i]);
Packit 47f805
    }
Packit 47f805
    return max >> 16;
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
levelmessage(unsigned int maxv, int* maxx, int* tmpx)
Packit 47f805
{
Packit 47f805
    char    buff[] = "|  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  \r";
Packit 47f805
    int     tmp = *tmpx, max = *maxx;
Packit 47f805
Packit 47f805
    buff[tmp] = '+';
Packit 47f805
    tmp = (maxv * 61 + 16384) / (32767 + 16384 / 61);
Packit 47f805
    if (tmp > sizeof(buff) - 2)
Packit 47f805
        tmp = sizeof(buff) - 2;
Packit 47f805
    if (max < tmp)
Packit 47f805
        max = tmp;
Packit 47f805
    buff[max] = 'x';
Packit 47f805
    buff[tmp] = '#';
Packit 47f805
    console_printf(buff);
Packit 47f805
    console_flush();
Packit 47f805
    *maxx = max;
Packit 47f805
    *tmpx = tmp;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
*
Packit 47f805
* main
Packit 47f805
*
Packit 47f805
* PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO 
Packit 47f805
* psychoacoustic model.
Packit 47f805
*
Packit 47f805
************************************************************************/
Packit 47f805
Packit 47f805
int
Packit 47f805
lame_main(lame_t gf, int argc, char **argv)
Packit 47f805
{
Packit 47f805
    unsigned char mp3buffer[LAME_MAXMP3BUFFER];
Packit 47f805
    char    inPath[PATH_MAX + 1];
Packit 47f805
    char    outPath[PATH_MAX + 1];
Packit 47f805
    int     Buffer[2][1152];
Packit 47f805
Packit 47f805
    int     maxx = 0, tmpx = 0;
Packit 47f805
    int     ret;
Packit 47f805
    int     wavsamples;
Packit 47f805
    int     mp3bytes;
Packit 47f805
    FILE   *outf;
Packit 47f805
Packit 47f805
    char    ip[16];
Packit 47f805
    unsigned int port = 5004;
Packit 47f805
    unsigned int ttl = 2;
Packit 47f805
    char    dummy;
Packit 47f805
Packit 47f805
    if (argc <= 2) {
Packit 47f805
        console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n"
Packit 47f805
                       "\n"
Packit 47f805
                       "    mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n"
Packit 47f805
                       "\n"
Packit 47f805
                       "    examples:\n"
Packit 47f805
                       "      arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n"
Packit 47f805
                       "      arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n"
Packit 47f805
                       "\n");
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) {
Packit 47f805
    case 1:
Packit 47f805
    case 2:
Packit 47f805
    case 3:
Packit 47f805
        break;
Packit 47f805
    default:
Packit 47f805
        error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]);
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
    rtp_initialization();
Packit 47f805
    if (rtp_socket(ip, port, ttl)) {
Packit 47f805
        rtp_deinitialization();
Packit 47f805
        error_printf("fatal error during initialization\n");
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    lame_set_errorf(gf, &frontend_errorf);
Packit 47f805
    lame_set_debugf(gf, &frontend_debugf);
Packit 47f805
    lame_set_msgf(gf, &frontend_msgf);
Packit 47f805
Packit 47f805
    /* Remove the argumets that are rtp related, and then 
Packit 47f805
     * parse the command line arguments, setting various flags in the
Packit 47f805
     * struct pointed to by 'gf'.  If you want to parse your own arguments,
Packit 47f805
     * or call libmp3lame from a program which uses a GUI to set arguments,
Packit 47f805
     * skip this call and set the values of interest in the gf struct.  
Packit 47f805
     * (see lame.h for documentation about these parameters)
Packit 47f805
     */
Packit 47f805
    {
Packit 47f805
        int     i;
Packit 47f805
        int     argc_mod = argc-1; /* leaving out exactly one argument */
Packit 47f805
        char**  argv_mod = calloc(argc_mod, sizeof(char*));
Packit 47f805
        argv_mod[0] = argv[0];
Packit 47f805
        for (i = 2; i < argc; ++i) { /* leaving out argument number 1, parsed above */
Packit 47f805
            argv_mod[i-1] = argv[i];
Packit 47f805
        }
Packit 47f805
        parse_args(gf, argc_mod, argv_mod, inPath, outPath, NULL, NULL);
Packit 47f805
        free(argv_mod);
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /* open the output file.  Filename parsed into gf.inPath */
Packit 47f805
    if (0 == strcmp(outPath, "-")) {
Packit 47f805
        lame_set_stream_binary_mode(outf = stdout);
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        if ((outf = lame_fopen(outPath, "wb+")) == NULL) {
Packit 47f805
            rtp_deinitialization();
Packit 47f805
            error_printf("Could not create \"%s\".\n", outPath);
Packit 47f805
            return 1;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /* open the wav/aiff/raw pcm or mp3 input file.  This call will
Packit 47f805
     * open the file with name gf.inFile, try to parse the headers and
Packit 47f805
     * set gf.samplerate, gf.num_channels, gf.num_samples.
Packit 47f805
     * if you want to do your own file input, skip this call and set
Packit 47f805
     * these values yourself.  
Packit 47f805
     */
Packit 47f805
    if (init_infile(gf, inPath) < 0) {
Packit 47f805
        rtp_deinitialization();
Packit 47f805
        fclose(outf);
Packit 47f805
        error_printf("Can't init infile '%s'\n", inPath);
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /* Now that all the options are set, lame needs to analyze them and
Packit 47f805
     * set some more options 
Packit 47f805
     */
Packit 47f805
    ret = lame_init_params(gf);
Packit 47f805
    if (ret < 0) {
Packit 47f805
        if (ret == -1)
Packit 47f805
            display_bitrates(stderr);
Packit 47f805
        rtp_deinitialization();
Packit 47f805
        fclose(outf);
Packit 47f805
        close_infile();
Packit 47f805
        error_printf("fatal error during initialization\n");
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    lame_print_config(gf); /* print useful information about options being used */
Packit 47f805
Packit 47f805
    if (global_ui_config.update_interval < 0.)
Packit 47f805
        global_ui_config.update_interval = 2.;
Packit 47f805
Packit 47f805
    /* encode until we hit EOF */
Packit 47f805
    while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */
Packit 47f805
        levelmessage(maxvalue(Buffer), &maxx, &tmpx);
Packit 47f805
        mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */
Packit 47f805
                                          Buffer[0], Buffer[1], wavsamples,
Packit 47f805
                                          mp3buffer, sizeof(mp3buffer));
Packit 47f805
        rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */
Packit 47f805
        fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */
Packit 47f805
    }
Packit 47f805
Packit 47f805
    mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */
Packit 47f805
                                 mp3buffer, sizeof(mp3buffer));
Packit 47f805
    rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */
Packit 47f805
    fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */
Packit 47f805
Packit 47f805
    lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
Packit 47f805
Packit 47f805
    rtp_deinitialization();
Packit 47f805
    fclose(outf);
Packit 47f805
    close_infile();     /* close the sound input file */
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
/* end of mp3rtp.c */