ffmpeg_bridge: fix cross-platform CI failures (Ubuntu/macOS/Windows)

Ubuntu (FFmpeg 7.0) build failure: the public FB_PIX_FMT_* values were
hardcoded to AVPixelFormat enum values, but those shift between FFmpeg
releases (new formats are inserted mid-enum: X2RGB10 in 7.0,
RGBF16/GRAYF16 later), so the static_asserts in internal.h failed and
RGBF16LE/GRAYF16LE did not exist at all.

The FB pixel format values are now fixed identifiers translated inside
the library by pixel format name (stable across releases):
- fb::PixFmtToAV/PixFmtFromAV resolve the static table by name;
  formats a decoder produces that have no static identifier (hardware
  downloads like nv12/p010le/p210le) receive process-local dynamic ids
  >= 1000 so they keep round-tripping through the API (scaler etc.)
  instead of collapsing to NONE and crashing sws.
- All crossing points translated: scaler, frame get/set format,
  decoder/probe stream info, encoder config and write_video_frame,
  fb_pix_fmt_* utilities, fb_find_best_pix_fmt_of_list (which also
  reinterpret_cast the caller's list; now translated element-wise and
  properly NONE-terminated).
- nv12 and p010le get static identifiers as the common hardware
  download formats.
- Hardware frame detection no longer compares pixel formats (breaks
  across format spaces); it uses the existing fb_frame_is_hw().

macOS test failures (FFmpegBridgeEncoder.WritePngVideoAndProbeBack,
WritePcmAudioAndProbeBack): config.filename held a dangling pointer to
a temporary QByteArray (UB; happened to work on Linux). Keep the
QByteArray alive for the encoder's lifetime.

Windows (MSYS2 UCRT64) build failure: timecodefunctions.h used int64_t
without including <cstdint> (previously pulled in transitively).

Full gtest suite: 584 passed.
This commit is contained in:
2026-07-16 08:35:19 +08:00
parent c203ce1dbf
commit 9957577cb9
11 changed files with 197 additions and 57 deletions
@@ -69,9 +69,12 @@ extern "C" {
#define FB_SCALER_POINT 0x10
/**
* Pixel formats. Values deliberately mirror AVPixelFormat so that the library
* can use them directly; every value is static_assert'ed against the real
* FFmpeg headers inside the library. Callers must treat them as opaque.
* Pixel formats. These are fixed identifiers; the library maps them to the
* AVPixelFormat values of whatever FFmpeg build it was compiled against
* (AVPixelFormat enum values shift between FFmpeg releases). Callers must
* treat them as opaque. A format may be unknown to an older FFmpeg build,
* in which case library calls reject it gracefully. Decoded frames whose
* format has no entry here receive an opaque process-local id >= 1000.
*/
typedef enum FBPixelFormat {
FB_PIX_FMT_NONE = -1,
@@ -85,6 +88,7 @@ typedef enum FBPixelFormat {
FB_PIX_FMT_YUVJ420P = 12,
FB_PIX_FMT_YUVJ422P = 13,
FB_PIX_FMT_YUVJ444P = 14,
FB_PIX_FMT_NV12 = 23,
FB_PIX_FMT_RGBA = 26,
FB_PIX_FMT_GRAY16LE = 30,
FB_PIX_FMT_YUV440P = 31,
@@ -98,6 +102,7 @@ typedef enum FBPixelFormat {
FB_PIX_FMT_YUV422P12LE = 127,
FB_PIX_FMT_YUV444P12LE = 131,
FB_PIX_FMT_YUVJ411P = 138,
FB_PIX_FMT_P010LE = 158,
FB_PIX_FMT_GRAYF32LE = 183,
FB_PIX_FMT_RGBAF16LE = 207,
FB_PIX_FMT_RGBF32LE = 218,