// // libtgvoip is free and unencumbered public domain software. // For more information, see http://unlicense.org or the UNLICENSE file // you should have received with this source code distribution. // #ifndef LIBTGVOIP_JITTERBUFFER_H #define LIBTGVOIP_JITTERBUFFER_H #include #include #include #include #include #include "controller/media/MediaStreamItf.h" #include "tools/BlockingQueue.h" #include "tools/Buffers.h" #include "tools/threading.h" #include "tools/logging.h" #define JITTER_SLOT_COUNT 64 #define JITTER_SLOT_SIZE 1024 #define JR_OK 1 #define JR_MISSING 2 #define JR_BUFFERING 3 namespace tgvoip { class JitterBuffer { public: JitterBuffer(uint32_t step); ~JitterBuffer(); void SetMinPacketCount(uint32_t count); int GetMinPacketCount(); unsigned int GetCurrentDelay(); double GetAverageDelay(); void Reset(); void HandleInput(unsigned char *data, size_t len, uint32_t timestamp, bool isEC); size_t HandleOutput(unsigned char *buffer, size_t len, bool advance, int &playbackScaledDuration, bool &isEC); void Tick(); void GetAverageLateCount(double *out); int GetAndResetLostPacketCount(); double GetLastMeasuredJitter(); double GetLastMeasuredDelay(); double GetTimeoutWindow(); // Get minimum refetchable seq for (reverse) NACK logic. // Any sequence numbers smaller than this cannot possibly arrive in time for playing. inline uint32_t GetSeqTooLate(double rtt) { //LOGE("Next fetch timestamp: %ld, rtt %lf, step %d", nextFetchTimestamp.load(), rtt * 1000, step) // The absolute minimum time(stamp) that will (barely) be accepted by the jitter buffer in time + RTT time // Then convert timestamp into a seqno: remember, in protocol >= PROTOCOL_RELIABLE, seq = ts * step + 1 return ((nextFetchTimestamp + (rtt * 1000)) / static_cast(step) + 1) - lostCount; // Seqs start at 1 } private: struct jitter_packet_t { Buffer buffer = Buffer(); uint32_t timestamp = 0; size_t size = 0; bool isEC = 0; double recvTimeDiff = 0.0; }; void PutInternal(const jitter_packet_t &pkt, bool overwriteExisting); int GetInternal(jitter_packet_t &pkt, bool advance); void Advance(); BufferPool bufferPool; Mutex mutex; uint32_t step; std::array slots{0}; std::atomic nextFetchTimestamp{0}; // What frame to read next (protected for GetSeqTooLate) std::atomic minDelay{6}; uint32_t minMinDelay; uint32_t maxMinDelay; uint32_t maxUsedSlots; uint32_t lastPutTimestamp; uint32_t lossesToReset; double resyncThreshold; unsigned int lostCount = 0; unsigned int lostSinceReset = 0; unsigned int gotSinceReset = 0; bool wasReset = true; bool needBuffering = true; HistoricBuffer delayHistory; HistoricBuffer lateHistory; bool adjustingDelay = false; unsigned int tickCount = 0; unsigned int latePacketCount = 0; unsigned int dontIncMinDelay = 0; unsigned int dontDecMinDelay = 0; int lostPackets = 0; double prevRecvTime = 0; double expectNextAtTime = 0; HistoricBuffer deviationHistory; double lastMeasuredJitter = 0; double lastMeasuredDelay = 0; int outstandingDelayChange = 0; unsigned int dontChangeDelay = 0; double avgDelay = 0; bool first = true; #ifdef TGVOIP_DUMP_JITTER_STATS FILE *dump; #endif }; } // namespace tgvoip #endif //LIBTGVOIP_JITTERBUFFER_H