125 lines
3.7 KiB
C#
Executable File
125 lines
3.7 KiB
C#
Executable File
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Luski.net.Sound
|
|
{
|
|
internal class JitterBuffer
|
|
{
|
|
internal JitterBuffer(object? sender, uint maxRTPPackets, uint timerIntervalInMilliseconds)
|
|
{
|
|
if (maxRTPPackets < 2)
|
|
{
|
|
throw new Exception("Wrong Arguments. Minimum maxRTPPackets is 2");
|
|
}
|
|
|
|
m_Sender = sender;
|
|
Maximum = maxRTPPackets;
|
|
IntervalInMilliseconds = timerIntervalInMilliseconds;
|
|
|
|
Init();
|
|
}
|
|
|
|
private readonly object? m_Sender = null;
|
|
private readonly EventTimer m_Timer = new();
|
|
private readonly Queue<RTPPacket> m_Buffer = new();
|
|
private RTPPacket m_LastRTPPacket = new();
|
|
private bool m_Underflow = true;
|
|
private bool m_Overflow = false;
|
|
|
|
internal delegate void DelegateDataAvailable(object sender, RTPPacket packet);
|
|
internal event DelegateDataAvailable? DataAvailable;
|
|
|
|
internal uint Maximum { get; } = 10;
|
|
internal uint IntervalInMilliseconds { get; } = 20;
|
|
private void Init()
|
|
{
|
|
InitTimer();
|
|
}
|
|
private void InitTimer()
|
|
{
|
|
m_Timer.TimerTick += new EventTimer.DelegateTimerTick(OnTimerTick);
|
|
}
|
|
internal void Start()
|
|
{
|
|
m_Timer.Start(IntervalInMilliseconds);
|
|
m_Underflow = true;
|
|
}
|
|
internal void Stop()
|
|
{
|
|
m_Timer.Stop();
|
|
m_Buffer.Clear();
|
|
}
|
|
private void OnTimerTick()
|
|
{
|
|
try
|
|
{
|
|
if (DataAvailable != null)
|
|
{
|
|
if (m_Buffer.Count > 0)
|
|
{
|
|
if (m_Overflow)
|
|
{
|
|
if (m_Buffer.Count <= Maximum / 2)
|
|
{
|
|
m_Overflow = false;
|
|
}
|
|
}
|
|
|
|
if (m_Underflow)
|
|
{
|
|
if (m_Buffer.Count < Maximum / 2)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
m_Underflow = false;
|
|
}
|
|
}
|
|
|
|
m_LastRTPPacket = m_Buffer.Dequeue();
|
|
DataAvailable(m_Sender, m_LastRTPPacket);
|
|
}
|
|
else
|
|
{
|
|
m_Overflow = false;
|
|
|
|
if (m_LastRTPPacket != null && m_Underflow == false)
|
|
{
|
|
if (m_LastRTPPacket.Data != null)
|
|
{
|
|
m_Underflow = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(string.Format("JitterBuffer.cs | OnTimerTick() | {0}", ex.Message));
|
|
}
|
|
}
|
|
internal void AddData(RTPPacket packet)
|
|
{
|
|
try
|
|
{
|
|
if (m_Overflow == false)
|
|
{
|
|
if (m_Buffer.Count <= Maximum)
|
|
{
|
|
m_Buffer.Enqueue(packet);
|
|
}
|
|
else
|
|
{
|
|
m_Overflow = true;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(string.Format("JitterBuffer.cs | AddData() | {0}", ex.Message));
|
|
}
|
|
}
|
|
}
|
|
}
|