public void write(VideoLib.AudioFrame frame) { if (audioBuffer == null || frame.Length == 0) { return; } // store pts for this frame and the byte offset at which this frame is // written pts = frame.Pts; ptsPos = offsetBytes; int playPos, writePos; audioBuffer.GetCurrentPosition(out playPos, out writePos); if (playPos <= offsetBytes && offsetBytes < writePos) { log.Warn("playpos:" + playPos.ToString() + " offset:" + offsetBytes.ToString() + " writePos:" + writePos.ToString() + " dataSize:" + frame.Length.ToString()); offsetBytes = writePos; } audioBuffer.Write(frame.Data, 0, frame.Length, offsetBytes, LockFlags.None); offsetBytes = (offsetBytes + frame.Length) % bufferSizeBytes; if (audioState == AudioState.START_PLAY_AFTER_NEXT_WRITE) { audioBuffer.Play(0, PlayFlags.Looping); audioState = AudioState.PLAYING; } }
public void play(VideoLib.AudioFrame frame) { if (audioBuffer == null || frame.Length == 0) { return; } // store pts for this frame and the byte offset at which this frame is // written pts = frame.Pts; ptsPos = offsetBytes; int playPos, writePos; audioBuffer.GetCurrentPosition(out playPos, out writePos); if (playPos <= offsetBytes && offsetBytes < writePos) { //log.Warn("playpos:" + playPos.ToString() + " offset:" + offsetBytes.ToString() + " writePos:" + writePos.ToString() + " dataSize:" + frame.Length.ToString()); offsetBytes = writePos; } audioBuffer.Write(frame.Data, 0, frame.Length, offsetBytes, LockFlags.None); offsetBytes = (offsetBytes + frame.Length) % bufferSizeBytes; if (Status == BufferStatus.None) { // start playing audioBuffer.Play(0, PlayFlags.Looping); } //System.Diagnostics.Debug.Print("AudioClock:" + getAudioClock().ToString()); }
void audioRefreshTimer_Tick(Object sender, EventArgs e) { restartaudio: VideoLib.AudioFrame audioFrame = videoDecoder.FrameQueue.getDecodedAudioFrame(); if (audioFrame == null) { return; } //videoDebug.AudioFrames = videoDebug.AudioFrames + 1; //videoDebug.AudioFrameLength = audioFrame.Length; // if the audio is lagging behind too much, skip the buffer completely double diff = getVideoClock() - audioFrame.Pts; if (diff > 0.2 && diff < 3 && syncMode == SyncMode.AUDIO_SYNCS_TO_VIDEO) { log.Warn("dropping audio buffer, lagging behind: " + (getVideoClock() - audioFrame.Pts).ToString() + " seconds"); goto restartaudio; } //adjustAudioSamplesPerSecond(audioFrame); adjustAudioLength(audioFrame); audioPlayer.write(audioFrame); int frameLength = audioFrame.Length; double actualDelay = synchronizeAudio(frameLength); if (actualDelay < 0) { // delay too small, play next frame as quickly as possible //videoDebug.NrAudioFramesLaggingBehind = videoDebug.NrAudioFramesLaggingBehind + 1; goto restartaudio; } // start timer with delay for next frame audioRefreshTimer.Interval = (int)(actualDelay * 1000 + 0.5); audioRefreshTimer.start(); }
void adjustAudioLength(VideoLib.AudioFrame frame) { //videoDebug.AudioFrameLengthAdjust = 0; if (syncMode == SyncMode.AUDIO_SYNCS_TO_VIDEO) { int n = videoDecoder.NrChannels * videoDecoder.BytesPerSample; double diff = audioPlayer.getAudioClock() - getVideoClock(); if (Math.Abs(diff) < AV_NOSYNC_THRESHOLD) { // accumulate the diffs audioDiffCum = diff + audioDiffAvgCoef * audioDiffCum; if (audioDiffAvgCount < AUDIO_DIFF_AVG_NB) { audioDiffAvgCount++; } else { double avgDiff = audioDiffCum * (1.0 - audioDiffAvgCoef); // Shrinking/expanding buffer code.... if (Math.Abs(avgDiff) >= audioDiffThreshold) { int wantedSize = (int)(frame.Length + diff * videoDecoder.SamplesPerSecond * n); // get a correction percent from 10 to 60 based on the avgDiff // in order to converge a little faster double correctionPercent = Misc.clamp(10 + (Math.Abs(avgDiff) - audioDiffThreshold) * 15, 10, 60); //Util.DebugOut(correctionPercent); //AUDIO_SAMPLE_CORRECTION_PERCENT_MAX int minSize = (int)(frame.Length * ((100 - correctionPercent) / 100)); int maxSize = (int)(frame.Length * ((100 + correctionPercent) / 100)); if (wantedSize < minSize) { wantedSize = minSize; } else if (wantedSize > maxSize) { wantedSize = maxSize; } // make sure the samples stay aligned after resizing the buffer wantedSize = (wantedSize / n) * n; if (wantedSize < frame.Length) { // remove samples //videoDebug.AudioFrameLengthAdjust = wantedSize - frame.Length; frame.Length = wantedSize; } else if (wantedSize > frame.Length) { // add samples by copying final samples int nrExtraSamples = wantedSize - frame.Length; //videoDebug.AudioFrameLengthAdjust = nrExtraSamples; byte[] lastSample = new byte[n]; for (int i = 0; i < n; i++) { lastSample[i] = frame.Data[frame.Length - n + i]; } frame.Stream.Position = frame.Length; while (nrExtraSamples > 0) { frame.Stream.Write(lastSample, 0, n); nrExtraSamples -= n; } frame.Stream.Position = 0; frame.Length = wantedSize; } } } } else { // difference is TOO big; reset diff stuff audioDiffAvgCount = 0; audioDiffCum = 0; } } }
void adjustAudioSamplesPerSecond(VideoLib.AudioFrame frame) { //videoDebug.AudioFrameLengthAdjust = 0; if (syncMode == SyncMode.AUDIO_SYNCS_TO_VIDEO) { int n = videoDecoder.NrChannels * videoDecoder.BytesPerSample; double diff = audioPlayer.getAudioClock() - getVideoClock(); if (Math.Abs(diff) < AV_NOSYNC_THRESHOLD) { // accumulate the diffs audioDiffCum = diff + audioDiffAvgCoef * audioDiffCum; if (audioDiffAvgCount < AUDIO_DIFF_AVG_NB) { audioDiffAvgCount++; } else { double avgDiff = audioDiffCum * (1.0 - audioDiffAvgCoef); // Shrinking/expanding buffer code.... if (Math.Abs(avgDiff) >= audioDiffThreshold) { int wantedSize = (int)(frame.Length + diff * videoDecoder.SamplesPerSecond * n); // get a correction percent from 10 to 60 based on the avgDiff // in order to converge a little faster double correctionPercent = Misc.clamp(10 + (Math.Abs(avgDiff) - audioDiffThreshold) * 15, 10, 60); //Util.DebugOut(correctionPercent); //AUDIO_SAMPLE_CORRECTION_PERCENT_MAX int minSize = (int)(frame.Length * ((100 - correctionPercent) / 100)); int maxSize = (int)(frame.Length * ((100 + correctionPercent) / 100)); if (wantedSize < minSize) { wantedSize = minSize; } else if (wantedSize > maxSize) { wantedSize = maxSize; } // adjust samples per second to speed up or slow down the audio Int64 length = frame.Length; Int64 sps = videoDecoder.SamplesPerSecond; int samplesPerSecond = (int)((length * sps) / wantedSize); //videoDebug.AudioFrameLengthAdjust = samplesPerSecond; audioPlayer.SamplesPerSecond = samplesPerSecond; } else { audioPlayer.SamplesPerSecond = videoDecoder.SamplesPerSecond; } } } else { // difference is TOO big; reset diff stuff audioDiffAvgCount = 0; audioDiffCum = 0; } } }