Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Technical question about audio sync #1

Closed
ilwoonam75 opened this issue May 11, 2020 · 4 comments
Closed

Technical question about audio sync #1

ilwoonam75 opened this issue May 11, 2020 · 4 comments

Comments

@ilwoonam75
Copy link

ilwoonam75 commented May 11, 2020

Hello.

First of all, thank you for your great project.

We are currently working on a video player project, and trying to use this project as a baseline.

I understand the video sync method with pts, but I don't understand how you synchronize audio with pts.

Can you explain how to sync audio?

The code block I don't understand is

if (decoder.hasAudio)
{
// Audio Sync
if (Math.Abs((audioDelayTicks - delayTicks) / 10000) > 220)
{
if (curTicks + audioExternalDelay < decoder.aStreamInfo.startTimeTicks || curTicks + audioExternalDelay > decoder.aStreamInfo.durationTicks)
audioDelayTicks = -10000000; // Force Resync Later (Audio Paused)
else if (ResynchAudio(curTicks - audioExternalDelay)) audioDelayTicks = delayTicks;
}
// Audio Frames [Callback]
if ( aFrames.Count > 0) SendAudioFrames();
}

@SuRGeoNix
Copy link
Owner

SuRGeoNix commented May 11, 2020

Hey, I'm glad you find useful :)

The audio sync is the most difficult part! I'm doing it by syncing audio samples with the video frames. At the beginning of Screamer you can see the following code:

// Audio
audioFlowTicks = DateTime.UtcNow.Ticks;
long audioDelayTicks = delayTicks;
if (decoder.hasAudio)
	if (vFrame.timestamp + audioExternalDelay < decoder.aStreamInfo.startTimeTicks || vFrame.timestamp + audioExternalDelay > decoder.aStreamInfo.durationTicks) 
		audioDelayTicks = -10000000; // Force Resync Later (Audio Paused)

> 	else ResynchAudio(vFrame.timestamp - audioExternalDelay, true);

After I make sure that Audio/Video queues are filled with the right timestamps and synced I keep track of audioDelayTicks/delayTicks. Those (delayTicks) are actually how much "off time" are currently the video frames and when they are much enough we reset them to the the current timestamp. But when the video frames are going off we don't reset audio directly (audioDelayTicks), in that way we would have to do it all the time. So when the distance is more than 220ms it will do the re-sync.

In that way you make sure that your video frames and your audio samples will be screamed almost at the same "allowed" time frame.

After that I use audioFlowBytes/ audioBytesPerSecond which are configured based on the audio configuration / sample ratio etc...

audioBytesPerSecond =(int)( _RATE * (_BITS / 8.0) * _CHANNELS);

to make sure that I will send the flow in the same rate that the audio player requires to keep the audio queue low (which means memory low). But even after all that, I still had a problem with the audio player (naudio). Each audio player has a different way that it works :) It means that NAudio requires some time/bytes to load its buffer before play. That's why you will see the comment...

const int NAUDIO_DELAY_MS = -330; // Probably waits to fill it's buffer? had to use this for sync https://www.youtube.com/watch?v=ucZl6vQ_8Uo

Finally, there are more thinks that you could add to make it better. For example, you could sync during silence. So the listeners will not notice the difference.

Hope that helped, but if not you could check more details about audio sync here:

Synchronizing the Audio

@ilwoonam75
Copy link
Author

Thank you very much for your answer.

@SuRGeoNix
Copy link
Owner

No problem dude. You made me look back again the code and I found a couple of issues, check out my latest commit for details!

@ilwoonam75
Copy link
Author

Let me check your new commit.
Thank you again.

SuRGeoNix pushed a commit that referenced this issue Apr 21, 2021
Fixing Thread.Abort() on decoder/demuxer
SuRGeoNix pushed a commit that referenced this issue Apr 23, 2021
- Adding Take a Snapshot feature
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
Fixing Thread.Abort() on decoder/demuxer
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
- Adding Take a Snapshot feature
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
Fixing Thread.Abort() on decoder/demuxer
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
- Adding Take a Snapshot feature
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
Fixing Thread.Abort() on decoder/demuxer

Former-commit-id: 908e06e
SuRGeoNix pushed a commit that referenced this issue Aug 25, 2021
- Adding Take a Snapshot feature

Former-commit-id: 9736831
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants