⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jvoiprtptransmission.cpp

📁 使用VOIP进行网络传输声音的类库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	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 + -