shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.21k stars 1.34k forks source link

Support playing VOD with non-zero first Period start #1884

Closed ssadovski007 closed 4 years ago

ssadovski007 commented 5 years ago

Have you read the FAQ and checked for duplicate open issues? yes

What version of Shaka Player are you using? 2.3.3

Can you reproduce the issue with our latest release version? yes, Shaka Player v2.4.7-uncompiled

Can you reproduce the issue with the latest code from master? didn't try yet

Are you using the demo app or your own custom app? Demo app

What browser and OS are you using? macOS 10.14.4 / Chrome Browser Version 73.0.3683.103 (Official Build) (64-bit)

What are the manifest and license server URIs? Sent to shaka-player-issues@google.com mailgroup

What did you do? Try to play a clearstream manifest configured as On-Demand Services with Live profiles (a chapter 3.10 of https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf, section 3.10.2 - On-Demand Services with Live profiles)

What did you expect to happen? It seems Shaka is only assuming a Live profile for dynamic manifests, which is incorrect because based of the spec static manifests are also possible.

Type dynamic manifest plays fine and the same logic expects for static manifests of Live profile.

What actually happened? Shaka Player failed playout the manifest composed as On-Demand Services with Live profiles with assertion failed: period duration must be a positive integer.

TheModMaker commented 5 years ago

For your static one period asset, there are several problems with it:

You have a mediaPresentationDuration attribute of 30 minutes, but the first Period's start time is 432100 hours. The mediaPresentationDuration must match the total duration of the media, including Period start time adjustments.

You have a presentationTimeOffset of 15555621015146590 and your segment times have huge values. These do not represent safe integers when used with JavaScript numbers. So we cannot represent their times accurately. We do not support playing content with large timestamps (larger than 2^51).

We interpret VOD to always start at 0 and play to the duration. This means that for your content, there will be 432100 hours of no content at the beginning of your content. Usually, the Period@start attribute will be 0 indicating the start of the content. However, for static content, it may make more sense to use the first Period's start value as the start of the content. The IOP doesn't say that with live profile what the start of the content should be. I've opened #1885 to discuss handling non-zero start for VOD.

joeyparrish commented 5 years ago

@ssadovski007, what piece of software created this content? Can you file a bug with them?

ssadovski007 commented 5 years ago

You have a mediaPresentationDuration attribute of 30 minutes, but the first Period's start time is 432100 hours. The mediaPresentationDuration must match the total duration of the media, including Period start time adjustments.

Sorry but I am not sure I understand that correctly. Given MPD@mediaPresentationDuration, MPD@availabilityStartTime and one-Period@start I would expect Shaka Player plays content starting from MPD@availabilityStartTime + Period@start lasting MPD@mediaPresentationDuration duration (one-Period element does not supply @duration attribute)

TheModMaker commented 5 years ago

This is VOD content, so we don't use availabilityStartTime. That is only used in Live content to determine where to start in the presentation. In Live content, we use the current wall-clock time and the availabilityStartTime to determine where in the presentation we currently are. But for VOD, we always start playing at presentation time of 0.

The Period@start attribute specifies the presentation time that the Period starts at. That means that if the Period@start is 10 minutes, then that Period should start at the 10 minute mark in the video. Since you only have one Period, there is no content until the first Period.

The mediaPresentationDuration specifies the presentation time that the video ends at. This means you need to include the Period@start value in that number. It should be equal to the Period@start + Period@duration of the last Period element.

So basically, for VOD content, the video always starts at 0 and goes to mediaPresentationDuration. But you also specify that the Period@start is way in the future, so is outside this range. For your content, there is nothing for 432100 hours and then the first segment starts then.

See this doc for more info on the presentation timeline.

ssadovski007 commented 5 years ago

@TheModMaker thanks for the explanation.

It's clear that

However, I am not convinced yet that bad content label is applicable here for the one-Period manifest provided (besides Number limitation in JS).

Please let me explain with a reference to https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf spec.

As per the following extracts from the spec (please ref to the full spec by the link above)

3.10. On-Demand Services Static services may be offered using live DASH profiles as defined in clause 3.10.2 as well as on- demand DASH profiles in clause 3.10.3. The use of live profiles is particularly interesting for cases where the content was offered live, but then also made available in a catchup or time shift format as documented in clause 4.6.3.10.2 as well as on-demand DASH profiles in clause.

This is exactly what we try to achieve: to have live content recorded as separate programs (catchups). Manifest file has profiles="urn:mpeg:dash:profile:isoff-live:2011" and type="static" defined.

Going down into sub-sections of the 3.10 section.

3.10.2. On-Demand Services with Live profiles MPD@mediaPresentationDuration - provides the duration of the Media Presentation Period@start - the start time of the Period relative to the MPD availability start time.

The inner section below describes how DASH client would suppose to calculate Period's start / end times.

3.10.2.2.3. Period Information For static Media Presentations, each regular Period i in the MPD is assigned a

  • Period start time PSwc[i] in MPD time,
  • Period end time PEwc[i], in MPD time.

The Period start time PSwc[i] for a regular Period i is determined according to section 5.3.2.1 of ISO/IEC 23009-1 [4]:

  • If the attribute @start is present in the Period, then PSwc[i] is the value of this attribute minus the value of @start of the first Period

The Period end time PEwc[i] for a regular Period i is determined as follows:

  • If the Period is the last one in the MPD, the time PEwc[i] is obtained as the Media Presentation Duration MPDur, with MPDur the value of MPD@mediaPresentationDuration

Given the above formula and the values from one-Period manifest provided, where

The final start/end values of the Period would be 0 and PT30M0S (30 min) respectively.

I did a test and removed Period@start="PT432100H35M1.514S" attribute or replaced it with Period@start="PT0" and Shaka did play content successfully with progress bar of 30 minutes long, what is expected.

Having said the above, I am considering Shaka Player is not properly handling Period(s) in VOD with Live profiles manifest with respect to the spec.

p.s. I am testing a manifest pre-processor which re-populates value of @start attributes of the next Period where the first Period starts from 0.

TheModMaker commented 5 years ago

So maybe the start time should be adjusted to 0. The wording in the DASH (ISO/IEC 23009-1:2014) spec is confusing on the matter. (I quote the DASH spec instead since the IOP is supposed to be a subset and using different profiles shouldn't change behavior) Section 5.3.2.1 starts with:

  • If the attribute @start is present in the Period, then the Period is a regular Period and the PeriodStart is equal to the value of this attribute.

The whole spec uses PeriodStart as an absolute value referring to the start of the Period and doesn't talk at all about subtracting the first Period time. It also never makes any reference to a difference between Live and VOD. However, in the prose that follows in that list it includes:

For any regular Period the following holds: PeriodStart reflects the actual time that should elapse after playing the media of all prior Periods in this Media Presentation relative to the PeriodStart time of the first Period in the Media Presentation. The Period extends until the PeriodStart of the next Period, ...

The first part sides with starting at 0 and having a gap; but the part about relative to... could be interpreted to mean we should subtract the first Period. But then this would be different for Live too? It is confusing.

But I think you are probably correct. There is really no reason to have a gap at the start of VOD content. I'll relabel this issue and just close #1885.

Also note that for shifting the timeline, it is probably not that complex. We don't need to shift the segments themselves since they are already relative to the Period. So all we need to do is change the Period start/duration and fix the handling of mediaPresentationDuration.

ssadovski007 commented 5 years ago

Also note that for shifting the timeline, it is probably not that complex. We don't need to shift the segments themselves since they are already relative to the Period. So all we need to do is change the Period start/duration and fix the handling of mediaPresentationDuration.

I tried that using proxy script and Shaka Player v2.4.7 (demo app) and dash.js (Reference Client 2.9.3) both play content fine (one-Period and multi-Period)

joeyparrish commented 4 years ago

Is this still an issue in our latest release, v2.5.9?

ShanePhelan commented 4 years ago

Hi @joeyparrish

I think we've got a similar issue to this where we've got a VOD manifest using a live profile - timeshifted manifest.

The presentationTimeOffset of the video is out of sync with the segment timeline start time by 31 milliseconds. If I manually change this to match the segment timeline start time then the content works. I've been told the usual by the stream vendor that the manifest is fine because it plays in dashjs, bitmovin etc etc.

Is this a bug in the player a bad manifest or is there a setting I can use to get it to work?

live2vod.mpd.txt

joeyparrish commented 4 years ago

We would need a URL, not a copy of the manifest. A copy of the manifest would let us parse it, but not fetch any content. To debug your issue, @ShanePhelan, we would need a manifest URL that is accessible to us. You can send those to us privately at shaka-player-issues@google.com.

ShanePhelan commented 4 years ago

Hi @joeyparrish sorry for the late response, we've had a long bank holiday weekend here in the UK. I've sent an email to shaka-player-issues@google.com with the stream details.

ShanePhelan commented 4 years ago

@joeyparrish I should've also mentioned that CORS is not correctly enabled on that stream so you'll have to launch Chrome / Firefox with web security disabled. Unfortunately I won't be able to get it enabled as we usually have a CDN in front of it that handles the CORS part.

joeyparrish commented 4 years ago

I have two bits of good news:

First, if you configure the player to jump "large" gaps, this plays fine in current versions of Shaka Player. For example, I get this message in the console:

Ignoring large gap at 0 size 5.959334

But with this config:

player.configure('streaming.jumpLargeGaps', true);

Instead I get this message:

Jumping forward 5.959334 seconds because of gap before start time of 5.959334

and the content plays from the non-zero start time. Browsers will generally play through a larger gap at the start of the content than in the middle, but Chrome, for example, will only tolerate up to a 1s gap at the start. Gap-jumping in Shaka Player takes over and handles larger gaps.

Secondly, this content in it's live form exposed a bug in our recent Period-flattening work for v2.6 (#1339), so I can now write new test cases for that and improve it.

I'm going to close this as working correctly in our current release branch, v2.5.x.

Thanks, and let us know if we can do anything else for you.

ShanePhelan commented 4 years ago

Hi @joeyparrish

Thanks for investigating and pointing out the jumpLargeGaps config.

One other thing we've noticed is that in this timeshift scenario we never receive the 'canplay' event from the video element, but we do on other Dash clients. We rely on this event to display our Play CTA. I've noticed in the shaka player demo that the UX relies on the buffering event to hide the spinner. The content in question causes the spinner to never disappear indicating that it's still in a buffering state. You can play the content by clicking play, but it still seems as though something is wrong.

Is there a way to get the canplay event to fire? Or workout via some other event / warning etc that canplay probably wont fire so fake it?

Thanks Shane

joeyparrish commented 4 years ago

I see the 'canplay' event firing with your content. Perhaps you're adding the event listener too late?

video.addEventListener('canplay', () => console.log('canplay'));
player.configure('streaming.jumpLargeGaps', true);

Then I click the play button and I see this in the console:

Jumping forward 5.429334 seconds because of gap before start time of 5.429334
canplay

The 'canplay' event won't fire until after the player jumps over the gap, because until then, there isn't enough content buffered at the current position (0). After seeking to the start of the buffer, there is enough content buffered at that position, so the event fires.

ShanePhelan commented 4 years ago

Hi @joeyparrish

Your clicking play and then seeing the canplay event. We load the manifest and wait until the canplay event is fired before displaying the play button / calling play, otherwise we could have a scenario where the user has clicked play before the content is ready.

I understand there isn't enough content buffered at that position. Other dash clients seem to implement an 'auto' jump and then buffer the content on the load call. Is there a way to do something similar in Shaka?