From d493d4643149e91a22088c2c245a74eaef9ed333 Mon Sep 17 00:00:00 2001 From: sechshelme Date: Sat, 5 Aug 2023 17:25:43 +0200 Subject: [PATCH] webcam --- .../Webcam-SDL2-master/Lazarus/project1.lpr | 81 +++++----- .../Lazarus/v4l2_driver.pas | 14 +- Webcam/Webcam-SDL2-master/src/main.c | 23 +-- Webcam/Webcam-SDL2-master/src/simple_cam | Bin 21920 -> 21920 bytes codeblocks/Texturen/main.c | 66 -------- codeblocks/webcam/main.cpp | 146 ++++++++++++++++++ codeblocks/webcam/test.cbp | 36 +++++ codeblocks/webcam/v4l2_driver.h | 31 ++++ 8 files changed, 274 insertions(+), 123 deletions(-) delete mode 100644 codeblocks/Texturen/main.c create mode 100644 codeblocks/webcam/main.cpp create mode 100644 codeblocks/webcam/test.cbp create mode 100644 codeblocks/webcam/v4l2_driver.h diff --git a/Webcam/Webcam-SDL2-master/Lazarus/project1.lpr b/Webcam/Webcam-SDL2-master/Lazarus/project1.lpr index daa3d25..4841918 100644 --- a/Webcam/Webcam-SDL2-master/Lazarus/project1.lpr +++ b/Webcam/Webcam-SDL2-master/Lazarus/project1.lpr @@ -11,39 +11,22 @@ const device = '/dev/video0'; - IMAGE_WIDTH = 640; - IMAGE_HEIGHT = 480; -type - TFramehandler = procedure(pframe: Pointer; len: cint); - - TStreamHandle = record - fd: cint; - framehandler: TFramehandler; - end; - var video_fildes: longint; - sH: TStreamHandle; sdlTexture: PSDL_Texture; sdlRenderer: PSDL_Renderer; sdlRect: TSDL_Rect; sdlScreen: PSDL_Window; + e: TSDL_Event; + quit: boolean = False; fds: TFDSet; tv: TTimeVal = (tv_sec: 1; tv_usec: 0); - buf:Tv4l2_buffer; - - procedure frame_handler(pframe: Pointer; len: cint); - begin - SDL_UpdateTexture(sdlTexture, @sdlRect, pframe, IMAGE_WIDTH * 2); - SDL_RenderClear(sdlRenderer); - SDL_RenderCopy(sdlRenderer, sdlTexture, nil, @sdlRect); - SDL_RenderPresent(sdlRenderer); - end; + buf: Tv4l2_buffer; begin video_fildes := v4l2_open(device); @@ -57,7 +40,7 @@ TStreamHandle = record Halt(1); end; - if v4l2_sfmt(video_fildes, 1448695129) = -1 then begin // ?????? + if v4l2_sfmt(video_fildes, V4L2_PIX_FMT_YUYV) = -1 then begin WriteLn('v4l2_sfmt'); Halt(1); end; @@ -67,7 +50,7 @@ TStreamHandle = record Halt(1); end; - if v4l2_sfmt(video_fildes, 30) = -1 then begin + if v4l2_sfps(video_fildes, 30) = -1 then begin WriteLn('v4l2_sfmt()'); Halt(1); end; @@ -82,12 +65,9 @@ TStreamHandle = record Halt(1); end; - sH.fd := video_fildes; - sH.framehandler := @frame_handler; - SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER); - sdlScreen := SDL_CreateWindow('webcam', SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); + sdlScreen := SDL_CreateWindow('webcam', SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, IMAGE_WIDTH, IMAGE_HEIGHT, SDL_WINDOW_SHOWN); if sdlScreen = nil then begin WriteLn('Kann SDL nicht öffnen'); end; @@ -97,15 +77,10 @@ TStreamHandle = record Write('Kann Renderer nicht öffnen'); end; - sdlTexture := SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_STREAMING, 640, 480); - - sdlRect.w := 640; - sdlRect.h := 480; - -// #define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) -// #define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer) -// #define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) + sdlTexture := SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_STREAMING, IMAGE_WIDTH, IMAGE_HEIGHT); + sdlRect.w := IMAGE_WIDTH; + sdlRect.h := IMAGE_HEIGHT; repeat fpFD_ZERO(fds); @@ -113,21 +88,41 @@ TStreamHandle = record fpSelect(video_fildes + 1, @fds, nil, nil, @tv); - buf._type:=V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory:=V4L2_MEMORY_MMAP; + buf._type := V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory := V4L2_MEMORY_MMAP; FpIOCtl(video_fildes, VIDIOC_DQBUF, @buf); - buf._type:=V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory:=V4L2_MEMORY_MMAP; + buf._type := V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory := V4L2_MEMORY_MMAP; FpIOCtl(video_fildes, VIDIOC_QBUF, @buf); - //////////////77 - - + while SDL_PollEvent(@e) <> 0 do begin + case e.type_ of + SDL_KEYDOWN: begin + case e.key.keysym.sym of + SDLK_ESCAPE: begin + quit := True; + end; + end; + end; + SDL_QUITEV: begin + quit := True; + end; + end; + end; + + SDL_UpdateTexture(sdlTexture, @sdlRect, v4l2_ubuffers[buf.index].start, IMAGE_WIDTH * 2); + // SDL_UpdateYUVTexture + SDL_RenderClear(sdlRenderer); + SDL_RenderCopy(sdlRenderer, sdlTexture, nil, @sdlRect); + SDL_RenderPresent(sdlRenderer); until quit; + v4l2_streamoff(video_fildes); + v4l2_munmap; + v4l2_close(video_fildes); + SDL_Quit(); - - WriteLn('io.'); + WriteLn('ende.'); end. diff --git a/Webcam/Webcam-SDL2-master/Lazarus/v4l2_driver.pas b/Webcam/Webcam-SDL2-master/Lazarus/v4l2_driver.pas index 126c7bc..5513280 100644 --- a/Webcam/Webcam-SDL2-master/Lazarus/v4l2_driver.pas +++ b/Webcam/Webcam-SDL2-master/Lazarus/v4l2_driver.pas @@ -20,6 +20,16 @@ interface IMAGE_HEIGHT: longint; cvar;external; // ---- von /usr/include/linux/videodev2.h +const + // #define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) + // #define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer) + // #define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) + + + VIDIOC_DQBUF = 3227014673; + VIDIOC_QBUF = 3227014671; + V4L2_PIX_FMT_YUYV = 1448695129; + const V4L2_BUF_TYPE_VIDEO_CAPTURE = 1; @@ -111,11 +121,9 @@ Tv4l2_ubuffer = record v4l2_ubuffers: Pv4l2_ubuffer; cvar;external; { functions } - (* Const before type ignored *) function v4l2_open(device: PChar): longint; cdecl; external; function v4l2_close(fd: longint): longint; cdecl; external; -(* Const before type ignored *) function v4l2_querycap(fd: longint; device: PChar): longint; cdecl; external; function v4l2_sfmt(fd: longint; pfmt: uint32): longint; cdecl; external; function v4l2_gfmt(fd: longint): longint; cdecl; external; @@ -124,9 +132,7 @@ function v4l2_munmap: longint; cdecl; external; function v4l2_sfps(fd: longint; fps: longint): longint; cdecl; external; function v4l2_streamon(fd: longint): longint; cdecl; external; function v4l2_streamoff(fd: longint): longint; cdecl; external; -//{$endif} implementation - end. diff --git a/Webcam/Webcam-SDL2-master/src/main.c b/Webcam/Webcam-SDL2-master/src/main.c index 4901e64..e3adcb0 100644 --- a/Webcam/Webcam-SDL2-master/src/main.c +++ b/Webcam/Webcam-SDL2-master/src/main.c @@ -19,12 +19,12 @@ SDL_Rect sdlRect; int video_fildes; -static void *v4l2_streaming() { +void v4l2_streaming() { // SDL2 begins memset(&sdlRect, 0, sizeof(sdlRect)); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) { printf("Could not initialize SDL - %s\n", SDL_GetError()); - return NULL; + exit(1); } sdlScreen = SDL_CreateWindow("Simple YUV Window", SDL_WINDOWPOS_UNDEFINED, @@ -32,26 +32,27 @@ static void *v4l2_streaming() { IMAGE_HEIGHT, SDL_WINDOW_SHOWN); if (!sdlScreen) { - fprintf(stderr, "SDL: could not create window - exiting:%s\n", - SDL_GetError()); - return NULL; + fprintf(stderr, "SDL: could not create window - exiting:%s\n", SDL_GetError()); + exit(1); } sdlRenderer = SDL_CreateRenderer( sdlScreen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (sdlRenderer == NULL) { fprintf(stderr, "SDL_CreateRenderer Error\n"); - return NULL; + exit(1); } - sdlTexture = - SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YUY2, - SDL_TEXTUREACCESS_STREAMING, IMAGE_WIDTH, IMAGE_HEIGHT); + + sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_STREAMING, IMAGE_WIDTH, IMAGE_HEIGHT); sdlRect.w = IMAGE_WIDTH; sdlRect.h = IMAGE_HEIGHT; fd_set fds; struct v4l2_buffer buf; +printf("VIDIOC_DQBUF: %lu\n", VIDIOC_DQBUF); +printf("VIDIOC_QBUF: %lu\n", VIDIOC_QBUF); + while (1) { FD_ZERO(&fds); FD_SET(video_fildes, &fds); @@ -92,7 +93,9 @@ int main(int argc, char const *argv[]) { goto exit_; } -printf("----- %d\n", V4L2_PIX_FMT_YUYV); +printf("V4L2_PIX_FMT_YUYV: %d\n", V4L2_PIX_FMT_YUYV); +printf("width : %d\n", IMAGE_WIDTH); +printf("height : %d\n", IMAGE_HEIGHT); // most of devices support YUYV422 packed. if (v4l2_sfmt(video_fildes, V4L2_PIX_FMT_YUYV) == -1) { diff --git a/Webcam/Webcam-SDL2-master/src/simple_cam b/Webcam/Webcam-SDL2-master/src/simple_cam index aa12c8f3c43ce1f0cf3bee2a60eae8db64b8de70..57f60b60cf87f8d26aac24fb362297544dde2457 100755 GIT binary patch delta 1701 zcmY*ZeN0pSmn?`5 z#nngS=Jhi%3duB?#AI1DgSp5Sn2q}b$29l>Q(!>KU=9ZuB-7)$@4c4!l6Qai+~4o~ z&bjx#wyTGB_0Y31ROd=2^5bGgny)(;twaX{PMS}RgIkp_g3PD6lblyHwEUA(%NqvJ`z`K)3E(Jgo~{OnNphwx8l^XlxOH<(NHc=;7h}=6z~t z;NgPVxvke&S#?SDeJlEfFA@n6eZgMt8S42Hpf@4HoxY!Y3prM3vC|9enB_tG5&O_m zNDr|eEE{pYDKjlSD<7Tw?-~H0Pw^iL`<~~5w%eQ51WJ*J;5eE~LK6!7@kEq_<2aLK zE8lhT@??}quZfZYiBqzN?QIUeVCeG&09i{bHoirkG@~T# zQj<&=&K~#|U@;+MwLQ$3=p>|8Y>t2S`M44iW5Uy3vVo7Sn)4ZNo|VIfaejHwE~ z-@6IQoh)Nxvv0~~R~6OEe=9ylRE?;r?@=}9R?c946(Cr$gehb$wtp2NRElNVTbGD; zK@wh5TnbRd&lX*3g^yJmAGgU=Y&usW0>Q8H9?sK~l2D|Wl;hXQP572tR80wLLf3BN z?}c~p-9P}c&%~W8Sk`1$I(Iww71!0sv)HA7Qi;d+Y+0Jo8P;LTpnKV;HuKYFZ00>~RHqWhvtfrRu@>1xd+7js71zRh8DxEBj~Pp?iXx1L O06h?=!Nbs3u>Syo6n&`x delta 1557 zcmYLJVN6?96n?km0R=kfsFseUrL1IAr&VcnQ>Oz&9~i}esOTn=skj6eP;ma3X%KXF zk0vvR%>wJEX6r20)Blk|rg?kHxwiI?cJ7MB7Jj%{ z{%=iNtk1DE(q(QnTW)xCJ&Rb-AJoM`mwvpNUt-b z3+@VPDJXGY^+{6r=||rGHd{G498V36D%(aCwfp;K&bca2(nP^V)pK0X8pcqTkxHOTx)2OL}MSiU2rl_oqzoOh>FIop> zs~nvLGd@DD!dru9b3|=;hQ4c@3lqB%mcv@*SX72Cwi!2lJXlv-_bizAbVfIP zZeG|7qvLTwi`!UCnlu#H<)m2k}>na;;u4L<<;Wnt|8ud{g`-k(f@`=zlHSwXAepPFFg*bJ4GzuW~1c6dVor>R#F4jT51otP3DW#7brC4U!u`~i|wY1 z0r!jbQO@@Zv+@-=ADGIlsitsNTDsW4pm@cBC!i@aBS~n?5155W@QdIV=Qw9Lcao1Y z@R1hpKq^f=q%bMs*;Jq69D>Azs~r%3ig+|nU@kRmc34g!Vv=1dphG2Voxci!lq)5E z_p}ttWtuK=IF}GHDNl+%mDtxYlWZvtT34FKTv}9+n#VSX$XSVVu0-!OMsICq6xGq8 zQpd`d4YpT|gr`fQnbIA}A5*F;+l?uv%gpkMxBX4`*1y&I=Bo{FY~RsH=as%lcSTb= t+e)n3XOX -#include - -// https://stackoverflow.com/questions/26698378/how-to-use-sdl-createtexture - -int main(int argc, char *argv[]) { - - GtkWidget *window; - GtkWidget *vbox; - - GtkWidget *menubar; - GtkWidget *fileMenu; - GtkWidget *fileMi; - GtkWidget *newMi; - GtkWidget *openMi; - GtkWidget *quitMi; - - GtkWidget *sep; - - GtkAccelGroup *accel_group = NULL; - - gtk_init(&argc, &argv); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); - gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); - gtk_window_set_title(GTK_WINDOW(window), "Images"); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - - menubar = gtk_menu_bar_new(); - fileMenu = gtk_menu_new(); - - accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); - - fileMi = gtk_menu_item_new_with_mnemonic("_File"); - newMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL); - openMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL); - sep = gtk_separator_menu_item_new(); - quitMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group); - - gtk_widget_add_accelerator(quitMi, "activate", accel_group, - GDK_x, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu); - gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), newMi); - gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), openMi); - gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep); - gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi); - gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi); - gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); - - g_signal_connect(G_OBJECT(window), "destroy", - G_CALLBACK(gtk_main_quit), NULL); - - g_signal_connect(G_OBJECT(quitMi), "activate", - G_CALLBACK(gtk_main_quit), NULL); - - gtk_widget_show_all(window); - - gtk_main(); - - return 0; -} diff --git a/codeblocks/webcam/main.cpp b/codeblocks/webcam/main.cpp new file mode 100644 index 0000000..55764b9 --- /dev/null +++ b/codeblocks/webcam/main.cpp @@ -0,0 +1,146 @@ +#include "v4l2_driver.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SAVE_EVERY_FRAME 0 + +pthread_t thread_stream; +SDL_Window *sdlScreen; +SDL_Renderer *sdlRenderer; +SDL_Texture *sdlTexture; +SDL_Rect sdlRect; + +int video_fildes; + +static void *v4l2_streaming() { + // SDL2 begins + memset(&sdlRect, 0, sizeof(sdlRect)); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) { + printf("Could not initialize SDL - %s\n", SDL_GetError()); + return NULL; + } + + sdlScreen = SDL_CreateWindow("Simple YUV Window", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, IMAGE_WIDTH, + IMAGE_HEIGHT, SDL_WINDOW_SHOWN); + + if (!sdlScreen) { + fprintf(stderr, "SDL: could not create window - exiting:%s\n", + SDL_GetError()); + return NULL; + } + + sdlRenderer = SDL_CreateRenderer( + sdlScreen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (sdlRenderer == NULL) { + fprintf(stderr, "SDL_CreateRenderer Error\n"); + return NULL; + } + sdlTexture = + SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YUY2, + SDL_TEXTUREACCESS_STREAMING, IMAGE_WIDTH, IMAGE_HEIGHT); + sdlRect.w = IMAGE_WIDTH; + sdlRect.h = IMAGE_HEIGHT; + + fd_set fds; + struct v4l2_buffer buf; + + while (1) { + FD_ZERO(&fds); + FD_SET(video_fildes, &fds); + struct timeval tv = {.tv_sec = 1, .tv_usec = 0}; + select(video_fildes + 1, &fds, NULL, NULL, &tv); + +// if (FD_ISSET(video_fildes, &fds)) { +// memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + ioctl(video_fildes, VIDIOC_DQBUF, &buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + ioctl(video_fildes, VIDIOC_QBUF, &buf); + + + SDL_UpdateTexture(sdlTexture, &sdlRect, v4l2_ubuffers[buf.index].start, IMAGE_WIDTH * 2); + // SDL_UpdateYUVTexture + SDL_RenderClear(sdlRenderer); + SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); + SDL_RenderPresent(sdlRenderer); +// } + } +} + +int main(int argc, char const *argv[]) { + const char *device = "/dev/video0"; + + video_fildes = v4l2_open(device); + if (video_fildes == -1) { + fprintf(stderr, "can't open %s\n", device); + exit(-1); + } + + if (v4l2_querycap(video_fildes, device) == -1) { + perror("v4l2_querycap"); +// goto exit_; + } + +printf("----- %d\n", V4L2_PIX_FMT_YUYV); + + // most of devices support YUYV422 packed. + if (v4l2_sfmt(video_fildes, V4L2_PIX_FMT_YUYV) == -1) { + perror("v4l2_sfmt"); + // goto exit_; + } + + if (v4l2_gfmt(video_fildes) == -1) { + perror("v4l2_gfmt"); +// goto exit_; + } + + if (v4l2_sfps(video_fildes, 30) == -1) { // no fatal error + perror("v4l2_sfps"); + } + + if (v4l2_mmap(video_fildes) == -1) { + perror("v4l2_mmap"); + // goto exit_; + } + + if (v4l2_streamon(video_fildes) == -1) { + perror("v4l2_streamon"); +// goto exit_; + } + + v4l2_streaming(); + + int quit = 0; + while (!quit) { + usleep(250); + } + + + if (v4l2_streamoff(video_fildes) == -1) { + perror("v4l2_streamoff"); +// goto exit_; + } + + if (v4l2_munmap() == -1) { + perror("v4l2_munmap"); +// goto exit_; + } + +//exit_: + if (v4l2_close(video_fildes) == -1) { + perror("v4l2_close"); + }; + SDL_Quit(); + return 0; +} diff --git a/codeblocks/webcam/test.cbp b/codeblocks/webcam/test.cbp new file mode 100644 index 0000000..a2d0978 --- /dev/null +++ b/codeblocks/webcam/test.cbp @@ -0,0 +1,36 @@ + + + + + + diff --git a/codeblocks/webcam/v4l2_driver.h b/codeblocks/webcam/v4l2_driver.h new file mode 100644 index 0000000..7e600e7 --- /dev/null +++ b/codeblocks/webcam/v4l2_driver.h @@ -0,0 +1,31 @@ +#ifndef _V4l2_DRIVER__ +#define _V4l2_DRIVER__ + +#include +#include + +#define BUF_NUM 4 + +extern int IMAGE_WIDTH; +extern int IMAGE_HEIGHT; + +struct v4l2_ubuffer { + void *start; + unsigned int length; +}; + +extern struct v4l2_ubuffer *v4l2_ubuffers; + +/* functions */ +extern int v4l2_open(const char *device); +extern int v4l2_close(int fd); +extern int v4l2_querycap(int fd, const char *device); +extern int v4l2_sfmt(int fd, uint32_t pfmt); +extern int v4l2_gfmt(int fd); +extern int v4l2_mmap(int fd); +extern int v4l2_munmap(); +extern int v4l2_sfps(int fd, int fps); +extern int v4l2_streamon(int fd); +extern int v4l2_streamoff(int fd); + +#endif