Now not prebuffering more than 100 megs of PCM data

This commit is contained in:
Kwoth 2016-07-24 18:00:11 +02:00
parent 305a9a4a98
commit 922739be63
3 changed files with 70 additions and 27 deletions

View File

@ -303,6 +303,15 @@ namespace NadekoBot.Extensions
public static int GiB(this int value) => value.MiB() * 1024; public static int GiB(this int value) => value.MiB() * 1024;
public static int GB(this int value) => value.MB() * 1000; public static int GB(this int value) => value.MB() * 1000;
public static ulong KiB(this ulong value) => value * 1024;
public static ulong KB(this ulong value) => value * 1000;
public static ulong MiB(this ulong value) => value.KiB() * 1024;
public static ulong MB(this ulong value) => value.KB() * 1000;
public static ulong GiB(this ulong value) => value.MiB() * 1024;
public static ulong GB(this ulong value) => value.MB() * 1000;
public static Stream ToStream(this Image img, System.Drawing.Imaging.ImageFormat format = null) public static Stream ToStream(this Image img, System.Drawing.Imaging.ImageFormat format = null)
{ {
if (format == null) if (format == null)

View File

@ -113,17 +113,10 @@ namespace NadekoBot.Modules.Music.Classes
if (CurrentSong == null) if (CurrentSong == null)
continue; continue;
try
{ OnStarted(this, CurrentSong);
OnStarted(this, CurrentSong); await CurrentSong.Play(audioClient, cancelToken);
await CurrentSong.Play(audioClient, cancelToken);
}
catch (OperationCanceledException)
{
Console.WriteLine("Song canceled");
SongCancelSource = new CancellationTokenSource();
cancelToken = SongCancelSource.Token;
}
OnCompleted(this, CurrentSong); OnCompleted(this, CurrentSong);
if (RepeatPlaylist) if (RepeatPlaylist)
@ -135,6 +128,12 @@ namespace NadekoBot.Modules.Music.Classes
} }
finally finally
{ {
if (!cancelToken.IsCancellationRequested)
{
SongCancelSource.Cancel();
}
SongCancelSource = new CancellationTokenSource();
cancelToken = SongCancelSource.Token;
CurrentSong = null; CurrentSong = null;
await Task.Delay(300).ConfigureAwait(false); await Task.Delay(300).ConfigureAwait(false);
} }

View File

@ -32,9 +32,7 @@ namespace NadekoBot.Modules.Music.Classes
public SongInfo SongInfo { get; } public SongInfo SongInfo { get; }
public string QueuerName { get; set; } public string QueuerName { get; set; }
private PoopyBuffer songBuffer { get; set; } private bool bufferingCompleted { get; set; } = false;
private bool prebufferingComplete { get; set; } = false;
public MusicPlayer MusicPlayer { get; set; } public MusicPlayer MusicPlayer { get; set; }
public string PrettyCurrentTime() public string PrettyCurrentTime()
@ -90,9 +88,20 @@ namespace NadekoBot.Modules.Music.Classes
RedirectStandardError = false, RedirectStandardError = false,
CreateNoWindow = true, CreateNoWindow = true,
}); });
var prebufferSize = 100ul.MiB();
using (var outStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read)) using (var outStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read))
await p.StandardOutput.BaseStream.CopyToAsync(outStream, 81920, cancelToken); {
prebufferingComplete = true; byte[] buffer = new byte[81920];
int bytesRead;
while ((bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) != 0)
{
await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false);
while ((ulong)outStream.Length - bytesSent > prebufferSize)
await Task.Delay(100, cancelToken);
}
}
bufferingCompleted = true;
} }
catch (System.ComponentModel.Win32Exception) { catch (System.ComponentModel.Win32Exception) {
var oldclr = Console.ForegroundColor; var oldclr = Console.ForegroundColor;
@ -106,11 +115,11 @@ Check the guides for your platform on how to setup ffmpeg correctly:
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Buffering errored: {ex.Message}"); Console.WriteLine($"Buffering stopped: {ex.Message}");
} }
finally finally
{ {
Console.WriteLine($"Buffering done." + $" [{songBuffer.ContentLength}]"); Console.WriteLine($"Buffering done.");
if (p != null) if (p != null)
{ {
try try
@ -128,18 +137,36 @@ Check the guides for your platform on how to setup ffmpeg correctly:
var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
var bufferTask = BufferSong(filename, cancelToken).ConfigureAwait(false); var bufferTask = BufferSong(filename, cancelToken).ConfigureAwait(false);
var inStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); var inStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
bytesSent = 0;
try try
{ {
await Task.Delay(1000); var prebufferingTask = CheckPrebufferingAsync(inStream, cancelToken);
var sw = new Stopwatch();
sw.Start();
var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken));
if (t != prebufferingTask)
{
Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream.");
return;
}
else if(prebufferingTask.IsCanceled)
{
Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream.");
return;
}
sw.Stop();
Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed);
const int blockSize = 3840; const int blockSize = 3840;
var attempt = 0; var attempt = 0;
byte[] buffer = new byte[blockSize];
while (!cancelToken.IsCancellationRequested) while (!cancelToken.IsCancellationRequested)
{ {
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
byte[] buffer = new byte[blockSize];
var read = inStream.Read(buffer, 0, buffer.Length); var read = inStream.Read(buffer, 0, buffer.Length);
//await inStream.CopyToAsync(voiceClient.OutputStream); //await inStream.CopyToAsync(voiceClient.OutputStream);
unchecked unchecked
@ -149,9 +176,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
if (read == 0) if (read == 0)
if (attempt++ == 20) if (attempt++ == 20)
{ {
Console.WriteLine("blocking");
voiceClient.Wait(); voiceClient.Wait();
Console.WriteLine("unblocking");
break; break;
} }
else else
@ -161,19 +186,29 @@ Check the guides for your platform on how to setup ffmpeg correctly:
while (this.MusicPlayer.Paused) while (this.MusicPlayer.Paused)
await Task.Delay(200, cancelToken).ConfigureAwait(false); await Task.Delay(200, cancelToken).ConfigureAwait(false);
buffer = AdjustVolume(buffer, MusicPlayer.Volume); buffer = AdjustVolume(buffer, MusicPlayer.Volume);
voiceClient.Send(buffer, 0, read); voiceClient.Send(buffer, 0, read);
} }
await bufferTask;
voiceClient.Clear();
cancelToken.ThrowIfCancellationRequested();
} }
finally { finally
{
await bufferTask;
await Task.Run(() => voiceClient.Clear());
inStream.Dispose(); inStream.Dispose();
try { File.Delete(filename); } catch { } try { File.Delete(filename); } catch { }
} }
} }
private async Task CheckPrebufferingAsync(Stream inStream, CancellationToken cancelToken)
{
while (!bufferingCompleted && inStream.Length < 2.MiB())
{
await Task.Delay(100, cancelToken);
}
Console.WriteLine("Buffering successfull");
}
/* /*
//stackoverflow ftw //stackoverflow ftw
private static byte[] AdjustVolume(byte[] audioSamples, float volume) private static byte[] AdjustVolume(byte[] audioSamples, float volume)