Commit graph

1029 commits

Author SHA1 Message Date
harupong
43a4e6d296
Added translation using Weblate (Japanese) 2026-10-31 19:35:01 +00:00
tal_sarid
ecbf1e68df
Translated using Weblate (Hebrew)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/he/
2026-10-31 19:35:01 +00:00
danpergal84
6ba2d8ced5
Translated using Weblate (Spanish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/es/
2026-10-31 19:35:01 +00:00
PreAcc
02261f3993
Translated using Weblate (Hungarian)
Currently translated at 72.9% (489 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/hu/
2026-10-31 19:35:01 +00:00
filippvl
546c00ba1a
Translated using Weblate (Serbian)
Currently translated at 20.4% (137 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sr/
2026-10-31 19:35:01 +00:00
opakholis
a272cea6a0
Translated using Weblate (Indonesian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/id/
2026-10-31 19:35:01 +00:00
TheMatrixan
a4abd56274
Translated using Weblate (Polish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/pl/
2026-10-31 19:35:01 +00:00
ymir
545ef636ff
Translated using Weblate (French)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/fr/
2026-10-31 19:35:01 +00:00
n8llcaster
b4c5697755
Translated using Weblate (Slovak)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sk/
2026-10-31 19:35:01 +00:00
Priit Jõerüüt
f4178ce803
Translated using Weblate (Estonian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/et/
2026-10-31 19:35:00 +00:00
North-DaCoder
3fe6054813
Translated using Weblate (German)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/de/
2026-10-31 19:35:00 +00:00
idezentas
e9c8f8483d
Translated using Weblate (Turkish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/tr/
2026-10-31 19:35:00 +00:00
arcker95
ffc4d2fd5e
Translated using Weblate (Italian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/it/
2026-10-31 19:35:00 +00:00
SimonHung
d03538c8bb
Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (670 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/zh_Hant/
2026-10-31 19:35:00 +00:00
Priit Jõerüüt
6b3a0872b1
Translated using Weblate (Estonian)
Currently translated at 99.8% (669 of 670 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/et/
2026-10-31 19:35:00 +00:00
Clint Bird
d2713ff2f5
Can Select Artist or Album Artist to be displayed on Music > Artists Page (#2127)
## Description
The Music / Artists view currently appears to use the artist metadata
from individual tracks. While at a track level this makes perfect sense,
it can result in a very noisy and fragmented artists view.

For example, an album by Eminem might contain tracks with artists such
as:
- Eminem
- Eminem feat. 50 Cent
- Eminem ft. Rihanna
- Eminem & Dr. Dre

Each of these seem to appear as a separate artist entry (even though
they are all tracks from the same album by Eminem)

This becomes particularly noticeable in large music libraries, where
featured artists, collaborations, remixes, and slightly different artist
metadata ends up resulting in a large number of sparsely populated or
duplicate / strange looking artist entries.

This PR adds an option / toggle to determine which metadata field is
used to populate the artists view. This option sits neatly within the
current artist view settings e.g. Music > Artists > View options >
Artist source
- Artist (current behavior)
- Album Artist (use the album artist metadata instead)

That Artist setting stays as the default choice (so nobody sees a change
unless they pick it) but now gives the option to filter down only to
Album Artists if desired - this choice is saved per library and applies
immediately.

### Related issues
Closes #1868

### Testing
I've tested it extensively on an Amazon Fire TV Cube Gen 2 (using the
firetv debug variant) the following manual tests were performed:
- The list changes when you pick Album artist and importantly the
selection survives a full app restart
- It was tested on a large library and can confirm only the Album
Artists remained (e.g. only one Eminem entry remained)

Automated checks were run (testFiretvDebugUnitTest & pre-commit) As well
as two new tests being added to the CollectionFolderViewModelTest.kt:
- For letter counting its checking via the album artist endpoint (and
not the standard one) when the source is set as ALBUM_ARTIST
- When the source is changed via the saveViewOptions its triggering a
load from the album artist endpoint

## Screenshots
Please see the screenshots below showing the UI impact / modification:
<img width="4624" height="3472" alt="1"
src="https://github.com/user-attachments/assets/6b53575e-ad15-4f66-b9c0-074657128a1d"
/>
<img width="4624" height="3472" alt="2"
src="https://github.com/user-attachments/assets/528c5766-44d8-43d3-8519-778f5aab7441"
/>
<img width="4624" height="3472" alt="3"
src="https://github.com/user-attachments/assets/5de2fb6d-173d-4ac3-ad1b-e08f27f4dafd"
/>

## AI or LLM usage
The code was written / supported with Claude - the approach (e.g. design
/ storing the choice in ViewOptions) endpoint research etc was done by
myself - I reviewed the approaches / refactoring and than deployed a
debug.apk to my local device to confirm everything was working as
expected.

I've reviewed each line and can explain it / the thinking to approaches
/ logic etc and am comfortable submitting the PR.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-31 14:21:41 -04:00
SergeiAK
2f7804fd5e
Convert Dolby Vision profile 7 to 8.1 on devices without a profile 7 decoder (#2017)
## Description

**On Amlogic boxes (S905X4 and similar) Dolby Vision Profile 7 does not
play as Dolby Vision.**
The server transcodes it, or, with "Direct play Dolby Vision Profile 7"
switched on by hand, the
decoder answers `NoSupport` and fallback ends in HDR10. Devices with a
native Profile 7 decoder,
such as the Shield, are not affected and nothing changes for them.

This PR converts Profile 7 to 8.1 on the fly. It has two halves and one
decision.

The preference `convertDolbyVisionProfile7` is proto field 6 in the
experimental settings, off by
default. In `WholphinRenderersFactory` the filter comes first in the
list, followed by the HDR10+
masking from #1876.

**What this PR does not do.** The enhancement layer is dropped; that is
the price of the
conversion, which is why devices with a native Profile 7 decoder are
left alone.
`BlockAdditional` (an enhancement layer outside the stream) is not read
— like the rest of
Wholphin today — so such a file stays HDR10, as it is now.

### Related issues

Closes #244

Builds on #1876 (the `BitstreamFilter` list). Related to #1540. @fanni42
asked for exactly this on
an S905X4 in #1876.

### Testing

**Hardware** — a debug build of this branch, Homatics box (Amlogic
S905X4, Android 14) + LG BX,
Jellyfin 12.1.0, a Profile 7 FEL remux with the enhancement layer in
band, played from the start
for 39 seconds. Only the new preference was switched on; manual "Direct
play Dolby Vision
Profile 7" was **off**:

* `DolbyVisionProfile7FilterTest` (14) — a fake rewriter on a direct
buffer: offset ≠ 0,
position/limit untouched, every "bytes stay as they were" branch,
three-byte start codes,
  `UnsatisfiedLinkError` tried once;
* `DolbyVisionProfile7ExtractorsFactoryTest` (5, mockk) — only the video
track is rewritten;
* `DolbyVisionProfile7ConversionTest` (6) — codec strings, DRM, `dvh1`.

CI in my fork ran on this branch plus a debug signing commit:
`pre-commit`,
`testDefaultDebugUnitTest` and `assembleDefaultDebug` are all green. The
hardware measurement
above is that build.

## Screenshots

The only UI change is one toggle in the experimental settings.

## AI or LLM usage

The code was written with Claude (Claude Code): the filter, the
extractor wrapper, the condition
and the tests. I reviewed every line and can explain it. It was tested
with the unit tests and
the hardware measurement above. This description was written by me in
Russian and translated
into English with the same assistant.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-28 15:16:42 -04:00
Damontecres
f66746cf47
Auto-configure Discover from Wholphin server plugin (#2134)
## Description
https://github.com/damontecres/jellyfin-plugin-wholphin/pull/3 added a
new endpoint for Seerr configuration in Wholphin server plugin.

This PR adds support for reading that configuration and either
pre-filling the URL or automatically logging in.

Some code was copied from #1418 (thanks @matschi95!), but that PR worked
by inserting a DB record for the plugin provided server. Since the local
DB was preferred, this meant plugin config changes wouldn't be reflected
in the client. This PR instead attempts the connection and only updates
the in-memory connection state, so user switching and app restarts will
re-fetch from the plugin.

If the server plugin is not installed or no Seerr server is configured,
nothing in Wholphin changes.

### Related issues
#598 

This PR replaces #1418


### Testing
Emulator with different scenarios

## Screenshots
N/A

## AI or LLM usage
None
2026-10-26 14:18:56 -04:00
Damontecres
6cde8ce8a6
Show warning for future unsupported server version (#2115)
## Description
Now that Jellyfin 12 has been out for over six weeks, it's time to start
considering dropping support for Jellyfin 10 & 11 as part of #1640.

This PR adds a warning message on the switch server, switch user, &
preferences pages if the current server version is <12.

### Related issues
See https://github.com/damontecres/Wholphin/discussions/1640 for further
discussion!

### Testing
Emulator w/ faked data

## Screenshots
N/A, reuses the same error message space

## AI or LLM usage
None
2026-10-25 20:52:20 -04:00
bobberb
9218940a69
Rename music "Top Rated Unwatched" row to "Top Rated" (#2118)
## Description
Rename music "Top Rated Unwatched" row to "Top Rated"

### Related issues
Typo.

### Testing
Android TV

## Screenshots
<!-- Please include screenshots if the PR alters any UI elements -->
<img width="1920" height="1080" alt="pr2-music-recommended-top-rated"
src="https://github.com/user-attachments/assets/3978bc9b-a020-4ee7-ae35-feb19e19ebae"
/>

## AI or LLM usage
Claude wrote the code, I reviewed, deploed a -debug.apk to my device and
tested live.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 20:52:04 -04:00
Damontecres
551501fa75
Add support for server plugin (#1384)
## Description
PR to add support for a Wholphin server plugin:
https://github.com/damontecres/jellyfin-plugin-wholphin

Note: The plugin is not required to use Wholphin. It adds features the
server admin can use to set default settings like the home page or
eventually Seerr connection info.

### Changes
Wholphin will use the home page settings in order of:
1. Saved on the device locally
2. Saved on the server in the user's profile settings (display
preferences)
3. Provided by `jellyfin-plugin-wholphin`
4. Default fallback: combined continue watching & recently added in
libraries

Under customize home page, you can now see the "source" of the home
settings. This also allows to pick a different source

Finally, instead of the home customization being saved in the background
only locally, if there are any changes, a dialog is shown with options
to save locally, server-side user profile, or discard.

So overall, it's more clear where the home page settings are from and
where the user wants to save them.

### Install

[See instructions
here](https://github.com/damontecres/Wholphin/releases/tag/develop-server-plugin)

### Related issues
Related to #598

### Testing
WIP

## Screenshots
N/A

## AI or LLM usage
None

---------

Co-authored-by: Mario Reisinger <marioreisinger95@gmail.com>
2026-10-19 14:41:08 -04:00
Damontecres
3ef221bf91
Improve track persistence for series & episodes (#1802)
## Description
This PR overhauls how audio and subtitle track persistence works for
series! Previously, when you chose an audio or subtitle track for an
episode, only the language was saved and used for subsequent episodes.
This meant aspects about why that choice were lost such as a forced or
hearing impaired track.

This PR changes the persistence to include more details about the chosen
track. Additionally, the persistence is saved at both the season and
series levels.

## How it works

Selecting the track uses the first success option:
1. Episode specific - User has explicitly chosen an audio/subtitle track
for this episode
2. Season specific - User has chosen the track for another episode in
this season
3. Series specific - User has chosen the track for another episode in
this series
4. User preferences - User has _not_ chosen a track for the episode,
season, nor series, so determine track based on the preferred audio
language, preferred subtitle language, and subtitle mode

Additionally, the season or series specific choices use a scoring
algorithm to find the best suited track. For example, if the chosen
tracks for an episode in the season had the forced flag, this will be
preferred for subsequent episodes. Same for SDH/hearing impaired or
title, etc. This means that the common case, where a season has
substantially identical tracks, will use the same ones across all
episodes (after choosing for one, otherwise falling back to the series
or user preferences).

Finally, this also means that users that prefer SDH/hearing impaired
subtitles can be prioritized now, though there is no global preference
for this yet.

The previous track language choices are migrated to the new algorithm.
They lack the additional context, but this makes for a seamless
transition.

## UI changes

The context menu for choosing audio or subtitle tracks now displays why
that track was chosen.

### Related issues
Fixes #1795
Maybe fixes #1783
Related to #1136 & #1798
Closes #1470

### Testing
Previous unit tests for track selection all pass, plus there are a few
additional unit tests. I've done some testing on the emulator and it
seems to work well. But I think real world testing will be needed.

## AI or LLM usage
None
2026-10-16 10:53:44 -04:00
Jeff Whiting
9f557416ea
New user preference to force enable or disable common HDR and Dolby Vision formats (#1644)
Description
Adding per-format HDR override preferences (HDR10, HDR10+, Dolby Vision
Profile 5/7/8) to control device compatibility information sent to the
Jellyfin server, so users can force specific formats on or off
independently instead of disabling Dolby Vision as a whole.

Related issues
This is a common problem across the Jellyfin ecosystem, but there isn't
a specific issue for Wholphin. My experience is the issue is FireTV
(model and generation) + TV dependent + media dependent. I tested videos
from
https://kodi.wiki/view/Samples with the same DOVIWithHDR10 flag that
worked while other movies I have with It is a very frustrating user
experience and the current workaround of setting the bitrate really low
to force a transcode is sub-optimal IMO as it lowers the video quality.
This allows the user to maintain full quality while disabling only the
specific format(s) causing problems.

https://github.com/jellyfin/jellyfin-androidtv/issues/4021
https://github.com/jellyfin/jellyfin-androidtv/issues/4892
https://github.com/nova-video-player/aos-AVP/issues/1503

https://www.reddit.com/r/jellyfin/comments/12jqoxh/dolby_vision_video_not_working_on_fire_stick_4k/

Testing

<!-- Describe how this change was tested and on what device(s) -->
FireTV 4K (gen 1) + Vizio
FireTV 4K Max (gen 1) + LG
FireTV 4K Max (gen 2) + Vizio
FireTV (gen 1) + Olevia


AI or LLM usage
Claude code assisted and wrote much of the code in this PR. I've
reviewed it all and run the pre-commit linting and formatting.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-13 15:41:53 -04:00
Prahlis
1571591a12
Translated using Weblate (Swedish)
Currently translated at 94.9% (626 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sv/
2026-10-10 10:52:06 +00:00
TheMatrixan
db77aaa3a4
Translated using Weblate (Polish)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/pl/
2026-10-10 10:52:06 +00:00
Prahlis
55d3254b1e
Translated using Weblate (Swedish)
Currently translated at 94.8% (625 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sv/
2026-10-10 10:52:06 +00:00
danpergal84
f14e5a5756
Translated using Weblate (Spanish)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/es/
2026-10-10 10:52:06 +00:00
danpergal84
68c48f154c
Translated using Weblate (Spanish)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/es/
2026-10-10 10:52:06 +00:00
Outbreak2096
c879a5713f
Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/zh_Hans/
2026-10-10 10:52:06 +00:00
SergeiAK
6308ad85a9
Translated using Weblate (Russian)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/ru/
2026-10-10 10:52:06 +00:00
Prahlis
ba5351f8dc
Translated using Weblate (Swedish)
Currently translated at 94.6% (624 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sv/
2026-10-10 10:52:06 +00:00
Prahlis
4502a12dcb
Translated using Weblate (Swedish)
Currently translated at 92.7% (611 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sv/
2026-10-10 10:52:06 +00:00
Andi Chandler
b03325accb
Translated using Weblate (English (United Kingdom))
Currently translated at 9.4% (62 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/en_GB/
2026-10-10 10:52:06 +00:00
MrGegaz
e4c3257c13
Translated using Weblate (Croatian)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/hr/
2026-10-10 10:52:06 +00:00
Greeg0ry
26d3e5b6fc
Translated using Weblate (Russian)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/ru/
2026-10-10 10:52:06 +00:00
idezentas
121208e021
Translated using Weblate (Turkish)
Currently translated at 99.8% (658 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/tr/
2026-10-10 10:52:05 +00:00
American_Jesus
0e0d50753b
Translated using Weblate (Portuguese)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/pt/
2026-10-10 10:52:05 +00:00
Priit Jõerüüt
29e235ffa5
Translated using Weblate (Estonian)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/et/
2026-10-10 10:52:05 +00:00
Sk4hnt42
c0eceba16c
Translated using Weblate (German)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/de/
2026-10-10 10:52:05 +00:00
SimonHung
22254bac32
Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/zh_Hant/
2026-10-10 10:52:05 +00:00
n8llcaster
0e11b8ff6f
Translated using Weblate (Slovak)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sk/
2026-10-10 10:52:05 +00:00
Damontecres
559abe2458
Add setting to force transcoding above a max resolution (#1955)
## Description
Adds a new setting to pick a maximum resolution (by height). Any
playback that has a larger resolution will be transcoded down to the
maximum resolution.

Playback equal or less than the maximum resolution will not be affected
and will direct play if otherwise able. This setting is also independent
of the maximum bitrate (ie if max resolution is 4K and max bitrate is
2mbps, playing 4K will transcode).

This setting is pretty much equivalent to the Web UI setting "Maximum
Allowed Video Transcoding Resolution" with "Limit maximum supported
video resolution" enabled.

Note: this setting does not affect which version is chosen by default

### Related issues
Closes #756
Closes #1594

### Testing
Manual emulator testing

## Screenshots
N/A

## AI or LLM usage
None
2026-10-03 18:41:18 -04:00
Damontecres
b0d270380d
Better home page header for Seasons (#2016)
## Description
Updates the home page header & card text when a Season type is shown,
such as in recently added for a TV Show library.

The title or logo for the series is shown with the season name as the
title. The "quick details" has the year of the season. The card shows
the unplayed count of episodes.

### Related issues
Closes #1958

### Testing
Emulator over a few days to see different seasons

## Screenshots
<img width="313" height="153" alt="image"
src="https://github.com/user-attachments/assets/c41e9edd-9f2a-4f62-b76d-e452e83dd8bf"
/>

## AI or LLM usage
None
2026-09-30 17:35:29 -04:00
Jycreyn
a577ae9f1a
Add option to prefer Dolby Vision over HDR10+ on hybrid videos (#1876)
## Description

Adds a "Prefer Dolby Vision over HDR10+" switch (off by default) under
Experimental settings. That screen only shows up once "Experimental
settings" is enabled under Advanced, and until then the switch is read
as off: it goes through `experimentalPreferences.get {}`, so nothing is
wrapped and the playback path is untouched.

Most current 4K web releases carry both Dolby Vision (profile 8.1) RPUs
and HDR10+ dynamic metadata in the same HEVC stream. Some MediaTek based
devices (Philips and TCL TVs, some Fire TV models) latch onto the HDR10+
metadata on those files and never engage Dolby Vision, even though a
Dolby Vision decoder is selected.

I isolated this on my Philips 55OLED810 by playing the same episode
three ways, direct play in all three cases:

| | Stream | TV shows |
|---|---|---|
| A | MKV with DV 8.1 + HDR10+ | HDR10+ |
| B | Same MKV with the HDR10+ metadata removed using
[hdr10plus_tool](https://github.com/quietvoid/hdr10plus_tool), DV
untouched | Dolby Vision |
| C | Same stream remuxed to MP4, both kinds of metadata present |
HDR10+ |

The container doesn't matter and the Dolby Vision signaling is picked up
correctly. The only thing the app can do is keep the HDR10+ metadata
away from the decoder.

When the switch is on, and only when a Dolby Vision decoder was actually
selected, the HDR10+ SEI messages (SMPTE ST 2094-40, recognized by their
ITU-T T.35 header `B5 003C 0001`) are masked in each access unit before
it is queued to MediaCodec. The SEI payload type byte is overwritten
with an unused value (254), so the decoder skips the message. That is
one byte rewritten in place per message: the masking filter returns the
size it was given, so the access unit is queued exactly as long as it
came out of the extractor, which is what makes it safe with both the
synchronous and asynchronous MediaCodec adapters. media3 does the same
thing for HAGC metadata in `HevcSeiUtil`; this filter only targets ST
2094-40, so other T.35 SEI such as CEA-708 captions are not affected.
The filter was written from the H.265 spec, no Kodi or media3 code was
copied.

The hook is generic rather than HDR10+ specific, as asked in the thread.
`BitstreamFilteringCodecAdapterFactory` wraps the codec adapter with a
`List<BitstreamFilter>`, and a filter is `(ByteBuffer, offset, size) ->
Int` where the returned `Int` is the new size of the access unit: the
adapter queues the size the chain reports, and hands each filter the
size the previous one reported. A filter which only overwrites bytes
returns the size unchanged, which is what the HDR10+ masking does; a
filter which drops NAL units compacts what it keeps and reports the
shorter size. A reported size which is negative or larger than the one
the filter was given is ignored rather than queued. That is what lets
the Dolby Vision profile 7 to 8.1 conversion of #244 arrive later as one
more filter instead of a second copy of the adapter plumbing.

When the switch is off, the playback path is unchanged. On a device
without a Dolby Vision decoder (or a display without DV support) the
wrapper is never installed, so HDR10+ only devices keep their metadata.
Encrypted samples, codec config buffers and empty buffers are passed
through untouched.

Kodi has an equivalent option for the same reason: xbmc/xbmc@032cbfeb
and xbmc/xbmc@e2c54e7f.

### Related issues

Implements what was requested in #1855. The filter list is what #244
(Dolby Vision profile 7 direct play) needs, so that conversion can be
added as another filter. #1895 implemented the same masking
independently and was closed in favour of this PR; the device profile
part of it was not carried over, see the note under Testing. Upstream:
androidx/media#1895, where the maintainers say the bug is in the device
codecs and that they don't plan a workaround in ExoPlayer itself.

## AI or LLM usage

The implementation (bitstream filter, MediaCodecAdapter wiring, unit
tests) were written with AI assistance (Claude). I reviewed the changes
and validated the behavior myself on a real MediaTek TV (Philips
55OLED810), with the setting on and off, on hybrid and DV-only content.

---------

Co-authored-by: Jycreyn <github.2ilp7@passmail.com>
2026-09-29 12:41:40 -04:00
Damontecres
190c6be41a
Run pre-commit 2026-09-12 18:43:14 -04:00
Prahlis
af6a3b9916
Translated using Weblate (Swedish)
Currently translated at 92.2% (608 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/sv/
2026-09-12 22:39:03 +00:00
TheMatrixan
a60433dbbf
Translated using Weblate (Polish)
Currently translated at 99.6% (657 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/pl/
2026-09-12 22:39:03 +00:00
arcker95
f181770870
Translated using Weblate (Italian)
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/it/
2026-09-12 22:39:03 +00:00
SimonHung
923f0b7ea3
Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (659 of 659 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/zh_Hant/
2026-09-12 22:39:03 +00:00
TheMatrixan
391a38e777
Translated using Weblate (Polish)
Currently translated at 98.6% (648 of 657 strings)

Translation: Wholphin/Wholphin
Translate-URL: https://translate.codeberg.org/projects/wholphin/wholphin/pl/
2026-09-12 22:39:03 +00:00