parent
2f7facc853
commit
9dc2947c08
@ -1,45 +1,116 @@ |
|||||||
|
#define FSM_DEBUG 1 |
||||||
#include <fmt/core.h> |
#include <fmt/core.h> |
||||||
#include <nlohmann/json.hpp> |
#include <nlohmann/json.hpp> |
||||||
#include <fstream> |
#include <fstream> |
||||||
#include "dbc.hpp" |
#include "dbc.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; |
||||||
|
|
||||||
FILE *run_ffmpeg(const string listen_at, const string bitrate, const string send_to) { |
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 {}", |
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 {}", |
||||||
listen_at, bitrate, bitrate, send_to); |
config.listen_at, |
||||||
|
config.bitrate, |
||||||
|
config.bitrate, |
||||||
|
config.send_to); |
||||||
|
|
||||||
println("RUNNING: {}", ffmpeg_cmd); |
println("RUNNING: {}", ffmpeg_cmd); |
||||||
|
|
||||||
FILE *handle = popen(ffmpeg_cmd.c_str(), "r"); |
return popen(ffmpeg_cmd.c_str(), "r"); |
||||||
dbc::check(handle != nullptr, "failed to start ffmpeg"); |
|
||||||
return handle; |
|
||||||
} |
} |
||||||
|
|
||||||
json load_config(const string file_name) { |
|
||||||
std::ifstream infile(file_name); |
|
||||||
return json::parse(infile); |
|
||||||
} |
|
||||||
|
|
||||||
int main() { |
enum class ServerState { |
||||||
|
START, READING, STOP, ERROR |
||||||
|
}; |
||||||
|
|
||||||
|
enum class ServerEvent { |
||||||
|
GO |
||||||
|
}; |
||||||
|
|
||||||
|
class Server : DeadSimpleFSM<ServerState, ServerEvent> { |
||||||
|
Config &config; |
||||||
FILE *handle = nullptr; |
FILE *handle = nullptr; |
||||||
char buffer[BUF_MAX]; |
char buffer[BUF_MAX]; |
||||||
char *res = nullptr; |
char *res = nullptr; |
||||||
json config = load_config("config.json"); |
|
||||||
|
|
||||||
const string listen_at = config["listen_at"].template get<string>(); |
public: |
||||||
const string bitrate = config["bitrate"].template get<string>(); |
|
||||||
const string send_to = config["send_to"].template get<string>(); |
|
||||||
|
|
||||||
handle = run_ffmpeg(listen_at, bitrate, send_to); |
Server(Config &config) : config(config) {}; |
||||||
|
|
||||||
do { |
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); |
res = fgets(buffer, BUF_MAX, handle); |
||||||
print("OUT: {}", res); |
|
||||||
} while(res != nullptr); |
|
||||||
|
|
||||||
|
if(res == nullptr) { |
||||||
|
state(ServerState::STOP); |
||||||
|
} else { |
||||||
|
state(ServerState::READING); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void STOP(ServerEvent ev) { |
||||||
int rc = pclose(handle); |
int rc = pclose(handle); |
||||||
dbc::check(rc == 0, "error closing ffmpeg"); |
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); |
||||||
|
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue