1 /*****************************************************************************
2 * a52tospdif.c : encapsulates A/52 frames into S/PDIF packets
3 *****************************************************************************
4 * Copyright (C) 2002 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Stéphane Borel <stef@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
37 #include "audio_output.h"
38 #include "aout_internal.h"
40 /*****************************************************************************
42 *****************************************************************************/
43 static int Create ( vlc_object_t * );
44 static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
53 static const struct frmsize_s frmsizecod_tbl[64] =
55 { 32 ,{64 ,69 ,96 } },
56 { 32 ,{64 ,70 ,96 } },
57 { 40 ,{80 ,87 ,120 } },
58 { 40 ,{80 ,88 ,120 } },
59 { 48 ,{96 ,104 ,144 } },
60 { 48 ,{96 ,105 ,144 } },
61 { 56 ,{112 ,121 ,168 } },
62 { 56 ,{112 ,122 ,168 } },
63 { 64 ,{128 ,139 ,192 } },
64 { 64 ,{128 ,140 ,192 } },
65 { 80 ,{160 ,174 ,240 } },
66 { 80 ,{160 ,175 ,240 } },
67 { 96 ,{192 ,208 ,288 } },
68 { 96 ,{192 ,209 ,288 } },
69 { 112 ,{224 ,243 ,336 } },
70 { 112 ,{224 ,244 ,336 } },
71 { 128 ,{256 ,278 ,384 } },
72 { 128 ,{256 ,279 ,384 } },
73 { 160 ,{320 ,348 ,480 } },
74 { 160 ,{320 ,349 ,480 } },
75 { 192 ,{384 ,417 ,576 } },
76 { 192 ,{384 ,418 ,576 } },
77 { 224 ,{448 ,487 ,672 } },
78 { 224 ,{448 ,488 ,672 } },
79 { 256 ,{512 ,557 ,768 } },
80 { 256 ,{512 ,558 ,768 } },
81 { 320 ,{640 ,696 ,960 } },
82 { 320 ,{640 ,697 ,960 } },
83 { 384 ,{768 ,835 ,1152 } },
84 { 384 ,{768 ,836 ,1152 } },
85 { 448 ,{896 ,975 ,1344 } },
86 { 448 ,{896 ,976 ,1344 } },
87 { 512 ,{1024 ,1114 ,1536 } },
88 { 512 ,{1024 ,1115 ,1536 } },
89 { 576 ,{1152 ,1253 ,1728 } },
90 { 576 ,{1152 ,1254 ,1728 } },
91 { 640 ,{1280 ,1393 ,1920 } },
92 { 640 ,{1280 ,1394 ,1920 } }
95 /*****************************************************************************
97 *****************************************************************************/
99 set_category( CAT_AUDIO );
100 set_subcategory( SUBCAT_AUDIO_MISC );
101 set_description( _("audio filter for A/52->S/PDIF encapsulation") );
102 set_capability( "audio filter", 10 );
103 set_callbacks( Create, NULL );
106 /*****************************************************************************
108 *****************************************************************************/
109 static int Create( vlc_object_t *p_this )
111 aout_filter_t * p_filter = (aout_filter_t *)p_this;
113 if ( p_filter->input.i_format != VLC_FOURCC('a','5','2',' ')
114 || p_filter->output.i_format != VLC_FOURCC('s','p','d','b')
115 || p_filter->output.i_format != VLC_FOURCC('s','p','d','i') )
120 p_filter->pf_do_work = DoWork;
121 p_filter->b_in_place = 0;
126 /*****************************************************************************
127 * DoWork: convert a buffer
128 *****************************************************************************/
129 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
130 aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
132 /* AC3 is natively big endian. Most SPDIF devices have the native endianness of
133 * the computersystem. On MAc OS X however, little endian devices are also common.
135 uint32_t syncword, crc1, fscod, frmsizecod, bsid, bsmod, frame_size;
136 static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
137 static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
142 byte_t * p_in = p_in_buf->p_buffer;
143 byte_t * p_out = p_out_buf->p_buffer;
145 /* AC3 header decode */
146 syncword = p_in[0] | (p_in[1] << 8);
147 crc1 = p_in[2] | (p_in[3] << 8);
148 fscod = (p_in[4] >> 6) & 0x3;
149 frmsizecod = p_in[4] & 0x3f;
150 bsid = (p_in[5] >> 3) & 0x1f;
151 bsmod = p_in[5] & 0x7;
152 frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod];
154 /* Copy the S/PDIF headers. */
155 if( p_filter->output.i_format == VLC_FOURCC('s','p','d','b') )
157 p_filter->p_vlc->pf_memcpy( p_out, p_sync_be, 6 );
159 p_out[6] = ((frame_size ) >> 4) & 0xff;
160 p_out[7] = (frame_size << 4) & 0xff;
161 p_filter->p_vlc->pf_memcpy( &p_out[8], p_in, frame_size * 2 );
165 memcpy( p_out, p_sync_le, 6 );
167 p_out[6] = (frame_size << 4) & 0xff;
168 p_out[7] = ((frame_size ) >> 4) & 0xff;
170 swab( p_in, &p_out[8], frame_size * 2 );
173 for( i = frame_size; i-- ; )
177 p_tmp += 2; p_in += 2;
182 p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
183 p_out_buf->i_nb_bytes = AOUT_SPDIF_SIZE;