* rtp.c: RTP access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: rtp.c,v 1.2 2002/09/30 11:05:34 sam Exp $
+ * $Id: rtp.c,v 1.6 2002/11/13 20:23:21 fenrir Exp $
*
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Authors: Tristan Leteurtre <tooney@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
# include <io.h>
#endif
+#ifdef WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# ifndef IN_MULTICAST
+# define IN_MULTICAST(a) IN_CLASSD(a)
+# endif
+#else
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
#include "network.h"
#define RTP_HEADER_LEN 12
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
-static int RTPNetworkRead( input_thread_t *, byte_t *, size_t );
+static void Close ( vlc_object_t * );
+static ssize_t RTPNetworkRead( input_thread_t *, byte_t *, size_t );
+static ssize_t Read ( input_thread_t *, byte_t *, size_t );
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
add_shortcut( "rtpstream" );
add_shortcut( "rtp4" );
add_shortcut( "rtp6" );
- set_callbacks( Open, __input_FDNetworkClose );
+ set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
p_access_data->i_handle = socket_desc.i_handle;
p_input->i_mtu = socket_desc.i_mtu;
-
- p_input->psz_demux = "ts";
+ if( !p_input->psz_demux || !*p_input->psz_demux )
+ {
+ p_input->psz_demux = "ts";
+ }
return( 0 );
}
+/*****************************************************************************
+ * Close: free unused data structures
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
+
+ msg_Info( p_input, "closing RTP target `%s'", p_input->psz_source );
+
+#ifdef UNDER_CE
+ CloseHandle( (HANDLE)p_access_data->i_handle );
+#elif defined( WIN32 )
+ closesocket( p_access_data->i_handle );
+#else
+ close( p_access_data->i_handle );
+#endif
+
+ free( p_access_data );
+}
+
/*****************************************************************************
* RTPNetworkRead : Read for the network, and parses the RTP header
*****************************************************************************/
-static int RTPNetworkRead( input_thread_t * p_input, byte_t * p_buffer,
+static ssize_t RTPNetworkRead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len )
{
int i_rtp_version;
int i_CSRC_count;
int i_payload_type;
- int i;
-
- byte_t p_tmp_buffer[1500];
-
- // Get the Raw data from the socket
- // We first assume that RTP header size is the classic RTP_HEADER_LEN
- ssize_t i_ret = input_FDNetworkRead(p_input, p_tmp_buffer,
- i_len + RTP_HEADER_LEN);
+ byte_t * p_tmp_buffer = alloca( p_input->i_mtu );
+
+ /* Get the raw data from the socket.
+ * We first assume that RTP header size is the classic RTP_HEADER_LEN. */
+ ssize_t i_ret = Read( p_input, p_tmp_buffer, p_input->i_mtu );
+
if (!i_ret) return 0;
-
- // Parse the header and make some verifications
- // See RFC 1889 & RFC 2250
+
+ /* Parse the header and make some verifications.
+ * See RFC 1889 & RFC 2250. */
i_rtp_version = ( p_tmp_buffer[0] & 0xC0 ) >> 6;
i_CSRC_count = ( p_tmp_buffer[0] & 0x0F );
msg_Dbg( p_input, "RTP version is %u, should be 2", i_rtp_version );
if ( i_payload_type != 33 )
- msg_Dbg( p_input, "RTP payload type is %u, only 33 (Mpeg2-TS) \
-is supported", i_payload_type );
-
- // If both bytes are wrong, maybe a synchro error occurred...
- if (( i_rtp_version != 2 ) && ( i_payload_type != 0x33 ))
- {
- msg_Dbg( p_input, "Too many RTP errors, trying to re-synchronize" );
+ msg_Dbg( p_input, "RTP payload type is %u, only 33 (Mpeg2-TS) " \
+ "is supported", i_payload_type );
- //Trying to re-synchronize
- for ( i=0 ; (i<i_len) ||
- ((( p_tmp_buffer[0] & 0xC0 ) >> 6 == 2 )
- && ( p_tmp_buffer[1] & 0x7F ) >> 6 == 0x33 ) ; i++);
-
- if (i!=i_len)
- {
- input_FDNetworkRead(p_input, p_tmp_buffer,i);
- return 0;
- }
-
- }
+ /* Return the packet without the RTP header. */
+ i_ret -= ( RTP_HEADER_LEN + 4 * i_CSRC_count );
-/*
- // if i_CSRC_count != 0, the header is in fact longer than RTP_HEADER_LEN
- // so we have to read some extra bytes
- // This case is supposed to be very rare (vls does not handle that),
- // so in practical this second input_FDNetworkRead is never done...
- if (i_CSRC_count)
- { i_ret += input_FDNetworkRead(p_input,
- p_tmp_buffer + i_len + RTP_HEADER_LEN,
- 4 * i_CSRC_count );
+ if ( i_ret > i_len )
+ {
+ /* This should NOT happen. */
+ msg_Warn( p_input, "RTP input trashing %d bytes", i_ret - i_len );
+ i_ret = i_len;
}
-*/
-
- // Return the packet without the RTP header
- i_ret -= ( RTP_HEADER_LEN + 4 * i_CSRC_count );
p_input->p_vlc->pf_memcpy( p_buffer,
p_tmp_buffer + RTP_HEADER_LEN + 4 * i_CSRC_count,
i_ret );
- return (i_ret);
+ return i_ret;
}
+
+/*****************************************************************************
+ * Read: read on a file descriptor, checking b_die periodically
+ *****************************************************************************/
+static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
+{
+#ifdef UNDER_CE
+ return -1;
+
+#else
+ input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
+ struct timeval timeout;
+ fd_set fds;
+ int i_ret;
+
+ /* Initialize file descriptor set */
+ FD_ZERO( &fds );
+ FD_SET( p_access_data->i_handle, &fds );
+
+ /* We'll wait 0.5 second if nothing happens */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000;
+
+ /* Find if some data is available */
+ i_ret = select( p_access_data->i_handle + 1, &fds,
+ NULL, NULL, &timeout );
+
+ if( i_ret == -1 && errno != EINTR )
+ {
+ msg_Err( p_input, "network select error (%s)", strerror(errno) );
+ }
+ else if( i_ret > 0 )
+ {
+ ssize_t i_recv = recv( p_access_data->i_handle, p_buffer, i_len, 0 );
+
+ if( i_recv > 0 )
+ {
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.p_selected_area->i_tell += i_recv;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+ if( i_recv < 0 )
+ {
+ msg_Err( p_input, "recv failed (%s)", strerror(errno) );
+ }
+
+ return i_recv;
+ }
+
+ return 0;
+
+#endif
+}
+