diff --git a/src/FFmpegAudioDecoder.cs b/src/FFmpegAudioDecoder.cs index ef4cebe..e3140a5 100644 --- a/src/FFmpegAudioDecoder.cs +++ b/src/FFmpegAudioDecoder.cs @@ -315,13 +315,7 @@ private unsafe void RunDecodeLoop() } else { - if (_isMicrophone) - { - RaiseError("Cannot read more frame"); - return; - } - else - OnEndOfFile?.Invoke(); + OnEndOfFile?.Invoke(); } } } diff --git a/src/FFmpegAudioSource.cs b/src/FFmpegAudioSource.cs index 1cd72c8..ba4d2a9 100644 --- a/src/FFmpegAudioSource.cs +++ b/src/FFmpegAudioSource.cs @@ -23,6 +23,7 @@ public class FFmpegAudioSource : IAudioSource, IDisposable internal byte[] buffer; // Avoid to create buffer of same size private int frameSize; + private String path; private BasicBufferShort _incomingSamples = new BasicBufferShort(48000); @@ -32,7 +33,6 @@ public class FFmpegAudioSource : IAudioSource, IDisposable internal MediaFormatManager _audioFormatManager; public event EncodedSampleDelegate? OnAudioSourceEncodedSample; - public event Action? OnEndOfFile; public event SourceErrorDelegate? OnAudioSourceError; #pragma warning disable CS0067 @@ -55,25 +55,26 @@ public FFmpegAudioSource(IAudioEncoder audioEncoder, uint frameSize = 960) public unsafe void CreateAudioDecoder(String path, AVInputFormat* avInputFormat, bool repeat = false, bool isMicrophone = false) { + this.path = path; _audioDecoder = new FFmpegAudioDecoder(path, avInputFormat, repeat, isMicrophone); _audioDecoder.OnAudioFrame += AudioDecoder_OnAudioFrame; + _audioDecoder.OnError += AudioDecoder_OnError; + _audioDecoder.OnEndOfFile += AudioDecoder_OnEndOfFile; + } - _audioDecoder.OnError += (msg) => - { - OnAudioSourceError?.Invoke(msg); - Dispose(); - }; - + private void AudioDecoder_OnEndOfFile() + { + AudioDecoder_OnError("End of file"); + } - _audioDecoder.OnEndOfFile += () => - { - logger.LogDebug($"File source decode complete for {path}."); - OnEndOfFile?.Invoke(); - _audioDecoder.Dispose(); - }; + private void AudioDecoder_OnError(string errorMessage) + { + logger.LogDebug($"Audio - Source error for {path} - ErrorMessage:[{errorMessage}]"); + OnAudioSourceError?.Invoke(errorMessage); + Dispose(); } - + public Boolean InitialiseDecoder() { return _audioDecoder?.InitialiseSource(_audioFormatManager.SelectedFormat.ClockRate) == true; @@ -90,12 +91,9 @@ public List GetAudioSourceFormats() public void SetAudioSourceFormat(AudioFormat audioFormat) { - if (_audioFormatManager != null) - { - logger.LogDebug($"Setting audio source format to {audioFormat.FormatID}:{audioFormat.Codec} {audioFormat.ClockRate}."); - _audioFormatManager.SetSelectedFormat(audioFormat); - InitialiseDecoder(); - } + logger.LogDebug($"Setting audio source format to {audioFormat.FormatID}:{audioFormat.Codec} {audioFormat.ClockRate}."); + _audioFormatManager.SetSelectedFormat(audioFormat); + InitialiseDecoder(); } public void RestrictFormats(Func filter) @@ -164,14 +162,9 @@ public Task Start() { if (!_isStarted) { - if (_audioDecoder == null) - { - OnAudioSourceError?.Invoke("Initialization has not be done correctly"); - } - else + if (_audioDecoder != null) { _isStarted = true; - InitialiseDecoder(); _audioDecoder.StartDecode(); } } @@ -221,9 +214,14 @@ public void Dispose() _isStarted = false; if (_audioDecoder != null) - _audioDecoder.Dispose(); + { + _audioDecoder.OnAudioFrame -= AudioDecoder_OnAudioFrame; + _audioDecoder.OnError -= AudioDecoder_OnError; + _audioDecoder.OnEndOfFile -= AudioDecoder_OnEndOfFile; - _audioDecoder = null; + _audioDecoder.Dispose(); + _audioDecoder = null; + } } } } diff --git a/src/FFmpegFileSource.cs b/src/FFmpegFileSource.cs index e0f0e7c..efa3cdb 100644 --- a/src/FFmpegFileSource.cs +++ b/src/FFmpegFileSource.cs @@ -24,8 +24,6 @@ public class FFmpegFileSource: IAudioSource, IVideoSource, IDisposable public event EncodedSampleDelegate? OnVideoSourceEncodedSample; public event RawVideoSampleFasterDelegate? OnVideoSourceRawSampleFaster; - public event Action? OnEndOfFile; - public event SourceErrorDelegate? OnAudioSourceError; public event SourceErrorDelegate? OnVideoSourceError; @@ -50,7 +48,6 @@ public unsafe FFmpegFileSource(string path, bool repeat, IAudioEncoder? audioEnc _FFmpegAudioSource.OnAudioSourceEncodedSample += _FFmpegAudioSource_OnAudioSourceEncodedSample; _FFmpegAudioSource.OnAudioSourceRawSample += _FFmpegAudioSource_OnAudioSourceRawSample; - _FFmpegAudioSource.OnEndOfFile += _FFmpegAudioSource_OnEndOfFile; _FFmpegAudioSource.OnAudioSourceError += _FFmpegAudioSource_OnAudioSourceError; } @@ -58,11 +55,9 @@ public unsafe FFmpegFileSource(string path, bool repeat, IAudioEncoder? audioEnc { _FFmpegVideoSource = new FFmpegVideoSource(); _FFmpegVideoSource.CreateVideoDecoder(path, null, repeat, false); - _FFmpegVideoSource.InitialiseDecoder(); _FFmpegVideoSource.OnVideoSourceEncodedSample += _FFmpegVideoSource_OnVideoSourceEncodedSample; _FFmpegVideoSource.OnVideoSourceRawSampleFaster += _FFmpegVideoSource_OnVideoSourceRawSampleFaster; - _FFmpegVideoSource.OnEndOfFile += _FFmpegVideoSource_OnEndOfFile; _FFmpegVideoSource.OnVideoSourceError += _FFmpegVideoSource_OnVideoSourceError; } } @@ -77,16 +72,6 @@ private void _FFmpegVideoSource_OnVideoSourceError(string errorMessage) OnVideoSourceError?.Invoke(errorMessage); } - private void _FFmpegVideoSource_OnEndOfFile() - { - OnEndOfFile?.Invoke(); - } - - private void _FFmpegAudioSource_OnEndOfFile() - { - OnEndOfFile?.Invoke(); - } - private void _FFmpegVideoSource_OnVideoSourceEncodedSample(uint durationRtpUnits, byte[] sample) { OnVideoSourceEncodedSample?.Invoke(durationRtpUnits, sample); @@ -288,7 +273,6 @@ public void Dispose() { _FFmpegAudioSource.OnAudioSourceEncodedSample -= _FFmpegAudioSource_OnAudioSourceEncodedSample; _FFmpegAudioSource.OnAudioSourceRawSample -= _FFmpegAudioSource_OnAudioSourceRawSample; - _FFmpegAudioSource.OnEndOfFile -= _FFmpegAudioSource_OnEndOfFile; _FFmpegAudioSource.OnAudioSourceError -= _FFmpegAudioSource_OnAudioSourceError; _FFmpegAudioSource.Dispose(); @@ -300,7 +284,6 @@ public void Dispose() { _FFmpegVideoSource.OnVideoSourceEncodedSample -= _FFmpegVideoSource_OnVideoSourceEncodedSample; _FFmpegVideoSource.OnVideoSourceRawSampleFaster -= _FFmpegVideoSource_OnVideoSourceRawSampleFaster; - _FFmpegVideoSource.OnEndOfFile -= _FFmpegVideoSource_OnEndOfFile; _FFmpegVideoSource.OnVideoSourceError -= _FFmpegVideoSource_OnVideoSourceError; _FFmpegVideoSource.Dispose(); diff --git a/src/FFmpegVideoDecoder.cs b/src/FFmpegVideoDecoder.cs index e151205..8c8eed1 100644 --- a/src/FFmpegVideoDecoder.cs +++ b/src/FFmpegVideoDecoder.cs @@ -323,13 +323,7 @@ private void RunDecodeLoop() } else { - if (_isCamera) - { - RaiseError("Cannot read more frame"); - return; - } - else - OnEndOfFile?.Invoke(); + OnEndOfFile?.Invoke(); } } } diff --git a/src/FFmpegVideoSource.cs b/src/FFmpegVideoSource.cs index 1b0efb7..1b9ec88 100644 --- a/src/FFmpegVideoSource.cs +++ b/src/FFmpegVideoSource.cs @@ -19,6 +19,8 @@ public class FFmpegVideoSource: IVideoSource, IDisposable internal bool _isPaused; internal bool _isClosed; + private String path; + internal FFmpegVideoDecoder ? _videoDecoder; internal VideoFrameConverter? _videoFrameYUV420PConverter = null; @@ -34,8 +36,6 @@ public class FFmpegVideoSource: IVideoSource, IDisposable public event SourceErrorDelegate? OnVideoSourceError; - public event Action? OnEndOfFile; - #pragma warning disable CS0067 public event RawVideoSampleDelegate? OnVideoSourceRawSample; #pragma warning restore CS0067 @@ -44,25 +44,29 @@ public FFmpegVideoSource() { _videoFormatManager = new MediaFormatManager(_supportedVideoFormats); _videoEncoder = new FFmpegVideoEncoder(); + path = ""; } public unsafe void CreateVideoDecoder(String path, AVInputFormat* avInputFormat, bool repeat = false, bool isCamera = false) { + this.path = path; _videoDecoder = new FFmpegVideoDecoder(path, avInputFormat, repeat, isCamera); + _videoDecoder.OnVideoFrame += VideoDecoder_OnVideoFrame; + _videoDecoder.OnError += VideoDecoder_OnError; + _videoDecoder.OnEndOfFile += VideoDecoder_OnEndOfFile; + } - _videoDecoder.OnError += (msg) => - { - OnVideoSourceError?.Invoke(msg); - Dispose(); - }; + private void VideoDecoder_OnEndOfFile() + { + VideoDecoder_OnError("End of file"); + } - _videoDecoder.OnEndOfFile += () => - { - logger.LogDebug($"File source decode complete for {path}."); - OnEndOfFile?.Invoke(); - Dispose(); - }; + private void VideoDecoder_OnError(string errorMessage) + { + logger.LogDebug($"Video - Source error for {path} - ErrorMessage:[{errorMessage}]"); + OnVideoSourceError?.Invoke(errorMessage); + Dispose(); } public Boolean InitialiseDecoder(Dictionary? decoderOptions = null) @@ -81,7 +85,9 @@ public void SetVideoSourceFormat(VideoFormat videoFormat) { logger.LogDebug($"Setting video source format to {videoFormat.FormatID}:{videoFormat.Codec} {videoFormat.ClockRate}."); _videoFormatManager.SetSelectedFormat(videoFormat); + InitialiseDecoder(); } + public void RestrictFormats(Func filter) { _videoFormatManager.RestrictFormats(filter); @@ -178,11 +184,7 @@ public Task Start() { if (!_isStarted) { - if (_videoDecoder == null) - { - OnVideoSourceError?.Invoke("Initialization has not be done correctly"); - } - else + if (_videoDecoder != null) { _isStarted = true; _videoDecoder?.StartDecode(); @@ -230,11 +232,21 @@ public void Dispose() { _isStarted = false; - _videoDecoder?.Dispose(); - _videoDecoder = null; + if (_videoDecoder != null) + { + _videoDecoder.OnVideoFrame -= VideoDecoder_OnVideoFrame; + _videoDecoder.OnError -= VideoDecoder_OnError; + _videoDecoder.OnEndOfFile -= VideoDecoder_OnEndOfFile; - _videoEncoder?.Dispose(); - _videoEncoder = null; + _videoDecoder.Dispose(); + _videoDecoder = null; + } + + if (_videoEncoder != null) + { + _videoEncoder.Dispose(); + _videoEncoder = null; + } } } diff --git a/src/SIPSorceryMedia.FFmpeg.csproj b/src/SIPSorceryMedia.FFmpeg.csproj index 5d3a8aa..12e183b 100644 --- a/src/SIPSorceryMedia.FFmpeg.csproj +++ b/src/SIPSorceryMedia.FFmpeg.csproj @@ -5,7 +5,7 @@ - 1.2 + 1.2.1 true enable preview diff --git a/test/FFmpegFileAndDevicesTest/Program.cs b/test/FFmpegFileAndDevicesTest/Program.cs index 66ee5f7..9e87b31 100644 --- a/test/FFmpegFileAndDevicesTest/Program.cs +++ b/test/FFmpegFileAndDevicesTest/Program.cs @@ -140,7 +140,8 @@ static private Task CreatePeerConnection() if ((AudioSourceType == AUDIO_SOURCE.FILE_OR_STREAM) && (AudioSourceFile == VideoSourceFile)) { SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(VideoSourceFile, RepeatVideoFile, new AudioEncoder(), 960, true); - fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); + fileSource.OnAudioSourceError += (msg) => PeerConnection.Close(msg); + fileSource.OnVideoSourceError += (msg) => PeerConnection.Close(msg); videoSource = fileSource as IVideoSource; audioSource = fileSource as IAudioSource; @@ -148,7 +149,7 @@ static private Task CreatePeerConnection() else { SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(VideoSourceFile, RepeatVideoFile, new AudioEncoder(), 960, true); - fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); + fileSource.OnVideoSourceError += (msg) => PeerConnection.Close(msg); videoSource = fileSource as IVideoSource; } @@ -164,7 +165,10 @@ static private Task CreatePeerConnection() camera = cameras.Last(); } if (camera != null) + { videoSource = new SIPSorceryMedia.FFmpeg.FFmpegCameraSource(camera.Path); + videoSource.OnVideoSourceError += (msg) => PeerConnection.Close(msg); + } else throw new NotSupportedException($"Cannot find adequate camera ..."); @@ -187,8 +191,11 @@ static private Task CreatePeerConnection() primaryMonitor = monitors[0]; } - if(primaryMonitor != null) + if (primaryMonitor != null) + { videoSource = new SIPSorceryMedia.FFmpeg.FFmpegScreenSource(primaryMonitor.Path, primaryMonitor.Rect, 10); + videoSource.OnVideoSourceError += (msg) => PeerConnection.Close(msg); + } else throw new NotSupportedException($"Cannot find adequate monitor ..."); break; @@ -200,7 +207,7 @@ static private Task CreatePeerConnection() { case AUDIO_SOURCE.FILE_OR_STREAM: SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(AudioSourceFile, RepeatAudioFile, new AudioEncoder(), 960, false); - fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); + fileSource.OnAudioSourceError += (msg) => PeerConnection.Close(msg); audioSource = fileSource as IAudioSource; break;