📄 jitter.cxx
字号:
return; } if (currentReadFrame->GetMarker()) { // See if remote appears to be setting marker bit on EVERY packet. consecutiveMarkerBits++; if (consecutiveMarkerBits < maxConsecutiveMarkerBits) { PTRACE(3, "RTP\tReceived start of talk burst: " << currentReadFrame->GetTimestamp()); preBuffering = TRUE; } if (consecutiveMarkerBits == maxConsecutiveMarkerBits) { PTRACE(3, "RTP\tEvery packet has Marker bit, ignoring them from this client!"); } } else consecutiveMarkerBits = 0;#if PTRACING analyser->In(currentReadFrame->GetTimestamp(), currentDepth, preBuffering ? "PreBuf" : "");#endif // Queue the frame for playing by the thread at other end of jitter buffer bufferMutex.Wait(); // Have been reading a frame, put it into the queue now, at correct position if (newestFrame == NULL) oldestFrame = newestFrame = currentReadFrame; // Was empty else { DWORD time = currentReadFrame->GetTimestamp(); if (time > newestFrame->GetTimestamp()) { // Is newer than newst, put at that end of queue currentReadFrame->prev = newestFrame; newestFrame->next = currentReadFrame; newestFrame = currentReadFrame; } else if (time <= oldestFrame->GetTimestamp()) { // Is older than the oldest, put at that end of queue currentReadFrame->next = oldestFrame; oldestFrame->prev = currentReadFrame; oldestFrame = currentReadFrame; } else { // Somewhere in between, locate its position Entry * frame = newestFrame->prev; while (time < frame->GetTimestamp()) frame = frame->prev; currentReadFrame->prev = frame; currentReadFrame->next = frame->next; frame->next = currentReadFrame; frame->next->prev = currentReadFrame; } } currentDepth++; }}BOOL RTP_JitterBuffer::ReadData(DWORD timestamp, RTP_DataFrame & frame){ if (shuttingDown) return FALSE; /*Free the frame just written to codec, putting it back into the free list and clearing the parking spot for it. */ if (currentWriteFrame != NULL) { bufferMutex.Wait(); // Move frame from current to free list currentWriteFrame->next = freeFrames; if (freeFrames != NULL) freeFrames->prev = currentWriteFrame; freeFrames = currentWriteFrame; currentWriteFrame = NULL; bufferMutex.Signal(); } // Default response is an empty frame, ie silence frame.SetPayloadSize(0); /*Get the next frame to write to the codec. Takes it from the oldest position in the queue, if it is time to do so, and parks it in the special member so can unlock the mutex while the writer thread has its way with the buffer. */ if (oldestFrame == NULL) { /*No data to play! We ran the buffer down to empty, restart buffer by setting flag that will fill it again before returning any data. */ preBuffering = TRUE;#if PTRACING analyser->Out(0, currentDepth, "Empty");#endif return TRUE; } PWaitAndSignal mutex(bufferMutex); /* See if time for this packet, if our oldest frame is older than the required age, then use it. If it is not time yet, make sure that the writer thread isn't falling behind (not enough MIPS). If the time between the oldest and the newest entries in the jitter buffer is greater than the size specified for the buffer, then return the oldest entry regardless, making the writer thread catch up. */ DWORD oldestTimestamp = oldestFrame->GetTimestamp(); DWORD newestTimestamp = newestFrame->GetTimestamp(); if (preBuffering && (newestTimestamp - oldestTimestamp) > maxJitterTime/2) preBuffering = FALSE; if (preBuffering) { // Are filling the buffer, don't return anything yet#if PTRACING analyser->Out(oldestTimestamp, currentDepth, "PreBuf");#endif return TRUE; } if (timestamp < oldestTimestamp && timestamp > (newestTimestamp - maxJitterTime)) { // It is not yet time for something in the buffer#if PTRACING analyser->Out(oldestTimestamp, currentDepth, "Wait");#endif return TRUE; } // Detatch oldest packet from the list, put into parking space currentDepth--;#if PTRACING analyser->Out(oldestTimestamp, currentDepth, timestamp >= oldestTimestamp ? "" : "Late");#endif currentWriteFrame = oldestFrame; oldestFrame = currentWriteFrame->next; currentWriteFrame->next = NULL; if (oldestFrame == NULL) newestFrame = NULL; else { oldestFrame->prev = NULL; // See if exceeded maximum jitter buffer time delay, waste them if so while ((newestTimestamp - oldestFrame->GetTimestamp()) > maxJitterTime) { // Throw away the oldest entry Entry * wastedFrame = oldestFrame; oldestFrame = oldestFrame->next; oldestFrame->prev = NULL; currentDepth--; // Put thrown away frame on free list wastedFrame->next = freeFrames; if (freeFrames != NULL) freeFrames->prev = wastedFrame; freeFrames = wastedFrame; packetsTooLate++; } } frame = *currentWriteFrame; return TRUE;}#if PTRACINGRTP_JitterBufferAnalyser::RTP_JitterBufferAnalyser(){ inPos = outPos = 1; in[0].time = out[0].time = 0; in[0].tick = out[0].tick = PTimer::Tick(); in[0].depth = out[0].depth = 0;}void RTP_JitterBufferAnalyser::In(DWORD time, unsigned depth, const char * extra){ if (inPos < PARRAYSIZE(in)) { in[inPos].tick = PTimer::Tick(); in[inPos].time = time; in[inPos].depth = depth; in[inPos++].extra = extra; }}void RTP_JitterBufferAnalyser::Out(DWORD time, unsigned depth, const char * extra){ if (outPos < PARRAYSIZE(out)) { out[outPos].tick = PTimer::Tick(); if (time == 0 && outPos > 0) out[outPos].time = out[outPos-1].time; else out[outPos].time = time; out[outPos].depth = depth; out[outPos++].extra = extra; }}void RTP_JitterBufferAnalyser::PrintOn(ostream & strm) const{ strm << "Input samples: " << inPos << " Output samples: " << outPos << "\n" "Dir\tRTPTime\tInDiff\tOutDiff\tInMode\tOutMode\t" "InDepth\tOutDep\tInTick\tInDelay\tOutTick\tOutDel\tIODelay\n"; PINDEX ix = 1; PINDEX ox = 1; while (ix < inPos || ox < outPos) { while (ix < inPos && (ox >= outPos || in[ix].time < out[ox].time)) { strm << "In\t" << in[ix].time << '\t' << (in[ix].time - in[ix-1].time) << "\t" "\t" << in[ix].extra << "\t" "\t" << in[ix].depth << "\t" "\t" << (in[ix].tick - in[0].tick) << '\t' << (in[ix].tick - in[ix-1].tick) << "\t" "\t" "\t" "\n"; ix++; } while (ox < outPos && (ix >= inPos || out[ox].time < in[ix].time)) { strm << "Out\t" << out[ox].time << "\t" "\t" << (out[ox].time - out[ox-1].time) << "\t" "\t" << out[ox].extra << "\t" "\t" << out[ox].depth << "\t" "\t" "\t" << (out[ox].tick - out[0].tick) << '\t' << (out[ox].tick - out[ox-1].tick) << "\t" "\n"; ox++; } while (ix < inPos && ox < outPos && in[ix].time == out[ox].time) { strm << "I/O\t" << in[ix].time << '\t' << (in[ix].time - in[ix-1].time) << '\t' << (out[ox].time - out[ox-1].time) << '\t' << in[ix].extra << '\t' << out[ox].extra << '\t' << in[ix].depth << '\t' << out[ox].depth << '\t' << (in[ix].tick - in[0].tick) << '\t' << (in[ix].tick - in[ix-1].tick) << '\t' << (out[ox].tick - out[0].tick) << '\t' << (out[ox].tick - out[ox-1].tick) << '\t' << (out[ox].tick - in[ix].tick) << '\n'; ox++; ix++; } }}#endif/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -