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