Add design doc for macOS FFmpeg player

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Noisyfox
2026-08-14 20:08:35 +08:00
parent 73131735a2
commit 111364d880

View File

@@ -0,0 +1,110 @@
# FFmpeg Media Player for macOS — Design
Date: 2026-08-14
Branch: `dev/ffmpeg-player-macos`
## Problem
The branch's new FFmpeg-based media player (`wxMediaCtrl3` + `AVVideoDecoder`) is used on
Windows and Linux, but macOS still runs the old player: `wxMediaCtrl2.mm`, an ObjC
`BambuPlayer` class dlsym'd from the Bambu network plugin that renders via CALayer.
On macOS, `wxMediaCtrl3` is currently aliased to `wxMediaCtrl2` and FFmpeg is not linked
into the app at all.
Goal: make macOS use the same FFmpeg player as Windows/Linux, linking the **static**
FFmpeg libraries from the deps build instead of dynamic ones.
## Current state (verified)
- New player (Win/Linux): `GUI/wxMediaCtrl3.cpp` + `GUI/AVVideoDecoder.cpp`. Decodes with
FFmpeg (libavcodec/libswscale/libavutil), renders frames into `wxImage` (non-Windows) /
`wxBitmap` (Windows) drawn in a `paintEvent`, feeds via the `Bambu_*` C API
(`BambuTunnel.h`, `BAMBU_DYNAMIC`) dlsym'd from the network plugin through
`StaticBambuLib::get()` (`GUI/Printer/PrinterFileSystem.cpp`, compiled on all platforms).
- Old player (macOS): `GUI/wxMediaCtrl2.mm` uses the ObjC `BambuPlayer` class found via
`dlsym(module, "OBJC_CLASS_$_BambuPlayer")` in `libBambuSource.dylib`.
- The macOS network plugin `libBambuSource.dylib` already exports the full Bambu C API
(verified with `nm`), so the new player needs zero plugin changes.
- FFmpeg linking in `src/slic3r/CMakeLists.txt` is guarded by `if (NOT APPLE)`
macOS currently does not link FFmpeg.
- `deps/FFMPEG/FFMPEG.cmake`: non-MSVC branch builds FFmpeg from source with
`--enable-shared`. The existing arm64 deps build on the dev machine happened to be
configured with both static and shared enabled, so `libavcodec.a` / `libswscale.a` /
`libavutil.a` are already present at
`deps/build/arm64/OrcaSlicer_dep/usr/local/lib/`.
- `EVT_MEDIA_CTRL_STAT` is `wxDEFINE_EVENT`'d in `wxMediaCtrl2.cpp` (Win/Linux) and
`wxMediaCtrl2.mm` (macOS); the define in `wxMediaCtrl3.cpp` is commented out.
- `wxMediaCtrl2` is never instantiated anywhere on any platform — dead code.
- `StatusPanel` already creates `wxMediaCtrl3`; `MediaPlayCtrl` only uses the
`wxMediaCtrl3` interface (`Load/Play/Stop/GetState/GetVideoSize/GetLastError/SetIdleImage`),
so no UI-side changes are needed.
## Approach (approved)
**Reuse the shared player on macOS.** Compile the existing `wxMediaCtrl3.cpp` +
`AVVideoDecoder.cpp` on macOS so all three platforms run one implementation.
Rendering uses the existing `wxImage``DrawBitmap` paint path, identical to Linux.
Known trade-off: frames are scaled to the widget's logical (1x) size, so Retina is
slightly soft compared to the old CALayer player. Accepted for now; a Retina-aware
scaling follow-up is possible later.
Rejected alternative: a native CGImage/CALayer renderer for macOS — faster and
Retina-crisp, but adds a second render implementation to maintain.
## Changes
### 1. Enable the FFmpeg player on macOS (source)
- `GUI/wxMediaCtrl3.h`: remove the `#ifdef __WXMAC__` branch (lines 1822) that aliases
`wxMediaCtrl3``wxMediaCtrl2`. macOS then compiles the real `wxMediaCtrl3` class,
including the `BAMBU_DYNAMIC` BambuTunnel path used on Linux.
- Event symbol fix: move `wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent)` into
`wxMediaCtrl3.cpp` (uncomment the existing line) and remove it from
`wxMediaCtrl2.cpp`. One definition total in the lib; all three platforms resolve it.
### 2. Static FFmpeg linking (deps + app)
- `deps/FFMPEG/FFMPEG.cmake`: in the non-MSVC branch, pass
`--disable-shared --enable-static` when `APPLE`. Linux keeps `--enable-shared`;
Windows keeps its prebuilt shared DLL zips. Fresh macOS deps builds install only
`libavcodec.a` / `libswscale.a` / `libavutil.a` — no dylibs to bundle, no
rpath/install_name handling. (The existing local arm64 deps build already contains
the `.a` files, so no deps rebuild is strictly needed to try the change locally,
but a fresh CI deps build must produce them.)
- `src/slic3r/CMakeLists.txt`:
- APPLE branch of `SLIC3R_GUI_SOURCES`: add `GUI/wxMediaCtrl3.cpp`,
`GUI/wxMediaCtrl3.h`, `GUI/AVVideoDecoder.cpp`, `GUI/AVVideoDecoder.hpp`;
remove `GUI/wxMediaCtrl2.mm` and `GUI/wxMediaCtrl2.h` (the `.h` stays on
disk for the Win/Linux build of `wxMediaCtrl2.cpp`, but nothing on macOS
includes it after this change).
- Add an APPLE mirror of the `NOT APPLE` FFmpeg block: `find_library` for
`libavcodec.a`, `libswscale.a`, `libavutil.a` under `${CMAKE_PREFIX_PATH}/lib`
with `NO_DEFAULT_PATH`, link them (order avcodec → swscale → avutil), and add
`${CMAKE_PREFIX_PATH}/include` as a SYSTEM include directory. Deps are built with
`--disable-zlib` and no external codecs, so the three static libs link cleanly.
### 3. Remove the old player
- Delete `GUI/wxMediaCtrl2.mm` and `GUI/BambuPlayer/BambuPlayer.h` (header used only
by the `.mm`; the real `BambuPlayer` lives inside the network plugin).
- Remove the now-dead `__WXMAC__` section of `GUI/wxMediaCtrl2.h`.
- `wxMediaCtrl2.cpp` (Win/Linux) stays in the build as-is (dead but harmless; out of
scope to remove on this branch).
### 4. Verification
- Build on macOS: `cmake --build build_arm64` (or `build/arm64`).
- Confirm no dynamic FFmpeg dependency: `otool -L` on the app binary shows no `libav*`
dylib references.
- Runtime: with the network plugin loaded, the Device tab camera preview streams via
the FFmpeg player (check the device page / `MediaPlayCtrl`).
- macOS `ctest` still passes — static linking means no test-executable `.so` copying
hacks (unlike the Linux shared-lib setup).
## Out of scope
- Linux (shared libs, AppImage/flatpak bundling) and Windows (prebuilt DLL zips)
keep their current FFmpeg setup.
- Retina-aware frame scaling / native CGImage rendering (follow-up if visual quality
is judged insufficient).
- Audio streaming (neither player plays audio in this UI path).