diff options
author | kartofen <mladenovnasko0@gmail.com> | 2022-10-18 23:25:46 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2022-10-18 23:25:46 +0300 |
commit | 145775818375bafcf191a7b4986e57a00b41ac68 (patch) | |
tree | b539525328515401be6bc2a6c9fb17841b8a16d1 | |
parent | 7e64d0c78e8a21f2ede7eab1303758391001c0dc (diff) |
use glfw and some minor refactoring
-rw-r--r-- | README.md | 28 | ||||
-rwxr-xr-x | build.sh | 6 | ||||
-rw-r--r-- | src/display.c | 81 | ||||
-rw-r--r-- | src/display.h | 2 | ||||
-rw-r--r-- | src/listener.c | 29 | ||||
-rw-r--r-- | src/socket.c | 50 | ||||
-rw-r--r-- | src/talker.c | 11 | ||||
-rw-r--r-- | src/typedef.h | 13 |
8 files changed, 123 insertions, 97 deletions
@@ -3,16 +3,14 @@ This is a simple application that uses various linux apis to send video and audio through udp datagram sockets -### Build +### Libraries and APIs -To build use `./build`, to clean binaries use `./build clean` -When build it create two binaries, `listener` and `talker` - -### Run +This project is written only on C, using the following techonologies: +1. V4L2 - video for linux api for getting images from the camera +2. Pulse Audio Simple API for playing and recording audio (will be changed to alsa soon) +3. GLFW with OpenGL for displaying the recieved image -The `listener` listens for connections and displays the video and plays the -audio. -The `talker` records audio and camera and sends it. +No other external libraires and things. ### Limitations @@ -23,5 +21,15 @@ The `talker` records audio and camera and sends it. ### TODO 1. Use alsa and not pulse audio simple api -2. Don't use glut, find a way to sync displaying and getting the video and audio data -3. MUST run at 30 fps +2. MUST run at 30 fps + +### Build + +To build use `./build`, to clean binaries use `./build clean` +When build it create two binaries, `listener` and `talker` + +### Run + +The `listener` listens for connections and displays the video and plays the +audio. +The `talker` records audio and camera and sends it. @@ -2,8 +2,8 @@ cd ${0%/*} # go to project root -FLAGS="-Wall -Wextra -g -pedantic -lpthread -D_GNU_SOURCE" -FGLUT="-lglut -lGLU -lGL" +FLAGS="-g -Wall -Wextra -pedantic -lpthread" +FGLFW="-lGL -lglfw" FV4L2="-lv4l2" FPASM="-lpulse -lpulse-simple" SRC="src" @@ -31,5 +31,5 @@ gcc -o $OBJ/display.o -c $SRC/display.c gcc -o $OBJ/camera.o -c $SRC/camera.c gcc -o $OBJ/audio.o -c $SRC/audio.c -gcc -o $BIN/listener $SRC/listener.c $OBJ/socket.o $OBJ/display.o $OBJ/audio.o $FLAGS $FPASM $FGLUT +gcc -o $BIN/listener $SRC/listener.c $OBJ/socket.o $OBJ/display.o $OBJ/audio.o $FLAGS $FPASM $FGLFW gcc -o $BIN/talker $SRC/talker.c $OBJ/socket.o $OBJ/camera.o $OBJ/audio.o $FLAGS $FPASM $FV4L2 diff --git a/src/display.c b/src/display.c index 6d4c55a..a09cc46 100644 --- a/src/display.c +++ b/src/display.c @@ -1,15 +1,24 @@ #include <stdio.h> -#include <unistd.h> #include <string.h> -#include <GL/glut.h> -#include "display.h" +#include <GLFW/glfw3.h> #include "typedef.h" #define MAX(x, y) (((x) > (y)) ? (x) : (y)) -extern unsigned char *cam_data; +static void error_callback(int error, const char* description) +{ + err("display: %s\n", description); +} + +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, GLFW_TRUE); +} + +extern unsigned char cam_data[]; -unsigned char WIDTH = 1; +unsigned char WIDTH = 1; unsigned char HEIGHT = 1; GLubyte pixels[BUF_CAP] = {0}; @@ -22,30 +31,52 @@ void pixel(int x, int y, char *buf) pixels[p+2] = buf[b+2]; } -void render() +int display(void) { - WIDTH = MAX(cam_data[0], 1); - HEIGHT = MAX(cam_data[1], 1); + GLFWwindow* window; + glfwSetErrorCallback(error_callback); - for(int i = 0; i < HEIGHT; i++) - for(int j = 0; j < WIDTH; j++) - pixel(j, i, &(cam_data[2])); + if (!glfwInit()) { + return 1; + } - glClear(GL_COLOR_BUFFER_BIT); - glDrawPixels(WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - glutSwapBuffers(); - glutReshapeWindow(WIDTH, HEIGHT); - glutPostRedisplay(); -} + window = glfwCreateWindow(WIDTH, HEIGHT, "Client", NULL, NULL); + if (!window) { + glfwTerminate(); + return 1; + } -void display(int *argc, char **argv) -{ - glutInit(argc, argv); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); - glutInitWindowSize(69, 69); - glutCreateWindow(argv[0]); + glfwSetKeyCallback(window, key_callback); + glfwMakeContextCurrent(window); + glfwSwapInterval(1); + + + unsigned char *copy_cam_data; + while (!glfwWindowShouldClose(window)) + { + // memcpy(copy_cam_data, cam_data, BUF_CAP); + copy_cam_data = cam_data; + + WIDTH = MAX(copy_cam_data[0], 1); + HEIGHT = MAX(copy_cam_data[1], 1); + glfwSetWindowSize(window, WIDTH, HEIGHT); + + for(int i = 0; i < HEIGHT; i++) + for(int j = 0; j < WIDTH; j++) + pixel(j, i, &(copy_cam_data[2])); + + glClear(GL_COLOR_BUFFER_BIT); + glDrawPixels(WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwDestroyWindow(window); + glfwTerminate(); - glutDisplayFunc(render); - glutMainLoop(); + return 0; } diff --git a/src/display.h b/src/display.h index f48998a..f4b57a4 100644 --- a/src/display.h +++ b/src/display.h @@ -1,6 +1,6 @@ #ifndef DISPLAY_H #define DISPLAY_H -void display(int *argc, char **argv); +int display(void); #endif diff --git a/src/listener.c b/src/listener.c index 135405c..141a3f3 100644 --- a/src/listener.c +++ b/src/listener.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <fcntl.h> #include <pthread.h> @@ -9,32 +10,38 @@ #include "audio.h" #include "typedef.h" -char *cam_data; +char cam_data[BUF_CAP]; void *display_thread(void *arg) { (void)arg; - int c = 1; - char *name = "./display"; - display(&c, &name); - pthread_exit(0); + int r = display(); + if(r == 0) + info("display: closed\n"); + else + err("display: failed\n"); + exit(r); + // pthread_exit(0); } void on_recv(char *buf, int numbytes) { - cam_data = &(buf[REC_CAP]); - usleep(100000); - // audio_play(buf); + memcpy(cam_data, &(buf[REC_CAP]), BUF_CAP-REC_CAP); + audio_play(buf); } int main(void) { - // char empty[1024] = {0}; - // cam_data = empty; + memset(cam_data, 0, BUF_CAP); pthread_t tid; pthread_create(&tid, NULL, display_thread, NULL); - return listener("4950", &on_recv); + if(listener("4950", &on_recv) != 0) { + err("listener: failed"); + return 1; + } + + return 0; } diff --git a/src/socket.c b/src/socket.c index 838df53..2ce4900 100644 --- a/src/socket.c +++ b/src/socket.c @@ -5,8 +5,6 @@ #include <string.h> #include <arpa/inet.h> #include <netdb.h> -#include <signal.h> -#include <wait.h> #include <time.h> #include "socket.h" @@ -23,16 +21,6 @@ void *get_in_addr(struct sockaddr *sa) return &(((struct sockaddr_in6*)sa)->sin6_addr); } -void sigchld_handler(int s) -{ - // waitpid() might overwrite errno, so we save and restore it: - int saved_errno = errno; - - while(waitpid(-1, NULL, WNOHANG) > 0); - - errno = saved_errno; -} - int listener(char *port, void (*on_recv)(char *, int)) { int sockfd; @@ -46,7 +34,7 @@ int listener(char *port, void (*on_recv)(char *, int)) int rv; if((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + err("getaddrinfo: %s\n", gai_strerror(rv)); return 1; } @@ -69,8 +57,8 @@ int listener(char *port, void (*on_recv)(char *, int)) } if(p == NULL) { - fprintf(stderr, "listener: failed to bind socket\n"); - return 2; + err("listener: failed to bind socket\n"); + return 1; } freeaddrinfo(servinfo); @@ -81,17 +69,8 @@ int listener(char *port, void (*on_recv)(char *, int)) { if(now < time(NULL)) { now = time(NULL); - printf("FPS: %d\n", i); + info("FPS: %d\n", i); i = 0; - - // struct sigaction sa; - // sa.sa_handler = sigchld_handler; // reap all dead processes - // sigemptyset(&sa.sa_mask); - // sa.sa_flags = SA_RESTART; - // if (sigaction(SIGCHLD, &sa, NULL) == -1) { - // perror("sigaction"); - // return 1; - // } } char buf[BUF_CAP] = {0}; @@ -107,20 +86,13 @@ int listener(char *port, void (*on_recv)(char *, int)) #ifdef LOG_INFO_STDOUT char s[INET6_ADDRSTRLEN]; - printf("listener: got packet from %s, %d bytes long\n", + info("listener: got packet from %s, %d bytes long\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof(s)), numbytes); #endif - // #include <stdlib.h> - - // pid_t p = fork(); - // if(p < -1) { return 69; } - // else if(p == 0) { - on_recv(buf, numbytes); - // exit(0); - // } + on_recv(buf, numbytes); i++; } @@ -139,7 +111,7 @@ int talker(char *port, char *address, void (*on_send)(char *, int *)) int rv; if((rv = getaddrinfo(address, port, &hints, &servinfo)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + err("getaddrinfo: %s\n", gai_strerror(rv)); return 1; } @@ -156,8 +128,8 @@ int talker(char *port, char *address, void (*on_send)(char *, int *)) } if(p == NULL) { - fprintf(stderr, "talker: failed to create socket\n"); - return 2; + err("talker: failed to create socket\n"); + return 1; } int i = 0; @@ -166,7 +138,7 @@ int talker(char *port, char *address, void (*on_send)(char *, int *)) { if(now < time(NULL)) { now = time(NULL); - printf("FPS %d\n", i); + info("FPS %d\n", i); i = 0; } @@ -181,7 +153,7 @@ int talker(char *port, char *address, void (*on_send)(char *, int *)) return 1; } #ifdef LOG_INFO_STDOUT - printf("talker: sent %d bytes to %s\n", numbytes, address); + info("talker: sent %d bytes to %s\n", numbytes, address); #endif i++; diff --git a/src/talker.c b/src/talker.c index 0ba2994..c481570 100644 --- a/src/talker.c +++ b/src/talker.c @@ -31,21 +31,18 @@ void on_send(char *buf, int *bytes) int main(void) { - int ret = 1; - camera_params params = {0}; - params.device = "/dev/video0"; + params.device = CAM; params.x_res = 160; params.y_res = 120; camera_init(&cam_handle, params); if(talker("4950", "localhost", &on_send) != 0) { - goto finish; + err("talker: failed\n"); + return 1; } - ret = 0; -finish: camera_deinit(&cam_handle); - return ret; + return 0; } diff --git a/src/typedef.h b/src/typedef.h index a875116..c585f7a 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -1,7 +1,18 @@ #ifndef TYPEDEF_H #define TYPEDEF_H -#define BUF_CAP 65536 +#include <stdio.h> +#define __str__(x) #x +#define stringize(x) __str__(x) + +#define __RED__ "\033[0;31m" +#define __GREEN__ "\033[0;32m" +#define __RESET__ "\033[0m" + +#define info(...) fprintf(stdout, __GREEN__"[INFO]"__RESET__" "__FILE__":"stringize(__LINE__)": "__VA_ARGS__) +#define err(...) fprintf(stderr, __RED__"[ERR]"__RESET__" "__FILE__":"stringize(__LINE__)": "__VA_ARGS__) + +#define BUF_CAP 65536 // max datagram size #define REC_CAP 5880 // 30th of a second of audio #endif |