From 43bbf490dca972cb96fcf1d69dd0b6859377e452 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 15 Nov 2026 16:00:06 -0500 Subject: tools/guest-diag: tag BGRA capture records as GZF2 fmt 33 sdl_cap.c wrote the same 32 in the GZF2 record format field for every capture path, so gzf2_video.py's auto mode decoded ARGB8888/X-surface frames (BGRA byte order on little-endian) as RGBA and swapped red and blue. Make the field the documented pixel-order tag: 32 = RGBA8 from the GL swap path (glReadPixels GL_RGBA), 33 = BGRA8 from SDL_RenderReadPixels(ARGB8888) and X window surfaces; xgrab.c tags its ZPixmap BGRA records 33 as well. gzf2_video.py continues to accept both tags (and old all-32 captures via --pix-fmt bgra), checks ffmpeg/ffprobe before indexing, and keeps the final resampled endpoint so a 90-frame 60 fps capture encodes as 90 frames instead of 88. --- tools/guest-diag/sdl_cap.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'tools/guest-diag/sdl_cap.c') diff --git a/tools/guest-diag/sdl_cap.c b/tools/guest-diag/sdl_cap.c index 5b9c096..f875ed0 100644 --- a/tools/guest-diag/sdl_cap.c +++ b/tools/guest-diag/sdl_cap.c @@ -11,9 +11,12 @@ // File layout (little endian): // [0] 8B magic "GZCAPV01" (+ 4088 B reserved zero) // [4096] frame records: -// 4B "GZF2" | u32 w | u32 h | u32 stride | u32 bpp +// 4B "GZF2" | u32 w | u32 h | u32 stride | u32 fmt // u64 ts_ns (CLOCK_MONOTONIC) | u64 seq | stride*h bytes (top-down) -// A trailing record with seq = 0xFFFFFFFFFFFFFFFF marks clean stop. +// fmt is a pixel-order tag (not bits per pixel): 32 = RGBA8 from the GL +// swap path (glReadPixels GL_RGBA), 33 = BGRA8 from SDL_RenderReadPixels +// ARGB8888 or an X window surface. A trailing record with +// seq = 0xFFFFFFFFFFFFFFFF marks clean stop. // // Env: GZCAP (path, default /dev/shm/gzframes.bin), GZCAP_MAXF (0=unlimited) #define _GNU_SOURCE @@ -26,6 +29,8 @@ #include #define ARGB8888 0x16362004u +#define GZF2_FMT_RGBA 32 +#define GZF2_FMT_BGRA 33 typedef struct SDL_Renderer SDL_Renderer; typedef struct SDL_Window SDL_Window; @@ -87,7 +92,7 @@ __attribute__((constructor)) static void cap_init(void) if (h) real_glReadPixels = dlsym(h, "glReadPixels"); } - fprintf(stderr, "[gzcap] init pid=%d path=%s present=%p updwin=%p swap=%p read=%p gros=%p\n", + fprintf(stderr, "[gzcap] init pid=%d path=%s present=%p updwin=%p swap=%p read=%p gros=%p readpix=%p\n", (int)getpid(), p, (void *)real_RenderPresent, (void *)real_UpdateWindowSurface, (void *)real_GL_SwapWindow, (void *)real_RenderReadPixels, (void *)real_GetRendererOutputSize, (void *)real_glReadPixels); @@ -102,7 +107,7 @@ __attribute__((constructor)) static void cap_init(void) fflush(cap_fp); } -static void cap_record(const void *px, int w, int h, int stride, int bpp) +static void cap_record(const void *px, int w, int h, int stride, int fmt) { struct timespec ts; uint64_t tns, seq; @@ -126,7 +131,7 @@ static void cap_record(const void *px, int w, int h, int stride, int bpp) rh[0] = (uint32_t)w; rh[1] = (uint32_t)h; rh[2] = (uint32_t)stride; - rh[3] = (uint32_t)bpp; + rh[3] = (uint32_t)fmt; fwrite(m, 1, 4, cap_fp); fwrite(rh, 4, 4, cap_fp); fwrite(&tns, 8, 1, cap_fp); @@ -161,7 +166,7 @@ int SDL_RenderPresent(SDL_Renderer *r) } if (buf && real_RenderReadPixels(r, NULL, ARGB8888, buf, w * 4) == 0) - cap_record(buf, w, h, w * 4, 32); + cap_record(buf, w, h, w * 4, GZF2_FMT_BGRA); } } if (real_RenderPresent) @@ -180,7 +185,7 @@ int SDL_UpdateWindowSurface(SDL_Window *win) if (s && s->pixels && s->w > 0 && s->h > 0 && s->pitch > 0 && s->w <= 4096 && s->h <= 4096) - cap_record(s->pixels, s->w, s->h, s->pitch, 32); + cap_record(s->pixels, s->w, s->h, s->pitch, GZF2_FMT_BGRA); } if (real_UpdateWindowSurface) return real_UpdateWindowSurface(win); @@ -221,7 +226,7 @@ void SDL_GL_SwapWindow(SDL_Window *win) memcpy(tmp + (size_t)y * w * 4, gbuf + (size_t)(h - 1 - y) * w * 4, (size_t)w * 4); - cap_record(tmp, w, h, w * 4, 32); + cap_record(tmp, w, h, w * 4, GZF2_FMT_RGBA); free(tmp); } } -- cgit v1.2.3