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

📄 rtptrans.c

📁 RTP 实现的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/** RTP translator.** Usage:*   rtptrans host/port/ttl host/port/ttl [...]** Forwards RTP/RTCP packets from one of the named sockets to all* others.  Addresses can be a multicast or unicast.  TTL values for* unicast addresses are ignored. (Actually, doesn't check whether* packets are RTP or not.)** It would be easy to add transcoding on a packet-by-packet basis (as*   long as the sampling rate doesn't change).** Author: Henning Schulzrinne* GMD Fokus, Berlin*** Additionally, the translator can translate VAT packets into RTP packets. * Thereby, the VAT control packets are translated into RTCP SDES packets with* a CNAME and a NAME entry. However, this is only entended to be used in the * following configuration:* VAT packets arriving on a multicast connection are translated into RTP and* sent over a unicast link. RTP packets are not translated -not yet at least-* into VAT packets and and all packets arriving on unicast links are not* changed at all. Therefore, currently mainly the following topology is * supported:**    multicast VAT -> translator -> unicast RTP**    and on the way back it should lokk like this**    multicast VAT <- translator <- unicast VAT*** This means that the audio agent on the unicast link should be able to use* both VAT and RTP.** Author: Dorgham Sisalem* GMD Fokus, Berlin** Bug fixes and supstantial improvements by * Stephen Casner <casner@precept.com>* */#include <sys/types.h>#include <sys/uio.h>#include <sys/socket.h>#include <netinet/in.h>  /* struct sockaddr_in */#include <sys/time.h>    /* gettimeofday() */#include <arpa/inet.h>   /* inet_ntoa() */#include <string.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <values.h>#include <unistd.h>      /* select(), perror() */#include <stdlib.h>      /* getopt(), atoi() */#include <memory.h>      /* memset() */#include "rtp.h"#include "rtpdump.h"#include "ansi.h"#include "notify.h"#include "multimer.h"#include "vat.h"#define PAD(x,n) (((n) - ((x) & (n-1))) & (n-1))#define MAX_HOST 10extern int gettimeofday();static int debug = 0;static int hostc = 0;static multi_sock[3] = {0,0,0};static struct {  int sock;  struct sockaddr_in sin;} side[MAX_HOST][3];  /* [host][proto] *//*  * create a linked list for traversing the sequence numbers of the different  * streams arriving over a multicast link to a unicast network */typedef struct stream_id{  int seq;  int addr;  int next_ts;  struct stream_id* next;} STREAM;typedef struct stream_id stream;/*  * We need to keep in memory the sequence number of the last sent packet * for each data stream. */static stream *head;   /* start of list */static stream *middle; /* middle of the list, keeping this pointer reduces the                        * avarage searching path to a 1/4 of the list instead of                        * 1/2.                        */static stream *last;   /* Last seen stream, as the probability that the next                        * packet will belong to the last seen one this reduces                        * the searching path even further.                        */static int list_len;int create_stream(int addr, int next){  stream *elem;  int i;  stream* new_stream=( stream *) malloc(sizeof( stream));  if(new_stream==NULL) {    perror("can not create a new steam identifier ");    exit (0);  }  /* init created stream */  new_stream->next=NULL;  new_stream->addr=addr;  new_stream->seq=addr;  new_stream->next_ts=next;  if(head==NULL) { /* initialize the list */    head=new_stream;    middle=new_stream;    list_len=1;#if !defined(nextstep)    srand48(rand());  /* initialize random number generator */#else    srand(rand());    /* (fred) This is surprising */#endif    new_stream->seq=rand();    last=new_stream;    return new_stream->seq;  }  new_stream->seq=rand(); /* init the first sequence number for this stream */  if((list_len++)%2) {    for(elem=head, i=1; i<(list_len/2)+(list_len%2);i++,elem=elem->next);    middle=elem;  }  /* organize the list in order of the ssrc */  if(head->addr>addr) {    new_stream->next=head;    head=new_stream;    last=new_stream;    return new_stream->seq;  }      for(elem=head;elem->next!=NULL;elem=elem->next) {    if(elem->next->addr>addr) {      new_stream->next=elem->next;      elem->next=new_stream;      last=new_stream;      return new_stream->seq;    }   }      ;  if(elem->next==NULL) {    elem->next=new_stream;    last=new_stream;    return new_stream->seq;  }     return new_stream->seq;}/*  * Add a stream to the list. */int find_stream(int addr, int ts, int next, int m){  stream *element;  /* packet belongs to the last seen stream */  if ((last!=NULL)&&(addr==last->addr)) {     last->seq+=1;     if (ts != last->next_ts && !m)       last->seq+=1;   /* approximate missing some packets */     last->next_ts = next;     return(last->seq);  }  if((middle!=NULL)&&(addr>=middle->addr))    element=middle;  else    element=head;  for(; (element!=NULL)&&(element->addr<=addr); element=element->next) {    if(element->addr==addr) {      element->seq+=1;       if (ts != element->next_ts && !m)         element->seq += 1;  /* approximate missing some packets */       element->next_ts = next;      return (element->seq);    }  }  return(create_stream(addr, next));}struct sdes_msg {  rtcp_common_t header;  struct rtcp_sdes sdes;};/** Handle file input events from network sockets.*/static Notify_value socket_handler(Notify_client client, int sock){  int len, addr_len;  int proto;  struct sockaddr_in sin_from;  char packet[8192];  int i;  const int VAT_LEN=8;  vat_hdr_t *vat_hdr;  rtp_hdr_t *rtp_hdr;  rtp_hdr_t rtp_hdr_send;  proto = ((int)client & 1);  /* Read packet data from socket. */  addr_len = sizeof(sin_from);  len = recvfrom(sock, packet, sizeof(packet), 0,        (struct sockaddr *)&sin_from, &addr_len);  rtp_hdr=(rtp_hdr_t *)packet;  if (debug) {    struct timeval now;    gettimeofday(&now, 0);    printf("%0.3f %s %4d [%s/%d]\n",       now.tv_sec + now.tv_usec/1e6,       rtp_hdr->version==2 ? (proto ? "RTCP" : "RTP ") :        rtp_hdr->version==0 ? (proto ? "vatC" : "vat ") : "UKWN", len,      inet_ntoa(sin_from.sin_addr), ntohs(sin_from.sin_port));  }  /* do not translate packets that already use RTP or arrive over the unicast   link*/  if((rtp_hdr->version==2)||((sock!=multi_sock[0])&&(sock!=multi_sock[1]))) {    rtp_hdr=(rtp_hdr_t *)packet;       for (i = 0; i < hostc; i++) {      if (side[i][proto].sock != sock) {        if (sendto(side[i][2].sock, packet, len, 0,          (struct sockaddr *)&side[i][proto].sin,sizeof(side[i][proto].sin))<0)        perror("sendto RTCP");      }    }  }  else {    struct msghdr msg;    if (!proto) { /*translate VAT packets */      struct iovec iov[2];      char type;       int samples = len-VAT_LEN;      vat_hdr=(vat_hdr_t *)packet;         if(vat_hdr->flags&VATHF_NEWTS)        rtp_hdr_send.m=1;      else        rtp_hdr_send.m=0;      type= vat_hdr->flags&VATHF_FMTMASK;      switch (type) {      case VAT_AUDF_GSM:        samples = (samples/33)*160;      case VAT_AUDF_MULAW8:      case VAT_AUDF_G721:   /* samples not right for this */      case VAT_AUDF_G723:   /* samples not right for this */        rtp_hdr_send.pt=type;        break;      case VAT_AUDF_IDVI:        samples = (samples-4)*2;        rtp_hdr_send.pt=5;        break;      case VAT_AUDF_L16_16:      case VAT_AUDF_L16_44:      case VAT_AUDF_LPC4:      case VAT_AUDF_CELP:      case VAT_AUDF_LPC1:      case VAT_AUDF_UNDEF :

⌨️ 快捷键说明

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