1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-12-04 10:37:49 +01:00
libtgvoip/controller/net/JitterBuffer.h

130 lines
3.3 KiB
C
Raw Normal View History

2020-01-22 12:43:51 +01:00
//
// 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
2020-01-25 18:36:49 +01:00
#include "controller/media/MediaStreamItf.h"
2020-01-22 12:43:51 +01:00
#include "tools/BlockingQueue.h"
#include "tools/Buffers.h"
2020-01-29 15:52:43 +01:00
#include "tools/logging.h"
2020-03-24 21:59:49 +01:00
#include "tools/threading.h"
#include <algorithm>
#include <atomic>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
2020-01-22 12:43:51 +01:00
#define JITTER_SLOT_COUNT 64
#define JR_OK 1
#define JR_MISSING 2
#define JR_BUFFERING 3
2020-04-20 16:17:40 +02:00
#define INVALID_SEQ 0xFFFFFFFF
2020-01-22 12:43:51 +01:00
namespace tgvoip
{
2020-04-20 16:17:40 +02:00
struct JitterArray
{
JitterArray(bool isEC);
private:
inline uint8_t getOffset(uint32_t seq)
{
return (back + (seq - backSeq)) % JITTER_SLOT_COUNT;
}
public:
bool has(uint32_t seq);
uint32_t put(uint32_t seq, std::unique_ptr<Buffer> &&buffer);
std::array<std::unique_ptr<Buffer>, JITTER_SLOT_COUNT>::iterator get(uint32_t seq);
void advance(uint32_t seq);
void clear();
uint8_t count();
bool empty();
auto end()
{
return slots.end();
}
uint8_t front = 0;
uint8_t back = 0;
uint32_t frontSeq = INVALID_SEQ;
uint32_t backSeq = INVALID_SEQ;
bool isEC = false;
std::array<std::unique_ptr<Buffer>, JITTER_SLOT_COUNT> slots;
};
2020-01-22 12:43:51 +01:00
class JitterBuffer
{
public:
2020-03-24 21:59:49 +01:00
JitterBuffer(uint32_t step);
~JitterBuffer();
void SetMinPacketCount(uint32_t count);
int GetMinPacketCount();
unsigned int GetCurrentDelay();
double GetAverageDelay();
void Reset();
void HandleInput(std::unique_ptr<Buffer> &&buf, uint32_t timestamp, bool isEC);
2020-04-20 17:07:06 +02:00
std::pair<std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> HandleOutput(int &playbackScaledDuration);
bool haveNext(bool ec);
2020-03-24 21:59:49 +01:00
void Tick();
void GetAverageLateCount(double *out);
int GetAndResetLostPacketCount();
double GetLastMeasuredJitter();
double GetLastMeasuredDelay();
2020-01-22 12:43:51 +01:00
2020-03-24 21:59:49 +01:00
double GetTimeoutWindow();
2020-01-26 21:06:16 +01:00
2020-01-22 12:43:51 +01:00
private:
2020-03-24 21:59:49 +01:00
Mutex mutex;
2020-03-30 19:10:20 +02:00
int64_t lastMain = 0;
2020-04-20 16:17:40 +02:00
JitterArray slotsMain{false};
JitterArray slotsEc{true};
2020-03-30 19:14:51 +02:00
uint32_t step;
2020-04-20 16:17:40 +02:00
int32_t nextFetchTimestamp = 0; // What frame to read next (protected for GetSeqTooLate)
2020-03-24 21:59:49 +01:00
std::atomic<double> 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<int, 64, double> delayHistory;
HistoricBuffer<int, 64, double> lateHistory;
bool adjustingDelay = false;
unsigned int tickCount = 0;
unsigned int latePacketCount = 0;
unsigned int dontIncMinDelayFor = 0;
unsigned int dontDecMinDelayFor = 0;
2020-03-24 21:59:49 +01:00
int lostPackets = 0;
double prevRecvTime = 0;
double expectNextAtTimeMs = 0;
2020-03-24 21:59:49 +01:00
HistoricBuffer<double, 64> deviationHistory;
double lastMeasuredJitter = 0;
double lastMeasuredDelay = 0;
int outstandingDelayChange = 0;
unsigned int dontChangeDelayFor = 0;
2020-03-24 21:59:49 +01:00
double avgDelay = 0;
bool first = true;
2020-01-22 12:43:51 +01:00
#ifdef TGVOIP_DUMP_JITTER_STATS
2020-03-24 21:59:49 +01:00
FILE *dump;
2020-01-22 12:43:51 +01:00
#endif
};
} // namespace tgvoip
#endif //LIBTGVOIP_JITTERBUFFER_H