Have the server back off when ffmpeg fails repeatedly.

main
Zed A. Shaw 2 months ago
parent 9dc2947c08
commit b0274b8254
  1. 2
      config.json
  2. 27
      main.cpp

@ -1,5 +1,5 @@
{ {
"listen_at": "rtmp://192.168.254.146/", "listen_at": "rtmp://192.168.254.147/",
"bitrate": "7M", "bitrate": "7M",
"send_to": "https://127.0.0.1:5001/" "send_to": "https://127.0.0.1:5001/"
} }

@ -1,13 +1,17 @@
#define FSM_DEBUG 1 #define FSM_DEBUG 1
#include <fmt/core.h> #include <fmt/core.h>
#include <fmt/chrono.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <fstream> #include <fstream>
#include <chrono>
#include <thread>
#include "dbc.hpp" #include "dbc.hpp"
#include "fsm.hpp" #include "fsm.hpp"
#define BUF_MAX 1024 * 10 #define BUF_MAX 1024 * 10
using namespace fmt; using namespace fmt;
using namespace nlohmann; using namespace nlohmann;
using namespace std::chrono_literals;
struct Config { struct Config {
json json_config; json json_config;
@ -30,7 +34,7 @@ struct Config {
}; };
FILE *run_ffmpeg(Config &config) { FILE *run_ffmpeg(Config &config) {
string ffmpeg_cmd = format("ffmpeg -listen 1 -i {} -bufsize 3000k -maxrate {} -flags +global_header -c:v libx264 -preset veryfast -tune zerolatency -g:v 60 -vb {} -c:a copy -f flv {}", string ffmpeg_cmd = format("ffmpeg -listen 1 -i {} -bufsize 3000k -maxrate {} -flags +global_header -c:v libx264 -preset veryfast -tune zerolatency -g:v 60 -vb {} -c:a copy -f flv {} 2> output.log",
config.listen_at, config.listen_at,
config.bitrate, config.bitrate,
config.bitrate, config.bitrate,
@ -38,7 +42,7 @@ FILE *run_ffmpeg(Config &config) {
println("RUNNING: {}", ffmpeg_cmd); println("RUNNING: {}", ffmpeg_cmd);
return popen(ffmpeg_cmd.c_str(), "r"); return popen(ffmpeg_cmd.c_str(), "re");
} }
@ -55,13 +59,14 @@ class Server : DeadSimpleFSM<ServerState, ServerEvent> {
FILE *handle = nullptr; FILE *handle = nullptr;
char buffer[BUF_MAX]; char buffer[BUF_MAX];
char *res = nullptr; char *res = nullptr;
std::chrono::milliseconds wait_time = 200ms;
public: public:
Server(Config &config) : config(config) {}; Server(Config &config) : config(config) {};
bool stopped() { bool stopped() {
return in_state(ServerState::STOP) || in_state(ServerState::ERROR); return in_state(ServerState::STOP);
} }
void event(ServerEvent ev) { void event(ServerEvent ev) {
@ -76,8 +81,10 @@ public:
void START(ServerEvent ev) { void START(ServerEvent ev) {
handle = run_ffmpeg(config); handle = run_ffmpeg(config);
if(handle == nullptr) { if(handle == nullptr) {
dbc::log("ERROR when launching ffmpeg");
state(ServerState::ERROR); state(ServerState::ERROR);
} else { } else {
wait_time = 200ms;
state(ServerState::READING); state(ServerState::READING);
} }
} }
@ -86,6 +93,7 @@ public:
res = fgets(buffer, BUF_MAX, handle); res = fgets(buffer, BUF_MAX, handle);
if(res == nullptr) { if(res == nullptr) {
dbc::log("STOP shutting down...");
state(ServerState::STOP); state(ServerState::STOP);
} else { } else {
state(ServerState::READING); state(ServerState::READING);
@ -95,6 +103,7 @@ public:
void STOP(ServerEvent ev) { void STOP(ServerEvent ev) {
int rc = pclose(handle); int rc = pclose(handle);
if(rc != 0) { if(rc != 0) {
dbc::log("ERROR when calling pclose on ffmpeg");
state(ServerState::ERROR); state(ServerState::ERROR);
} else { } else {
state(ServerState::STOP); state(ServerState::STOP);
@ -102,12 +111,18 @@ public:
} }
void ERROR(ServerEvent ev) { void ERROR(ServerEvent ev) {
state(ServerState::ERROR); println("Error in server, waiting {}...", wait_time);
wait_time *= 2;
std::this_thread::sleep_for(wait_time);
dbc::log("Attempting to run it again...");
state(ServerState::START);
} }
}; };
int main() { int main(int argc, char *argv[]) {
Config config("config.json"); dbc::check(argc == 2, "USAGE: distributary config.json");
println("Using config {}", argv[1]);
Config config(argv[1]);
Server server(config); Server server(config);
while(!server.stopped()) { while(!server.stopped()) {

Loading…
Cancel
Save