]> git.sesse.net Git - vlc/blob - modules/packetizer/mpegaudio.c
1f998a85f0f136e10be07c94b0d491ec1d94944b
[vlc] / modules / packetizer / mpegaudio.c
1 /*****************************************************************************
2  * mpegaudio.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: mpegaudio.c,v 1.3 2003/02/18 00:51:40 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
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 <vlc/vlc.h>
29 #include <vlc/aout.h>
30 #include <vlc/decoder.h>
31 #include <vlc/input.h>
32 #include <vlc/sout.h>
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36 #include "codecs.h"                         /* WAVEFORMATEX BITMAPINFOHEADER */
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 typedef struct packetizer_s
41 {
42     /* Input properties */
43     decoder_fifo_t          *p_fifo;
44     bit_stream_t            bit_stream;
45
46     /* Output properties */
47     sout_input_t            *p_sout_input;
48     sout_packet_format_t    output_format;
49
50     uint64_t                i_samplescount;
51     uint32_t                i_samplespersecond;
52
53 } packetizer_t;
54
55 static int  Open    ( vlc_object_t * );
56 static int  Run     ( decoder_fifo_t * );
57
58 static int  InitThread     ( packetizer_t * );
59 static void PacketizeThread   ( packetizer_t * );
60 static void EndThread      ( packetizer_t * );
61
62 #define FREE( p ) if( p ) free( p ); p = NULL
63
64 /*****************************************************************************
65  * Module descriptor
66  *****************************************************************************/
67
68 vlc_module_begin();
69     set_description( _("MPEG-I/II audio packetizer") );
70     set_capability( "packetizer", 50 );
71     set_callbacks( Open, NULL );
72 vlc_module_end();
73
74
75 static int mpegaudio_bitrate[2][3][16] =
76 {
77   {
78     /* v1 l1 */
79     { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
80     /* v1 l2 */
81     { 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
82     /* v1 l3 */
83     { 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 0} 
84   },
85
86   {
87      /* v2 l1 */
88     { 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
89     /* v2 l2 */
90     { 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0},
91     /* v2 l3 */
92     { 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0} 
93   }
94
95 };
96
97 static int mpegaudio_samplerate[2][4] = /* version 1 then 2 */
98 {
99     { 44100, 48000, 32000, 0 },
100     { 22050, 24000, 16000, 0 }
101 };
102
103
104 /*****************************************************************************
105  * OpenDecoder: probe the packetizer and return score
106  *****************************************************************************
107  * Tries to launch a decoder and return score so that the interface is able
108  * to choose.
109  *****************************************************************************/
110 static int Open( vlc_object_t *p_this )
111 {
112     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
113
114     if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') )
115     {
116         return VLC_EGENERIC;
117     }
118
119     p_fifo->pf_run = Run;
120     return VLC_SUCCESS;
121 }
122
123 /*****************************************************************************
124  * RunDecoder: this function is called just after the thread is created
125  *****************************************************************************/
126 static int Run( decoder_fifo_t *p_fifo )
127 {
128     packetizer_t *p_pack;
129     int b_error;
130
131     msg_Info( p_fifo, "Running mpegaudio packetizer" );
132     if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
133     {
134         msg_Err( p_fifo, "out of memory" );
135         DecoderError( p_fifo );
136         return( -1 );
137     }
138     memset( p_pack, 0, sizeof( packetizer_t ) );
139
140     p_pack->p_fifo = p_fifo;
141
142     if( InitThread( p_pack ) != 0 )
143     {
144         DecoderError( p_fifo );
145         return( -1 );
146     }
147
148     while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
149     {
150         PacketizeThread( p_pack );
151     }
152
153
154     if( ( b_error = p_pack->p_fifo->b_error ) )
155     {
156         DecoderError( p_pack->p_fifo );
157     }
158
159     EndThread( p_pack );
160
161     FREE( p_pack );
162
163     if( b_error )
164     {
165         return( -1 );
166     }
167
168     return( 0 );
169 }
170
171
172
173 /*****************************************************************************
174  * InitThread: initialize data before entering main loop
175  *****************************************************************************/
176
177 static int InitThread( packetizer_t *p_pack )
178 {
179
180     p_pack->output_format.i_cat = AUDIO_ES;
181     p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
182
183     p_pack->output_format.p_format = NULL;
184
185     p_pack->p_sout_input = NULL;
186
187     p_pack->i_samplescount = 0;
188     p_pack->i_samplespersecond = 0;
189
190     if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
191                        NULL, NULL ) != VLC_SUCCESS )
192     {
193         msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
194         return -1;
195     }
196
197     return( 0 );
198 }
199
200 /*****************************************************************************
201  * PacketizeThread: packetize an unit (here copy a complete pes)
202  *****************************************************************************/
203 static void PacketizeThread( packetizer_t *p_pack )
204 {
205     sout_buffer_t   *p_sout_buffer;
206     size_t          i_size;
207
208     uint32_t        i_sync, i_header;
209     int             i_version, i_layer;
210     int             i_channels, i_samplerate, i_bitrate;
211     int             i_samplesperframe, i_framelength;
212     int i_skip = 0;
213     /* search a valid start code */
214     for( ;; )
215     {
216         int i_crc, i_bitrate_index, i_samplerate_index;
217         int i_padding, i_extention, i_mode, i_modeext, i_copyright;
218         int i_original, i_emphasis;
219
220         RealignBits( &p_pack->bit_stream );
221
222
223         while( ShowBits( &p_pack->bit_stream, 12 ) != 0x0fff &&
224                !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
225         {
226             //msg_Warn( p_pack->p_fifo, "trash..." );
227             RemoveBits( &p_pack->bit_stream, 8 );
228             i_skip++;
229         }
230
231         if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
232         {
233             return;
234         }
235
236         i_sync      = GetBits( &p_pack->bit_stream, 12 );
237         i_header    = ShowBits( &p_pack->bit_stream, 20 );
238
239         i_version   = 1 - GetBits( &p_pack->bit_stream, 1 );
240         i_layer     = 3 - GetBits( &p_pack->bit_stream, 2 );
241         i_crc       = 1 - GetBits( &p_pack->bit_stream, 1 );
242         i_bitrate_index = GetBits( &p_pack->bit_stream, 4 );
243         i_samplerate_index = GetBits( &p_pack->bit_stream, 2 );
244         i_padding   = GetBits( &p_pack->bit_stream, 1 );
245         i_extention = GetBits( &p_pack->bit_stream, 1 );
246         i_mode      = GetBits( &p_pack->bit_stream, 2 );
247         i_modeext   = GetBits( &p_pack->bit_stream, 2 );
248         i_copyright = GetBits( &p_pack->bit_stream, 1 );
249         i_original  = GetBits( &p_pack->bit_stream, 1 );
250         i_emphasis  = GetBits( &p_pack->bit_stream, 2 );
251
252         if( i_layer != 3 &&
253             i_bitrate_index > 0x00 && i_bitrate_index < 0x0f &&
254             i_samplerate_index != 0x03 &&
255             i_emphasis != 0x02 )
256         {
257             i_channels = ( i_mode == 3 ) ? 1 : 2;
258             i_bitrate = mpegaudio_bitrate[i_version][i_layer][i_bitrate_index];
259             i_samplerate = mpegaudio_samplerate[i_version][i_samplerate_index];
260             switch( i_layer )
261             {
262                 case 0:
263                     i_framelength = ( 12000 * i_bitrate /
264                                       i_samplerate + i_padding ) * 4;
265                     break;
266                  case 1:
267                     i_framelength = 144000 * i_bitrate /
268                                       i_samplerate + i_padding;
269                     break;
270                  case 2:
271                     i_framelength = ( i_version ? 72000 : 144000 ) *
272                                     i_bitrate / i_samplerate + i_padding;
273                     break;
274                 default:
275                     i_framelength = 0;
276             }
277             switch( i_layer )
278             {
279                 case 0:
280                     i_samplesperframe = 384;
281                     break;
282                 case 1:
283                     i_samplesperframe = 1152;
284                     break;
285                 case 2:
286                     i_samplesperframe = i_version ? 576 : 1152;
287                     break;
288                 default:
289                     i_samplesperframe = 0;
290             }
291             break;
292         }
293     }
294
295     if( !p_pack->p_sout_input )
296     {
297         /* add a input for the stream ouput */
298         WAVEFORMATEX    *p_wf;
299
300         p_wf = malloc( sizeof( WAVEFORMATEX ) );
301         p_pack->output_format.p_format = (void*)p_wf;
302
303         p_wf->wFormatTag        = WAVE_FORMAT_MPEG;
304         p_wf->nChannels         = i_channels;
305         p_wf->nSamplesPerSec    = i_samplerate;
306         p_wf->nAvgBytesPerSec   = 0;
307         p_wf->nBlockAlign       = 1;
308         p_wf->wBitsPerSample    = 0;
309         p_wf->cbSize            = 0; // FIXME there are more field for mpegaudio
310
311         p_pack->p_sout_input =
312             sout_InputNew( p_pack->p_fifo,
313                            &p_pack->output_format );
314
315         if( !p_pack->p_sout_input )
316         {
317             msg_Err( p_pack->p_fifo,
318                      "cannot add a new stream" );
319             p_pack->p_fifo->b_error = 1;
320             return;
321         }
322         msg_Dbg( p_pack->p_fifo,
323                  "v:%d l:%d channels:%d samplerate:%d bitrate:%d size:%d",
324                  i_version, i_layer, i_channels, i_samplerate,
325                  i_bitrate, i_framelength );
326     }
327
328     i_size = __MAX( i_framelength, 4 );
329 //    msg_Dbg( p_pack->p_fifo, "frame length %d b", i_size );
330     p_sout_buffer =
331         sout_BufferNew( p_pack->p_sout_input->p_sout, i_size );
332     if( !p_sout_buffer )
333     {
334         p_pack->p_fifo->b_error = 1;
335         return;
336     }
337     p_sout_buffer->p_buffer[0] = ( i_sync >> 4 )&0xff;
338     p_sout_buffer->p_buffer[1] = 
339         ( ( i_sync << 4 )&0xf0 ) | ( ( i_header >> 16 )&0x0f );
340     p_sout_buffer->p_buffer[2] = ( i_header >> 8 )&0xff;
341     p_sout_buffer->p_buffer[3] = ( i_header      )&0xff;
342     p_sout_buffer->i_bitrate = i_bitrate;
343
344     p_sout_buffer->i_pts =
345         p_sout_buffer->i_dts =
346             (uint64_t)1000000 *
347             (uint64_t)p_pack->i_samplescount /
348             (uint64_t)i_samplerate;
349     p_sout_buffer->i_length =
350             (uint64_t)1000000 *
351             (uint64_t)i_samplesperframe /
352             (uint64_t)i_samplerate;
353
354     p_pack->i_samplescount += i_samplesperframe;
355
356     /* we are already aligned */
357     GetChunk( &p_pack->bit_stream,
358               p_sout_buffer->p_buffer + 4,
359               i_size - 4 );
360
361     sout_InputSendBuffer( p_pack->p_sout_input,
362                           p_sout_buffer );
363 }
364
365
366 /*****************************************************************************
367  * EndThread : packetizer thread destruction
368  *****************************************************************************/
369 static void EndThread ( packetizer_t *p_pack)
370 {
371     if( p_pack->p_sout_input )
372     {
373         sout_InputDelete( p_pack->p_sout_input );
374     }
375 }