private void RestartAudio() { if (aScreamer != null) { aScreamer.Abort(); } if (decoder.hasAudio) { Log("[AUDIO SCREAMER] Restarting ..."); aScreamer = new Thread(() => { decoder.PauseAudio(); if (!isPlaying || videoStartTicks == -1) { return; } Thread.Sleep(20); lock (aFrames) aFrames = new ConcurrentQueue <MediaFrame>(); AudioResetClbk.Invoke(); decoder.SeekAccurate((int)((CurTime - audioExternalDelay) / 10000) - 50, FFmpeg.AutoGen.AVMediaType.AVMEDIA_TYPE_AUDIO); decoder.RunAudio(); while (isPlaying && (decoder.hasAudio && aFrames.Count < AUDIO_MIX_QUEUE_SIZE)) { Thread.Sleep(20); } try { AudioScreamer(); } catch (Exception) { } }); aScreamer.SetApartmentState(ApartmentState.STA); aScreamer.Start(); } }
private bool ResynchAudio(long syncTimestamp) { // Give it 1 Second if (DateTime.UtcNow.Ticks - audioLastSyncTicks < 10000000) { return(false); } audioLastSyncTicks = DateTime.UtcNow.Ticks; lock (aFrames) { Log("[AUDIO] Resynch Request to -> " + syncTimestamp / 10000); // Initialize Audio Player / Clear Audio Frames AudioResetClbk.BeginInvoke(null, null); aFrames = new Queue <MediaFrame>(); // Seek Audio Decoder (syncTimestamp - 2 Audio Frames) to ensure audioFirstTimeStamp < syncTimestamp (-50ms to make sure will get a previous Frame within QueueSize) decoder.SeekAccurate((int)((syncTimestamp / 10000) - 50), FFmpeg.AutoGen.AVMediaType.AVMEDIA_TYPE_AUDIO); decoder.RunAudio(); // Fill Audio Frames int escapeInfinity = 0; while (aFrames.Count < AUDIO_MIX_QUEUE_SIZE && isPlaying && decoder.isRunning) { escapeInfinity++; Thread.Sleep(10); if (escapeInfinity > 50) { Log("[ERROR EI2] Audio Frames Queue will not be filled by decoder"); return(false); } } // Validate We have AudioTimestamp < syncTimestamp MediaFrame aFrame = aFrames.Peek(); MediaFrame aFramePrev = new MediaFrame(); if (aFrame.timestamp > syncTimestamp) { Log("[AUDIO] Failed to force aFrame.timestamp < syncTimestamp (" + ", audioTimestamp: " + aFrame.timestamp + ", syncTimestamp: " + syncTimestamp + ")"); audioFlowTicks = DateTime.UtcNow.Ticks; audioFlowBytes = 0; SendAudioFrames(); return(false); } // Find Closest Audio Timestamp and Cut It precise while (aFrame.timestamp <= syncTimestamp && isPlaying) { if (aFrames.Count < 2) { return(false); } aFramePrev = aFrames.Dequeue(); aFrame = aFrames.Peek(); } if (!isPlaying) { return(false); } int removeBytes = (int)Math.Round((syncTimestamp - aFramePrev.timestamp) / ((1.0 / audioBytesPerSecond) * 10000 * 1000)); if (removeBytes > aFramePrev.data.Length) { removeBytes = aFramePrev.data.Length; } // Reset Timers & Fill Audio Player AudioFrameClbk(aFramePrev.data, removeBytes, aFramePrev.data.Length - removeBytes); audioFlowTicks = DateTime.UtcNow.Ticks; audioFlowBytes = 0; SendAudioFrames(); Log("[AUDIO] Resynch Successfully to -> " + aFramePrev.timestamp / 10000 + " ++"); return(true); } }