void srs_vhost_resolve(std::string& vhost, std::string& app) { app = srs_replace(app, "...", "?"); size_t pos = 0; if ((pos = app.find("?")) == std::string::npos) { return; } std::string query = app.substr(pos + 1); app = app.substr(0, pos); if ((pos = query.find("vhost?")) != std::string::npos || (pos = query.find("vhost=")) != std::string::npos || (pos = query.find("Vhost?")) != std::string::npos || (pos = query.find("Vhost=")) != std::string::npos ) { query = query.substr(pos + 6); if (!query.empty()) { vhost = query; } } }
int SrsFFMPEG::initialize(std::string vhost, std::string port, std::string app, std::string stream, SrsConfDirective* engine) { int ret = ERROR_SUCCESS; config->get_engine_vfilter(engine, vfilter); 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); config->get_engine_vparams(engine, vparams); 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); config->get_engine_aparams(engine, aparams); output = config->get_engine_output(engine); // ensure the size is even. vwidth -= vwidth % 2; vheight -= vheight % 2; // input stream, from local. // ie. rtmp://127.0.0.1:1935/live/livestream input = "rtmp://127.0.0.1:"; input += port; input += "/"; input += app; input += "/"; input += stream; // output stream, to other/self server // ie. rtmp://127.0.0.1:1935/live/livestream_sd 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); // important: loop check, donot transcode again. // we think the following is loop circle: // input: rtmp://127.0.0.1:1935/live/livestream_sd // output: rtmp://127.0.0.1:1935/live/livestream_sd_sd std::string tail = ""; // tail="_sd" if (output.length() > input.length()) { tail = output.substr(input.length()); } // TODO: better dead loop check. // if input also endwiths the tail, loop detected. if (!tail.empty() && input.rfind(tail) == input.length() - tail.length()) { ret = ERROR_ENCODER_LOOP; srs_info("detect a loop cycle, input=%s, output=%s, ignore it. ret=%d", input.c_str(), output.c_str(), ret); return ret; } 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; }