-
Notifications
You must be signed in to change notification settings - Fork 33
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
Support multi-variant HLS streams #311
base: main
Are you sure you want to change the base?
Conversation
Thanks for submitting this. Glad to see there is a way to make this work with decodebin3. The added logic to upscale the video to the largest layer would however break an existing functionality where we drop layers that are bigger than the source, and match the biggest layer size to the source if smaller. You can see this logic in the It is important that this functionality is not lost in most cases as upscaling is wasteful, and can lead to degraded quality, by decreasing the amount of bits available per macro bloc to encode no extra details. Does gstreamer with decodebin3 provide any way to get the expected list of variants from the manifest, anywhere in the pipeline? If not, we may want to ensure that the upscaling code is only triggered on multivariant sources. |
Ah, makes sense. Unfortunately I didn't find a way to access the list of variants—the manifest is obviously being parsed, and I can see them in the gstreamer logs, but We could potentially recalculate layer sizes and change the |
* Store original width and height in layers * When output bins receive new video caps, change capsfilter caps to use new resolution, without upscaling
Update: changing the caps on the capsfilter does work, and avoids upscaling. This does introduce a separate issue, however: we can't discard layers when the source is too small, since those layers need to exist for use later. As an example: an HLS stream is started, and defaults to 320x180. We then use the layers:
Later,
The downside is, of course, that if the video remains 320x180, then we're pushing 3 duplicate streams for the lifetime of the input. It would be best if we could skip creating lower layers when they're duplicates, and then create them when needed. I'll look into that next. Maybe we could block output bins that aren't needed yet? |
Thanks for looking into this further. The livekit protocol doesn't allow changing the layers after initial publication. However, it is possible to:
So, indeed, one approach would be to block the output of the layers that are duplicates of the smaller ones, and change the dimensions of layers dynamically as needed. I'm also curious: what is the behavior of the x264enc gstreamer module when the caps change on its sink pad? The underlying x264 encoding library doesn't support changing video size on the fly. Does the gstreamer module recreate an encoder context as needed on caps change? |
Fixes #310. Allows multi-variant HLS streams to work for URL ingresses. This fixes two issues:
1.
decodebin3
handles variant selection automatically, but sends thenotify::caps
signal when the source resolution changes. This caused the pipeline to attempt to create a new video output bin and link it to the input bin's video src pad, which fails. Then, the whole pipeline fails.2.
WebRTCSink.AddTrack
creates acapsfilter
for each layer with caps:fmt.Sprintf("video/x-raw,width=%d,height=%d", layer.Width, layer.Height)
. The width and height used for these layers come from the video's initial resolution, which can be very low if it's a low-bitrate variant. So, even if a higher-resolution variant is selected, it will be scaled back down to whatever it was at first.Changes:
I've tested with this HLS file: https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8 (Note that this may still fail on main, since it contains subtitle tracks, and fails with
unsupported mime type (application/x-subtitle-vtt) for the source media
. As a workaround, addingapplication/x-subtitle-vtt
tosupportedMimeTypes
inpkg/media/urlpull/source.go
fixes this, and variant selection works correctly.)