/src/vlc/modules/codec/lpcm.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * lpcm.c: lpcm decoder/packetizer module |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 1999-2008 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Samuel Hocevar <sam@zoy.org> |
7 | | * Henri Fallon <henri@videolan.org> |
8 | | * Christophe Massiot <massiot@via.ecp.fr> |
9 | | * Gildas Bazin <gbazin@videolan.org> |
10 | | * Lauren Aimar <fenrir _AT_ videolan _DOT_ org > |
11 | | * Steinar H. Gunderson <steinar+vlc@gunderson.no> |
12 | | * |
13 | | * This program is free software; you can redistribute it and/or modify it |
14 | | * under the terms of the GNU Lesser General Public License as published by |
15 | | * the Free Software Foundation; either version 2.1 of the License, or |
16 | | * (at your option) any later version. |
17 | | * |
18 | | * This program is distributed in the hope that it will be useful, |
19 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | | * GNU Lesser General Public License for more details. |
22 | | * |
23 | | * You should have received a copy of the GNU Lesser General Public License |
24 | | * along with this program; if not, write to the Free Software Foundation, |
25 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
26 | | *****************************************************************************/ |
27 | | |
28 | | /***************************************************************************** |
29 | | * Preamble |
30 | | *****************************************************************************/ |
31 | | #ifdef HAVE_CONFIG_H |
32 | | # include "config.h" |
33 | | #endif |
34 | | |
35 | | #include <vlc_common.h> |
36 | | #include <vlc_plugin.h> |
37 | | #include <vlc_codec.h> |
38 | | #include <vlc_aout.h> |
39 | | #include <unistd.h> |
40 | | #include <assert.h> |
41 | | |
42 | | /***************************************************************************** |
43 | | * Module descriptor |
44 | | *****************************************************************************/ |
45 | | static int OpenDecoder ( vlc_object_t * ); |
46 | | static int OpenPacketizer( vlc_object_t * ); |
47 | | |
48 | | #ifdef ENABLE_SOUT |
49 | | static int OpenEncoder ( vlc_object_t * ); |
50 | | static void CloseEncoder ( encoder_t * ); |
51 | | static block_t *EncodeFrames( encoder_t *, block_t * ); |
52 | | #endif |
53 | | |
54 | 104 | vlc_module_begin () |
55 | | |
56 | 52 | set_subcategory( SUBCAT_INPUT_ACODEC ) |
57 | 52 | set_description( N_("Linear PCM audio decoder") ) |
58 | 52 | set_capability( "audio decoder", 100 ) |
59 | 52 | set_callback( OpenDecoder ) |
60 | | |
61 | 52 | add_submodule () |
62 | 52 | set_description( N_("Linear PCM audio packetizer") ) |
63 | 52 | set_capability( "audio packetizer", 100 ) |
64 | 52 | set_callback( OpenPacketizer ) |
65 | | |
66 | 52 | #ifdef ENABLE_SOUT |
67 | 52 | add_submodule () |
68 | 52 | set_description( N_("Linear PCM audio encoder") ) |
69 | 52 | set_capability( "audio encoder", 100 ) |
70 | 52 | set_callback( OpenEncoder ) |
71 | 52 | add_shortcut( "lpcm" ) |
72 | 52 | #endif |
73 | | |
74 | 52 | vlc_module_end () |
75 | | |
76 | | |
77 | | /***************************************************************************** |
78 | | * decoder_sys_t : lpcm decoder descriptor |
79 | | *****************************************************************************/ |
80 | | typedef struct |
81 | | { |
82 | | /* Module mode */ |
83 | | bool b_packetizer; |
84 | | |
85 | | /* |
86 | | * Output properties |
87 | | */ |
88 | | date_t end_date; |
89 | | |
90 | | /* */ |
91 | | unsigned i_header_size; |
92 | | int i_type; |
93 | | uint8_t i_chans_to_reorder; |
94 | | uint8_t pi_chan_table[AOUT_CHAN_MAX]; |
95 | | } decoder_sys_t; |
96 | | |
97 | | #ifdef ENABLE_SOUT |
98 | | typedef struct |
99 | | { |
100 | | int i_channels; |
101 | | int i_rate; |
102 | | |
103 | | int i_frame_samples; |
104 | | uint8_t *p_buffer; |
105 | | int i_buffer_used; |
106 | | int i_frame_num; |
107 | | } encoder_sys_t; |
108 | | #endif |
109 | | |
110 | | /* |
111 | | * LPCM DVD header : |
112 | | * - number of frames in this packet (8 bits) |
113 | | * - first access unit (16 bits) == 0x0003 ? |
114 | | * - emphasis (1 bit) |
115 | | * - mute (1 bit) |
116 | | * - reserved (1 bit) |
117 | | * - current frame (5 bits) |
118 | | * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal |
119 | | * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz |
120 | | * - reserved (1 bit) |
121 | | * - number of channels - 1 (3 bits) 1 == 2 channels |
122 | | * - dynamic range (8 bits) 0x80 == neutral |
123 | | * |
124 | | * LPCM DVD-A header (http://dvd-audio.sourceforge.net/spec/aob.shtml) |
125 | | * - continuity counter (8 bits, clipped to 0x00-0x1f) |
126 | | * - header size (16 bits) |
127 | | * - byte pointer to start of first audio frame. |
128 | | * - unknown (8bits, 0x10 for stereo, 0x00 for surround) |
129 | | * - sample size (4+4 bits) |
130 | | * - samplerate (4+4 bits) |
131 | | * - unknown (8 bits) |
132 | | * - group assignment (8 bits) |
133 | | * - unknown (8 bits) |
134 | | * - padding(variable) |
135 | | * |
136 | | * LPCM BD header : |
137 | | * - unknown (16 bits) |
138 | | * - number of channels (4 bits) |
139 | | * - frequency (4 bits) |
140 | | * - bits per sample (2 bits) |
141 | | * - unknown (6 bits) |
142 | | * |
143 | | * LPCM WIDI header |
144 | | * refers http://www.dvdforum.org/images/Guideline1394V10R0_20020911.pdf |
145 | | * - sub stream id (8 bits) = 0xa0 |
146 | | * - frame header count (8 bits) = 0x06 |
147 | | * [ 0b0000000 (7 bits) |
148 | | * - audio emphasis (1 bit) ] (8 bits) |
149 | | * [ qz word length (2 bits) 0x00 == 16bits |
150 | | * - sampling freq (3 bits) 0b001 == 44.1K, 0b010 == 48K Hz |
151 | | * - channels count(3 bits) ] (8 bits) 0b000 == dual mono, 0b001 == stereo |
152 | | * follows: LPCM data (15360 bits/1920 bytes) |
153 | | */ |
154 | | |
155 | 457 | #define LPCM_VOB_HEADER_LEN (6) |
156 | 70.2k | #define LPCM_AOB_HEADER_LEN (11) |
157 | 6.10k | #define LPCM_BD_HEADER_LEN (4) |
158 | 19 | #define LPCM_WIDI_HEADER_LEN (4) |
159 | | |
160 | | enum |
161 | | { |
162 | | LPCM_VOB, |
163 | | LPCM_AOB, |
164 | | LPCM_BD, |
165 | | LPCM_WIDI, |
166 | | }; |
167 | | |
168 | | typedef struct |
169 | | { |
170 | | unsigned i_channels; |
171 | | unsigned i_bits; |
172 | | unsigned pi_position[6]; |
173 | | } aob_group_t; |
174 | | |
175 | | /***************************************************************************** |
176 | | * Local prototypes |
177 | | *****************************************************************************/ |
178 | | static int DecodeFrame ( decoder_t *, block_t * ); |
179 | | static block_t *Packetize ( decoder_t *, block_t ** ); |
180 | | static void Flush( decoder_t * ); |
181 | | |
182 | | /* */ |
183 | | static int VobHeader( unsigned *pi_rate, |
184 | | unsigned *pi_channels, unsigned *pi_original_channels, |
185 | | unsigned *pi_bits, |
186 | | const uint8_t *p_header ); |
187 | | static void VobExtract( block_t *, block_t *, unsigned i_bits ); |
188 | | /* */ |
189 | | static int AobHeader( unsigned *pi_rate, |
190 | | unsigned *pi_channels, unsigned *pi_layout, |
191 | | unsigned *pi_bits, |
192 | | unsigned *pi_padding, |
193 | | aob_group_t g[2], |
194 | | const uint8_t *p_header ); |
195 | | static void AobExtract( block_t *, block_t *, unsigned i_bits, aob_group_t p_group[2] ); |
196 | | /* */ |
197 | | static int BdHeader( decoder_sys_t *p_sys, |
198 | | unsigned *pi_rate, |
199 | | unsigned *pi_channels, |
200 | | unsigned *pi_channels_padding, |
201 | | unsigned *pi_original_channels, |
202 | | unsigned *pi_bits, |
203 | | const uint8_t *p_header ); |
204 | | static void BdExtract( block_t *, block_t *, unsigned, unsigned, unsigned, unsigned ); |
205 | | /* */ |
206 | | static int WidiHeader( unsigned *pi_rate, |
207 | | unsigned *pi_channels, unsigned *pi_original_channels, |
208 | | unsigned *pi_bits, |
209 | | const uint8_t *p_header ); |
210 | | |
211 | | /***************************************************************************** |
212 | | * OpenCommon: |
213 | | *****************************************************************************/ |
214 | | static int OpenCommon( decoder_t *p_dec, bool b_packetizer ) |
215 | 2.37M | { |
216 | 2.37M | decoder_sys_t *p_sys; |
217 | 2.37M | int i_type; |
218 | 2.37M | int i_header_size; |
219 | | |
220 | 2.37M | switch( p_dec->fmt_in->i_codec ) |
221 | 2.37M | { |
222 | | /* DVD LPCM */ |
223 | 457 | case VLC_CODEC_DVD_LPCM: |
224 | 457 | i_type = LPCM_VOB; |
225 | 457 | i_header_size = LPCM_VOB_HEADER_LEN; |
226 | 457 | break; |
227 | | /* DVD-Audio LPCM */ |
228 | 878 | case VLC_CODEC_DVDA_LPCM: |
229 | 878 | i_type = LPCM_AOB; |
230 | 878 | i_header_size = LPCM_AOB_HEADER_LEN; |
231 | 878 | break; |
232 | | /* BD LPCM */ |
233 | 6.10k | case VLC_CODEC_BD_LPCM: |
234 | 6.10k | i_type = LPCM_BD; |
235 | 6.10k | i_header_size = LPCM_BD_HEADER_LEN; |
236 | 6.10k | break; |
237 | | /* WIDI LPCM */ |
238 | 19 | case VLC_CODEC_WIDI_LPCM: |
239 | 19 | i_type = LPCM_WIDI; |
240 | 19 | i_header_size = LPCM_WIDI_HEADER_LEN; |
241 | 19 | break; |
242 | 2.36M | default: |
243 | 2.36M | return VLC_EGENERIC; |
244 | 2.37M | } |
245 | | |
246 | | /* Allocate the memory needed to store the decoder's structure */ |
247 | 7.45k | p_sys = vlc_obj_malloc(VLC_OBJECT(p_dec), sizeof (*p_sys)); |
248 | 7.45k | if (unlikely(p_sys == NULL)) |
249 | 0 | return VLC_ENOMEM; |
250 | | |
251 | | /* Misc init */ |
252 | 7.45k | p_sys->b_packetizer = b_packetizer; |
253 | 7.45k | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
254 | 7.45k | p_sys->i_type = i_type; |
255 | 7.45k | p_sys->i_header_size = i_header_size; |
256 | 7.45k | p_sys->i_chans_to_reorder = 0; |
257 | | |
258 | | /* Set output properties */ |
259 | 7.45k | if( b_packetizer ) |
260 | 237 | { |
261 | 237 | switch( i_type ) |
262 | 237 | { |
263 | 105 | case LPCM_VOB: |
264 | 105 | p_dec->fmt_out.i_codec = VLC_CODEC_DVD_LPCM; |
265 | 105 | break; |
266 | 95 | case LPCM_AOB: |
267 | 95 | p_dec->fmt_out.i_codec = VLC_CODEC_DVDA_LPCM; |
268 | 95 | break; |
269 | 9 | case LPCM_WIDI: |
270 | 9 | p_dec->fmt_out.i_codec = VLC_CODEC_WIDI_LPCM; |
271 | 9 | break; |
272 | 0 | default: |
273 | 0 | vlc_assert_unreachable(); |
274 | 28 | case LPCM_BD: |
275 | 28 | p_dec->fmt_out.i_codec = VLC_CODEC_BD_LPCM; |
276 | 28 | break; |
277 | 237 | } |
278 | 237 | } |
279 | 7.21k | else |
280 | 7.21k | { |
281 | 7.21k | switch( p_dec->fmt_out.audio.i_bitspersample ) |
282 | 7.21k | { |
283 | 0 | case 24: |
284 | 0 | case 20: |
285 | 0 | p_dec->fmt_out.i_codec = VLC_CODEC_S32N; |
286 | 0 | p_dec->fmt_out.audio.i_bitspersample = 32; |
287 | 0 | break; |
288 | 7.21k | default: |
289 | 7.21k | p_dec->fmt_out.i_codec = VLC_CODEC_S16N; |
290 | 7.21k | p_dec->fmt_out.audio.i_bitspersample = 16; |
291 | 7.21k | break; |
292 | 7.21k | } |
293 | 7.21k | } |
294 | | |
295 | | /* Set callback */ |
296 | 7.45k | if( !b_packetizer ) |
297 | 7.21k | p_dec->pf_decode = DecodeFrame; |
298 | 237 | else |
299 | 237 | p_dec->pf_packetize = Packetize; |
300 | 7.45k | p_dec->pf_flush = Flush; |
301 | 7.45k | p_dec->p_sys = p_sys; |
302 | 7.45k | return VLC_SUCCESS; |
303 | 7.45k | } |
304 | | static int OpenDecoder( vlc_object_t *p_this ) |
305 | 486k | { |
306 | 486k | return OpenCommon( (decoder_t*) p_this, false ); |
307 | 486k | } |
308 | | static int OpenPacketizer( vlc_object_t *p_this ) |
309 | 1.88M | { |
310 | 1.88M | return OpenCommon( (decoder_t*) p_this, true ); |
311 | 1.88M | } |
312 | | |
313 | | /***************************************************************************** |
314 | | * Flush: |
315 | | *****************************************************************************/ |
316 | | static void Flush( decoder_t *p_dec ) |
317 | 1.56k | { |
318 | 1.56k | decoder_sys_t *p_sys = p_dec->p_sys; |
319 | | |
320 | 1.56k | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
321 | 1.56k | } |
322 | | |
323 | | /***************************************************************************** |
324 | | * DecodeFrame: decodes an lpcm frame. |
325 | | **************************************************************************** |
326 | | * Beware, this function must be fed with complete frames (PES packet). |
327 | | *****************************************************************************/ |
328 | | static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) |
329 | 310k | { |
330 | 310k | decoder_sys_t *p_sys = p_dec->p_sys; |
331 | 310k | block_t *p_block; |
332 | 310k | unsigned int i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0; |
333 | 310k | int i_frame_length; |
334 | | |
335 | 310k | if( !pp_block || !*pp_block ) return NULL; |
336 | | |
337 | 151k | p_block = *pp_block; |
338 | 151k | *pp_block = NULL; /* So the packet doesn't get re-sent */ |
339 | | |
340 | 151k | if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) ) |
341 | 1.56k | { |
342 | 1.56k | Flush( p_dec ); |
343 | 1.56k | if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) |
344 | 0 | { |
345 | 0 | block_Release( p_block ); |
346 | 0 | *pp_block = NULL; |
347 | 0 | return NULL; |
348 | 0 | } |
349 | 1.56k | } |
350 | | |
351 | | /* Date management */ |
352 | 151k | if( p_block->i_pts != VLC_TICK_INVALID && |
353 | 151k | p_block->i_pts != date_Get( &p_sys->end_date ) ) |
354 | 61.0k | { |
355 | 61.0k | date_Set( &p_sys->end_date, p_block->i_pts ); |
356 | 61.0k | } |
357 | | |
358 | 151k | if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID ) |
359 | 77 | { |
360 | | /* We've just started the stream, wait for the first PTS. */ |
361 | 77 | block_Release( p_block ); |
362 | 77 | return NULL; |
363 | 77 | } |
364 | | |
365 | 151k | if( p_block->i_buffer <= p_sys->i_header_size ) |
366 | 84 | { |
367 | 84 | msg_Err(p_dec, "frame is too short"); |
368 | 84 | block_Release( p_block ); |
369 | 84 | return NULL; |
370 | 84 | } |
371 | | |
372 | 151k | int i_ret; |
373 | 151k | unsigned i_channels_padding = 0; |
374 | 151k | unsigned i_padding = 0; /* only for AOB */ |
375 | 151k | aob_group_t p_aob_group[2]; |
376 | | |
377 | 151k | switch( p_sys->i_type ) |
378 | 151k | { |
379 | 3.93k | case LPCM_VOB: |
380 | 3.93k | i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, |
381 | 3.93k | p_block->p_buffer ); |
382 | 3.93k | break; |
383 | 41.9k | case LPCM_AOB: |
384 | 41.9k | i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding, |
385 | 41.9k | p_aob_group, |
386 | 41.9k | p_block->p_buffer ); |
387 | 41.9k | break; |
388 | 80.5k | case LPCM_BD: |
389 | 80.5k | i_ret = BdHeader( p_sys, &i_rate, &i_channels, &i_channels_padding, &i_original_channels, &i_bits, |
390 | 80.5k | p_block->p_buffer ); |
391 | 80.5k | break; |
392 | 24.9k | case LPCM_WIDI: |
393 | 24.9k | i_ret = WidiHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, |
394 | 24.9k | p_block->p_buffer ); |
395 | 24.9k | break; |
396 | 0 | default: |
397 | 0 | abort(); |
398 | 151k | } |
399 | | |
400 | 151k | if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding ) |
401 | 130k | { |
402 | 130k | msg_Warn( p_dec, "no frame sync or too small frame" ); |
403 | 130k | block_Release( p_block ); |
404 | 130k | return NULL; |
405 | 130k | } |
406 | | |
407 | | /* Set output properties */ |
408 | 21.1k | if( p_dec->fmt_out.audio.i_rate != i_rate ) |
409 | 12.1k | { |
410 | 12.1k | date_Init( &p_sys->end_date, i_rate, 1 ); |
411 | 12.1k | date_Set( &p_sys->end_date, p_block->i_pts ); |
412 | 12.1k | } |
413 | 21.1k | p_dec->fmt_out.audio.i_rate = i_rate; |
414 | 21.1k | p_dec->fmt_out.audio.i_channels = i_channels; |
415 | 21.1k | p_dec->fmt_out.audio.i_physical_channels = i_original_channels; |
416 | | |
417 | 21.1k | if ( p_sys->i_type == LPCM_AOB ) |
418 | 3.37k | { |
419 | 3.37k | i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) / |
420 | 3.37k | ( |
421 | 3.37k | ( (p_aob_group[0].i_bits / 8) * p_aob_group[0].i_channels ) + |
422 | 3.37k | ( (p_aob_group[1].i_bits / 8) * p_aob_group[1].i_channels ) |
423 | 3.37k | ); |
424 | 3.37k | } |
425 | 17.7k | else |
426 | 17.7k | { |
427 | 17.7k | i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) / |
428 | 17.7k | (i_channels + i_channels_padding) * 8 / i_bits; |
429 | 17.7k | } |
430 | | |
431 | 21.1k | if( p_sys->b_packetizer ) |
432 | 10.5k | { |
433 | 10.5k | p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date ); |
434 | 10.5k | p_block->i_length = |
435 | 10.5k | date_Increment( &p_sys->end_date, i_frame_length ) - |
436 | 10.5k | p_block->i_pts; |
437 | | |
438 | | /* Just pass on the incoming frame */ |
439 | 10.5k | return p_block; |
440 | 10.5k | } |
441 | 10.5k | else |
442 | 10.5k | { |
443 | | /* */ |
444 | 10.5k | if( i_bits == 16 ) |
445 | 6.88k | { |
446 | 6.88k | p_dec->fmt_out.audio.i_format = |
447 | 6.88k | p_dec->fmt_out.i_codec = VLC_CODEC_S16N; |
448 | 6.88k | p_dec->fmt_out.audio.i_bitspersample = 16; |
449 | 6.88k | } |
450 | 3.69k | else |
451 | 3.69k | { |
452 | 3.69k | p_dec->fmt_out.audio.i_format = |
453 | 3.69k | p_dec->fmt_out.i_codec = VLC_CODEC_S32N; |
454 | 3.69k | p_dec->fmt_out.audio.i_bitspersample = 32; |
455 | 3.69k | } |
456 | 10.5k | aout_FormatPrepare(&p_dec->fmt_out.audio); |
457 | | |
458 | | /* */ |
459 | 10.5k | block_t *p_aout_buffer; |
460 | 10.5k | if( decoder_UpdateAudioFormat( p_dec ) != VLC_SUCCESS || |
461 | 0 | !(p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length )) ) |
462 | 10.5k | { |
463 | 10.5k | block_Release( p_block ); |
464 | 10.5k | return NULL; |
465 | 10.5k | } |
466 | | |
467 | 0 | p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); |
468 | 0 | p_aout_buffer->i_length = |
469 | 0 | date_Increment( &p_sys->end_date, i_frame_length ) |
470 | 0 | - p_aout_buffer->i_pts; |
471 | |
|
472 | 0 | p_block->p_buffer += p_sys->i_header_size + i_padding; |
473 | 0 | p_block->i_buffer -= p_sys->i_header_size + i_padding; |
474 | |
|
475 | 0 | switch( p_sys->i_type ) |
476 | 0 | { |
477 | 0 | case LPCM_WIDI: |
478 | 0 | case LPCM_VOB: |
479 | 0 | VobExtract( p_aout_buffer, p_block, i_bits ); |
480 | 0 | break; |
481 | 0 | case LPCM_AOB: |
482 | 0 | AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group ); |
483 | 0 | break; |
484 | 0 | default: |
485 | 0 | vlc_assert_unreachable(); |
486 | 0 | case LPCM_BD: |
487 | 0 | BdExtract( p_aout_buffer, p_block, i_frame_length, i_channels, i_channels_padding, i_bits ); |
488 | 0 | break; |
489 | 0 | } |
490 | | |
491 | 0 | if( p_sys->i_chans_to_reorder ) |
492 | 0 | { |
493 | 0 | aout_ChannelReorder( p_aout_buffer->p_buffer, p_aout_buffer->i_buffer, |
494 | 0 | p_sys->i_chans_to_reorder, p_sys->pi_chan_table, |
495 | 0 | p_dec->fmt_out.i_codec ); |
496 | 0 | } |
497 | |
|
498 | 0 | block_Release( p_block ); |
499 | 0 | return p_aout_buffer; |
500 | 0 | } |
501 | 21.1k | } |
502 | | |
503 | | static int DecodeFrame( decoder_t *p_dec, block_t *p_block ) |
504 | 158k | { |
505 | 158k | block_t *p_out = Packetize( p_dec, &p_block ); |
506 | 158k | if( p_out != NULL ) |
507 | 0 | decoder_QueueAudio( p_dec, p_out ); |
508 | 158k | return VLCDEC_SUCCESS; |
509 | 158k | } |
510 | | |
511 | | #ifdef ENABLE_SOUT |
512 | | /***************************************************************************** |
513 | | * OpenEncoder: lpcm encoder construction |
514 | | *****************************************************************************/ |
515 | | static int OpenEncoder( vlc_object_t *p_this ) |
516 | 0 | { |
517 | 0 | encoder_t *p_enc = (encoder_t *)p_this; |
518 | 0 | encoder_sys_t *p_sys; |
519 | | |
520 | | /* We only support DVD LPCM yet. */ |
521 | 0 | if( p_enc->fmt_out.i_codec != VLC_CODEC_DVD_LPCM ) |
522 | 0 | return VLC_EGENERIC; |
523 | | |
524 | 0 | if( p_enc->fmt_in.audio.i_rate != 48000 && |
525 | 0 | p_enc->fmt_in.audio.i_rate != 96000 && |
526 | 0 | p_enc->fmt_in.audio.i_rate != 44100 && |
527 | 0 | p_enc->fmt_in.audio.i_rate != 32000 ) |
528 | 0 | { |
529 | 0 | msg_Err( p_enc, "DVD LPCM supports only sample rates of 48, 96, 44.1 or 32 kHz" ); |
530 | 0 | return VLC_EGENERIC; |
531 | 0 | } |
532 | | |
533 | 0 | if( p_enc->fmt_in.audio.i_channels > 8 ) |
534 | 0 | { |
535 | 0 | msg_Err( p_enc, "DVD LPCM supports a maximum of eight channels" ); |
536 | 0 | return VLC_EGENERIC; |
537 | 0 | } |
538 | | |
539 | | /* Allocate the memory needed to store the encoder's structure */ |
540 | 0 | if( ( p_sys = |
541 | 0 | (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) |
542 | 0 | return VLC_ENOMEM; |
543 | | |
544 | | /* In DVD LCPM, a frame is always 150 PTS ticks. */ |
545 | 0 | p_sys->i_frame_samples = p_enc->fmt_in.audio.i_rate * 150 / 90000; |
546 | 0 | p_sys->p_buffer = xmalloc(p_sys->i_frame_samples |
547 | 0 | * p_enc->fmt_in.audio.i_channels * 16); |
548 | 0 | p_sys->i_buffer_used = 0; |
549 | 0 | p_sys->i_frame_num = 0; |
550 | |
|
551 | 0 | p_sys->i_channels = p_enc->fmt_in.audio.i_channels; |
552 | 0 | p_sys->i_rate = p_enc->fmt_in.audio.i_rate; |
553 | |
|
554 | 0 | p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec; |
555 | |
|
556 | 0 | p_enc->fmt_in.audio.i_bitspersample = 16; |
557 | 0 | p_enc->fmt_in.i_codec = VLC_CODEC_S16N; |
558 | |
|
559 | 0 | p_enc->fmt_out.i_bitrate = |
560 | 0 | p_enc->fmt_in.audio.i_channels * |
561 | 0 | p_enc->fmt_in.audio.i_rate * |
562 | 0 | p_enc->fmt_in.audio.i_bitspersample * |
563 | 0 | (p_sys->i_frame_samples + LPCM_VOB_HEADER_LEN) / |
564 | 0 | p_sys->i_frame_samples; |
565 | |
|
566 | 0 | static const struct vlc_encoder_operations ops = |
567 | 0 | { |
568 | 0 | .close = CloseEncoder, |
569 | 0 | .encode_audio = EncodeFrames, |
570 | 0 | }; |
571 | |
|
572 | 0 | p_enc->ops = &ops; |
573 | 0 | p_enc->p_sys = p_sys; |
574 | |
|
575 | 0 | return VLC_SUCCESS; |
576 | 0 | } |
577 | | |
578 | | /***************************************************************************** |
579 | | * CloseEncoder: lpcm encoder destruction |
580 | | *****************************************************************************/ |
581 | | static void CloseEncoder ( encoder_t *p_enc ) |
582 | 0 | { |
583 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
584 | |
|
585 | 0 | free( p_sys->p_buffer ); |
586 | 0 | free( p_sys ); |
587 | 0 | } |
588 | | |
589 | | /***************************************************************************** |
590 | | * EncodeFrames: encode zero or more LCPM audio packets |
591 | | *****************************************************************************/ |
592 | | static block_t *EncodeFrames( encoder_t *p_enc, block_t *p_aout_buf ) |
593 | 0 | { |
594 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
595 | 0 | block_t *p_first_block = NULL, *p_last_block = NULL; |
596 | |
|
597 | 0 | if( !p_aout_buf || !p_aout_buf->i_buffer ) return NULL; |
598 | | |
599 | 0 | const int i_num_frames = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) / |
600 | 0 | p_sys->i_frame_samples; |
601 | 0 | const int i_leftover_samples = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) % |
602 | 0 | p_sys->i_frame_samples; |
603 | 0 | const int i_frame_size = p_sys->i_frame_samples * p_sys->i_channels * 2 + LPCM_VOB_HEADER_LEN; |
604 | 0 | const int i_start_offset = -p_sys->i_buffer_used; |
605 | |
|
606 | 0 | uint8_t i_freq_code = 0; |
607 | |
|
608 | 0 | switch( p_sys->i_rate ) { |
609 | 0 | case 48000: |
610 | 0 | i_freq_code = 0; |
611 | 0 | break; |
612 | 0 | case 96000: |
613 | 0 | i_freq_code = 1; |
614 | 0 | break; |
615 | 0 | case 44100: |
616 | 0 | i_freq_code = 2; |
617 | 0 | break; |
618 | 0 | case 32000: |
619 | 0 | i_freq_code = 3; |
620 | 0 | break; |
621 | 0 | default: |
622 | 0 | vlc_assert_unreachable(); |
623 | 0 | } |
624 | | |
625 | 0 | int i_bytes_consumed = 0; |
626 | |
|
627 | 0 | for ( int i = 0; i < i_num_frames; ++i ) |
628 | 0 | { |
629 | 0 | block_t *p_block = block_Alloc( i_frame_size ); |
630 | 0 | if( unlikely(p_block == NULL) ) |
631 | 0 | { |
632 | 0 | if( p_first_block ) |
633 | 0 | block_ChainRelease( p_first_block ); |
634 | |
|
635 | 0 | return NULL; |
636 | 0 | } |
637 | | |
638 | 0 | uint8_t *frame = (uint8_t *)p_block->p_buffer; |
639 | 0 | frame[0] = 1; /* one frame in packet */ |
640 | 0 | frame[1] = 0; |
641 | 0 | frame[2] = 0; /* no first access unit */ |
642 | 0 | frame[3] = (p_sys->i_frame_num + i) & 0x1f; /* no emphasis, no mute */ |
643 | 0 | frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1); |
644 | 0 | frame[5] = 0x80; /* neutral dynamic range */ |
645 | |
|
646 | 0 | const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used; |
647 | 0 | const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2; |
648 | 0 | const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2; |
649 | |
|
650 | | #ifdef WORDS_BIGENDIAN |
651 | | memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes ); |
652 | | memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed, |
653 | | i_consume_bytes ); |
654 | | #else |
655 | 0 | swab( p_sys->p_buffer, frame + 6, i_kept_bytes ); |
656 | 0 | swab( p_aout_buf->p_buffer + i_bytes_consumed, frame + 6 + i_kept_bytes, |
657 | 0 | i_consume_bytes ); |
658 | 0 | #endif |
659 | |
|
660 | 0 | p_sys->i_frame_num++; |
661 | 0 | p_sys->i_buffer_used = 0; |
662 | 0 | i_bytes_consumed += i_consume_bytes; |
663 | | |
664 | | /* We need to find i_length by means of next_pts due to possible roundoff errors. */ |
665 | 0 | vlc_tick_t this_pts = p_aout_buf->i_pts + |
666 | 0 | vlc_tick_from_samples(i * p_sys->i_frame_samples + i_start_offset, p_sys->i_rate); |
667 | 0 | vlc_tick_t next_pts = p_aout_buf->i_pts + |
668 | 0 | vlc_tick_from_samples((i + 1) * p_sys->i_frame_samples + i_start_offset, p_sys->i_rate); |
669 | |
|
670 | 0 | p_block->i_pts = p_block->i_dts = this_pts; |
671 | 0 | p_block->i_length = next_pts - this_pts; |
672 | |
|
673 | 0 | if( !p_first_block ) |
674 | 0 | p_first_block = p_last_block = p_block; |
675 | 0 | else |
676 | 0 | p_last_block = p_last_block->p_next = p_block; |
677 | 0 | } |
678 | | |
679 | 0 | memcpy( p_sys->p_buffer, |
680 | 0 | p_aout_buf->p_buffer + i_bytes_consumed, |
681 | 0 | i_leftover_samples * p_sys->i_channels * 2 ); |
682 | 0 | p_sys->i_buffer_used = i_leftover_samples; |
683 | |
|
684 | 0 | return p_first_block; |
685 | 0 | } |
686 | | #endif |
687 | | |
688 | | /***************************************************************************** |
689 | | * |
690 | | *****************************************************************************/ |
691 | | static int VobHeader( unsigned *pi_rate, |
692 | | unsigned *pi_channels, unsigned *pi_original_channels, |
693 | | unsigned *pi_bits, |
694 | | const uint8_t *p_header ) |
695 | 3.93k | { |
696 | 3.93k | const uint8_t i_header = p_header[4]; |
697 | | |
698 | 3.93k | switch( (i_header >> 4) & 0x3 ) |
699 | 3.93k | { |
700 | 317 | case 0: |
701 | 317 | *pi_rate = 48000; |
702 | 317 | break; |
703 | 80 | case 1: |
704 | 80 | *pi_rate = 96000; |
705 | 80 | break; |
706 | 115 | case 2: |
707 | 115 | *pi_rate = 44100; |
708 | 115 | break; |
709 | 3.42k | case 3: |
710 | 3.42k | *pi_rate = 32000; |
711 | 3.42k | break; |
712 | 3.93k | } |
713 | | |
714 | 3.93k | *pi_channels = (i_header & 0x7) + 1; |
715 | 3.93k | switch( *pi_channels - 1 ) |
716 | 3.93k | { |
717 | 296 | case 0: |
718 | 296 | *pi_original_channels = AOUT_CHAN_CENTER; |
719 | 296 | break; |
720 | 77 | case 1: |
721 | 77 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; |
722 | 77 | break; |
723 | 3 | case 2: |
724 | | /* This is unsure. */ |
725 | 3 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE; |
726 | 3 | break; |
727 | 117 | case 3: |
728 | 117 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
729 | 117 | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; |
730 | 117 | break; |
731 | 9 | case 4: |
732 | | /* This is unsure. */ |
733 | 9 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
734 | 9 | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
735 | 9 | | AOUT_CHAN_LFE; |
736 | 9 | break; |
737 | 14 | case 5: |
738 | 14 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
739 | 14 | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
740 | 14 | | AOUT_CHAN_CENTER | AOUT_CHAN_LFE; |
741 | 14 | break; |
742 | 2 | case 6: |
743 | 2 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
744 | 2 | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
745 | 2 | | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
746 | 2 | | AOUT_CHAN_MIDDLERIGHT; |
747 | 2 | break; |
748 | 3.41k | case 7: |
749 | 3.41k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
750 | 3.41k | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
751 | 3.41k | | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
752 | 3.41k | | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE; |
753 | 3.41k | break; |
754 | 3.93k | } |
755 | | |
756 | 3.93k | switch( (i_header >> 6) & 0x3 ) |
757 | 3.93k | { |
758 | 3 | case 2: |
759 | 3 | *pi_bits = 24; |
760 | 3 | break; |
761 | 76 | case 1: |
762 | 76 | *pi_bits = 20; |
763 | 76 | break; |
764 | 331 | case 0: |
765 | 3.85k | default: |
766 | 3.85k | *pi_bits = 16; |
767 | 3.85k | break; |
768 | 3.93k | } |
769 | | |
770 | | /* Check frame sync and drop it. */ |
771 | 3.93k | if( p_header[5] != 0x80 ) |
772 | 608 | return -1; |
773 | 3.32k | return 0; |
774 | 3.93k | } |
775 | | |
776 | | static const unsigned p_aob_group1[21][6] = { |
777 | | { AOUT_CHAN_CENTER, 0 }, |
778 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
779 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
780 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
781 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
782 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
783 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
784 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
785 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
786 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
787 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
788 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
789 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 }, |
790 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 }, |
791 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 }, |
792 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 }, |
793 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 }, |
794 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 }, |
795 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
796 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
797 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
798 | | }; |
799 | | static const unsigned p_aob_group2[21][6] = { |
800 | | { 0 }, |
801 | | { 0 }, |
802 | | { AOUT_CHAN_REARCENTER, 0 }, |
803 | | { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
804 | | { AOUT_CHAN_LFE, 0 }, |
805 | | { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 }, |
806 | | { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
807 | | { AOUT_CHAN_CENTER, 0 }, |
808 | | { AOUT_CHAN_CENTER, AOUT_CHAN_REARCENTER, 0 }, |
809 | | { AOUT_CHAN_CENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
810 | | { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 }, |
811 | | { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 }, |
812 | | { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
813 | | { AOUT_CHAN_REARCENTER, 0 }, |
814 | | { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
815 | | { AOUT_CHAN_LFE, 0 }, |
816 | | { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 }, |
817 | | { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }, |
818 | | { AOUT_CHAN_LFE, 0 }, |
819 | | { AOUT_CHAN_CENTER, 0 }, |
820 | | { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 }, |
821 | | }; |
822 | | |
823 | | static int AobHeader( unsigned *pi_rate, |
824 | | unsigned *pi_channels, unsigned *pi_layout, |
825 | | unsigned *pi_bits, |
826 | | unsigned *pi_padding, |
827 | | aob_group_t g[2], |
828 | | const uint8_t *p_header ) |
829 | 41.9k | { |
830 | 41.9k | const unsigned i_header_size = GetWBE( &p_header[1] ); |
831 | 41.9k | if( i_header_size + 3 < LPCM_AOB_HEADER_LEN ) |
832 | 14.4k | return VLC_EGENERIC; |
833 | | |
834 | | /* Padding = Total header size - Normal AOB header |
835 | | * + 3 bytes (1 for continuity counter + 2 for header_size ) */ |
836 | 27.4k | *pi_padding = 3 + i_header_size - LPCM_AOB_HEADER_LEN; |
837 | | |
838 | 27.4k | const int i_index_size_g1 = (p_header[6] >> 4); |
839 | 27.4k | const int i_index_size_g2 = (p_header[6] ) & 0x0f; |
840 | 27.4k | const int i_index_rate_g1 = (p_header[7] >> 4); |
841 | 27.4k | const int i_index_rate_g2 = (p_header[7] ) & 0x0f; |
842 | 27.4k | const int i_assignment = p_header[9]; |
843 | | |
844 | | /* Validate */ |
845 | 27.4k | if( i_index_size_g1 > 0x02 || |
846 | 18.3k | ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) ) |
847 | 12.4k | return VLC_EGENERIC; |
848 | 15.0k | if( (i_index_rate_g1 & 0x07) > 0x02 || |
849 | 14.1k | ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) ) |
850 | 932 | return VLC_EGENERIC; |
851 | 14.1k | if( i_assignment > 20 ) |
852 | 5.82k | return VLC_EGENERIC; |
853 | | |
854 | | /* */ |
855 | | /* max is 0x2, 0xf == unused */ |
856 | 8.30k | g[0].i_bits = 16 + 4 * i_index_size_g1; |
857 | 8.30k | g[1].i_bits = ( i_index_size_g2 != 0x0f ) ? 16 + 4 * i_index_size_g2 : 0; |
858 | | |
859 | | /* No info about interlacing of different sampling rate */ |
860 | 8.30k | if ( g[1].i_bits && ( i_index_rate_g1 != i_index_rate_g2 ) ) |
861 | 815 | return VLC_EGENERIC; |
862 | | |
863 | | /* only set 16bits if both are <= */ |
864 | 7.48k | if( g[0].i_bits ) |
865 | 7.48k | { |
866 | 7.48k | if( g[0].i_bits > 16 || g[1].i_bits > 16 ) |
867 | 3.25k | *pi_bits = 32; |
868 | 4.23k | else |
869 | 4.23k | *pi_bits = 16; |
870 | 7.48k | } |
871 | 0 | else |
872 | 0 | return VLC_EGENERIC; |
873 | | |
874 | 7.48k | if( i_index_rate_g1 & 0x08 ) |
875 | 510 | *pi_rate = 44100 << (i_index_rate_g1 & 0x07); |
876 | 6.97k | else |
877 | 6.97k | *pi_rate = 48000 << (i_index_rate_g1 & 0x07); |
878 | | |
879 | | |
880 | | /* Group1 */ |
881 | 7.48k | unsigned i_channels1 = 0; |
882 | 7.48k | unsigned i_layout1 = 0; |
883 | 20.6k | for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ ) |
884 | 13.1k | { |
885 | 13.1k | i_channels1++; |
886 | 13.1k | i_layout1 |= p_aob_group1[i_assignment][i]; |
887 | 13.1k | } |
888 | | /* Group2 */ |
889 | 7.48k | unsigned i_channels2 = 0; |
890 | 7.48k | unsigned i_layout2 = 0; |
891 | 7.48k | if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f ) |
892 | 6.66k | { |
893 | 13.2k | for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ ) |
894 | 6.62k | { |
895 | 6.62k | i_channels2++; |
896 | 6.62k | i_layout2 |= p_aob_group2[i_assignment][i]; |
897 | 6.62k | } |
898 | 6.66k | assert( (i_layout1 & i_layout2) == 0 ); |
899 | 6.66k | } |
900 | | |
901 | | /* */ |
902 | 7.48k | *pi_channels = i_channels1 + ( g[1].i_bits ? i_channels2 : 0 ); |
903 | 7.48k | *pi_layout = i_layout1 | ( g[1].i_bits ? i_layout2 : 0 ); |
904 | | |
905 | | /* */ |
906 | 22.4k | for( unsigned i = 0; i < 2; i++ ) |
907 | 14.9k | { |
908 | 14.9k | const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] : |
909 | 14.9k | p_aob_group2[i_assignment]; |
910 | 14.9k | g[i].i_channels = i == 0 ? i_channels1 : |
911 | 14.9k | i_channels2; |
912 | | |
913 | 14.9k | if( !g[i].i_bits ) |
914 | 827 | continue; |
915 | 33.9k | for( unsigned j = 0; j < g[i].i_channels; j++ ) |
916 | 19.7k | { |
917 | 19.7k | g[i].pi_position[j] = 0; |
918 | 95.3k | for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ ) |
919 | 95.3k | { |
920 | 95.3k | const unsigned i_channel = pi_vlc_chan_order_wg4[k]; |
921 | 95.3k | if( i_channel == p_aob[j] ) |
922 | 19.7k | break; |
923 | 75.5k | if( (*pi_layout) & i_channel ) |
924 | 25.8k | g[i].pi_position[j]++; |
925 | 75.5k | } |
926 | 19.7k | } |
927 | 14.1k | } |
928 | 7.48k | return VLC_SUCCESS; |
929 | 7.48k | } |
930 | | |
931 | | static const uint32_t pi_8channels_in[] = |
932 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, |
933 | | AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, |
934 | | AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_LFE, 0 }; |
935 | | |
936 | | static const uint32_t pi_7channels_in[] = |
937 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, |
938 | | AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, |
939 | | AOUT_CHAN_MIDDLERIGHT, 0 }; |
940 | | |
941 | | static const uint32_t pi_6channels_in[] = |
942 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, |
943 | | AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 }; |
944 | | |
945 | | static const uint32_t pi_5channels_in[] = |
946 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, |
947 | | AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 }; |
948 | | |
949 | | static const uint32_t pi_4channels_in[] = |
950 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, |
951 | | AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 }; |
952 | | |
953 | | static const uint32_t pi_3channels_in[] = |
954 | | { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, |
955 | | AOUT_CHAN_CENTER, 0 }; |
956 | | |
957 | | |
958 | | static int BdHeader( decoder_sys_t *p_sys, |
959 | | unsigned *pi_rate, |
960 | | unsigned *pi_channels, |
961 | | unsigned *pi_channels_padding, |
962 | | unsigned *pi_original_channels, |
963 | | unsigned *pi_bits, |
964 | | const uint8_t *p_header ) |
965 | 80.5k | { |
966 | 80.5k | const uint32_t h = GetDWBE( p_header ); |
967 | 80.5k | const uint32_t *pi_channels_in = NULL; |
968 | 80.5k | switch( ( h & 0xf000) >> 12 ) |
969 | 80.5k | { |
970 | 4.26k | case 1: |
971 | 4.26k | *pi_channels = 1; |
972 | 4.26k | *pi_original_channels = AOUT_CHAN_CENTER; |
973 | 4.26k | break; |
974 | 2.83k | case 3: |
975 | 2.83k | *pi_channels = 2; |
976 | 2.83k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; |
977 | 2.83k | break; |
978 | 5.77k | case 4: |
979 | 5.77k | *pi_channels = 3; |
980 | 5.77k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER; |
981 | 5.77k | pi_channels_in = pi_3channels_in; |
982 | 5.77k | break; |
983 | 2.90k | case 5: |
984 | 2.90k | *pi_channels = 3; |
985 | 2.90k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER; |
986 | 2.90k | break; |
987 | 8.18k | case 6: |
988 | 8.18k | *pi_channels = 4; |
989 | 8.18k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | |
990 | 8.18k | AOUT_CHAN_REARCENTER; |
991 | 8.18k | break; |
992 | 6.64k | case 7: |
993 | 6.64k | *pi_channels = 4; |
994 | 6.64k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | |
995 | 6.64k | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; |
996 | 6.64k | pi_channels_in = pi_4channels_in; |
997 | 6.64k | break; |
998 | 2.95k | case 8: |
999 | 2.95k | *pi_channels = 5; |
1000 | 2.95k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | |
1001 | 2.95k | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; |
1002 | 2.95k | pi_channels_in = pi_5channels_in; |
1003 | 2.95k | break; |
1004 | 1.92k | case 9: |
1005 | 1.92k | *pi_channels = 6; |
1006 | 1.92k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | |
1007 | 1.92k | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | |
1008 | 1.92k | AOUT_CHAN_LFE; |
1009 | 1.92k | pi_channels_in = pi_6channels_in; |
1010 | 1.92k | break; |
1011 | 2.53k | case 10: |
1012 | 2.53k | *pi_channels = 7; |
1013 | 2.53k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | |
1014 | 2.53k | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | |
1015 | 2.53k | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT; |
1016 | 2.53k | pi_channels_in = pi_7channels_in; |
1017 | 2.53k | break; |
1018 | 1.78k | case 11: |
1019 | 1.78k | *pi_channels = 8; |
1020 | 1.78k | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | |
1021 | 1.78k | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | |
1022 | 1.78k | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | |
1023 | 1.78k | AOUT_CHAN_LFE; |
1024 | 1.78k | pi_channels_in = pi_8channels_in; |
1025 | 1.78k | break; |
1026 | | |
1027 | 40.7k | default: |
1028 | 40.7k | return -1; |
1029 | 80.5k | } |
1030 | 39.8k | *pi_channels_padding = *pi_channels & 1; |
1031 | | |
1032 | 39.8k | switch( (h >> 6) & 0x03 ) |
1033 | 39.8k | { |
1034 | 18.1k | case 1: |
1035 | 18.1k | *pi_bits = 16; |
1036 | 18.1k | break; |
1037 | 6.07k | case 2: /* 20 bits but samples are stored on 24 bits */ |
1038 | 12.2k | case 3: /* 24 bits */ |
1039 | 12.2k | *pi_bits = 24; |
1040 | 12.2k | break; |
1041 | 9.43k | default: |
1042 | 9.43k | return -1; |
1043 | 39.8k | } |
1044 | 30.3k | switch( (h >> 8) & 0x0f ) |
1045 | 30.3k | { |
1046 | 5.70k | case 1: |
1047 | 5.70k | *pi_rate = 48000; |
1048 | 5.70k | break; |
1049 | 5.10k | case 4: |
1050 | 5.10k | *pi_rate = 96000; |
1051 | 5.10k | break; |
1052 | 3.62k | case 5: |
1053 | 3.62k | *pi_rate = 192000; |
1054 | 3.62k | break; |
1055 | 15.9k | default: |
1056 | 15.9k | return -1; |
1057 | 30.3k | } |
1058 | | |
1059 | 14.4k | if( pi_channels_in ) |
1060 | 8.43k | { |
1061 | 8.43k | p_sys->i_chans_to_reorder = |
1062 | 8.43k | aout_CheckChannelReorder( pi_channels_in, NULL, |
1063 | 8.43k | *pi_original_channels, |
1064 | 8.43k | p_sys->pi_chan_table ); |
1065 | 8.43k | } |
1066 | | |
1067 | 14.4k | return 0; |
1068 | 30.3k | } |
1069 | | |
1070 | | static int WidiHeader( unsigned *pi_rate, |
1071 | | unsigned *pi_channels, unsigned *pi_original_channels, |
1072 | | unsigned *pi_bits, |
1073 | | const uint8_t *p_header ) |
1074 | 24.9k | { |
1075 | 24.9k | if ( p_header[0] != 0xa0 || p_header[1] != 0x06 ) |
1076 | 24.8k | return -1; |
1077 | | |
1078 | 75 | switch( ( p_header[3] & 0x38 ) >> 3 ) |
1079 | 75 | { |
1080 | 36 | case 0x01: //0b001 |
1081 | 36 | *pi_rate = 44100; |
1082 | 36 | break; |
1083 | 36 | case 0x02: //0b010 |
1084 | 36 | *pi_rate = 48000; |
1085 | 36 | break; |
1086 | 3 | default: |
1087 | 3 | return -1; |
1088 | 75 | } |
1089 | | |
1090 | 72 | if( p_header[3] >> 6 != 0 ) |
1091 | 36 | return -1; |
1092 | 36 | else |
1093 | 36 | *pi_bits = 16; |
1094 | | |
1095 | 36 | *pi_channels = (p_header[3] & 0x7) + 1; |
1096 | | |
1097 | 36 | *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; |
1098 | | |
1099 | 36 | return 0; |
1100 | 72 | } |
1101 | | |
1102 | | static void VobExtract( block_t *p_aout_buffer, block_t *p_block, |
1103 | | unsigned i_bits ) |
1104 | 0 | { |
1105 | | /* 20/24 bits LPCM use special packing */ |
1106 | 0 | if( i_bits == 24 ) |
1107 | 0 | { |
1108 | 0 | uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer; |
1109 | |
|
1110 | 0 | while( p_block->i_buffer / 12 ) |
1111 | 0 | { |
1112 | | /* Sample 1 */ |
1113 | 0 | *(p_out++) = (p_block->p_buffer[ 0] << 24) |
1114 | 0 | | (p_block->p_buffer[ 1] << 16) |
1115 | 0 | | (p_block->p_buffer[ 8] << 8); |
1116 | | /* Sample 2 */ |
1117 | 0 | *(p_out++) = (p_block->p_buffer[ 2] << 24) |
1118 | 0 | | (p_block->p_buffer[ 3] << 16) |
1119 | 0 | | (p_block->p_buffer[ 9] << 8); |
1120 | | /* Sample 3 */ |
1121 | 0 | *(p_out++) = (p_block->p_buffer[ 4] << 24) |
1122 | 0 | | (p_block->p_buffer[ 5] << 16) |
1123 | 0 | | (p_block->p_buffer[10] << 8); |
1124 | | /* Sample 4 */ |
1125 | 0 | *(p_out++) = (p_block->p_buffer[ 6] << 24) |
1126 | 0 | | (p_block->p_buffer[ 7] << 16) |
1127 | 0 | | (p_block->p_buffer[11] << 8); |
1128 | |
|
1129 | 0 | p_block->i_buffer -= 12; |
1130 | 0 | p_block->p_buffer += 12; |
1131 | 0 | } |
1132 | 0 | } |
1133 | 0 | else if( i_bits == 20 ) |
1134 | 0 | { |
1135 | 0 | uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer; |
1136 | |
|
1137 | 0 | while( p_block->i_buffer / 10 ) |
1138 | 0 | { |
1139 | | /* Sample 1 */ |
1140 | 0 | *(p_out++) = ( p_block->p_buffer[0] << 24) |
1141 | 0 | | ( p_block->p_buffer[1] << 16) |
1142 | 0 | | ((p_block->p_buffer[8] & 0xF0) << 8); |
1143 | | /* Sample 2 */ |
1144 | 0 | *(p_out++) = ( p_block->p_buffer[2] << 24) |
1145 | 0 | | ( p_block->p_buffer[3] << 16) |
1146 | 0 | | ((p_block->p_buffer[8] & 0x0F) << 12); |
1147 | | /* Sample 3 */ |
1148 | 0 | *(p_out++) = ( p_block->p_buffer[4] << 24) |
1149 | 0 | | ( p_block->p_buffer[5] << 16) |
1150 | 0 | | ((p_block->p_buffer[9] & 0xF0) << 8); |
1151 | | /* Sample 4 */ |
1152 | 0 | *(p_out++) = ( p_block->p_buffer[6] << 24) |
1153 | 0 | | ( p_block->p_buffer[7] << 16) |
1154 | 0 | | ((p_block->p_buffer[9] & 0x0F) << 12); |
1155 | |
|
1156 | 0 | p_block->i_buffer -= 10; |
1157 | 0 | p_block->p_buffer += 10; |
1158 | 0 | } |
1159 | 0 | } |
1160 | 0 | else |
1161 | 0 | { |
1162 | 0 | assert( i_bits == 16 ); |
1163 | | #ifdef WORDS_BIGENDIAN |
1164 | | memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer ); |
1165 | | #else |
1166 | 0 | swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer ); |
1167 | 0 | #endif |
1168 | 0 | } |
1169 | 0 | } |
1170 | | |
1171 | | static void AobExtract( block_t *p_aout_buffer, |
1172 | | block_t *p_block, unsigned i_aoutbits, aob_group_t p_group[2] ) |
1173 | 0 | { |
1174 | 0 | uint8_t *p_out = p_aout_buffer->p_buffer; |
1175 | 0 | const unsigned i_total_channels = p_group[0].i_channels + |
1176 | 0 | ( p_group[1].i_bits ? p_group[1].i_channels : 0 ); |
1177 | |
|
1178 | 0 | while( p_block->i_buffer > 0 ) |
1179 | 0 | { |
1180 | 0 | unsigned int i_aout_written = 0; |
1181 | |
|
1182 | 0 | for( int i = 0; i < 2; i++ ) |
1183 | 0 | { |
1184 | 0 | const aob_group_t *g = &p_group[1-i]; |
1185 | 0 | const unsigned int i_group_size = 2 * g->i_channels * g->i_bits / 8; |
1186 | |
|
1187 | 0 | if( p_block->i_buffer < i_group_size ) |
1188 | 0 | { |
1189 | 0 | p_block->i_buffer = 0; |
1190 | 0 | break; |
1191 | 0 | } |
1192 | | |
1193 | 0 | if( !g->i_bits ) |
1194 | 0 | continue; |
1195 | | |
1196 | 0 | for( unsigned n = 0; n < 2; n++ ) |
1197 | 0 | { |
1198 | 0 | for( unsigned j = 0; j < g->i_channels; j++ ) |
1199 | 0 | { |
1200 | 0 | const int i_src = n * g->i_channels + j; |
1201 | 0 | const int i_dst = n * i_total_channels + g->pi_position[j]; |
1202 | 0 | uint32_t *p_out32 = (uint32_t *) &p_out[4*i_dst]; |
1203 | |
|
1204 | 0 | if( g->i_bits == 24 ) |
1205 | 0 | { |
1206 | 0 | assert( i_aoutbits == 32 ); |
1207 | 0 | *p_out32 = (p_block->p_buffer[2*i_src+0] << 24) |
1208 | 0 | | (p_block->p_buffer[2*i_src+1] << 16) |
1209 | 0 | | (p_block->p_buffer[4*g->i_channels+i_src] << 8); |
1210 | | #ifdef WORDS_BIGENDIAN |
1211 | | *p_out32 = vlc_bswap32(*p_out32); |
1212 | | #endif |
1213 | 0 | i_aout_written += 4; |
1214 | 0 | } |
1215 | 0 | else if( g->i_bits == 20 ) |
1216 | 0 | { |
1217 | 0 | assert( i_aoutbits == 32 ); |
1218 | 0 | *p_out32 = (p_block->p_buffer[2*i_src+0] << 24) |
1219 | 0 | | (p_block->p_buffer[2*i_src+1] << 16) |
1220 | 0 | | (((p_block->p_buffer[4*g->i_channels+i_src] << ((!n)?0:4) ) & 0xf0) << 8); |
1221 | | #ifdef WORDS_BIGENDIAN |
1222 | | *p_out32 = vlc_bswap32(*p_out32); |
1223 | | #endif |
1224 | 0 | i_aout_written += 4; |
1225 | 0 | } |
1226 | 0 | else |
1227 | 0 | { |
1228 | 0 | assert( g->i_bits == 16 ); |
1229 | 0 | assert( i_aoutbits == 16 || i_aoutbits == 32 ); |
1230 | 0 | if( i_aoutbits == 16 ) |
1231 | 0 | { |
1232 | | #ifdef WORDS_BIGENDIAN |
1233 | | memcpy( &p_out[2*i_dst], &p_block->p_buffer[2*i_src], 2 ); |
1234 | | #else |
1235 | 0 | p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+0]; |
1236 | 0 | p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+1]; |
1237 | 0 | #endif |
1238 | 0 | i_aout_written += 2; |
1239 | 0 | } |
1240 | 0 | else |
1241 | 0 | { |
1242 | 0 | *p_out32 = (p_block->p_buffer[2*i_src+0] << 24) |
1243 | 0 | | (p_block->p_buffer[2*i_src+1] << 16); |
1244 | | #ifdef WORDS_BIGENDIAN |
1245 | | *p_out32 = vlc_bswap32(*p_out32); |
1246 | | #endif |
1247 | 0 | i_aout_written += 4; |
1248 | 0 | } |
1249 | 0 | } |
1250 | 0 | } |
1251 | 0 | } |
1252 | | |
1253 | | /* */ |
1254 | 0 | p_block->i_buffer -= i_group_size; |
1255 | 0 | p_block->p_buffer += i_group_size; |
1256 | 0 | } |
1257 | 0 | p_out += i_aout_written; |
1258 | 0 | } |
1259 | 0 | } |
1260 | | static void BdExtract( block_t *p_aout_buffer, block_t *p_block, |
1261 | | unsigned i_frame_length, |
1262 | | unsigned i_channels, unsigned i_channels_padding, |
1263 | | unsigned i_bits ) |
1264 | 0 | { |
1265 | 0 | if( i_bits != 16 || i_channels_padding > 0 ) |
1266 | 0 | { |
1267 | 0 | uint8_t *p_src = p_block->p_buffer; |
1268 | 0 | uint8_t *p_dst = p_aout_buffer->p_buffer; |
1269 | 0 | int dst_inc = ((i_bits == 16) ? 2 : 4) * i_channels; |
1270 | |
|
1271 | 0 | while( i_frame_length > 0 ) |
1272 | 0 | { |
1273 | | #ifdef WORDS_BIGENDIAN |
1274 | | memcpy( p_dst, p_src, i_channels * i_bits / 8 ); |
1275 | | #else |
1276 | 0 | if (i_bits == 16) { |
1277 | 0 | swab( p_src, p_dst, (i_channels + i_channels_padding) * i_bits / 8 ); |
1278 | 0 | } else { |
1279 | 0 | for (unsigned i = 0; i < i_channels; ++i) { |
1280 | 0 | p_dst[i * 4] = 0; |
1281 | 0 | p_dst[1 + (i * 4)] = p_src[2 + (i * 3)]; |
1282 | 0 | p_dst[2 + (i * 4)] = p_src[1 + (i * 3)]; |
1283 | 0 | p_dst[3 + (i * 4)] = p_src[i * 3]; |
1284 | 0 | } |
1285 | 0 | } |
1286 | 0 | #endif |
1287 | 0 | p_src += (i_channels + i_channels_padding) * i_bits / 8; |
1288 | 0 | p_dst += dst_inc; |
1289 | 0 | i_frame_length--; |
1290 | 0 | } |
1291 | 0 | } |
1292 | 0 | else |
1293 | 0 | { |
1294 | | #ifdef WORDS_BIGENDIAN |
1295 | | memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer ); |
1296 | | #else |
1297 | 0 | swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer ); |
1298 | 0 | #endif |
1299 | 0 | } |
1300 | 0 | } |
1301 | | |