output_rtp.c
来自「this ebook is for GSM if any one has int」· C语言 代码 · 共 283 行
C
283 行
#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <time.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include "output.h"#include "simplebuffer.h"#include "socket.h"#if 0static inline void sout_send_tsp_rtp(struct stream_s *s, uint8_t *tsp) {}static void sout_sock_read(int fd, short event, void *arg) { struct stream_s *s=arg; ssize_t size; struct sockaddr_in sin; socklen_t sinlen=sizeof(struct sockaddr_in); size=recvfrom(fd, s->ctlbuf, MAX_CTL_MSG_SIZE, 0, (struct sockaddr *) &sin, &sinlen); sout_parse_rtcp(s, s->ctlbuf, size, &sin);}static int sout_init_socket(struct stream_s *s) { struct sockaddr_in sin; memset(&sin, 0, sizeof(struct sockaddr_in)); s->sockfd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); sin.sin_port=htons(s->port); sin.sin_family=AF_INET; sin.sin_addr.s_addr=s->groupinaddr.s_addr; if (s->dist == STREAM_DIST_LISTEN) { /* Open control aka RTCP socket. I reverse engineered * that this is group socket + 1 */ s->ctlfd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); sin.sin_port=htons(s->port+1); bind(s->ctlfd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)); /* Add callback for packet receiption on control socket e.g. RTCP */ event_set(&s->ctlevent, s->ctlfd, EV_READ|EV_PERSIST, sout_sock_read, s); event_add(&s->ctlevent, NULL); } else { /* MCAST - Set destination */ connect(s->sockfd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)); if (s->dist == STREAM_DIST_MCAST) { /* * Set socket TTL - Be warned - I DoSed a Cisco 5500 RSM by sending * a 60MBit/s stream in 14 Groups all with TTL of 1 and the switch * went to lala land. It seems dropping MCAST traffic is very expensive * in IOS 12.1 land and its even dropped in Layer 3 instead of Layer 2 although * nobody expects ICMP "TTL expired" for MCAST traffic * */ setsockopt(s->sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)); } } return 1;}#endifint output_rtp_new_receiver(struct output_s *o, char *addr, int port, uint32_t ssrc) { struct rtp_receiver_s *r; r=calloc(1, sizeof(struct rtp_receiver_s)); /* Copy address and port */ r->addr=strdup(addr); r->port=port; r->ssrc=ssrc; r->lastrr=time(NULL); /* Create sockaddr_in struct for later sendmsg */ r->sin.sin_family=AF_INET; inet_aton(r->addr, &r->sin.sin_addr); r->sin.sin_port=htons(r->port); r->sinlen=sizeof(struct sockaddr_in); /* Prepend receiver to receiver list */ r->next=o->rtpreceiver; o->rtpreceiver=r; /* We want to receive packets */ o->receiver++; return 0;}#if 0static struct rtp_receiver_s *output_rtp_find_rtpr(struct output_s *o, uint32_t ssrc) { struct rtp_receiver_s *r; for(r=o->rtpreceiver;r;r=r->next) if (r->ssrc == ssrc) return r; return NULL;}static void output_rtp_free_rtpr(struct output_s *o, uint32_t ssrc) { struct rtp_receiver_s *r, *lr; for(r=o->rtpreceiver,lr=NULL;r;r=r->next) { if (r->ssrc == ssrc) { if (lr) lr->next=r->next; free(r); return; } lr=r; }}static void output_rtp_parse_rtcp(struct output_s *o, uint8_t *b, int len, struct sockaddr_in *sin) { struct rtp_receiver_s *r; uint32_t ssrc; logwrite(LOG_DEBUG, "streamrtp: got rtcp packet version %d\n", RTCP_VERSION(b)); /* Version 2 ? */ if (RTCP_VERSION(b) != 2) return; /* Get SSRC from RTCP packet */ ssrc=b[3]<<24 | b[4]<<16 | b[5]<<8 | b[6]; switch(RTCP_PT(b)) { case(RTP_PT_RR): logwrite(LOG_DEBUG, "streamrtp: Got Receiver Report size %d from %s ssrc %08x\n", len, inet_ntoa(sin->sin_addr), ssrc); r=output_rtp_find_rtpr(o, ssrc); if (!r) { logwrite(LOG_INFO, "streamrtp: Createing new RTP Receiver %08x\n", ssrc); output_rtp_new_receiver(o, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)-1, ssrc); } else { /* Store last RR timestamp */ r->lastrr=time(NULL); } break; case(RTP_PT_BYE): logwrite(LOG_INFO, "streamrtp: Got Bye size %d from %s ssrc %08x\n", len, inet_ntoa(sin->sin_addr), ssrc); /* Find receiver struct */ output_rtp_free_rtpr(o, ssrc); break; }}static void output_rtp_read_rtcp(int fd, short event, void *arg) { struct output_s *o=arg; ssize_t size; struct sockaddr_in sin; socklen_t sinlen=sizeof(struct sockaddr_in); size=recvfrom(fd, o->rtcpbuffer, RTCP_BUFFER_SIZE, 0, (struct sockaddr *) &sin, &sinlen); logwrite(LOG_DEBUG, "streamrtp: got packet size %d\n", size); output_rtp_parse_rtcp(o, o->rtcpbuffer, size, &sin);}static void output_init_rtp_rtcp(struct output_s *o) { struct sockaddr_in sin; /* Allocate the RTCP incoming packet buffer */ o->rtcpbuffer=malloc(RTCP_BUFFER_SIZE); memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(o->rtcpport); /* Create a socket and bind */ o->rtcpfd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); bind(o->rtcpfd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)); /* Install rtcp callback */ event_set(&o->rtcpevent, o->rtcpfd, EV_READ|EV_PERSIST, output_rtp_read_rtcp, o); event_add(&o->rtcpevent, NULL);}#endifint output_init_rtp(struct output_s *o) { o->sockfd=socket_open(o->localaddr, 0); if (o->sockfd < 0) return -1; socket_set_nonblock(o->sockfd); socket_set_ttl(o->sockfd, o->ttl); /* Join multicast group if its a multicast address */ socket_join_multicast(o->sockfd, o->remoteaddr), /* Do you have a better idea ? */ o->rtpssrc=(uint32_t) random(); o->buffer=sb_init(RTP_MAX_TS, TS_PACKET_SIZE, RTP_HEADROOM); output_rtp_new_receiver(o, o->remoteaddr, o->remoteport, 0); return 0;}void output_send_rtp(struct output_s *o, uint8_t *tsp) { sb_add_atoms(o->buffer, tsp, 1); /* check whether another packet would fit ? */ if (!sb_free_atoms(o->buffer)) { struct rtp_receiver_s *r; struct timeval tv; long msec; uint8_t *b=sb_bufptr(o->buffer); gettimeofday(&tv, (struct timezone *) NULL); msec=(tv.tv_sec%1000000)*1000 + tv.tv_usec/1000; b[RTP_VERSION_OFF] = 0x80; b[RTP_PT_OFF] = RTP_PT_MP2T; /* RFC 2250 */ b[RTP_SEQ_OFF] = o->rtpseq >> 8 & 0xff; b[RTP_SEQ_OFF+1] = o->rtpseq & 0xff; b[RTP_TSTAMP_OFF] = msec>>24 & 0xff; b[RTP_TSTAMP_OFF+1] = msec>>16 & 0xff; b[RTP_TSTAMP_OFF+2] = msec>>8 & 0xff; b[RTP_TSTAMP_OFF+3] = msec & 0xff; b[RTP_SSRC_OFF] = o->rtpssrc>>24 & 0xff; b[RTP_SSRC_OFF+1] = o->rtpssrc>>16 & 0xff; b[RTP_SSRC_OFF+2] = o->rtpssrc>>8 & 0xff; b[RTP_SSRC_OFF+3] = o->rtpssrc & 0xff; for(r=o->rtpreceiver;r;r=r->next) { int len; len=sendto(o->sockfd, sb_bufptr(o->buffer), sb_buflen(o->buffer), MSG_DONTWAIT, (struct sockaddr *) &r->sin, r->sinlen); } sb_zap(o->buffer); o->rtpseq++; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?