diff options
author | kartofen <mladenovnasko0@gmail.com> | 2022-10-17 23:04:12 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2022-10-17 23:04:12 +0300 |
commit | 7e64d0c78e8a21f2ede7eab1303758391001c0dc (patch) | |
tree | a01e44b12d66de3e4fbc5cf5ab20f439fc8d6fc8 | |
parent | b1b7c92aa96af5502f276819b628b05d54f4655c (diff) |
many changes in progess
-rw-r--r-- | README.md | 27 | ||||
-rwxr-xr-x | build.sh | 11 | ||||
-rw-r--r-- | src/audio.c | 11 | ||||
-rw-r--r-- | src/camera.c | 18 | ||||
-rw-r--r-- | src/camera.h | 16 | ||||
-rw-r--r-- | src/display.c | 24 | ||||
-rw-r--r-- | src/display.h | 2 | ||||
-rw-r--r-- | src/listener.c | 56 | ||||
-rw-r--r-- | src/socket.c | 25 | ||||
-rw-r--r-- | src/talker.c | 22 |
10 files changed, 128 insertions, 84 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..f58bcd4 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +### Video call + +This is a simple application that uses various linux apis to send video and audio +through udp datagram sockets + +### 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. + +### Limitations + +1. 160x120 video resolution because of the limited size of sockets +2. Crappy audio, most likely because of pulse audio +3. Works only one linux, I don't plan porting it to windows. + +### 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 @@ -9,11 +9,6 @@ FPASM="-lpulse -lpulse-simple" SRC="src" OBJ="obj" BIN="bin" -RUN=0 - -function __run__ { - RUN=1 -} function __clean__ { rm -rf $BIN @@ -38,9 +33,3 @@ 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/talker $SRC/talker.c $OBJ/socket.o $OBJ/camera.o $OBJ/audio.o $FLAGS $FPASM $FV4L2 - -# if ! { [[ $RUN -eq 0 ]]; } 2> /dev/null -# then -# fi - -# bin/listener diff --git a/src/audio.c b/src/audio.c index f7a51a5..710c10c 100644 --- a/src/audio.c +++ b/src/audio.c @@ -32,6 +32,12 @@ int audio_play(char *buf) } } + if(pa_simple_flush(play, &error) < 0) + { + fprintf(stderr, __FILE__": pa_simple_flush() failed: %s\n", pa_strerror(error)); + goto finish; + } + if(pa_simple_write(play, buf, REC_CAP, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error)); goto finish; @@ -64,6 +70,11 @@ int audio_record(char *buf) } } + if(pa_simple_flush(rec, &error) < 0) { + fprintf(stderr, __FILE__": pa_simple_flush() failed: %s\n", pa_strerror(error)); + goto finish; + } + if (pa_simple_read(rec, buf, REC_CAP, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); goto finish; diff --git a/src/camera.c b/src/camera.c index 6842a12..8d74217 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,20 +1,20 @@ #include "camera.h" #include "common_v4l2.h" -CommonV4l2 common_v4l2; - -void camera_init(char *dev_name, unsigned int x_res, unsigned int y_res) +void camera_init(camera_handle *handle, camera_params params) { - CommonV4l2_init(&common_v4l2, dev_name, x_res, y_res); + handle->handle = malloc(sizeof(CommonV4l2)); + CommonV4l2_init(handle->handle, params.device, params.x_res, params.y_res); } -char *camera_get_image() +char *camera_get_image(camera_handle *handle) { - CommonV4l2_update_image(&common_v4l2); - return CommonV4l2_get_image(&common_v4l2); + CommonV4l2_update_image(handle->handle); + return CommonV4l2_get_image(handle->handle); } -void camera_deinit() +void camera_deinit(camera_handle *handle) { - CommonV4l2_deinit(&common_v4l2); + CommonV4l2_deinit(handle->handle); + free(handle->handle); } diff --git a/src/camera.h b/src/camera.h index aaf690c..bfc5394 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,10 +1,20 @@ #ifndef CAMERA_H #define CAMERA_H -void camera_init(char *dev_name, unsigned int x_res, unsigned int y_res); +typedef struct camera_handle { + void *handle; +} camera_handle; -char *camera_get_image(); +typedef struct camera_params { + char *device; + int x_res; + int y_res; +} camera_params; -void camera_deinit(); +void camera_init(camera_handle *handle, camera_params params); + +char *camera_get_image(camera_handle *handle); + +void camera_deinit(camera_handle *handle); #endif diff --git a/src/display.c b/src/display.c index 2fb1d78..6d4c55a 100644 --- a/src/display.c +++ b/src/display.c @@ -5,11 +5,13 @@ #include "display.h" #include "typedef.h" +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +extern unsigned char *cam_data; + unsigned char WIDTH = 1; unsigned char HEIGHT = 1; - GLubyte pixels[BUF_CAP] = {0}; -static int fd; void pixel(int x, int y, char *buf) { @@ -22,14 +24,12 @@ void pixel(int x, int y, char *buf) void render() { - read(fd, &WIDTH, sizeof(WIDTH)); - read(fd, &HEIGHT, sizeof(HEIGHT)); + WIDTH = MAX(cam_data[0], 1); + HEIGHT = MAX(cam_data[1], 1); - char buf[BUF_CAP] = {0}; - if(read(fd, buf, sizeof(buf)) != -1) - for(int i = 0; i < HEIGHT; i++) - for(int j = 0; j < WIDTH; j++) - pixel(j, i, buf); + for(int i = 0; i < HEIGHT; i++) + for(int j = 0; j < WIDTH; j++) + pixel(j, i, &(cam_data[2])); glClear(GL_COLOR_BUFFER_BIT); glDrawPixels(WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); @@ -39,17 +39,13 @@ void render() glutPostRedisplay(); } -void display(int *argc, char **argv, int readfd) +void display(int *argc, char **argv) { glutInit(argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(69, 69); glutCreateWindow(argv[0]); - fd = readfd; - glutDisplayFunc(render); glutMainLoop(); - - puts("DISPLAY EXIT"); } diff --git a/src/display.h b/src/display.h index 7e4f187..f48998a 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 readfd); +void display(int *argc, char **argv); #endif diff --git a/src/listener.c b/src/listener.c index 7e9a839..135405c 100644 --- a/src/listener.c +++ b/src/listener.c @@ -2,51 +2,39 @@ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> +#include <pthread.h> #include "socket.h" #include "display.h" #include "audio.h" #include "typedef.h" -static int fd; +char *cam_data; -void on_recv(char *buf, int numbytes) +void *display_thread(void *arg) { - // read and play audio - pid_t p = fork(); - if(p < 0) { - fputs("fork: failed", stderr); - exit(1); - } else if(p > 0) { - write(fd, &(buf[REC_CAP]), numbytes-REC_CAP); - } else { - audio_play(buf); - exit(0); - } + (void)arg; - // audio_play(buf); - // write(fd, &(buf[REC_CAP]), numbytes-REC_CAP); + int c = 1; + char *name = "./display"; + display(&c, &name); + pthread_exit(0); +} +void on_recv(char *buf, int numbytes) +{ + cam_data = &(buf[REC_CAP]); + usleep(100000); + // audio_play(buf); } -int main(int argc, char **argv) +int main(void) { - int pipefd[2]; - if(pipe2(pipefd, O_NONBLOCK) == -1) { - fputs("pipe: failed", stderr); - return 1; - } - - pid_t p = fork(); - if(p < 0) { - fputs("fork: failed", stderr); - return 1; - } else if(p > 0) { - close(pipefd[0]); - fd = pipefd[1]; - return listener("4950", &on_recv); - } else { - close(pipefd[1]); - display(&argc, argv, pipefd[0]); - } + // char empty[1024] = {0}; + // cam_data = empty; + + pthread_t tid; + pthread_create(&tid, NULL, display_thread, NULL); + + return listener("4950", &on_recv); } diff --git a/src/socket.c b/src/socket.c index f435812..838df53 100644 --- a/src/socket.c +++ b/src/socket.c @@ -84,14 +84,14 @@ int listener(char *port, void (*on_recv)(char *, int)) printf("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; - } + // 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}; @@ -113,7 +113,14 @@ int listener(char *port, void (*on_recv)(char *, int)) s, sizeof(s)), numbytes); #endif - on_recv(buf, numbytes); + // #include <stdlib.h> + + // pid_t p = fork(); + // if(p < -1) { return 69; } + // else if(p == 0) { + on_recv(buf, numbytes); + // exit(0); + // } i++; } diff --git a/src/talker.c b/src/talker.c index 027d0e6..0ba2994 100644 --- a/src/talker.c +++ b/src/talker.c @@ -13,6 +13,7 @@ #define X_RES 160 #define Y_RES 120 +camera_handle cam_handle; void on_send(char *buf, int *bytes) { @@ -24,12 +25,27 @@ void on_send(char *buf, int *bytes) *bytes = REC_CAP + 2 + image_sz; - memcpy(&(buf[REC_CAP+2]), camera_get_image(), image_sz); + memcpy(&(buf[REC_CAP+2]), camera_get_image(&cam_handle), image_sz); } int main(void) { - camera_init(CAM, X_RES, Y_RES); - return talker("4950", "localhost", &on_send); + int ret = 1; + + camera_params params = {0}; + params.device = "/dev/video0"; + params.x_res = 160; + params.y_res = 120; + + camera_init(&cam_handle, params); + + if(talker("4950", "localhost", &on_send) != 0) { + goto finish; + } + + ret = 0; +finish: + camera_deinit(&cam_handle); + return ret; } |