1 /*****************************************************************************
2 * aes3.c: aes3 decoder/packetizer module
3 *****************************************************************************
4 * Copyright (C) 2008 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int OpenDecoder ( vlc_object_t
* );
41 static int OpenPacketizer( vlc_object_t
* );
42 static void Close ( vlc_object_t
* );
46 set_category( CAT_INPUT
)
47 set_subcategory( SUBCAT_INPUT_ACODEC
)
48 set_description( N_("AES3/SMPTE 302M audio decoder") )
49 set_capability( "decoder", 100 )
50 set_callbacks( OpenDecoder
, Close
)
53 set_description( N_("AES3/SMPTE 302M audio packetizer") )
54 set_capability( "packetizer", 100 )
55 set_callbacks( OpenPacketizer
, Close
)
59 /*****************************************************************************
60 * decoder_sys_t : aes3 decoder descriptor
61 *****************************************************************************/
70 #define AES3_HEADER_LEN 4
72 /*****************************************************************************
74 *****************************************************************************/
75 static int Open( decoder_t
*p_dec
, bool b_packetizer
);
77 static block_t
*Parse( decoder_t
*p_dec
, int *pi_frame_length
, int *pi_bits
,
78 block_t
**pp_block
, bool b_packetizer
);
80 static inline uint8_t Reverse8( int n
)
82 n
= ((n
>> 1) & 0x55) | ((n
<< 1) & 0xaa);
83 n
= ((n
>> 2) & 0x33) | ((n
<< 2) & 0xcc);
84 n
= ((n
>> 4) & 0x0f) | ((n
<< 4) & 0xf0);
88 /*****************************************************************************
90 *****************************************************************************/
91 static int OpenDecoder( vlc_object_t
*p_this
)
93 decoder_t
*p_dec
= (decoder_t
*)p_this
;
95 return Open( p_dec
, false );
98 /*****************************************************************************
100 *****************************************************************************/
101 static int OpenPacketizer( vlc_object_t
*p_this
)
103 decoder_t
*p_dec
= (decoder_t
*)p_this
;
105 return Open( p_dec
, true );
108 /*****************************************************************************
109 * Close : aes3 decoder destruction
110 *****************************************************************************/
111 static void Close( vlc_object_t
*p_this
)
113 decoder_t
*p_dec
= (decoder_t
*)p_this
;
114 free( p_dec
->p_sys
);
117 /*****************************************************************************
118 * Decode: decodes an aes3 frame.
119 ****************************************************************************
120 * Beware, this function must be fed with complete frames (PES packet).
121 *****************************************************************************/
122 static aout_buffer_t
*Decode( decoder_t
*p_dec
, block_t
**pp_block
)
124 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
126 aout_buffer_t
*p_aout_buffer
;
127 int i_frame_length
, i_bits
;
129 p_block
= Parse( p_dec
, &i_frame_length
, &i_bits
, pp_block
, false );
133 p_aout_buffer
= decoder_NewAudioBuffer( p_dec
, i_frame_length
);
134 if( p_aout_buffer
== NULL
)
137 p_aout_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
138 p_aout_buffer
->i_length
= date_Increment( &p_sys
->end_date
,
139 i_frame_length
) - p_aout_buffer
->i_pts
;
141 p_block
->i_buffer
-= AES3_HEADER_LEN
;
142 p_block
->p_buffer
+= AES3_HEADER_LEN
;
146 uint8_t *p_out
= p_aout_buffer
->p_buffer
;
148 while( p_block
->i_buffer
/ 7 )
150 p_out
[0] = Reverse8( p_block
->p_buffer
[0] );
151 p_out
[1] = Reverse8( p_block
->p_buffer
[1] );
152 p_out
[2] = Reverse8( p_block
->p_buffer
[2] );
154 p_out
[3] = (Reverse8( p_block
->p_buffer
[3] ) >> 4) | ( (Reverse8( p_block
->p_buffer
[4] ) << 4) & 0xf0 );
155 p_out
[4] = (Reverse8( p_block
->p_buffer
[4] ) >> 4) | ( (Reverse8( p_block
->p_buffer
[5] ) << 4) & 0xf0 );
156 p_out
[5] = (Reverse8( p_block
->p_buffer
[5] ) >> 4) | ( (Reverse8( p_block
->p_buffer
[6] ) << 4) & 0xf0 );
158 p_block
->i_buffer
-= 7;
159 p_block
->p_buffer
+= 7;
164 else if( i_bits
== 20 )
166 uint8_t *p_out
= p_aout_buffer
->p_buffer
;
168 while( p_block
->i_buffer
/ 6 )
170 p_out
[0] = ( (Reverse8( p_block
->p_buffer
[0] ) << 4) & 0xf0 );
171 p_out
[1] = ( Reverse8( p_block
->p_buffer
[0]) >> 4 ) | ( (Reverse8( p_block
->p_buffer
[1]) << 4 ) & 0xf0 );
172 p_out
[2] = ( Reverse8( p_block
->p_buffer
[1]) >> 4 ) | ( (Reverse8( p_block
->p_buffer
[2]) << 4 ) & 0xf0 );
174 p_out
[3] = ( (Reverse8( p_block
->p_buffer
[3] ) << 4) & 0xf0 );
175 p_out
[4] = ( Reverse8( p_block
->p_buffer
[3]) >> 4 ) | ( (Reverse8( p_block
->p_buffer
[4]) << 4 ) & 0xf0 );
176 p_out
[5] = ( Reverse8( p_block
->p_buffer
[4]) >> 4 ) | ( (Reverse8( p_block
->p_buffer
[5]) << 4 ) & 0xf0 );
178 p_block
->i_buffer
-= 6;
179 p_block
->p_buffer
+= 6;
185 uint8_t *p_out
= p_aout_buffer
->p_buffer
;
187 assert( i_bits
== 16 );
189 while( p_block
->i_buffer
/ 5 )
191 p_out
[0] = Reverse8( p_block
->p_buffer
[0] );
192 p_out
[1] = Reverse8( p_block
->p_buffer
[1] );
194 p_out
[2] = (Reverse8( p_block
->p_buffer
[2] ) >> 4) | ( (Reverse8( p_block
->p_buffer
[3] ) << 4) & 0xf0 );
195 p_out
[3] = (Reverse8( p_block
->p_buffer
[3] ) >> 4) | ( (Reverse8( p_block
->p_buffer
[4] ) << 4) & 0xf0 );
197 p_block
->i_buffer
-= 5;
198 p_block
->p_buffer
+= 5;
204 block_Release( p_block
);
205 return p_aout_buffer
;
208 /*****************************************************************************
209 * Packetize: packetizes an aes3 frame.
210 ****************************************************************************
211 * Beware, this function must be fed with complete frames (PES packet).
212 *****************************************************************************/
213 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
215 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
217 int i_frame_length
, i_bits
;
219 p_block
= Parse( p_dec
, &i_frame_length
, &i_bits
, pp_block
, true );
223 p_block
->i_pts
= p_block
->i_dts
= date_Get( &p_sys
->end_date
);
224 p_block
->i_length
= date_Increment( &p_sys
->end_date
, i_frame_length
) - p_block
->i_pts
;
226 /* Just pass on the incoming frame */
230 /*****************************************************************************
232 ****************************************************************************/
233 static int Open( decoder_t
*p_dec
, bool b_packetizer
)
235 decoder_sys_t
*p_sys
;
237 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_302M
)
240 /* Allocate the memory needed to store the decoder's structure */
241 p_dec
->p_sys
= p_sys
= malloc( sizeof(decoder_sys_t
) );
247 date_Init( &p_sys
->end_date
, 48000, 1 );
248 date_Set( &p_sys
->end_date
, 0 );
250 /* Set output properties */
251 p_dec
->fmt_out
.i_cat
= AUDIO_ES
;
252 p_dec
->fmt_out
.audio
.i_rate
= 48000;
257 p_dec
->fmt_out
.i_codec
= VLC_CODEC_302M
;
259 p_dec
->pf_decode_audio
= NULL
;
260 p_dec
->pf_packetize
= Packetize
;
264 p_dec
->fmt_out
.i_codec
= VLC_CODEC_S16N
;
265 p_dec
->fmt_out
.audio
.i_bitspersample
= 16;
267 p_dec
->pf_decode_audio
= Decode
;
268 p_dec
->pf_packetize
= NULL
;
273 static const unsigned int pi_original_channels
[4] = {
274 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
275 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
|
276 AOUT_CHAN_CENTER
| AOUT_CHAN_LFE
,
277 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
|
278 AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
|
279 AOUT_CHAN_CENTER
| AOUT_CHAN_LFE
,
280 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
|
281 AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
|
282 AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT
|
283 AOUT_CHAN_CENTER
| AOUT_CHAN_LFE
,
286 static block_t
*Parse( decoder_t
*p_dec
, int *pi_frame_length
, int *pi_bits
,
287 block_t
**pp_block
, bool b_packetizer
)
289 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
297 if( !pp_block
|| !*pp_block
) return NULL
;
300 *pp_block
= NULL
; /* So the packet doesn't get re-sent */
302 /* Date management */
303 if( p_block
->i_pts
> VLC_TS_INVALID
&&
304 p_block
->i_pts
!= date_Get( &p_sys
->end_date
) )
306 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
309 if( !date_Get( &p_sys
->end_date
) )
311 /* We've just started the stream, wait for the first PTS. */
312 block_Release( p_block
);
316 if( p_block
->i_buffer
<= AES3_HEADER_LEN
)
318 msg_Err(p_dec
, "frame is too short");
319 block_Release( p_block
);
332 h
= GetDWBE( p_block
->p_buffer
);
333 i_size
= (h
>> 16) & 0xffff;
334 i_channels
= 2 + 2*( (h
>> 14) & 0x03 );
335 i_id
= (h
>> 6) & 0xff;
336 i_bits
= 16 + 4*( (h
>> 4)&0x03 );
338 if( AES3_HEADER_LEN
+ i_size
!= p_block
->i_buffer
|| i_bits
> 24 )
340 msg_Err(p_dec
, "frame has invalid header");
341 block_Release( p_block
);
345 /* Set output properties */
348 p_dec
->fmt_out
.audio
.i_bitspersample
= i_bits
;
352 p_dec
->fmt_out
.i_codec
= i_bits
== 16 ? VLC_CODEC_S16L
: VLC_CODEC_S24L
;
353 p_dec
->fmt_out
.audio
.i_bitspersample
= i_bits
== 16 ? 16 : 24;
356 p_dec
->fmt_out
.audio
.i_channels
= i_channels
;
357 p_dec
->fmt_out
.audio
.i_original_channels
= pi_original_channels
[i_channels
/2-1];
358 p_dec
->fmt_out
.audio
.i_physical_channels
= pi_original_channels
[i_channels
/2-1] & AOUT_CHAN_PHYSMASK
;
360 *pi_frame_length
= (p_block
->i_buffer
- AES3_HEADER_LEN
) / ( (4+i_bits
) * i_channels
/ 8 );