Nevcairiel / LAVFilters

LAV Filters - Open-Source DirectShow Media Splitter and Decoders
GNU General Public License v2.0
7.52k stars 789 forks source link

[Suggestion] LAV Splitter Source: allow selecting smaller video resolution in multi-resolution HLS livestream #604

Open 59de44955ebd opened 4 months ago

59de44955ebd commented 4 months ago

Hi, I often use LAV Splitter Source (in MPC-HC) to watch german television HLS livestreams, which works great, But for me it would be a great improvement if there was any way - even if it's just a registry tweak, I wouldn't care - to make LAV Splitter Source not always automatically pick the highest resolution offered in a master.m3u8 - which in this case usually is 1080p - but a smaller one, like 720p or 480p. Since I usually do other stuff while watching, and therefor the player window is small anyway, full HD is just a waste of bandwidth and energy/climate destruction for me. So it would be great, if either a) there was an interactive video stream selection (e.g. via tray icon menu), like there already is for the available audio streams inside a master.m3u8, or b) there would be some (GUI or just registry) setting to pick a favorite resolution (e.g. 720p), and the filter would then always try to select the video stream that comes closest to it.

Here some example livestream master.m3u8 that offers 6 different video resolutions, from 270p up to 1080p: https://mcdn.daserste.de/daserste/de/master.m3u8

And here all avaliable german public tv livestreams combined in a single playlist: https://valentin.dasdeck.com/projects/tv/livestreams.m3u8

59de44955ebd commented 4 months ago

Update: today I recompiled LAV Filters myself from master and hacked this function into LAVSplitter, attached .zip contains my adjusted version: https://nextcloud.dasdeck.com/index.php/s/bGPRdyxtXdAD7qL

There is only this single change: if there is a REG_DWORD value called "PreferredVideoStreamHeight" under HKCU\Software\LAV\Splitter, the demuxer will select the video stream with the smallest absolute difference to this value. If there is no such value in the registry, it will select the stream with the smallest difference to 4320 (=8K), so basically the same behavior as before, since I guess there are no HLS streams with higher resolution (but 4320 could also be replaced with 0xFFFFFFFF, so to really "always select the largest").

To make this work, I added this line on top of the programs for loop in method STDMETHODIMP CLAVFDemuxer::CreateStreams() in LAVFDemuxer.cpp: DWORD dwFavoriteHeight = m_pSettings->GetPreferredVideoStreamHeight(); // CUSTOM

And inside the loop, I changed //DWORD dwResolutionScore = st->codecpar->width * st->codecpar->height; to DWORD dwResolutionScore = 0xFFFFFFFF - (st->codecpar->height >= dwFavoriteHeight ? st->codecpar->height - dwFavoriteHeight : dwFavoriteHeight - st->codecpar->height);

And that's about it. New method "GetPreferredVideoStreamHeight" is declared in LAVSplitterSettingsInternal.h - since I didn't want to touch the public COM interface - and implemented in LAVSplitter.cpp like this:

STDMETHODIMP_(DWORD) CLAVSplitter::GetPreferredVideoStreamHeight()
{
    return m_settings.PreferredVideoStreamHeight;
}

And new DWORD property "PreferredVideoStreamHeight" of CLAVSplitter's Settings struct is initialized directly inside CLAVSplitter::LoadDefaults() like this:

    HRESULT hr;
    CRegistry reg = CRegistry(HKEY_CURRENT_USER, LAVF_REGISTRY_KEY, hr, TRUE);
    DWORD dwVal = reg.ReadDWORD(L"PreferredVideoStreamHeight", hr);
    if (SUCCEEDED(hr))
        m_settings.PreferredVideoStreamHeight = dwVal;
    else
        m_settings.PreferredVideoStreamHeight = 4320; // 8K

That's because I didn't want to recompile MPC-HC as well, so I wanted it to work also in case of m_bRuntimeConfig being true, and therefor couldn't add it to the ReadSettings method. For now it's just a hidden extra feature not showing up in the settings GUI, so only for those willing to edit stuff in the Registry. But that's perfectly fine for me.