Skip to content

Add encoded letterbox crop for desktop and Android - #1524

Merged
RadicalMuffinMan merged 5 commits into
Moonfin-Client:mainfrom
selmant:feat/libmpv-letterbox-crop
Sep 13, 2026
Merged

RadicalMuffinMan merged 5 commits into
Moonfin-Client:mainfrom
selmant:feat/libmpv-letterbox-crop

Conversation

@selmant

@selmant selmant commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Crop black bars playback toggle that detects encoded letterbox/pillarbox and crops it, then fills the screen. This is a separate setting from zoom Auto Crop on purpose.

#1523 is why: Auto Crop is cover-zoom (BoxFit.cover / aspect-fill). It scales the whole coded frame to fill the window and clips overflow. It does not find or remove black bars baked into a 16:9 file. Putting real bar-detection into that zoom control would make the existing confusion worse, so this ships as its own toggle next to zoom until that naming is sorted. If #1523 lands (rename Auto Crop so zoom is clearly fill/cover, not a crop), this can move into zoom settings.

Related Issues

Type of Change

  • New feature

Changes Made

  • Desktop libmpv: cropdetect then vf crop
  • Android Media3 (phone and TV): PixelCopy (TextureView getBitmap fallback), then layout zoom into the crop rect (SurfaceView + tunneling cannot use Media3 Crop effects)
  • Shared LetterboxCropper in playback_core; Aether / HTML / tvOS are explicit stubs
  • Setting is hidden where no cropper runs

Platform

  • Android
  • Android TV
  • Windows
  • Linux
  • iOS
  • tvOS
  • Web
  • macOS

No devices on hand for iOS / macOS / tvOS / web. The cropper interface is there so those platforms can follow this path.

Testing

  • Tested on emulator / simulator
  • Tested on physical device
  • Manual testing completed

Test Steps

  1. Settings → Playback & SyncPlay → Video Playback Preferences → enable Crop black bars (off by default)
  2. Play a title with encoded letterbox (not just window pillarboxing)
  3. After a few seconds the bars should crop and the picture should fill
  4. Confirm zoom Auto Crop is still cover-zoom and is not this detect

Tested on Linux (libmpv) and Android TV emulator (Media3). Phone uses the same Media3 path; iOS/macOS/tvOS/web untested.

Checklist

  • Code follows project style and conventions
  • No unnecessary commented-out code

Made with Cursor

selmant and others added 5 commits September 12, 2026 22:02
Detect encoded black bars with cropdetect, then fill the frame, instead of treating cover-zoom as auto crop.

Co-authored-by: Cursor <cursoragent@cursor.com>
Media3 detects encoded bars via PixelCopy and zooms into the crop rect. Hide Crop black bars on phone, iOS, macOS, web, and tvOS. Drop the Fill rename so Auto Crop stays cover-zoom, not bar detection.

Co-authored-by: Cursor <cursoragent@cursor.com>
The Media3 PixelCopy path is not TV-only. Drop the duplicate plugin junit/gradle.properties and keep Auto Crop labels/descriptions unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
…les.

Co-authored-by: Cursor <cursoragent@cursor.com>
@RadicalMuffinMan
RadicalMuffinMan force-pushed the feat/libmpv-letterbox-crop branch from 7b492f6 to 80dcf24 Compare September 13, 2026 02:30
@RadicalMuffinMan
RadicalMuffinMan merged commit ed0704e into Moonfin-Client:main Sep 13, 2026
@mattsigal

mattsigal commented Sep 13, 2026 •

Copy link
Copy Markdown
Collaborator

Hope you don't mind me popping in to ask a few questions @selmant -- I just don't have a file at the ready to test this with and was curious.

  1. If I understand this right, using the new toggles means it'll apply the crop just to the bars then do the requested zoom mode? So having this on + zoom mode set to Fit would mean it'll always show the entire image, yeah? And only make a difference if the source file has the black bars included.
  2. Does this have any impact on direct playing? If the toggle kicks in, would that force a transcode?
  3. There are some movies (e.g. films with some scenes that use IMAX dimensions) that switch between letterboxed and full-screen images. How would the toggle handle those cases?

@selmant

selmant commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author
  1. Not exactly. This is basically separate from the zoom mode. The zoom modes are mainly about how the video frame is fitted/stretched to the screen, while this specifically detects black bars that are actually encoded into the video and removes them. This is especially useful on ultrawide monitors. I have a 21:9 monitor myself. A lot of 18:9 / 21:9 movies are still encoded inside a 16:9 frame with black bars, so just using the existing zoom modes doesn't really solve the problem properly. Originally I actually disabled the normal zoom mode while this was enabled because once the bars are removed I didn't really need it anymore, but @RadicalMuffinMan changed that so the two can now be used independently. Maybe he has a different plan for how they should interact.

  2. No, this doesn't modify the file on the server or force a transcode. Everything happens locally in the client. On desktop it's basically cropdetect + vf crop. The only slightly special part is hardware decoding. cropdetect needs access to the decoded frames, so if the current hwdec mode doesn't allow that, Moonfin temporarily switches to a compatible decoding mode while detecting the bars and restores it afterwards. So Direct Play itself is still Direct Play.

  3. Right now I implemented it as a one-time detection near the beginning of playback, so movies that switch between letterboxed and IMAX/full-frame scenes won't update the crop dynamically. Maybe we can make it re-scan every 20 seconds or something like that. I think it's worth testing to see if that works well without causing visible jumps or too much overhead.

@selmant selmant mentioned this pull request Sep 17, 2026
11 of 25 tasks
@JayBrown

Copy link
Copy Markdown

Question, though not for me, because I'm on macOS/iOS/tvOS: does this also cover vertical black bars? Example – a screengrab from a movie's internal production copy (16:9 video) with black bars all around:

snap

Does this also detect and crop the vertical bars left & right? (For me on macOS, I'll have to reencode the file with ffmpeg incl. cropping anyway, but maybe it works on Linux/Windows.)

@selmant

selmant commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor Author

@JayBrown Good question. It didn't cover that before: bars on all four sides were ignored. I've added support for it in the new PR, #1579 (#1579), so a picture with black bars all around (like your screengrab) now gets cropped on Android, Linux and Windows.

Unfortunately I don't have an Apple device, so there's no macOS/iOS/tvOS support for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants