-
Notifications
You must be signed in to change notification settings - Fork 133
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
DASH: Be more optimistic on the buffer depth of DASH contents #1483
Conversation
fc6e35e
to
fb9176d
Compare
Overview -------- We were debugging some ad insertion usage, where an ad would be dynamically inserted at a live content's start on the initial Manifest request. An application reported to us that while playing such content with the RxPlayer, we were starting a few seconds into the ad instead of right at the beginning of it. When looking at segment requests we saw that the first media segment was never requested: we always started with the second one instead. Issue ----- After investigation, I found out that one of the issue, was that the `MPD@timeShiftBufferDepth` attribute of the produced stream was on the first Manifest request exactly equal to the duration of the video segments generated until now. Yet the RxPlayer always interpreted that it could only play segments whose ending timestamp is inferior or equal to the "live edge" (the live position basically, which monotically increases as time increases) and, more importantly here, whose starting timestamp is superior or equal to that same live edge minus the `timeShiftBufferDepth`. All this is not shocking, and other players have a similar interpretation here, but I noticed that this was why we were not requesting the first segment on the problematic content: as some milliseconds passed between the time the Manifest is parsed and the time at which we began choosing a segment to request, our "live edge" as further in the future (by the same amount of milliseconds) and thus the minimum timestamp we can request will also be further in the future - and ahead of the first segment position by the same amount of milliseconds. How to fix this --------------- So the fix seemed to be to either raise the `MPD@timeShiftBufferDepth` server-side or to raise the tolerance of what can still be requested RxPlayer-side. I dived into the DASH specification (5th edition) - which is a little hard to interpret here - but I found the following passage: > Assume the parameter availabilityTimeOffset is determined as the sum of all values of @availabilityTimeOffset on all levels that are processed in determining the URL for the corresponding segment. If the attribute @availabilityTimeOffset is not present, the value is of availabilityTimeOffset is 0. Then for services with MPD@type='dynamic', the Segment availability start time Tavail[i] for a Segment i in a specific Period is determined as MPD@availabilityStartTime + PeriodStart + MediaSegment[i].startTime + MediaSegment[i].duration - availabilityTimeOffset and the Segment availability end time is determined as MPD@availabilityStartTime + PeriodStart + MediaSegment[i].startTime + @timeshiftBufferDepth + 2*MediaSegment[i].duration At the very end, it seems that we have to re-apply a segment's duration, on top of the `timeShiftBufferDepth` to know when it is not available anymore (they indicate "2 times the duration"). So I guess we may have been too pessimistic with how we previously considered whether a segment could be requested or not. How other players treat this ---------------------------- Because the people behind the ad-insertion tool told me they succeeded to rely on the shaka-player, I looked at what they did on this issue. It turns out that they have roughly the same interpretation that we had for the minimum requestable position (`live edge - timeshiftBufferDepth`) but their "live edge" was basically offset by `- MPD@maxSegmentDuration`, so in the end they were removing the MPD's maximum segment duration from the minimum requestable position relatively to us. If I had to guess why they do that, it may be that they clonflate the "live edge" concept (the timestamp pointing to the current last media data basically) and what in the RxPlayer we call the "maximum safe position" (the last timestamp for which we're sure that a segment is currently available) where the RxPlayer make those two very different concepts and properties.
fb9176d
to
c453d11
Compare
src/parsers/manifest/dash/common/__tests__/manifest_bounds_calculator.test.ts
Show resolved
Hide resolved
I was just thinking about a case (that were already possible) and I'm not sure how the player handle this: The segment is not available anymore so we should fall into error again, or does the player run a logic to determine if the segment is still available when the request was retried ? |
We already though of that exact scenario hehehe! :P From the /**
* Returns `true` if a Segment returned by this index is still considered
* available.
* Returns `false` if it is not available anymore.
* Returns `undefined` if we cannot know whether it is still available or not.
* @param {Object} segment
* @returns {Boolean|undefined}
*/
isSegmentStillAvailable(segment: ISegment): boolean | undefined; It is used like this in the downloadingQueue.addEventListener("requestRetry", (payload) => {
callbacks.warning(payload.error);
if (segmentsLoadingCanceller.signal.isCancelled()) {
return; // If the previous callback led to loading operations being stopped, skip
}
const retriedSegment = payload.segment;
const { index } = representation;
if (index.isSegmentStillAvailable(retriedSegment) === false) {
checkStatus();
} else if (index.canBeOutOfSyncError(payload.error, retriedSegment)) {
callbacks.manifestMightBeOufOfSync();
}
}); NOTES:
|
Thanks for your explanation! |
Overview
We were debugging some ad insertion usage, where an ad would be dynamically inserted at a live content's start on the initial Manifest request.
An application reported to us that while playing such content with the RxPlayer, we were starting a few seconds into the ad instead of right at the beginning of it. When looking at segment requests we saw that the first media segment was never requested: we always started with the second one instead.
Issue
After investigation, I found out that the issue was that the
MPD@timeShiftBufferDepth
attribute of the produced stream was on the first Manifest request exactly equal to the duration of the video segments generated until now.Yet the RxPlayer always interpreted that it could only play segments whose ending timestamp is inferior or equal to the "live edge" (the live position basically, which monotically increases as time increases) and, more importantly here, whose starting timestamp is superior or equal to that same live edge minus the
timeShiftBufferDepth
.All this is not shocking, and other players have a similar interpretation here, but I noticed that this was why we were not requesting the first segment on the problematic content: as some milliseconds passed between the time the Manifest is parsed and the time at which we began choosing a segment to request, our "live edge" was further in the future (by the same amount of milliseconds) and thus the minimum timestamp we can request will also be further in the future - and ahead of the starting timestamp of the first segment by the same amount of milliseconds (so too late for it).
How to fix this
So the fix seemed to be to either raise the
MPD@timeShiftBufferDepth
server-side or to raise the tolerance of what can still be requested RxPlayer-side.I dived into the DASH specification (5th edition) - which is a little hard to interpret here - but I found the following passage:
At the very end, it seems that we have to re-apply a segment's duration, on top of the
timeShiftBufferDepth
to know when it is not available anymore (they indicate "2 times the duration").So I guess we may have been too pessimistic with how we previously considered whether a segment could be requested or not.
How other players treat this
Because the people behind the ad-insertion tool told me they succeeded to rely on the shaka-player, I looked at what they did on this issue.
It turns out that they have roughly the same interpretation that we had for the minimum requestable position (
live edge - timeshiftBufferDepth
) but their "live edge" was basically offset by- MPD@maxSegmentDuration
, so in the end they were removing the MPD's maximum segment duration from the minimum requestable position relatively to us.If I had to guess why they do that, it may be that they clonflate the "live edge" concept (the timestamp pointing to the current last theoretical media data basically) and what in the RxPlayer we call the "maximum safe position" (the last timestamp for which we're sure that a segment is currently available) where the RxPlayer make those two very different concepts and properties.