]> git.sesse.net Git - vlc/blob - modules/packetizer/mpegaudio.c
* all: new sout scheme. Now a chain of module are created that can
[vlc] / modules / packetizer / mpegaudio.c
1 /*****************************************************************************
2  * mpegaudio.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: mpegaudio.c,v 1.6 2003/04/13 20:00:21 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_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     p_pack->output_format.i_sample_rate = 0;
184     p_pack->output_format.i_channels    = 0;
185     p_pack->output_format.i_block_align = 0;
186     p_pack->output_format.i_bitrate     = 0;
187     p_pack->output_format.i_extra_data  = 0;
188     p_pack->output_format.p_extra_data  = NULL;
189
190
191     p_pack->p_sout_input = NULL;
192
193     p_pack->i_samplescount = 0;
194     p_pack->i_samplespersecond = 0;
195     p_pack->i_last_pts = 0;
196
197     if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
198                        NULL, NULL ) != VLC_SUCCESS )
199     {
200         msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
201         return -1;
202     }
203
204     return( 0 );
205 }
206
207 /*****************************************************************************
208  * PacketizeThread: packetize an unit (here copy a complete pes)
209  *****************************************************************************/
210 static void PacketizeThread( packetizer_t *p_pack )
211 {
212     sout_buffer_t   *p_sout_buffer;
213     size_t          i_size;
214     mtime_t         i_pts;
215
216     uint32_t        i_sync, i_header;
217     int             i_version, i_layer;
218     int             i_channels, i_samplerate, i_bitrate;
219     int             i_samplesperframe, i_framelength;
220     int i_skip = 0;
221     /* search a valid start code */
222     for( ;; )
223     {
224         int i_crc, i_bitrate_index, i_samplerate_index;
225         int i_padding, i_extention, i_mode, i_modeext, i_copyright;
226         int i_original, i_emphasis;
227
228         RealignBits( &p_pack->bit_stream );
229
230
231         while( ShowBits( &p_pack->bit_stream, 12 ) != 0x0fff &&
232                !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
233         {
234             //msg_Warn( p_pack->p_fifo, "trash..." );
235             RemoveBits( &p_pack->bit_stream, 8 );
236             i_skip++;
237         }
238
239         if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
240         {
241             return;
242         }
243
244         /* Set the Presentation Time Stamp */
245         NextPTS( &p_pack->bit_stream, &i_pts, NULL );
246
247         i_sync      = GetBits( &p_pack->bit_stream, 12 );
248         i_header    = ShowBits( &p_pack->bit_stream, 20 );
249
250         i_version   = 1 - GetBits( &p_pack->bit_stream, 1 );
251         i_layer     = 3 - GetBits( &p_pack->bit_stream, 2 );
252         i_crc       = 1 - GetBits( &p_pack->bit_stream, 1 );
253         i_bitrate_index = GetBits( &p_pack->bit_stream, 4 );
254         i_samplerate_index = GetBits( &p_pack->bit_stream, 2 );
255         i_padding   = GetBits( &p_pack->bit_stream, 1 );
256         i_extention = GetBits( &p_pack->bit_stream, 1 );
257         i_mode      = GetBits( &p_pack->bit_stream, 2 );
258         i_modeext   = GetBits( &p_pack->bit_stream, 2 );
259         i_copyright = GetBits( &p_pack->bit_stream, 1 );
260         i_original  = GetBits( &p_pack->bit_stream, 1 );
261         i_emphasis  = GetBits( &p_pack->bit_stream, 2 );
262
263         if( i_layer != 3 &&
264             i_bitrate_index > 0x00 && i_bitrate_index < 0x0f &&
265             i_samplerate_index != 0x03 &&
266             i_emphasis != 0x02 )
267         {
268             i_channels = ( i_mode == 3 ) ? 1 : 2;
269             i_bitrate = mpegaudio_bitrate[i_version][i_layer][i_bitrate_index];
270             i_samplerate = mpegaudio_samplerate[i_version][i_samplerate_index];
271             switch( i_layer )
272             {
273                 case 0:
274                     i_framelength = ( 12000 * i_bitrate /
275                                       i_samplerate + i_padding ) * 4;
276                     break;
277                  case 1:
278                     i_framelength = 144000 * i_bitrate /
279                                       i_samplerate + i_padding;
280                     break;
281                  case 2:
282                     i_framelength = ( i_version ? 72000 : 144000 ) *
283                                     i_bitrate / i_samplerate + i_padding;
284                     break;
285                 default:
286                     i_framelength = 0;
287             }
288             switch( i_layer )
289             {
290                 case 0:
291                     i_samplesperframe = 384;
292                     break;
293                 case 1:
294                     i_samplesperframe = 1152;
295                     break;
296                 case 2:
297                     i_samplesperframe = i_version ? 576 : 1152;
298                     break;
299                 default:
300                     i_samplesperframe = 0;
301             }
302             break;
303         }
304     }
305
306     if( !p_pack->p_sout_input )
307     {
308         /* add a input for the stream ouput */
309         p_pack->output_format.i_sample_rate = i_samplerate;
310         p_pack->output_format.i_channels    = i_channels;
311         p_pack->output_format.i_block_align = 1;
312         p_pack->output_format.i_bitrate     = 0;
313
314         p_pack->p_sout_input =
315             sout_InputNew( p_pack->p_fifo,
316                            &p_pack->output_format );
317
318         if( !p_pack->p_sout_input )
319         {
320             msg_Err( p_pack->p_fifo,
321                      "cannot add a new stream" );
322             p_pack->p_fifo->b_error = 1;
323             return;
324         }
325         msg_Dbg( p_pack->p_fifo,
326                  "v:%d l:%d channels:%d samplerate:%d bitrate:%d size:%d",
327                  i_version, i_layer, i_channels, i_samplerate,
328                  i_bitrate, i_framelength );
329     }
330
331     if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
332     {
333         msg_Dbg( p_pack->p_fifo, "need a starting pts" );
334         return;
335     }
336     if( i_pts <= 0 )
337     {
338         i_pts = p_pack->i_last_pts +
339             (uint64_t)1000000 *
340             (uint64_t)i_samplesperframe /
341             (uint64_t)i_samplerate;
342     }
343     p_pack->i_last_pts = i_pts;
344
345     i_size = __MAX( i_framelength, 4 );
346 //    msg_Dbg( p_pack->p_fifo, "frame length %d b", i_size );
347     p_sout_buffer =
348         sout_BufferNew( p_pack->p_sout_input->p_sout, i_size );
349     if( !p_sout_buffer )
350     {
351         p_pack->p_fifo->b_error = 1;
352         return;
353     }
354     p_sout_buffer->p_buffer[0] = ( i_sync >> 4 )&0xff;
355     p_sout_buffer->p_buffer[1] = 
356         ( ( i_sync << 4 )&0xf0 ) | ( ( i_header >> 16 )&0x0f );
357     p_sout_buffer->p_buffer[2] = ( i_header >> 8 )&0xff;
358     p_sout_buffer->p_buffer[3] = ( i_header      )&0xff;
359     p_sout_buffer->i_bitrate = i_bitrate;
360
361     p_sout_buffer->i_dts = i_pts;
362     p_sout_buffer->i_pts = i_pts;
363
364     p_sout_buffer->i_length =
365             (uint64_t)1000000 *
366             (uint64_t)i_samplesperframe /
367             (uint64_t)i_samplerate;
368
369     p_pack->i_samplescount += i_samplesperframe;
370
371     /* we are already aligned */
372     GetChunk( &p_pack->bit_stream,
373               p_sout_buffer->p_buffer + 4,
374               i_size - 4 );
375
376     sout_InputSendBuffer( p_pack->p_sout_input,
377                           p_sout_buffer );
378 }
379
380
381 /*****************************************************************************
382  * EndThread : packetizer thread destruction
383  *****************************************************************************/
384 static void EndThread ( packetizer_t *p_pack)
385 {
386     if( p_pack->p_sout_input )
387     {
388         sout_InputDelete( p_pack->p_sout_input );
389     }
390 }