]> git.sesse.net Git - vlc/blob - src/input/input_netlist.c
b63aa853f281793ad2d99de11edf299dd518881a
[vlc] / src / input / input_netlist.c
1 /*****************************************************************************
2  * dvd_netlist.c: netlist management v2
3  *****************************************************************************
4  * There is only one major change from input_netlist.c (1) : data is now a
5  * pointer to an offset in iovec ; and iovec has a reference counter. It
6  * will only be given back to netlist when refcount is zero.
7  *****************************************************************************
8  * Copyright (C) 1998-2001 VideoLAN
9  * $Id: input_netlist.c,v 1.48 2001/12/09 17:01:37 sam Exp $
10  *
11  * Authors: Henri Fallon <henri@videolan.org>
12  *          Stéphane Borel <stef@videolan.org>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
27  *****************************************************************************/
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #include "defs.h"
33
34 #include <stdlib.h>
35 #include <string.h>                                    /* memcpy(), memset() */
36 #include <sys/types.h>
37
38 #ifdef HAVE_UNISTD_H
39 #   include <unistd.h>
40 #endif
41
42 #if defined( WIN32 )
43 #   include <io.h>                                                 /* read() */
44 #else
45 #   include <sys/uio.h>                                      /* struct iovec */
46 #endif
47
48 #include "common.h"
49 #include "intf_msg.h"                                           /* intf_*Msg */
50 #include "threads.h"                                                /* mutex */
51 #include "mtime.h"
52
53 #if defined( WIN32 )
54 #   include "input_iovec.h"
55 #endif
56
57 #include "stream_control.h"
58 #include "input_ext-intf.h"
59 #include "input_ext-dec.h"
60 #include "input_ext-plugins.h"
61
62 /*****************************************************************************
63  * Local prototypes
64  *****************************************************************************/
65
66 /*****************************************************************************
67  * input_NetlistInit: allocates netlist buffers and init indexes
68  * ---
69  * Changes from input_NetList: we have to give the length of the buffer which
70  * is different from i_nb_data now, since we may have several data pointers
71  * in one iovec. Thus we can only delete an iovec when its refcount is 0.
72  * We only received a buffer with a GetIovec whereas NewPacket gives a pointer.
73  *****************************************************************************/
74 int input_NetlistInit( input_thread_t * p_input,
75                        int i_nb_iovec, int i_nb_data, int i_nb_pes,
76                        size_t i_buffer_size, int i_read_once )
77 {
78     unsigned int        i_loop;
79     netlist_t *         p_netlist;
80
81     /* First we allocate and initialise our netlist struct */
82     p_input->p_method_data = malloc(sizeof(netlist_t));
83     if ( p_input->p_method_data == NULL )
84     {
85         intf_ErrMsg("Unable to malloc the netlist struct");
86         return (-1);
87     }
88
89     p_netlist = (netlist_t *) p_input->p_method_data;
90                 
91     /* Nb of packets read once by input */
92     p_netlist->i_read_once = i_read_once;
93     
94     /* In order to optimize netlist, we are taking i_nb_data a 2^i 
95      * so that modulo is an "&".
96      * This is not changing i_nb data outside this function except in 
97      * the netlist_t struct */ 
98     /* As i_loop is unsigned int, and i_ns_data int, this shouldn't be a 
99      * problem */
100     for( i_loop = 1; i_loop < i_nb_data; i_loop *= 2 )
101     {
102         ;
103     }
104
105     intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_data,i_loop );
106     i_nb_data = i_loop;
107
108     /* Same thing for i_nb_pes */
109     for( i_loop = 1; i_loop < i_nb_pes; i_loop *= 2 )
110     {
111         ;
112     }
113
114     intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_pes,i_loop );
115     i_nb_pes = i_loop;
116
117      /* Same thing for i_nb_iovec */
118     for( i_loop = 1; i_loop < i_nb_iovec; i_loop *= 2 )
119     {
120         ;
121     }
122
123     intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_iovec,i_loop );
124     i_nb_iovec = i_loop;
125    
126     /* allocate the buffers */ 
127     p_netlist->p_buffers = malloc( i_nb_iovec *i_buffer_size );
128     if ( p_netlist->p_buffers == NULL )
129     {
130         intf_ErrMsg ("Unable to malloc in netlist initialization (1)");
131         free( p_netlist );
132         return -1;
133     }
134     
135     /* table of pointers to data packets */
136     p_netlist->p_data = malloc( i_nb_data *sizeof(data_packet_t) );
137     if ( p_netlist->p_data == NULL )
138     {
139         intf_ErrMsg ("Unable to malloc in netlist initialization (2)");
140         free( p_netlist->p_buffers );
141         free( p_netlist );
142         return -1;
143     }
144     
145     /* table of pointer to PES packets */
146     p_netlist->p_pes = malloc( i_nb_pes *sizeof(pes_packet_t) );
147     if ( p_netlist->p_pes == NULL )
148     {
149         intf_ErrMsg ("Unable to malloc in netlist initialization (3)");
150         free( p_netlist->p_buffers );
151         free( p_netlist->p_data );
152         free( p_netlist );
153         return -1;
154     }
155     
156     /* allocate the FIFOs : tables of free pointers */
157     p_netlist->pp_free_data = 
158                         malloc( i_nb_data *sizeof(data_packet_t *) );
159     if ( p_netlist->pp_free_data == NULL )
160     {
161         intf_ErrMsg ("Unable to malloc in netlist initialization (4)");
162         free( p_netlist->p_buffers );
163         free( p_netlist->p_data );
164         free( p_netlist->p_pes );
165         free( p_netlist );
166         return -1;
167     }
168     p_netlist->pp_free_pes = 
169                         malloc( i_nb_pes *sizeof(pes_packet_t *) );
170     if ( p_netlist->pp_free_pes == NULL )
171     {
172         intf_ErrMsg ("Unable to malloc in netlist initialization (5)");
173         free( p_netlist->p_buffers );
174         free( p_netlist->p_data );
175         free( p_netlist->p_pes );
176         free( p_netlist->pp_free_data );
177         free( p_netlist );
178         return -1;
179     }
180     
181     p_netlist->p_free_iovec =
182         malloc( (i_nb_iovec + p_netlist->i_read_once) * sizeof(struct iovec) );
183     if ( p_netlist->p_free_iovec == NULL )
184     {
185         intf_ErrMsg ("Unable to malloc in DVD netlist initialization (6)");
186         free( p_netlist->p_buffers );
187         free( p_netlist->p_data );
188         free( p_netlist->p_pes );
189         free( p_netlist->pp_free_data );
190         free( p_netlist->pp_free_pes );
191         free( p_netlist );
192         return -1;
193     }
194
195     /* table for reference counter of iovecs */
196     p_netlist->pi_refcount = malloc( i_nb_iovec *sizeof(int) );
197     if ( p_netlist->pi_refcount == NULL )
198     {
199         intf_ErrMsg ("Unable to malloc in DVD netlist initialization (7)");
200         free( p_netlist->p_buffers );
201         free( p_netlist->p_data );
202         free( p_netlist->p_pes );
203         free( p_netlist->pp_free_data );
204         free( p_netlist->pp_free_pes );
205         free( p_netlist->p_free_iovec );
206         free( p_netlist );
207         return -1;
208     }
209
210     /* Fill the data FIFO */
211     for ( i_loop = 0; i_loop < i_nb_data; i_loop++ )
212     {
213         p_netlist->pp_free_data[i_loop] = 
214             p_netlist->p_data + i_loop;
215
216         /* by default, one data packet for one buffer */
217         if( i_nb_data == i_nb_iovec )
218         {
219             p_netlist->pp_free_data[i_loop]->p_buffer =
220                 p_netlist->p_buffers + i_loop * i_buffer_size;
221
222             p_netlist->pp_free_data[i_loop]->p_payload_start =
223                 p_netlist->pp_free_data[i_loop]->p_buffer;
224
225             p_netlist->pp_free_data[i_loop]->p_payload_end =
226                 p_netlist->pp_free_data[i_loop]->p_buffer + i_buffer_size;
227         }
228     }
229
230     /* Fill the PES FIFO */
231     for ( i_loop = 0; i_loop < i_nb_pes ; i_loop++ )
232     {
233         p_netlist->pp_free_pes[i_loop] = 
234             p_netlist->p_pes + i_loop;
235     }
236    
237     /* Deal with the iovec */
238     for ( i_loop = 0; i_loop < i_nb_iovec; i_loop++ )
239     {
240         p_netlist->p_free_iovec[i_loop].iov_base = 
241             p_netlist->p_buffers + i_loop * i_buffer_size;
242    
243         p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size;
244     }
245
246     /* initialize reference counters */
247     memset( p_netlist->pi_refcount, 0, i_nb_iovec *sizeof(int) );
248    
249     /* vlc_mutex_init */
250     vlc_mutex_init (&p_netlist->lock);
251     
252     /* initialize indexes */
253     p_netlist->i_iovec_start = 0;
254     p_netlist->i_iovec_end = i_nb_iovec - 1;
255
256     p_netlist->i_data_start = 0;
257     p_netlist->i_data_end = i_nb_data - 1;
258
259     p_netlist->i_pes_start = 0;
260     p_netlist->i_pes_end = i_nb_pes - 1;
261
262     /* we give (nb - 1) to use & instead of %
263      * if you really need nb you have to add 1 */
264     p_netlist->i_nb_iovec = i_nb_iovec - 1;
265     p_netlist->i_nb_data = i_nb_data - 1;
266     p_netlist->i_nb_pes = i_nb_pes - 1;
267     p_netlist->i_buffer_size = i_buffer_size;
268
269     return 0; /* Everything went all right */
270 }
271
272 /*****************************************************************************
273  * input_NetlistGetiovec: returns an iovec pointer for a readv() operation
274  *****************************************************************************
275  * We return an iovec vector, so that readv can read many packets at a time.
276  * pp_data will be set to direct to the fifo pointer in DVDMviovec, which
277  * will allow us to get the corresponding data_packet.
278  *****************************************************************************/
279 struct iovec * input_NetlistGetiovec( void * p_method_data )
280 {
281     netlist_t *     p_netlist;
282
283     /* cast */
284     p_netlist = (netlist_t *)p_method_data;
285     
286     /* check that we have enough free iovec */
287     if( (
288      (p_netlist->i_iovec_end - p_netlist->i_iovec_start)
289         & p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
290     {
291         intf_WarnMsg( 4, "input info: waiting for free iovec" );
292         msleep( INPUT_IDLE_SLEEP );
293
294         while( (
295          (p_netlist->i_iovec_end - p_netlist->i_iovec_start)
296             & p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
297         {
298             msleep( INPUT_IDLE_SLEEP );
299         }
300
301         intf_WarnMsg( 4, "input info: found free iovec" );
302     }
303
304     if( (
305      (p_netlist->i_data_end - p_netlist->i_data_start)
306         & p_netlist->i_nb_data ) < p_netlist->i_read_once )
307     {
308         intf_WarnMsg( 4, "input info: waiting for free data packet" );
309         msleep( INPUT_IDLE_SLEEP );
310
311         while( (
312          (p_netlist->i_data_end - p_netlist->i_data_start)
313             & p_netlist->i_nb_data ) < p_netlist->i_read_once )
314         {
315             msleep( INPUT_IDLE_SLEEP );
316         }
317
318         intf_WarnMsg( 4, "input info: found free data packet" );
319     }
320
321     /* readv only takes contiguous buffers 
322      * so, as a solution, we chose to have a FIFO a bit longer
323      * than i_nb_data, and copy the begining of the FIFO to its end
324      * if the readv needs to go after the end */
325     if( p_netlist->i_nb_iovec - p_netlist->i_iovec_start + 1 <
326                                                     p_netlist->i_read_once )
327     {
328         memcpy( &p_netlist->p_free_iovec[p_netlist->i_nb_iovec + 1], 
329                 p_netlist->p_free_iovec, 
330                 (p_netlist->i_read_once -
331                     (p_netlist->i_nb_iovec + 1 - p_netlist->i_iovec_start))
332                     * sizeof(struct iovec)
333               );
334
335     }
336
337     return p_netlist->p_free_iovec + p_netlist->i_iovec_start;
338
339 }
340
341 /*****************************************************************************
342  * input_NetlistMviovec: move the iovec pointer by one after a readv()
343  *  operation and gives a data_packet corresponding to iovec in p_data
344  *****************************************************************************/
345 void input_NetlistMviovec( void * p_method_data, int i_nb_iovec,
346                            struct data_packet_s ** pp_data )
347 {
348     netlist_t *         p_netlist;
349     unsigned int        i_loop = 0;
350
351     /* cast */
352     p_netlist = (netlist_t *)p_method_data;
353     
354     /* lock */
355     vlc_mutex_lock( &p_netlist->lock );
356
357     /* Fills a table of pointers to packets associated with the io_vec's */
358     while( i_loop < i_nb_iovec )
359     {
360         pp_data[i_loop] = p_netlist->pp_free_data[p_netlist->i_data_start];
361         
362         pp_data[i_loop]->p_buffer =
363                     p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
364         
365         pp_data[i_loop]->p_payload_start = pp_data[i_loop]->p_buffer;
366
367         pp_data[i_loop]->p_payload_end =
368                   pp_data[i_loop]->p_buffer + p_netlist->i_buffer_size;
369
370         pp_data[i_loop]->p_next = NULL;
371         pp_data[i_loop]->b_discard_payload = 0;
372
373         pp_data[i_loop]->pi_refcount = p_netlist->pi_refcount +
374                                        p_netlist->i_iovec_start;
375         if( (*pp_data[i_loop]->pi_refcount) != 0)
376         {
377             intf_ErrMsg( "netlist error: refcount should be 0 (%d)",
378                   (*pp_data[i_loop]->pi_refcount) );
379         }
380         (*pp_data[i_loop]->pi_refcount) = 1;
381
382         p_netlist->i_iovec_start ++;
383         p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
384
385         p_netlist->i_data_start ++;
386         p_netlist->i_data_start &= p_netlist->i_nb_data;
387
388         i_loop ++;
389     }
390
391     /* unlock */
392     vlc_mutex_unlock( &p_netlist->lock );
393     
394 }
395
396 /*****************************************************************************
397  * input_NetlistNewPtr: returns a free data_packet_t
398  * Gives a pointer ; its fields need to be initialized
399  *****************************************************************************/
400 struct data_packet_s * input_NetlistNewPtr( void * p_method_data )
401 {    
402     netlist_t *             p_netlist; 
403     struct data_packet_s *  p_return;
404     
405     /* cast */
406     p_netlist = (netlist_t *)p_method_data; 
407
408     /* lock */
409     vlc_mutex_lock ( &p_netlist->lock );
410         
411     /* check */
412     if ( p_netlist->i_data_start == p_netlist->i_data_end )
413     {
414         intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
415         return ( NULL );
416     }
417     
418     p_return = (p_netlist->pp_free_data[p_netlist->i_data_start]);
419
420     p_netlist->i_data_start++;
421     p_netlist->i_data_start &= p_netlist->i_nb_data;
422
423     p_return->p_payload_start = p_return->p_buffer;
424
425     p_return->p_payload_end =
426               p_return->p_buffer + p_netlist->i_buffer_size;
427
428     p_return->p_next = NULL;
429     p_return->b_discard_payload = 0;
430
431     /* unlock */
432     vlc_mutex_unlock (&p_netlist->lock);
433
434     return ( p_return );
435 }
436
437 /*****************************************************************************
438  * input_NetlistNewPacket: returns a free data_packet_t, and takes
439  * a corresponding storage iovec.
440  *****************************************************************************/
441 struct data_packet_s * input_NetlistNewPacket( void * p_method_data,
442                                                size_t i_buffer_size )
443 {
444     netlist_t *             p_netlist;
445     struct data_packet_s *  p_packet;
446
447     /* cast */
448     p_netlist = (netlist_t *)p_method_data;
449
450 #ifdef DEBUG
451     if( i_buffer_size > p_netlist->i_buffer_size )
452     {
453         /* This should not happen */
454         intf_ErrMsg( "Netlist packet too small !" );
455         return NULL;
456     }
457 #endif
458     
459     /* lock */
460     vlc_mutex_lock( &p_netlist->lock );
461
462      /* check */
463     if ( p_netlist->i_iovec_start == p_netlist->i_iovec_end )
464     {
465         intf_ErrMsg("Empty io_vec FIFO in netlist. Unable to allocate memory");
466         return ( NULL );
467     }
468
469     if ( p_netlist->i_data_start == p_netlist->i_data_end )
470     {
471         intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
472         return ( NULL );
473     }
474
475
476     /* Gives an io_vec and associated data */
477     p_packet = p_netlist->pp_free_data[p_netlist->i_data_start];
478         
479     p_packet->p_buffer =
480               p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
481         
482     p_packet->p_payload_start = p_packet->p_buffer;
483         
484     p_packet->p_payload_end =
485               p_packet->p_buffer + i_buffer_size;
486
487     p_packet->p_next = NULL;
488     p_packet->b_discard_payload = 0;
489
490     p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start;
491     if( (*p_packet->pi_refcount) != 0)
492     {
493         intf_ErrMsg( "netlist error: refcount should be 0 (%d)",
494                      (*p_packet->pi_refcount) );
495     }
496     (*p_packet->pi_refcount) = 1;
497
498     p_netlist->i_iovec_start ++;
499     p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
500
501     p_netlist->i_data_start ++;
502     p_netlist->i_data_start &= p_netlist->i_nb_data;
503
504     /* unlock */
505     vlc_mutex_unlock( &p_netlist->lock );
506
507     return p_packet;
508 }
509
510 /*****************************************************************************
511  * input_NetlistNewPES: returns a free pes_packet_t
512  *****************************************************************************/
513 struct pes_packet_s * input_NetlistNewPES( void * p_method_data )
514 {
515     netlist_t *         p_netlist;
516     pes_packet_t *      p_return;
517     
518     /* cast */ 
519     p_netlist = (netlist_t *)p_method_data;
520     
521     /* lock */
522     vlc_mutex_lock ( &p_netlist->lock );
523     
524     /* check */
525     if ( p_netlist->i_pes_start == p_netlist->i_pes_end )
526     {
527         intf_ErrMsg("Empty PES FIFO in netlist - Unable to allocate memory");
528         return ( NULL );
529     }
530
531     /* allocate */
532     p_return = p_netlist->pp_free_pes[p_netlist->i_pes_start];
533     p_netlist->i_pes_start++;
534     p_netlist->i_pes_start &= p_netlist->i_nb_pes; 
535    
536     /* unlock */
537     vlc_mutex_unlock (&p_netlist->lock);
538     
539     /* initialize PES */
540     p_return->b_data_alignment = 0;
541     p_return->b_discontinuity = 0; 
542     p_return->i_pts = 0;
543     p_return->i_dts = 0;
544     p_return->i_pes_size = 0;
545     p_return->p_first = NULL;
546
547     return ( p_return );
548 }
549
550 /*****************************************************************************
551  * input_NetlistDeletePacket: puts a data_packet_t back into the netlist
552  *****************************************************************************/
553 void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data )
554 {
555     netlist_t * p_netlist;
556     
557     /* cast */
558     p_netlist = (netlist_t *) p_method_data;
559
560     /* lock */
561     vlc_mutex_lock ( &p_netlist->lock );
562
563    /* Delete data_packet */
564     p_netlist->i_data_end ++;
565     p_netlist->i_data_end &= p_netlist->i_nb_data;
566     
567     p_data->p_payload_start = p_data->p_buffer;
568     p_data->p_payload_end = p_data->p_buffer + p_netlist->i_buffer_size;
569         
570     p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
571
572     p_data->p_next = NULL;
573     p_data->b_discard_payload = 0;
574
575     /* Update reference counter */
576     (*p_data->pi_refcount)--;
577
578     if( (*p_data->pi_refcount) == 0 )
579     {
580         (*p_data->pi_refcount) = 0;
581         p_netlist->i_iovec_end++;
582         p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
583         p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
584                                                             p_data->p_buffer;
585     }
586     else if( (*p_data->pi_refcount) < 0 )
587     {
588         intf_ErrMsg( "netlist error: refcount can't be negative (%d)",
589                      (*p_data->pi_refcount) );
590     }
591  
592     /* unlock */
593     vlc_mutex_unlock (&p_netlist->lock);
594 }
595
596 /*****************************************************************************
597  * input_NetlistDeletePES: puts a pes_packet_t back into the netlist
598  *****************************************************************************/
599 void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes )
600 {
601     netlist_t *         p_netlist; 
602     data_packet_t *     p_current_packet;
603     data_packet_t *     p_next_packet;
604     
605     /* cast */
606     p_netlist = (netlist_t *)p_method_data;
607
608     /* lock */
609     vlc_mutex_lock ( &p_netlist->lock );
610
611     /* delete free  p_pes->p_first, p_next ... */
612     p_current_packet = p_pes->p_first;
613     while ( p_current_packet != NULL )
614     {
615         /* copy of NetListDeletePacket, duplicate code avoid many locks */
616
617         p_netlist->i_data_end ++;
618         p_netlist->i_data_end &= p_netlist->i_nb_data;
619
620         /* re initialize */
621         p_current_packet->p_payload_start = p_current_packet->p_buffer;
622         p_current_packet->p_payload_end = p_current_packet->p_buffer
623             + p_netlist->i_buffer_size;
624         
625         p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet;
626
627         /* Update reference counter */
628         (*p_current_packet->pi_refcount)--;
629
630         if( (*p_current_packet->pi_refcount) == 0 )
631         {
632             (*p_current_packet->pi_refcount) = 0;
633             p_netlist->i_iovec_end++;
634             p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
635             p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
636                     p_current_packet->p_buffer;
637         }
638         else if( (*p_current_packet->pi_refcount) < 0 )
639         {
640             intf_ErrMsg( "netlist error: refcount can't be negative (%d)",
641                          (*p_current_packet->pi_refcount) );
642         }
643     
644         p_next_packet = p_current_packet->p_next;
645         p_current_packet->p_next = NULL;
646         p_current_packet->b_discard_payload = 0;
647         p_current_packet = p_next_packet;
648     }
649  
650     /* delete our current PES packet */
651     p_netlist->i_pes_end ++;
652     p_netlist->i_pes_end &= p_netlist->i_nb_pes;
653     p_netlist->pp_free_pes[p_netlist->i_pes_end] = p_pes;
654     
655     /* unlock */
656     vlc_mutex_unlock (&p_netlist->lock);
657
658 }
659
660 /*****************************************************************************
661  * input_NetlistEnd: frees all allocated structures
662  *****************************************************************************/
663 void input_NetlistEnd( input_thread_t * p_input )
664 {
665     netlist_t * p_netlist;
666
667     /* cast */
668     p_netlist = ( netlist_t * ) p_input->p_method_data;
669
670     /* destroy the mutex lock */
671     vlc_mutex_destroy( &p_netlist->lock );
672     
673     /* free the FIFO, the buffer, and the netlist structure */
674     free( p_netlist->pi_refcount );
675     free( p_netlist->p_free_iovec );
676     free( p_netlist->pp_free_pes );
677     free( p_netlist->pp_free_data );
678     free( p_netlist->p_pes );
679     free( p_netlist->p_data );
680     free( p_netlist->p_buffers );
681
682     /* free the netlist */
683     free( p_netlist );
684 }