|
|
@@ -8,100 +8,82 @@
|
|
|
#include <sys/wait.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
-#define OLIVEC_IMPLEMENTATION
|
|
|
-#include "olive.c"
|
|
|
-
|
|
|
#define READ_END 0
|
|
|
#define WRITE_END 1
|
|
|
|
|
|
-#define WIDTH 800
|
|
|
-#define HEIGHT 600
|
|
|
-#define FPS 30
|
|
|
-#define STR2(x) #x
|
|
|
-#define STR(x) STR2(x)
|
|
|
-uint32_t pixels[WIDTH*HEIGHT];
|
|
|
-
|
|
|
-int main(void)
|
|
|
+int ffmpeg_start_rendering(size_t width, size_t height, size_t fps)
|
|
|
{
|
|
|
int pipefd[2];
|
|
|
|
|
|
if (pipe(pipefd) < 0) {
|
|
|
fprintf(stderr, "ERROR: could not create a pipe: %s\n", strerror(errno));
|
|
|
- return 1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
pid_t child = fork();
|
|
|
if (child < 0) {
|
|
|
fprintf(stderr, "ERROR: could not fork a child: %s\n", strerror(errno));
|
|
|
- return 1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
if (child == 0) {
|
|
|
if (dup2(pipefd[READ_END], STDIN_FILENO) < 0) {
|
|
|
fprintf(stderr, "ERROR: could not reopen read end of pipe as stdin: %s\n", strerror(errno));
|
|
|
- return 1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
close(pipefd[WRITE_END]);
|
|
|
-
|
|
|
+
|
|
|
+ char resolution[64];
|
|
|
+ snprintf(resolution, sizeof(resolution), "%zux%zu", width, height);
|
|
|
+ char framerate[64];
|
|
|
+ snprintf(framerate, sizeof(framerate), "%zu", fps);
|
|
|
+
|
|
|
int ret = execlp("ffmpeg",
|
|
|
"ffmpeg",
|
|
|
"-loglevel", "verbose",
|
|
|
"-y",
|
|
|
+
|
|
|
"-f", "rawvideo",
|
|
|
"-pix_fmt", "rgba",
|
|
|
- "-s", STR(WIDTH) "x" STR(HEIGHT),
|
|
|
- "-r", STR(FPS),
|
|
|
- "-an",
|
|
|
+ "-s", resolution,
|
|
|
+ "-r", framerate,
|
|
|
"-i", "-",
|
|
|
- "-c:v", "libx264",
|
|
|
|
|
|
+ "-c:v", "libx264",
|
|
|
+ "-vb", "2500k",
|
|
|
+ "-c:a", "aac",
|
|
|
+ "-ab", "200k",
|
|
|
+ "-pix_fmt", "yuv420p",
|
|
|
"output.mp4",
|
|
|
- // ...
|
|
|
+
|
|
|
NULL
|
|
|
);
|
|
|
if (ret < 0) {
|
|
|
fprintf(stderr, "ERROR: could not run ffmpeg as a child process: %s\n", strerror(errno));
|
|
|
- return 1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
assert(0 && "unreachable");
|
|
|
}
|
|
|
|
|
|
close(pipefd[READ_END]);
|
|
|
|
|
|
- Olivec_Canvas oc = olivec_canvas(pixels, WIDTH, HEIGHT, WIDTH);
|
|
|
-
|
|
|
- size_t duration = 10;
|
|
|
- float x = WIDTH/2;
|
|
|
- float y = HEIGHT/2;
|
|
|
- float r = HEIGHT/8;
|
|
|
- float dx = 200;
|
|
|
- float dy = 200;
|
|
|
- float dt = 1.0f/FPS;
|
|
|
- for (size_t i = 0; i < FPS*duration; ++i) {
|
|
|
- float nx = x + dx*dt;
|
|
|
- if (0 < nx - r && nx + r < WIDTH) {
|
|
|
- x = nx;
|
|
|
- } else {
|
|
|
- dx = -dx;
|
|
|
- }
|
|
|
-
|
|
|
- float ny = y + dy*dt;
|
|
|
- if (0 < ny - r && ny + r < HEIGHT) {
|
|
|
- y = ny;
|
|
|
- } else {
|
|
|
- dy = -dy;
|
|
|
- }
|
|
|
-
|
|
|
- olivec_fill(oc, 0xFF181818);
|
|
|
- olivec_circle(oc, x, y, r, 0xFF0000FF);
|
|
|
- write(pipefd[WRITE_END], pixels, sizeof(*pixels)*WIDTH*HEIGHT);
|
|
|
- }
|
|
|
-
|
|
|
- close(pipefd[WRITE_END]);
|
|
|
+ return pipefd[WRITE_END];
|
|
|
+}
|
|
|
|
|
|
+void ffmpeg_end_rendering(int pipe)
|
|
|
+{
|
|
|
+ close(pipe);
|
|
|
wait(NULL);
|
|
|
+}
|
|
|
|
|
|
- printf("Done rendering the video!\n");
|
|
|
+void ffmpeg_send_frame(int pipe, void *data, size_t width, size_t height)
|
|
|
+{
|
|
|
+ write(pipe, data, sizeof(uint32_t)*width*height);
|
|
|
+}
|
|
|
|
|
|
- return 0;
|
|
|
+void ffmpeg_send_frame_flipped(int pipe, void *data, size_t width, size_t height)
|
|
|
+{
|
|
|
+ for (size_t y = height; y > 0; --y) {
|
|
|
+ write(pipe, (uint32_t*)data + (y - 1)*width, sizeof(uint32_t)*width);
|
|
|
+ }
|
|
|
}
|