/* v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps [email protected] (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 a=recvonly m=audio 3456 RTP/AVP 0 m=video 2232 RTP/AVP 31 m=whiteboard 32416 UDP WB a=orient:portrait */ int rtsp_client_sdp(struct rtsp_client_t* rtsp, const char* content) { int i, j, n, count; int formats[N_MEDIA_FORMAT]; struct rtsp_media_t* media; void* sdp; sdp = sdp_parse(content); if (!sdp) return -1; count = sdp_media_count(sdp); if(count > N_MEDIA) { rtsp->media_ptr = (struct rtsp_media_t*)malloc(sizeof(struct rtsp_media_t)*(count-N_MEDIA)); if(!rtsp->media_ptr) { sdp_destroy(sdp); return ENOMEM; } memset(rtsp->media_ptr, 0, sizeof(struct rtsp_media_t)*(count-N_MEDIA)); } rtsp->media_count = count; // rfc 2326 C.1.1 Control URL (p80) // If found at the session level, the attribute indicates the URL for aggregate control rtsp->aggregate = rtsp_media_aggregate_control_enable(sdp); rtsp_get_session_uri(sdp, rtsp->aggregate_uri, sizeof(rtsp->aggregate_uri), rtsp->uri, rtsp->baseuri, rtsp->location); for(i = 0; i < count; i++) { media = rtsp_get_media(rtsp, i); //media->cseq = rand(); // RTSP2326 C.1.1 Control URL rtsp_get_media_uri(sdp, i, media->uri, sizeof(media->uri), rtsp->aggregate_uri); n = sdp_media_formats(sdp, i, formats, N_MEDIA_FORMAT); media->avformat_count = n > N_MEDIA_FORMAT ? N_MEDIA_FORMAT : n; for(j = 0; j < media->avformat_count; j++) { media->avformats[j].fmt = formats[j]; } // update media encoding sdp_media_attribute_list(sdp, i, NULL, rtsp_media_onattr, media); } sdp_destroy(sdp); return 0; }
/* v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps [email protected] (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 a=recvonly m=audio 3456 RTP/AVP 0 m=video 2232 RTP/AVP 31 m=whiteboard 32416 UDP WB a=orient:portrait */ int rtsp_client_sdp(struct rtsp_client_context_t* ctx, void* sdp) { int i, count; int formats[N_MEDIA_FORMAT]; struct rtsp_media_t* media; assert(sdp); count = sdp_media_count(sdp); if(count > N_MEDIA) { ctx->media_ptr = (struct rtsp_media_t*)malloc(sizeof(struct rtsp_media_t)*(count-N_MEDIA)); if(!ctx->media_ptr) return -1; memset(ctx->media_ptr, 0, sizeof(struct rtsp_media_t)*(count-N_MEDIA)); } ctx->media_count = count; // rfc 2326 C.1.1 Control URL (p80) // If found at the session level, the attribute indicates the URL for aggregate control ctx->aggregate = rtsp_media_aggregate_control_enable(sdp); rtsp_get_session_uri(sdp, ctx->aggregate_uri, sizeof(ctx->aggregate_uri), ctx->uri, ctx->baseuri, ctx->location); for(i = 0; i < count; i++) { int j, n; media = rtsp_get_media(ctx, i); media->cseq = rand(); // RTSP2326 C.1.1 Control URL rtsp_get_media_uri(sdp, i, media->uri, sizeof(media->uri), ctx->aggregate_uri); n = sdp_media_formats(sdp, i, formats, N_MEDIA_FORMAT); media->avformat_count = n > N_MEDIA_FORMAT ? N_MEDIA_FORMAT : n; for(j = 0; j < media->avformat_count; j++) { media->avformats[j].pt = formats[j]; } // update media encoding sdp_media_attribute_list(sdp, i, NULL, rtsp_media_onattr, media); } return 0; }
static int rtsp_client_media_pause(struct rtsp_client_t *rtsp) { int r; struct rtsp_media_t* media; assert(0 == rtsp->aggregate); assert(RTSP_PAUSE == rtsp->state); assert(rtsp->progress < rtsp->media_count); media = rtsp_get_media(rtsp, rtsp->progress); if (NULL == media) return -1; assert(media && media->uri && media->session.session[0]); r = rtsp_client_authenrization(rtsp, "PAUSE", media->uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization)); r = snprintf(rtsp->req, sizeof(rtsp->req), sc_format, media->uri, rtsp->cseq++, media->session.session, rtsp->authenrization, USER_AGENT); assert(r > 0 && r < sizeof(rtsp->req)); return r == rtsp->handler.send(rtsp->param, media->uri, rtsp->req, r) ? 0 : -1; }
int rtsp_client_media_pause(struct rtsp_client_context_t *ctx) { struct rtsp_media_t* media; assert(0 == ctx->aggregate); assert(RTSP_PAUSE == ctx->status); assert(ctx->progress < ctx->media_count); media = rtsp_get_media(ctx, ctx->progress); assert(media && media->uri && media->session); snprintf(ctx->req, sizeof(ctx->req), "PAUSE %s RTSP/1.0\r\n" "CSeq: %u\r\n" "Session: %s\r\n" "User-Agent: %s\r\n" "\r\n", media->uri, media->cseq++, media->session, USER_AGENT); return ctx->client.request(ctx->transport, media->uri, ctx->req, strlen(ctx->req), ctx, rtsp_client_media_pause_onreply); }
int rtsp_client_setup(struct rtsp_client_t* rtsp, const char* sdp) { int i, r; struct rtsp_media_t *media; if (NULL == sdp || 0 == *sdp) return -1; r = rtsp_client_sdp(rtsp, sdp); if (0 != r) return r; for (i = 0; i < rtsp->media_count; i++) { media = rtsp_get_media(rtsp, i); r = rtsp->handler.rtpport(rtsp->param, &media->transport.rtp.u.client_port1); if (0 != r) return r; if (0 == media->transport.rtp.u.client_port1) { media->transport.transport = RTSP_TRANSPORT_RTP_TCP; media->transport.rtp.u.client_port1 = 2 * (unsigned short)i; media->transport.rtp.u.client_port2 = 2 * (unsigned short)i + 1; } else { assert(0 == media->transport.rtp.u.client_port1 % 2); media->transport.transport = RTSP_TRANSPORT_RTP_UDP; media->transport.rtp.u.client_port2 = media->transport.rtp.u.client_port1 + 1; } } rtsp->state = RTSP_SETUP; rtsp->progress = 0; return rtsp_client_media_setup(rtsp); }
static int rtsp_client_media_setup(struct rtsp_client_t* rtsp) { int len; struct rtsp_media_t *media; char session[sizeof(media->session.session) + 12], *p; assert(RTSP_SETUP == rtsp->state); assert(rtsp->progress < rtsp->media_count); media = rtsp_get_media(rtsp, rtsp->progress); if (NULL == media) return -1; p = rtsp->media[0].session.session; len = snprintf(session, sizeof(session), (rtsp->aggregate && *p) ? "Session: %s\r\n" : "", p); assert(len >= 0 && len < sizeof(session)); // TODO: multicast assert(0 == media->transport.multicast); len = rtsp_client_authenrization(rtsp, "SETUP", media->uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization)); len = snprintf(rtsp->req, sizeof(rtsp->req), RTSP_TRANSPORT_RTP_TCP==media->transport.transport?sc_rtsp_tcp:sc_rtsp_udp, media->uri, rtsp->cseq++, session, rtsp->authenrization, media->transport.rtp.u.client_port1, media->transport.rtp.u.client_port2, USER_AGENT); return len == rtsp->handler.send(rtsp->param, media->uri, rtsp->req, len) ? 0 : -1; }