Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
RuiDGPires committed Jun 18, 2023
0 parents commit f4c5e7e
Show file tree
Hide file tree
Showing 14 changed files with 339 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "CCLArgs"]
path = CCLArgs
url = https://github.com/RuiDGPires/CCLArgs
1 change: 1 addition & 0 deletions CCLArgs
Submodule CCLArgs added at d08b78
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
C_FILES := $(wildcard src/*.c)
H_FILES := $(wildcard src/*.h) $(wildcard src/include/*.h)
TARGET := vis
CC := gcc

$(TARGET): $(C_FILES) $(H_FILES)
gcc $(C_FILES) -o $@

.PHONY: clean
clean:
rm $(TARGET)
Binary file added a.mp4
Binary file not shown.
7 changes: 7 additions & 0 deletions buildnrun.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

VIDEO_FILE=output.mp4

make
./vis ${VIDEO_FILE}
vlc ${VIDEO_FILE} >/dev/null 2>&1
60 changes: 60 additions & 0 deletions src/canvas.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <stdlib.h>
#include <unistd.h>
#include "canvas.h"
#include "err.h"

u32 point_dist_sqrd(point_t p1, point_t p2) {
i32 dx = (i32) (p1.x - p2.x), dy = (i32) (p1.y - p2.y);
return dx*dx + dy*dy;
}

canvas_t *canvas_create(u32 width, u32 height) {
u32 *buffer = (u32*) malloc(sizeof(u32) * width * height);
canvas_t *canvas = canvas_from_buffer(buffer, width, height);
canvas->is_static = FALSE;
return canvas;
}

canvas_t *canvas_from_buffer(u32 *buffer, u32 width, u32 height) {
canvas_t *canvas = (canvas_t *) malloc(sizeof(canvas_t));
canvas->width = width;
canvas->height = height;
canvas->buffer = buffer;
canvas->is_static = TRUE;
return canvas;
}

void canvas_destroy(canvas_t **canvas) {
if ((*canvas)->is_static == FALSE)
free((*canvas)->buffer);

free(*canvas);
*canvas = NULL;
}

void canvas_fill(canvas_t *canvas, color_t color) {
for (usize i = 0; i < canvas->width * canvas->height; i++) {
canvas->buffer[i] = color;
}
}

void canvas_dump(canvas_t *canvas, int fd) {
write(fd, canvas->buffer, sizeof(color_t)*canvas->width*canvas->height);
}

void canvas_draw_point(canvas_t *canvas, point_t point, color_t color) {
canvas->buffer[point.x + point.y*canvas->width] = color;
}

void canvas_draw_circle(canvas_t *canvas, point_t center, u32 radius, color_t color) {
ERR_ASSERT(center.x - radius >= 0 && center.x + radius < canvas->width && center.y - radius >= 0 && center.y + radius < canvas->height, "Invalid circle");
for (u32 x = center.x - radius; x < center.x + radius; x++){
for (u32 y = center.y - radius; y < center.y + radius; y++){
point_t p = (point_t) {.x = x, .y = y};

if (point_dist_sqrd(p, center) <= radius*radius) {
canvas_draw_point(canvas, p, color);
}
}
}
}
37 changes: 37 additions & 0 deletions src/canvas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef __CANVAS_H__
#define __CANVAS_H__

#include "defs.h"

typedef u32 color_t;

#define RGBA(r, g, b, a) ((((r)&0xFF)<<(8*0)) | (((g)&0xFF)<<(8*1)) | (((b)&0xFF)<<(8*2)) | (((a)&0xFF)<<(8*3)))

#define COLOR_RED RGBA(0xFF, 0x00, 0x00, 0xFF)
#define COLOR_GREEN RGBA(0x00, 0xFF, 0x00, 0xFF)
#define COLOR_BLUE RGBA(0x00, 0x00, 0xFF, 0xFF)
#define COLOR_BLACK RGBA(0x00, 0x00, 0x00, 0xFF)
#define COLOR_WHITE RGBA(0xFF, 0xFF, 0xFF, 0xFF)

typedef struct {
u32 width, height;
color_t *buffer;
u8 is_static;
} canvas_t;

typedef struct {
usize x, y;
} point_t;

u32 point_dist_sqrd(point_t, point_t);

canvas_t *canvas_create(u32, u32);
canvas_t *canvas_from_buffer(u32 *, u32, u32);
void canvas_destroy(canvas_t **);

void canvas_fill(canvas_t *, color_t);
void canvas_dump(canvas_t *, int);
void canvas_draw_point(canvas_t *, point_t, color_t);
void canvas_draw_circle(canvas_t *, point_t, u32, color_t);

#endif
23 changes: 23 additions & 0 deletions src/defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef __DEFS_H__
#define __DEFS_H__

#include <stddef.h>
#include <stdint.h>

#define TRUE 1
#define FALSE 0

#define STR2(v) #v
#define STR(v) STR2(v)

typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

typedef int32_t i32;
typedef int16_t i16;
typedef int8_t i8;

typedef size_t usize;

#endif
14 changes: 14 additions & 0 deletions src/err.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef __ERR_H__
#define __ERR_H__

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#define ERR(...) {fprintf(stderr, "ERR: " __VA_ARGS__); fprintf(stderr, "\n"); exit(1);}

#define ERR_ASSERT(cond, ...) {if (!(cond)) ERR(__VA_ARGS__)}
#define ERR_ASSERT_CLN(cond, cln, ...) {if (!(cond)) {{cln;} ERR(__VA_ARGS__)}}

#endif
51 changes: 51 additions & 0 deletions src/ffmpeg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <stdlib.h>
#include <unistd.h>
#include "ffmpeg.h"
#include "err.h"

#define PIPE_READ 0
#define PIPE_WRITE 1

#define MAX_CHARS_DIM 100
#define MAX_CHARS_FPS 4

int open_ffmpeg(const char *filename, u32 width, u32 height, u32 fps) {
int pipefd[2];
ERR_ASSERT(pipe(pipefd) >= 0, "Unable to open pipe");

int child = fork();

char dims_s[MAX_CHARS_DIM];
char fps_s[MAX_CHARS_FPS];
snprintf(dims_s, MAX_CHARS_DIM, "%ux%u", width, height);
snprintf(fps_s, MAX_CHARS_FPS, "%u", fps);

ERR_ASSERT(child >= 0, "Unable to fork");

if (child == 0) {
ERR_ASSERT(dup2(pipefd[PIPE_READ], STDIN_FILENO) >= 0, "Unable to reopen read pipe as stdin");
close(pipefd[PIPE_WRITE]);

ERR_ASSERT(execlp("ffmpeg",
"ffmpeg",
"-loglevel", "verbose",
"-y",
"-f", "rawvideo",
"-pix_fmt", "rgba",
"-s", dims_s,
"-r", fps_s,
"-an",
"-i", "-",
"-c:v", "libx264",

filename,
// ...
NULL
) >= 0, "Unable to open FFMPEG: %s", strerror(errno));
assert(0 && "Unreachable");
}

close(pipefd[PIPE_READ]);
return pipefd[PIPE_WRITE];
}

8 changes: 8 additions & 0 deletions src/ffmpeg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef __FFMPEG_H__
#define __FFMPEG_H__

#include "defs.h"

int open_ffmpeg(const char *, u32 width, u32 height, u32 fps);

#endif
46 changes: 46 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "../CCLArgs/cclargs.h"
#include "ffmpeg.h"
#include "defs.h"
#include "err.h"
#include "wav.h"
#include "canvas.h"

#define WIDTH 600
#define HEIGHT 400
#define FPS 30
#define DURATION 5

#define MAX_FILENAME 100

#define USAGE "vis <output_name>"
#define DEFAULT_NAME "a.mp4"

int main(ARGS) {
char *output_file = DEFAULT_NAME;

BEGIN_PARSE_ARGS("")
ARG_STRING(output_file, "-o")
END_PARSE_ARGS

color_t pixels[WIDTH*HEIGHT];
canvas_t *canvas = canvas_from_buffer(pixels, WIDTH, HEIGHT);

int outfd = open_ffmpeg(output_file, WIDTH, HEIGHT, FPS);

canvas_fill(canvas, COLOR_BLUE);
canvas_draw_circle(canvas, (point_t){.x = WIDTH/2, .y = HEIGHT/2}, HEIGHT/3, COLOR_RED);

for (usize i = 0; i < FPS * DURATION; i++) {
canvas_dump(canvas, outfd);
}

close(outfd);
canvas_destroy(&canvas);
wait(NULL);
printf("Operation completed\n");
return 0;
}
47 changes: 47 additions & 0 deletions src/wav.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <stdlib.h>

#include "wav.h"
#include "err.h"

#define BUFFER_SIZE 4096

// Function to read audio file and retrieve its contents
wav_t *wav_from_file(const char* filename) {
FILE* file = fopen(filename, "rb");
ERR_ASSERT(file != NULL, "Failed to open file");

wav_t *wav = (wav_t *) malloc(sizeof(wav_t));
wav_header_t header;

// Read the WAV file header
size_t headerSize = fread(&header, 1, sizeof(wav_header_t), file);

ERR_ASSERT_CLN(headerSize == sizeof(wav_header_t), fclose(file), "Invalid WAV File");

// Check if the file format is valid
ERR_ASSERT_CLN(header.chunkID[0] == 'R' && header.chunkID[1] == 'I' && header.chunkID[2] == 'F' && header.chunkID[3] == 'F' && header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E',
fclose(file), "Invalid WAV file format");

// Allocate memory to store audio data
u32 dataSize = header.subchunk2Size;

wav->header = header;
u8* buffer = (uint8_t*)malloc(sizeof(u8) * dataSize);

ERR_ASSERT_CLN(buffer != NULL, fclose(file), "Failed to allocate memory");
wav->buffer = buffer;

// Read the audio data into the buffer
usize bytesRead = fread(buffer, 1, dataSize, file);
fclose(file);

ERR_ASSERT_CLN(bytesRead == dataSize, free(buffer), "Error occurred while reading the audio data")

return wav;
}

void destroy_wav(wav_t **wav) {
free((*wav)->buffer);
free(*wav);
*wav = NULL;
}
31 changes: 31 additions & 0 deletions src/wav.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef __WAV_H__
#define __WAV_H__

#include "defs.h"

// WAV file header structure
typedef struct {
char chunkID[4];
u32 chunkSize;
char format[4];
char subchunk1ID[4];
u32 subchunk1Size;
u16 audioFormat;
u16 numChannels;
u32 sampleRate;
u32 byteRate;
u16 blockAlign;
u16 bitsPerSample;
char subchunk2ID[4];
u32 subchunk2Size;
} wav_header_t;

typedef struct {
wav_header_t header;
u8 *buffer;
} wav_t;

wav_t *wav_from_file(const char *);
void wav_destroy(wav_t **);

#endif

0 comments on commit f4c5e7e

Please sign in to comment.