public static void StopRecording() { if (!Recording) { return; } Duration += (Time.time - StartTime); if (!Recording) { return; } Recording = false; //while(FfmpegFrameSent < FfmpegFrameRendered) //{ // Thread.Sleep(50); //} FfmpegStream.Close(); FfmpegStream = null; FfmpegProcess.Close(); FfmpegProcess = null; Time.captureFramerate = 0; RecordingStopped(); }
public void Close() { Closed = true; try { if (!FfmpegProcess.HasExitedSafe()) { FfmpegProcess.Kill(); } } catch { } try { FfmpegProcess.CancelErrorRead(); } catch { } try { FfmpegProcess.StandardInput.Dispose(); } catch { } try { FfmpegProcess.StandardOutput.Dispose(); } catch { } try { FfmpegProcess.Dispose(); } catch { } IcyStream?.Dispose(); }
public void Initialize() { _process = new Mock <IProcessAsync>(); _tempFileManager = new Mock <ITempFileManager>(); _ffmpeg = new FfmpegProcess(_process.Object, _tempFileManager.Object); }
private void PlaybackThreadStart(object obj) { var objs = (object[])obj; var cancellationToken = (CancellationToken)objs[0]; int sampleRate = 48000; int channelCount = 2; string format = BitConverter.IsLittleEndian ? "f32le" : "f32be"; string codec = "pcm_" + format; var playerArguments = new ArgumentList() .Add("-v").Add("fatal") .Add("-autoexit") .Add("-nodisp") .Add("-ar").Add(sampleRate.ToStringInvariant()) .Add("-ac").Add(channelCount.ToStringInvariant()) .Add("-f").Add(format) .Add("-"); using (var serviceScope = _serviceScopeFactory.CreateScope()) { var dbContext = serviceScope.ServiceProvider.GetRequiredService <MediaInfoContext>(); restartPlayer: // Wait for playing. for (; ;) { if (cancellationToken.IsCancellationRequested) { return; } lock (_lock) { if (_playing) { break; } } WaitHandle.WaitAny(new[] { cancellationToken.WaitHandle, _playEvent }); } using (var playerProcess = new FfmpegProcess("ffplay", playerArguments)) using (var playerStream = playerProcess.InputStream) { var sampleBuffer = new float[sampleRate / 20 * channelCount]; var buffer = MemoryMarshal.AsBytes(sampleBuffer.AsSpan()); restartTrack: for (; ;) { if (cancellationToken.IsCancellationRequested) { return; } int playerTrackId; int playerTrackPositionSamples; int playerTrackPosition; lock (_lock) { if (!_playing) { goto restartPlayer; } int trackId = _playlistIndex != -1 ? _playlist[_playlistIndex] : -1; if (trackId == -1) { goto nextTrack; } playerTrackId = trackId; playerTrackPositionSamples = _trackPosition * sampleRate * channelCount; playerTrackPosition = _trackPosition; } var track = dbContext.Tracks // where track is current jukebox track .Where(t => t.TrackId == playerTrackId) // find files for tracks .Join(dbContext.Files, t => t.FileId, f => f.FileId, (t, f) => new { LibraryPath = f.Library.Path, DirectoryPath = f.Directory.Path, FileName = f.Name, t.StreamIndex, t.AlbumGain, t.TrackGain, }) .FirstOrDefault(); if (track == null) { goto nextTrack; } string filePath = Path.Join(track.LibraryPath, track.DirectoryPath, track.FileName); var decoderArguments = new ArgumentList() .Add("-i").Add(filePath) .Add("-ss").Add(playerTrackPosition.ToStringInvariant()) .Add("-map").Add(b => b.Append("0:").Append(track.StreamIndex.ToStringInvariant())) .Add("-c:a:0").Add(codec) .Add("-ar:0").Add(sampleRate.ToStringInvariant()) .Add("-ac:0").Add(channelCount.ToStringInvariant()) .Add("-f").Add(format) .Add("-"); using (var decoderProcess = FfmpegTranscoder.Transcode(decoderArguments)) using (var decoderStream = decoderProcess.OutputStream) { decoderProcess.InputStream.Close(); float replayGainScale = MathF.Pow(10, (track.TrackGain ?? 0) / 20); int bufferOffset = 0; int bufferCount = 0; for (; ;) { if (cancellationToken.IsCancellationRequested) { return; } lock (_lock) { if (!_playing) { goto restartPlayer; } int trackId = _playlistIndex != -1 ? _playlist[_playlistIndex] : -1; if (playerTrackId != trackId || playerTrackPosition != _trackPosition) { goto restartTrack; } playerTrackPosition = playerTrackPositionSamples / (sampleRate * channelCount); _trackPosition = playerTrackPosition; } try { int readCount = decoderStream.Read(buffer.Slice(bufferOffset + bufferCount)); if (readCount == 0) { break; } bufferCount += readCount; } catch (IOException ex) { Debug.WriteLine("Exception thrown while reading from ffmpeg: {0}", ex); break; } var samplesSpan = sampleBuffer.AsSpan(bufferOffset / sizeof(float), bufferCount / sizeof(float)); float scale = replayGainScale * _gainScale; for (int i = 0; i < samplesSpan.Length; ++i) { samplesSpan[i] *= scale; } try { int writeCount = samplesSpan.Length * sizeof(float); playerStream.Write(buffer.Slice(bufferOffset, writeCount)); bufferOffset += writeCount; bufferCount -= writeCount; } catch (IOException ex) { Debug.WriteLine("Exception thrown while writing to ffplay: {0}", ex); goto restartPlayer; } if (bufferCount == 0) { bufferOffset = 0; } playerTrackPositionSamples += samplesSpan.Length; } } nextTrack: lock (_lock) { if (_playlistIndex + 1 < _playlist.Count) { _playlistIndex += 1; _trackPosition = 0; } else { _playing = false; _playlistIndex = -1; _trackPosition = 0; goto restartPlayer; } } } } } }