* aac/* remove old aac demuxer.
[vlc.git] / modules / demux / wav / wav.c
1 /*****************************************************************************
2  * wav.c : wav file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: wav.c,v 1.16 2003/05/21 10:02:55 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31
32 #include <codecs.h>
33 #include "wav.h"
34
35 /*****************************************************************************
36  * Local prototypes
37  *****************************************************************************/
38 static int    WAVInit       ( vlc_object_t * );
39 static void __WAVEnd        ( vlc_object_t * );
40 static int    WAVDemux      ( input_thread_t * );
41 static int    WAVCallDemux  ( input_thread_t * );
42
43 #define WAVEnd(a) __WAVEnd(VLC_OBJECT(a))
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 vlc_module_begin();
49     set_description( _("WAV demuxer") );
50     set_capability( "demux", 142 );
51     set_callbacks( WAVInit, __WAVEnd );
52 vlc_module_end();
53
54 /*****************************************************************************
55  * Declaration of local function
56  *****************************************************************************/
57
58 #define FREE( p ) if( p ) free( p ); (p) = NULL
59
60 #define __EVEN( x ) ( (x)%2 != 0 ) ? ((x)+1) : (x)
61
62 /* Some functions to manipulate memory */
63 static uint16_t GetWLE( uint8_t *p_buff )
64 {
65     return( (p_buff[0]) + ( p_buff[1] <<8 ) );
66 }
67
68 static uint32_t GetDWLE( uint8_t *p_buff )
69 {
70     return( p_buff[0] + ( p_buff[1] <<8 ) +
71             ( p_buff[2] <<16 ) + ( p_buff[3] <<24 ) );
72 }
73
74 static uint32_t CreateDWLE( int a, int b, int c, int d )
75 {
76     return( a + ( b << 8 ) + ( c << 16 ) + ( d << 24 ) );
77 }
78
79
80 static off_t TellAbsolute( input_thread_t *p_input )
81 {
82     off_t i_pos;
83
84     vlc_mutex_lock( &p_input->stream.stream_lock );
85
86     i_pos= p_input->stream.p_selected_area->i_tell;
87
88     vlc_mutex_unlock( &p_input->stream.stream_lock );
89
90     return( i_pos );
91 }
92
93 /* return 1 if success, 0 if fail */
94 static int ReadData( input_thread_t *p_input, uint8_t *p_buff, int i_size )
95 {
96     data_packet_t *p_data;
97
98     int i_count = 0;
99
100     if( !i_size )
101     {
102         return( 0 );
103     }
104
105     do
106     {
107         int i_read;
108
109         i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size, 1024 ) );
110         if( i_read <= 0 )
111         {
112             return( i_count );
113         }
114         memcpy( p_buff, p_data->p_payload_start, i_read );
115         input_DeletePacket( p_input->p_method_data, p_data );
116
117         p_buff += i_read;
118         i_size -= i_read;
119         i_count += i_read;
120
121     } while( i_size );
122
123     return( i_count );
124 }
125
126 static int SeekAbsolute( input_thread_t *p_input,
127                          off_t i_pos)
128 {
129     int         i_skip;
130 #if 0
131     if( i_pos >= p_input->stream.p_selected_area->i_size )
132     {
133         return( 0 );
134     }
135 #endif
136
137     i_skip    = i_pos - TellAbsolute( p_input );
138     if( i_skip == 0 )
139     {
140         return( VLC_SUCCESS );
141     }
142     if( i_skip < 0 && !p_input->stream.b_seekable )
143     {
144         return( VLC_EGENERIC );
145     }
146     else if( !p_input->stream.b_seekable ||
147              ( i_skip > 0 && i_skip < 1024 && p_input->stream.i_method != INPUT_METHOD_FILE ) )
148     {
149         while( i_skip > 0 )
150         {
151             uint8_t dummy[1024];
152             int     i_read;
153
154             i_read = ReadData( p_input, dummy, __MIN( i_skip, 1024 ) );
155             if( i_read <= 0 )
156             {
157                 return( VLC_EGENERIC );
158             }
159             i_skip -= i_read;
160         }
161         return( VLC_SUCCESS );
162     }
163     else
164     {
165             input_AccessReinit( p_input );
166             p_input->pf_seek( p_input, i_pos );
167             return( VLC_SUCCESS );
168     }
169 }
170
171 static int SkipBytes( input_thread_t *p_input, int i_skip )
172 {
173     return( SeekAbsolute( p_input, TellAbsolute( p_input ) + i_skip ) );
174 }
175
176 static int ReadPES( input_thread_t *p_input,
177                     pes_packet_t **pp_pes,
178                     int i_size )
179 {
180     pes_packet_t *p_pes;
181
182     *pp_pes = NULL;
183
184     if( !(p_pes = input_NewPES( p_input->p_method_data )) )
185     {
186         msg_Err( p_input, "cannot allocate new PES" );
187         return( 0 );
188     }
189
190     while( i_size > 0 )
191     {
192         data_packet_t   *p_data;
193         int i_read;
194
195         if( (i_read = input_SplitBuffer( p_input,
196                                          &p_data,
197                                          __MIN( i_size, 1024 ) ) ) <= 0 )
198         {
199             input_DeletePES( p_input->p_method_data, p_pes );
200             return( 0 );
201         }
202         if( !p_pes->p_first )
203         {
204             p_pes->p_first = p_data;
205             p_pes->i_nb_data = 1;
206             p_pes->i_pes_size = i_read;
207         }
208         else
209         {
210             p_pes->p_last->p_next  = p_data;
211             p_pes->i_nb_data++;
212             p_pes->i_pes_size += i_read;
213         }
214         p_pes->p_last  = p_data;
215         i_size -= i_read;
216     }
217     *pp_pes = p_pes;
218     return( 1 );
219 }
220
221 static int FindTag( input_thread_t *p_input, uint32_t i_tag )
222 {
223     uint32_t   i_id;
224     uint32_t   i_size;
225     uint8_t    *p_peek;
226
227     for( ;; )
228     {
229
230         if( input_Peek( p_input, &p_peek, 8 ) < 8 )
231         {
232             msg_Err( p_input, "cannot peek()" );
233             return( 0 );
234         }
235
236         i_id   = GetDWLE( p_peek );
237         i_size = GetDWLE( p_peek + 4 );
238
239         msg_Dbg( p_input, "FindTag: tag:%4.4s size:%d", (char*)&i_id, i_size );
240         if( i_id == i_tag )
241         {
242             /* Yes, we have found the good tag */
243             return( 1 );
244         }
245         if( SkipBytes( p_input, __EVEN( i_size ) + 8 ) )
246         {
247             return( 0 );
248         }
249     }
250 }
251
252 static int LoadTag_fmt( input_thread_t *p_input,
253                         demux_sys_t *p_demux )
254 {
255     uint8_t  *p_peek;
256     uint32_t i_size;
257     WAVEFORMATEX *p_wf;
258
259
260     if( input_Peek( p_input, &p_peek , 8 ) < 8 )
261     {
262         return( 0 );
263     }
264
265     p_demux->i_wf = i_size = GetDWLE( p_peek + 4 );
266     SkipBytes( p_input, 8 );
267     if( i_size < 16 )
268     {
269         SkipBytes( p_input, i_size );
270         return( 0 );
271     }
272     p_wf = p_demux->p_wf = malloc( __MAX( i_size, sizeof( WAVEFORMATEX) ) );
273     ReadData( p_input, (uint8_t*)p_wf, __EVEN( i_size ) );
274
275     p_wf->wFormatTag      = GetWLE( (uint8_t*)&p_demux->p_wf->wFormatTag );
276     p_wf->nChannels       = GetWLE( (uint8_t*)&p_demux->p_wf->nChannels );
277     p_wf->nSamplesPerSec  = GetWLE( (uint8_t*)&p_demux->p_wf->nSamplesPerSec );
278     p_wf->nAvgBytesPerSec = GetWLE( (uint8_t*)&p_demux->p_wf->nAvgBytesPerSec );
279     p_wf->nBlockAlign     = GetWLE( (uint8_t*)&p_demux->p_wf->nBlockAlign );
280     p_wf->wBitsPerSample  = GetWLE( (uint8_t*)&p_demux->p_wf->wBitsPerSample );
281     if( i_size >= sizeof( WAVEFORMATEX) )
282     {
283         p_wf->cbSize          = GetWLE( (uint8_t*)&p_demux->p_wf->cbSize );
284     }
285     else
286     {
287         p_wf->cbSize = 0;
288     }
289
290     msg_Dbg( p_input, "loaded \"fmt \" chunk" );
291     return( 1 );
292 }
293
294 static int PCM_GetFrame( input_thread_t *p_input,
295                          WAVEFORMATEX   *p_wf,
296                          pes_packet_t   **pp_pes,
297                          mtime_t        *pi_length )
298 {
299     int i_samples;
300
301     int i_bytes;
302     int i_modulo;
303
304     /* read samples for 50ms of */
305     i_samples = __MAX( p_wf->nSamplesPerSec / 20, 1 );
306
307
308     *pi_length = (mtime_t)1000000 *
309                  (mtime_t)i_samples /
310                  (mtime_t)p_wf->nSamplesPerSec;
311
312     i_bytes = i_samples * p_wf->nChannels * ( (p_wf->wBitsPerSample + 7) / 8 );
313
314     if( p_wf->nBlockAlign > 0 )
315     {
316         if( ( i_modulo = i_bytes % p_wf->nBlockAlign ) != 0 )
317         {
318             i_bytes += p_wf->nBlockAlign - i_modulo;
319         }
320     }
321
322     return( ReadPES( p_input, pp_pes, i_bytes ) );
323 }
324
325 static int MS_ADPCM_GetFrame( input_thread_t *p_input,
326                               WAVEFORMATEX   *p_wf,
327                               pes_packet_t   **pp_pes,
328                               mtime_t        *pi_length )
329 {
330     int i_samples;
331
332     i_samples = 2 + 2 * ( p_wf->nBlockAlign -
333                                 7 * p_wf->nChannels ) / p_wf->nChannels;
334
335     *pi_length = (mtime_t)1000000 *
336                  (mtime_t)i_samples /
337                  (mtime_t)p_wf->nSamplesPerSec;
338
339     return( ReadPES( p_input, pp_pes, p_wf->nBlockAlign ) );
340 }
341
342 static int IMA_ADPCM_GetFrame( input_thread_t *p_input,
343                                WAVEFORMATEX   *p_wf,
344                                pes_packet_t   **pp_pes,
345                                mtime_t        *pi_length )
346 {
347     int i_samples;
348
349     i_samples = 2 * ( p_wf->nBlockAlign -
350                         4 * p_wf->nChannels ) / p_wf->nChannels;
351
352     *pi_length = (mtime_t)1000000 *
353                  (mtime_t)i_samples /
354                  (mtime_t)p_wf->nSamplesPerSec;
355
356     return( ReadPES( p_input, pp_pes, p_wf->nBlockAlign ) );
357 }
358
359 /*****************************************************************************
360  * WAVInit: check file and initializes structures
361  *****************************************************************************/
362 static int WAVInit( vlc_object_t * p_this )
363 {
364     input_thread_t *p_input = (input_thread_t *)p_this;
365     uint8_t  *p_peek;
366     uint32_t i_size;
367
368     demux_sys_t *p_demux;
369
370
371
372     /* Initialize access plug-in structures. */
373     if( p_input->i_mtu == 0 )
374     {
375         /* Improve speed. */
376         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
377     }
378
379     /* a little test to see if it's a wav file */
380     if( input_Peek( p_input, &p_peek, 12 ) < 12 )
381     {
382         msg_Warn( p_input, "WAV plugin discarded (cannot peek)" );
383         return( -1 );
384     }
385
386     if( ( GetDWLE( p_peek ) != CreateDWLE( 'R', 'I', 'F', 'F' ) )||
387         ( GetDWLE( p_peek + 8 ) != CreateDWLE( 'W', 'A', 'V', 'E' ) ) )
388     {
389         msg_Warn( p_input, "WAV plugin discarded (not a valid file)" );
390         return( -1 );
391     }
392     i_size = GetDWLE( p_peek + 4 );
393     SkipBytes( p_input, 12 );
394
395     if( !FindTag( p_input, CreateDWLE( 'f', 'm', 't' ,' ' ) ) )
396     {
397         msg_Err( p_input, "cannot find \"fmt \" tag" );
398         return( -1 );
399     }
400
401     /* create our structure that will contains all data */
402     if( !( p_input->p_demux_data =
403                 p_demux = malloc( sizeof( demux_sys_t ) ) ) )
404     {
405         msg_Err( p_input, "out of memory" );
406         return( -1 );
407     }
408     memset( p_demux, 0, sizeof( demux_sys_t ) );
409
410     /* Load WAVEFORMATEX header */
411     if( !LoadTag_fmt( p_input, p_demux ) )
412     {
413         msg_Err( p_input, "cannot load \"fmt \" tag" );
414         FREE( p_demux );
415         return( -1 );
416     }
417     msg_Dbg( p_input, "format:0x%4.4x channels:%d %dHz %dKo/s blockalign:%d bits/samples:%d extra size:%d",
418             p_demux->p_wf->wFormatTag,
419             p_demux->p_wf->nChannels,
420             p_demux->p_wf->nSamplesPerSec,
421             p_demux->p_wf->nAvgBytesPerSec / 1024,
422             p_demux->p_wf->nBlockAlign,
423             p_demux->p_wf->wBitsPerSample,
424             p_demux->p_wf->cbSize );
425
426     if( !FindTag( p_input, CreateDWLE( 'd', 'a', 't', 'a' ) ) )
427     {
428         msg_Err( p_input, "cannot find \"data\" tag" );
429         FREE( p_demux->p_wf );
430         FREE( p_demux );
431         return( -1 );
432     }
433     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
434     {
435         msg_Warn( p_input, "WAV plugin discarded (cannot peek)" );
436         FREE( p_demux->p_wf );
437         FREE( p_demux );
438         return( -1 );
439     }
440
441     p_demux->i_data_pos = TellAbsolute( p_input ) + 8;
442     p_demux->i_data_size = GetDWLE( p_peek + 4 );
443     SkipBytes( p_input, 8 );
444
445     /* XXX p_demux->psz_demux shouldn't be NULL ! */
446     switch( p_demux->p_wf->wFormatTag )
447     {
448         case( WAVE_FORMAT_PCM ):
449             msg_Dbg( p_input,"found raw pcm audio format" );
450             p_demux->i_fourcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
451             p_demux->GetFrame = PCM_GetFrame;
452             p_demux->psz_demux = strdup( "" );
453             break;
454         case( WAVE_FORMAT_MULAW ):
455             msg_Dbg( p_input,"found mulaw pcm audio format" );
456             p_demux->i_fourcc = VLC_FOURCC( 'u', 'l', 'a', 'w' );
457             p_demux->GetFrame = PCM_GetFrame;
458             p_demux->psz_demux = strdup( "" );
459             break;
460         case( WAVE_FORMAT_ALAW ):
461             msg_Dbg( p_input,"found alaw pcm audio format" );
462             p_demux->i_fourcc = VLC_FOURCC( 'a', 'l', 'a', 'w' );
463             p_demux->GetFrame = PCM_GetFrame;
464             p_demux->psz_demux = strdup( "" );
465             break;
466         case( WAVE_FORMAT_MPEG ):
467         case( WAVE_FORMAT_MPEGLAYER3 ):
468             msg_Dbg( p_input, "found mpeg audio format" );
469             p_demux->i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
470             p_demux->GetFrame = NULL;
471             p_demux->psz_demux = strdup( "mpegaudio" );
472             break;
473         case( WAVE_FORMAT_A52 ):
474             msg_Dbg( p_input,"found a52 audio format" );
475             p_demux->i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
476             p_demux->GetFrame = NULL;
477             p_demux->psz_demux = strdup( "a52" );
478             break;
479         case( WAVE_FORMAT_ADPCM ):
480             msg_Dbg( p_input, "found ms adpcm audio format" );
481             p_demux->i_fourcc = VLC_FOURCC( 'm', 's', 0x00, 0x02 );
482             p_demux->GetFrame = MS_ADPCM_GetFrame;
483             p_demux->psz_demux = strdup( "" );
484             break;
485         case( WAVE_FORMAT_IMA_ADPCM ):
486             msg_Dbg( p_input, "found ima adpcm audio format" );
487             p_demux->i_fourcc = VLC_FOURCC( 'm', 's', 0x00, 0x11 );
488             p_demux->GetFrame = IMA_ADPCM_GetFrame;
489             p_demux->psz_demux = strdup( "" );
490             break;
491         default:
492             msg_Warn( p_input,"unrecognize audio format(0x%x)",
493                       p_demux->p_wf->wFormatTag );
494             p_demux->i_fourcc =
495                 VLC_FOURCC( 'm', 's',
496                             (p_demux->p_wf->wFormatTag >> 8)&0xff,
497                             (p_demux->p_wf->wFormatTag )&0xff);
498             p_demux->GetFrame = NULL;
499             p_demux->psz_demux = strdup( "" );
500             break;
501     }
502
503     if( p_demux->GetFrame )
504     {
505         msg_Dbg( p_input, "using internal demux" );
506
507         p_input->pf_demux = WAVDemux;
508         p_input->p_demux_data = p_demux;
509
510         /*  create one program */
511         vlc_mutex_lock( &p_input->stream.stream_lock );
512         if( input_InitStream( p_input, 0 ) == -1)
513         {
514             vlc_mutex_unlock( &p_input->stream.stream_lock );
515             msg_Err( p_input, "cannot init stream" );
516             // FIXME
517             return( -1 );
518         }
519         if( input_AddProgram( p_input, 0, 0) == NULL )
520         {
521             vlc_mutex_unlock( &p_input->stream.stream_lock );
522             msg_Err( p_input, "cannot add program" );
523             // FIXME
524             return( -1 );
525         }
526         p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
527         p_input->stream.i_mux_rate = 0 ; /* FIXME */
528
529         p_demux->p_es = input_AddES( p_input,
530                                      p_input->stream.p_selected_program,
531                                      1, AUDIO_ES, NULL, 0 );
532         p_demux->p_es->i_stream_id = 1;
533         p_demux->p_es->i_fourcc = p_demux->i_fourcc;
534         p_demux->p_es->p_waveformatex = malloc( p_demux->i_wf );
535         memcpy( p_demux->p_es->p_waveformatex, p_demux->p_wf, p_demux->i_wf );
536
537         input_SelectES( p_input, p_demux->p_es );
538
539         p_input->stream.p_selected_program->b_is_ok = 1;
540         vlc_mutex_unlock( &p_input->stream.stream_lock );
541     }
542     else
543     {
544         char *psz_sav;
545         /* call an external demux */
546         msg_Warn( p_input, "unsupported formattag, using external demux" );
547
548         psz_sav = p_input->psz_demux;
549         p_input->psz_demux = p_demux->psz_demux;
550
551         p_demux->p_demux = module_Need( p_input, "demux", NULL );
552
553         p_input->psz_demux = psz_sav;
554
555         if( !p_demux->p_demux )
556         {
557             msg_Err( p_input,
558                      "cannot get external demux for formattag 0x%x",
559                      p_demux->p_wf->wFormatTag );
560             FREE( p_demux->psz_demux );
561             FREE( p_demux->p_wf );
562             FREE( p_demux );
563             return( -1 );
564         }
565         /* save value and switch back */
566         p_demux->pf_demux = p_input->pf_demux;
567         p_demux->p_demux_data = p_input->p_demux_data;
568
569         p_input->pf_demux = WAVCallDemux;
570         p_input->p_demux_data = p_demux;
571
572     }
573
574     return( 0 );
575 }
576
577 /*****************************************************************************
578  * WAVCallDemux: call true demux
579  *****************************************************************************
580  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
581  *****************************************************************************/
582 static int WAVCallDemux( input_thread_t *p_input )
583 {
584     demux_sys_t  *p_demux = p_input->p_demux_data;
585     int i_status;
586     char *psz_sav;
587
588     /* save context */
589     psz_sav = p_input->psz_demux;
590
591     /* switch context */
592     p_input->pf_demux = p_demux->pf_demux;
593     p_input->p_demux_data = p_demux->p_demux_data;
594     p_input->psz_demux = p_demux->psz_demux;
595
596     /* call demux */
597     i_status = p_input->pf_demux( p_input );
598
599     /* save (new?) state */
600     p_demux->pf_demux = p_input->pf_demux;
601     p_demux->p_demux_data = p_input->p_demux_data;
602
603     /* switch back */
604     p_input->psz_demux = psz_sav;
605     p_input->pf_demux = WAVCallDemux;
606     p_input->p_demux_data = p_demux;
607
608     return( i_status );
609 }
610
611 /*****************************************************************************
612  * WAVDemux: read packet and send them to decoders
613  *****************************************************************************
614  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
615  *****************************************************************************/
616 static int WAVDemux( input_thread_t *p_input )
617 {
618     demux_sys_t  *p_demux = p_input->p_demux_data;
619     pes_packet_t *p_pes;
620     mtime_t      i_length;
621
622     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
623     {
624         off_t   i_offset;
625
626         i_offset = TellAbsolute( p_input ) - p_demux->i_data_pos;
627         if( i_offset < 0 )
628         {
629             i_offset = 0;
630         }
631         if( p_demux->p_wf->nBlockAlign != 0 )
632         {
633             i_offset += p_demux->p_wf->nBlockAlign -
634                                 i_offset % p_demux->p_wf->nBlockAlign;
635         }
636         SeekAbsolute( p_input, p_demux->i_data_pos + i_offset );
637     }
638
639     input_ClockManageRef( p_input,
640                           p_input->stream.p_selected_program,
641                           p_demux->i_pcr );
642
643     if( TellAbsolute( p_input )
644          >= (off_t)(p_demux->i_data_pos + p_demux->i_data_size) )
645     {
646         return( 0 ); // EOF
647     }
648
649     if( !p_demux->GetFrame( p_input, p_demux->p_wf, &p_pes, &i_length ) )
650     {
651         msg_Warn( p_input, "failed to get one frame" );
652         return( 0 );
653     }
654
655     p_pes->i_dts =
656         p_pes->i_pts = input_ClockGetTS( p_input,
657                                          p_input->stream.p_selected_program,
658                                          p_demux->i_pcr );
659
660     if( !p_demux->p_es->p_decoder_fifo )
661     {
662         msg_Err( p_input, "no audio decoder" );
663         input_DeletePES( p_input->p_method_data, p_pes );
664         return( -1 );
665     }
666     else
667     {
668         input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
669     }
670
671     p_demux->i_pcr += i_length * 9 / 100;
672     return( 1 );
673 }
674
675 /*****************************************************************************
676  * WAVEnd: frees unused data
677  *****************************************************************************/
678 static void __WAVEnd ( vlc_object_t * p_this )
679 {
680     input_thread_t *  p_input = (input_thread_t *)p_this;
681     demux_sys_t *p_demux = p_input->p_demux_data;
682
683     FREE( p_demux->p_wf );
684     FREE( p_demux->psz_demux );
685
686     if( p_demux->p_demux )
687     {
688         char *psz_sav;
689
690         /* save context */
691         psz_sav = p_input->psz_demux;
692
693         /* switch context */
694         p_input->pf_demux = p_demux->pf_demux;
695         p_input->p_demux_data = p_demux->p_demux_data;
696         p_input->psz_demux = p_demux->psz_demux;
697
698         /* unload module */
699         module_Unneed( p_input, p_demux->p_demux );
700
701         /* switch back */
702         p_input->psz_demux = psz_sav;
703         p_input->p_demux_data = p_demux;
704     }
705
706     FREE( p_input->p_demux_data );
707 }
708