Skip to content
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

[DASHTree] handle new Period better #1175

Merged
merged 1 commit into from
Mar 13, 2023
Merged

Conversation

tmm1
Copy link
Contributor

@tmm1 tmm1 commented Feb 27, 2023

Description

i observed that on a playlist where new <Period> is added when going into commercial break, the player would stall out for 30s and then jump ahead in the stream.

the logs showed it as so:

2023-02-24 15:44:06.453 T:21159   debug <general>: CVideoPlayerVideo - Stillframe detected, switching to forced 29.970030 fps
2023-02-24 15:44:06.453 T:21146   debug <general>: Stream stalled, start buffering. Audio: 0 - Video: 0
2023-02-24 15:44:06.453 T:21159   debug <general>: CPtsTracker: pattern lost on diff 166833.335938, number of losses 1
2023-02-24 15:44:06.453 T:21146   debug <general>: CVideoPlayer::SetCaching - caching state 1
2023-02-24 15:44:06.453 T:21146   debug <general>: CDVDClock::SetSpeedAdjust - adjusted:0.000000
2023-02-24 15:44:06.453 T:21164   debug <general>: CDVDAudio::Pause - pausing audio stream
2023-02-24 15:44:07.244 T:2472    debug <general>: AddOnLog: inputstream.adaptive: ensureSegment: Begin WaitForSegment stream 1654049944917item-06item
2023-02-24 15:44:08.248 T:2475     info <general>: Skipped 9 duplicate messages..
...
2023-02-24 15:44:41.121 T:2763    debug <general>: AddOnLog: inputstream.adaptive: ensureSegment: Begin WaitForSegment stream 1654049944917item-06item
2023-02-24 15:44:41.808 T:21164    info <general>: Skipped 1 duplicate messages..
2023-02-24 15:44:41.808 T:21164    info <general>: CVideoPlayerAudio::Process - stream stalled
2023-02-24 15:44:41.808 T:21146   debug <general>: Stream stalled, start buffering. Audio: 0 - Video: 2
2023-02-24 15:44:41.809 T:21146   debug <general>: CVideoPlayer::SetCaching - caching state 1
2023-02-24 15:44:41.809 T:21164   debug <general>: CDVDAudio::Pause - pausing audio stream
2023-02-24 15:44:41.809 T:21146   debug <general>: CDVDClock::SetSpeedAdjust - adjusted:0.000000
2023-02-24 15:44:42.121 T:2768    debug <general>: AddOnLog: inputstream.adaptive: ensureSegment: Begin WaitForSegment stream 1654049944917item-06item
2023-02-24 15:44:42.323 T:21159    info <general>: Skipped 2 duplicate messages..
2023-02-24 15:44:42.323 T:21159 warning <general>: OutputPicture - timeout waiting for buffer
2023-02-24 15:44:42.422 T:2769    debug <general>: AddOnLog: inputstream.adaptive: ensureSegment: Begin WaitForSegment stream 1654049944917item-06item
2023-02-24 15:44:43.125 T:2771     info <general>: Skipped 6 duplicate messages..

Motivation and context

The code would not previously deal with new <Period> appearing, and would only map Period entries based on their index.

So if originally the MPD had one period, then all of a sudden it had two, only the first would be updated.

Eventually, if the old period was removed then all of a sudden it would resume playback but skip ahead because it would start adding segments from the new period into the old period again once the position (idx==0) matched again.

Now the code will properly insert new periods into the tree, and also notice when one period ends and switch into the next one.

This looks as so in the new logs:

RefreshLiveSegments: Inserting new Period (id=45124, start=23478067190)
ensureSegment: Switching to new Period (id=45124, start=23478067190)
ensureSegment: Switching to new AdaptationSet (startNumber=6014396)

How has this been tested?

compile and runtime tested using a local news stream that keeps adding new Period and was not working previously

Screenshots (if appropriate):

Types of change

  • Bug fix (non-breaking change which fixes an issue)
  • Clean up (non-breaking change which removes non-working, unmaintained functionality)
  • Improvement (non-breaking change which improves existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that will cause existing functionality to change)
  • Cosmetic change (non-breaking change that doesn't touch code)
  • None of the above (please explain below)

Checklist:

  • I have read the Contributing document
  • My code follows the Code Guidelines of this project
  • My change requires a change to the Wiki documentation
  • I have updated the documentation accordingly

@tmm1 tmm1 force-pushed the better-period-matching branch 3 times, most recently from 7ba0047 to f6b833e Compare February 28, 2023 05:07
@tmm1
Copy link
Contributor Author

tmm1 commented Feb 28, 2023

This works great now:

RefreshLiveSegments: Inserting new Period (id=45211, start=23511749873)                
ensureSegment: Switching to new Period (id=45211, start=23511749873)
ensureSegment: Switching to new Period (id=45211, start=23511749873)                   
EnableStream(1001: false)   
EnableStream(1002: false)
EnableStream(1003: false)   
InitializePeriod: Period (id=45211 start=23511749873)
Reusing DRM psshSets for new period!
DEMUX_SPECIALID_STREAMCHANGE
GetStreamIds()
GetStream(1001)
EnableStream(1001: true)
OpenStream(1001)

@matthuisman
Copy link
Contributor

i suspect DEMUX_SPECIALID_STREAMCHANGE is what we do in HLS for x-discontuity so this brings it in line with that?

@tmm1
Copy link
Contributor Author

tmm1 commented Feb 28, 2023

@matthuisman yea, also matches what happens with MPD VOD when it has multiple Periods. The STREAMCHANGE allows kodi to reinitialize playback and pick the proper streams from the newly available audio/video. It will also reinit drm so new period could use different keys or not have drm at all.

@matthuisman
Copy link
Contributor

Awesome!

Any clever ideas to stop frame rate switching on short periods? Users often find adverts trigger it and then it triggers again going back to main content. I can't think of any clean way to fix that

@CastagnaIT
Copy link
Collaborator

Any clever ideas to stop frame rate switching on short periods?

suggest to not spam this PR for OP discussions
however the problem (on kodi side) should be similar of the variable frame rate mkv frame rate switch problem that i tried to fix time ago

@CastagnaIT CastagnaIT added Type: Improvement non-breaking change which improves existing functionality Component: MPEG-DASH v21 Omega labels Feb 28, 2023
src/parser/DASHTree.cpp Outdated Show resolved Hide resolved
src/parser/DASHTree.cpp Outdated Show resolved Hide resolved
src/parser/DASHTree.cpp Outdated Show resolved Hide resolved
@tmm1 tmm1 force-pushed the better-period-matching branch 2 times, most recently from 13b58b5 to 212ac1d Compare March 1, 2023 18:17
@tmm1
Copy link
Contributor Author

tmm1 commented Mar 1, 2023

I ran this on a live stream for several hours today. There were 21 new periods and it worked seamlessly across them all. Ready to merge IMHO

@glennguy
Copy link
Contributor

glennguy commented Mar 2, 2023

I don't think that any changes should be needed to ensureSegment for this to work - HLS live multiperiod works correctly at the moment. When we come to the end of a stream the normal triggers should already end/close the stream and cause a streamchange packet to be sent.

Gut feeling is that stream IDs are causing you all the trouble.

Normally for VOD it would look like this in the log as you progress from first to second period:

EnableStream(1001: false)
EnableStream(1002: false)
DEMUX_SPECIALID_STREAMCHANGE
GetStreamIds()
GetStream(2001)
GetStream(2002)
OpenStream(2001)
OpenStream(2002)

Live HLS is similar but only first chapter is 100x, following chapters are the discontinuity sequence number * 1000 + stream number.

For DASH no seqence_ or initial_sequence values are set on periods.

I think that period ID for DASH can be alpha numeric so that doesn't help much though. So perhaps we just increment sequentially based on matching new periods to old periods?

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 2, 2023

I don't think that any changes should be needed to ensureSegment for this to work

You're right. I removed the changes from ensureSegment and it still works fine.

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 4, 2023

@glennguy this should now work for live dash with multi-period exactly the same way it does for VOD. AFAIK VOD has no issues with the lack of distinct stream ids so I think this is good to merge.

@glennguy
Copy link
Contributor

glennguy commented Mar 5, 2023

Thanks for updating @tmm1

I can't actually verify properly with the one from the dash live simulator, would you be able to have a look?

#KODIPROP:inputstream=inputstream.adaptive
#KODIPROP:inputstream.adaptive.manifest_type=mpd
#KODIPROP:inputstream.adaptive.manifest_update_parameter=full
http://livesim.dashif.org/livesim/periods_20/testpic_2s/Manifest.mpd

VOD has distinct stream IDs normally e.g period 1 video is usually 1001, period 2 2001 etc, I'm not certain this is an issue but thought it may be.

Not trying to be a pain, just thinking that it ideally works on more than the 1 test stream. I know there's going to be plenty of cases (maybe yours) where there's just the main program content, and we only ever see going from 1 period to 2, then back to 1. But it would be great to know it can work well in most if not all cases.

If you want we can bring this in and fix other cases going forward, what do you think?

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 7, 2023

I can't actually verify properly with the one from the dash live simulator, would you be able to have a look?

Seems in this one ISA is happen to continue streaming the Period it starts with. This is because SegmentTimeline is unbounded with no contents, and the pattern can continue forever. When a new period appears, it still follows the same exact template format.

In the real world MPDs I saw, the SegmentTimeline usually has S entries which tell it how many segments are available and ISA will eventually run out and that's what triggers it to move onto the new Period.

I know there's going to be plenty of cases (maybe yours) where there's just the main program content, and we only ever see going from 1 period to 2, then back to 1. But it would be great to know it can work well in most if not all cases.

In mine I saw it go up to 3-4 periods sometimes and it still works correctly.

If you want we can bring this in and fix other cases going forward, what do you think?

This would be my preference.

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 7, 2023

VOD has distinct stream IDs normally e.g period 1 video is usually 1001, period 2 2001 etc, I'm not certain this is an issue but thought it may be.

I found a VOD to test and confirmed the stream ids do change there. So I will try to make it work the same way here.

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 7, 2023

So I will try to make it work the same way here.

Done, confirmed it goes from 1001 to 2001 to 3001 on live stream.

@glennguy
Copy link
Contributor

Thanks @tmm1 for all the updates!

@glennguy glennguy merged commit 3b67f2f into xbmc:Omega Mar 13, 2023
@glennguy
Copy link
Contributor

I take the point that the dash live simulator test stream is a very 'out there' case, and something needs to happen to allow the periods in that one to actually transition.

@tmm1
Copy link
Contributor Author

tmm1 commented Mar 13, 2023

Thanks for merging!

something needs to happen to allow the periods in that one to actually transition.

Open to suggestions. I'm not sure how to tell the period has ended. That stream still plays correctly so it didn't seem like a huge priority.

@glennguy
Copy link
Contributor

Yeah I had a couple of ideas but I think it's not a super huge priority either. I think the stream plays still only because the new period is still using the same segments and there's no actual discontinuity. What I found though is it stops once it gets to the 5:00 mark.
What I would expect with the eventual solution is that the 'now' time marker will move backwards as old periods are removed, and that some post parsing cleanup would need to happen to set the correct length of all periods that aren't the newest i.e if period 2 starts at 3:00 then go back to period 1 and make sure to truncate/finish it at 3:00.
But more questions come out of this:

  • If we're playing in the old period near the 'far' edge and the period is removed, we need to then move or seek to the new oldest period, while making sure we don't crash because we've deleted current_segment_ or something like that...
  • In this stream example there's always either 6 or 9 minutes of periods, plus the 'never-ending' newest period, yet we only show 5 minutes in the timeshift buffer window. I think (iirc) that this 5 minutes is starting at the oldest point and going forwards... I assume that this would be the preferred behaviour but not sure
  • Do we truncate/finish the last/newest period according to timeshiftbuffer? Probably...

Anyway lets see what comes of this change and go from there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backport: Done Component: MPEG-DASH Type: Improvement non-breaking change which improves existing functionality v21 Omega
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants