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.
116 lines
2.4 KiB
116 lines
2.4 KiB
#define FSM_DEBUG 1
|
|
#include <fmt/core.h>
|
|
#include <nlohmann/json.hpp>
|
|
#include <fstream>
|
|
#include "dbc.hpp"
|
|
#include "fsm.hpp"
|
|
|
|
#define BUF_MAX 1024 * 10
|
|
using namespace fmt;
|
|
using namespace nlohmann;
|
|
|
|
struct Config {
|
|
json json_config;
|
|
string listen_at = "";
|
|
string bitrate = "";
|
|
string send_to = "";
|
|
|
|
Config(const string json_file) {
|
|
load(json_file);
|
|
}
|
|
|
|
void load(const string file_name) {
|
|
std::ifstream infile(file_name);
|
|
json_config = json::parse(infile);
|
|
|
|
listen_at = json_config["listen_at"].template get<string>();
|
|
bitrate = json_config["bitrate"].template get<string>();
|
|
send_to = json_config["send_to"].template get<string>();
|
|
}
|
|
};
|
|
|
|
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 {}",
|
|
config.listen_at,
|
|
config.bitrate,
|
|
config.bitrate,
|
|
config.send_to);
|
|
|
|
println("RUNNING: {}", ffmpeg_cmd);
|
|
|
|
return popen(ffmpeg_cmd.c_str(), "r");
|
|
}
|
|
|
|
|
|
enum class ServerState {
|
|
START, READING, STOP, ERROR
|
|
};
|
|
|
|
enum class ServerEvent {
|
|
GO
|
|
};
|
|
|
|
class Server : DeadSimpleFSM<ServerState, ServerEvent> {
|
|
Config &config;
|
|
FILE *handle = nullptr;
|
|
char buffer[BUF_MAX];
|
|
char *res = nullptr;
|
|
|
|
public:
|
|
|
|
Server(Config &config) : config(config) {};
|
|
|
|
bool stopped() {
|
|
return in_state(ServerState::STOP) || in_state(ServerState::ERROR);
|
|
}
|
|
|
|
void 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 START(ServerEvent ev) {
|
|
handle = run_ffmpeg(config);
|
|
if(handle == nullptr) {
|
|
state(ServerState::ERROR);
|
|
} else {
|
|
state(ServerState::READING);
|
|
}
|
|
}
|
|
|
|
void READING(ServerEvent ev) {
|
|
res = fgets(buffer, BUF_MAX, handle);
|
|
|
|
if(res == nullptr) {
|
|
state(ServerState::STOP);
|
|
} else {
|
|
state(ServerState::READING);
|
|
}
|
|
}
|
|
|
|
void STOP(ServerEvent ev) {
|
|
int rc = pclose(handle);
|
|
if(rc != 0) {
|
|
state(ServerState::ERROR);
|
|
} else {
|
|
state(ServerState::STOP);
|
|
}
|
|
}
|
|
|
|
void ERROR(ServerEvent ev) {
|
|
state(ServerState::ERROR);
|
|
}
|
|
};
|
|
|
|
int main() {
|
|
Config config("config.json");
|
|
Server server(config);
|
|
|
|
while(!server.stopped()) {
|
|
server.event(ServerEvent::GO);
|
|
}
|
|
}
|
|
|