aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2022-10-17 23:04:12 +0300
committerkartofen <mladenovnasko0@gmail.com>2022-10-17 23:04:12 +0300
commit7e64d0c78e8a21f2ede7eab1303758391001c0dc (patch)
treea01e44b12d66de3e4fbc5cf5ab20f439fc8d6fc8
parentb1b7c92aa96af5502f276819b628b05d54f4655c (diff)
many changes in progess
-rw-r--r--README.md27
-rwxr-xr-xbuild.sh11
-rw-r--r--src/audio.c11
-rw-r--r--src/camera.c18
-rw-r--r--src/camera.h16
-rw-r--r--src/display.c24
-rw-r--r--src/display.h2
-rw-r--r--src/listener.c56
-rw-r--r--src/socket.c25
-rw-r--r--src/talker.c22
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
diff --git a/build.sh b/build.sh
index 2958199..c7a7e88 100755
--- a/build.sh
+++ b/build.sh
@@ -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;
}