/// <summary> /// Processes RTCP packets. /// </summary> /// <param name="packets">The packets to process.</param> public override void ProcessRTCP(RTCPPacket[] packets) { if (_Encoder != null) { foreach (var packet in packets) { if (packet is RTCPReportPacket) { _ReportsReceived++; var report = (RTCPReportPacket)packet; foreach (var block in report.ReportBlocks) { Log.DebugFormat("Opus report: {0} packet loss ({1} cumulative packets lost)", block.PercentLost.ToString("P2"), block.CumulativeNumberOfPacketsLost.ToString()); if (block.PercentLost > 0) { _LosslessCount = 0; _LossyCount++; if (_LossyCount > 5 && _Encoder.Quality > 0.0) { _LossyCount = 0; _Encoder.Quality = MathAssistant.Max(0.0, _Encoder.Quality - 0.1); Log.InfoFormat("Decreasing Opus encoder quality to {0}.", _Encoder.Quality.ToString("P2")); } } else { _LossyCount = 0; _LosslessCount++; if (_LosslessCount > 5 && _Encoder.Quality < 1.0) { _LosslessCount = 0; _Encoder.Quality = MathAssistant.Min(1.0, _Encoder.Quality + 0.1); Log.InfoFormat("Increasing Opus encoder quality to {0}.", _Encoder.Quality.ToString("P2")); } } if (!DisableFEC && !FecActive && _ReportsReceived > _MinimumReportsBeforeFEC) { if ((block.PercentLost * 100) > PercentLossToTriggerFEC) { Log.Info("Activating FEC for Opus audio stream."); _Encoder.ActivateFEC(PercentLossToTriggerFEC); FecActive = true; } } } } } } }