Короче захотел сделать фотку через SDL3
столкнулся с парой проблем.
Пишу просто по причине того что я долго ломал голову что не так, откуда ошибка, пока не втыкнул паузу, почему вместо снимка чернота, пока не пропустил несколько первых кадров. Для меня это было нифига не очевидно, может кому сэкономит время.
-
Появляется ошибка
Parameter 'surface' is invalid
если не сделать паузу после открытия камеры, решается в установлении паузы в0,5
секунды послеSDL_OpenCamera
-
Первые кадры с камеры либо просто чёрные, либо очень тёмные. Решается пропуском (в моём случае 7) нескольких первых кадров.
Я забросил в SDL3
уведомительное issue, чтобы было
Продублирую тут тестовый пример и результаты
Информация о системе
Web-camera встроена в ноут, понятия не имею что за камера
description: Notebook
product: K53U
vendor: ASUSTeK Computer Inc.
version: 1.0
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm
fedor@nixfed:~/drawshoot$ cat SDL3/VERSION.txt
3.1.3
fedor@nixfed:~/drawshoot$
Тестовый код
Makefile
SDL_DIR=SDL3
SDL_LIB_DIR=$(SDL_DIR)/build
SDL_INC_DIR=$(SDL_DIR)/include
test-1:
$(CC) main.c -I$(SDL_INC_DIR) -L$(SDL_LIB_DIR) -lSDL3 -o app
test-2:
$(CC) main.c -I$(SDL_INC_DIR) -L$(SDL_LIB_DIR) -lSDL3 -o app -DENABLE_DELAY
test-3:
$(CC) main.c -I$(SDL_INC_DIR) -L$(SDL_LIB_DIR) -lSDL3 -o app -DENABLE_DELAY -DENABLE_FRAMEDROP
sdl:
cd $(SDL_DIR) && mkdir build
cd $(SDL_DIR)/build && cmake ..
cd $(SDL_DIR)/build && $(MAKE) -j2
clean:
-$(MAKE) -C $(SDL_DIR) clean
-rm app
run:
LD_LIBRARY_PATH=$(SDL_DIR)/build ./app
main.c
#include "SDL3/SDL.h"
#include "SDL3/SDL_camera.h"
#include <stdio.h>
/*just for debug*/
const char * pixel_format_name(SDL_PixelFormat format)
{
switch(format){
case SDL_PIXELFORMAT_UNKNOWN: return "UNKNOWN";
case SDL_PIXELFORMAT_INDEX1LSB: return "INDEX1LSB";
case SDL_PIXELFORMAT_INDEX1MSB: return "INDEX1MSB";
case SDL_PIXELFORMAT_INDEX2LSB: return "INDEX2LSB";
case SDL_PIXELFORMAT_INDEX2MSB: return "INDEX2MSB";
case SDL_PIXELFORMAT_INDEX4LSB: return "INDEX4LSB";
case SDL_PIXELFORMAT_INDEX4MSB: return "INDEX4MSB";
case SDL_PIXELFORMAT_INDEX8: return "INDEX8";
case SDL_PIXELFORMAT_RGB332: return "RGB332";
case SDL_PIXELFORMAT_XRGB4444: return "XRGB4444";
case SDL_PIXELFORMAT_XBGR4444: return "XBGR4444";
case SDL_PIXELFORMAT_XRGB1555: return "XXRGB1555";
case SDL_PIXELFORMAT_XBGR1555: return "XXBGR1555";
case SDL_PIXELFORMAT_ARGB4444: return "XARGB4444";
case SDL_PIXELFORMAT_RGBA4444: return "XRGBA4444";
case SDL_PIXELFORMAT_ABGR4444: return "XABGR4444";
case SDL_PIXELFORMAT_BGRA4444: return "XBGRA4444";
case SDL_PIXELFORMAT_ARGB1555: return "XARGB1555";
case SDL_PIXELFORMAT_RGBA5551: return "XRGBA5551";
case SDL_PIXELFORMAT_ABGR1555: return "XABGR1555";
case SDL_PIXELFORMAT_BGRA5551: return "XBGRA5551";
case SDL_PIXELFORMAT_RGB565: return "XRGB565";
case SDL_PIXELFORMAT_BGR565: return "XBGR565";
case SDL_PIXELFORMAT_RGB24: return "XRGB24";
case SDL_PIXELFORMAT_BGR24: return "XBGR24";
case SDL_PIXELFORMAT_XRGB8888: return "XXRGB8888";
case SDL_PIXELFORMAT_RGBX8888: return "XRGBX8888";
case SDL_PIXELFORMAT_XBGR8888: return "XXBGR8888";
case SDL_PIXELFORMAT_BGRX8888: return "XBGRX8888";
case SDL_PIXELFORMAT_ARGB8888: return "XARGB8888";
case SDL_PIXELFORMAT_RGBA8888: return "XRGBA8888";
case SDL_PIXELFORMAT_ABGR8888: return "XABGR8888";
case SDL_PIXELFORMAT_BGRA8888: return "XBGRA8888";
case SDL_PIXELFORMAT_XRGB2101010: return "XXRGB2101010";
case SDL_PIXELFORMAT_XBGR2101010: return "XXBGR2101010";
case SDL_PIXELFORMAT_ARGB2101010: return "XARGB2101010";
case SDL_PIXELFORMAT_ABGR2101010: return "XABGR2101010";
case SDL_PIXELFORMAT_RGB48: return "XRGB48";
case SDL_PIXELFORMAT_BGR48: return "XBGR48";
case SDL_PIXELFORMAT_RGBA64: return "XRGBA64";
case SDL_PIXELFORMAT_ARGB64: return "XARGB64";
case SDL_PIXELFORMAT_BGRA64: return "XBGRA64";
case SDL_PIXELFORMAT_ABGR64: return "XABGR64";
case SDL_PIXELFORMAT_RGB48_FLOAT: return "XRGB48_FLOAT";
case SDL_PIXELFORMAT_BGR48_FLOAT: return "XBGR48_FLOAT";
case SDL_PIXELFORMAT_RGBA64_FLOAT: return "XRGBA64_FLOAT";
case SDL_PIXELFORMAT_ARGB64_FLOAT: return "XARGB64_FLOAT";
case SDL_PIXELFORMAT_BGRA64_FLOAT: return "XBGRA64_FLOAT";
case SDL_PIXELFORMAT_ABGR64_FLOAT: return "XABGR64_FLOAT";
case SDL_PIXELFORMAT_RGB96_FLOAT: return "XRGB96_FLOAT";
case SDL_PIXELFORMAT_BGR96_FLOAT: return "XBGR96_FLOAT";
case SDL_PIXELFORMAT_RGBA128_FLOAT: return "XRGBA128_FLOAT";
case SDL_PIXELFORMAT_ARGB128_FLOAT: return "XARGB128_FLOAT";
case SDL_PIXELFORMAT_BGRA128_FLOAT: return "XBGRA128_FLOAT";
case SDL_PIXELFORMAT_ABGR128_FLOAT: return "XABGR128_FLOAT";
case SDL_PIXELFORMAT_YV12: return "XYV12";
case SDL_PIXELFORMAT_IYUV: return "XIYUV";
case SDL_PIXELFORMAT_YUY2: return "XYUY2";
case SDL_PIXELFORMAT_UYVY: return "XUYVY";
case SDL_PIXELFORMAT_YVYU: return "XYVYU";
case SDL_PIXELFORMAT_NV12: return "XNV12";
case SDL_PIXELFORMAT_NV21: return "XNV21";
case SDL_PIXELFORMAT_P010: return "XP010";
case SDL_PIXELFORMAT_EXTERNAL_OES: return "XEXTERNAL_OES";
}
return "UNKNOWN";
}
int main(int argc, char *argv[])
{
SDL_InitSubSystem(SDL_INIT_CAMERA);
int camera_count = 0;
SDL_CameraID * camera_id = SDL_GetCameras(&camera_count);
printf("count=%d id=%u %s\n",camera_count,camera_id,SDL_GetError());
SDL_CameraSpec ** camera_spec;
int camera_specs = 0;
camera_spec = SDL_GetCameraSupportedFormats(*camera_id,&camera_specs);
/*show supported formats and resolutions*/
for(int i=0; i != camera_specs;i++)
{
printf("camera=%-2i "
"w=%-4d h=%-4d "
"format=%-14s "
"frame_n=%-3d "
"frame_d=%d\n",
i,
camera_spec[i]->width,
camera_spec[i]->height,
pixel_format_name(camera_spec[i]->format),
camera_spec[i]->framerate_numerator,
camera_spec[i]->framerate_denominator);
}
/*init camera*/
SDL_Camera * cam = SDL_OpenCamera(*camera_id, camera_spec[0]);
#ifdef ENABLE_DELAY
SDL_Delay(5000);
#endif
printf("[1] %s\n",SDL_GetError());
SDL_Surface * frame;
Uint64 t=0;
SDL_Surface * s;
SDL_Event event;
while ( SDL_WaitEvent(&event) >= 0 )
{
if(event.type == SDL_EVENT_CAMERA_DEVICE_APPROVED)
{
printf("DEVICE_APPROVED!\n");
break;
};
if(event.type == SDL_EVENT_CAMERA_DEVICE_DENIED)
{
printf("DEVICE_DENIED!\n");
return 0;
};
}
#ifdef ENABLE_FRAMEDROP
for(int i=0;i<7;i++)
{
frame = SDL_AcquireCameraFrame(cam, &t);
SDL_ReleaseCameraFrame(cam, frame);
}
#endif
/*take photo*/
frame = SDL_AcquireCameraFrame(cam, &t);
printf("[2] %lu %s\n",t,SDL_GetError());
/*convert photo*/
s = SDL_ConvertSurface(frame, SDL_PIXELFORMAT_RGB24);
/*save result*/
SDL_SaveBMP(s,"out.bmp");
printf("[4] %lu %s\n",t,SDL_GetError());
/*release memory*/
SDL_ReleaseCameraFrame(cam, frame);
printf("[4] %lu %s\n",t,SDL_GetError());
SDL_Quit();
return 0;
}
Результаты
- Ошибка Invalid surface
fedor@nixfed:~/drawshoot$ make test-1 run
cc main.c -ISDL3/include -LSDL3/build -lSDL3 -o app
LD_LIBRARY_PATH=SDL3/build ./app
count=1 id=845253408
camera=0 w=640 h=480 format=XYUY2 frame_n=30 frame_d=1
camera=1 w=640 h=480 format=XYUY2 frame_n=25 frame_d=1
camera=2 w=640 h=480 format=XYUY2 frame_n=20 frame_d=1
camera=3 w=352 h=288 format=XYUY2 frame_n=30 frame_d=1
camera=4 w=352 h=288 format=XYUY2 frame_n=25 frame_d=1
camera=5 w=352 h=288 format=XYUY2 frame_n=20 frame_d=1
camera=6 w=320 h=240 format=XYUY2 frame_n=30 frame_d=1
camera=7 w=320 h=240 format=XYUY2 frame_n=25 frame_d=1
camera=8 w=320 h=240 format=XYUY2 frame_n=20 frame_d=1
camera=9 w=176 h=144 format=XYUY2 frame_n=30 frame_d=1
camera=10 w=176 h=144 format=XYUY2 frame_n=25 frame_d=1
camera=11 w=176 h=144 format=XYUY2 frame_n=20 frame_d=1
camera=12 w=160 h=120 format=XYUY2 frame_n=30 frame_d=1
camera=13 w=160 h=120 format=XYUY2 frame_n=25 frame_d=1
camera=14 w=160 h=120 format=XYUY2 frame_n=20 frame_d=1
[1]
DEVICE_APPROVED!
[2] 0
[4] 0 Parameter 'surface' is invalid
[4] 0 Parameter 'surface' is invalid
fedor@nixfed:~/drawshoot$
- Чёрный снимок вместо нормального
fedor@nixfed:~/drawshoot$ make test-2 run
cc main.c -ISDL3/include -LSDL3/build -lSDL3 -o app -DENABLE_DELAY
LD_LIBRARY_PATH=SDL3/build ./app
count=1 id=3957504800
camera=0 w=640 h=480 format=XYUY2 frame_n=30 frame_d=1
camera=1 w=640 h=480 format=XYUY2 frame_n=25 frame_d=1
camera=2 w=640 h=480 format=XYUY2 frame_n=20 frame_d=1
camera=3 w=352 h=288 format=XYUY2 frame_n=30 frame_d=1
camera=4 w=352 h=288 format=XYUY2 frame_n=25 frame_d=1
camera=5 w=352 h=288 format=XYUY2 frame_n=20 frame_d=1
camera=6 w=320 h=240 format=XYUY2 frame_n=30 frame_d=1
camera=7 w=320 h=240 format=XYUY2 frame_n=25 frame_d=1
camera=8 w=320 h=240 format=XYUY2 frame_n=20 frame_d=1
camera=9 w=176 h=144 format=XYUY2 frame_n=30 frame_d=1
camera=10 w=176 h=144 format=XYUY2 frame_n=25 frame_d=1
camera=11 w=176 h=144 format=XYUY2 frame_n=20 frame_d=1
camera=12 w=160 h=120 format=XYUY2 frame_n=30 frame_d=1
camera=13 w=160 h=120 format=XYUY2 frame_n=25 frame_d=1
camera=14 w=160 h=120 format=XYUY2 frame_n=20 frame_d=1
[1]
DEVICE_APPROVED!
[2] 706952397
[4] 706952397
[4] 706952397
fedor@nixfed:~/drawshoot$
- Всё хорошо, ошибок нет, фотография с камеры нормальная
fedor@nixfed:~/drawshoot$ make test-3 run
cc main.c -ISDL3/include -LSDL3/build -lSDL3 -o app -DENABLE_DELAY -DENABLE_FRAMEDROP
LD_LIBRARY_PATH=SDL3/build ./app
count=1 id=3940756256
camera=0 w=640 h=480 format=XYUY2 frame_n=30 frame_d=1
camera=1 w=640 h=480 format=XYUY2 frame_n=25 frame_d=1
camera=2 w=640 h=480 format=XYUY2 frame_n=20 frame_d=1
camera=3 w=352 h=288 format=XYUY2 frame_n=30 frame_d=1
camera=4 w=352 h=288 format=XYUY2 frame_n=25 frame_d=1
camera=5 w=352 h=288 format=XYUY2 frame_n=20 frame_d=1
camera=6 w=320 h=240 format=XYUY2 frame_n=30 frame_d=1
camera=7 w=320 h=240 format=XYUY2 frame_n=25 frame_d=1
camera=8 w=320 h=240 format=XYUY2 frame_n=20 frame_d=1
camera=9 w=176 h=144 format=XYUY2 frame_n=30 frame_d=1
camera=10 w=176 h=144 format=XYUY2 frame_n=25 frame_d=1
camera=11 w=176 h=144 format=XYUY2 frame_n=20 frame_d=1
camera=12 w=160 h=120 format=XYUY2 frame_n=30 frame_d=1
camera=13 w=160 h=120 format=XYUY2 frame_n=25 frame_d=1
camera=14 w=160 h=120 format=XYUY2 frame_n=20 frame_d=1
[1]
DEVICE_APPROVED!
[2] 1329622684
[4] 1329622684
[4] 1329622684
fedor@nixfed:~/drawshoot$
Может быть кому пригодится, досвиданья ::)