bvibber / OGVKit

Ogg and WebM media playback for iOS
MIT License
216 stars 67 forks source link

@synchronized (self.timeLock) and purpose? #180

Closed theprojectabot closed 4 years ago

theprojectabot commented 7 years ago

@brion thanks for the great kit! I'm going through trying to get the whole flow in my mind but had a question about your use of timeLock on your inputStreams, like => OGVHTTPInputStream. During init: you make an NSObject of timeLock and then use that as a mutex lock @synchronized when modifying any of the OGVHTTPInputStream properties. I'm guessing that you are doing this to put everything on the same thread so you don't have race conditions abound. Am I thinking that correctly? by @synchronized locking the timeLock property it sync locks all the other properties on the parent class so you can mutate their values...?

Im working on a player my self and trying to make sure I dont run into audio sync problems. Thanks for any tips!

bvibber commented 7 years ago

Right, there's a separate thread for the background download so it's trying to make sure there's no "surprises" when accessing stuff from either the download thread or the read thread.

For audio sync, the main thing is to make sure that the video decode doesn't get slow/behind, as I don't yet have good logic for skipping frames to get back in sync. (In my similar JavaScript framework ogv.js I have more advanced A/V synchronization, but haven't ported it over to OGVKit yet.)

theprojectabot commented 7 years ago

@brion thx for the knowledge - Ill dig through your js stuff for the AVSync. Shouldn't the presentation timestamp of the audio become the master clock and then I compare the presentation timestamp of the video frames and seek forward in the video queue til they matchup(or are within visual auditory ms perception limits) - as long as those presentation timestamps have the same source master time reference?

theprojectabot commented 7 years ago

I see your bisecting seek - cool. Ill dig into that.

bvibber commented 7 years ago

Yes the master clock is based on the audio: if a video frame's presentation timestamp is in the future, we wait until that time arrives, while if it's now or in the past then we output it. The problem is that if video decoding is slow (due to a particularly high-motion scene requiring more resources, or just being too high a resolution for the CPU) it will get more and more out of sync.

In ogv.js, there's now some logic to re-synchronize in this condition by seeing that audio has reached the presentation time of a keyframe coming up in the video packet stream: the intermediate frames are skipped, and video continues decoding and playing from the keyframe, now back in sync with audio.

I hope to copy this logic over to OGVKit when time permits. :)

You should be able to similarly re-sync by manually forcing a seek, especially if on a local file. (On network that might be ssllooww)

theprojectabot commented 7 years ago

Good to know. You are saying slow on network because the bisecting manual force seek for re-sync is unbounded in a network stream vs a flash/ssd hosted local file.

bvibber commented 7 years ago

Exactly; on network bisect can mean a lot of round-trips, which is high latency. Much faster on local file storage, and almost instant if in-memory.

bvibber commented 7 years ago

Also -- if file has an index, then seeking is much faster because we don't have to do a full bisect, and only need one or two network round-trips. This is usually default on WebM videos, but often not on ogg or audio-only files. (For ogg, using ffmpeg2theora instead of ffmpeg will create an index in the "ogg skeleton" track.)

theprojectabot commented 7 years ago

@brion So I have been looking at your audio sync code. With avsampledisplaylayer how are you making sure that the audioqueue and the enqueuedSample are in sync with eachother?