Skip to content

Support for HLS EXT-X-IFRAME-ONLY playlists - #6270

Merged
marcbaechinger merged 6 commits into
google:dev-v2from
TiVo:p-iframe-only-playlist
Apr 17, 2020
Merged

marcbaechinger merged 6 commits into
google:dev-v2from
TiVo:p-iframe-only-playlist

Conversation

@stevemayhew

Copy link
Copy Markdown
Contributor

This branch adds support for parsing HLS I-Frame only playlists and adding them as a selectable Format in an TrackGroup.

All existing unit test cases pass, the branch includes one test case for iFrame specifically. I modified AdaptiveTrackSelection to not include these IDR only Formats, so they will not affect current ExoPlayer playback for existing master playlists that already contain iFrame only variants. The expectation is a subclass of same would do this intelligently based on desired playback speed.

I can provide (privately) sample broadcast and VOD streams that have IDR streams you can manually select to see the behavior. The existing apple streams all parse and present their iFrame only tracks (bipbop), however playback of these is not very interesting ;-).

See my notes in the code in the individual commits for more thoughts on direction.

PS, our CLA is signed and in Google's hands for approval.

@googlebot

Copy link
Copy Markdown

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@stevemayhew stevemayhew changed the title P iframe only playlist Support for HLS EXT-X-IFRAME-ONLY playlists Aug 7, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm certainly not married to this idea... But, there needs to be some hook in the Format to identify the Iframe only tracks. It's unfortunate the HLS spec does not mandate (or even allow) specifying the frame rate on the Master Playlist EXT-X-IFRAME-ONLY

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will prevent any of the Iframe Format from being part of default ABR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry the diff might be a bit hard to read. Basically added an argument to pass Variants and replaced all references to the variants field in the HlsMasterPlaylist with same.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternate 'VIDEO' renditions should be a TODO, it is in the spec but I've never seen it in the wild.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ROLE_FLAG_ALTERNATE should probably go, I added this to surface it to the track selector UI.

@liambresnahan

Copy link
Copy Markdown

@googlebot I signed it!

@stevemayhew

stevemayhew commented Aug 7, 2019 via email

Copy link
Copy Markdown
Contributor Author

@googlebot

Copy link
Copy Markdown

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@tonihei

tonihei commented Aug 19, 2019

Copy link
Copy Markdown
Collaborator

@AquilesCanta Would you mind reviewing this change? See #474 for context.

@defagos defagos mentioned this pull request Aug 19, 2019
18 of 21 tasks
@AfanasievAnton

Copy link
Copy Markdown

hey, was wondering about your future plans with regard to this pr.
Do you consider to review it, or decline. And if so, are you planning to provide some kind of support for I-FRAMES extraction?

@stevemayhew

Copy link
Copy Markdown
Contributor Author

@AfanasievAnton I've got another pull reques that also cover this same set of files, but I need to rebase this one. Will do that this week.

We are using this with our release version of ExoPlayer (2.10.6 based) for visual trick play.

@ojw28

ojw28 commented Mar 12, 2020

Copy link
Copy Markdown
Contributor

@AquilesCanta - Did you have a chance to look at this?

@stevemayhew

Copy link
Copy Markdown
Contributor Author

Added a commit to enable support for "implicit" Media Initialization Section (PAT/PMT for MPEG-TS). This is generated by Apple's tools (mediafilesegmenter for example).

This was a change suggested by @ojw28 to allow adpative track selection to work with IFrame only `Variant` as any other adaptive seleted `Track` in the `TrackGroup`.  This actually works quite well with the exceptions that:

1. IFrame only tracks do not contain the same Rendition Group references as other non-iframe only varaints (so track selection should disable these tracks even in other non-video renderers.
2. Adapting to iFrame tracks only based on bandwidth might not be so good (as often larger spacial resolution iFrame track might have higher bitrate then lower spacial resolution non-iframe only track).

This change includes one proposed workaround in the AdaptiveTrackSelection class (only use iFrame for higher playback speeds).
Pull in change to default to not use i-Frames for base AdaptiveTrackSelection.
The expectation is a subclases, that support transitioning to iFrame, will select these tracks.
@stevemayhew
stevemayhew force-pushed the p-iframe-only-playlist branch from aadb36b to b3796cc Compare March 18, 2020 00:01
In the HLS Spec (https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-04#section-4.4.3.6), specifically this or condition of this statement:

"... defined by the EXT-X-MAP tag, or is located between the start of the resource
    and the offset of the first I-frame segment in that resource."

Change adds code to add this "implicit" Media Initialization Segment if no EXT-X-MAP defines one explicitly.
@stevemayhew
stevemayhew force-pushed the p-iframe-only-playlist branch from b3796cc to 1f11233 Compare March 18, 2020 00:18
@stevemayhew

Copy link
Copy Markdown
Contributor Author

Rebased to latest dev-v2 (removing the old merge commits). @AquilesCanta let me know if you need me to rebase and collapse some commits to make it clearer. I did merge in the updates to use the new Format.builder() in the method I refactor extracted.

@stevemayhew

Copy link
Copy Markdown
Contributor Author

PS I can send you some sample content to try as well. You can either modify demo player to change speed or simply use track selector to override select the i-Frame only track and play it.

Locally I subclassed AdaptiveTrackSelection and change this code to select i-Frame only track if over 8x speed (you'll want to disable audio if you do this):

  protected boolean canSelectFormat(
      Format format, int trackBitrate, float playbackSpeed, long effectiveBitrate) {

    boolean isNonIframeOnly = (format.roleFlags & C.ROLE_FLAG_TRICK_PLAY) == 0;
    boolean canSelect = Math.round(trackBitrate * playbackSpeed) <= effectiveBitrate;

    return canSelect && isNonIframeOnly;    // Default is not to use the IDR only tracks in selection
  }

@AquilesCanta

Copy link
Copy Markdown
Contributor

If this is now updated to dev-v2 I'll do my best to look into it this week. Sorry for the delay, there are some high priority deadlines.

@stevemayhew

Copy link
Copy Markdown
Contributor Author

No worries @AquilesCanta I'm becoming good at merging it ;-) I'm keeping a back-ported to 2.10.6 version as well for us internally where I've added the support for the implicit init segment (Apple's hack), so that triggered updating this branch too. I'll keep using rebase to avoid pollution of the history with merges.

@AquilesCanta AquilesCanta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Two main points to visit, rest of comments just nits.

Format format, int trackBitrate, float playbackSpeed, long effectiveBitrate) {
return Math.round(trackBitrate * playbackSpeed) <= effectiveBitrate;

boolean isNonIframeOnly = (format.roleFlags & C.ROLE_FLAG_TRICK_PLAY) == 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we replace this variable is isTrickPlayTrack or isIFrameOnlyTrack (would require negating the comparison to != 0). Otherwise, it could be read as a track that has no I-frames, which would be inaccurate. Right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that sounds fine. Really this logic is just to prevent selecting these tracks ever, for now. The right thing to do is add the logic to TrackSelection itself. In our back-port to release we have subclassed AdaptiveTrackSelection. The idea is when you move to high-speed mode (or scrub based trick-play) a TrackSelection occurs that results in a TrackSelection.Definition that includes only formats that are relevant (either all i-Frame or all non-iFrame tracks). Oliver had other thoughts about adapting based on frame rate. I think all of these are worth visiting, and the changes would be restricted to track selection so this code could be merged in first.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with a positive logic variable, hopefully this is more clear. The function should return fall if the track is an iFrame only track.

Logic to return true will depend on the trick-play implementation.

if (hasVariants) {
ArrayList<Variant> allVariants = new ArrayList<>();
allVariants.addAll(masterPlaylist.variants);
allVariants.addAll(masterPlaylist.iFrameVariants);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So my view on the I-FRAME tracks is that they should belong in their own track group, I think.

One can summarise (and simplify) a TrackGroup as a group of tracks that can be adapted between.

  • However, it's not intended that a player adapts between a regular track and a I-FRAME only tag.
  • Additionally, I can conceive a scenario where I-frame tags are track-selected to a different renderer than the variants. For these two reasons I think we should put I-FRAME only tracks in their own track group. To do this, they need to be in their own HlsSampleStreamWrapper.

Please do feel free to provide evidence pointing in a different direction.

@stevemayhew stevemayhew Mar 19, 2020 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally did it this way, #474 (comment)

@ojw28 Made good points for including all the tracks in the same adaption set #474 (comment) So basically we are adapting based on frame rate as well as bandwidth.

One advantage to the current approach, that Oliver advocated, is it may make more sense to trick play a very low bandwidths 30FPS track rather than a higher resolution low frame rate i-Frame only track. Having the tracks all in an adaptive set allows this to occur when adapting to speed changes without the overhead of a full on track selection.

I can go either way, could we get the parsing part in first at least, and do this as a later enhancement? Rebasing my collection of pull requests that alter this code is becoming laborious ;-), there is a lot of change to these files.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we get the parsing part in first at least

Hah, I was going to suggest splitting this into smaller independent pieces, but I didn't want to get too annoying. So I'll assume the scope of this change is only parsing as of now?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be pretty well contained now. Thanks!

Address the minor issues raised in @AquilesCanta's review of pull request 6270.  Also remove unused variable (`hasIFrameVariants`)
: Collections.emptyMap();

boolean hasVariants = !masterPlaylist.variants.isEmpty();
boolean hasIFrameVariants = !masterPlaylist.iFrameVariants.isEmpty();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable removed, unused.

@AquilesCanta AquilesCanta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I forgot to send the previous round of comments. I'll try to merge this next week and address any minor changes manually. Thanks for the pull request!

if (hasVariants) {
ArrayList<Variant> allVariants = new ArrayList<>();
allVariants.addAll(masterPlaylist.variants);
allVariants.addAll(masterPlaylist.iFrameVariants);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we get the parsing part in first at least

Hah, I was going to suggest splitting this into smaller independent pieces, but I didn't want to get too annoying. So I'll assume the scope of this change is only parsing as of now?

* @param baseUri See {@link #baseUri}.
* @param tags See {@link #tags}.
* @param variants See {@link #variants}.
* @param iFrameVariants

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we add See {@link iFrameVariants}?

if (hasVariants) {
ArrayList<Variant> allVariants = new ArrayList<>();
allVariants.addAll(masterPlaylist.variants);
allVariants.addAll(masterPlaylist.iFrameVariants);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be pretty well contained now. Thanks!

@marcbaechinger
marcbaechinger merged commit 88de774 into google:dev-v2 Apr 17, 2020
@AquilesCanta

Copy link
Copy Markdown
Contributor

Hi @stevemayhew, have you been able to play an i-frame-only variant?

I was playing around with this, and it would seem that the fmp4 extractor throws whenever you try to play an i-frame only variant. Could you please confirm for me whether you have used the fmp4 extractor to play i-frame only variants? If not, I think I will disable them until we manage to make it work.

@stevemayhew

stevemayhew commented Jun 16, 2020 via email

Copy link
Copy Markdown
Contributor Author

@AquilesCanta

Copy link
Copy Markdown
Contributor

Perhaps you are testing against the Apple bib-bop streams

Correct. I was assuming the issue was that the I-frame only variants were just trimming samples from the original content, so the extractor was expecting the missing samples.

So if you have working I-FRAME only streams, do you use a i-frame-only-specific EXT-X-MAP for them (as opposed to just linking to ranges in the original content)?

I'll file an issue for fixing I-FRAME only support in the HLS bip-bop streams. You are welcome to send a pull request for fixing that.

@AquilesCanta

Copy link
Copy Markdown
Contributor

Filed #7512.

@stevemayhew

stevemayhew commented Jun 16, 2020 via email

Copy link
Copy Markdown
Contributor Author

@google google locked and limited conversation to collaborators Jun 23, 2020
@stevemayhew
stevemayhew deleted the p-iframe-only-playlist branch June 11, 2021 20:40
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants