qml/KeyNavigableTableView: Add 'delegate' and 'contentY' aliases
[vlc.git] / modules / codec / shine.c
blob45e8ca41146912045a7ad8c725c21aae4eeaf4b0
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 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
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>
37 #include <vlc_bits.h>
38 #include <vlc_aout.h>
40 #include <assert.h>
41 #include <inttypes.h>
43 #include <shine/layer3.h>
45 typedef struct
47 shine_t s;
48 unsigned int samples_per_frame;
49 block_t *first, **lastp;
51 unsigned int i_buffer;
52 uint8_t *p_buffer;
53 } encoder_sys_t;
55 /*****************************************************************************
56 * Local prototypes
57 *****************************************************************************/
58 static int OpenEncoder ( vlc_object_t * );
59 static void CloseEncoder ( vlc_object_t * );
61 static block_t *EncodeFrame ( encoder_t *, block_t * );
63 vlc_module_begin();
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 );
69 vlc_module_end();
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;
76 encoder_sys_t *p_sys;
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 )
81 return VLC_EGENERIC;
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 );
88 return VLC_EGENERIC;
91 if( p_enc->fmt_out.i_bitrate <= 0 )
93 msg_Err( p_enc, "unknown bitrate" );
94 return VLC_EGENERIC;
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" );
104 return VLC_EGENERIC;
107 p_enc->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) );
108 if( !p_sys )
109 goto enomem;
111 p_sys->first = NULL;
112 p_sys->lastp = &p_sys->first;
114 shine_config_t cfg = {
115 .wave = {
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);
126 free(p_sys);
127 return VLC_EGENERIC;
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;
138 return VLC_SUCCESS;
140 enomem:
141 atomic_store(&busy, false);
142 return VLC_ENOMEM;
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 );
158 if( !p_pcm_block )
159 break;
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;
166 p_sys->i_buffer = 0;
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 )
184 uint8_t *p_tmp;
186 if( p_sys->i_buffer > 0 )
187 p_tmp = realloc( p_sys->p_buffer, p_block->i_buffer + p_sys->i_buffer );
188 else
189 p_tmp = malloc( p_block->i_buffer );
191 if( !p_tmp )
193 p_sys->i_buffer = 0;
194 free( p_sys->p_buffer );
195 p_sys->p_buffer = NULL;
196 return 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;
206 buffered:
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;
216 return p_pcm_block;
219 static block_t *EncodeFrame( encoder_t *p_enc, block_t *p_block )
221 if (!p_block) /* TODO: flush */
222 return NULL;
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);
231 VLC_UNUSED(p_enc);
233 do {
234 p_pcm_block = GetPCM( p_enc, p_block );
235 if( !p_pcm_block )
236 break;
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] = {
241 &pcm_planar_buf[0],
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);
247 int written;
248 unsigned char *buf = shine_encode_buffer(p_sys->s, pcm_planar_buf_chans, &written);
249 block_Release( p_pcm_block );
251 if (written <= 0)
252 break;
254 block_t *p_mp3_block = block_Alloc( written );
255 if( !p_mp3_block )
256 break;
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 );
273 return p_chain;
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);
289 free( p_sys );