📄 jvoiprtptransmission.cpp
字号:
jitter = srcdat->INF_GetJitter(); // Retrieve participant info partinf = GetParticipantInfo(ssrc); if (partinf == NULL) // participant NOT found, ignore data { vb->Clear(); delete pack; return 0; } // set jitter info curtime = time(NULL); if (partinf->prevjittertime == 0 || (curtime - partinf->prevjittertime) > JVOIPRTPTRANS_JITTERADJUSTINTERVAL) { partinf->prevjittertime = curtime; partinf->lastknownjitter = jitter; } // Check if we have already processed this packet packnum = 0; if (!partinf->isnewsource) { while (pack && AlreadyProcessedPacket(pack,partinf,&packnum)) { numbytesreceived += pack->GetPayloadLength() + JVOIPRTPTRANS_HEADEROVERHEAD; delete pack; pack = rtpsess->GetNextPacket(); } if (!pack) { vb->Clear(); return 0; } } // Ok, now we have a packet we may process, so we'll process it :-) if (!FillInVoiceBlock(vb,pack,partinf)) { vb->Clear(); delete pack; return 0; } // set info for new participants if (partinf->isnewsource) { partinf->isnewsource = false; partinf->lastknownjitter = jitter; // NOTE: this value is set again in case the participant info was cleared AlreadyProcessedPacket partinf->samplingrate = vb->GetSampleRate(); partinf->buffering = (VoIPFramework::VOIPdouble)defaultbuffer; partinf->basepacknum = pack->GetExtendedSequenceNumber(); partinf->basetimestamp = pack->GetTimestamp(); partinf->basetimeoffset = cursampleoffset; vb->SetSampleOffset(cursampleoffset+defaultbuffer); // store the timestamp unit: this is needed for accurate // jitter calculations. double tsunit; tsunit = 1.0/((double)vb->GetSampleRate()); srcdat->SetTimestampUnit(tsunit); } else { if (!CalculateTimeOffset(vb,pack,partinf,&offset)) { vb->Clear(); delete pack; return 0; } else vb->SetSampleOffset(offset); } // add the packet number-offset pair to the list it = partinf->receivedpacknums.begin(); while (it != partinf->receivedpacknums.end() && packnum > (*it).packnum) ++it; if (it == partinf->receivedpacknums.end()) partinf->receivedpacknums.push_back(PacknumOffsetPair(packnum,vb->GetSampleOffset())); else partinf->receivedpacknums.insert(it,PacknumOffsetPair(packnum,vb->GetSampleOffset())); delete pack; return 0;}bool JVOIPRTPTransmission::AlreadyProcessedPacket(RTPPacket *pack,JVOIPRTPTransmission::ParticipantInfo *partinf,VoIPFramework::VOIPuint64 *packetnumber){ bool found; std::list<PacknumOffsetPair>::iterator it; VoIPFramework::VOIPuint64 curpacknum,tmppacknum; unsigned long extpacknum; extpacknum = pack->GetExtendedSequenceNumber() - partinf->basepacknum; if (extpacknum > partinf->prevpacknum) { if ((extpacknum - partinf->prevpacknum) > JVOIPRTPTRANS_MAXPACKDIST) { if ((partinf->prevpacknum - extpacknum) <= JVOIPRTPTRANS_MAXPACKDIST) { if (partinf->packnumcycles == 0) { // in this case, we have to ignore the packet! return true; } else { curpacknum = (partinf->packnumcycles-1); curpacknum <<= 32; tmppacknum = extpacknum; curpacknum |= tmppacknum; } } else { // packet number out of range if ( ++(partinf->packnumoutrangecount) >= JVOIPRTPTRANS_MAXPACKOUTRANGECOUNT) { // reset connection for this participant and assume this packet // is the first one received partinf->ClearAllPublicFields(); *packetnumber = 0; return false; } } } else { curpacknum = partinf->packnumcycles; curpacknum <<= 32; tmppacknum = extpacknum; curpacknum |= tmppacknum; } } else if (extpacknum < partinf->prevpacknum) { if ((extpacknum - partinf->prevpacknum) > JVOIPRTPTRANS_MAXPACKDIST) { if ((partinf->prevpacknum - extpacknum) <= JVOIPRTPTRANS_MAXPACKDIST) { curpacknum = partinf->packnumcycles; curpacknum <<= 32; tmppacknum = extpacknum; curpacknum |= tmppacknum; } else { // packet number out of range if ( ++(partinf->packnumoutrangecount) >= JVOIPRTPTRANS_MAXPACKOUTRANGECOUNT) { // reset connection for this participant and assume this packet // is the first one received partinf->ClearAllPublicFields(); *packetnumber = 0; return false; } } } else { partinf->packnumcycles++; curpacknum = partinf->packnumcycles; curpacknum <<= 32; tmppacknum = extpacknum; curpacknum |= tmppacknum; } } else // same ext packet number as previous packet number return true; partinf->prevpacknum = extpacknum; *packetnumber = curpacknum; // search the participant's list for this packet number it = partinf->receivedpacknums.begin(); found = false; while (!found && it != partinf->receivedpacknums.end() && (*it).packnum <= curpacknum) { if ((*it).packnum == curpacknum) found = true; else ++it; } return found;}bool JVOIPRTPTransmission::FillInVoiceBlock(VoIPFramework::VoiceBlock *vb,RTPPacket *pack,ParticipantInfo *partinf){ // set some default values vb->Clear(); vb->SetIsSilence(false); if (pack->GetPayloadType() != JVOIPRTPTRANS_JVOIPPAYLOADTYPE) { // check specific encodings unsigned char *data; int len; len = pack->GetPayloadLength(); switch(pack->GetPayloadType()) { case JVOIPRTPTRANS_PAYLOADTYPE_PCMU: vb->SetSampleRate(8000); vb->SetNumSamples(len); vb->SetMajorCompressionID(JVOIPCOMPRESSIONTYPE_MAJOR_ULAWCOMPRESSION); break; case JVOIPRTPTRANS_PAYLOADTYPE_GSM: vb->SetSampleRate(8000); vb->SetNumSamples(160); vb->SetMajorCompressionID(JVOIPCOMPRESSIONTYPE_MAJOR_GSMCOMPRESSION); break; case JVOIPRTPTRANS_PAYLOADTYPE_LPC: vb->SetSampleRate(8000); vb->SetNumSamples(160); vb->SetMajorCompressionID(JVOIPCOMPRESSIONTYPE_MAJOR_LPCCOMPRESSION); break; default: return false; } data = new unsigned char[len]; if (data == NULL) // out of memory return false; memcpy(data,pack->GetPayloadData(),len); vb->SetSamples(data,len); } else { unsigned char *data,infobyte,*samples; int pos,len; bool has3dinfo; data = pack->GetPayloadData(); len = pack->GetPayloadLength(); if (len <= 0) return false; pos = 0; infobyte = data[pos++]; // test for 3D info if (infobyte & (1<<4)) has3dinfo = true; else has3dinfo = false; // test bytes per sample if (infobyte & (1<<5)) vb->SetBytesPerSample(2); // test samplingrate switch(infobyte & 0x0F) { case 0: vb->SetSampleRate(4000); break; case 1: vb->SetSampleRate(8000); break; case 2: vb->SetSampleRate(11025); break; case 3: vb->SetSampleRate(22050); break; case 4: vb->SetSampleRate(44100); break; default: return false; } // get 3D info if necessary if (has3dinfo) { int info3dlen; unsigned char *info3d; if (pos >= len) return false; info3dlen = (int)data[pos++]; if ((len-pos) < info3dlen) return false; info3d = new unsigned char[info3dlen]; if (info3d == NULL) // out of memory return false; memcpy(info3d,data+pos,info3dlen); vb->SetInfo3D(info3d,info3dlen); pos += info3dlen; } if ((len-pos) < 2) return false; // set compression info vb->SetMajorCompressionID((int)data[pos++]); vb->SetMinorCompressionID((int)data[pos++]); // the rest is the data itself if (pos >= len) return false; samples = new unsigned char[len-pos]; if (samples == NULL) return false; memcpy(samples,data+pos,len-pos); vb->SetSamples(samples,len-pos); } if (!partinf->isnewsource && (int)vb->GetSampleRate() != partinf->samplingrate) // sampling rate changed! { // reset this participants info partinf->ClearAllPublicFields(); return false; } return true;}bool JVOIPRTPTransmission::CalculateTimeOffset(VoIPFramework::VoiceBlock *vb,RTPPacket *pack,ParticipantInfo *partinf,VoIPFramework::VOIPdouble *offset){ VoIPFramework::VOIPuint64 samplenum,tmpnum; VoIPFramework::VOIPdouble timeoffset,jitterbuffer,addbuffer; unsigned long curtimestamp; curtimestamp = pack->GetTimestamp() - partinf->basetimestamp; if (curtimestamp > partinf->prevtimestamp) { if ((curtimestamp - partinf->prevtimestamp) > JVOIPRTPTRANS_MAXTSDIST) { if ((partinf->prevtimestamp - curtimestamp) <= JVOIPRTPTRANS_MAXTSDIST) { if (partinf->timestampcycles == 0) { // in this case, we have to ignore the packet! return false; } else { samplenum = (partinf->timestampcycles-1); samplenum <<= 32; tmpnum = curtimestamp; samplenum |= tmpnum; } } else { // timestamp out of range if ( ++(partinf->timestampoutrangecount) >= JVOIPRTPTRANS_MAXTSOUTRANGECOUNT) { // reset connection for this participant partinf->ClearAllPublicFields(); return false; } } } else { samplenum = partinf->timestampcycles; samplenum <<= 32; tmpnum = curtimestamp; samplenum |= tmpnum; } } else if (curtimestamp < partinf->prevtimestamp) { if ((curtimestamp - partinf->prevtimestamp) > JVOIPRTPTRANS_MAXTSDIST) { if ((partinf->prevtimestamp - curtimestamp) <= JVOIPRTPTRANS_MAXTSDIST) { samplenum = partinf->timestampcycles; samplenum <<= 32; tmpnum = curtimestamp; samplenum |= tmpnum; } else { // timestamp out of range if ( ++(partinf->timestampoutrangecount) >= JVOIPRTPTRANS_MAXTSOUTRANGECOUNT) { // reset connection for this participant partinf->ClearAllPublicFields(); return false; } } } else { partinf->timestampcycles++; samplenum = partinf->timestampcycles; samplenum <<= 32; tmpnum = curtimestamp; samplenum |= tmpnum; } } else // we already processed this packet return false;#ifdef WIN32 // Visual C++ 6 can't do the conversion from uint64 timeoffset = VoIPFramework::GetVOIPdouble(samplenum);#else timeoffset = (VoIPFramework::VOIPdouble)samplenum;#endif // WIN32 timeoffset /= ((VoIPFramework::VOIPdouble)partinf->samplingrate); // convert to seconds timeoffset += partinf->basetimeoffset; if (autoadjustbuffering) { // add buffering to compensate jitter jitterbuffer = (VoIPFramework::VOIPdouble)partinf->lastknownjitter; jitterbuffer *= 2.0; // buffer a bit more than the actual jitter jitterbuffer /= ((VoIPFramework::VOIPdouble)partinf->samplingrate); // convert to seconds addbuffer = jitterbuffer; // we must also buffer at least one sample interval, otherwise there might // be glitches if (addbuffer < interval) addbuffer += interval; } else addbuffer = defaultbuffer; if (addbuffer < minimbuffer) addbuffer = minimbuffer; timeoffset += addbuffer; // allow packets within a one second delay: // if it's large enough, something might still be played back // ideally, we should know the amount of samples in a packet, but because the // data is possibly compressed, this information is not available at this point if (timeoffset < (cursampleoffset - 1.0)) { if ( ++(partinf->timestampoutrangecount) >= JVOIPRTPTRANS_MAXTSOUTRANGECOUNT) { // reset connection for this participant partinf->ClearAllPublicFields(); } return false; } else if (timeoffset < cursampleoffset) { // Here, we'll still let the block pass, but we do have to increment // the timestampoutrange count. Otherwise, if the timestamp keeps // ending up in the 1 second range used above, and the block does // not contain enough information (more than 1 sec), it is possible // that nothing will be played back from this source: the mixer // will discard all packets... if ( ++(partinf->timestampoutrangecount) >= JVOIPRTPTRANS_MAXTSOUTRANGECOUNT) { // reset connection for this participant partinf->ClearAllPublicFields(); return false; } } *offset = timeoffset; return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -