From 563e9fd3205d401413b70ab010a60e2c4078fcd3 Mon Sep 17 00:00:00 2001 From: Julian Rother <julianr@fsmpi.rwth-aachen.de> Date: Thu, 26 Jul 2018 03:31:38 +0200 Subject: [PATCH] Added complex_live_transcode --- Makefile | 4 +- complex_live_transcode.c | 94 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 complex_live_transcode.c diff --git a/Makefile b/Makefile index d572862..9c5766f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGETS = probe probe-raw remux thumbnail transcode publish_video simple_live_transcode live_forward +TARGETS = probe probe-raw remux thumbnail transcode publish_video simple_live_transcode live_forward complex_live_transcode CFLAGS = -I /usr/include/libxml2 LDFLAGS= -lcurl -lavcodec -lavformat -lavfilter -lswscale -lavutil -lxml2 @@ -20,6 +20,8 @@ publish_video: publish_video.c *.h util/*.c simple_live_transcode: simple_live_transcode.c *.h util/*.c +complex_live_transcode: complex_live_transcode.c *.h util/*.c + live_forward: live_forward.c *.h util/*.c clean: diff --git a/complex_live_transcode.c b/complex_live_transcode.c new file mode 100644 index 0000000..5c4ab9b --- /dev/null +++ b/complex_live_transcode.c @@ -0,0 +1,94 @@ +#include <poll.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "util.h" + +#define OUTPUT_FORMAT(bitrate) "-f", "flv", "-r", "25", "-c:v", "libx264", "-b:v", bitrate, "-bufsize", bitrate, "-preset", "veryfast", "-x264-params", "keyint=125:min-keyint=125:no-scenecut", "-c:a", "aac" + +static void copy_to_log(int fd) +{ + static char buf[1024]; + size_t len; + if ((len = read(fd, BL(buf))) > 0) + fwrite(buf, 1, len, logstream); +} + +int main(int argc, char *argv[]) +{ + int ret, canceled = 0, errpipe[2] = {-1, -1}; + char *src1, *src2, *src1fmt = "flv", *src2fmt = "flv", *dest, *logo_expr; + pid_t pid; + struct pollfd fds = {.fd = -1, .events = POLLIN}; + if (argc != 5) + return 1; + init_env(); + init_avlogbuf(); + jobid = atoi(argv[1]); + src1 = jlookup(argv[4], "src1"); + src2 = jlookup(argv[4], "src2"); + if (!jstr(jlookup(src1, "url"), 0)) + src1fmt = "lavfi"; + if (!jstr(jlookup(src2, "url"), 0)) + src2fmt = "lavfi"; + dest = jstr(jlookup(argv[4], "destbase"), "rtmp://127.0.0.1:999999/nourl"); + if (jint(jlookup(argv[4], "videoag_logo"), 1)) + logo_expr = "overlay=x=W-195:y=H-155"; + else + logo_expr = "overlay=x=W+1000:y=H+1000"; + + pipe(errpipe); + if (!(pid = fork())) + { + close(errpipe[0]); + dup2(errpipe[1], 2); close(errpipe[1]); + dup2(open("/dev/null", O_RDONLY|O_CLOEXEC), 0); + dup2(open("/dev/null", O_WRONLY|O_CLOEXEC), 1); + execlp("ffmpeg", "ffmpeg", "-nostats", + "-f", src1fmt, "-i", jstr(jlookup(src1, "url"), "smptehdbars[out0]; anullsrc[out1]"), + "-f", src2fmt, "-i", jstr(jlookup(src2, "url"), "smptehdbars[out0]; anullsrc[out1]"), + "-filter_complex", + mprintf("[0:a]%s[a1]; [1:a]%s[a2]; [a1][a2]amix,%s,asplit=3[lowa][mida][higha];" + "[0:v]%s[v1]; [1:v]%s[v2]; [v1][v2]%s,scale=1920:1080[tmp];" + "movie=%s/video-logo-150px-trans.png,scale=w=100:h=100[logo];" + "[tmp][logo]%s,split=3[lowtmp][midtmp][high];" + "[lowtmp]scale=640:360[low];" + "[midtmp]scale=1280:720[mid]", + jstr(jlookup(src1, "afilter"), "acopy"), + jstr(jlookup(src2, "afilter"), "acopy"), + jstr(jlookup(argv[4], "afilter"), "acopy"), + jstr(jlookup(src1, "vfilter"), "copy"), + jstr(jlookup(src2, "vfilter"), "copy"), + jstr(jlookup(argv[4], "vmix"), "streamselect=map=0"), + getenv(WORKER_RAW), logo_expr + ), + "-map", "[low]", "-map", "[lowa]", OUTPUT_FORMAT("512k"), mprintf("%s_low", dest), + "-map", "[mid]", "-map", "[mida]", OUTPUT_FORMAT("2024k"), mprintf("%s_mid", dest), + "-map", "[high]", "-map", "[higha]", OUTPUT_FORMAT("6024k"), mprintf("%s_high", dest), 0); + exit(1); + } + close(errpipe[1]); + fds.fd = errpipe[0]; + + while (1) + { + canceled = ping_job(jobid, "running", "{\"log\": \"%s\"}", jescape(get_avlogbuf())); + if (canceled == 1) + kill(pid, SIGINT); /* Stop ffmpeg */ + poll(&fds, 1, 15000); + if (fds.revents & POLLIN) + copy_to_log(fds.fd); + else if (fds.revents & (POLLERR|POLLHUP|POLLNVAL)) + break; + } + + waitpid(pid, &ret, 0); + if (canceled == 1 && (WEXITSTATUS(ret) == 255 || (WIFSIGNALED(ret) && WTERMSIG(ret) == SIGINT))) + ping_job(jobid, "finished", "{\"log\": \"%s\"}", jescape(get_avlogbuf())); + else if (WIFSIGNALED(ret)) + job_failed("Subprocesses was killed by signal %s (%i)", strsignal(WTERMSIG(ret)), WTERMSIG(ret)); + else + job_failed("Subprocesses terminated with exit status %i", WEXITSTATUS(ret)); + return 0; +} -- GitLab