1 /*
2  *  decode_mp3.c
3  *
4  *  Copyright (C) Thomas Oestreich - June 2001
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 #include <stdint.h>
25 
26 #include "transcode.h"
27 #include "libtc/libtc.h"
28 #include "tcinfo.h"
29 
30 #include "ioaux.h"
31 #include "tc.h"
32 
33 #ifdef HAVE_LAME
34 
35 #include "mpg123.h"
36 
37 #define MP3_PCM_SIZE 1152
38 static uint16_t buffer[MP3_PCM_SIZE<<2];
39 static uint16_t ch1[MP3_PCM_SIZE], ch2[MP3_PCM_SIZE];
40 
41 #endif  // HAVE_LAME
42 
43 #define MP3_AUDIO_ID    0x55
44 #define MP2_AUDIO_ID    0x50
45 
46 /*
47  * About MP2/3 handling differences:
48  * It is possible that lame_decode_initfile() when looking for an MP3 syncbyte
49  * finds an invalid one (esp. in broken mp3 streams). Thats why we use the
50  * format argument to decide which syncword detection is to be done. The
51  * syncword detection for mp2 also finds mp3 sync bytes but NOT the other way round.
52  */
53 
54 /* ------------------------------------------------------------
55  *
56  * decoder thread
57  *
58  * ------------------------------------------------------------*/
59 
60 
decode_mpaudio(decode_t * decode,int format)61 static void decode_mpaudio(decode_t *decode, int format)
62 {
63 #ifdef HAVE_LAME
64     int samples = 0, j, bytes, channels = 0, i, padding = 0;
65     int verbose;
66 
67     mp3data_struct *mp3data = NULL;
68     FILE *in_file = NULL;
69 
70     if (format != MP2_AUDIO_ID && format != MP3_AUDIO_ID) {
71         tc_log_error(__FILE__, "wrong mpeg audio format: 0x%x", format);
72         exit(1);
73     }
74 
75     verbose = decode->verbose;
76 
77     // init decoder
78 
79     mp3data = tc_zalloc(sizeof(mp3data_struct));
80     if (mp3data == NULL) {
81         tc_log_error(__FILE__, "out of memory");
82         exit(1);
83     }
84 
85     if (lame_decode_init() < 0) {
86         tc_log_error(__FILE__, "failed to init decoder");
87         exit(1);
88     }
89 
90     in_file = fdopen(decode->fd_in, "r");
91 
92     if (format == MP3_AUDIO_ID) {
93         int c = 0;
94         /* padding detection */
95         while (!(c = fgetc(in_file)))
96             padding++;
97         if (c != EOF)
98             ungetc(c, in_file);
99     }
100 
101     samples = lame_decode_initfile(in_file, mp3data, format);
102 
103     if (verbose) {
104         tc_log_info(__FILE__, "channels=%d, samplerate=%d Hz, bitrate=%d kbps, (%d)",
105 		            mp3data->stereo, mp3data->samplerate, mp3data->bitrate,
106             		mp3data->framesize);
107     }
108 
109     if (format == MP3_AUDIO_ID) {
110         if (decode->padrate > 0) {
111             padding = (int)((double)padding / (double)decode->padrate * mp3data->samplerate)
112                       * mp3data->stereo * 2;
113             memset(buffer, 0, sizeof(buffer));
114             while (padding >= sizeof(buffer)) {
115                 if (tc_pwrite(decode->fd_out, (uint8_t *)buffer, sizeof(buffer)) != sizeof(buffer)) {
116                     tc_log_error(__FILE__, "error while writing padding output data");
117                     import_exit(1);
118                 }
119                 padding -= sizeof(buffer);
120             }
121             if (padding && tc_pwrite(decode->fd_out, (uint8_t *)buffer, padding) != padding) {
122                 tc_log_error(__FILE__, "error while writing final padding output data");
123                 import_exit(1);
124             }
125         }
126     }
127 
128     // decoder loop
129     channels = mp3data->stereo;
130 
131     while ((samples=lame_decode_fromfile(in_file, ch1, ch2, mp3data)) > 0) {
132         // interleave data
133         j = 0;
134         switch (channels) {
135           case 1: // mono
136             ac_memcpy (buffer, ch1, samples * sizeof(uint16_t));
137             break;
138           case 2: // stereo
139             for (i=0; i < samples; i++) {
140                 *(buffer+j+0) = ch1[i];
141                 *(buffer+j+1) = ch2[i];
142                 j+=2;
143             }
144             break;
145         }
146 
147         bytes = samples * channels * sizeof(uint16_t);
148 
149         if (tc_pwrite(decode->fd_out, (uint8_t *) buffer, bytes) != bytes) {
150             tc_log_error(__FILE__, "error while writing output data");
151             import_exit(1);
152             break; /* broken pipe */
153         }
154     }
155 
156     import_exit(0);
157 
158 #else  // HAVE_LAME
159     tc_log_error(__FILE__, "no lame support available");
160     import_exit(1);
161 #endif
162 }
163 
decode_mp3(decode_t * decode)164 void decode_mp3(decode_t *decode)
165 {
166     decode_mpaudio(decode, MP3_AUDIO_ID);
167 }
168 
169 
decode_mp2(decode_t * decode)170 void decode_mp2(decode_t *decode)
171 {
172     decode_mpaudio(decode, MP2_AUDIO_ID);
173 }
174 
175 /*************************************************************************/
176 
177 /*
178  * Local variables:
179  *   c-file-style: "stroustrup"
180  *   c-file-offsets: ((case-label . *) (statement-case-intro . *))
181  *   indent-tabs-mode: nil
182  * End:
183  *
184  * vim: expandtab shiftwidth=4:
185  */
186