]> git.sesse.net Git - vlc/blob - modules/audio_filter/converter/a52tospdif.c
Fix the a52 spdif filter, add big endian support to the DTS filter and add big endian...
[vlc] / modules / audio_filter / converter / a52tospdif.c
1 /*****************************************************************************
2  * a52tospdif.c : encapsulates A/52 frames into S/PDIF packets
3  *****************************************************************************
4  * Copyright (C) 2002 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Stéphane Borel <stef@via.ecp.fr>
9  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32
33 #ifdef HAVE_UNISTD_H
34 #   include <unistd.h>
35 #endif
36
37 #include "audio_output.h"
38 #include "aout_internal.h"
39
40 /*****************************************************************************
41  * Local prototypes
42  *****************************************************************************/
43 static int  Create    ( vlc_object_t * );
44 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
45                         aout_buffer_t * );
46
47 struct frmsize_s
48 {
49   uint16_t bit_rate;
50   uint16_t frm_size[3];
51 };
52
53 static const struct frmsize_s frmsizecod_tbl[64] =
54 {
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 } }
93 };
94
95 /*****************************************************************************
96  * Module descriptor
97  *****************************************************************************/
98 vlc_module_begin();
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 );
104 vlc_module_end();
105
106 /*****************************************************************************
107  * Create:
108  *****************************************************************************/
109 static int Create( vlc_object_t *p_this )
110 {
111     aout_filter_t * p_filter = (aout_filter_t *)p_this;
112
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') ) )
116     {
117         return -1;
118     }
119
120     p_filter->pf_do_work = DoWork;
121     p_filter->b_in_place = 0;
122
123     return 0;
124 }
125
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 )
131 {
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.
134      */
135     uint32_t i_syncword, i_crc1, i_fscod, i_frmsizecod, i_bsid, i_bsmod, i_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 };
138 #ifndef HAVE_SWAB
139     byte_t * p_tmp;
140     uint16_t i;
141 #endif
142     byte_t * p_in = p_in_buf->p_buffer;
143     byte_t * p_out = p_out_buf->p_buffer;
144
145     /* AC3 header decode */
146     i_syncword = p_in[0] | (p_in[1] << 8);
147     i_crc1 = p_in[2] | (p_in[3] << 8);
148     i_fscod = (p_in[4] >> 6) & 0x3;
149     i_frmsizecod = p_in[4] & 0x3f;
150     i_bsid = (p_in[5] >> 3) & 0x1f;
151     i_bsmod = p_in[5] & 0x7;
152     i_frame_size = frmsizecod_tbl[i_frmsizecod].frm_size[i_fscod];
153     
154     /* Copy the S/PDIF headers. */
155     if( p_filter->output.i_format == VLC_FOURCC('s','p','d','b') )
156     {
157         p_filter->p_vlc->pf_memcpy( p_out, p_sync_be, 6 );
158         p_out[4] = i_bsmod;
159         p_out[6] = ((i_frame_size ) >> 4) & 0xff;
160         p_out[7] = (i_frame_size << 4) & 0xff;
161         p_filter->p_vlc->pf_memcpy( &p_out[8], p_in, i_frame_size * 2 );
162     }
163     else
164     {
165         p_filter->p_vlc->pf_memcpy( p_out, p_sync_le, 6 );
166         p_out[5] = i_bsmod;
167         p_out[6] = (i_frame_size << 4) & 0xff;
168         p_out[7] = ((i_frame_size ) >> 4) & 0xff;
169 #ifdef HAVE_SWAB
170         swab( p_in, &p_out[8], i_frame_size * 2 );
171 #else
172         p_tmp = &p_out[8];
173         for( i = i_frame_size; i-- ; )
174         {
175             p_tmp[0] = p_in[1];
176             p_tmp[1] = p_in[0];
177             p_tmp += 2; p_in += 2;
178         }
179 #endif
180     }
181
182     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
183     p_out_buf->i_nb_bytes = AOUT_SPDIF_SIZE;
184 }
185