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

📄 rtsp_rtp.c

📁 mplayer播放器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2006 Benjamin Zores *   based on the Freebox patch for xine by Vincent Mussard *   but with many enhancements for better RTSP RFC compliance. * *   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 *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software Foundation, *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include <unistd.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include <sys/types.h>#include <inttypes.h>#include "config.h"#ifndef HAVE_WINSOCK2#include <netdb.h>#include <netinet/in.h>#include <sys/socket.h>#include <arpa/inet.h>#else#include <winsock2.h>#include <ws2tcpip.h>#endif#include "mp_msg.h"#include "rtsp.h"#include "rtsp_rtp.h"#include "rtsp_session.h"#include "../freesdp/common.h"#include "../freesdp/parser.h"#define RTSP_DEFAULT_PORT 31336#define MAX_LENGTH 256#define RTSP_ACCEPT_SDP "Accept: application/sdp"#define RTSP_CONTENT_LENGTH "Content-length"#define RTSP_CONTENT_TYPE "Content-Type"#define RTSP_APPLICATION_SDP "application/sdp"#define RTSP_RANGE "Range: "#define RTSP_NPT_NOW "npt=now-"#define RTSP_MEDIA_CONTAINER_MPEG_TS "33"#define RTSP_TRANSPORT_REQUEST "Transport: RTP/AVP;%s;%s%i-%i;mode=\"PLAY\""  #define RTSP_TRANSPORT_MULTICAST "multicast"#define RTSP_TRANSPORT_UNICAST "unicast"#define RTSP_MULTICAST_PORT "port="#define RTSP_UNICAST_CLIENT_PORT "client_port="#define RTSP_UNICAST_SERVER_PORT "server_port="#define RTSP_SETUP_DESTINATION "destination="#define RTSP_SESSION "Session"#define RTSP_TRANSPORT "Transport"/* hardcoded RTCP RR - this is _NOT_ RFC compliant */#define RTCP_RR_SIZE 32#define RTCP_RR "\201\311\0\7(.JD\31+\306\343\0\0\0\0\0\0/E\0\0\2&\0\0\0\0\0\0\0\0\201"#define RTCP_SEND_FREQUENCY 1024int rtsp_port = 0;char *rtsp_destination = NULL;voidrtcp_send_rr (rtsp_t *s, struct rtp_rtsp_session_t *st){  if (st->rtcp_socket == -1)    return;    /* send RTCP RR every RTCP_SEND_FREQUENCY packets   * FIXME : NOT CORRECT, HARDCODED, BUT MAKES SOME SERVERS HAPPY   * not rfc compliant   * http://www.faqs.org/rfcs/rfc1889.html chapter 6 for RTCP   */  if (st->count == RTCP_SEND_FREQUENCY)  {    char rtcp_content[RTCP_RR_SIZE];    strcpy (rtcp_content, RTCP_RR);    send (st->rtcp_socket, rtcp_content, RTCP_RR_SIZE, 0);    /* ping RTSP server to keep connection alive.       we use OPTIONS instead of PING as not all servers support it */    rtsp_request_options (s, "*");    st->count = 0;  }  else    st->count++;}static struct rtp_rtsp_session_t *rtp_session_new (void){  struct rtp_rtsp_session_t *st = NULL;    st = malloc (sizeof (struct rtp_rtsp_session_t));    st->rtp_socket = -1;  st->rtcp_socket = -1;  st->control_url = NULL;  st->count = 0;    return st;}voidrtp_session_free (struct rtp_rtsp_session_t *st){  if (!st)    return;  if (st->rtp_socket != -1)    close (st->rtp_socket);  if (st->rtcp_socket != -1)    close (st->rtcp_socket);  if (st->control_url)    free (st->control_url);  free (st);}static voidrtp_session_set_fd (struct rtp_rtsp_session_t *st,                    int rtp_sock, int rtcp_sock){  if (!st)    return;  st->rtp_socket = rtp_sock;  st->rtcp_socket = rtcp_sock;}static intparse_port (const char *line, const char *param,            int *rtp_port, int *rtcp_port){  char *parse1;  char *parse2;  char *parse3;    char *line_copy = strdup (line);  parse1 = strstr (line_copy, param);  if (parse1)  {    parse2 = strstr (parse1, "-");        if (parse2)    {      parse3 = strstr (parse2, ";");            if (parse3)	parse3[0] = 0;            parse2[0] = 0;    }    else    {      free (line_copy);      return 0;    }  }  else  {    free (line_copy);    return 0;  }    *rtp_port = atoi (parse1 + strlen (param));  *rtcp_port = atoi (parse2 + 1);  free (line_copy);    return 1;}static char *parse_destination (const char *line){  char *parse1;  char *parse2;  char *dest = NULL;  char *line_copy = strdup (line);  int len;    parse1 = strstr (line_copy, RTSP_SETUP_DESTINATION);  if (!parse1)  {    free (line_copy);    return NULL;  }    parse2 = strstr (parse1, ";");  if (!parse2)  {    free (line_copy);    return NULL;  }   len = strlen (parse1) - strlen (parse2)    - strlen (RTSP_SETUP_DESTINATION) + 1;  dest = (char *) malloc (len + 1);  snprintf (dest, len, parse1 + strlen (RTSP_SETUP_DESTINATION));  free (line_copy);  return dest;}static intrtcp_connect (int client_port, int server_port, const char* server_hostname){  struct sockaddr_in sin;  struct hostent *hp;  int s;    if (client_port <= 1023)    return -1;  s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);  if (s == -1)    return -1;  hp = gethostbyname (server_hostname);  if (!hp)  {    close (s);    return -1;  }  sin.sin_family = AF_INET;  sin.sin_addr.s_addr = INADDR_ANY;  sin.sin_port = htons (client_port);    if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))  {#ifndef HAVE_WINSOCK2    if (errno != EINPROGRESS)#else    if (WSAGetLastError() != WSAEINPROGRESS)#endif    {      close (s);      return -1;    }  }    sin.sin_family = AF_INET;  memcpy (&(sin.sin_addr.s_addr), hp->h_addr, sizeof (hp->h_addr));  sin.sin_port = htons (server_port);  /* datagram socket */  if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0)  {    close (s);    return -1;  }  return s;}static intrtp_connect (char *hostname, int port){  struct sockaddr_in sin;  struct timeval tv;  int err, err_len;  int rxsockbufsz;  int s;  fd_set set;  if (port <= 1023)    return -1;  s = socket (PF_INET, SOCK_DGRAM, 0);  if (s == -1)    return -1;  sin.sin_family = AF_INET;  if (!hostname || !strcmp (hostname, "0.0.0.0"))    sin.sin_addr.s_addr = htonl (INADDR_ANY);  else#ifndef HAVE_WINSOCK2#ifdef USE_ATON    inet_aton (hostname, &sin.sin_addr);#else    inet_pton (AF_INET, hostname, &sin.sin_addr);#endif#else    sin.sin_addr.s_addr = htonl (INADDR_ANY);#endif  sin.sin_port = htons (port);  /* Increase the socket rx buffer size to maximum -- this is UDP */  rxsockbufsz = 240 * 1024;  if (setsockopt (s, SOL_SOCKET, SO_RCVBUF,                  &rxsockbufsz, sizeof (rxsockbufsz)))    mp_msg (MSGT_OPEN, MSGL_ERR, "Couldn't set receive socket buffer size\n");  /* if multicast address, add membership */  if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe)  {    struct ip_mreq mcast;    mcast.imr_multiaddr.s_addr = sin.sin_addr.s_addr;    mcast.imr_interface.s_addr = 0;    if (setsockopt (s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof (mcast)))    {      mp_msg (MSGT_OPEN, MSGL_ERR, "IP_ADD_MEMBERSHIP failed\n");      close (s);      return -1;    }  }    /* datagram socket */  if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))  {#ifndef HAVE_WINSOCK2    if (errno != EINPROGRESS)#else    if (WSAGetLastError() != WSAEINPROGRESS)#endif    {      mp_msg (MSGT_OPEN, MSGL_ERR, "bind: %s\n", strerror (errno));      close (s);      return -1;    }  }  tv.tv_sec = 0;  tv.tv_usec = (1 * 1000000); /* 1 second timeout */    FD_ZERO (&set);  FD_SET (s, &set);  

⌨️ 快捷键说明

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