1 /***************************************************************************
2 \file audioencoder_lame.cpp
3 \brief Avidemux audio encoder plugin, front end for libmp3lame
4 copyright : (C) 2006/2009 by mean
5 email : fixounet@free.fr
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "ADM_default.h"
18 #include "DIA_factory.h"
19 #include "DIA_coreToolkit.h"
20 #include <lame/lame.h>
21 #include "audioencoder.h"
22 #include "audioencoderInternal.h"
23 #include "audioencoder_lame_param.h"
24 #include "audioencoder_lame.h"
25 #include "lame_encoder.h"
26 #include "lame_encoder_desc.cpp"
27
28 #define LAME_DEFAULT_CONF {128, ADM_LAME_PRESET_CBR, 2, 0}
29 static lame_encoder defaultConfig = LAME_DEFAULT_CONF;
30
31 extern "C"
32 {
33 static bool configure (CONFcouple **setup);
34 static bool setOption(CONFcouple **c, const char *paramName, uint32_t value);
35 static void getDefaultConfiguration(CONFcouple **c);
36 };
37
38 /********************* Declare Plugin *****************************************************/
39 ADM_DECLARE_AUDIO_ENCODER_PREAMBLE(AUDMEncoder_Lame);
40
41 static ADM_audioEncoder encoderDesc = {
42 ADM_AUDIO_ENCODER_API_VERSION,
43 create, // Defined by macro automatically
44 destroy, // Defined by macro automatically
45 configure, //** put your own function here**
46 "Lame",
47 "MP3 (lame)",
48 "Lame MP3 encoder plugin Mean 2009",
49 2, // Max channels
50 1,0,0, // Version
51 WAV_MP3, // WavTag
52 200, // Priority
53
54 setOption, //** put your own function here**
55 getDefaultConfiguration,
56 NULL
57 };
58 ADM_DECLARE_AUDIO_ENCODER_CONFIG();
59
60 /******************* / Declare plugin*******************************************************/
61 #define MYFLAGS (lame_global_flags *)lameFlags
62 /**
63 \fn AUDMEncoder_Lame Constructor
64 \brief
65 */
AUDMEncoder_Lame(AUDMAudioFilter * instream,bool globalHeader,CONFcouple * setup)66 AUDMEncoder_Lame::AUDMEncoder_Lame (AUDMAudioFilter * instream,bool globalHeader,
67 CONFcouple *setup) :ADM_AudioEncoder (instream,setup)
68 {
69 printf ("[Lame] Creating lame\n");
70 lameFlags = NULL;
71 wavheader.encoding = WAV_MP3;
72 _config=defaultConfig;
73 if(setup) // load config if possible
74 ADM_paramLoad(setup,lame_encoder_param,&_config);
75 };
76
77 /**
78 \fn AUDMEncoder_Lame
79 \brief Destructor
80 */
81
~AUDMEncoder_Lame()82 AUDMEncoder_Lame::~AUDMEncoder_Lame ()
83 {
84
85 printf ("[Lame] Deleting lame\n");
86 if (lameFlags)
87 {
88 lame_close (MYFLAGS);
89 }
90 lameFlags = NULL;
91 };
92
93
94 /**
95 \fn initialize
96 \brief initialize lame encoder
97 @return 1 on success, 0 on error
98 */
99
initialize(void)100 bool AUDMEncoder_Lame::initialize (void)
101 {
102
103 int ret;
104 MPEG_mode_e mmode;
105 uint32_t frequence;
106
107
108
109 lameFlags = lame_init ();
110 if (lameFlags == NULL)
111 return false;
112
113 if (_incoming->getInfo ()->channels > 2)
114 {
115 printf ("[Lame]Too many channels\n");
116 return false;
117 }
118
119 // recompute output length
120
121
122 ret = lame_set_in_samplerate (MYFLAGS, wavheader.frequency);
123 ret = lame_set_num_channels (MYFLAGS, wavheader.channels);
124
125
126 frequence = wavheader.frequency;
127 printf ("[Lame] output frequency : %" PRIu32"\n", frequence);
128 ret = lame_set_out_samplerate (MYFLAGS, frequence);
129
130 ret = lame_set_quality (MYFLAGS, 2);
131
132 if (wavheader.channels == 2)
133 {
134
135 mmode = STEREO;
136 }
137 else
138 {
139 mmode = MONO;
140 printf ("[Lame] mono audio mp3");
141 }
142
143 ret = lame_set_brate (MYFLAGS, _config.bitrate);
144 ret = lame_set_mode (MYFLAGS, mmode); // 0 stereo 1 jstero
145 ret = lame_set_quality (MYFLAGS, _config.quality); // 0 stereo 1 jstero
146 ret = lame_set_disable_reservoir (MYFLAGS, _config.disableBitReservoir);
147 printf ("[Lame]Using quality of %d\n", lame_get_quality (MYFLAGS));
148 // update bitrate in header
149 wavheader.byterate = (_config.bitrate >> 3) * 1000;
150 #define BLOCK_SIZE 1152
151 // configure CBR/ABR/...
152
153 switch (_config.preset)
154 {
155 default:
156 case ADM_LAME_PRESET_CBR:
157 ADM_info("Lame : CBR Mode\n");
158 break;
159 case ADM_LAME_PRESET_ABR:
160 ADM_info("Lame : ABR Mode\n");
161
162 lame_set_preset (MYFLAGS, _config.bitrate);
163 wavheader.blockalign = BLOCK_SIZE;
164 break;
165 case ADM_LAME_PRESET_EXTREME:
166 ADM_info("Lame : Extreme Mode\n");
167 wavheader.blockalign = BLOCK_SIZE;
168 lame_set_preset (MYFLAGS, EXTREME);
169 break;
170
171
172 }
173 ret = lame_init_params (MYFLAGS);
174 if (ret == -1)
175 {
176 printf("[Lame] Init params failes %d\n",ret);
177 return false;
178 }
179
180 lame_print_config (MYFLAGS);
181 lame_print_internals (MYFLAGS);
182 _chunk = BLOCK_SIZE * wavheader.channels;
183
184 return true;
185 }
186 /**
187 \fn isVBR
188 @return 1 if the stream is vbr, 0 is cbr
189
190 */
isVBR(void)191 bool AUDMEncoder_Lame::isVBR (void)
192 {
193 if (_config.preset == ADM_LAME_PRESET_CBR)
194 return false;
195 return true;
196
197 }
198 /**
199 \fn send
200 \brief Encode a block
201 */
send(uint32_t nbSample,uint8_t * dest)202 int AUDMEncoder_Lame::send(uint32_t nbSample, uint8_t *dest)
203 {
204 int nbout;
205 dither16 (&(tmpbuffer[tmphead]), nbSample, wavheader.channels);
206 ADM_assert (tmptail >= tmphead);
207 int16_t *sample16=(int16_t *)& (tmpbuffer[tmphead]);
208 if (wavheader.channels == 1)
209 {
210 nbout = lame_encode_buffer (MYFLAGS,
211 sample16,
212 sample16, nbSample, dest,
213 16 * 1024);
214
215 }
216 else
217 {
218 nbout = lame_encode_buffer_interleaved (MYFLAGS,
219 sample16,
220 nbSample / 2, dest, 16 * 1024);
221 }
222 return nbout;
223 }
224 /**
225 \fn encode
226 \brief Get an encoded mp3 packet
227 @param dest [in] Where to write datas
228 @param len [out] Length of encoded datas in bytes
229 @param samples [out] Number of samples
230 @return true on success, false on error
231
232 */
encode(uint8_t * dest,uint32_t * len,uint32_t * samples)233 bool AUDMEncoder_Lame::encode(uint8_t *dest, uint32_t *len, uint32_t *samples)
234 {
235
236 int32_t nbout;
237
238 *samples = BLOCK_SIZE; //FIXME
239 *len = 0;
240 if(AudioEncoderStopped==_state)
241 return false;
242
243 refillBuffer (_chunk);
244 if(AudioEncoderNoInput==_state)
245 {
246 int left=tmptail-tmphead;
247 if (left < _chunk)
248 {
249 if(left)
250 {
251 nbout=send(left,dest);
252 tmphead=tmptail;
253 ADM_info("[lame]Sending last packet\n");
254 goto cont;
255 }
256 // Flush
257 _state=AudioEncoderStopped;
258 nbout=lame_encode_flush(MYFLAGS,dest,16*1024);
259 if(nbout<0)
260 {
261 ADM_warning("Error while flushing lame\n");
262 return false;
263 }
264
265 *len=nbout;
266 *samples=BLOCK_SIZE;
267 ADM_info("[Lame] Flushing, last block is %d bytes\n",nbout);
268 return true;
269 }
270 }
271 nbout=send(_chunk,dest);
272 tmphead += _chunk;
273 cont:
274 if (nbout < 0)
275 {
276 printf ("[Lame] Error !!! : %" PRIi32"\n", nbout);
277 return false;
278 }
279 *len = nbout;
280 if (!*len)
281 *samples = 0;
282 else
283 *samples=BLOCK_SIZE;
284 return true;
285 }
286 /**
287 \fn configure
288 \brief Dialog to set lame settings
289 @return 1 on success, 0 on failure
290
291 */
292
configure(CONFcouple ** setup)293 bool configure (CONFcouple **setup)
294 {
295 int ret = 0;
296 char string[400];
297 uint32_t mmode, ppreset;
298 #define SZT(x) sizeof(x)/sizeof(diaMenuEntry )
299 #define PX(x) &(config.x)
300
301 lame_encoder config=defaultConfig;
302 if(*setup)
303 {
304 ADM_paramLoad(*setup,lame_encoder_param,&config);
305 }
306
307 ppreset = config.preset;
308
309 diaMenuEntry encodingMode[] = {
310 {ADM_LAME_PRESET_CBR, QT_TRANSLATE_NOOP("lame","CBR"), NULL},
311 {ADM_LAME_PRESET_ABR, QT_TRANSLATE_NOOP("lame","ABR"), NULL},
312 };
313 diaElemMenu Mode (&ppreset, QT_TRANSLATE_NOOP("lame","Bit_rate mode:"), SZT (encodingMode), encodingMode);
314
315 #define BITRATE(x) {x,QT_TRANSLATE_NOOP("lame",#x)}
316 diaMenuEntry bitrateM[] = {
317 BITRATE (56),//56
318 BITRATE (64),
319 BITRATE (80),
320 BITRATE (96),
321 BITRATE (112),
322 BITRATE (128),
323 BITRATE (160),
324 BITRATE (192),
325 BITRATE (224),
326 BITRATE (256),
327 BITRATE (320)
328 };
329
330 //***
331 diaElemMenu bitrate (&(config.bitrate), QT_TRANSLATE_NOOP("lame","_Bitrate:"), SZT (bitrateM),
332 bitrateM);
333 diaElemUInteger quality (PX (quality), QT_TRANSLATE_NOOP("lame","_Quality:"), 0, 9);
334 bool reservoir32=config.disableBitReservoir;
335 diaElemToggle reservoir (&reservoir32, QT_TRANSLATE_NOOP("lame","_Disable reservoir"));
336
337 diaElem *elems[] = { &Mode, &bitrate,&quality, &reservoir };
338
339 if (diaFactoryRun (QT_TRANSLATE_NOOP("lame","LAME Configuration"), 4, elems))
340 {
341 config.preset=(ADM_LAME_PRESET)ppreset;
342 config.disableBitReservoir=reservoir32;
343 if(*setup) delete *setup;
344 *setup=NULL;
345 ADM_paramSave(setup,lame_encoder_param,&config);
346 defaultConfig=config;
347 return 1;
348 }
349 return 0;
350 }
351 /**
352 \fn setOption
353 \brief Allow giving codec specific options as string+value
354 */
setOption(CONFcouple ** c,const char * paramName,uint32_t value)355 bool setOption(CONFcouple **c, const char *paramName, uint32_t value)
356 {
357 lame_encoder config=defaultConfig;
358 if(*c)
359 {
360 ADM_paramLoad(*c,lame_encoder_param,&config);
361 }else
362 {
363 config=defaultConfig;
364 }
365 if(!strcasecmp(paramName,"MP3DisableReservoir"))
366 {
367 config.disableBitReservoir=value;
368 ADM_paramSave(c,lame_encoder_param,&config);
369 return 1;
370 }
371 ADM_error("Not supported\n");
372 return 0;
373 }
374
getDefaultConfiguration(CONFcouple ** c)375 void getDefaultConfiguration(CONFcouple **c)
376 {
377 lame_encoder config = LAME_DEFAULT_CONF;
378
379 ADM_paramSave(c, lame_encoder_param, &config);
380 }
381
382 // EOF
383