| 1157 | |
| 1158 | |
| 1159 | GSM::AudioFrame *SipRtp::rxFrame() |
| 1160 | { |
| 1161 | if(getSipState()!=Active) { |
| 1162 | LOG(DEBUG) <<"skip"<<LOGVAR(getSipState()); |
| 1163 | return 0; |
| 1164 | } |
| 1165 | int more = 0; |
| 1166 | |
| 1167 | // The buffer size is: |
| 1168 | // For GSM, 260 bits + 4 bit header is 33 bytes. |
| 1169 | // For TFO (3GPP 28.062 5.2.2) is 40 bytes. |
| 1170 | // For AMR 'compact transport format', variable size, max is 244 bits + 10 bit header?? |
| 1171 | // (pat) We will not support TFO for years, if ever. |
| 1172 | // TODO: Make the rxFrame buffer big enough (160?) for G.711. But we dont support that yet. |
| 1173 | const int maxsize = 33; |
| 1174 | |
| 1175 | // (pat 8-2013) I tried rtp_session_get_current_recv_ts but it just doesnt work; returns garbage. |
| 1176 | // It is frightening how much we depend on the extremely buggy RTP library. |
| 1177 | //uint32_t suggestedRxTime = rtp_session_get_current_recv_ts(mSession); |
| 1178 | |
| 1179 | // (pat 8-2013) The RTP library has a scheduling mode and a blocking mode whereby it blocks the thread |
| 1180 | // until the specified time has elapsed, which is 20ms. |
| 1181 | // But after a discontinuity in the send data stream the RTP scheduler seems to get confused and rxFrame |
| 1182 | // returns 0 for long periods of time. |
| 1183 | // A discontinuity can be artificially generated at the time of writing using an in-call-SMS, |
| 1184 | // which currently blocks TCH while the current thread runs SACCH, a bug to be fixed, |
| 1185 | // however discontinuities could occur for other reasons so the code should not break when one occurs. |
| 1186 | // I added this code controlled by rtpUseRealTime so we could handle the real elapsed time ourselves and not block. |
| 1187 | // This code below suffers no such instability, so we are using it. Someday if we switch RTP libraries, |
| 1188 | // someone can try turning off rtpUseRealTime - but you have to TEST DISCONTINUITIES, which is hard, |
| 1189 | // so dont just turn this off, try a test call, and pronounce it fixed. |
| 1190 | if (rtpUseRealTime) { |
| 1191 | struct timeval tv; |
| 1192 | gettimeofday(&tv,NULL); |
| 1193 | uint64_t realTime = (uint64_t)tv.tv_sec * (1000 * 1000) + (uint64_t)tv.tv_usec; // time in usecs. |
| 1194 | if (mRxRealTime == 0) { |
| 1195 | // First time, init for next pass through... |
| 1196 | devassert(mRxTime == 0); |
| 1197 | mRxRealTime = realTime; |
| 1198 | } else { |
| 1199 | uint64_t delay = realTime - mRxRealTime; // total elapsed time in usecs. |
| 1200 | uint64_t delayInFrames = delay / (1000 * 20); // 20ms per frame // elapsed time in frames. |
| 1201 | unsigned proposedRxTime = delayInFrames * 160; // elapsed time in RTP 'time' units. (160 / 8000 bitrate == 20 msecs) |
| 1202 | LOG(DEBUG) << format("realTime=%.3f delay=%.3f delayInFrames=%u RxTime=%u proposed=%u", |
| 1203 | realTime/1e6,delay/1e6,(unsigned)delayInFrames,mRxTime,proposedRxTime); |
| 1204 | if (proposedRxTime <= mRxTime) { |
| 1205 | LOG(DEBUG) <<"skip, insufficient time passed"; |
| 1206 | return NULL; |
| 1207 | } |
| 1208 | // We will snag the next frame with a number equal or higher than this. If there are none available, we get NULL. |
| 1209 | // When there is a discontinuity of missing frames, we get a bunch of NULL frames during the discontinuity, then |
| 1210 | // things pick up normally again. |
| 1211 | mRxTime += 160; |
| 1212 | } |
| 1213 | } |
| 1214 | |
| 1215 | GSM::AudioFrame *result = new GSM::AudioFrame(maxsize); // Make it big enough for anything we might support. |
| 1216 | int ret = rtp_session_recv_with_ts(mSession, result->begin(), maxsize, mRxTime, &more); |
nothing calls this directly
no test coverage detected