-
Notifications
You must be signed in to change notification settings - Fork 425
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
ExoPlayer signals Player.STATE_ENDED
with MPD transition from dynamic to static
#1441
Comments
…amic to static This checkin fixes Issue androidx#1441 where the player transitons to `Player.STATE_ENDED` once the buffer runs out on a DASH start-over playlist that has transitioned from dynamic to static. The fix detects the DASH Period has changed offset to the window, which occurs when the origin vendor follows the DASH-IF recommendations in *Section 4.6.4. Transition Phase between Live and On-Demand* , summerized as: - adds the attribute `MPD@mediaPresentationDuration` - removes the attribute `MPD@minimumUpdatePeriod` - `Period@start` is removed (if it was present) - `Period@duration` is added (in case more than 1 period is present) - `Adaptationset .SegmentTemplate@presentationTimeOffset` is set to earliest presentation time of a segment in the Adaptationset The MPD change does not affect the render position or the segment timeline at all, however the cleanest way to implement this was to report a `PositionUpdateForPlaylistChange` which triggers a seek and flushes the current buffered content.
…amic to static This checkin fixes Issue androidx#1441 where the player transitons to `Player.STATE_ENDED` once the buffer runs out on a DASH start-over playlist that has transitioned from dynamic to static. The fix detects the DASH Period has changed offset to the window, which occurs when the origin vendor follows the DASH-IF recommendations in *Section 4.6.4. Transition Phase between Live and On-Demand* , summerized as: - adds the attribute `MPD@mediaPresentationDuration` - removes the attribute `MPD@minimumUpdatePeriod` - `Period@start` is removed (if it was present) - `Period@duration` is added (in case more than 1 period is present) - `Adaptationset .SegmentTemplate@presentationTimeOffset` is set to earliest presentation time of a segment in the Adaptationset The MPD change does not affect the render position or the segment timeline at all, however the cleanest way to implement this was to report a `PositionUpdateForPlaylistChange` which triggers a seek and flushes the current buffered content.
Thanks for the detailed explanation :) I'm still not fully sure I understand everything correctly. Let me rephrase what I understand and maybe you can point out where I got this wrong if needed:
If all of that makes sense, I think the fix needs to be in the
Could you confirm this matches your understanding? And if you agree on the proposed fix, we are happy to look into another PR to implement that. |
Hey @stevemayhew. We need more information to resolve this issue but there hasn't been an update in 14 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically. If you have more information that will help us get to the bottom of this, just add a comment! |
Sorry @tonihei I missed seeing your comment (I think you need to @stevemayhew to make GitHub notify me) Let me work on getting you access to the DASH-IF working group on this. Perhaps we can direct the solution not to alter presentationTimeOffset (which is the source of the issue). We have this code in our ExoPlayer version to deal with origin vendors that match the original DASH-IF guidelines (which encourage zeroing the Period start) It is less than ideal as it forces a vacuous seek, as only the period position changes. This causes needless rebuffing |
Thanks, please let me know if you discover anything new. |
@tonihei Here's the document that DASH-IF is working on: https://github.com/Dash-Industry-Forum/DASH-IF-IOP/blob/master/specs/live2vod/01-live2vod.inc.md We are not voting members anymore, but this is completely the wrong approach if we want to avoid what this pull request "fixes". I've started working on a pull request to re-write this document, but not sure I will have much weight. Here's the link to my changes (WIP): https://github.com/stevemayhew/DASH-IF-IOP/tree/update-transition-options Feel free to add whatever you can. |
I would say, for now, keep this pull request "DRAFT". We have this work-around in our code base, but it would be far better if origin vendors would get in-line behind the better approach to the live2vod transiton |
Okay, thanks! Please let us know if you find out something new and we can see how to incorporate that into our code. |
Version
Media3 main branch
More version details
Main@1ffeafecc374ed82d94ce16fb57c23f99cb78765
Devices that reproduce the issue
Any
Devices that do not reproduce the issue
None
Reproducible in the demo app?
Yes
Use Case Background
Start Over / Catch Up (SoCu) is a use case where live playback is stored by the origin in a rolling buffer that the clients can address within a time window in order to perform a "Start Over", that is re-start live playback of an in-progress linear at the start of the program bounded to the end. This is typically done with a "start-over URL" is a SoCu URL where start_time is in the past and end_time is in the future. The origin will play this as live (dynamic MPD) until the end_time is reached then transition to VOD (static MPD). The VOD is accessible (the "Catch Up" case) for some time after the end_time, always starting as a simple static MPD.
Issue Steps
The steps to recreate the use-case are:
It is expected that once end_time is in the past the MPD becomes static (see background notes below on "Transitioning Live to Static"). Playback should continue and play all the way to the end of the show, with ExoPlayer it transitons to
Player.STATE_ENDED
as soon as the current buffered media is exausted.Transitioning Live to Static (On-Demand)
The DASH-IF IOP Working Group on updating the description of how to do this properly in a working group that is updating the IOP "Section 4 Liver Services". This is in the DASH-IF Interoperability WG, I am a reviewer for this and am looking at how ExoPlayer handles it.
The origin that reproduces this bug is following these guidelines (as currently written). The basic transiton to static does the following
Period@duration
to the on-demand content durationPeriod@startTime
to 0.SegmentTemplate@presentationTimeOffset
to map the existing segments time to the new period start at 0.Analysis
Note that the working group has put a "fix" for this in
dash.js
, see issue Dash.js issue #3311, this "fix" is far from perfect as the fix does not appear to update the HTMLMediaElement's view of time correctly so seeks are not possible. For ExoPlayer a much more robust fix is possible as the mapping from Timeline to Period position is completely in control of ExoPlayer code.My analysis of the ExoPlayer code shows it is handling the update of the period to a fixed duration correctly (setting the duration) but not reseting the mapping to render time correctly (so the current Period Position does not update)
Background
This background material is for readers that are not familure with how ExoPlayer handles position internally.
Positions In ExoPlayer
ExoPlayer maintains position in three coordinate spaces:
PlaybackInfo.positionUs
, this is position relative to the current playingPeriod@startTime
for DASH (note for HLS this is 0 as HLS is "single period". Most of ExoPlayer internally maintains position in the Period Time coordinate space. Window Position maps to Period Position via thePeriod.positionInWindowUs
.As ExoPlayer loads segments and extracts samples from them the actual queued timestamps are adjusted to Period Position as they are, for DASH the position on the sample timeline, actual EPT of the samples is adjusted to Period Position using the
presentationTimeOffset
when theMediaChunk
is queued for loading. For HLS there is a singlePeriod
that starts at time 0, and sample PTS/EPT time is normalized to this time by the timestamp master (selected by theTimestampAdjuster
)User Facing Position
ExoPlayer exposes getCurrentPosition() to the client (UI). For non-ad playback this is the position relative to the start of the current playing Window. If the window is "live" (Window.isLive()), then the Window.windowStartTimeMs will be the time since the epoch of the start of the window. For HLS
windowStartTimeMs
comes from theEXT-X-PROGRAM-DATE-TIME
, and for DASH it is the availability windowPeriod Position
ExoPlayer maintains multiple Periods in a set of
MediaPeriodHolder
objects, these match up with DASH Periods. The methodstoPeriodTime()
andfromPeriodTime()
map between render position (the Sample Timeline) and Period PositionSuggested Fix
Looking at the code in
ExoPlayerImplInternal.handleMediaSourceListInfoRefreshed()
IMO the solution is to recoginze the Period Position has changed and updatePlaybackInfo.positionUs
to match this, note therenderPositionUs
would not change and it would be best not to stop and/or flush the renderers as only the mapping has changed not the actual samples and segments.Logging shows the update is seem (the change to
positionInWindow
after the newDashTimeline
is copied) but this is after the position discontinuity check, here is the change to dynamic is false:Note this is proved out pretty simply by issuing a seek right after the source update,
The pull request pull #1451 basically does this.
Expected result
Media plays to the end.
Actual result
It is expected that once end_time is in the past the MPD becomes static (see background notes below on "Transitioning Live to Static"). Playback should continue and play all the way to the end of the show, with ExoPlayer it transitons to
Player.STATE_ENDED
as soon as the current buffered media is exausted.Media
I can send a sample URL with instructions how to set start/end time.
Bug Report
adb bugreport
to [email protected] after filing this issue.The text was updated successfully, but these errors were encountered: