public ChunkFile GetClosestChunk(ChunksCollectorModelByTime model) { var streamCfg = _streamsConfigs.StreamSources .FirstOrDefault(x => x.Name == model.Channel); if (streamCfg == null) { throw new NoSuchChannelException(model.Channel); } model.channelRoot = Path.Combine( _chunkerConfig.ChunkStorageDir, streamCfg.Name); model.streamSource = streamCfg; var chunkTime = streamCfg.ChunkTime; var minTime = GetMinChunkTimeSpan(model); var minTimeS = minTime .Add(-DateTimeOffset.Now.Offset) .ToUnixTimeSeconds(); var testTime = TimeTools.SecsToDateWithOffset((int)minTimeS); var files = GetFilesInsideTimeRange( model.channelRoot, minTime.AddSeconds(-2.2 * 1 * chunkTime), minTime.AddSeconds( 1 * chunkTime * (model.HlsListSize + safeHlsLstDelta + 1)) ); var result = files .Select(x => ChunkFileLoader.Load(x)) .Where(x => x.timeSeconds > minTimeS - streamCfg.ChunkTime) .OrderBy(x => x.timeSeconds) .FirstOrDefault(); if (result == null) { throw new NoAvailableFilesException(); } return(result); }
/// <summary> /// Get the closest possible time to the target time, depending /// on the number of chunks and the newest file. /// If it's live, then the newest file - (n + 1) * chunkTime will /// be returned. Note +1 because the newest is still being created. /// /// Otherwise, the received time is returned. /// </summary> private DateTime GetMinChunkTimeSpan(ChunksCollectorModelByTime model) { var mostRecent = Directory.GetFiles( model.channelRoot, "*.ts", SearchOption.AllDirectories ).OrderByDescending(File.GetCreationTime).FirstOrDefault(); if (mostRecent == null) { throw new NoAvailableFilesException($"0/{model.HlsListSize}"); } var targetTime = model.RequestedTime .AddSeconds( -model.streamSource.ChunkTime * model.HlsListSize); var newestChunk = ChunkFileLoader.Load(mostRecent); var newestDateTime = TimeTools.SecsToDateWithOffset(newestChunk.timeSeconds); var totalRequiredSec = (model.HlsListSize + safeHlsLstDelta + 1) * (model.streamSource.ChunkTime); if (targetTime.AddSeconds(totalRequiredSec) > newestDateTime) { var delta = newestDateTime - targetTime; return(newestDateTime.AddSeconds(-totalRequiredSec) .Add(-delta)); } else { return(targetTime); } }