📄 rtsp_rtp.c
字号:
err = select (s + 1, &set, NULL, NULL, &tv); if (err < 0) { mp_msg (MSGT_OPEN, MSGL_ERR, "Select failed: %s\n", strerror (errno)); close (s); return -1; } else if (err == 0) { mp_msg (MSGT_OPEN, MSGL_ERR, "Timeout! No data from host %s\n", hostname); close (s); return -1; } err_len = sizeof (err); getsockopt (s, SOL_SOCKET, SO_ERROR, &err, (socklen_t *) &err_len); if (err) { mp_msg (MSGT_OPEN, MSGL_ERR, "Socket error: %d\n", err); close (s); return -1; } return s;}static intis_multicast_address (char *addr){ struct sockaddr_in sin; if (!addr) return -1; sin.sin_family = AF_INET;#ifndef HAVE_WINSOCK2#ifdef USE_ATON inet_aton (addr, &sin.sin_addr);#else inet_pton (AF_INET, addr, &sin.sin_addr);#endif#else sin.sin_addr.s_addr = htonl (INADDR_ANY);#endif if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe) return 1; return 0;}struct rtp_rtsp_session_t *rtp_setup_and_play (rtsp_t *rtsp_session){ struct rtp_rtsp_session_t* rtp_session = NULL; const fsdp_media_description_t *med_dsc = NULL; char temp_buf[MAX_LENGTH + 1]; char npt[256]; char* answer; char* sdp; char *server_addr = NULL; char *destination = NULL; int statut; int content_length = 0; int is_multicast = 0; fsdp_description_t *dsc = NULL; fsdp_error_t result; int client_rtp_port = -1; int client_rtcp_port = -1; int server_rtp_port = -1; int server_rtcp_port = -1; int rtp_sock = -1; int rtcp_sock = -1; /* 1. send a RTSP DESCRIBE request to server */ rtsp_schedule_field (rtsp_session, RTSP_ACCEPT_SDP); statut = rtsp_request_describe (rtsp_session, NULL); if (statut < 200 || statut > 299) return NULL; answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_LENGTH); if (answer) content_length = atoi (answer); else return NULL; answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_TYPE); if (!answer || !strstr (answer, RTSP_APPLICATION_SDP)) return NULL; /* 2. read SDP message from server */ sdp = (char *) malloc (content_length + 1); if (rtsp_read_data (rtsp_session, sdp, content_length) <= 0) { free (sdp); return NULL; } sdp[content_length] = 0; /* 3. parse SDP message */ dsc = fsdp_description_new (); result = fsdp_parse (sdp, dsc); if (result != FSDPE_OK) { free (sdp); fsdp_description_delete (dsc); return NULL; } mp_msg (MSGT_OPEN, MSGL_V, "SDP:\n%s\n", sdp); free (sdp); /* 4. check for number of media streams: only one is supported */ if (fsdp_get_media_count (dsc) != 1) { mp_msg (MSGT_OPEN, MSGL_ERR, "A single media stream only is supported atm.\n"); fsdp_description_delete (dsc); return NULL; } /* 5. set the Normal Play Time parameter * use range provided by server in SDP or start now if empty */ sprintf (npt, RTSP_RANGE); if (fsdp_get_range (dsc)) strcat (npt, fsdp_get_range (dsc)); else strcat (npt, RTSP_NPT_NOW); /* 5. check for a valid media stream */ med_dsc = fsdp_get_media (dsc, 0); if (!med_dsc) { fsdp_description_delete (dsc); return NULL; } /* 6. parse the `m=<media> <port> <transport> <fmt list>' line */ /* check for an A/V media */ if (fsdp_get_media_type (med_dsc) != FSDP_MEDIA_VIDEO && fsdp_get_media_type (med_dsc) != FSDP_MEDIA_AUDIO) { fsdp_description_delete (dsc); return NULL; } /* only RTP/AVP transport method is supported right now */ if (fsdp_get_media_transport_protocol (med_dsc) != FSDP_TP_RTP_AVP) { fsdp_description_delete (dsc); return NULL; } /* only MPEG-TS is supported at the moment */ if (!strstr (fsdp_get_media_format (med_dsc, 0), RTSP_MEDIA_CONTAINER_MPEG_TS)) { fsdp_description_delete (dsc); return NULL; } /* get client port (if any) advised by server */ client_rtp_port = fsdp_get_media_port (med_dsc); if (client_rtp_port == -1) { fsdp_description_delete (dsc); return NULL; } /* if client_rtp_port = 0 => let client randomly pick one */ if (client_rtp_port == 0) { /* TODO: we should check if the port is in use first */ if (rtsp_port) client_rtp_port = rtsp_port; else client_rtp_port = RTSP_DEFAULT_PORT; } /* RTCP port generally is RTP port + 1 */ client_rtcp_port = client_rtp_port + 1; mp_msg (MSGT_OPEN, MSGL_V, "RTP Port from SDP appears to be: %d\n", client_rtp_port); mp_msg (MSGT_OPEN, MSGL_V, "RTCP Port from SDP appears to be: %d\n", client_rtcp_port); /* 7. parse the `c=<network type> <addr type> <connection address>' line */ /* check for a valid media network type (inet) */ if (fsdp_get_media_network_type (med_dsc) != FSDP_NETWORK_TYPE_INET) { /* no control for media: try global one instead */ if (fsdp_get_global_conn_network_type (dsc) != FSDP_NETWORK_TYPE_INET) { fsdp_description_delete (dsc); return NULL; } } /* only IPv4 is supported atm. */ if (fsdp_get_media_address_type (med_dsc) != FSDP_ADDRESS_TYPE_IPV4) { /* no control for media: try global one instead */ if (fsdp_get_global_conn_address_type (dsc) != FSDP_ADDRESS_TYPE_IPV4) { fsdp_description_delete (dsc); return NULL; } } /* get the media server address to connect to */ if (fsdp_get_media_address (med_dsc)) server_addr = strdup (fsdp_get_media_address (med_dsc)); else if (fsdp_get_global_conn_address (dsc)) { /* no control for media: try global one instead */ server_addr = strdup (fsdp_get_global_conn_address (dsc)); } if (!server_addr) { fsdp_description_delete (dsc); return NULL; } /* check for a UNICAST or MULTICAST address to connect to */ is_multicast = is_multicast_address (server_addr); /* 8. initiate an RTP session */ rtp_session = rtp_session_new (); if (!rtp_session) { free (server_addr); fsdp_description_delete (dsc); return NULL; } /* get the media control URL */ if (fsdp_get_media_control (med_dsc, 0)) rtp_session->control_url = strdup (fsdp_get_media_control (med_dsc, 0)); fsdp_description_delete (dsc); if (!rtp_session->control_url) { free (server_addr); rtp_session_free (rtp_session); return NULL; } /* 9. create the payload for RTSP SETUP request */ memset (temp_buf, '\0', MAX_LENGTH); snprintf (temp_buf, MAX_LENGTH, RTSP_TRANSPORT_REQUEST, is_multicast ? RTSP_TRANSPORT_MULTICAST : RTSP_TRANSPORT_UNICAST, is_multicast ? RTSP_MULTICAST_PORT : RTSP_UNICAST_CLIENT_PORT, client_rtp_port, client_rtcp_port); mp_msg (MSGT_OPEN, MSGL_V, "RTSP Transport: %s\n", temp_buf); rtsp_unschedule_field (rtsp_session, RTSP_SESSION); rtsp_schedule_field (rtsp_session, temp_buf); /* 10. check for the media control URL type and initiate RTSP SETUP */ if (!strncmp (rtp_session->control_url, "rtsp://", 7)) /* absolute URL */ statut = rtsp_request_setup (rtsp_session, rtp_session->control_url, NULL); else /* relative URL */ statut = rtsp_request_setup (rtsp_session, NULL, rtp_session->control_url); if (statut < 200 || statut > 299) { free (server_addr); rtp_session_free (rtp_session); return NULL; } /* 11. parse RTSP SETUP response: we need it to actually determine * the real address and port to connect to */ answer = rtsp_search_answers (rtsp_session, RTSP_TRANSPORT); if (!answer) { free (server_addr); rtp_session_free (rtp_session); return NULL; } /* check for RTP and RTCP ports to bind according to how request was done */ is_multicast = 0; if (strstr (answer, RTSP_TRANSPORT_MULTICAST)) is_multicast = 1; if (is_multicast) parse_port (answer, RTSP_MULTICAST_PORT, &client_rtp_port, &client_rtcp_port); else { parse_port (answer, RTSP_UNICAST_CLIENT_PORT, &client_rtp_port, &client_rtcp_port); parse_port (answer, RTSP_UNICAST_SERVER_PORT, &server_rtp_port, &server_rtcp_port); } /* now check network settings as determined by server */ if (rtsp_destination) destination = strdup (rtsp_destination); else destination = parse_destination (answer); if (!destination) destination = strdup (server_addr); free (server_addr); mp_msg (MSGT_OPEN, MSGL_V, "RTSP Destination: %s\n", destination); mp_msg (MSGT_OPEN, MSGL_V, "Client RTP port : %d\n", client_rtp_port); mp_msg (MSGT_OPEN, MSGL_V, "Client RTCP port : %d\n", client_rtcp_port); mp_msg (MSGT_OPEN, MSGL_V, "Server RTP port : %d\n", server_rtp_port); mp_msg (MSGT_OPEN, MSGL_V, "Server RTCP port : %d\n", server_rtcp_port); /* 12. performs RTSP PLAY request */ rtsp_schedule_field (rtsp_session, npt); statut = rtsp_request_play (rtsp_session, NULL); if (statut < 200 || statut > 299) { free (destination); rtp_session_free (rtp_session); return NULL; } /* 13. create RTP and RTCP connections */ rtp_sock = rtp_connect (destination, client_rtp_port); rtcp_sock = rtcp_connect (client_rtcp_port, server_rtcp_port, destination); rtp_session_set_fd (rtp_session, rtp_sock, rtcp_sock); free (destination); mp_msg (MSGT_OPEN, MSGL_V, "RTP Sock : %d\nRTCP Sock : %d\n", rtp_session->rtp_socket, rtp_session->rtcp_socket); if (rtp_session->rtp_socket == -1) { rtp_session_free (rtp_session); return NULL; } return rtp_session;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -