Extract the "use whatever decoder ffmpeg provides" logic from
FFmpeg_Input into a shared open_fallback_decoder() and call it from
FfmpegCamera, which had lost the fallback: its generic path only ran
inside the preferred-codec loop, so an empty get_decoder_data() result
failed outright instead of trying the codec's default decoder.
The dec_codecs table stays a preference list; a codec present in the
ffmpeg build but absent from the table (e.g. libopenh264 for H264) now
decodes via the fallback instead of requiring a hard-coded entry.
Add tests/zm_ffmpeg_fallback.cpp covering the fallback with a codec not
in dec_codecs (mpeg2video), the optional codec_out argument, and the
no-decoder case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
swscale assumes limited (MPEG, 16-235) input range by default. Mapping a
full-range JPEG format (YUVJ*) to its non-J equivalent for the conversion
therefore washes the colours out, because full-range luma/chroma gets
treated as limited.
Add pix_fmt_is_jpeg_range() and zm_sws_set_input_range(), which sets
srcRange=1 on the context when the original source format was full range.
Apply it at every conversion site that takes decoded frames: Image::Assign
and both SWScale::Convert overloads. Monitor::setupConvertContext already
did this inline with a hand-rolled switch and colorspace block; replace
that with the shared helpers to remove the duplication.
Add tests/zm_swscale_range.cpp: converting a Y=16 YUVJ420P image to RGB24
keeps luma ~16 (full range) rather than being crushed to ~0 (limited).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ZM_COLOUR_GRAY8, ZM_COLOUR_YUV420P, and ZM_COLOUR_YUVJ420P were all
defined to 1, making format identification via colours ambiguous.
LocalCamera misidentified YUV420P as GRAY8, causing V4L2 MJPEG cameras
to decode to grayscale via expensive sws_scale conversion.
Replace the legacy ZM_COLOUR_*/ZM_SUBPIX_ORDER_* integer pair with
AVPixelFormat as the single source of truth for pixel format dispatch:
- Add src/zm_pixformat.h with central format helpers:
zm_pixformat_from_colours, zm_colours_from_pixformat,
zm_bytes_per_pixel, zm_db_colours_to_pixformat, zm_is_rgb32,
zm_is_rgb24, zm_is_yuv420
- Add AVPixelFormat pixelFormat member + PixelFormat() accessor to Camera
- Add PixFormat() accessor to Image, delegate AVPixFormat methods
to shared helpers
- Migrate all ~100 format dispatch comparisons in zm_image.cpp,
zm_local_camera.cpp, zm_ffmpeg_camera.cpp, zm_remote_camera_rtsp.cpp,
zm_libvlc_camera.cpp, zm_libvnc_camera.cpp, zm_monitor.cpp,
zm_mpeg.cpp from colours/subpixelorder checks to imagePixFormat/
AVPixelFormat checks
- Deprecate GetFFMPEGPixelFormat, delegate to zm_pixformat_from_colours
- Fix DeColourise bug: imagePixFormat was not updated to GRAY8
- Deprecate ZM_COLOUR_* and ZM_SUBPIX_ORDER_* constants in zm_rgb.h
- Add deprecation notice on Monitor.Colours web UI dropdown
- Add 13 Catch2 test cases (105 assertions) for format mapping helpers
refs #4735
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Debug messages incorrectly used "!=" when describing matching conditions.
Changed to "==" to accurately reflect that the codec name/id matched.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
send_packet will fail with -EAGAIN if receive_frame hasn't consumed the
last packet. Similarly send_frame will fail if receive_packet has
pending frames.
This fixes problems with the raspberry pi hardware decoder. The change
likely affects many other codecs as well.
FFmpeg is an integral component of ZM. Promote the appropriate libraries to required dependencies.
This reduces the possible build configurations greatly and thus maintenance burden.
FFmpeg is an integral component of ZM. Promote the appropriate libraries to required dependencies.
This reduces the possible build configurations greatly and thus maintenance burden.