[vlc-devel] [PATCH] realrtsp pause seek

Wang Bo silencewang at msn.com
Fri May 23 14:38:13 CEST 2008


---
 modules/access/rtsp/access.c |   92 ++++++++++++++++++++++++++++++++++++++---
 modules/access/rtsp/real.c   |   13 +++++-
 modules/access/rtsp/rtsp.c   |   54 ++++++++++++++++++++++++-
 3 files changed, 149 insertions(+), 10 deletions(-)

diff --git a/modules/access/rtsp/access.c b/modules/access/rtsp/access.c
index b8b42b1..3887650 100644
--- a/modules/access/rtsp/access.c
+++ b/modules/access/rtsp/access.c
@@ -79,6 +79,7 @@ struct access_sys_t
 
     int fd;
 
+    int64_t  i_seekto;
     block_t *p_header;
 };
 
@@ -120,6 +121,25 @@ static int RtspRead( void *p_userdata, uint8_t *p_buffer, int i_buffer )
     return net_Read( p_access, p_sys->fd, 0, p_buffer, i_buffer, true );
 }
 
+static int RtspReadAndSkip( void * p_userdata )
+{
+    access_t *p_access = (access_t *)p_userdata;
+    access_sys_t *p_sys = p_access->p_sys;
+    char buf[10240];
+    mtime_t time_wait = 500000;
+    int size, total=0;
+
+    /*msg_Dbg( p_access, "Try RtspReadAndSkip ");*/
+    do {
+        size = net_ReadNonBlock( p_access, p_sys->fd, 0, buf, 10240,  time_wait );
+        /*if ( size > 0 ) buf[size] = 0;
+                          msg_Dbg( p_access, "skip %d byte [0]%c [0] %d %s", size, buf[0], buf[0], buf);*/
+        total += size;
+    }while( size > 0 );
+
+    msg_Dbg( p_access, "RtspReadAndSkip skip %d bytes ", total);
+    return total;
+}
 static int RtspReadLine( void *p_userdata, uint8_t *p_buffer, int i_buffer )
 {
     access_t *p_access = (access_t *)p_userdata;
@@ -127,11 +147,19 @@ static int RtspReadLine( void *p_userdata, uint8_t *p_buffer, int i_buffer )
 
     char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, 0 );
 
-    //fprintf(stderr, "ReadLine: %s\n", psz);
-
-    if( psz ) strncpy( (char *)p_buffer, psz, i_buffer );
+    if ( psz )
+    {
+        if( strlen( psz ) > i_buffer - 1 )
+        {
+            msg_Warn( p_access, "read data exceed the buffer size , simple skip some datas!");
+            strncpy( (char *)p_buffer, psz + strlen(psz) - i_buffer + 10, i_buffer - 1 );
+        }
+        else
+            strncpy( (char *)p_buffer, psz, i_buffer - 1 );
+    }
     else *p_buffer = 0;
 
+    p_buffer[ i_buffer -1 ] = '\0';
     free( psz );
     return 0;
 }
@@ -179,6 +207,7 @@ static int Open( vlc_object_t *p_this )
     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
     p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) );
 
+    p_sys->i_seekto = 0;
     p_sys->p_header = 0;
     p_sys->p_rtsp->p_userdata = p_access;
     p_sys->p_rtsp->pf_connect = RtspConnect;
@@ -209,7 +238,8 @@ static int Open( vlc_object_t *p_this )
             psz_server = strdup("unknown");
     }
 
-    if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) )
+	/* vatata is another rtsp/p2p streaming server which support real/rmvb streaming  */
+    if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" )|| strstr( psz_server, "Vatata" ) )
     {
         uint32_t bandwidth = 10485800;
         rmff_header_t *h;
@@ -237,6 +267,8 @@ static int Open( vlc_object_t *p_this )
         p_sys->p_header = block_New( p_access, 4096 );
         p_sys->p_header->i_buffer =
             rmff_dump_header( h, (char *)p_sys->p_header->p_buffer, 1024 );
+        p_sys->b_seekable = true;
+        p_sys->b_pace_control = true;
         rmff_free_header( h );
     }
     else
@@ -288,6 +320,24 @@ static block_t *BlockRead( access_t *p_access )
         return p_block;
     }
 
+    if ( p_sys->i_seekto != 0 )
+    {
+        char buf[100];
+
+        sprintf(buf, "Range: npt=%.6f-", (double) p_sys->i_seekto/1000000 );
+        msg_Dbg( p_access, "Seek to %"PRId64" %s ", p_sys->i_seekto , buf );
+
+        /*pause at first*/
+        rtsp_request_pause(  p_sys->p_rtsp, NULL );
+        RtspReadAndSkip( p_access );
+		/* skip data which have sent to player, so next play will play the correct position */
+
+        /* replay*/
+        rtsp_schedule_field(p_sys->p_rtsp, buf );
+        rtsp_request_play(p_sys->p_rtsp,NULL);
+        p_sys->i_seekto = 0;
+
+    }
     i_size = real_get_rdt_chunk_header( p_access->p_sys->p_rtsp, &pheader );
     if( i_size <= 0 ) return 0;
 
@@ -303,7 +353,32 @@ static block_t *BlockRead( access_t *p_access )
  *****************************************************************************/
 static int Seek( access_t *p_access, int64_t i_pos )
 {
+    access_sys_t *p_sys = p_access->p_sys;
+
+    p_sys->i_seekto = i_pos ;
     return VLC_SUCCESS;
+
+#if 0
+    /*  the code do seek, but i meet some errors, i am afarid the send rtsp request may block the thread,
+	so i move the code to another function BlockRead which is in read-thread(?) and use iseekto as flag.
+	maybe real_get_rdt_chunk_header will read the rtsp's answer in another thread?
+	or maybe it is no problem here?
+	*/
+    int64_t i_time = i_pos / 1000 ;
+    char buf[100];
+    sprintf(buf, "Range: npt=%.6f-", (double) i_time/1000 );
+
+    msg_Dbg( p_access, "Seek to "I64Fd" %s ", i_time, buf );
+
+    // pause at first
+    rtsp_request_pause(  p_sys->p_rtsp, NULL );
+
+    // replay
+    rtsp_schedule_field(p_sys->p_rtsp, buf );
+    rtsp_request_play(p_sys->p_rtsp,NULL);
+
+    return VLC_SUCCESS;
+#endif
 }
 
 /*****************************************************************************
@@ -311,6 +386,7 @@ static int Seek( access_t *p_access, int64_t i_pos )
  *****************************************************************************/
 static int Control( access_t *p_access, int i_query, va_list args )
 {
+    access_sys_t *p_sys = p_access->p_sys;
     bool   *pb_bool;
     int          *pi_int;
     int64_t      *pi_64;
@@ -321,12 +397,12 @@ static int Control( access_t *p_access, int i_query, va_list args )
         case ACCESS_CAN_SEEK:
         case ACCESS_CAN_FASTSEEK:
             pb_bool = (bool*)va_arg( args, bool* );
-            *pb_bool = false;//p_sys->b_seekable;
+            *pb_bool = p_sys->b_seekable;
             break;
 
         case ACCESS_CAN_PAUSE:
             pb_bool = (bool*)va_arg( args, bool* );
-            *pb_bool = false;
+            *pb_bool = true;
             break;
 
         case ACCESS_CAN_CONTROL_PACE:
@@ -347,7 +423,9 @@ static int Control( access_t *p_access, int i_query, va_list args )
 
         /* */
         case ACCESS_SET_PAUSE_STATE:
-            /* Nothing to do */
+            pb_bool = (bool*)va_arg( args, bool* );
+            if ( ! pb_bool )
+                return Seek( p_access, p_access->info.i_pos );
             break;
 
         case ACCESS_GET_TITLE_INFO:
diff --git a/modules/access/rtsp/real.c b/modules/access/rtsp/real.c
index da499ec..83d3de2 100644
--- a/modules/access/rtsp/real.c
+++ b/modules/access/rtsp/real.c
@@ -469,6 +469,11 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt
     char b[64];
     int rulematches[16];
 
+	if ( ! desc->stream[i]->asm_rule_book )
+	{
+		goto error;
+	}
+
     lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
 
     n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
@@ -591,7 +596,11 @@ int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) {
   ph->stream_number=(flags1>>1)&1;
   ph->timestamp=ts;
   ph->reserved=0;
-  ph->flags=0;      /* TODO: determine keyframe flag and insert here? */
+
+  if ( header[7] == 0xc0 )
+	ph->flags=2;
+  else
+	ph->flags=0;
   return size;
 }
 
@@ -690,7 +699,7 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
   rmff_fix_header(h);
 
 #if 0
-  fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
+  fprintf(stderr, "Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
       h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
 #endif
 
diff --git a/modules/access/rtsp/rtsp.c b/modules/access/rtsp/rtsp.c
index 6730a93..9b2042e 100644
--- a/modules/access/rtsp/rtsp.c
+++ b/modules/access/rtsp/rtsp.c
@@ -215,6 +215,13 @@ static int rtsp_get_answers( rtsp_client_t *rtsp )
 
     answer = rtsp_get( rtsp );
     if( !answer ) return 0;
+    if ( answer[0] == '$' )
+    {
+        free( answer );
+        rtsp_free_answers( rtsp );
+        return 0;
+    }
+
     code = rtsp_get_status_code( rtsp, answer );
     free( answer );
 
@@ -234,6 +241,7 @@ static int rtsp_get_answers( rtsp_client_t *rtsp )
             //       answer_seq, rtsp->p_private->cseq );
 
               rtsp->p_private->cseq = answer_seq;
+              rtsp->p_private->cseq ++;
           }
       }
       if( !strncasecmp( answer, "Server:", 7 ) )
@@ -337,7 +345,12 @@ int rtsp_request_describe( rtsp_client_t *rtsp, const char *what )
 
 int rtsp_request_setup( rtsp_client_t *rtsp, const char *what )
 {
+    if(! what )
+    {
+		return 500;
+    }
     rtsp_send_request( rtsp, "SETUP", what );
+
     return rtsp_get_answers( rtsp );
 }
 
@@ -379,15 +392,54 @@ int rtsp_request_play( rtsp_client_t *rtsp, const char *what )
                  rtsp->p_private->port, rtsp->p_private->path );
     }
 
+    rtsp_schedule_standard( rtsp );
     rtsp_send_request( rtsp, "PLAY", buf );
     free( buf );
 
     return rtsp_get_answers( rtsp );
 }
 
+int rtsp_request_pause( rtsp_client_t *rtsp, const char *what )
+{
+    char *buf;
+
+    if( what )
+    {
+        buf = strdup( what );
+    }
+    else
+    {
+        buf = malloc( strlen(rtsp->p_private->host) +
+                      strlen(rtsp->p_private->path) + 16 );
+        sprintf( buf, "rtsp://%s:%i/%s", rtsp->p_private->host,
+                 rtsp->p_private->port, rtsp->p_private->path );
+    }
+    rtsp_schedule_field( rtsp, "User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)" );
+    //rtsp_schedule_standard( rtsp );
+    rtsp_send_request( rtsp, "PAUSE", buf );
+    free( buf );
+
+    return rtsp_get_answers( rtsp );
+}
+
 int rtsp_request_tearoff( rtsp_client_t *rtsp, const char *what )
 {
-    rtsp_send_request( rtsp, "TEAROFF", what );
+    char *buf;
+
+    if( what )
+    {
+        buf = strdup( what );
+    }
+    else
+    {
+        buf = malloc( strlen(rtsp->p_private->host) +
+                      strlen(rtsp->p_private->path) + 16 );
+        sprintf( buf, "rtsp://%s:%i/%s", rtsp->p_private->host,
+                 rtsp->p_private->port, rtsp->p_private->path );
+    }
+    rtsp_send_request( rtsp, "TEAROFF", buf );
+    free( buf );
+
     return rtsp_get_answers( rtsp );
 }
 
-- 
1.5.5.1




More information about the vlc-devel mailing list