apps/astreamer/rtp_stream.cpp

Go to the documentation of this file.
00001 #include <arpa/inet.h>
00002 #include <iostream>
00003 #include "rtp_stream.h"
00004 #include "helper.h"
00005 
00006 using namespace std;
00007 
00008 #define CNAME "elphel353"
00009 
00010 #undef RTP_DEBUG
00011 //#define RTP_DEBUG
00012 
00013 #ifdef RTP_DEBUG
00014         #define D(a) a
00015 #else
00016         #define D(a)
00017 #endif
00018 
00019 
00020 int RTP_Stream::_fd = -1;
00021 
00022 RTP_Stream::RTP_Stream(void) {
00023         _play = false;
00024         pthread_mutex_init(&pthm_flow, NULL);
00025         stream_name = "unknown";
00026 }
00027 
00028 void RTP_Stream::init_pthread(void *__this) {
00029         pth_id = pthread_create(&pth, NULL, RTP_Stream::pthread_f, (void *)__this);
00030 }
00031 
00032 void *RTP_Stream::pthread_f(void *_this) {
00033         RTP_Stream *__this = (RTP_Stream *)_this;
00034         return __this->thread();
00035 }
00036 
00037 void RTP_Stream::Start(string ip, int port) {
00038 D(cerr << " new " << stream_name << " UDP socket at port: " << port << endl;)
00039         rtp_socket = new Socket(ip, port, Socket::TYPE_UDP);
00040         rtcp_socket = new Socket(ip, port + 1, Socket::TYPE_UDP);
00041         rtp_packets = 0;
00042         rtp_octets = 0;
00043         rtcp_tv.tv_sec = 0;
00044         rtcp_tv.tv_usec = 0;
00045         rtcp_delay = 1000000;
00046         _play = true;
00047 }
00048 
00049 void RTP_Stream::Stop(void) {
00050 D(cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ <<endl;)
00051         pthread_mutex_lock(&pthm_flow);
00052         _play = false;
00053 //      delete rtcp_socket;
00054         delete rtp_socket;
00055         pthread_mutex_unlock(&pthm_flow);
00056 }
00057 
00067 void *RTP_Stream::thread(void) {
00068 D(      cerr << "RTP_Stream::thread(void)" <<endl;)
00069         for(;;) {
00070                 if(_play) {
00071                         pthread_mutex_lock(&pthm_flow);
00072                         long f = 0;
00073                         if(_play) {
00074                                 f = process();
00075                         }
00076                         if(f>0)
00077                                 rtcp();
00078                         pthread_mutex_unlock(&pthm_flow);
00079                         if (f<0) {
00080 D(  cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__<< "process exception detected: " << f << endl;)
00082                           Stop();
00083                         }
00084                 } else
00085                         sched_yield();
00086         }
00087         return NULL;
00088 }
00089 
00090 void RTP_Stream::rtcp(void) {
00091         // check time for next one RTCP...
00092         if(f_tv.tv_sec == 0 && f_tv.tv_usec == 0)
00093                 return;
00094         long td = time_delta_us(f_tv, rtcp_tv);
00095         if(td < 0) {
00096                 rtcp_tv = f_tv;
00097                 return;
00098         }
00099         if(td < rtcp_delay)
00100                 return;
00101         rtcp_tv = f_tv;
00102         rtcp_send_sdes();
00103         rtcp_send_sr();
00104 }
00105 
00106 void RTP_Stream::rtcp_send_sr(void) {
00107         char packet[8 + 20]; // by RTP RFC 3550, for SR RTCP packet needed 8 + 20 bytes
00108         int packet_len = sizeof(packet);
00109         unsigned short us;
00110         unsigned long ul;
00111 
00112         // RTCP header
00113         packet[0] = 0x81;
00114         packet[1] = 200;
00115         us = htons(((packet_len) / 4) - 1);
00116         memcpy((void *)&packet[2], (void *)&us, 2);
00117         memcpy((void *)&packet[4], (void *)&SSRC, 4);
00118         // SR
00119 char buf[64];
00120 sprintf(buf, "%d:%06d", (int) f_tv.tv_sec, (int) f_tv.tv_usec);
00121         ul = htonl(f_tv.tv_sec);
00122         memcpy((void *)&packet[8], (void *)&ul, 4);
00123         ul = htonl(f_tv.tv_usec);
00124         memcpy((void *)&packet[12], (void *)&ul, 4);
00125         ul = htonl(timestamp);
00126         memcpy((void *)&packet[16], (void *)&ul, 4);
00127         ul = htonl(rtp_packets);
00128         memcpy((void *)&packet[20], (void *)&ul, 4);
00129         ul = htonl(rtp_octets);
00130         memcpy((void *)&packet[24], (void *)&ul, 4);
00131         rtcp_socket->send(packet, packet_len);
00132 //cerr << "stream: " << stream_name << "; send SR; timestamp == " << timestamp << "; sync CLOCK == " << buf << endl;
00133         // fresh statistically information
00134 //      rtp_packets = 0;
00135 //      rtp_octets = 0;
00136 }
00137 
00138 void RTP_Stream::rtcp_send_sdes(void) {
00139         char packet[8 + 4 + 128]; // by RTP RFC 3550, for SDES RTCP packet needed 8 + 4 + ... bytes, so get additional 128 bytes for 126 CNAME field
00140         int packet_len = 0;
00141 
00142         unsigned short us;
00143         const char *cname = CNAME;
00144         int cname_len = strlen(cname);
00145         // RTCP header
00146         packet[0] = 0x81;
00147         packet[1] = 202;
00148         memcpy((void *)&packet[4], (void *)&SSRC, 4);
00149         packet_len += 8;
00150         // SDES fields
00151         packet[8] = 0x01;
00152         packet[9] = cname_len;
00153         memcpy((void *)&packet[10], (void *)cname, cname_len);
00154         packet_len += 2 + cname_len;
00155         us = htons((packet_len / 4) - 1);
00156         memcpy((void *)&packet[2], (void *)&us, 2);
00157 
00158         rtcp_socket->send(packet, packet_len);
00159 }

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1