SRGSSR / srgmediaplayer-apple

An advanced media player library, simple and reliable
MIT License
158 stars 33 forks source link

Add accurate date support for streams with date information #32

Closed defagos closed 4 years ago

defagos commented 6 years ago

For streams containing date information, we should rely on this specific information instead.

For information, AVPlayer and AVPlayerItem provide seek to date methods. Moreover, AVPlayerItem provides a currentDate property, which probably not nil when date information is available from the stream.

defagos commented 4 years ago

I could find a playable sample stream with DVR capabilities and date information (#EXT-X-PROGRAM-DATE-TIME) embedded in the playlist: Das Erste Live, with playlist https://mcdn.daserste.de/daserste/int/master.m3u8.

defagos commented 4 years ago

I implemented this feature as follows:

defagos commented 4 years ago

I had forgotten we had a date property already, which was returning a date for all livestreams. I propose we merge its behavior with the new currentDate behavior and remove it. Though this change is breaking, the currentDate name is more consistent with the currentTime similar property.

We could of course also introduce a temporary deprecation to avoid this breaking change. To be discussed.

defagos commented 4 years ago

Properly supporting dates with segments required some more work. The approach outlined above only works when starting playback at a position, or seeking to a position. When playing a segment, though, we need to be able to start and end at given dates. The current SRGSegment protocol, having only time range information was not sufficient. We need dates.

Here are the options I considered in order, each one being refined to lead to the next one:

With these changes, segments can be defined with times or dates (even a mixture of both, though this is unlikely). SRGMark and SRGMarkRange can then be mapped to a player CMTime and CMTimeRange, depending on whether the stream contains timestamp information. For conversion, I added dedicated methods to SRGMediaPlayerController, so that accurate positions can be calculated when a reference date / time relationship can be extracted from the stream.

The rest of the implementation is rather straightforward. No further changes are required to internals since the controller works with converted CMTime only internally. After initial conversions, the code stays the same, which is good since the logic to adjust positions (keeping positions within valid ranges, including possible tolerances), quite complicated, works with CMTimes.

defagos commented 4 years ago

When using a slider, it is also useful to have date information (if available) alongside the time information already provided.

I therefore initially thought: "Let's have SRGMark returned by SRGMediaPlayerController, and in general everywhere clients previously received a CMTime from the public AP!". This seemed appealing.

Well, it is not. A mark should always be checked for the associated controller, only in very rare cases should a mark be interpreted as is. If controllers were to returns marks for location information, this would be a shame, as the controller returning the mark is known (the controller itself!), but the mark does not contain this piece of information, forcing clients to remember the controller to interpret a mark for.

For this reason, time and date known to a controller must not be returned together as SRGMark. We could pack them into another CMTime / NSDate dual object just to group related information, but I don't see the point in doing so.

I therefore improved the existing date support as follows:

This is available for review on the feature/date-info branch.

defagos commented 4 years ago

If timestamps are not available in the stream, our code was guessing the date from the DVR end window and the current time. This was not reliable, as this relationship oscillates because of chunks being added or removed.

To fix this it suffices to cache the date / player time relationship only once. This could also be made for streams with timestamps, but according to my tests the information is in such cases correct. If this still proves to have slight noticeable variations, we can apply the same strategy in this case and cache the date / player time relationship once.