/src/vlc/modules/codec/vorbis.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * vorbis.c: vorbis decoder/encoder/packetizer module using of libvorbis. |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2012 VLC authors and VideoLAN |
5 | | * Copyright (C) 2007 Société des arts technologiques |
6 | | * Copyright (C) 2007 Savoir-faire Linux |
7 | | * |
8 | | * |
9 | | * Authors: Gildas Bazin <gbazin@videolan.org> |
10 | | * |
11 | | * This program is free software; you can redistribute it and/or modify it |
12 | | * under the terms of the GNU Lesser General Public License as published by |
13 | | * the Free Software Foundation; either version 2.1 of the License, or |
14 | | * (at your option) any later version. |
15 | | * |
16 | | * This program is distributed in the hope that it will be useful, |
17 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | | * GNU Lesser General Public License for more details. |
20 | | * |
21 | | * You should have received a copy of the GNU Lesser General Public License |
22 | | * along with this program; if not, write to the Free Software Foundation, |
23 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
24 | | *****************************************************************************/ |
25 | | |
26 | | /***************************************************************************** |
27 | | * Preamble |
28 | | *****************************************************************************/ |
29 | | #ifdef HAVE_CONFIG_H |
30 | | # include "config.h" |
31 | | #endif |
32 | | |
33 | | #include <vlc_common.h> |
34 | | #include <vlc_configuration.h> |
35 | | #include <vlc_plugin.h> |
36 | | #include <vlc_codec.h> |
37 | | #include <vlc_charset.h> |
38 | | #include <vlc_aout.h> |
39 | | #include <vlc_input_item.h> |
40 | | #include <vlc_sout.h> |
41 | | #include <vlc_replay_gain.h> |
42 | | #include "../demux/xiph.h" |
43 | | |
44 | | #include <ogg/ogg.h> |
45 | | |
46 | | #ifdef PLUGIN_TREMOR |
47 | | # include <tremor/ivorbiscodec.h> |
48 | | # define INTERLEAVE_TYPE int32_t |
49 | | |
50 | | #else |
51 | | # include <vorbis/codec.h> |
52 | 17.1k | # define INTERLEAVE_TYPE float |
53 | | |
54 | | # ifdef ENABLE_SOUT |
55 | | # define HAVE_VORBIS_ENCODER |
56 | | # include <vorbis/vorbisenc.h> |
57 | | # ifndef OV_ECTL_RATEMANAGE_AVG |
58 | | # define OV_ECTL_RATEMANAGE_AVG 0x0 |
59 | | # endif |
60 | | # endif |
61 | | #endif |
62 | | |
63 | | /***************************************************************************** |
64 | | * decoder_sys_t : vorbis decoder descriptor |
65 | | *****************************************************************************/ |
66 | | typedef struct |
67 | | { |
68 | | /* Module mode */ |
69 | | bool b_packetizer; |
70 | | |
71 | | bool b_has_headers; |
72 | | |
73 | | /* |
74 | | * Vorbis properties |
75 | | */ |
76 | | vorbis_info vi; /* struct that stores all the static vorbis bitstream |
77 | | settings */ |
78 | | vorbis_comment vc; /* struct that stores all the bitstream user |
79 | | * comments */ |
80 | | vorbis_dsp_state vd; /* central working state for the packet->PCM |
81 | | * decoder */ |
82 | | vorbis_block vb; /* local working space for packet->PCM decode */ |
83 | | |
84 | | /* |
85 | | * Common properties |
86 | | */ |
87 | | date_t end_date; |
88 | | int i_last_block_size; |
89 | | |
90 | | /* |
91 | | ** Channel reordering |
92 | | */ |
93 | | uint8_t pi_chan_table[AOUT_CHAN_MAX]; |
94 | | } decoder_sys_t; |
95 | | |
96 | | static const int pi_channels_maps[9] = |
97 | | { |
98 | | 0, |
99 | | AOUT_CHAN_CENTER, |
100 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, |
101 | | AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, |
102 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT |
103 | | | AOUT_CHAN_REARRIGHT, |
104 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
105 | | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT, |
106 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
107 | | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE, |
108 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
109 | | | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
110 | | | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE, |
111 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
112 | | | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
113 | | | AOUT_CHAN_LFE, |
114 | | }; |
115 | | |
116 | | /* |
117 | | ** channel order as defined in http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9 |
118 | | */ |
119 | | |
120 | | /* recommended vorbis channel order for 8 channels */ |
121 | | static const uint32_t pi_8channels_in[] = |
122 | | { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, |
123 | | AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, |
124 | | AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,AOUT_CHAN_LFE, 0 }; |
125 | | |
126 | | /* recommended vorbis channel order for 7 channels */ |
127 | | static const uint32_t pi_7channels_in[] = |
128 | | { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, |
129 | | AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, |
130 | | AOUT_CHAN_REARCENTER, AOUT_CHAN_LFE, 0 }; |
131 | | |
132 | | /* recommended vorbis channel order for 6 channels */ |
133 | | static const uint32_t pi_6channels_in[] = |
134 | | { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, |
135 | | AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 }; |
136 | | |
137 | | /* recommended vorbis channel order for 4 channels */ |
138 | | static const uint32_t pi_4channels_in[] = |
139 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }; |
140 | | |
141 | | /* recommended vorbis channel order for 3 channels */ |
142 | | static const uint32_t pi_3channels_in[] = |
143 | | { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, 0 }; |
144 | | |
145 | | /**************************************************************************** |
146 | | * Local prototypes |
147 | | ****************************************************************************/ |
148 | | static int OpenDecoder ( vlc_object_t * ); |
149 | | static int OpenPacketizer( vlc_object_t * ); |
150 | | static void CloseDecoder ( vlc_object_t * ); |
151 | | static int DecodeAudio ( decoder_t *, block_t * ); |
152 | | static block_t *Packetize ( decoder_t *, block_t ** ); |
153 | | static void Flush( decoder_t * ); |
154 | | |
155 | | static int ProcessHeaders( decoder_t * ); |
156 | | static block_t *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** ); |
157 | | |
158 | | static block_t *DecodePacket( decoder_t *, ogg_packet * ); |
159 | | static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * ); |
160 | | |
161 | | static void ParseVorbisComments( decoder_t * ); |
162 | | |
163 | | static void ConfigureChannelOrder(uint8_t *, int, uint32_t ); |
164 | | |
165 | | #ifdef HAVE_VORBIS_ENCODER |
166 | | static int OpenEncoder ( vlc_object_t * ); |
167 | | static void CloseEncoder ( encoder_t * ); |
168 | | static block_t *Encode ( encoder_t *, block_t * ); |
169 | | #endif |
170 | | |
171 | | /***************************************************************************** |
172 | | * Module descriptor |
173 | | *****************************************************************************/ |
174 | | #define ENC_QUALITY_TEXT N_("Encoding quality") |
175 | | #define ENC_QUALITY_LONGTEXT N_( \ |
176 | | "Enforce a quality between 1 (low) and 10 (high), instead " \ |
177 | | "of specifying a particular bitrate. This will produce a VBR stream." ) |
178 | | #define ENC_MAXBR_TEXT N_("Maximum encoding bitrate") |
179 | | #define ENC_MAXBR_LONGTEXT N_( \ |
180 | | "Maximum bitrate in kbps. This is useful for streaming applications." ) |
181 | | #define ENC_MINBR_TEXT N_("Minimum encoding bitrate") |
182 | | #define ENC_MINBR_LONGTEXT N_( \ |
183 | | "Minimum bitrate in kbps. This is useful for encoding for a fixed-size channel." ) |
184 | | #define ENC_CBR_TEXT N_("CBR encoding") |
185 | | #define ENC_CBR_LONGTEXT N_( \ |
186 | | "Force a constant bitrate encoding (CBR)." ) |
187 | | |
188 | 116 | vlc_module_begin () |
189 | 58 | set_shortname( "Vorbis" ) |
190 | 58 | set_description( N_("Vorbis audio decoder") ) |
191 | | #ifdef PLUGIN_TREMOR |
192 | | set_capability( "audio decoder", 90 ) |
193 | | #else |
194 | 58 | set_capability( "audio decoder", 100 ) |
195 | 58 | #endif |
196 | 58 | set_subcategory( SUBCAT_INPUT_ACODEC ) |
197 | 58 | set_callbacks( OpenDecoder, CloseDecoder ) |
198 | | |
199 | 58 | add_submodule () |
200 | 58 | set_description( N_("Vorbis audio packetizer") ) |
201 | 58 | set_capability( "audio packetizer", 100 ) |
202 | 116 | set_callbacks( OpenPacketizer, CloseDecoder ) |
203 | | |
204 | 58 | #ifdef HAVE_VORBIS_ENCODER |
205 | 58 | # define ENC_CFG_PREFIX "sout-vorbis-" |
206 | 58 | add_submodule () |
207 | 58 | set_description( N_("Vorbis audio encoder") ) |
208 | 58 | set_capability( "audio encoder", 130 ) |
209 | 58 | set_callback( OpenEncoder ) |
210 | | |
211 | 58 | add_integer( ENC_CFG_PREFIX "quality", 0, ENC_QUALITY_TEXT, |
212 | 58 | ENC_QUALITY_LONGTEXT ) |
213 | 58 | change_integer_range( 0, 10 ) |
214 | 58 | add_integer( ENC_CFG_PREFIX "max-bitrate", 0, ENC_MAXBR_TEXT, |
215 | 58 | ENC_MAXBR_LONGTEXT ) |
216 | 58 | add_integer( ENC_CFG_PREFIX "min-bitrate", 0, ENC_MINBR_TEXT, |
217 | 58 | ENC_MINBR_LONGTEXT ) |
218 | 58 | add_bool( ENC_CFG_PREFIX "cbr", false, ENC_CBR_TEXT, |
219 | 58 | ENC_CBR_LONGTEXT ) |
220 | 58 | #endif |
221 | | |
222 | 58 | vlc_module_end () |
223 | | |
224 | | #ifdef HAVE_VORBIS_ENCODER |
225 | | static const char *const ppsz_enc_options[] = { |
226 | | "quality", "max-bitrate", "min-bitrate", "cbr", NULL |
227 | | }; |
228 | | #endif |
229 | | |
230 | | static int OpenCommon( vlc_object_t *p_this, bool b_packetizer ) |
231 | 2.90M | { |
232 | 2.90M | decoder_t *p_dec = (decoder_t*)p_this; |
233 | 2.90M | decoder_sys_t *p_sys; |
234 | | |
235 | 2.90M | if( p_dec->fmt_in->i_codec != VLC_CODEC_VORBIS ) |
236 | 2.89M | return VLC_EGENERIC; |
237 | | |
238 | | /* Allocate the memory needed to store the decoder's structure */ |
239 | 1.00k | p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ); |
240 | 1.00k | if( unlikely( !p_sys ) ) |
241 | 0 | return VLC_ENOMEM; |
242 | | |
243 | | /* Misc init */ |
244 | 1.00k | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
245 | 1.00k | p_sys->i_last_block_size = 0; |
246 | 1.00k | p_sys->b_packetizer = b_packetizer; |
247 | 1.00k | p_sys->b_has_headers = false; |
248 | | |
249 | | /* Take care of vorbis init */ |
250 | 1.00k | vorbis_info_init( &p_sys->vi ); |
251 | 1.00k | vorbis_comment_init( &p_sys->vc ); |
252 | | |
253 | 1.00k | if( b_packetizer ) |
254 | 474 | { |
255 | 474 | p_dec->fmt_out.i_codec = VLC_CODEC_VORBIS; |
256 | 474 | p_dec->pf_packetize = Packetize; |
257 | 474 | } |
258 | 530 | else |
259 | 530 | { |
260 | | #ifdef PLUGIN_TREMOR |
261 | | p_dec->fmt_out.i_codec = VLC_CODEC_S32N; |
262 | | #else |
263 | 530 | p_dec->fmt_out.i_codec = VLC_CODEC_FL32; |
264 | 530 | #endif |
265 | 530 | p_dec->pf_decode = DecodeAudio; |
266 | 530 | } |
267 | | |
268 | 1.00k | p_dec->pf_flush = Flush; |
269 | | |
270 | 1.00k | return VLC_SUCCESS; |
271 | 1.00k | } |
272 | | |
273 | | static int OpenDecoder( vlc_object_t *p_this ) |
274 | 700k | { |
275 | 700k | return OpenCommon( p_this, false ); |
276 | 700k | } |
277 | | |
278 | | static int OpenPacketizer( vlc_object_t *p_this ) |
279 | 2.19M | { |
280 | 2.19M | return OpenCommon( p_this, true ); |
281 | 2.19M | } |
282 | | |
283 | | /**************************************************************************** |
284 | | * DecodeBlock: the whole thing |
285 | | **************************************************************************** |
286 | | * This function must be fed with ogg packets. |
287 | | ****************************************************************************/ |
288 | | static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) |
289 | 143k | { |
290 | 143k | decoder_sys_t *p_sys = p_dec->p_sys; |
291 | 143k | ogg_packet oggpacket; |
292 | | |
293 | 143k | if( *pp_block ) |
294 | 126k | { |
295 | | /* Block to Ogg packet */ |
296 | 126k | oggpacket.packet = (*pp_block)->p_buffer; |
297 | 126k | oggpacket.bytes = (*pp_block)->i_buffer; |
298 | 126k | } |
299 | 17.1k | else |
300 | 17.1k | { |
301 | 17.1k | if( p_sys->b_packetizer ) return NULL; |
302 | | |
303 | | /* Block to Ogg packet */ |
304 | 0 | oggpacket.packet = NULL; |
305 | 0 | oggpacket.bytes = 0; |
306 | 0 | } |
307 | | |
308 | 126k | oggpacket.granulepos = -1; |
309 | 126k | oggpacket.b_o_s = 0; |
310 | 126k | oggpacket.e_o_s = 0; |
311 | 126k | oggpacket.packetno = 0; |
312 | | |
313 | | /* Check for headers */ |
314 | 126k | if( !p_sys->b_has_headers ) |
315 | 89.8k | { |
316 | 89.8k | if( ProcessHeaders( p_dec ) ) |
317 | 89.7k | { |
318 | 89.7k | if( *pp_block ) |
319 | 89.7k | block_Release( *pp_block ); |
320 | 89.7k | return NULL; |
321 | 89.7k | } |
322 | 108 | p_sys->b_has_headers = true; |
323 | 108 | } |
324 | | |
325 | 36.4k | return ProcessPacket( p_dec, &oggpacket, pp_block ); |
326 | 126k | } |
327 | | |
328 | | static int DecodeAudio( decoder_t *p_dec, block_t *p_block ) |
329 | 38.5k | { |
330 | 38.5k | if( p_block == NULL ) /* No Drain */ |
331 | 20.5k | return VLCDEC_SUCCESS; |
332 | | |
333 | 17.9k | block_t **pp_block = &p_block, *p_out; |
334 | 17.9k | while( ( p_out = DecodeBlock( p_dec, pp_block ) ) != NULL ) |
335 | 0 | decoder_QueueAudio( p_dec, p_out ); |
336 | 17.9k | return VLCDEC_SUCCESS; |
337 | 38.5k | } |
338 | | |
339 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
340 | 125k | { |
341 | 125k | if( pp_block == NULL ) /* No Drain */ |
342 | 474 | return NULL; |
343 | 125k | return DecodeBlock( p_dec, pp_block ); |
344 | 125k | } |
345 | | |
346 | | /***************************************************************************** |
347 | | * ProcessHeaders: process Vorbis headers. |
348 | | *****************************************************************************/ |
349 | | static int ProcessHeaders( decoder_t *p_dec ) |
350 | 89.8k | { |
351 | 89.8k | decoder_sys_t *p_sys = p_dec->p_sys; |
352 | 89.8k | ogg_packet oggpacket; |
353 | | |
354 | 89.8k | size_t pi_size[XIPH_MAX_HEADER_COUNT]; |
355 | 89.8k | const void *pp_data[XIPH_MAX_HEADER_COUNT]; |
356 | 89.8k | size_t i_count; |
357 | 89.8k | if( xiph_SplitHeaders( pi_size, pp_data, &i_count, |
358 | 89.8k | p_dec->fmt_in->i_extra, p_dec->fmt_in->p_extra) ) |
359 | 24.7k | return VLC_EGENERIC; |
360 | 65.0k | if( i_count < 3 ) |
361 | 101 | return VLC_EGENERIC; |
362 | | |
363 | 64.9k | oggpacket.granulepos = -1; |
364 | 64.9k | oggpacket.e_o_s = 0; |
365 | 64.9k | oggpacket.packetno = 0; |
366 | | |
367 | | /* Take care of the initial Vorbis header */ |
368 | 64.9k | oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ |
369 | 64.9k | oggpacket.bytes = pi_size[0]; |
370 | 64.9k | oggpacket.packet = (void *)pp_data[0]; |
371 | 64.9k | if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) |
372 | 64.6k | { |
373 | 64.6k | msg_Err( p_dec, "this bitstream does not contain Vorbis audio data"); |
374 | 64.6k | return VLC_EGENERIC; |
375 | 64.6k | } |
376 | | |
377 | | /* Setup the format */ |
378 | 349 | p_dec->fmt_out.audio.i_rate = p_sys->vi.rate; |
379 | 349 | p_dec->fmt_out.audio.i_channels = p_sys->vi.channels; |
380 | | |
381 | 349 | if( p_dec->fmt_out.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) ) |
382 | 1 | { |
383 | 1 | msg_Err( p_dec, "invalid number of channels (1-%zu): %i", |
384 | 1 | ARRAY_SIZE(pi_channels_maps), |
385 | 1 | p_dec->fmt_out.audio.i_channels ); |
386 | 1 | return VLC_EGENERIC; |
387 | 1 | } |
388 | | |
389 | 348 | p_dec->fmt_out.audio.i_physical_channels = |
390 | 348 | pi_channels_maps[p_sys->vi.channels]; |
391 | 348 | p_dec->fmt_out.i_bitrate = __MAX( 0, (int32_t) p_sys->vi.bitrate_nominal ); |
392 | | |
393 | 348 | date_Init( &p_sys->end_date, p_sys->vi.rate, 1 ); |
394 | | |
395 | 348 | msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ud", |
396 | 348 | p_sys->vi.channels, p_sys->vi.rate, p_dec->fmt_out.i_bitrate ); |
397 | | |
398 | | /* The next packet in order is the comments header */ |
399 | 348 | oggpacket.b_o_s = 0; |
400 | 348 | oggpacket.bytes = pi_size[1]; |
401 | 348 | oggpacket.packet = (void *)pp_data[1]; |
402 | 348 | if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) |
403 | 217 | { |
404 | 217 | msg_Err( p_dec, "2nd Vorbis header is corrupted" ); |
405 | 217 | return VLC_EGENERIC; |
406 | 217 | } |
407 | 131 | ParseVorbisComments( p_dec ); |
408 | | |
409 | 131 | int i_ret = vlc_replay_gain_CopyFromMeta( &p_dec->fmt_out.audio_replay_gain, p_dec->p_description ); |
410 | | |
411 | | /* use replay gain if available; otherwise see vorbisgain(1) */ |
412 | 131 | if( i_ret != VLC_SUCCESS && p_dec->p_description != NULL ) |
413 | 2 | { |
414 | 2 | audio_replay_gain_t *p_arg = &p_dec->fmt_out.audio_replay_gain; |
415 | 2 | replay_gain_Reset( p_arg ); |
416 | | |
417 | 2 | const char *track_gain = vlc_meta_GetExtra( p_dec->p_description, "RG_RADIO" ); |
418 | 2 | if( track_gain ) |
419 | 0 | { |
420 | 0 | p_arg->pb_gain[AUDIO_REPLAY_GAIN_TRACK] = true; |
421 | 0 | p_arg->pf_gain[AUDIO_REPLAY_GAIN_TRACK] = vlc_strtof_c( track_gain, NULL ); |
422 | 0 | } |
423 | | |
424 | 2 | const char *track_peak = vlc_meta_GetExtra( p_dec->p_description, "RG_PEAK" ); |
425 | 2 | if( track_peak ) |
426 | 0 | { |
427 | 0 | p_arg->pb_peak[AUDIO_REPLAY_GAIN_TRACK] = true; |
428 | 0 | p_arg->pf_peak[AUDIO_REPLAY_GAIN_TRACK] = vlc_strtof_c( track_peak, NULL ); |
429 | 0 | } |
430 | | |
431 | 2 | const char *album_gain = vlc_meta_GetExtra( p_dec->p_description, "RG_AUDIOPHILE" ); |
432 | 2 | if( album_gain ) |
433 | 0 | { |
434 | 0 | p_arg->pb_gain[AUDIO_REPLAY_GAIN_ALBUM] = true; |
435 | 0 | p_arg->pf_gain[AUDIO_REPLAY_GAIN_ALBUM] = vlc_strtof_c( album_gain, NULL ); |
436 | 0 | } |
437 | 2 | } |
438 | | |
439 | | /* The next packet in order is the codebooks header |
440 | | * We need to watch out that this packet is not missing as a |
441 | | * missing or corrupted header is fatal. */ |
442 | 131 | oggpacket.b_o_s = 0; |
443 | 131 | oggpacket.bytes = pi_size[2]; |
444 | 131 | oggpacket.packet = (void *)pp_data[2]; |
445 | 131 | if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) |
446 | 23 | { |
447 | 23 | msg_Err( p_dec, "3rd Vorbis header is corrupted" ); |
448 | 23 | return VLC_EGENERIC; |
449 | 23 | } |
450 | | |
451 | 108 | if( !p_sys->b_packetizer ) |
452 | 49 | { |
453 | | /* Initialize the Vorbis packet->PCM decoder */ |
454 | 49 | vorbis_synthesis_init( &p_sys->vd, &p_sys->vi ); |
455 | 49 | vorbis_block_init( &p_sys->vd, &p_sys->vb ); |
456 | 49 | } |
457 | 59 | else |
458 | 59 | { |
459 | 59 | void* p_extra = realloc( p_dec->fmt_out.p_extra, |
460 | 59 | p_dec->fmt_in->i_extra ); |
461 | 59 | if( unlikely( p_extra == NULL ) ) |
462 | 0 | { |
463 | 0 | return VLC_ENOMEM; |
464 | 0 | } |
465 | 59 | p_dec->fmt_out.p_extra = p_extra; |
466 | 59 | p_dec->fmt_out.i_extra = p_dec->fmt_in->i_extra; |
467 | 59 | memcpy( p_dec->fmt_out.p_extra, |
468 | 59 | p_dec->fmt_in->p_extra, p_dec->fmt_out.i_extra ); |
469 | 59 | } |
470 | | |
471 | 108 | ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels, |
472 | 108 | p_dec->fmt_out.audio.i_physical_channels); |
473 | | |
474 | 108 | return VLC_SUCCESS; |
475 | 108 | } |
476 | | |
477 | | /***************************************************************************** |
478 | | * Flush: |
479 | | *****************************************************************************/ |
480 | | static void Flush( decoder_t *p_dec ) |
481 | 0 | { |
482 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
483 | |
|
484 | 0 | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
485 | 0 | } |
486 | | |
487 | | /***************************************************************************** |
488 | | * ProcessPacket: processes a Vorbis packet. |
489 | | *****************************************************************************/ |
490 | | static block_t *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, |
491 | | block_t **pp_block ) |
492 | 36.4k | { |
493 | 36.4k | decoder_sys_t *p_sys = p_dec->p_sys; |
494 | 36.4k | block_t *p_block = *pp_block; |
495 | | |
496 | 36.4k | *pp_block = NULL; /* To avoid being fed the same packet again */ |
497 | 36.4k | if( !p_block ) |
498 | 0 | return NULL; |
499 | | |
500 | 36.4k | if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) |
501 | 0 | { |
502 | 0 | Flush( p_dec ); |
503 | 0 | if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) |
504 | 0 | { |
505 | 0 | block_Release(p_block); |
506 | 0 | return NULL; |
507 | 0 | } |
508 | 0 | } |
509 | | |
510 | | /* Date management */ |
511 | 36.4k | vlc_tick_t pts = p_block->i_pts != VLC_TICK_INVALID ? p_block->i_pts : p_block->i_dts; |
512 | 36.4k | if( pts != VLC_TICK_INVALID && |
513 | 26.6k | pts != date_Get( &p_sys->end_date ) ) |
514 | 17.0k | { |
515 | 17.0k | date_Set( &p_sys->end_date, pts ); |
516 | 17.0k | } |
517 | | |
518 | 36.4k | if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID ) |
519 | 2.14k | { |
520 | | /* We've just started the stream, wait for the first PTS. */ |
521 | 2.14k | if( p_block ) block_Release( p_block ); |
522 | 2.14k | return NULL; |
523 | 2.14k | } |
524 | | |
525 | | |
526 | 34.2k | if( p_sys->b_packetizer ) |
527 | 17.1k | { |
528 | 17.1k | return SendPacket( p_dec, p_oggpacket, p_block ); |
529 | 17.1k | } |
530 | 17.1k | else |
531 | 17.1k | { |
532 | 17.1k | block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket ); |
533 | 17.1k | if( p_block ) |
534 | 17.1k | block_Release( p_block ); |
535 | 17.1k | return p_aout_buffer; |
536 | 17.1k | } |
537 | 34.2k | } |
538 | | |
539 | | /***************************************************************************** |
540 | | * Interleave: helper function to interleave channels |
541 | | *****************************************************************************/ |
542 | | static void Interleave( INTERLEAVE_TYPE *p_out, const INTERLEAVE_TYPE **pp_in, |
543 | | int i_nb_channels, int i_samples, uint8_t *pi_chan_table) |
544 | 0 | { |
545 | 0 | for( int j = 0; j < i_samples; j++ ) |
546 | 0 | for( int i = 0; i < i_nb_channels; i++ ) |
547 | 0 | { |
548 | | #ifdef PLUGIN_TREMOR |
549 | | union { int32_t i; uint32_t u;} spl; |
550 | | |
551 | | spl.u = ((uint32_t)pp_in[i][j]) << 8; |
552 | | p_out[j * i_nb_channels + pi_chan_table[i]] = spl.i; |
553 | | #else |
554 | 0 | p_out[j * i_nb_channels + pi_chan_table[i]] = pp_in[i][j]; |
555 | 0 | #endif |
556 | 0 | } |
557 | 0 | } |
558 | | |
559 | | /***************************************************************************** |
560 | | * DecodePacket: decodes a Vorbis packet. |
561 | | *****************************************************************************/ |
562 | | static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) |
563 | 17.1k | { |
564 | 17.1k | decoder_sys_t *p_sys = p_dec->p_sys; |
565 | 17.1k | int i_samples; |
566 | | |
567 | 17.1k | INTERLEAVE_TYPE **pp_pcm; |
568 | | |
569 | 17.1k | if( p_oggpacket->bytes && |
570 | 16.8k | vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 ) |
571 | 16.6k | vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb ); |
572 | | |
573 | | /* **pp_pcm is a multichannel float vector. In stereo, for |
574 | | * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is |
575 | | * the size of each channel. Convert the float values |
576 | | * (-1.<=range<=1.) to whatever PCM format and write it out */ |
577 | | |
578 | 17.1k | if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 ) |
579 | 16.9k | { |
580 | | |
581 | 16.9k | block_t *p_aout_buffer; |
582 | | |
583 | 16.9k | if( decoder_UpdateAudioFormat( p_dec ) ) return NULL; |
584 | 0 | p_aout_buffer = |
585 | 0 | decoder_NewAudioBuffer( p_dec, i_samples ); |
586 | |
|
587 | 0 | if( p_aout_buffer == NULL ) return NULL; |
588 | | |
589 | | /* Interleave the samples */ |
590 | 0 | Interleave( (INTERLEAVE_TYPE*)p_aout_buffer->p_buffer, |
591 | 0 | (const INTERLEAVE_TYPE**)pp_pcm, p_sys->vi.channels, i_samples, |
592 | 0 | p_sys->pi_chan_table); |
593 | | |
594 | | /* Tell libvorbis how many samples we actually consumed */ |
595 | 0 | vorbis_synthesis_read( &p_sys->vd, i_samples ); |
596 | | |
597 | | /* Date management */ |
598 | 0 | p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); |
599 | 0 | p_aout_buffer->i_length = date_Increment( &p_sys->end_date, |
600 | 0 | i_samples ) - p_aout_buffer->i_pts; |
601 | 0 | return p_aout_buffer; |
602 | 0 | } |
603 | 168 | else |
604 | 168 | { |
605 | 168 | return NULL; |
606 | 168 | } |
607 | 17.1k | } |
608 | | |
609 | | /***************************************************************************** |
610 | | * SendPacket: send an ogg dated packet to the stream output. |
611 | | *****************************************************************************/ |
612 | | static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, |
613 | | block_t *p_block ) |
614 | 17.1k | { |
615 | 17.1k | decoder_sys_t *p_sys = p_dec->p_sys; |
616 | 17.1k | int i_block_size, i_samples; |
617 | | |
618 | 17.1k | i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket ); |
619 | 17.1k | if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */ |
620 | 17.1k | i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2; |
621 | 17.1k | p_sys->i_last_block_size = i_block_size; |
622 | | |
623 | | /* Date management */ |
624 | 17.1k | p_block->i_dts = p_block->i_pts = date_Get( &p_sys->end_date ); |
625 | | |
626 | 17.1k | p_block->i_length = date_Increment( &p_sys->end_date, i_samples ) - p_block->i_pts; |
627 | | |
628 | 17.1k | return p_block; |
629 | 17.1k | } |
630 | | |
631 | | /***************************************************************************** |
632 | | * ParseVorbisComments |
633 | | *****************************************************************************/ |
634 | | static void ParseVorbisComments( decoder_t *p_dec ) |
635 | 131 | { |
636 | 131 | char *psz_name, *psz_value, *psz_comment; |
637 | 131 | int i = 0; |
638 | | |
639 | 131 | decoder_sys_t *p_sys = p_dec->p_sys; |
640 | | |
641 | 138 | while( i < p_sys->vc.comments ) |
642 | 7 | { |
643 | 7 | psz_comment = strdup( p_sys->vc.user_comments[i] ); |
644 | 7 | if( !psz_comment ) |
645 | 0 | break; |
646 | 7 | psz_name = psz_comment; |
647 | 7 | psz_value = strchr( psz_comment, '=' ); |
648 | | /* Don't add empty values */ |
649 | 7 | if( psz_value && psz_value[1] != '\0') |
650 | 6 | { |
651 | 6 | *psz_value = '\0'; |
652 | 6 | psz_value++; |
653 | | |
654 | 6 | if( !strcasecmp( psz_name, "METADATA_BLOCK_PICTURE" ) ) |
655 | 0 | { /* Do nothing, for now */ } |
656 | 6 | else |
657 | 6 | { |
658 | 6 | if( !p_dec->p_description ) |
659 | 2 | p_dec->p_description = vlc_meta_New(); |
660 | 6 | if( p_dec->p_description ) |
661 | 6 | vlc_meta_SetExtra( p_dec->p_description, psz_name, psz_value ); |
662 | 6 | } |
663 | | |
664 | 6 | } |
665 | 7 | free( psz_comment ); |
666 | 7 | i++; |
667 | 7 | } |
668 | 131 | } |
669 | | |
670 | | /***************************************************************************** |
671 | | * |
672 | | *****************************************************************************/ |
673 | | static void ConfigureChannelOrder(uint8_t *pi_chan_table, int i_channels, |
674 | | uint32_t i_channel_mask) |
675 | 108 | { |
676 | 108 | const uint32_t *pi_channels_in; |
677 | 108 | switch( i_channels ) |
678 | 108 | { |
679 | 0 | case 8: |
680 | 0 | pi_channels_in = pi_8channels_in; |
681 | 0 | break; |
682 | 0 | case 7: |
683 | 0 | pi_channels_in = pi_7channels_in; |
684 | 0 | break; |
685 | 4 | case 6: |
686 | 4 | case 5: |
687 | 4 | pi_channels_in = pi_6channels_in; |
688 | 4 | break; |
689 | 0 | case 4: |
690 | 0 | pi_channels_in = pi_4channels_in; |
691 | 0 | break; |
692 | 0 | case 3: |
693 | 0 | pi_channels_in = pi_3channels_in; |
694 | 0 | break; |
695 | 104 | default: |
696 | 264 | for( int i = 0; i< i_channels; ++i ) |
697 | 160 | pi_chan_table[i] = i; |
698 | | |
699 | 104 | return; |
700 | 108 | } |
701 | | |
702 | 4 | aout_CheckChannelReorder( pi_channels_in, NULL, |
703 | 4 | i_channel_mask, pi_chan_table ); |
704 | 4 | } |
705 | | |
706 | | /***************************************************************************** |
707 | | * CloseDecoder: vorbis decoder destruction |
708 | | *****************************************************************************/ |
709 | | static void CloseDecoder( vlc_object_t *p_this ) |
710 | 1.00k | { |
711 | 1.00k | decoder_t *p_dec = (decoder_t *)p_this; |
712 | 1.00k | decoder_sys_t *p_sys = p_dec->p_sys; |
713 | | |
714 | 1.00k | if( !p_sys->b_packetizer && p_sys->b_has_headers ) |
715 | 49 | { |
716 | 49 | vorbis_block_clear( &p_sys->vb ); |
717 | 49 | vorbis_dsp_clear( &p_sys->vd ); |
718 | 49 | } |
719 | | |
720 | 1.00k | vorbis_comment_clear( &p_sys->vc ); |
721 | 1.00k | vorbis_info_clear( &p_sys->vi ); /* must be called last */ |
722 | | |
723 | 1.00k | free( p_sys ); |
724 | 1.00k | } |
725 | | |
726 | | #ifdef HAVE_VORBIS_ENCODER |
727 | | /***************************************************************************** |
728 | | * encoder_sys_t : vorbis encoder descriptor |
729 | | *****************************************************************************/ |
730 | | typedef struct |
731 | | { |
732 | | /* |
733 | | * Vorbis properties |
734 | | */ |
735 | | vorbis_info vi; /* struct that stores all the static vorbis bitstream |
736 | | settings */ |
737 | | vorbis_comment vc; /* struct that stores all the bitstream user |
738 | | * comments */ |
739 | | vorbis_dsp_state vd; /* central working state for the packet->PCM |
740 | | * decoder */ |
741 | | vorbis_block vb; /* local working space for packet->PCM decode */ |
742 | | |
743 | | int i_last_block_size; |
744 | | int i_samples_delay; |
745 | | |
746 | | /* |
747 | | ** Channel reordering |
748 | | */ |
749 | | uint8_t pi_chan_table[AOUT_CHAN_MAX]; |
750 | | |
751 | | } encoder_sys_t; |
752 | | |
753 | | /***************************************************************************** |
754 | | * OpenEncoder: probe the encoder and return score |
755 | | *****************************************************************************/ |
756 | | static int OpenEncoder( vlc_object_t *p_this ) |
757 | 0 | { |
758 | 0 | encoder_t *p_enc = (encoder_t *)p_this; |
759 | 0 | encoder_sys_t *p_sys; |
760 | 0 | int i_quality, i_min_bitrate, i_max_bitrate; |
761 | 0 | ogg_packet header[3]; |
762 | |
|
763 | 0 | if( p_enc->fmt_out.i_codec != VLC_CODEC_VORBIS && |
764 | 0 | !p_enc->obj.force ) |
765 | 0 | { |
766 | 0 | return VLC_EGENERIC; |
767 | 0 | } |
768 | | |
769 | | /* Allocate the memory needed to store the decoder's structure */ |
770 | 0 | if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) |
771 | 0 | return VLC_ENOMEM; |
772 | | |
773 | 0 | p_enc->fmt_in.i_codec = VLC_CODEC_FL32; |
774 | 0 | p_enc->fmt_out.i_codec = VLC_CODEC_VORBIS; |
775 | |
|
776 | 0 | if( p_enc->fmt_in.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) ) |
777 | 0 | { |
778 | 0 | p_enc->fmt_in.audio.i_channels = ARRAY_SIZE(pi_channels_maps) - 1; |
779 | 0 | msg_Warn( p_enc, "lowering channel count to %u", p_enc->fmt_in.audio.i_channels ); |
780 | 0 | } |
781 | 0 | config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); |
782 | |
|
783 | 0 | i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" ); |
784 | 0 | if( i_quality > 10 ) i_quality = 10; |
785 | 0 | if( i_quality < 0 ) i_quality = 0; |
786 | |
|
787 | 0 | if( var_GetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ) i_quality = 0; |
788 | 0 | i_max_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "max-bitrate" ); |
789 | 0 | i_min_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "min-bitrate" ); |
790 | | |
791 | | /* Initialize vorbis encoder */ |
792 | 0 | vorbis_info_init( &p_sys->vi ); |
793 | |
|
794 | 0 | if( i_quality > 0 ) |
795 | 0 | { |
796 | | /* VBR mode */ |
797 | 0 | if( vorbis_encode_setup_vbr( &p_sys->vi, |
798 | 0 | p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate, |
799 | 0 | i_quality * 0.1 ) ) |
800 | 0 | { |
801 | 0 | msg_Err( p_enc, "VBR mode initialisation failed %"PRIu8"x(%uHz,q=%d)", |
802 | 0 | p_enc->fmt_in.audio.i_channels, |
803 | 0 | p_enc->fmt_in.audio.i_rate, i_quality ); |
804 | 0 | goto error; |
805 | 0 | } |
806 | | |
807 | | /* Do we have optional hard quality restrictions? */ |
808 | 0 | if( i_max_bitrate > 0 || i_min_bitrate > 0 ) |
809 | 0 | { |
810 | 0 | struct ovectl_ratemanage_arg ai; |
811 | 0 | vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai ); |
812 | |
|
813 | 0 | ai.bitrate_hard_min = i_min_bitrate; |
814 | 0 | ai.bitrate_hard_max = i_max_bitrate; |
815 | 0 | ai.management_active = 1; |
816 | |
|
817 | 0 | vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai ); |
818 | |
|
819 | 0 | } |
820 | 0 | else |
821 | 0 | { |
822 | | /* Turn off management entirely */ |
823 | 0 | vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL ); |
824 | 0 | } |
825 | 0 | } |
826 | 0 | else |
827 | 0 | { |
828 | 0 | if( vorbis_encode_setup_managed( &p_sys->vi, |
829 | 0 | p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate, |
830 | 0 | i_min_bitrate > 0 ? i_min_bitrate * 1000: -1, |
831 | 0 | p_enc->fmt_out.i_bitrate, |
832 | 0 | i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) ) |
833 | 0 | { |
834 | 0 | msg_Err( p_enc, "CBR mode initialisation failed %"PRIu8"x(%uHz,r=%u)", |
835 | 0 | p_enc->fmt_in.audio.i_channels, |
836 | 0 | p_enc->fmt_in.audio.i_rate, |
837 | 0 | p_enc->fmt_out.i_bitrate); |
838 | 0 | goto error; |
839 | 0 | } |
840 | 0 | } |
841 | | |
842 | 0 | vorbis_encode_setup_init( &p_sys->vi ); |
843 | | |
844 | | /* Add a comment */ |
845 | 0 | vorbis_comment_init( &p_sys->vc); |
846 | 0 | vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player"); |
847 | | |
848 | | /* Set up the analysis state and auxiliary encoding storage */ |
849 | 0 | vorbis_analysis_init( &p_sys->vd, &p_sys->vi ); |
850 | 0 | vorbis_block_init( &p_sys->vd, &p_sys->vb ); |
851 | | |
852 | | /* Create and store headers */ |
853 | 0 | vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc, |
854 | 0 | &header[0], &header[1], &header[2]); |
855 | 0 | for( int i = 0; i < 3; i++ ) |
856 | 0 | { |
857 | 0 | if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra, &p_enc->fmt_out.p_extra, |
858 | 0 | header[i].bytes, header[i].packet ) ) |
859 | 0 | { |
860 | 0 | free(p_enc->fmt_out.p_extra); |
861 | 0 | p_enc->fmt_out.i_extra = 0; |
862 | 0 | p_enc->fmt_out.p_extra = NULL; |
863 | 0 | } |
864 | 0 | } |
865 | |
|
866 | 0 | assert(p_sys->vi.channels > 0 && (size_t) p_sys->vi.channels < ARRAY_SIZE(pi_channels_maps) ); |
867 | |
|
868 | 0 | p_enc->fmt_out.audio.i_channels = p_enc->fmt_in.audio.i_channels = |
869 | 0 | p_sys->vi.channels; |
870 | |
|
871 | 0 | p_enc->fmt_out.audio.i_physical_channels = |
872 | 0 | p_enc->fmt_in.audio.i_physical_channels = |
873 | 0 | pi_channels_maps[p_sys->vi.channels]; |
874 | |
|
875 | 0 | p_sys->i_last_block_size = 0; |
876 | 0 | p_sys->i_samples_delay = 0; |
877 | |
|
878 | 0 | ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels, |
879 | 0 | p_enc->fmt_in.audio.i_physical_channels); |
880 | |
|
881 | 0 | static const struct vlc_encoder_operations ops = |
882 | 0 | { |
883 | 0 | .close = CloseEncoder, |
884 | 0 | .encode_audio = Encode, |
885 | 0 | }; |
886 | 0 | p_enc->ops = &ops; |
887 | 0 | p_enc->p_sys = p_sys; |
888 | |
|
889 | 0 | return VLC_SUCCESS; |
890 | 0 | error: |
891 | 0 | vorbis_info_clear( &p_sys->vi ); |
892 | 0 | free(p_sys); |
893 | 0 | return VLC_EGENERIC; |
894 | 0 | } |
895 | | |
896 | | /**************************************************************************** |
897 | | * Encode: the whole thing |
898 | | **************************************************************************** |
899 | | * This function spits out ogg packets. |
900 | | ****************************************************************************/ |
901 | | static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf ) |
902 | 0 | { |
903 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
904 | 0 | ogg_packet oggpacket; |
905 | 0 | block_t *p_block, *p_chain = NULL; |
906 | 0 | float **buffer; |
907 | | |
908 | | /* Packets are already flushed, see below. */ |
909 | 0 | if( unlikely( !p_aout_buf ) ) return NULL; |
910 | | |
911 | 0 | vlc_tick_t i_pts = p_aout_buf->i_pts - |
912 | 0 | vlc_tick_from_samples( p_sys->i_samples_delay, |
913 | 0 | p_enc->fmt_in.audio.i_rate ); |
914 | |
|
915 | 0 | p_sys->i_samples_delay += p_aout_buf->i_nb_samples; |
916 | |
|
917 | 0 | buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples ); |
918 | | |
919 | | /* convert samples to float and uninterleave */ |
920 | 0 | const unsigned i_channels = p_enc->fmt_in.audio.i_channels; |
921 | 0 | for( unsigned int i = 0; i < i_channels; i++ ) |
922 | 0 | { |
923 | 0 | for( unsigned int j = 0 ; j < p_aout_buf->i_nb_samples ; j++ ) |
924 | 0 | { |
925 | 0 | buffer[i][j]= ((float *)p_aout_buf->p_buffer) |
926 | 0 | [j * i_channels + p_sys->pi_chan_table[i]]; |
927 | 0 | } |
928 | 0 | } |
929 | |
|
930 | 0 | vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples ); |
931 | |
|
932 | 0 | while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 ) |
933 | 0 | { |
934 | 0 | int i_samples; |
935 | |
|
936 | 0 | vorbis_analysis( &p_sys->vb, NULL ); |
937 | 0 | vorbis_bitrate_addblock( &p_sys->vb ); |
938 | |
|
939 | 0 | while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) ) |
940 | 0 | { |
941 | 0 | int i_block_size; |
942 | 0 | p_block = block_Alloc( oggpacket.bytes ); |
943 | 0 | if( unlikely(p_block == NULL) ) { |
944 | 0 | block_ChainRelease( p_chain ); |
945 | 0 | p_chain = NULL; |
946 | 0 | break; |
947 | 0 | } |
948 | | |
949 | 0 | memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes ); |
950 | |
|
951 | 0 | i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket ); |
952 | |
|
953 | 0 | if( i_block_size < 0 ) i_block_size = 0; |
954 | 0 | i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2; |
955 | 0 | p_sys->i_last_block_size = i_block_size; |
956 | |
|
957 | 0 | p_block->i_length = vlc_tick_from_samples(i_samples, |
958 | 0 | p_enc->fmt_in.audio.i_rate); |
959 | |
|
960 | 0 | p_block->i_dts = p_block->i_pts = i_pts; |
961 | |
|
962 | 0 | p_sys->i_samples_delay -= i_samples; |
963 | | |
964 | | /* Update pts */ |
965 | 0 | i_pts += p_block->i_length; |
966 | 0 | block_ChainAppend( &p_chain, p_block ); |
967 | 0 | } |
968 | 0 | } |
969 | |
|
970 | 0 | return p_chain; |
971 | 0 | } |
972 | | |
973 | | /***************************************************************************** |
974 | | * CloseEncoder: vorbis encoder destruction |
975 | | *****************************************************************************/ |
976 | | static void CloseEncoder( encoder_t *p_enc ) |
977 | 0 | { |
978 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
979 | |
|
980 | 0 | vorbis_block_clear( &p_sys->vb ); |
981 | 0 | vorbis_dsp_clear( &p_sys->vd ); |
982 | 0 | vorbis_comment_clear( &p_sys->vc ); |
983 | 0 | vorbis_info_clear( &p_sys->vi ); /* must be called last */ |
984 | |
|
985 | 0 | free( p_sys ); |
986 | 0 | } |
987 | | |
988 | | #endif /* HAVE_VORBIS_ENCODER */ |