-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Shaka is trying to download more slices than exist for an ad inserted into a dash live stream #1304
Comments
Okay, that makes sense. I agree with the math. But since the ad period doesn't have a duration in the manifest, we don't know how that it's 73.045 seconds long until there's another period following it. I'm guessing, but by that time, we may already have tried to buffer that non-existent segment. Maybe this is a silly question, but if you know the ad period is 73.045 seconds, why not put that in the ad period's duration attribute?
I haven't re-read the spec or IOP since we started this conversation, but that's not how we interpret it. We treat minimumUpdatePeriod as how often to update the manifest, period. It doesn't have anything to do with the length of a period. Now, if we were generating a segment list from SegmentTemplate+duration every time we parsed a manifest update, it might work the way you are suggesting. But instead, we have these functions that calculate segment references on-the-fly: let find = function(periodTime) {
if (periodTime < 0)
return null;
else if (periodDuration && periodTime >= periodDuration)
return null;
return Math.floor(periodTime / segmentDuration);
};
let get = function(position) {
let segmentStart = position * segmentDuration;
// Cap the segment end at the period end, to avoid period transition issues
// in StreamingEngine.
let segmentEnd = segmentStart + segmentDuration;
if (periodDuration) segmentEnd = Math.min(segmentEnd, periodDuration);
// Do not construct segments references that should not exist.
if (segmentEnd < 0)
return null;
else if (periodDuration && segmentStart >= periodDuration)
return null;
let getUris = function() {
let mediaUri = MpdUtils.fillUriTemplate(
template, id, position + startNumber, bandwidth,
segmentStart * timescale);
return ManifestParserUtils.resolveUris(baseUris, [mediaUri]);
};
return new shaka.media.SegmentReference(
position, segmentStart, segmentEnd, getUris, 0, null);
}; Until the next content period appears, periodDuration here is null, so there is no cap on the segments we think we can find in that period. All that said, I don't expect we should fail, even if we try to buffer ahead to a non-existent segment. When the new period shows up, ideally, we would recognize that we had buffered to the end of the ad period already, and move on to the next period. |
The answer to that is that I don't know the actual duration when the period starts. In my test case I personally know that I am going to end it at 73.0.45 seconds, but we don't require people signaling an ad break in a stream to tell us exactly when it will end when they start it. Referring to "Guidelines for Implementation: DASH-IF Interoperability Points" at http://dashif.org/w/2015/04/DASH-IF-IOP-v3.0.pdf I think section 4.4 actually says it pretty well, and I am leaning on that section quite a bit when it comes to what I am expecting the player to do here. Specifically many of the "Backgrounds and Assumptions" in 4.4.1 hold true in this case.
Well, give the name "minimum update period" that makes perfect sense, but my reading of the spec seems to suggest that it also has a dual purpose when the last period in the manifest has an unknown duration.
That last line is the most important one here and has me looking to 4.4 Specifically 4.4.2.2
So it seems to me in the case of an unknown final period duration, the minimum update period provides a cap on how many segments can be downloaded. Specifically the way I interpret is this: I will have a given window of segments I know about on any given MPD update. Say at one point in time I know that one period ends 15 seconds through the window, but I don't have an end time for the second period. I will put the second period in with the appropriate start time and then set the minimum update time to 15 seconds. That 15 seconds should be the cap on the number of segments that a player will download. So when you say:
That feels wrong to me from what I am reading. I don't think it should be uncapped. I believe the min period update is supposed to provide a cap in this instance. I could put a duration on the final period in the mpd trying to limit what is downloaded before the next update, but that doesn't seem to be the way that the spec says periods of unknown duration should be handled, and I would also have to just keep increasing that duration potentially after every update. Let me know how you interpret this. |
So I am going to take back the comments I made earlier about having a stream that actually duplicated this easily, as I had a bad time sync server URL that caused me other problems. For now let's just talk about this in terms of the spec and what you have already said about Shaka's behavior (uncapped download), vs what I think the spec says should be happening (cap final period based on minimumUpdatePeriod). |
At this point, it's difficult to understand what's happening until we can reproduce it locally and debug it directly. Can you provide us with some way to reproduce ths issue? |
We could discuss it from a spec point of view, but that's largely academic if everything plays correctly. A counterexample would be helpful. |
I would interpret 4.4.2.2 as indicating that NOW is moving forward all the time, independent of the fetch time. NOW refers to the live edge, so it is moving forward as the client clock moves. From DASH IOP 4.3.2.2.2
So it is the current wall-clock time on the content server, not the fetch time. This is why clock sync is important; both the client and the server need synchronized clocks so we can determine availability consistently. Also from the DASH spec:
|
I am having trouble getting a stream that reproduces ONLY that issue, but I have managed to get pretty close with this. There is some additional issues with transitioning between assets, largish gaps, that don't seem to be jumped even with large gap jumping enabled for example, but whenever I reload the MPD it start playing again, which tells suggests to me I am at least pretty close (as in If I start on the period playback will work, but if I am transitioning into it from a previous period it does not). This asset doesn't ALWAYS show the error the issue with downloading beyond the end of the segment, but it does pretty frequently on asset transition. The error seen as a 403 fetching a segment that doesn't exist because it is beyond the end of the segment, as described by the body of the initial entry to this bug. This stream inserts a 118 second break every 5 minutes. This break is filled mostly by a movie trailer and then a couple seconds of "Ad Slate".
|
First, I think the Second, you are reusing I have also occasionally seen the video stop or a black frame on seeks and the video refuses to move forward. This appears to be a DRM problem and I will look into it more. |
Ok, it wasn't clear to me that I should not reuse period ID's - In fact I thought I was supposed to because of what was referred to as "Continuous Period Offering" in the IOP. I made a period ID change (to make period IDs unique) and I think I fixed the PTO issue as well, and now that stream seems to be playing pretty well. I guess what must have been happening was that the second period with a given id was ignored as you suggested and we must have kept downloading slices derived from the first period with a given ID to end up downloading beyond where we should have been. In any case I think that solves my current problem. Thanks! |
I actually believe it is a bug to drop a period because it has the same identifier btw. I believe the IOP describes valid situations in which this is done in section 3.2.12, but I am more interested in having thing play than in worrying specifically about the spec. So I have changed my periods ids to be unique, now that they are things are playing so I am happy, but you might want to consider that this could be a valid use case. |
If you can recommend a way to disambiguate when period IDs are reused, I would consider it. It's really just about matching the new manifest to the old one on update. |
Well, anytime the period id and the period start time were the same in my content, that meant it was the same period. If the period id was the same and the start time changed, that meant it was a new period, but it was continuous with the previous one that had the same id. |
Hrm... We have someone else asking us to in #1341 to allow the period start time to change, which is apparently allowed by the spec currently. But in Dash-Industry-Forum/DASH-IF-IOP#160, they are discussing disallowing the changing of period start, which would be more practical and in line with our current requirements. |
From what I can tell, the Period ID needs to be unique. Section 3.2.12 of the IOP guidelines talks about the AdaptationSet IDs, not the Period IDs. The DASH spec is pretty clear on this in section 5.3.2.2, Table 4.
|
Okay, that works for me. |
Ok, I misread that. I conceed that it does appear that period ids are required to be unique. |
ManifestRequestsLeadingToShakaDownloadingTooFar.har.zip
Have you read the FAQ and checked for duplicate open issues?:
Yes
What version of Shaka Player are you using?:
I am working out of master currently
Can you reproduce the issue with our latest release version?:
I have only tried master so far.
Can you reproduce the issue with the latest code from
master
?:Yes
Are you using the demo app or your own custom app?:
Demo App
If custom app, can you reproduce the issue using our demo app?:
NA
What browser and OS are you using?:
Chrome
What are the manifest and license server URIs?:
This is tricky to because I have to setup a live stream with the same repeating ad break, and I don't have the infrastructure set up to do this right this moment.
I will work on doing this, but I am hoping just having the manifest will at least be able to start the conversation. Maybe you see something you think I should be doing in manifest generation for example, although I do feel like this is likely a bug.
What did you do? What did you expect to happen? What actually happened?
I am going to answer all of these questions below:
I play back a live stream successfully until an ad gets inserted. The ad is 73.045 seconds in length and it causes a new period to show up in my presentation. All my adaptation sets use SegmentTemplates with$Number$ expansion to give the names of the segments for download. An example of exactly what that looks like in my presentation is here:
Since my ad is 73.045 Seconds long and my duration is 4.096 -- Download must stop at D00000017.m4f. Shaka keeps going though and tries to download a D00000018.m4f -- Since this slice doesn't exist playback of course breaks.
So I get a manifest update that shows this upcoming period at 14:57:49 that looks like this:
============Transitioning Into Ad================
============================
Then ~20 Seconds later (at 14:58:09) another manifest update that looks like this - The ad period is the only one now visible:
============Nothing but ad================
============================
Then another ~20 Seconds Pass and the manifest is unchanged -- Still only the ad period is visible (at 14:58:30)
============Nothing but ad================
============================
Then after another ~20 Seconds we get another update where we can see a new period coming up (at 14:58:50)
============Transitioning out of ad================
============================
You can see from this last manifest update that the length of the ad period can be determined from the difference in the start times to be 1252.853 - 1179.808 == 73.045 seconds long.
Our numbering starts at 0 and the duration is 4096 with a timescale of 1000 so this requires 18 slices numbered from $RepresentationID$00000000.m4f - $RepresentationID$00000017.m4f
The problem I have is that shaka keeps trying to download a $RepresentationID$00000018.m4f
I cannot see why this would be happening.
According to 4.4.2.2 - "If the Period is the last one in the MPD and the MPD @minimumUpdatePeriod is present, then the time PEwc[i] is obtained as the sum of NOW and the value of MPD @minimumUpdatePeriod
So I the way I understand the spec, the MinimumUpdatePeriod determines the length of that last period - Potentially Extending it over and over again. In my case I am going to have a 73.045 second period, but it increases by at most the minimum update period of ~20 seconds 3 times before a new period shows up to set the absolute length of the period. Since the update happens 3 times with a minimum update period of ~20 seconds each time, shaka should be assuming that period is at MOST 60 seconds long before it sees the next period and can determine the exact length of 73.045 seconds.
Am I doing something wrong here?
I feel like the console error shows pretty obviously what the problem is, but for completeness I am including it here:
VM226 http_plugin.js:111 GET http://stgec-ausc.uplynk.com/80C078/ausc/slices/338/c77021f506ae42c799fe165c9634267e/338ffab7c2b143e2ba718473ce1a13f3/TK_00000018.m4f 403 (Forbidden)
(anonymous) @ VM226 http_plugin.js:111
shaka.net.HttpPlugin @ VM226 http_plugin.js:39
backoffOperation.chain @ VM173 networking_engine.js:471
wrapChainCallback_ @ VM168 abortable_operation.js:221
promise.then @ VM168 abortable_operation.js:182
Promise.then (async)
chain @ VM168 abortable_operation.js:162
shaka.net.NetworkingEngine.send_ @ VM173 networking_engine.js:465
shaka.net.NetworkingEngine.makeRequestWithRetry_ @ VM173 networking_engine.js:415
requestFilterOperation.chain @ VM173 networking_engine.js:328
wrapChainCallback_ @ VM168 abortable_operation.js:221
promise.then @ VM168 abortable_operation.js:182
Promise.then (async)
chain @ VM168 abortable_operation.js:162
shaka.net.NetworkingEngine.request @ VM173 networking_engine.js:327
shaka.media.StreamingEngine.fetch_ @ VM199 streaming_engine.js:2063
shaka.media.StreamingEngine.fetchAndAppend_ @ VM199 streaming_engine.js:1424
shaka.media.StreamingEngine.update_ @ VM199 streaming_engine.js:1167
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1053
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
(anonymous) @ VM199 streaming_engine.js:1444
Promise.then (async)
shaka.media.StreamingEngine.fetchAndAppend_ @ VM199 streaming_engine.js:1434
shaka.media.StreamingEngine.update_ @ VM199 streaming_engine.js:1167
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1053
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
(anonymous) @ VM199 streaming_engine.js:1444
Promise.then (async)
shaka.media.StreamingEngine.fetchAndAppend_ @ VM199 streaming_engine.js:1434
shaka.media.StreamingEngine.update_ @ VM199 streaming_engine.js:1167
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1053
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
setTimeout (async)
shaka.media.StreamingEngine.scheduleUpdate_ @ VM199 streaming_engine.js:2120
shaka.media.StreamingEngine.onUpdate_ @ VM199 streaming_engine.js:1055
VM199 streaming_engine.js:1473 (audio:694) failed fetch and append: code=1001
The entirety of the manifest requests can be seen in the .har attachment if you want to look explicitly at more than what I have outlined above.
The text was updated successfully, but these errors were encountered: