Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7b21371
Reapply "fix: replace ZM_COLOUR system with AVPixelFormat for format …
connortechnology May 3, 2026
45a4671
fix: planar YUV correctness + alignment in Image methods
connortechnology May 3, 2026
c8d8cc3
feat: SHM cross-process format consistency via per-slot AVPixelFormat
connortechnology May 3, 2026
a7c3fb7
Merge branch 'master' into fix/avpixelformat-respin
connortechnology May 22, 2026
1fe2920
fix: address PR #4788 review comments on AVPixelFormat migration
connortechnology May 22, 2026
d6a146e
fix: address PR #4788 review comments on SHM publish ordering and ove…
connortechnology May 23, 2026
158d943
fix: address PR #4788 review comments on planar sizing and SHM bounds
connortechnology May 23, 2026
766b3c7
fix: cross-process AVPixelFormat sync for alarm_image (PR #4788)
connortechnology May 24, 2026
77edeca
fix: use linesize for row stride in pixel ops (PR #4788)
connortechnology May 25, 2026
6a1c4e7
fix: fully invalidate Image on AssignDirect(AVFrame) format failure (…
connortechnology May 25, 2026
667b00b
fix: address remaining width-vs-linesize and planar chroma issues (PR…
connortechnology May 25, 2026
e6ed0e0
fix: linesize/planar correctness for Overlay, Rotate, Flip, AssignDir…
connortechnology May 26, 2026
e5446d3
fix: report AVPixelFormat in Panic messages for actionable diagnosis …
connortechnology May 27, 2026
3592fbb
fix: dest linesize in HighlightEdges, ceiling chroma dims in MaskPriv…
connortechnology May 27, 2026
070704d
fix: ceiling chroma dims in Rotate/Flip; clearer Assign error (PR #4788)
connortechnology May 27, 2026
133bb53
fix: Camera::linesize/imagesize back to tightly-packed (PR #4788)
connortechnology May 27, 2026
a5bf39d
fix: keep DeColourise/AssignDirect(AVFrame) state self-consistent (PR…
connortechnology May 28, 2026
2846970
fix: PopulateFrame error handling + canonical pix fmt in Scale (PR #4…
connortechnology May 28, 2026
aa9884e
Merge branch 'master' into fix/avpixelformat-respin
connortechnology May 29, 2026
36effc8
fix: stride-aware Delta and Deinterlace_4Field (PR #4788)
connortechnology May 29, 2026
f794e26
fix: per-row Overlay; align image_pixelformats SHM pointer (PR #4788)
connortechnology May 30, 2026
fb7b1d1
fix: SHM padding covers both alignment adjustments (PR #4788)
connortechnology May 31, 2026
6765962
fix: nullptr-safe pixfmt name; route GetImage/getSnapshot through Rea…
connortechnology May 31, 2026
ec8d48a
fix: switch remaining av_get_pix_fmt_name calls in zm_ffmpeg_camera.c…
connortechnology May 31, 2026
90c6bc0
fix: guard SHM pixformat publish on assign failure (PR #4788)
connortechnology Jun 1, 2026
bfe9c4a
fix: free previously-owned buffer in AssignDirect(AVFrame); nullptr-s…
connortechnology Jun 3, 2026
bc8be20
fix: use canonical imagePixFormat in Image::Assign(AVFrame*) (PR #4788)
connortechnology Jun 3, 2026
9bae26b
fix: handle "no frames yet" sentinel before bounds check (PR #4788)
connortechnology Jun 3, 2026
bc88781
fix: Image::Assign(uint8_t*) handle packed source -> aligned dest (PR…
connortechnology Jun 3, 2026
de3638e
fix: Image::Assign(Image&) handle smaller-source linesize; explicit p…
connortechnology Jun 4, 2026
9e19c66
fix: Image(AVFrame*) ctor delegates to default ctor before AssignDire…
connortechnology Jun 4, 2026
6ecf510
fix: more actionable error messages in GetImage/getSnapshot/WriteBuff…
connortechnology Jun 4, 2026
12d864e
fix: Deinterlace_Discard OOB write on odd heights (PR #4788)
connortechnology Jun 5, 2026
965936e
fix: pass delta8_* fn ptrs directly; zm_get_pix_fmt_name in Delta pan…
connortechnology Jun 5, 2026
2b55ed4
fix: nullptr-safe pix fmt name in Colourise/Deinterlace_4Field error …
connortechnology Jun 6, 2026
b486c0c
fix: include <libavutil/pixdesc.h> in zm_pixformat.h (PR #4788)
connortechnology Jun 6, 2026
9687faa
refactor: remove dead FfmpegCamera::imagePixFormat field
connortechnology Jun 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/zm_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Camera::Camera(
height(p_height),
colours(p_colours),
subpixelorder(p_subpixelorder),
pixelFormat(zm_pixformat_from_colours(p_colours, p_subpixelorder)),
brightness(p_brightness),
hue(p_hue),
colour(p_colour),
Expand All @@ -63,9 +64,37 @@ Camera::Camera(
mLastAudioDTS(AV_NOPTS_VALUE),
bytes(0),
mIsPrimed(false) {
linesize = width * colours;
// Camera::linesize/imagesize describe the *device-side* buffer that
// capture paths copy from (V4L2 mmap buffers, raw RTP frames, etc).
// Those buffers are tightly packed at the driver/source stride, not
// 32-byte aligned, so use align=1 here. ZM's internal Image buffers
// and SHM slots independently apply their own 32-byte alignment for
// SIMD performance — that decoupling is the source of the size-mismatch
// Fatal in LocalCamera::PrimeCapture when widths aren't 32-aligned.
//
// Guard against an unknown (colours, subpixelorder) pair that produced
// pixelFormat == AV_PIX_FMT_NONE, or any case where av_image_get_*
// returns a negative size — assigning those to unsigned would wrap to a
// huge value and break SHM sizing and downstream allocations.
pixels = width * height;
imagesize = static_cast<unsigned long long>(height) * linesize;
if (pixelFormat == AV_PIX_FMT_NONE) {
Error("Camera: unknown pixel format from colours=%u subpixelorder=%u; falling back to width*colours stride",
p_colours, p_subpixelorder);
linesize = width * colours;
imagesize = static_cast<unsigned long long>(height) * linesize;
} else {
int raw_linesize = av_image_get_linesize(pixelFormat, width, 0);
int raw_imagesize = av_image_get_buffer_size(pixelFormat, width, height, 1);
if (raw_linesize < 0 || raw_imagesize < 0) {
Error("Camera: av_image_get_* returned %d/%d for pixelFormat=%s; falling back",
raw_linesize, raw_imagesize, zm_get_pix_fmt_name(pixelFormat));
linesize = width * colours;
imagesize = static_cast<unsigned long long>(height) * linesize;
} else {
linesize = static_cast<unsigned int>(raw_linesize);
imagesize = static_cast<unsigned long long>(raw_imagesize);
}
Comment thread
connortechnology marked this conversation as resolved.
}

Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d, size: %llu",
monitor->Id(), width, linesize, height, colours, subpixelorder, capture, imagesize);
Expand Down Expand Up @@ -101,7 +130,7 @@ AVStream *Camera::getVideoStream() {
mVideoStream->time_base = (AVRational) {1, 1000000}; // microseconds as base frame rate
mVideoStream->codecpar->width = width;
mVideoStream->codecpar->height = height;
mVideoStream->codecpar->format = GetFFMPEGPixelFormat(colours, subpixelorder);
mVideoStream->codecpar->format = pixelFormat;
mVideoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
mVideoStream->codecpar->codec_id = AV_CODEC_ID_NONE;
Debug(1, "Allocating avstream %p %p %d", mVideoStream, mVideoStream->codecpar, mVideoStream->codecpar->codec_id);
Expand Down
11 changes: 7 additions & 4 deletions src/zm_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define ZM_CAMERA_H

#include "zm_image.h"
#include "zm_pixformat.h"
#include <sys/ioctl.h>
#include <sys/types.h>

Expand All @@ -42,8 +43,9 @@ class Camera {
uint16_t width;
uint16_t height;
unsigned int linesize;
unsigned int colours;
unsigned int subpixelorder;
unsigned int colours; // DEPRECATED: use pixelFormat
unsigned int subpixelorder; // DEPRECATED: use pixelFormat
AVPixelFormat pixelFormat;
unsigned int pixels;
unsigned long long imagesize;
int brightness;
Expand Down Expand Up @@ -98,8 +100,9 @@ class Camera {
unsigned int Width() const { return width; }
unsigned int LineSize() const { return linesize; }
unsigned int Height() const { return height; }
unsigned int Colours() const { return colours; }
unsigned int SubpixelOrder() const { return subpixelorder; }
unsigned int Colours() const { return colours; } // DEPRECATED
unsigned int SubpixelOrder() const { return subpixelorder; } // DEPRECATED
AVPixelFormat PixelFormat() const { return pixelFormat; }
unsigned int Pixels() const { return pixels; }
unsigned long long ImageSize() const { return imagesize; }
unsigned int Bytes() const { return bytes; };
Expand Down
42 changes: 3 additions & 39 deletions src/zm_ffmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "zm_ffmpeg.h"

#include "zm_logger.h"
#include "zm_pixformat.h"
#include "zm_rgb.h"
#include "zm_utils.h"

Expand Down Expand Up @@ -327,46 +328,9 @@ void FFMPEGDeInit() {
bInit = false;
}

// DEPRECATED: use zm_pixformat_from_colours() from zm_pixformat.h instead.
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder) {
enum _AVPIXELFORMAT pf;

Debug(8,"Colours: %d SubpixelOrder: %d",p_colours,p_subpixelorder);

switch (p_colours) {
case ZM_COLOUR_RGB24:
if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) {
/* BGR subpixel order */
pf = AV_PIX_FMT_BGR24;
} else {
/* Assume RGB subpixel order */
pf = AV_PIX_FMT_RGB24;
}
break;
case ZM_COLOUR_RGB32:
if (p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) {
/* ARGB subpixel order */
pf = AV_PIX_FMT_ARGB;
} else if (p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) {
/* ABGR subpixel order */
pf = AV_PIX_FMT_ABGR;
} else if (p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) {
/* BGRA subpixel order */
pf = AV_PIX_FMT_BGRA;
} else {
/* Assume RGBA subpixel order */
pf = AV_PIX_FMT_RGBA;
}
break;
case ZM_COLOUR_GRAY8:
pf = AV_PIX_FMT_GRAY8;
break;
default:
Panic("Unexpected colours: %d", p_colours);
pf = AV_PIX_FMT_GRAY8; /* Just to shush gcc variable may be unused warning */
break;
}

return pf;
return zm_pixformat_from_colours(p_colours, p_subpixelorder);
}

#if LIBAVUTIL_VERSION_CHECK(56, 0, 0, 17, 100)
Expand Down
19 changes: 10 additions & 9 deletions src/zm_ffmpeg_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,18 @@ FfmpegCamera::FfmpegCamera(

/* Has to be located inside the constructor so other components such as zma
* will receive correct colours and subpixel order */
if ( colours == ZM_COLOUR_RGB32 ) {
if ( zm_is_rgb32(pixelFormat) ) {
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
imagePixFormat = AV_PIX_FMT_RGBA;
} else if ( colours == ZM_COLOUR_RGB24 ) {
pixelFormat = AV_PIX_FMT_RGBA;
} else if ( zm_is_rgb24(pixelFormat) ) {
subpixelorder = ZM_SUBPIX_ORDER_RGB;
imagePixFormat = AV_PIX_FMT_RGB24;
} else if ( colours == ZM_COLOUR_GRAY8 ) {
pixelFormat = AV_PIX_FMT_RGB24;
} else if ( pixelFormat == AV_PIX_FMT_GRAY8 ) {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
imagePixFormat = AV_PIX_FMT_GRAY8;
pixelFormat = AV_PIX_FMT_GRAY8;
} else {
Panic("Unexpected colours: %d", colours);
Panic("Unexpected pixel format %d (%s); legacy colours=%d subpixelorder=%d",
pixelFormat, zm_get_pix_fmt_name(pixelFormat), colours, subpixelorder);
}
Comment thread
connortechnology marked this conversation as resolved.
Comment thread
connortechnology marked this conversation as resolved.
Comment thread
connortechnology marked this conversation as resolved.
Comment thread
connortechnology marked this conversation as resolved.

packet = av_packet_ptr{av_packet_alloc()};
Expand Down Expand Up @@ -525,7 +526,7 @@ int FfmpegCamera::OpenFfmpeg() {
mVideoCodec->name,
av_hwdevice_get_type_name(type),
av_hwdevice_get_type_name(config->device_type),
av_get_pix_fmt_name(config->pix_fmt)
zm_get_pix_fmt_name(config->pix_fmt)
);
}
} // end foreach hwconfig
Expand All @@ -534,7 +535,7 @@ int FfmpegCamera::OpenFfmpeg() {
#endif
if (hw_pix_fmt != AV_PIX_FMT_NONE) {
Debug(1, "Selected hw_pix_fmt %d %s",
hw_pix_fmt, av_get_pix_fmt_name(hw_pix_fmt));
hw_pix_fmt, zm_get_pix_fmt_name(hw_pix_fmt));

mVideoCodecContext->hwaccel_flags |= AV_HWACCEL_FLAG_IGNORE_LEVEL;
//if (!lavc_param->check_hw_profile)
Expand Down
2 changes: 0 additions & 2 deletions src/zm_ffmpeg_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ class FfmpegCamera : public Camera {

int frameCount;

_AVPIXELFORMAT imagePixFormat;

bool use_hwaccel; //will default to on if hwaccel specified, will get turned off if there is a failure
#if HAVE_LIBAVUTIL_HWCONTEXT_H
AVBufferRef *hw_device_ctx = nullptr;
Expand Down
Loading
Loading