1 /*****************************************************************************
2 * shine_mod.c: MP3 encoder using Shine, a fixed point implementation
3 *****************************************************************************
4 * Copyright (C) 2008-2009 M2X
6 * Authors: Rafaël Carré <rcarre@m2x.nl>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program 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 Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <stdatomic.h>
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
36 #include <vlc_block_helper.h>
43 #include <shine/layer3.h>
48 unsigned int samples_per_frame
;
49 block_t
*first
, **lastp
;
51 unsigned int i_buffer
;
55 /*****************************************************************************
57 *****************************************************************************/
58 static int OpenEncoder ( vlc_object_t
* );
59 static void CloseEncoder ( vlc_object_t
* );
61 static block_t
*EncodeFrame ( encoder_t
*, block_t
* );
64 set_category( CAT_INPUT
);
65 set_subcategory( SUBCAT_INPUT_ACODEC
);
66 set_description( N_("MP3 fixed point audio encoder") );
67 set_capability( "encoder", 50 );
68 set_callbacks( OpenEncoder
, CloseEncoder
);
71 static atomic_bool busy
= ATOMIC_VAR_INIT(false);
73 static int OpenEncoder( vlc_object_t
*p_this
)
75 encoder_t
*p_enc
= (encoder_t
*)p_this
;
78 /* shine is an 'MP3' encoder */
79 if( (p_enc
->fmt_out
.i_codec
!= VLC_CODEC_MP3
&& p_enc
->fmt_out
.i_codec
!= VLC_CODEC_MPGA
) ||
80 p_enc
->fmt_out
.audio
.i_channels
> 2 )
83 /* Shine is strict on its input */
84 if( p_enc
->fmt_in
.audio
.i_channels
!= 2 )
86 msg_Err( p_enc
, "Only stereo input is accepted, rejecting %d channels",
87 p_enc
->fmt_in
.audio
.i_channels
);
91 if( p_enc
->fmt_out
.i_bitrate
<= 0 )
93 msg_Err( p_enc
, "unknown bitrate" );
97 msg_Dbg( p_enc
, "bitrate %d, samplerate %d, channels %d",
98 p_enc
->fmt_out
.i_bitrate
, p_enc
->fmt_out
.audio
.i_rate
,
99 p_enc
->fmt_out
.audio
.i_channels
);
101 if( atomic_exchange(&busy
, true) )
103 msg_Err( p_enc
, "encoder already in progress" );
107 p_enc
->p_sys
= p_sys
= calloc( 1, sizeof( *p_sys
) );
112 p_sys
->lastp
= &p_sys
->first
;
114 shine_config_t cfg
= {
116 .channels
= p_enc
->fmt_out
.audio
.i_channels
,
117 .samplerate
= p_enc
->fmt_out
.audio
.i_rate
,
121 shine_set_config_mpeg_defaults(&cfg
.mpeg
);
122 cfg
.mpeg
.bitr
= p_enc
->fmt_out
.i_bitrate
/ 1000;
124 if (shine_check_config(cfg
.wave
.samplerate
, cfg
.mpeg
.bitr
) == -1) {
125 msg_Err(p_enc
, "Invalid bitrate %d\n", cfg
.mpeg
.bitr
);
130 p_sys
->s
= shine_initialise(&cfg
);
131 p_sys
->samples_per_frame
= shine_samples_per_pass(p_sys
->s
);
133 p_enc
->pf_encode_audio
= EncodeFrame
;
134 p_enc
->fmt_out
.i_cat
= AUDIO_ES
;
136 p_enc
->fmt_in
.i_codec
= VLC_CODEC_S16N
;
141 atomic_store(&busy
, false);
145 /* We split/pack PCM blocks to a fixed size: p_sys->samples_per_frame * 4 bytes */
146 static block_t
*GetPCM( encoder_t
*p_enc
, block_t
*p_block
)
148 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
149 block_t
*p_pcm_block
;
151 if( !p_block
) goto buffered
; /* just return a block if we can */
153 /* Put the PCM samples sent by VLC in the Fifo */
154 while( p_sys
->i_buffer
+ p_block
->i_buffer
>= p_sys
->samples_per_frame
* 4 )
156 unsigned int i_buffer
= 0;
157 p_pcm_block
= block_Alloc( p_sys
->samples_per_frame
* 4 );
161 if( p_sys
->i_buffer
)
163 memcpy( p_pcm_block
->p_buffer
, p_sys
->p_buffer
, p_sys
->i_buffer
);
165 i_buffer
= p_sys
->i_buffer
;
167 free( p_sys
->p_buffer
);
168 p_sys
->p_buffer
= NULL
;
171 memcpy( p_pcm_block
->p_buffer
+ i_buffer
,
172 p_block
->p_buffer
, p_sys
->samples_per_frame
* 4 - i_buffer
);
173 p_block
->p_buffer
+= p_sys
->samples_per_frame
* 4 - i_buffer
;
175 p_block
->i_buffer
-= p_sys
->samples_per_frame
* 4 - i_buffer
;
177 *(p_sys
->lastp
) = p_pcm_block
;
178 p_sys
->lastp
= &p_pcm_block
->p_next
;
181 /* We hadn't enough data to make a block, put it in standby */
182 if( p_block
->i_buffer
)
186 if( p_sys
->i_buffer
> 0 )
187 p_tmp
= realloc( p_sys
->p_buffer
, p_block
->i_buffer
+ p_sys
->i_buffer
);
189 p_tmp
= malloc( p_block
->i_buffer
);
194 free( p_sys
->p_buffer
);
195 p_sys
->p_buffer
= NULL
;
198 p_sys
->p_buffer
= p_tmp
;
199 memcpy( p_sys
->p_buffer
+ p_sys
->i_buffer
,
200 p_block
->p_buffer
, p_block
->i_buffer
);
202 p_sys
->i_buffer
+= p_block
->i_buffer
;
203 p_block
->i_buffer
= 0;
207 /* and finally get a block back */
208 p_pcm_block
= p_sys
->first
;
210 if( p_pcm_block
!= NULL
) {
211 p_sys
->first
= p_pcm_block
->p_next
;
212 if( p_pcm_block
->p_next
== NULL
)
213 p_sys
->lastp
= &p_sys
->first
;
219 static block_t
*EncodeFrame( encoder_t
*p_enc
, block_t
*p_block
)
221 if (!p_block
) /* TODO: flush */
224 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
225 block_t
*p_pcm_block
;
226 block_t
*p_chain
= NULL
;
227 unsigned int i_samples
= p_block
->i_buffer
>> 2 /* s16l stereo */;
228 vlc_tick_t start_date
= p_block
->i_pts
;
229 start_date
-= vlc_tick_from_samples(i_samples
, p_enc
->fmt_out
.audio
.i_rate
);
234 p_pcm_block
= GetPCM( p_enc
, p_block
);
238 p_block
= NULL
; /* we don't need it anymore */
239 int16_t pcm_planar_buf
[SHINE_MAX_SAMPLES
* 2];
240 int16_t *pcm_planar_buf_chans
[2] = {
242 &pcm_planar_buf
[p_sys
->samples_per_frame
],
244 aout_Deinterleave( pcm_planar_buf
, p_pcm_block
->p_buffer
,
245 p_sys
->samples_per_frame
, p_enc
->fmt_in
.audio
.i_channels
, p_enc
->fmt_in
.i_codec
);
248 unsigned char *buf
= shine_encode_buffer(p_sys
->s
, pcm_planar_buf_chans
, &written
);
249 block_Release( p_pcm_block
);
254 block_t
*p_mp3_block
= block_Alloc( written
);
258 memcpy( p_mp3_block
->p_buffer
, buf
, written
);
260 /* date management */
261 p_mp3_block
->i_length
= vlc_tick_from_samples(p_sys
->samples_per_frame
,
262 p_enc
->fmt_out
.audio
.i_rate
);
264 start_date
+= p_mp3_block
->i_length
;
265 p_mp3_block
->i_dts
= p_mp3_block
->i_pts
= start_date
;
267 p_mp3_block
->i_nb_samples
= p_sys
->samples_per_frame
;
269 block_ChainAppend( &p_chain
, p_mp3_block
);
271 } while( p_pcm_block
);
276 static void CloseEncoder( vlc_object_t
*p_this
)
278 encoder_sys_t
*p_sys
= ((encoder_t
*)p_this
)->p_sys
;
280 /* TODO: we should send the last PCM block padded with 0
281 * But we don't know if other blocks will come before it's too late */
282 if( p_sys
->i_buffer
)
283 free( p_sys
->p_buffer
);
285 shine_close(p_sys
->s
);
286 atomic_store(&busy
, false);
288 block_ChainRelease(p_sys
->first
);