aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2022-10-18 23:25:46 +0300
committerkartofen <mladenovnasko0@gmail.com>2022-10-18 23:25:46 +0300
commit145775818375bafcf191a7b4986e57a00b41ac68 (patch)
treeb539525328515401be6bc2a6c9fb17841b8a16d1
parent7e64d0c78e8a21f2ede7eab1303758391001c0dc (diff)
use glfw and some minor refactoring
-rw-r--r--README.md28
-rwxr-xr-xbuild.sh6
-rw-r--r--src/display.c81
-rw-r--r--src/display.h2
-rw-r--r--src/listener.c29
-rw-r--r--src/socket.c50
-rw-r--r--src/talker.c11
-rw-r--r--src/typedef.h13
8 files changed, 123 insertions, 97 deletions
diff --git a/README.md b/README.md
index f58bcd4..7bffea3 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/build.sh b/build.sh
index c7a7e88..cf18d8a 100755
--- a/build.sh
+++ b/build.sh
@@ -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