You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.0 KiB
84 lines
2.0 KiB
3 weeks ago
|
#include "server.hpp"
|
||
|
#include <nlohmann/json.hpp>
|
||
|
#include <fmt/core.h>
|
||
|
#include <fmt/chrono.h>
|
||
|
#include <thread>
|
||
|
#include "dbc.hpp"
|
||
|
|
||
|
using namespace fmt;
|
||
|
|
||
|
FILE *run_ffmpeg(Config &config) {
|
||
|
string ffmpeg_cmd = format("ffmpeg -listen 1 -i {} -bufsize 3000k",
|
||
|
config.listen_at);
|
||
|
|
||
|
for(auto &el : config.send_to) {
|
||
|
SendTo send_spec = el.second;
|
||
|
ffmpeg_cmd += format(" -maxrate {} -flags +global_header -c:v libx264 -preset veryfast -tune zerolatency -g:v 60 -vb {} -c:a copy -f flv {}",
|
||
|
send_spec.bitrate, send_spec.bitrate, send_spec.url);
|
||
|
}
|
||
|
|
||
|
println("RUNNING: {}", ffmpeg_cmd);
|
||
|
|
||
|
return popen(ffmpeg_cmd.c_str(), "re");
|
||
|
}
|
||
|
|
||
|
bool Server::stopped() {
|
||
|
return in_state(ServerState::STOP);
|
||
|
}
|
||
|
|
||
|
void Server::event(ServerEvent ev) {
|
||
|
switch(_state) {
|
||
|
FSM_STATE(ServerState, START, ev);
|
||
|
FSM_STATE(ServerState, READING, ev);
|
||
|
FSM_STATE(ServerState, STOP, ev);
|
||
|
FSM_STATE(ServerState, ERROR, ev);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Server::START(ServerEvent ev) {
|
||
|
handle = run_ffmpeg(config);
|
||
|
if(handle == nullptr) {
|
||
|
dbc::log("ERROR when launching ffmpeg");
|
||
|
state(ServerState::ERROR);
|
||
|
} else {
|
||
|
wait_time = 200ms;
|
||
|
fail_count = 0;
|
||
|
state(ServerState::READING);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Server::READING(ServerEvent ev) {
|
||
|
res = fgets(buffer, BUF_MAX, handle);
|
||
|
|
||
|
if(res == nullptr) {
|
||
|
dbc::log("STOP shutting down...");
|
||
|
state(ServerState::STOP);
|
||
|
} else {
|
||
|
state(ServerState::READING);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Server::STOP(ServerEvent ev) {
|
||
|
int rc = pclose(handle);
|
||
|
if(rc != 0) {
|
||
|
dbc::log("ERROR when calling pclose on ffmpeg");
|
||
|
state(ServerState::ERROR);
|
||
|
} else {
|
||
|
state(ServerState::STOP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Server::ERROR(ServerEvent ev) {
|
||
|
fail_count++;
|
||
|
if(fail_count < config.fail_max) {
|
||
|
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);
|
||
|
} else {
|
||
|
dbc::log("ffmpeg failed to many times, exiting.");
|
||
|
state(ServerState::STOP);
|
||
|
}
|
||
|
}
|