]> git.sesse.net Git - vlc/blobdiff - modules/access/rtp.c
* fix and make better stream selection (if mms-maxbitrate unset, get the best
[vlc] / modules / access / rtp.c
index 9f3de26adac5f9a3d75d5f09bd85822100c3f4cb..621fed1897c11219ccfca4dc56741324ab11d3e4 100644 (file)
@@ -2,9 +2,9 @@
  * 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
  *****************************************************************************/
@@ -58,7 +76,7 @@ vlc_module_begin();
     add_shortcut( "rtpstream" );
     add_shortcut( "rtp4" );
     add_shortcut( "rtp6" );
-    set_callbacks( Open, __input_FDNetworkClose );
+    set_callbacks( Open, Close );
 vlc_module_end();
 
 /*****************************************************************************
@@ -250,34 +268,55 @@ static int Open( vlc_object_t *p_this )
 
     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 );
@@ -287,45 +326,77 @@ static int RTPNetworkRead( input_thread_t * p_input, byte_t * p_buffer,
         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
+}
+