144 lines
5.1 KiB
Go
144 lines
5.1 KiB
Go
package services
|
|
|
|
import (
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// BitrateStrategy représente une stratégie d'adaptation de bitrate
|
|
// T0361: Create Bitrate Adaptation Strategy Service
|
|
type BitrateStrategy string
|
|
|
|
const (
|
|
// StrategyConservative est une stratégie conservatrice qui adapte le bitrate
|
|
// seulement quand les conditions sont vraiment défavorables
|
|
StrategyConservative BitrateStrategy = "conservative"
|
|
|
|
// StrategyAggressive est une stratégie agressive qui adapte le bitrate
|
|
// rapidement pour éviter les problèmes de streaming
|
|
StrategyAggressive BitrateStrategy = "aggressive"
|
|
|
|
// StrategyBalanced est une stratégie équilibrée entre conservative et aggressive
|
|
StrategyBalanced BitrateStrategy = "balanced"
|
|
)
|
|
|
|
// StrategyThresholds représente les seuils pour une stratégie
|
|
type StrategyThresholds struct {
|
|
BufferLevelThreshold float64 // Seuil de niveau de buffer (0.0 à 1.0)
|
|
BandwidthRatioThreshold float64 // Seuil de ratio de bande passante (0.0 à 1.0)
|
|
UseOrCondition bool // Si true, utilise OR au lieu de AND
|
|
}
|
|
|
|
// BitrateStrategyService gère les stratégies d'adaptation de bitrate
|
|
type BitrateStrategyService struct {
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewBitrateStrategyService crée un nouveau service de stratégies d'adaptation
|
|
func NewBitrateStrategyService(logger *zap.Logger) *BitrateStrategyService {
|
|
if logger == nil {
|
|
logger = zap.NewNop()
|
|
}
|
|
return &BitrateStrategyService{
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// GetThresholds retourne les seuils pour une stratégie donnée
|
|
func (s *BitrateStrategyService) GetThresholds(strategy BitrateStrategy) StrategyThresholds {
|
|
switch strategy {
|
|
case StrategyConservative:
|
|
// Conservative: adapte seulement si buffer ET bande passante sont faibles
|
|
return StrategyThresholds{
|
|
BufferLevelThreshold: 0.3, // 30% de buffer
|
|
BandwidthRatioThreshold: 0.7, // 70% de la bande passante nécessaire
|
|
UseOrCondition: false, // Utilise AND
|
|
}
|
|
case StrategyAggressive:
|
|
// Aggressive: adapte si buffer OU bande passante est faible
|
|
return StrategyThresholds{
|
|
BufferLevelThreshold: 0.15, // 15% de buffer
|
|
BandwidthRatioThreshold: 0.5, // 50% de la bande passante nécessaire
|
|
UseOrCondition: true, // Utilise OR
|
|
}
|
|
case StrategyBalanced:
|
|
fallthrough
|
|
default:
|
|
// Balanced: adapte si buffer ET bande passante sont modérément faibles
|
|
return StrategyThresholds{
|
|
BufferLevelThreshold: 0.2, // 20% de buffer
|
|
BandwidthRatioThreshold: 0.6, // 60% de la bande passante nécessaire
|
|
UseOrCondition: false, // Utilise AND
|
|
}
|
|
}
|
|
}
|
|
|
|
// ShouldAdapt détermine si une adaptation de bitrate est nécessaire
|
|
// selon la stratégie, le niveau de buffer et le ratio de bande passante
|
|
// bufferLevel: niveau de buffer (0.0 = vide, 1.0 = plein)
|
|
// bandwidthRatio: ratio de bande passante disponible / nécessaire (0.0 à 1.0+)
|
|
// Retourne true si une adaptation est nécessaire
|
|
func (s *BitrateStrategyService) ShouldAdapt(strategy BitrateStrategy, bufferLevel float64, bandwidthRatio float64) bool {
|
|
thresholds := s.GetThresholds(strategy)
|
|
|
|
// Valider les paramètres
|
|
if bufferLevel < 0 || bufferLevel > 1 {
|
|
s.logger.Warn("Invalid buffer level",
|
|
zap.Float64("buffer_level", bufferLevel),
|
|
zap.String("strategy", string(strategy)))
|
|
return false
|
|
}
|
|
|
|
if bandwidthRatio < 0 {
|
|
s.logger.Warn("Invalid bandwidth ratio",
|
|
zap.Float64("bandwidth_ratio", bandwidthRatio),
|
|
zap.String("strategy", string(strategy)))
|
|
return false
|
|
}
|
|
|
|
// Vérifier si le buffer est faible
|
|
bufferLow := bufferLevel < thresholds.BufferLevelThreshold
|
|
|
|
// Vérifier si la bande passante est faible
|
|
// bandwidthRatio < threshold signifie que la bande passante disponible
|
|
// est inférieure au seuil requis
|
|
bandwidthLow := bandwidthRatio < thresholds.BandwidthRatioThreshold
|
|
|
|
// Appliquer la logique selon la stratégie
|
|
if thresholds.UseOrCondition {
|
|
// OR: adapter si buffer OU bande passante est faible
|
|
return bufferLow || bandwidthLow
|
|
} else {
|
|
// AND: adapter seulement si buffer ET bande passante sont faibles
|
|
return bufferLow && bandwidthLow
|
|
}
|
|
}
|
|
|
|
// SelectStrategy sélectionne une stratégie selon le contexte
|
|
// networkStability: stabilité du réseau (0.0 = instable, 1.0 = stable)
|
|
// userPreference: préférence de l'utilisateur (peut être nil pour auto)
|
|
// Retourne la stratégie recommandée
|
|
func (s *BitrateStrategyService) SelectStrategy(networkStability float64, userPreference *BitrateStrategy) BitrateStrategy {
|
|
// Si l'utilisateur a une préférence, l'utiliser
|
|
if userPreference != nil {
|
|
return *userPreference
|
|
}
|
|
|
|
// Sélectionner automatiquement selon la stabilité du réseau
|
|
if networkStability < 0.3 {
|
|
// Réseau instable: utiliser une stratégie conservative
|
|
return StrategyConservative
|
|
} else if networkStability > 0.7 {
|
|
// Réseau stable: utiliser une stratégie aggressive pour meilleure qualité
|
|
return StrategyAggressive
|
|
} else {
|
|
// Réseau modéré: utiliser une stratégie balanced
|
|
return StrategyBalanced
|
|
}
|
|
}
|
|
|
|
// IsValidStrategy vérifie si une stratégie est valide
|
|
func (s *BitrateStrategyService) IsValidStrategy(strategy BitrateStrategy) bool {
|
|
return strategy == StrategyConservative ||
|
|
strategy == StrategyAggressive ||
|
|
strategy == StrategyBalanced
|
|
}
|