1 /*****************************************************************************
2 * input_ext-plugins.c: useful functions for access and demux plug-ins
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: input_ext-plugins.c,v 1.5 2002/04/02 22:46:25 massiot Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <sys/types.h>
35 #include <videolan/vlc.h>
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
43 #elif defined( _MSC_VER ) && defined( _WIN32 )
48 # include <winsock2.h>
49 # include <ws2tcpip.h>
50 #elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
51 # include <netdb.h> /* hostent ... */
52 # include <sys/socket.h>
53 # include <netinet/in.h>
54 # ifdef HAVE_ARPA_INET_H
55 # include <arpa/inet.h> /* inet_ntoa(), inet_aton() */
60 # include <winsock2.h>
61 # include <ws2tcpip.h>
62 #elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
63 # include <netdb.h> /* hostent ... */
64 # include <sys/socket.h>
65 # include <netinet/in.h>
66 # ifdef HAVE_ARPA_INET_H
67 # include <arpa/inet.h> /* inet_ntoa(), inet_aton() */
73 #include "stream_control.h"
74 #include "input_ext-intf.h"
75 #include "input_ext-dec.h"
76 #include "input_ext-plugins.h"
80 * Buffers management : internal functions
82 * All functions are static, but exported versions with mutex protection
83 * start with input_*. Not all of these exported functions are actually used,
84 * but they are included here for completeness.
87 #define BUFFERS_CACHE_SIZE 500
88 #define DATA_CACHE_SIZE 1000
89 #define PES_CACHE_SIZE 1000
91 /*****************************************************************************
92 * data_buffer_t: shared data type
93 *****************************************************************************/
94 typedef struct data_buffer_s
96 struct data_buffer_s * p_next;
98 /* number of data packets this buffer is referenced from - when it falls
99 * down to 0, the buffer is freed */
102 /* size of the current buffer (starting right after this byte) */
106 /*****************************************************************************
107 * input_buffers_t: defines a LIFO per data type to keep
108 *****************************************************************************/
109 #define PACKETS_LIFO( TYPE, NAME ) \
113 unsigned int i_depth; \
116 typedef struct input_buffers_s
119 PACKETS_LIFO( pes_packet_t, pes )
120 PACKETS_LIFO( data_packet_t, data )
121 PACKETS_LIFO( data_buffer_t, buffers )
126 /*****************************************************************************
127 * input_BuffersInit: initialize the cache structures, return a pointer to it
128 *****************************************************************************/
129 void * input_BuffersInit( void )
131 input_buffers_t * p_buffers = malloc( sizeof( input_buffers_t ) );
133 if( p_buffers == NULL )
138 memset( p_buffers, 0, sizeof( input_buffers_t ) );
139 vlc_mutex_init( &p_buffers->lock );
144 /*****************************************************************************
145 * input_BuffersEnd: free all cached structures
146 *****************************************************************************/
147 #define BUFFERS_END_PACKETS_LOOP \
148 while( p_packet != NULL ) \
150 p_next = p_packet->p_next; \
155 void input_BuffersEnd( input_buffers_t * p_buffers )
157 if( p_buffers != NULL )
159 if( p_main->b_stats )
161 intf_StatMsg( "input buffers stats: pes: %d packets",
162 p_buffers->pes.i_depth );
163 intf_StatMsg( "input buffers stats: data: %d packets",
164 p_buffers->data.i_depth );
165 intf_StatMsg( "input buffers stats: buffers: %d packets",
166 p_buffers->buffers.i_depth );
171 pes_packet_t * p_next, * p_packet = p_buffers->pes.p_stack;
172 BUFFERS_END_PACKETS_LOOP;
176 /* Free data packets */
177 data_packet_t * p_next, * p_packet = p_buffers->data.p_stack;
178 BUFFERS_END_PACKETS_LOOP;
183 data_buffer_t * p_next, * p_buf = p_buffers->buffers.p_stack;
184 while( p_buf != NULL )
186 p_next = p_buf->p_next;
187 p_buffers->i_allocated -= p_buf->i_size;
193 if( p_buffers->i_allocated )
195 intf_ErrMsg( "input buffers error: %d bytes have not been"
196 " freed, expect memory leak",
197 p_buffers->i_allocated );
200 vlc_mutex_destroy( &p_buffers->lock );
205 /*****************************************************************************
206 * input_NewBuffer: return a pointer to a data buffer of the appropriate size
207 *****************************************************************************/
208 static __inline__ data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
211 data_buffer_t * p_buf;
214 if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION )
216 intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)",
217 p_buffers->i_allocated );
221 if( p_buffers->buffers.p_stack != NULL )
223 /* Take the buffer from the cache */
224 p_buf = p_buffers->buffers.p_stack;
225 p_buffers->buffers.p_stack = p_buf->p_next;
226 p_buffers->buffers.i_depth--;
228 /* Reallocate the packet if it is too small or too large */
229 if( p_buf->i_size < i_size || p_buf->i_size > 3 * i_size )
231 p_buffers->i_allocated -= p_buf->i_size;
233 p_buf = malloc( sizeof(input_buffers_t) + i_size );
236 intf_ErrMsg( "Out of memory" );
239 p_buf->i_size = i_size;
240 p_buffers->i_allocated += i_size;
245 /* Allocate a new buffer */
246 p_buf = malloc( sizeof(input_buffers_t) + i_size );
249 intf_ErrMsg( "Out of memory" );
252 p_buf->i_size = i_size;
253 p_buffers->i_allocated += i_size;
256 /* Initialize data */
257 p_buf->p_next = NULL;
258 p_buf->i_refcount = 0;
263 data_buffer_t * input_NewBuffer( input_buffers_t * p_buffers, size_t i_size )
265 data_buffer_t * p_buf;
267 vlc_mutex_lock( &p_buffers->lock );
268 p_buf = NewBuffer( p_buffers, i_size );
269 vlc_mutex_unlock( &p_buffers->lock );
274 /*****************************************************************************
275 * input_ReleaseBuffer: put a buffer back into the cache
276 *****************************************************************************/
277 static __inline__ void ReleaseBuffer( input_buffers_t * p_buffers,
278 data_buffer_t * p_buf )
280 /* Decrement refcount */
281 if( --p_buf->i_refcount > 0 )
286 if( p_buffers->buffers.i_depth < BUFFERS_CACHE_SIZE )
288 /* Cache not full : store the buffer in it */
289 p_buf->p_next = p_buffers->buffers.p_stack;
290 p_buffers->buffers.p_stack = p_buf;
291 p_buffers->buffers.i_depth++;
295 p_buffers->i_allocated -= p_buf->i_size;
300 void input_ReleaseBuffer( input_buffers_t * p_buffers, data_buffer_t * p_buf )
302 vlc_mutex_lock( &p_buffers->lock );
303 ReleaseBuffer( p_buffers, p_buf );
304 vlc_mutex_unlock( &p_buffers->lock );
307 /*****************************************************************************
308 * input_ShareBuffer: allocate a data_packet_t pointing to a given buffer
309 *****************************************************************************/
310 static __inline__ data_packet_t * ShareBuffer( input_buffers_t * p_buffers,
311 data_buffer_t * p_buf )
313 data_packet_t * p_data;
315 if( p_buffers->data.p_stack != NULL )
317 /* Take the packet from the cache */
318 p_data = p_buffers->data.p_stack;
319 p_buffers->data.p_stack = p_data->p_next;
320 p_buffers->data.i_depth--;
324 /* Allocate a new packet */
325 p_data = malloc( sizeof(data_packet_t) );
328 intf_ErrMsg( "Out of memory" );
333 p_data->p_buffer = p_buf;
334 p_data->p_next = NULL;
335 p_data->b_discard_payload = 0;
336 p_data->p_payload_start = p_data->p_demux_start
337 = (byte_t *)p_buf + sizeof(input_buffers_t);
338 p_data->p_payload_end = p_data->p_demux_start + p_buf->i_size;
344 data_packet_t * input_ShareBuffer( input_buffers_t * p_buffers,
345 data_buffer_t * p_buf )
347 data_packet_t * p_data;
349 vlc_mutex_lock( &p_buffers->lock );
350 p_data = ShareBuffer( p_buffers, p_buf );
351 vlc_mutex_unlock( &p_buffers->lock );
356 /*****************************************************************************
357 * input_NewPacket: allocate a packet along with a buffer
358 *****************************************************************************/
359 static __inline__ data_packet_t * NewPacket( input_buffers_t * p_buffers,
362 data_buffer_t * p_buf = NewBuffer( p_buffers, i_size );
363 data_packet_t * p_data;
370 p_data = ShareBuffer( p_buffers, p_buf );
373 ReleaseBuffer( p_buffers, p_buf );
378 data_packet_t * input_NewPacket( input_buffers_t * p_buffers, size_t i_size )
380 data_packet_t * p_data;
382 vlc_mutex_lock( &p_buffers->lock );
383 p_data = NewPacket( p_buffers, i_size );
384 vlc_mutex_unlock( &p_buffers->lock );
389 /*****************************************************************************
390 * input_DeletePacket: deallocate a packet and its buffers
391 *****************************************************************************/
392 static __inline__ void DeletePacket( input_buffers_t * p_buffers,
393 data_packet_t * p_data )
395 while( p_data != NULL )
397 data_packet_t * p_next = p_data->p_next;
399 ReleaseBuffer( p_buffers, p_data->p_buffer );
401 if( p_buffers->data.i_depth < DATA_CACHE_SIZE )
403 /* Cache not full : store the packet in it */
404 p_data->p_next = p_buffers->data.p_stack;
405 p_buffers->data.p_stack = p_data;
406 p_buffers->data.i_depth++;
417 void input_DeletePacket( input_buffers_t * p_buffers, data_packet_t * p_data )
419 vlc_mutex_lock( &p_buffers->lock );
420 DeletePacket( p_buffers, p_data );
421 vlc_mutex_unlock( &p_buffers->lock );
424 /*****************************************************************************
425 * input_NewPES: return a pointer to a new PES packet
426 *****************************************************************************/
427 static __inline__ pes_packet_t * NewPES( input_buffers_t * p_buffers )
429 pes_packet_t * p_pes;
431 if( p_buffers->pes.p_stack != NULL )
433 /* Take the packet from the cache */
434 p_pes = p_buffers->pes.p_stack;
435 p_buffers->pes.p_stack = p_pes->p_next;
436 p_buffers->pes.i_depth--;
440 /* Allocate a new packet */
441 p_pes = malloc( sizeof(pes_packet_t) );
444 intf_ErrMsg( "Out of memory" );
449 p_pes->p_next = NULL;
450 p_pes->b_data_alignment = p_pes->b_discontinuity =
451 p_pes->i_pts = p_pes->i_dts = 0;
452 p_pes->p_first = p_pes->p_last = NULL;
453 p_pes->i_pes_size = 0;
454 p_pes->i_nb_data = 0;
459 pes_packet_t * input_NewPES( input_buffers_t * p_buffers )
461 pes_packet_t * p_pes;
463 vlc_mutex_lock( &p_buffers->lock );
464 p_pes = NewPES( p_buffers );
465 vlc_mutex_unlock( &p_buffers->lock );
470 /*****************************************************************************
471 * input_DeletePES: put a pes and all data packets and all buffers back into
473 *****************************************************************************/
474 static __inline__ void DeletePES( input_buffers_t * p_buffers,
475 pes_packet_t * p_pes )
477 while( p_pes != NULL )
479 pes_packet_t * p_next = p_pes->p_next;
481 /* Delete all data packets */
482 if( p_pes->p_first != NULL )
484 DeletePacket( p_buffers, p_pes->p_first );
487 if( p_buffers->pes.i_depth < PES_CACHE_SIZE )
489 /* Cache not full : store the packet in it */
490 p_pes->p_next = p_buffers->pes.p_stack;
491 p_buffers->pes.p_stack = p_pes;
492 p_buffers->pes.i_depth++;
503 void input_DeletePES( input_buffers_t * p_buffers, pes_packet_t * p_pes )
505 vlc_mutex_lock( &p_buffers->lock );
506 DeletePES( p_buffers, p_pes );
507 vlc_mutex_unlock( &p_buffers->lock );
512 * Buffers management : external functions
514 * These functions make the glu between the access plug-in (pf_read) and
515 * the demux plug-in (pf_demux). We fill in a large buffer (approx. 10s kB)
516 * with a call to pf_read, then allow the demux plug-in to have a peep at
517 * it (input_Peek), and to split it in data_packet_t (input_SplitBuffer).
519 /*****************************************************************************
520 * input_FillBuffer: fill in p_data_buffer with data from pf_read
521 *****************************************************************************/
522 ssize_t input_FillBuffer( input_thread_t * p_input )
524 ptrdiff_t i_remains = p_input->p_last_data - p_input->p_current_data;
525 data_buffer_t * p_buf;
528 vlc_mutex_lock( &p_input->p_method_data->lock );
530 p_buf = NewBuffer( p_input->p_method_data,
531 i_remains + p_input->i_bufsize );
536 p_buf->i_refcount = 1;
538 if( p_input->p_data_buffer != NULL )
542 FAST_MEMCPY( (byte_t *)p_buf + sizeof(data_buffer_t),
543 p_input->p_current_data, (size_t)i_remains );
545 ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
548 /* Do not hold the lock during pf_read (blocking call). */
549 vlc_mutex_unlock( &p_input->p_method_data->lock );
551 i_ret = p_input->pf_read( p_input,
552 (byte_t *)p_buf + sizeof(data_buffer_t)
554 p_input->i_bufsize );
556 if( i_ret < 0 ) i_ret = 0;
557 p_input->p_data_buffer = p_buf;
558 p_input->p_current_data = (byte_t *)p_buf + sizeof(data_buffer_t);
559 p_input->p_last_data = p_input->p_current_data + i_remains + i_ret;
561 return( (ssize_t)i_remains + i_ret );
564 /*****************************************************************************
565 * input_Peek: give a pointer to the next available bytes in the buffer
566 * (min. i_size bytes)
567 * Returns the number of bytes read, or -1 in case of error
568 *****************************************************************************/
569 ssize_t input_Peek( input_thread_t * p_input, byte_t ** pp_byte, size_t i_size )
571 if( p_input->p_last_data - p_input->p_current_data < i_size )
573 /* Go to the next buffer */
574 ssize_t i_ret = input_FillBuffer( p_input );
580 else if( i_ret < i_size )
585 *pp_byte = p_input->p_current_data;
589 /*****************************************************************************
590 * input_SplitBuffer: give a pointer to a data packet containing i_size bytes
591 * Returns the number of bytes read, or -1 in case of error
592 *****************************************************************************/
593 ssize_t input_SplitBuffer( input_thread_t * p_input,
594 data_packet_t ** pp_data, size_t i_size )
596 if( p_input->p_last_data - p_input->p_current_data < i_size )
598 /* Go to the next buffer */
599 ssize_t i_ret = input_FillBuffer( p_input );
605 else if( i_ret < i_size )
611 *pp_data = input_ShareBuffer( p_input->p_method_data,
612 p_input->p_data_buffer );
614 (*pp_data)->p_demux_start = (*pp_data)->p_payload_start
615 = p_input->p_current_data;
616 (*pp_data)->p_payload_end = (*pp_data)->p_demux_start + i_size;
618 p_input->p_current_data += i_size;
623 /*****************************************************************************
624 * input_AccessInit: initialize access plug-in wrapper structures
625 *****************************************************************************/
626 int input_AccessInit( input_thread_t * p_input )
628 p_input->p_method_data = input_BuffersInit();
629 if( p_input->p_method_data == NULL ) return( -1 );
630 p_input->p_data_buffer = NULL;
631 p_input->p_current_data = NULL;
632 p_input->p_last_data = NULL;
636 /*****************************************************************************
637 * input_AccessReinit: reinit structures after a random seek
638 *****************************************************************************/
639 void input_AccessReinit( input_thread_t * p_input )
641 if( p_input->p_data_buffer != NULL )
643 ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
645 p_input->p_data_buffer = NULL;
646 p_input->p_current_data = NULL;
647 p_input->p_last_data = NULL;
650 /*****************************************************************************
651 * input_AccessEnd: free access plug-in wrapper structures
652 *****************************************************************************/
653 void input_AccessEnd( input_thread_t * p_input )
655 if( p_input->p_data_buffer != NULL )
657 ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
660 input_BuffersEnd( p_input->p_method_data );
665 * Optional file descriptor management functions, for use by access plug-ins
666 * base on file descriptors (file, udp, http...).
669 /*****************************************************************************
670 * input_FDClose: close the target
671 *****************************************************************************/
672 void input_FDClose( input_thread_t * p_input )
674 input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
676 intf_WarnMsg( 2, "input: closing `%s/%s:%s'",
677 p_input->psz_access, p_input->psz_demux, p_input->psz_name );
679 close( p_access_data->i_handle );
680 free( p_access_data );
683 /*****************************************************************************
684 * input_FDRead: standard read on a file descriptor.
685 *****************************************************************************/
686 ssize_t input_FDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
688 input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
690 ssize_t i_ret = read( p_access_data->i_handle, p_buffer, i_len );
694 vlc_mutex_lock( &p_input->stream.stream_lock );
695 p_input->stream.p_selected_area->i_tell += i_ret;
696 vlc_mutex_unlock( &p_input->stream.stream_lock );
701 intf_ErrMsg( "input error: read() failed (%s)", strerror(errno) );
707 /*****************************************************************************
708 * NetworkSelect: Checks whether data is available on a file descriptor
709 *****************************************************************************/
710 static __inline__ int NetworkSelect( input_thread_t * p_input )
712 input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
713 struct timeval timeout;
717 /* Initialize file descriptor set */
719 FD_SET( p_access_data->i_handle, &fds );
721 /* We'll wait 0.5 second if nothing happens */
723 timeout.tv_usec = 500000;
725 /* Find if some data is available */
726 i_ret = select( p_access_data->i_handle + 1, &fds,
727 NULL, NULL, &timeout );
731 intf_ErrMsg( "input error: network select error (%s)", strerror(errno) );
737 /*****************************************************************************
738 * input_FDNetworkRead: read on a file descriptor, checking periodically
740 *****************************************************************************/
741 ssize_t input_FDNetworkRead( input_thread_t * p_input, byte_t * p_buffer,
744 if( NetworkSelect( p_input ) > 0 )
746 input_socket_t * p_access_data
747 = (input_socket_t *)p_input->p_access_data;
749 ssize_t i_ret = recv( p_access_data->i_handle, p_buffer, i_len, 0 );
753 vlc_mutex_lock( &p_input->stream.stream_lock );
754 p_input->stream.p_selected_area->i_tell += i_ret;
755 vlc_mutex_unlock( &p_input->stream.stream_lock );
760 intf_ErrMsg( "input error: recv() failed (%s)", strerror(errno) );
769 /*****************************************************************************
770 * input_FDSeek: seek to a specific location in a file
771 *****************************************************************************/
772 void input_FDSeek( input_thread_t * p_input, off_t i_pos )
774 input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
776 lseek( p_access_data->i_handle, i_pos, SEEK_SET );
778 vlc_mutex_lock( &p_input->stream.stream_lock );
779 p_input->stream.p_selected_area->i_tell = i_pos;
780 vlc_mutex_unlock( &p_input->stream.stream_lock );