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