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