Exemple #1
0
        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;
            }
        }
Exemple #2
0
        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());
        }
Exemple #3
0
        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();
        }
Exemple #4
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 = 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;
                }
            }
        }
Exemple #5
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;
                }
            }
        }