Ejemplo n.º 1
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 = Utils.clamp(10 + (Math.Abs(avgDiff) - audioDiffThreshold) * 15, 10, 60);

                            //Util.DebugOut(correctionPercent);

                            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;
                }
            }
        }
Ejemplo n.º 2
0
        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 = Utils.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;
                }
            }
        }
Ejemplo n.º 3
0
        void audioRefreshTimer_Tick(Object sender, EventArgs e)
        {
restartaudio:

            double actualDelay = 0.04;

            if (!videoDecoder.HasVideo)
            {
                updateObservableVariables();
            }

            // returns null when framequeue is paused or closed
            VideoLib.AudioFrame audioFrame = videoDecoder.FrameQueue.getDecodedAudioFrame();
            if (audioFrame == null)
            {
                // stop audio if playing
                audioPlayer.stop();

                if (VideoState == VideoState.CLOSED)
                {
                    audioPlayer.flush();
                    return;
                }
                // when paused spin idle
            }
            else
            {
                if (audioPlayer.Status == SharpDX.DirectSound.BufferStatus.None)
                {
                    // reset audio frame timer before (re)starting playing
                    audioFrameTimer = videoFrameTimer = HRTimer.getTimestamp();
                }

                audioPts = audioFrame.Pts;
                audioDts = audioFrame.Dts;

                // 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.play(audioFrame);

                int frameLength = audioFrame.Length;

                actualDelay = synchronizeAudio(frameLength);

                if (actualDelay < 0)
                {
                    // delay too small, play next frame as quickly as possible
                    goto restartaudio;
                }
            }

            // start timer with delay for next frame
            audioRefreshTimer.Interval = (int)(actualDelay * 1000 + 0.5);
            audioRefreshTimer.start();
        }