-
-
Notifications
You must be signed in to change notification settings - Fork 481
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
Fix 4k HEVC downscaling on 1080p devices #3419
Conversation
ffbc8cd
to
7ebd612
Compare
ProfileConditionValue.VideoProfile, | ||
"none" | ||
), | ||
ProfileCondition( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do these conditions add? The max1080pProfileConditions
are already included in a CodecProfile to limit the resolution. Including them here too should be pointless noise.
See:
jellyfin-androidtv/app/src/main/java/org/jellyfin/androidtv/util/profile/ExoPlayerProfile.kt
Lines 202 to 208 in 5674a93
// Limit video resolution support for older devices | |
if (!DeviceUtils.has4kVideoSupport()) { | |
add(CodecProfile().apply { | |
type = CodecType.Video | |
conditions = max1080pProfileConditions | |
}) | |
} |
The way the Jellyfin server works is that all codec profiles that match the type
, codec
, container
and applyConditions
of a media file need all their conditions to be true in order for compatibility to be agreed. Therefore the width and height are already being checked for when DeviceUtils.has4kVideoSupport()
is false due to the above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, that statement should work, but it doesn't. Why not? Go figure. Luckily, I was able to dig up some old 1080p devices to test this out. I tried several different ways of rewriting this, but this is the version that actually worked.
I can tell you some findings with the original code. A 4k video would transcode initially for unsupported resolution as it should. Play another video then come back and the same file would no longer transcode and would just get remuxed causing the player to crash, along with any other video played after that. 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the profile is correct the bug should be fixed server-side
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the current state of this change? Do we still need it or has it been fixed with one of the other profile changes already?
With a 2160p stream:
The current code does not trigger a transcode and will only copy the video in its original resolution causing playback to fail for devices that do not support4k:
This fix will correctly trigger a transcode to a 1080p stream:
This should fix the issue described in #3820, allowing 4k to 1080p playback in Google Chromecast HD and on older 1080p firetv devices. |
Thanks for the explanation. I think I understand the issue now. Even before this PR the HEVC video would trigger a transcode but it wouldn't downscale the video. With these conditions added it does. I started debugging by adding a condition for a maximum width of 100, so any video I would play would have to be transcoded. After trying various things and looking through the server code I found the issue: the server uses all codec profiles to determine if transcoding is required, but only the FIRST matching codec profile is used to set transcoding requirements. |
Just tested out the pending server fix and it resolves the issue! This PR is no longer needed. |
Awesome! Thanks for testing that. It was quite the adventure to figure out this behavior, it appears to be a side-effect from a big change in the 10.8 release. |
Still not working with JF Server 10.9.10 and JF ATV 0.17.4, 4K content result in player error on Mi Stick 1080p with Android TV :( FFmpeg logs : {"Protocol":0,"Id":"d174a83eb441d949ac7a6413bd6fbc7f","Path":"D:\Medias\Films\2024\Black.Mass.2015.MULTi.VFF.2160p.10bit.4KLight.DV.HDR.BluRay.DTS-HD.MA.5.1.x265-QTZ-Wawacity.ing.mkv","EncoderPath":null,"EncoderProtocol":null,"Type":0,"Container":"mkv","Size":9409197364,"Name":"Black.Mass.2015.MULTi.VFF.2160p.10bit.4KLight.DV.HDR.BluRay.DTS-HD.MA.5.1.x265-QTZ-Wawacity.ing","IsRemote":false,"ETag":"0cb52f9c7f298f61aee84d4f795e9651","RunTimeTicks":73518860000,"ReadAtNativeFramerate":false,"IgnoreDts":false,"IgnoreIndex":false,"GenPtsInput":false,"SupportsTranscoding":true,"SupportsDirectStream":true,"SupportsDirectPlay":true,"IsInfiniteStream":false,"RequiresOpening":false,"OpenToken":null,"RequiresClosing":false,"LiveStreamId":null,"BufferMs":null,"RequiresLooping":false,"SupportsProbing":true,"VideoType":0,"IsoType":null,"Video3DFormat":null,"MediaStreams":[{"Codec":"hevc","CodecTag":null,"Language":null,"ColorRange":null,"ColorSpace":"bt2020nc","ColorTransfer":"smpte2084","ColorPrimaries":"bt2020","DvVersionMajor":1,"DvVersionMinor":0,"DvProfile":8,"DvLevel":6,"RpuPresentFlag":1,"ElPresentFlag":0,"BlPresentFlag":1,"DvBlSignalCompatibilityId":1,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":null,"VideoRange":2,"VideoRangeType":5,"VideoDoViTitle":"DV Profile 8.1 (HDR10)","AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":null,"LocalizedForced":null,"LocalizedExternal":null,"LocalizedHearingImpaired":null,"DisplayTitle":"4K HEVC HDR","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":10238676,"BitDepth":10,"RefFrames":1,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":true,"IsForced":false,"IsHearingImpaired":false,"Height":1600,"Width":3840,"AverageFrameRate":23.976025,"RealFrameRate":23.976025,"Profile":"Main 10","Type":1,"AspectRatio":"2.40:1","Index":0,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":"yuv420p10le","Level":153,"IsAnamorphic":false},{"Codec":"ac3","CodecTag":null,"Language":"fre","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"FR VFF : AC3 5.1","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Par d\u00E9faut","LocalizedForced":null,"LocalizedExternal":"Externe","LocalizedHearingImpaired":null,"DisplayTitle":"FR VFF : AC3 5.1 - Fre - Dolby Digital - Par d\u00E9faut","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"5.1","BitRate":640000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":6,"SampleRate":48000,"IsDefault":true,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":0,"AspectRatio":null,"Index":1,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"dts","CodecTag":null,"Language":"eng","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"ENG VO : DTS-HD MA 5.1","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Par d\u00E9faut","LocalizedForced":null,"LocalizedExternal":"Externe","LocalizedHearingImpaired":null,"DisplayTitle":"ENG VO : DTS-HD MA 5.1 - Anglais","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"5.1","BitRate":3443898,"BitDepth":24,"RefFrames":null,"PacketLength":null,"Channels":6,"SampleRate":48000,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":"DTS-HD MA","Type":0,"AspectRatio":null,"Index":2,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"subrip","CodecTag":null,"Language":"fre","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"FR Forced : SRT","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"FR Forced : SRT - Fre - Par d\u00E9faut - Forc\u00E9 - SUBRIP","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":true,"IsForced":true,"IsHearingImpaired":false,"Height":0,"Width":0,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":3,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":true,"SupportsExternalStream":true,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"subrip","CodecTag":null,"Language":"fre","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"FR Full : SRT","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"FR Full : SRT - Fre - SUBRIP","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":0,"Width":0,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":4,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":true,"SupportsExternalStream":true,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"subrip","CodecTag":null,"Language":"eng","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"ENG Full : SRT","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"ENG Full : SRT - Anglais - SUBRIP","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":0,"Width":0,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":5,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":true,"SupportsExternalStream":true,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"PGSSUB","CodecTag":null,"Language":"fre","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"FR Forced : PGS","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"FR Forced : PGS - Fre - Forc\u00E9 - PGSSUB","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":true,"IsHearingImpaired":false,"Height":1080,"Width":1920,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":6,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"PGSSUB","CodecTag":null,"Language":"fre","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"FR Full : PGS","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"FR Full : PGS - Fre - PGSSUB","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":1080,"Width":1920,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":7,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"PGSSUB","CodecTag":null,"Language":"eng","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"ENG Full SDH : PGS","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":"Non d\u00E9fini","LocalizedDefault":"Par d\u00E9faut","LocalizedForced":"Forc\u00E9","LocalizedExternal":"Externe","LocalizedHearingImpaired":"Malentendants","DisplayTitle":"ENG Full SDH : PGS - Anglais - Malentendants - PGSSUB","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":null,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":false,"IsHearingImpaired":true,"Height":1080,"Width":1920,"AverageFrameRate":null,"RealFrameRate":null,"Profile":null,"Type":2,"AspectRatio":null,"Index":8,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null}],"MediaAttachments":[],"Formats":[],"Bitrate":14322574,"Timestamp":null,"RequiredHttpHeaders":{},"TranscodingUrl":null,"TranscodingSubProtocol":0,"TranscodingContainer":null,"AnalyzeDurationMs":null,"DefaultAudioStreamIndex":null,"DefaultSubtitleStreamIndex":null} C:\Program Files\Jellyfin\Server\ffmpeg.exe -analyzeduration 200M -probesize 1G -init_hw_device cuda=cu:0 -filter_hw_device cu -hwaccel cuda -hwaccel_output_format cuda -hwaccel_flags +unsafe_output -threads 1 -noautorotate -i file:"D:\Medias\Films\2024\Black.Mass.2015.MULTi.VFF.2160p.10bit.4KLight.DV.HDR.BluRay.DTS-HD.MA.5.1.x265-QTZ-Wawacity.ing.mkv" -noautoscale -map_metadata -1 -map_chapters -1 -threads 0 -map 0:0 -map 0:1 -map -0:s -codec:v:0 hevc_nvenc -tag:v:0 hvc1 -preset p1 -b:v 10238676 -maxrate 10238676 -bufsize 20477352 -profile:v:0 main -g:v:0 72 -keyint_min:v:0 72 -vf "setparams=color_primaries=bt2020:color_trc=smpte2084:colorspace=bt2020nc,tonemap_cuda=format=yuv420p:p=bt709:t=bt709:m=bt709:tonemap=bt2390:peak=100:desat=0" -codec:a:0 copy -copyts -avoid_negative_ts disabled -max_muxing_queue_size 2048 -f hls -max_delay 5000000 -hls_time 3 -hls_segment_type mpegts -start_number 0 -hls_segment_filename "C:\ProgramData\Jellyfin\Server\transcodes\ca8384cf7052880e12a604a81cdd3092%d.ts" -hls_playlist_type vod -hls_list_size 0 -y "C:\ProgramData\Jellyfin\Server\transcodes\ca8384cf7052880e12a604a81cdd3092.m3u8" ffmpeg version 6.0.1-Jellyfin Copyright (c) 2000-2023 the FFmpeg developers [q] command received. Exiting. [hls @ 000001cba15eeb00] Opening 'C:\ProgramData\Jellyfin\Server\transcodes\ca8384cf7052880e12a604a81cdd30924.ts' for writing JellyFin server Logs : [2024-08-30 18:34:15.042 +02:00] [INF] [18] MediaBrowser.Controller.MediaEncoding.TranscodingJob: Stopping ffmpeg process with q command for "C:\ProgramData\Jellyfin\Server\transcodes\d3c7277a9744a6154fecaab84bec9e80.m3u8" |
@avionics75 Ex
|
Thanks for the reply ! Here are some info about the device : The model number is the one I found over the internet but i'm not sure if that's what you were talking about |
Changes
Add
DeviceUtils.has4kVideoSupport
conditional tests directly to thedeviceHevcCodecProfile
in the ProfileHelper.Issues
Fixes #3388 #2516