mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
parse ffmpeg params
This commit is contained in:
parent
ce15f4bce3
commit
80a81b1661
12 changed files with 704 additions and 18 deletions
|
@ -45,6 +45,7 @@ vhost all.transcode.vhost.com {
|
||||||
transcode {
|
transcode {
|
||||||
# whether the transcode enabled.
|
# whether the transcode enabled.
|
||||||
# if off, donot transcode.
|
# if off, donot transcode.
|
||||||
|
# default: off.
|
||||||
enabled on;
|
enabled on;
|
||||||
# the ffmpeg
|
# the ffmpeg
|
||||||
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
|
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
|
||||||
|
@ -53,6 +54,7 @@ vhost all.transcode.vhost.com {
|
||||||
# the transcode set name(ie. hd) is optional and not used.
|
# the transcode set name(ie. hd) is optional and not used.
|
||||||
engine super{
|
engine super{
|
||||||
# whether the engine is enabled
|
# whether the engine is enabled
|
||||||
|
# default: off.
|
||||||
enabled on;
|
enabled on;
|
||||||
# video encoder name
|
# video encoder name
|
||||||
vcodec libx264;
|
vcodec libx264;
|
||||||
|
|
|
@ -43,3 +43,20 @@ void srs_update_system_time_ms()
|
||||||
|
|
||||||
_srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache);
|
_srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string srs_replace(std::string str, std::string old_str, std::string new_str)
|
||||||
|
{
|
||||||
|
std::string ret = str;
|
||||||
|
|
||||||
|
if (old_str == new_str) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = ret.find(old_str, pos)) != std::string::npos) {
|
||||||
|
ret = ret.replace(pos, old_str.length(), new_str);
|
||||||
|
pos += new_str.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -91,4 +91,8 @@ extern void srs_update_system_time_ms();
|
||||||
// signal defines.
|
// signal defines.
|
||||||
#define SIGNAL_RELOAD SIGHUP
|
#define SIGNAL_RELOAD SIGHUP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
// replace utility
|
||||||
|
extern std::string srs_replace(std::string str, std::string old_str, std::string new_str);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -231,8 +231,7 @@ int SrsClient::check_vhost()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConfDirective* conf = NULL;
|
if (!config->get_vhost_enabled(req->vhost)) {
|
||||||
if ((conf = config->get_vhost_enabled(req->vhost)) != NULL && conf->arg0() != "on") {
|
|
||||||
ret = ERROR_RTMP_VHOST_NOT_FOUND;
|
ret = ERROR_RTMP_VHOST_NOT_FOUND;
|
||||||
srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret);
|
srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -344,7 +343,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle)
|
||||||
SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
|
SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
|
||||||
|
|
||||||
// notify the hls to prepare when publish start.
|
// notify the hls to prepare when publish start.
|
||||||
if ((ret = source->on_publish(req->vhost, req->app, req->stream)) != ERROR_SUCCESS) {
|
if ((ret = source->on_publish(req->vhost, req->port, req->app, req->stream)) != ERROR_SUCCESS) {
|
||||||
srs_error("hls on_publish failed. ret=%d", ret);
|
srs_error("hls on_publish failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -557,15 +557,24 @@ SrsConfDirective* SrsConfig::get_vhost(std::string vhost)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_vhost_enabled(std::string vhost)
|
bool SrsConfig::get_vhost_enabled(std::string vhost)
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = get_vhost(vhost);
|
SrsConfDirective* vhost_conf = get_vhost(vhost);
|
||||||
|
|
||||||
if (!conf) {
|
if (!vhost_conf) {
|
||||||
return NULL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf->get("enabled");
|
SrsConfDirective* conf = vhost_conf->get("enabled");
|
||||||
|
if (!conf) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->arg0() == "off") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)
|
SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)
|
||||||
|
@ -588,6 +597,300 @@ SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode)
|
||||||
|
{
|
||||||
|
if (!transcode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = transcode->get("enabled");
|
||||||
|
if (!conf || conf->arg0() != "on") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode)
|
||||||
|
{
|
||||||
|
if (!transcode) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = transcode->get("ffmpeg");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsConfig::get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines)
|
||||||
|
{
|
||||||
|
if (!transcode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)transcode->directives.size(); i++) {
|
||||||
|
SrsConfDirective* conf = transcode->directives[i];
|
||||||
|
|
||||||
|
if (conf->name == "engine") {
|
||||||
|
engines.push_back(conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::get_engine_enabled(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("enabled");
|
||||||
|
if (!conf || conf->arg0() != "on") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_vcodec(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vcodec");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_vbitrate(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vbitrate");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
double SrsConfig::get_engine_vfps(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vfps");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atof(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_vwidth(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vwidth");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_vheight(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vheight");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_vthreads(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vthreads");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vprofile");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vpreset");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_vparams(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("vparams");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string avparams;
|
||||||
|
for (int i = 0; i < (int)conf->directives.size(); i++) {
|
||||||
|
SrsConfDirective* p = conf->directives[i];
|
||||||
|
if (!p) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
avparams += p->name;
|
||||||
|
avparams += " ";
|
||||||
|
avparams += p->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
return avparams;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_acodec(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("acodec");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_abitrate(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("abitrate");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_asample_rate(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("asample_rate");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_engine_achannels(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("achannels");
|
||||||
|
if (!conf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_aparams(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("aparams");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string avparams;
|
||||||
|
for (int i = 0; i < (int)conf->directives.size(); i++) {
|
||||||
|
SrsConfDirective* p = conf->directives[i];
|
||||||
|
if (!p) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
avparams += p->name;
|
||||||
|
avparams += " ";
|
||||||
|
avparams += p->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
return avparams;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsConfig::get_engine_output(SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
if (!engine) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsConfDirective* conf = engine->get("output");
|
||||||
|
if (!conf) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
|
SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = get_vhost(vhost);
|
SrsConfDirective* conf = get_vhost(vhost);
|
||||||
|
@ -621,6 +924,21 @@ SrsConfDirective* SrsConfig::get_hls(std::string vhost)
|
||||||
return conf->get("hls");
|
return conf->get("hls");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::get_hls_enabled(std::string vhost)
|
||||||
|
{
|
||||||
|
SrsConfDirective* hls = get_hls(vhost);
|
||||||
|
|
||||||
|
if (!hls) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hls->arg0() == "off") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)
|
SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = get_vhost(vhost);
|
SrsConfDirective* conf = get_vhost(vhost);
|
||||||
|
|
|
@ -112,12 +112,33 @@ public:
|
||||||
virtual void unsubscribe(SrsReloadHandler* handler);
|
virtual void unsubscribe(SrsReloadHandler* handler);
|
||||||
public:
|
public:
|
||||||
virtual int parse_options(int argc, char** argv);
|
virtual int parse_options(int argc, char** argv);
|
||||||
|
public:
|
||||||
virtual SrsConfDirective* get_vhost(std::string vhost);
|
virtual SrsConfDirective* get_vhost(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_enabled(std::string vhost);
|
virtual bool get_vhost_enabled(std::string vhost);
|
||||||
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
||||||
|
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
|
||||||
|
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
|
||||||
|
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
|
||||||
|
virtual bool get_engine_enabled(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_vbitrate(SrsConfDirective* engine);
|
||||||
|
virtual double get_engine_vfps(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_vwidth(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_vheight(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_vthreads(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_vprofile(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_vpreset(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_vparams(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_acodec(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_abitrate(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_asample_rate(SrsConfDirective* engine);
|
||||||
|
virtual int get_engine_achannels(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_aparams(SrsConfDirective* engine);
|
||||||
|
virtual std::string get_engine_output(SrsConfDirective* engine);
|
||||||
virtual SrsConfDirective* get_gop_cache(std::string vhost);
|
virtual SrsConfDirective* get_gop_cache(std::string vhost);
|
||||||
virtual SrsConfDirective* get_forward(std::string vhost);
|
virtual SrsConfDirective* get_forward(std::string vhost);
|
||||||
virtual SrsConfDirective* get_hls(std::string vhost);
|
virtual SrsConfDirective* get_hls(std::string vhost);
|
||||||
|
virtual bool get_hls_enabled(std::string vhost);
|
||||||
virtual SrsConfDirective* get_hls_path(std::string vhost);
|
virtual SrsConfDirective* get_hls_path(std::string vhost);
|
||||||
virtual SrsConfDirective* get_hls_fragment(std::string vhost);
|
virtual SrsConfDirective* get_hls_fragment(std::string vhost);
|
||||||
virtual SrsConfDirective* get_hls_window(std::string vhost);
|
virtual SrsConfDirective* get_hls_window(std::string vhost);
|
||||||
|
|
|
@ -29,6 +29,154 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#define SRS_ENCODER_SLEEP_MS 2000
|
#define SRS_ENCODER_SLEEP_MS 2000
|
||||||
|
|
||||||
|
#define SRS_ENCODER_VCODEC "libx264"
|
||||||
|
#define SRS_ENCODER_ACODEC "libaacplus"
|
||||||
|
|
||||||
|
SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
|
||||||
|
{
|
||||||
|
started = false;
|
||||||
|
ffmpeg = ffmpeg_bin;
|
||||||
|
|
||||||
|
vbitrate = 0;
|
||||||
|
vfps = 0;
|
||||||
|
vwidth = 0;
|
||||||
|
vheight = 0;
|
||||||
|
vthreads = 0;
|
||||||
|
abitrate = 0;
|
||||||
|
asample_rate = 0;
|
||||||
|
achannels = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsFFMPEG::~SrsFFMPEG()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFFMPEG::initialize(std::string vhost, std::string port, std::string app, std::string stream, SrsConfDirective* engine)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
vcodec = config->get_engine_vcodec(engine);
|
||||||
|
vbitrate = config->get_engine_vbitrate(engine);
|
||||||
|
vfps = config->get_engine_vfps(engine);
|
||||||
|
vwidth = config->get_engine_vwidth(engine);
|
||||||
|
vheight = config->get_engine_vheight(engine);
|
||||||
|
vthreads = config->get_engine_vthreads(engine);
|
||||||
|
vprofile = config->get_engine_vprofile(engine);
|
||||||
|
vpreset = config->get_engine_vpreset(engine);
|
||||||
|
vparams = config->get_engine_vparams(engine);
|
||||||
|
acodec = config->get_engine_acodec(engine);
|
||||||
|
abitrate = config->get_engine_abitrate(engine);
|
||||||
|
asample_rate = config->get_engine_asample_rate(engine);
|
||||||
|
achannels = config->get_engine_achannels(engine);
|
||||||
|
aparams = config->get_engine_aparams(engine);
|
||||||
|
output = config->get_engine_output(engine);
|
||||||
|
|
||||||
|
// ensure the size is even.
|
||||||
|
vwidth -= vwidth % 2;
|
||||||
|
vheight -= vheight % 2;
|
||||||
|
|
||||||
|
if (vhost == RTMP_VHOST_DEFAULT) {
|
||||||
|
output = srs_replace(output, "[vhost]", "127.0.0.1");
|
||||||
|
} else {
|
||||||
|
output = srs_replace(output, "[vhost]", vhost);
|
||||||
|
}
|
||||||
|
output = srs_replace(output, "[port]", port);
|
||||||
|
output = srs_replace(output, "[app]", app);
|
||||||
|
output = srs_replace(output, "[stream]", stream);
|
||||||
|
|
||||||
|
if (vcodec != SRS_ENCODER_VCODEC) {
|
||||||
|
ret = ERROR_ENCODER_VCODEC;
|
||||||
|
srs_error("invalid vcodec, must be %s, actual %s, ret=%d",
|
||||||
|
SRS_ENCODER_VCODEC, vcodec.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vbitrate <= 0) {
|
||||||
|
ret = ERROR_ENCODER_VBITRATE;
|
||||||
|
srs_error("invalid vbitrate: %d, ret=%d", vbitrate, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vfps <= 0) {
|
||||||
|
ret = ERROR_ENCODER_VFPS;
|
||||||
|
srs_error("invalid vfps: %.2f, ret=%d", vfps, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vwidth <= 0) {
|
||||||
|
ret = ERROR_ENCODER_VWIDTH;
|
||||||
|
srs_error("invalid vwidth: %d, ret=%d", vwidth, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vheight <= 0) {
|
||||||
|
ret = ERROR_ENCODER_VHEIGHT;
|
||||||
|
srs_error("invalid vheight: %d, ret=%d", vheight, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vthreads < 0) {
|
||||||
|
ret = ERROR_ENCODER_VTHREADS;
|
||||||
|
srs_error("invalid vthreads: %d, ret=%d", vthreads, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vprofile.empty()) {
|
||||||
|
ret = ERROR_ENCODER_VPROFILE;
|
||||||
|
srs_error("invalid vprofile: %s, ret=%d", vprofile.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (vpreset.empty()) {
|
||||||
|
ret = ERROR_ENCODER_VPRESET;
|
||||||
|
srs_error("invalid vpreset: %s, ret=%d", vpreset.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (acodec != SRS_ENCODER_ACODEC) {
|
||||||
|
ret = ERROR_ENCODER_ACODEC;
|
||||||
|
srs_error("invalid acodec, must be %s, actual %s, ret=%d",
|
||||||
|
SRS_ENCODER_ACODEC, acodec.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (abitrate <= 0) {
|
||||||
|
ret = ERROR_ENCODER_ABITRATE;
|
||||||
|
srs_error("invalid abitrate: %d, ret=%d",
|
||||||
|
abitrate, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (asample_rate <= 0) {
|
||||||
|
ret = ERROR_ENCODER_ASAMPLE_RATE;
|
||||||
|
srs_error("invalid sample rate: %d, ret=%d",
|
||||||
|
asample_rate, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (achannels != 1 && achannels != 2) {
|
||||||
|
ret = ERROR_ENCODER_ACHANNELS;
|
||||||
|
srs_error("invalid achannels, must be 1 or 2, actual %d, ret=%d",
|
||||||
|
achannels, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (output.empty()) {
|
||||||
|
ret = ERROR_ENCODER_OUTPUT;
|
||||||
|
srs_error("invalid empty output, ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFFMPEG::start()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (started) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsFFMPEG::stop()
|
||||||
|
{
|
||||||
|
if (!started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SrsEncoder::SrsEncoder()
|
SrsEncoder::SrsEncoder()
|
||||||
{
|
{
|
||||||
tid = NULL;
|
tid = NULL;
|
||||||
|
@ -40,16 +188,50 @@ SrsEncoder::~SrsEncoder()
|
||||||
on_unpublish();
|
on_unpublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsEncoder::on_publish(std::string _vhost, std::string _app, std::string _stream)
|
int SrsEncoder::on_publish(std::string _vhost, std::string _port, std::string _app, std::string _stream)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
vhost = _vhost;
|
vhost = _vhost;
|
||||||
|
port = _port;
|
||||||
app = _app;
|
app = _app;
|
||||||
stream = _stream;
|
stream = _stream;
|
||||||
|
|
||||||
|
// parse all transcode engines.
|
||||||
|
SrsConfDirective* conf = NULL;
|
||||||
|
|
||||||
|
// parse vhost scope engines
|
||||||
|
std::string scope = "";
|
||||||
|
if ((conf = config->get_transcode(vhost, "")) != NULL) {
|
||||||
|
if ((ret = parse_transcode(conf)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("parse vhost scope=%s transcode engines failed. "
|
||||||
|
"ret=%d", scope.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// parse app scope engines
|
||||||
|
scope = app;
|
||||||
|
if ((conf = config->get_transcode(vhost, app)) != NULL) {
|
||||||
|
if ((ret = parse_transcode(conf)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("parse app scope=%s transcode engines failed. "
|
||||||
|
"ret=%d", scope.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// parse stream scope engines
|
||||||
|
scope += "/";
|
||||||
|
scope += stream;
|
||||||
|
if ((conf = config->get_transcode(vhost, app + "/" + stream)) != NULL) {
|
||||||
|
if ((ret = parse_transcode(conf)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("parse stream scope=%s transcode engines failed. "
|
||||||
|
"ret=%d", scope.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start thread to run all encoding engines.
|
||||||
srs_assert(!tid);
|
srs_assert(!tid);
|
||||||
if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL){
|
if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL) {
|
||||||
ret = ERROR_ST_CREATE_FORWARD_THREAD;
|
ret = ERROR_ST_CREATE_FORWARD_THREAD;
|
||||||
srs_error("st_thread_create failed. ret=%d", ret);
|
srs_error("st_thread_create failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -66,11 +248,89 @@ void SrsEncoder::on_unpublish()
|
||||||
st_thread_join(tid, NULL);
|
st_thread_join(tid, NULL);
|
||||||
tid = NULL;
|
tid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<SrsFFMPEG*>::iterator it;
|
||||||
|
for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) {
|
||||||
|
SrsFFMPEG* ffmpeg = *it;
|
||||||
|
srs_freep(ffmpeg);
|
||||||
|
}
|
||||||
|
ffmpegs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsFFMPEG* SrsEncoder::at(int index)
|
||||||
|
{
|
||||||
|
return ffmpegs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsEncoder::parse_transcode(SrsConfDirective* conf)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
srs_assert(conf);
|
||||||
|
|
||||||
|
// enabled
|
||||||
|
if (!config->get_transcode_enabled(conf)) {
|
||||||
|
srs_trace("ignore the disabled transcode: %s",
|
||||||
|
conf->arg0().c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ffmpeg
|
||||||
|
std::string ffmpeg_bin = config->get_transcode_ffmpeg(conf);
|
||||||
|
if (ffmpeg_bin.empty()) {
|
||||||
|
srs_trace("ignore the empty ffmpeg transcode: %s",
|
||||||
|
conf->arg0().c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all engines.
|
||||||
|
std::vector<SrsConfDirective*> engines;
|
||||||
|
config->get_transcode_engines(conf, engines);
|
||||||
|
if (engines.empty()) {
|
||||||
|
srs_trace("ignore the empty transcode engine: %s",
|
||||||
|
conf->arg0().c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create engine
|
||||||
|
for (int i = 0; i < (int)engines.size(); i++) {
|
||||||
|
SrsConfDirective* engine = engines[i];
|
||||||
|
if (!config->get_engine_enabled(engine)) {
|
||||||
|
srs_trace("ignore the diabled transcode engine: %s %s",
|
||||||
|
conf->arg0().c_str(), engine->arg0().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin);
|
||||||
|
|
||||||
|
if ((ret = ffmpeg->initialize(vhost, port, app, stream, engine)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(ffmpeg);
|
||||||
|
|
||||||
|
srs_error("invalid transcode engine: %s %s",
|
||||||
|
conf->arg0().c_str(), engine->arg0().c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffmpegs.push_back(ffmpeg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsEncoder::cycle()
|
int SrsEncoder::cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// start all ffmpegs.
|
||||||
|
std::vector<SrsFFMPEG*>::iterator it;
|
||||||
|
for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) {
|
||||||
|
SrsFFMPEG* ffmpeg = *it;
|
||||||
|
if ((ret = ffmpeg->start()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("ffmpeg start failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +355,12 @@ void SrsEncoder::encoder_cycle()
|
||||||
st_usleep(SRS_ENCODER_SLEEP_MS * 1000);
|
st_usleep(SRS_ENCODER_SLEEP_MS * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: kill ffmpeg when finished and it alive
|
// kill ffmpeg when finished and it alive
|
||||||
|
std::vector<SrsFFMPEG*>::iterator it;
|
||||||
|
for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) {
|
||||||
|
SrsFFMPEG* ffmpeg = *it;
|
||||||
|
ffmpeg->stop();
|
||||||
|
}
|
||||||
|
|
||||||
srs_trace("encoder cycle finished");
|
srs_trace("encoder cycle finished");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,59 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <st.h>
|
#include <st.h>
|
||||||
|
|
||||||
|
class SrsConfDirective;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a transcode engine: ffmepg,
|
||||||
|
* used to transcode a stream to another.
|
||||||
|
*/
|
||||||
|
class SrsFFMPEG
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool started;
|
||||||
|
private:
|
||||||
|
std::string ffmpeg;
|
||||||
|
std::string vcodec;
|
||||||
|
int vbitrate;
|
||||||
|
double vfps;
|
||||||
|
int vwidth;
|
||||||
|
int vheight;
|
||||||
|
int vthreads;
|
||||||
|
std::string vprofile;
|
||||||
|
std::string vpreset;
|
||||||
|
std::string vparams;
|
||||||
|
std::string acodec;
|
||||||
|
int abitrate;
|
||||||
|
int asample_rate;
|
||||||
|
int achannels;
|
||||||
|
std::string aparams;
|
||||||
|
std::string output;
|
||||||
|
public:
|
||||||
|
SrsFFMPEG(std::string ffmpeg_bin);
|
||||||
|
virtual ~SrsFFMPEG();
|
||||||
|
public:
|
||||||
|
virtual int initialize(std::string vhost, std::string port, std::string app, std::string stream, SrsConfDirective* engine);
|
||||||
|
virtual int start();
|
||||||
|
virtual void stop();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the encoder for a stream,
|
||||||
|
* may use multiple ffmpegs to transcode the specified stream.
|
||||||
|
*/
|
||||||
class SrsEncoder
|
class SrsEncoder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::string vhost;
|
std::string vhost;
|
||||||
|
std::string port;
|
||||||
std::string app;
|
std::string app;
|
||||||
std::string stream;
|
std::string stream;
|
||||||
|
private:
|
||||||
|
std::vector<SrsFFMPEG*> ffmpegs;
|
||||||
private:
|
private:
|
||||||
st_thread_t tid;
|
st_thread_t tid;
|
||||||
bool loop;
|
bool loop;
|
||||||
|
@ -46,9 +90,11 @@ public:
|
||||||
SrsEncoder();
|
SrsEncoder();
|
||||||
virtual ~SrsEncoder();
|
virtual ~SrsEncoder();
|
||||||
public:
|
public:
|
||||||
virtual int on_publish(std::string vhost, std::string app, std::string stream);
|
virtual int on_publish(std::string vhost, std::string port, std::string app, std::string stream);
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
private:
|
private:
|
||||||
|
virtual SrsFFMPEG* at(int index);
|
||||||
|
virtual int parse_transcode(SrsConfDirective* conf);
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
virtual void encoder_cycle();
|
virtual void encoder_cycle();
|
||||||
static void* encoder_thread(void* arg);
|
static void* encoder_thread(void* arg);
|
||||||
|
|
|
@ -122,4 +122,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define ERROR_HLS_AAC_FRAME_LENGTH 605
|
#define ERROR_HLS_AAC_FRAME_LENGTH 605
|
||||||
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
|
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
|
||||||
|
|
||||||
|
#define ERROR_ENCODER_VCODEC 700
|
||||||
|
#define ERROR_ENCODER_OUTPUT 701
|
||||||
|
#define ERROR_ENCODER_ACHANNELS 702
|
||||||
|
#define ERROR_ENCODER_ASAMPLE_RATE 703
|
||||||
|
#define ERROR_ENCODER_ABITRATE 704
|
||||||
|
#define ERROR_ENCODER_ACODEC 705
|
||||||
|
#define ERROR_ENCODER_VPRESET 706
|
||||||
|
#define ERROR_ENCODER_VPROFILE 707
|
||||||
|
#define ERROR_ENCODER_VTHREADS 708
|
||||||
|
#define ERROR_ENCODER_VHEIGHT 709
|
||||||
|
#define ERROR_ENCODER_VWIDTH 710
|
||||||
|
#define ERROR_ENCODER_VFPS 711
|
||||||
|
#define ERROR_ENCODER_VBITRATE 712
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -688,8 +688,7 @@ int SrsHls::reopen()
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// try to open the HLS muxer
|
// try to open the HLS muxer
|
||||||
SrsConfDirective* conf = config->get_hls(vhost);
|
if (!config->get_hls_enabled(vhost)) {
|
||||||
if (conf && conf->arg0() == "off") {
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +697,7 @@ int SrsHls::reopen()
|
||||||
|
|
||||||
hls_enabled = true;
|
hls_enabled = true;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = NULL;
|
||||||
hls_path = SRS_CONF_DEFAULT_HLS_PATH;
|
hls_path = SRS_CONF_DEFAULT_HLS_PATH;
|
||||||
if ((conf = config->get_hls_path(vhost)) != NULL) {
|
if ((conf = config->get_hls_path(vhost)) != NULL) {
|
||||||
hls_path = conf->arg0();
|
hls_path = conf->arg0();
|
||||||
|
|
|
@ -612,7 +612,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsSource::on_publish(std::string vhost, std::string app, std::string stream)
|
int SrsSource::on_publish(std::string vhost, std::string port, std::string app, std::string stream)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -625,7 +625,7 @@ int SrsSource::on_publish(std::string vhost, std::string app, std::string stream
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRS_FFMPEG
|
#ifdef SRS_FFMPEG
|
||||||
if ((ret = encoder->on_publish(vhost, app, stream)) != ERROR_SUCCESS) {
|
if ((ret = encoder->on_publish(vhost, port, app, stream)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -210,7 +210,7 @@ public:
|
||||||
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
||||||
virtual int on_audio(SrsCommonMessage* audio);
|
virtual int on_audio(SrsCommonMessage* audio);
|
||||||
virtual int on_video(SrsCommonMessage* video);
|
virtual int on_video(SrsCommonMessage* video);
|
||||||
virtual int on_publish(std::string vhost, std::string app, std::string stream);
|
virtual int on_publish(std::string vhost, std::string port, std::string app, std::string stream);
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
public:
|
public:
|
||||||
virtual int create_consumer(SrsConsumer*& consumer);
|
virtual int create_consumer(SrsConsumer*& consumer);
|
||||||
|
|
Loading…
Reference in a new issue