⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
                          "port-audio=%i}", ip, i_port_video, i_port_audio );            }            vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PLAY,                              psz_output );            free( psz_output );            break;        }        case HTTPD_MSG_DESCRIBE:        {            char *psz_sdp =                SDPGenerate( p_media, cl );            if( psz_sdp != NULL )            {                answer->i_status = 200;                answer->psz_status = strdup( "OK" );                httpd_MsgAdd( answer, "Content-type",  "%s", "application/sdp" );                answer->p_body = (uint8_t *)psz_sdp;                answer->i_body = strlen( psz_sdp );            }            else            {                answer->i_status = 500;                answer->psz_status = strdup( "Internal server error" );                answer->p_body = NULL;                answer->i_body = 0;            }            break;        }        case HTTPD_MSG_PAUSE:            psz_session = httpd_MsgGet( query, "Session" );            msg_Dbg( p_vod, "HTTPD_MSG_PAUSE for session: %s", psz_session );            p_rtsp = RtspClientGet( p_media, psz_session );            if( !p_rtsp ) break;            vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PAUSE );            p_rtsp->b_paused = VLC_TRUE;            answer->i_status = 200;            answer->psz_status = strdup( "OK" );            answer->i_body = 0;            answer->p_body = NULL;            break;        case HTTPD_MSG_TEARDOWN:            /* for now only multicast so easy again */            answer->i_status = 200;            answer->psz_status = strdup( "OK" );            answer->i_body = 0;            answer->p_body = NULL;            psz_session = httpd_MsgGet( query, "Session" );            msg_Dbg( p_vod, "HTTPD_MSG_TEARDOWN for session: %s", psz_session);            p_rtsp = RtspClientGet( p_media, psz_session );            if( !p_rtsp ) break;            vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_STOP );            RtspClientDel( p_media, p_rtsp );            break;        default:            return VLC_EGENERIC;    }    httpd_MsgAdd( answer, "Server", "VLC Server" );    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );    psz_cseq = httpd_MsgGet( query, "Cseq" );    psz_cseq ? i_cseq = atoi( psz_cseq ) : 0;    httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );    httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );    if( psz_session )    {        httpd_MsgAdd( answer, "Session", "%s;timeout=5", psz_session );    }    return VLC_SUCCESS;}static int RtspCallbackES( httpd_callback_sys_t *p_args, httpd_client_t *cl,                           httpd_message_t *answer, httpd_message_t *query ){    media_es_t *p_es = (media_es_t*)p_args;    vod_media_t *p_media = p_es->p_media;    vod_t *p_vod = p_media->p_vod;    rtsp_client_t *p_rtsp = NULL;    char *psz_transport = NULL;    char *psz_playnow = NULL; /* support option: x-playNow */    char *psz_session = NULL;    char *psz_position = NULL;    char *psz_cseq = NULL;    int i_cseq = 0;    int i;    if( answer == NULL || query == NULL ) return VLC_SUCCESS;    msg_Dbg( p_vod, "RtspCallback query: type=%d", query->i_type );    answer->i_proto   = HTTPD_PROTO_RTSP;    answer->i_version = query->i_version;    answer->i_type    = HTTPD_MSG_ANSWER;    answer->i_body    = 0;    answer->p_body      = NULL;    switch( query->i_type )    {        case HTTPD_MSG_SETUP:            psz_playnow = httpd_MsgGet( query, "x-playNow" );            psz_transport = httpd_MsgGet( query, "Transport" );            msg_Dbg( p_vod, "HTTPD_MSG_SETUP: transport=%s", psz_transport );            if( strstr( psz_transport, "unicast" ) &&                strstr( psz_transport, "client_port=" ) )            {                rtsp_client_t *p_rtsp;                rtsp_client_es_t *p_rtsp_es;                char ip[NI_MAXNUMERICHOST];                int i_port = atoi( strstr( psz_transport, "client_port=" ) +                                strlen("client_port=") );                if( httpd_ClientIP( cl, ip ) == NULL )                {                    answer->i_status = 500;                    answer->psz_status = strdup( "Internal server error" );                    answer->i_body = 0;                    answer->p_body = NULL;                    break;                }                msg_Dbg( p_vod, "HTTPD_MSG_SETUP: unicast ip=%s port=%d",                        ip, i_port );                psz_session = httpd_MsgGet( query, "Session" );                if( !psz_session || !*psz_session )                {                    if( ( p_vod->p_sys->i_throttle_users > 0 ) &&                        ( p_vod->p_sys->i_connections >= p_vod->p_sys->i_throttle_users ) )                    {                        answer->i_status = 503;                        answer->psz_status = strdup( "Too many connections" );                        answer->i_body = 0;                        answer->p_body = NULL;                        break;                    }                    asprintf( &psz_session, "%d", rand() );                    p_rtsp = RtspClientNew( p_media, psz_session );                }                else                {                    p_rtsp = RtspClientGet( p_media, psz_session );                    if( !p_rtsp )                    {                        answer->i_status = 454;                        answer->psz_status = strdup( "Unknown session id" );                        answer->i_body = 0;                        answer->p_body = NULL;                        break;                    }                }                p_rtsp_es = malloc( sizeof(rtsp_client_es_t) );                p_rtsp_es->i_port = i_port;                p_rtsp_es->psz_ip = strdup( ip );                p_rtsp_es->p_media_es = p_es;                TAB_APPEND( p_rtsp->i_es, p_rtsp->es, p_rtsp_es );                answer->i_status = 200;                answer->psz_status = strdup( "OK" );                answer->i_body = 0;                answer->p_body = NULL;                if( p_media->b_raw )                {                    if( strstr( psz_transport, "MP2T/H2221/UDP" ) )                    {                        httpd_MsgAdd( answer, "Transport", "MP2T/H2221/UDP;client_port=%d-%d",                                      i_port, i_port + 1 );                    }                    else if( strstr( psz_transport, "RAW/RAW/UDP" ) )                    {                        httpd_MsgAdd( answer, "Transport", "RAW/RAW/UDP;client_port=%d-%d",                                      i_port, i_port + 1 );                    }                }                else                {                    httpd_MsgAdd( answer, "Transport", "RTP/AVP/UDP;client_port=%d-%d",                                  i_port, i_port + 1 );                }            }            else /* TODO  strstr( psz_transport, "interleaved" ) ) */            {                answer->i_status = 461;                answer->psz_status = strdup( "Unsupported Transport" );                answer->i_body = 0;                answer->p_body = NULL;            }            /* Intentional fall-through on x-playNow option in RTSP request */            if( !psz_playnow )                break;        case HTTPD_MSG_PLAY:            /* This is kind of a kludge. Should we only support Aggregate             * Operations ? */            psz_session = httpd_MsgGet( query, "Session" );            msg_Dbg( p_vod, "HTTPD_MSG_PLAY for session: %s", psz_session );            p_rtsp = RtspClientGet( p_media, psz_session );            psz_position = httpd_MsgGet( query, "Range" );            if( psz_position ) psz_position = strstr( psz_position, "npt=" );            if( psz_position )            {                double f_pos;                char *end;                msg_Dbg( p_vod, "seeking request: %s", psz_position );                psz_position += 4;                /* FIXME: npt= is not necessarily formatted as a float */                f_pos = us_strtod( psz_position, &end );                if( end > psz_position )                {                    f_pos /= ((double)(p_media->i_length))/1000 /1000 / 100;                    vod_MediaControl( p_vod, p_media, psz_session,                                      VOD_MEDIA_SEEK, f_pos );                }            }            if( !psz_playnow )            {                answer->i_status = 200;                answer->psz_status = strdup( "OK" );                answer->i_body = 0;                answer->p_body = NULL;            }            break;        case HTTPD_MSG_TEARDOWN:            answer->i_status = 200;            answer->psz_status = strdup( "OK" );            answer->i_body = 0;            answer->p_body = NULL;            psz_session = httpd_MsgGet( query, "Session" );            msg_Dbg( p_vod, "HTTPD_MSG_TEARDOWN for session: %s", psz_session);            p_rtsp = RtspClientGet( p_media, psz_session );            if( !p_rtsp ) break;            for( i = 0; i < p_rtsp->i_es; i++ )            {                if( p_rtsp->es[i]->p_media_es == p_es )                {                    if( p_rtsp->es[i]->psz_ip ) free( p_rtsp->es[i]->psz_ip );                    TAB_REMOVE( p_rtsp->i_es, p_rtsp->es, p_rtsp->es[i] );                    break;                }            }            if( !p_rtsp->i_es )            {                vod_MediaControl( p_vod, p_media, psz_session,                                  VOD_MEDIA_STOP );                RtspClientDel( p_media, p_rtsp );            }            break;        case HTTPD_MSG_PAUSE:            /* This is kind of a kludge. Should we only support Aggregate             * Operations ? */            psz_session = httpd_MsgGet( query, "Session" );            msg_Dbg( p_vod, "HTTPD_MSG_PAUSE for session: %s", psz_session );            p_rtsp = RtspClientGet( p_media, psz_session );            if( !p_rtsp ) break;            vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PAUSE );            p_rtsp->b_paused = VLC_TRUE;            answer->i_status = 200;            answer->psz_status = strdup( "OK" );            answer->i_body = 0;            answer->p_body = NULL;            break;        default:            return VLC_EGENERIC;            break;    }    httpd_MsgAdd( answer, "Server", "VLC Server" );    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );    psz_cseq = httpd_MsgGet( query, "Cseq" );    if (psz_cseq)        i_cseq = atoi( psz_cseq );    else        i_cseq = 0;    httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );    httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );    if( psz_session )        httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );    return VLC_SUCCESS;}/***************************************************************************** * SDPGenerate: TODO * FIXME: need to be moved to a common place ? *****************************************************************************/static char *SDPGenerate( const vod_media_t *p_media, httpd_client_t *cl ){    int i, i_size;    char *p, *psz_sdp, ip[NI_MAXNUMERICHOST], ipv;    const char *psz_control;    if( httpd_ServerIP( cl, ip ) == NULL )        return NULL;    p = strchr( ip, '%' );    if( p != NULL )        *p = '\0'; /* remove scope if present */    ipv = ( strchr( ip, ':' ) != NULL ) ? '6' : '4';    /* Calculate size */    i_size = sizeof( "v=0\r\n" ) +        sizeof( "o=- * * IN IP4 \r\n" ) + 10 + NI_MAXNUMERICHOST +        sizeof( "s=*\r\n" ) + strlen( p_media->psz_session_name ) +        sizeof( "i=*\r\n" ) + strlen( p_media->psz_session_description ) +        sizeof( "u=*\r\n" ) + strlen( p_media->psz_session_url ) +        sizeof( "e=*\r\n" ) + strlen( p_media->psz_session_email ) +        sizeof( "c=IN IP4 0.0.0.0\r\n" ) + 20 + 10 +        sizeof( "t=0 0\r\n" ) + /* FIXME */        sizeof( "a=tool:"PACKAGE_STRING"\r\n" ) +        sizeof( "a=range:npt=0-1000000000.000\r\n" );    psz_control = (ipv == '6') ? p_media->psz_rtsp_control_v6                               : p_media->psz_rtsp_control_v4;    for( i = 0; i < p_media->i_es; i++ )    {        media_es_t *p_es = p_media->es[i];        i_size += sizeof( "m=**d*o * RTP/AVP *\r\n" ) + 19;        if( p_es->psz_rtpmap )        {            i_size += sizeof( "a=rtpmap:* *\r\n" ) +                strlen( p_es->psz_rtpmap ) + 9;        }        if( p_es->psz_fmtp )        {            i_size += sizeof( "a=fmtp:* *\r\n" ) +                strlen( p_es->psz_fmtp ) + 9;        }    }    i_size += (strlen( psz_control ) + strlen( ip ) + 9) * p_media->i_es;    p = psz_sdp = malloc( i_size );    p += sprintf( p, "v=0\r\n" );    p += sprintf( p, "o=- "I64Fd" %d IN IP%c %s\r\n",                  p_media->i_sdp_id, p_media->i_sdp_version, ipv, ip );    if( *p_media->psz_session_name )        p += sprintf( p, "s=%s\r\n", p_media->psz_session_name );    if( *p_media->psz_session_description )        p += sprintf( p, "i=%s\r\n", p_media->psz_session_description );    if( *p_media->psz_session_url )        p += sprintf( p, "u=%s\r\n", p_media->psz_session_url );    if( *p_media->psz_session_email )        p += sprintf( p, "e=%s\r\n", p_media->psz_session_email );    p += sprintf( p, "c=IN IP%c %s\r\n", ipv, ipv == '6' ? "::" : "0.0.0.0" );    p += sprintf( p, "t=0 0\r\n" ); /* FIXME */    p += sprintf( p, "a=tool:"PACKAGE_STRING"\r\n" );    if( p_media->i_length > 0 )    {        lldiv_t d = lldiv( p_media->i_length / 1000, 1000 );        p += sprintf( p, "a=range:npt=0-"I64Fd".%03u\r\n", d.quot,                      (unsigned)d.rem );    }    for( i = 0; i < p_media->i_es; i++ )    {        media_es_t *p_es = p_media->es[i];        if( p_es->fmt.i_cat == AUDIO_ES )        {            p += sprintf( p, "m=audio %d RTP/AVP %d\r\n",                          p_es->i_port, p_es->i_payload_type );        }        else if( p_es->fmt.i_cat == VIDEO_ES )        {            p += sprintf( p, "m=video %d RTP/AVP %d\r\n",                          p_es->i_port, p_es->i_payload_type );        }        else        {            continue;        }        if( p_es->psz_rtpmap )        {            p += sprintf( p, "a=rtpmap:%d %s\r\n", p_es->i_payload_type,                          p_es->psz_rtpmap );        }        if( p_es->psz_fmtp )        {            p += sprintf( p, "a=fmtp:%d %s\r\n", p_es->i_payload_type,                          p_es->psz_fmtp );        }        p += sprintf( p, psz_control, ip, i );    }    return psz_sdp;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -