CSL  5.2
RtpReceiver.cpp
Go to the documentation of this file.
1 //
2 // RtpReceiver.cpp -- a unit generator that listens on an RTP socket for incoming audio buffers.
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "RtpReceiver.h"
7 
8 using namespace csl;
9 
10 #ifdef RTP_TIMING
11 static struct timeval then, now; // used for getting the real time
12 static long timeVals, thisSec, timeSum; // for printing run-time statistics
13 #endif
14 
15 // RtpReceiver Constructor: socket-code heavy lifting
16 // Open up a remote frame stream using a socket to the given remote "server" ip/host
17 
19  : mNumChans(chans),
20  mBufferFrames(RTP_BUFFER_SIZE),
21  CslRtpSession(mNumChans, mBufferFrames),
22  mRtpMutex()
23 {
24 // The constructor should set up all of the transmission and session params, but
25 // should not do anything related to specific addresses
26 
27  // Create instances of our RTP classes
28  mTransparams = new RTPUDPv4TransmissionParams;
29  mSessparams = new RTPSessionParams;
30 
31 #ifdef CSL_WINDOWS
32  //MUST call WSAStartup() to use WS2_32.DLL
33  WSADATA wsaData;
34  if (WSAStartup(MAKEWORD( 2, 2 ), &wsaData)!= 0) //WSACleanup called in destructor
35  perror("Couldn't do WSAStartup");
36 #endif
37 
38  // create the RTP session, but don't add any destinations yet
39  // Note that this also creates the thread that polls for incoming RTP packets
40  if (!createRtpSession()) goto error;
41 
42  return;
43 error:
44  logMsg(kLogError, "RtpReceiver init error");
45  return;
46 }
47 
48 // Destructor
49 
51 
52  BYEDestroy(RTPTime(10,0),0,0); // Destroy the RTP session (wait 10 seconds for acknowledgement)
53 
54  if (mTransparams) delete mTransparams;
55  if (mSessparams) delete mSessparams;
56  if (mAddress) delete mAddress;
57 
58  #ifdef CSL_WINDOWS
59  WSACleanup(); // Must be called because WSAStartup() called in class constructor
60  #endif
61 }
62 
64 
65  mSessparams->SetOwnTimestampUnit(1.0/mFrameRate); // Our timestamp is 1/Fs
66  mSessparams->SetUsePollThread(TRUE); // This is the default behavior, but let's be verbose
67 
68 <<<<<<< RtpReceiver.cpp
69  mRtpSession->SetDefaultPayloadType(11); // Default payload is a mono 16/44.1 stream (type 11)
70  mRtpSession->SetDefaultMark(false); // Sets the default marker to false
71  mRtpSession->SetDefaultTimestampIncrement((unsigned) (CGestalt::frameRate() * 0.020)); // Default is 20 ms of samples per packet
72 =======
73  SetDefaultPayloadType(11); // Default payload is a mono 16/44.1 stream (type 11)
74  SetDefaultMark(false); // Sets the default marker to false
75  SetDefaultTimestampIncrement(CGestalt::frameRate() * 0.020); // Default is 20 ms of samples per packet
76 >>>>>>> 1.5
77 
78  mTransparams->SetPortbase(mLocalPort);
79  int status = Create(*mSessparams,mTransparams);
80  printError(status);
81  return true;
82 }
83 
84 bool RtpReceiver :: addRtpSource(char * remoteIP, unsigned short remotePort) {
85 
86  mAddress = new RTPIPv4Address;
87 
88  // The inet_addr function returns a value in network byte order, but
89  // we need the IP address in host byte order, so we use a call to
90  // ntohl
91  mRemoteIP = inet_addr(remoteIP);
92  mRemoteIP = ntohl(mRemoteIP);
93 
94  // Storing passed parameters to class members
96 
97  // Set the IP and port of the address we receive data from
98  mAddress->SetIP(mRemoteIP);
99  mAddress->SetPort(mRemotePort);
100 
101  int status = AddDestination(*mAddress); // Adds a destination to the RTP stream (potential for multicasting)
102  printError(status);
103  return true;
104 }
105 
107  // Destroy the RTP session, say bye to the server
108  DeleteDestination(*mAddress);
109  return true;
110 }
111 
112 void RtpReceiver:: printError(int rtperr)
113 {
114  if (rtperr < 0)
115  {
116  string errStr = "Error: " + RTPGetErrorString(rtperr) + "\n";
117 
118  // We need to convert the string to a char * before passing
119  // it to logMsg...
120  char * logStr = new char[errStr.length()+1];
121  strcpy(logStr, errStr.c_str());
122 
123  logMsg(kLogError, logStr);
124  exit(-1);
125  }
126 }
127 
128 //// nextBuffer method -- copy data and signal the semaphore when you need more ////
129 // TODO: This should actually deal with multi-channel nextBuffer calls, and support multi-channel RTP
130 
131 void RtpReceiver :: nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (Exception)
132 {
133  float * outputBufferPtr = outputBuffer.monoBuffer(outBufNum);
134  unsigned char * out, * buf;
135  unsigned numFramesRequested = outputBuffer.mNumFrames;
136  unsigned toCopy; // # of bytes to copy per channel
137  unsigned offset;
138 
139  mRtpMutex.lock();
140 
141  // TODO: multiple channels
142 
143  if (mBufferState == kBuffering) { // If we haven't started playback yet (still buffering from an underrun)
144  memset(outputBufferPtr, 0, numFramesRequested * sizeof(sample)); // Fill outBuf with zeroes
145  mRtpMutex.unlock();
146  return;
147  }
148 
149  // Read the next part of rBuff ring buffer into outputBuffer
150  mRtpBuffer.nextBuffer(outputBuffer);
151  mRtpMutex.unlock();
152 
153  return;
154 }