00001 // rtphello 00002 // A very simple program for testing and illustrating basic features of ccRTP. 00003 // Copyright (C) 2001,2002 Federico Montesino <fedemp@altern.org> 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 00020 // This is an introductory example file that illustrates basic usage 00021 // of ccRTP. You will also see a bit on how to use other classes from 00022 // CommonC++. 00023 00024 // I am a typical hello world program. I consist of a sender thread, 00025 // that sends the salutation message on RTP packets; and a receiver 00026 // thread, that prints the messages. This is a program with an unsual 00027 // structure, the receiver just tries to process the first available 00028 // packet periodically, and both are in the same program. Thus, it 00029 // should not be seen as an example for typical applications but as a 00030 // test of some functions of ccRTP. 00031 00032 #include <cstdio> 00033 #include <ctime> 00034 // In order to use ccRTP, the RTP stack of CommonC++, just include... 00035 #include <ccrtp/rtp.h> 00036 00037 #ifdef CCXX_NAMESPACES 00038 using namespace ost; 00039 using namespace std; 00040 #endif 00041 00042 // base ports 00043 const int RECEIVER_BASE = 33634; 00044 const int TRANSMITTER_BASE = 32522; 00045 00046 // For this example, this is irrelevant. 00047 //const int TIMESTAMP_RATE = 90000; 00048 00053 class ccRTP_Hello_Rx: public Thread 00054 { 00055 00056 private: 00057 // socket to receive packets 00058 RTPSession *socket; 00059 // loopback network address 00060 InetHostAddress local_ip; 00061 // identifier of this sender 00062 uint32 ssrc; 00063 00064 public: 00065 ccRTP_Hello_Rx(){ 00066 // Before using ccRTP you should learn something about other 00067 // CommonC++ classes. We need InetHostAddress... 00068 00069 // Construct loopback address 00070 local_ip = "127.0.0.1"; 00071 00072 // Is that correct? 00073 if( ! local_ip ){ 00074 // this is equivalent to `! local_ip.isInetAddress()' 00075 cerr << "Rx: IP address is not correct!" << endl; 00076 exit(); 00077 } 00078 00079 // create socket for RTP connection and get a random 00080 // SSRC identifier 00081 socket = new RTPSession(local_ip,RECEIVER_BASE); 00082 ssrc = socket->getLocalSSRC(); 00083 } 00084 00085 ~ccRTP_Hello_Rx(){ 00086 cout << endl << "Destroying receiver -ID: " << hex 00087 << (int)ssrc; 00088 terminate(); 00089 delete socket; 00090 cout << "... " << "destroyed."; 00091 } 00092 00093 // This method does almost everything. 00094 void run(void){ 00095 00096 cout << "Hello, " << defaultApplication(). 00097 getSDESItem(SDESItemTypeCNAME) 00098 << " ..." << endl; 00099 // redefined from Thread. 00100 // Set up connection 00101 socket->setSchedulingTimeout(20000); 00102 socket->setExpireTimeout(3000000); 00103 //socket->UDPTransmit::setTypeOfService(SOCKET_IPTOS_LOWDELAY); 00104 if( !socket->addDestination(local_ip,TRANSMITTER_BASE) ) 00105 cerr << "Rx (" << hex << (int)ssrc 00106 << "): could not connect to port." 00107 << TRANSMITTER_BASE; 00108 00109 cout << "Rx (" << hex << (int)ssrc 00110 << "): " << local_ip.getHostname() 00111 << " is waiting for salutes in port " 00112 << RECEIVER_BASE << "..." << endl; 00113 00114 socket->setPayloadFormat(StaticPayloadFormat(sptMP2T)); 00115 socket->startRunning(); 00116 // Let's check the queues (you should read the documentation 00117 // so that you know what the queues are for). 00118 cout << "Rx (" << hex << (int)ssrc 00119 << "): The queue is " 00120 << ( socket->isActive() ? "" : "in") 00121 << "active." << endl; 00122 00123 // This is the main loop, where packets are received. 00124 for( int i = 0 ; true ; i++ ){ 00125 00126 // Wait for an RTP packet. 00127 const AppDataUnit *adu = NULL; 00128 while ( NULL == adu ) { 00129 Thread::sleep(10); 00130 adu = socket->getData(socket->getFirstTimestamp()); 00131 } 00132 00133 // Print content (likely a salute :)) 00134 // Note we are sure the data is an asciiz string. 00135 time_t receiving_time = time(NULL); 00136 char tmstring[30]; 00137 strftime(tmstring,30,"%X",localtime(&receiving_time)); 00138 cout << "Rx (" << hex << (int)ssrc 00139 << "): [receiving at " << tmstring << "]: " 00140 << adu->getData() << endl; 00141 delete adu; 00142 } 00143 } 00144 }; 00145 00150 class ccRTP_Hello_Tx: public Thread, public TimerPort 00151 { 00152 00153 private: 00154 // socket to transmit 00155 RTPSession *socket; 00156 // loopback network address 00157 InetHostAddress local_ip; 00158 // identifier of this sender 00159 uint32 ssrc; 00160 00161 public: 00162 ccRTP_Hello_Tx(){ 00163 // Before using ccRTP you should learn something about other 00164 // CommonC++ classes. We need InetHostAddress... 00165 00166 // Construct loopback address 00167 local_ip = "127.0.0.1"; 00168 00169 // Is that correct? 00170 if( ! local_ip ){ 00171 // this is equivalent to `! local_ip.isInetAddress()' 00172 cerr << "Tx: IP address is not correct!" << endl; 00173 exit(); 00174 } 00175 00176 socket = new RTPSession(local_ip,TRANSMITTER_BASE); 00177 ssrc = socket->getLocalSSRC(); 00178 } 00179 00180 ~ccRTP_Hello_Tx(){ 00181 cout << endl << "Destroying transmitter -ID: " << hex 00182 << (int)ssrc; 00183 terminate(); 00184 delete socket; 00185 cout << "... " << "destroyed."; 00186 } 00187 00188 // This method does almost everything. 00189 void run(void){ 00190 // redefined from Thread. 00191 cout << "Tx (" << hex << (int)ssrc << "): " << 00192 local_ip.getHostname() 00193 << " is going to salute perself through " 00194 << local_ip << "..." << endl; 00195 00196 // Set up connection 00197 socket->setSchedulingTimeout(20000); 00198 socket->setExpireTimeout(3000000); 00199 if( !socket->addDestination(local_ip,RECEIVER_BASE) ) 00200 cerr << "Tx (" << hex << (int)ssrc 00201 << "): could not connect to port." 00202 << RECEIVER_BASE; 00203 00204 cout << "Tx (" << hex << (int)ssrc << 00205 "): Transmitting salutes to port " 00206 << RECEIVER_BASE << "..." << endl; 00207 00208 uint32 timestamp = 0; 00209 // This will be useful for periodic execution 00210 TimerPort::setTimer(1000); 00211 00212 // This is the main loop, where packets are sent. 00213 socket->setPayloadFormat(StaticPayloadFormat(sptMP2T)); 00214 socket->startRunning(); 00215 // Let's check the queues (you should read the documentation 00216 // so that you know what the queues are for). 00217 cout << "Tx (" << hex << (int)ssrc << "): The queue is " 00218 << ( socket->isActive()? "" : "in") 00219 << "active." << endl; 00220 00221 for( int i = 0 ; true ;i++ ){ 00222 00223 // send RTP packets, providing timestamp, 00224 // payload type and payload. 00225 // construct salute. 00226 unsigned char salute[50]; 00227 snprintf((char *)salute,50, 00228 "Hello, brave gnu world (#%u)!",i); 00229 time_t sending_time = time(NULL); 00230 // get timestamp to send salute 00231 if ( 0 == i ){ 00232 timestamp = socket->getCurrentTimestamp(); 00233 00234 } else { 00235 // increment for 1 second 00236 timestamp += socket->getCurrentRTPClockRate(); 00237 } 00238 00239 socket->putData(timestamp,salute, 00240 strlen((char *)salute)+1); 00241 // print info 00242 char tmstring[30]; 00243 strftime(tmstring,30,"%X", 00244 localtime(&sending_time)); 00245 cout << "Tx (" << hex << (int)ssrc 00246 << "): sending salute " << "no " << dec << i 00247 << ", at " << tmstring 00248 << "..." << endl; 00249 00250 // Let's wait for the next cycle 00251 Thread::sleep(TimerPort::getTimer()); 00252 TimerPort::incTimer(1000); 00253 } 00254 } 00255 }; 00256 00257 int main(int argc, char *argv[]) 00258 { 00259 00260 // Construct the two main threads. they will not run yet. 00261 ccRTP_Hello_Rx *receiver = new ccRTP_Hello_Rx; 00262 ccRTP_Hello_Tx *transmitter = new ccRTP_Hello_Tx; 00263 00264 cout << "This is rtphello, a very simple test program for ccRTP." << 00265 endl << "Strike [Enter] when you are fed up with it." << endl; 00266 00267 // Start execution of hello now. 00268 receiver->start(); 00269 transmitter->start(); 00270 00271 cin.get(); 00272 00273 delete transmitter; 00274 delete receiver; 00275 00276 cout << endl << "That's all." << endl; 00277 00278 return 0; 00279 } 00280