// The following function should delete rtppack if necessary int RTPInternalSourceData::ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored) { bool accept,onprobation,applyprobation; double tsunit; *stored = false; if (timestampunit < 0) tsunit = INF_GetEstimatedTimestampUnit(); else tsunit = timestampunit; #ifdef RTP_SUPPORT_PROBATION if (validated) // If the source is our own process, we can already be validated. No applyprobation = false; // probation should be applied in that case. else { if (probationtype == RTPSources::NoProbation) applyprobation = false; else applyprobation = true; } #else applyprobation = false; #endif // RTP_SUPPORT_PROBATION stats.ProcessPacket(rtppack,receivetime,tsunit,ownssrc,&accept,applyprobation,&onprobation); #ifdef RTP_SUPPORT_PROBATION switch (probationtype) { case RTPSources::ProbationStore: if (!(onprobation || accept)) return 0; if (accept) validated = true; break; case RTPSources::ProbationDiscard: case RTPSources::NoProbation: if (!accept) return 0; validated = true; break; default: return ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE; } #else if (!accept) return 0; validated = true; #endif // RTP_SUPPORT_PROBATION; if (validated && !ownssrc) // for own ssrc these variables depend on the outgoing packets, not on the incoming issender = true; // Now, we can place the packet in the queue if (packetlist.empty()) { *stored = true; packetlist.push_back(rtppack); return 0; } if (!validated) // still on probation { // Make sure that we don't buffer too much packets to avoid wasting memory // on a bad source. Delete the packet in the queue with the lowest sequence // number. if (packetlist.size() == RTPINTERNALSOURCEDATA_MAXPROBATIONPACKETS) { RTPPacket *p = *(packetlist.begin()); packetlist.pop_front(); RTPDelete(p,GetMemoryManager()); } } // find the right position to insert the packet std::list<RTPPacket*>::iterator it,start; bool done = false; uint32_t newseqnr = rtppack->GetExtendedSequenceNumber(); it = packetlist.end(); --it; start = packetlist.begin(); while (!done) { RTPPacket *p; uint32_t seqnr; p = *it; seqnr = p->GetExtendedSequenceNumber(); if (seqnr > newseqnr) { if (it != start) --it; else // we're at the start of the list { *stored = true; done = true; packetlist.push_front(rtppack); } } else if (seqnr < newseqnr) // insert after this packet { ++it; packetlist.insert(it,rtppack); done = true; *stored = true; } else // they're equal !! Drop packet { done = true; } } return 0; }
//called on timer //all data is processed here void MediaStream::timerClick() { //d->mutex.lock(); #ifndef TEST_AUDIO int status = d->session.Poll(); if ( status<0 ) { qDebug("Poll: %s", RTPGetErrorString(status).c_str() ); } // printf("JStat2 %d : %d\n", d->micBuffer->size(),d->dspBuffer->size()); //checkRtpError( status ); // check incoming packets d->session.BeginDataAccess(); if ( d->session.GotoFirstSourceWithData() ) { qDebug("have rtp data"); do { RTPSourceData *sourceData = d->session.GetCurrentSourceInfo(); RTPPacket *pack; if ((pack = d->session.GetNextPacket()) != NULL) { qDebug("Get packet N %ld", pack->GetExtendedSequenceNumber()); // debug("Got packet with payload type %d, size %d", pack->GetPayloadType(), pack->GetPayloadLength() ); // TODO initialise decoder here using pack payload type, maybe use QIntDict of decoders if ( d->decoder ) { short* decodedData = 0; int size = d->decoder->decode((char*)pack->GetPayloadData(), pack->GetPayloadLength(), &decodedData ); if ( size > 0 ) { // adjust the volume for ( int i=0; i<size; i++ ) { double val = double(decodedData[i]) * call_dlg_dsp_level / 50.0; if ( val > 32700.0 ) val = 32700.0; if ( val < -32700.0 ) val = -32700.0; decodedData[i] = short(val); } // write to DSP buffer d->dspBuffer->lock(); d->dspBuffer->put( (char*)decodedData, size*2 ); d->dspBuffer->unlock(); processDspData(decodedData,size); delete[] decodedData; } qDebug("decoded data (%d byes) with payload type %d", size*2, pack->GetPayloadType() ); } else { qDebug("can't decode data with payload type %d", pack->GetPayloadType() ); } // we don't longer need the packet, so // we'll delete it delete pack; } } while ( d->session.GotoNextSourceWithData()); } d->session.EndDataAccess(); // send the packet // check for in data short *data = 0; int micDataSize = 0; // size of readed mic data in samples d->micBuffer->lock(); micDataSize = d->micBuffer->size()/2; if ( micDataSize ) { data = new short[micDataSize]; memcpy( data, d->micBuffer->data(), micDataSize*2 ); d->micBuffer->fetch( micDataSize*2 ); } d->micBuffer->unlock(); // adjust mic volume for ( int i=0; i<micDataSize; i++ ) { double val = double(data[i]) * call_dlg_mic_level / 50.0; if ( val > 32700.0 ) val = 32700.0; if ( val < -32700.0 ) val = -32700.0; data[i] = short(val); } if(micDataSize == 0) { micDataSize = 160; data = new short[160]; } // examine the data here, to calculate levels processMicData(data, micDataSize); if ( data ) { char * encodedData = 0; int readed = micDataSize; int size = 0; qDebug("have mic data %d", micDataSize ); do { int readed = 0; size = d->encoder->encode( data, micDataSize, &encodedData, &readed ); int localPayload = d->codecPayload; // TODO get local payload here qDebug("readed %d encoded %d", readed, size ); delete[] data; data = 0; micDataSize = 0; // TODO: for pcmu packet (payload==0) send packets of certain size if ( size > 0 ) { memcpy( d->outBuffer+d->outBufferPos, encodedData, size ); d->outBufferPos += size; d->outBufferTime += readed; if ( d->outBufferPos ) { //checkRtpError( if ( d->session.IsActive() && d->sendPacketsFlag ) { int status = d->session.SendPacket( (void *)d->outBuffer, (int)d->outBufferPos, (unsigned char)localPayload , false, (long)d->outBufferTime ); if ( status<0 ) { qDebug("can't SendPacket, %s", RTPGetErrorString(status).c_str() ); } } qDebug("sent packet"); } d->outBufferPos = 0; d->outBufferTime = 0; } if ( encodedData ) { delete[] encodedData; encodedData = 0; } } while (size > 0); } status = d->session.Poll(); if ( status<0 ) { qDebug("Poll: %s", RTPGetErrorString(status).c_str() ); } #else // TEST_AUDIO short *data = 0; int micDataSize = 0; // size of readed mic data in samples d->micBuffer->lock(); micDataSize = d->micBuffer->size()/2; if ( micDataSize ) { data = new short[micDataSize]; memcpy( data, d->micBuffer->data(), micDataSize*2 ); d->micBuffer->fetch( micDataSize*2 ); } d->micBuffer->unlock(); if (data) { // write to DSP buffer d->dspBuffer->lock(); d->dspBuffer->put( (char*)data,micDataSize*2 ); d->dspBuffer->unlock(); } static int totalSamples = 0; totalSamples += micDataSize; if ( micDataSize ) printf("total audio samples: %d %d \r", micDataSize, totalSamples); #endif // TEST_AUDIO // d->mutex->unlock(); }