mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Squash: Merge SRS 4.0
This commit is contained in:
parent
6c597facfb
commit
a81aa2edc5
65 changed files with 276 additions and 5990 deletions
File diff suppressed because it is too large
Load diff
|
@ -100,7 +100,6 @@ extern bool srs_config_ingest_is_stream(std::string type);
|
|||
extern bool srs_config_dvr_is_plan_segment(std::string plan);
|
||||
extern bool srs_config_dvr_is_plan_session(std::string plan);
|
||||
extern bool srs_stream_caster_is_udp(std::string caster);
|
||||
extern bool srs_stream_caster_is_rtsp(std::string caster);
|
||||
extern bool srs_stream_caster_is_flv(std::string caster);
|
||||
// Whether the dvr_apply active the stream specified by req.
|
||||
extern bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req);
|
||||
|
@ -333,44 +332,8 @@ public:
|
|||
private:
|
||||
virtual srs_error_t do_persistence(SrsFileWriter* fw);
|
||||
public:
|
||||
// Dumps the global sections to json.
|
||||
virtual srs_error_t global_to_json(SrsJsonObject* obj);
|
||||
// Dumps the minimal sections to json.
|
||||
virtual srs_error_t minimal_to_json(SrsJsonObject* obj);
|
||||
// Dumps the vhost section to json.
|
||||
virtual srs_error_t vhost_to_json(SrsConfDirective* vhost, SrsJsonObject* obj);
|
||||
// Dumps the http_api sections to json for raw api info.
|
||||
virtual srs_error_t raw_to_json(SrsJsonObject* obj);
|
||||
// RAW set the global listen.
|
||||
virtual srs_error_t raw_set_listen(const std::vector<std::string>& eps, bool& applied);
|
||||
// RAW set the global pid.
|
||||
virtual srs_error_t raw_set_pid(std::string pid, bool& applied);
|
||||
// RAW set the global chunk size.
|
||||
virtual srs_error_t raw_set_chunk_size(std::string chunk_size, bool& applied);
|
||||
// RAW set the global ffmpeg log dir.
|
||||
virtual srs_error_t raw_set_ff_log_dir(std::string ff_log_dir, bool& applied);
|
||||
// RAW set the global log tank.
|
||||
virtual srs_error_t raw_set_srs_log_tank(std::string srs_log_tank, bool& applied);
|
||||
// RAW set the global log level.
|
||||
virtual srs_error_t raw_set_srs_log_level(std::string srs_log_level, bool& applied);
|
||||
// RAW set the global log file path for file tank.
|
||||
virtual srs_error_t raw_set_srs_log_file(std::string srs_log_file, bool& applied);
|
||||
// RAW set the global max connections of srs.
|
||||
virtual srs_error_t raw_set_max_connections(std::string max_connections, bool& applied);
|
||||
// RAW set the global whether use utc time.
|
||||
virtual srs_error_t raw_set_utc_time(std::string utc_time, bool& applied);
|
||||
// RAW set the global pithy print interval in ms.
|
||||
virtual srs_error_t raw_set_pithy_print_ms(std::string pithy_print_ms, bool& applied);
|
||||
// RAW create the new vhost.
|
||||
virtual srs_error_t raw_create_vhost(std::string vhost, bool& applied);
|
||||
// RAW update the disabled vhost name.
|
||||
virtual srs_error_t raw_update_vhost(std::string vhost, std::string name, bool& applied);
|
||||
// RAW delete the disabled vhost.
|
||||
virtual srs_error_t raw_delete_vhost(std::string vhost, bool& applied);
|
||||
// RAW disable the enabled vhost.
|
||||
virtual srs_error_t raw_disable_vhost(std::string vhost, bool& applied);
|
||||
// RAW enable the disabled vhost.
|
||||
virtual srs_error_t raw_enable_vhost(std::string vhost, bool& applied);
|
||||
private:
|
||||
virtual srs_error_t do_reload_listen();
|
||||
virtual srs_error_t do_reload_pid();
|
||||
|
@ -750,7 +713,6 @@ public:
|
|||
// all clients connected to edge must be tranverse to origin to verify.
|
||||
virtual bool get_vhost_edge_token_traverse(std::string vhost);
|
||||
// Get the transformed vhost for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
virtual std::string get_vhost_edge_transform_vhost(std::string vhost);
|
||||
// Whether enable the origin cluster.
|
||||
// @see https://github.com/ossrs/srs/wiki/v3_EN_OriginCluster
|
||||
|
@ -925,7 +887,6 @@ public:
|
|||
// Get the hls hls_on_error config.
|
||||
// The ignore will ignore error and disable hls.
|
||||
// The disconnect will disconnect publish connection.
|
||||
// @see https://github.com/ossrs/srs/issues/264
|
||||
virtual std::string get_hls_on_error(std::string vhost);
|
||||
// Get the HLS default audio codec.
|
||||
virtual std::string get_hls_acodec(std::string vhost);
|
||||
|
|
|
@ -71,7 +71,6 @@ srs_error_t SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
|
|||
if (true) {
|
||||
SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(req->vhost);
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/79
|
||||
// when origin is error, for instance, server is shutdown,
|
||||
// then user remove the vhost then reload, the conf is empty.
|
||||
if (!conf) {
|
||||
|
@ -98,7 +97,6 @@ srs_error_t SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
|
|||
selected_port = port;
|
||||
|
||||
// support vhost tranform for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req->vhost);
|
||||
vhost = srs_string_replace(vhost, "[vhost]", req->vhost);
|
||||
|
||||
|
@ -724,7 +722,6 @@ srs_error_t SrsEdgeForwarder::start()
|
|||
srs_parse_hostport(server, server, port);
|
||||
|
||||
// support vhost tranform for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req->vhost);
|
||||
vhost = srs_string_replace(vhost, "[vhost]", req->vhost);
|
||||
|
||||
|
@ -1005,7 +1002,6 @@ srs_error_t SrsPublishEdge::on_client_publish()
|
|||
return srs_error_new(ERROR_RTMP_EDGE_PUBLISH_STATE, "invalid state");
|
||||
}
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/180
|
||||
// to avoid multiple publish the same stream on the same edge,
|
||||
// directly enter the publish stage.
|
||||
if (true) {
|
||||
|
@ -1017,7 +1013,6 @@ srs_error_t SrsPublishEdge::on_client_publish()
|
|||
// start to forward stream to origin.
|
||||
err = forwarder->start();
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/180
|
||||
// when failed, revert to init
|
||||
if (err != srs_success) {
|
||||
SrsEdgeState pstate = state;
|
||||
|
|
|
@ -40,7 +40,6 @@ private:
|
|||
SrsRtmpJitter* jitter;
|
||||
SrsMessageQueue* queue;
|
||||
// Cache the sequence header for retry when slave is failed.
|
||||
// @see https://github.com/ossrs/srs/issues/150
|
||||
SrsSharedPtrMessage* sh_audio;
|
||||
SrsSharedPtrMessage* sh_video;
|
||||
public:
|
||||
|
|
|
@ -153,7 +153,6 @@ private:
|
|||
// The current writing segment.
|
||||
SrsHlsSegment* current;
|
||||
// The ts context, to keep cc continous between ts.
|
||||
// @see https://github.com/ossrs/srs/issues/375
|
||||
SrsTsContext* context;
|
||||
public:
|
||||
SrsHlsMuxer();
|
||||
|
@ -187,7 +186,6 @@ public:
|
|||
virtual bool wait_keyframe();
|
||||
// Whether segment absolutely overflow, for pure audio to reap segment,
|
||||
// that is whether the current segment duration>=2*(the segment in config)
|
||||
// @see https://github.com/ossrs/srs/issues/151#issuecomment-71155184
|
||||
virtual bool is_segment_absolutely_overflow();
|
||||
public:
|
||||
// Whether current hls muxer is pure audio mode.
|
||||
|
|
|
@ -902,7 +902,7 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// the rpc is required.
|
||||
// the allowd rpc method check.
|
||||
if (rpc.empty() || (rpc != "reload" && rpc != "query" && rpc != "raw" && rpc != "update")) {
|
||||
if (rpc.empty() || rpc != "reload") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW);
|
||||
}
|
||||
|
||||
|
@ -916,312 +916,6 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
|
|||
return srs_api_response_code(w, r, ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// for rpc=query, to get the configs of server.
|
||||
// @param scope the scope to query for config, it can be:
|
||||
// global, the configs belongs to the root, donot includes any sub directives.
|
||||
// minimal, the minimal summary of server, for preview stream to got the port serving.
|
||||
// vhost, the configs for specified vhost by @param vhost.
|
||||
// @param vhost the vhost name for @param scope is vhost to query config.
|
||||
// for the default vhost, must be __defaultVhost__
|
||||
if (rpc == "query") {
|
||||
if (!allow_query) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_DISABLED);
|
||||
}
|
||||
|
||||
std::string scope = r->query_get("scope");
|
||||
std::string vhost = r->query_get("vhost");
|
||||
if (scope.empty() || (scope != "global" && scope != "vhost" && scope != "minimal")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
if (scope == "vhost") {
|
||||
// query vhost scope.
|
||||
if (vhost.empty()) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
SrsConfDirective* root = _srs_config->get_root();
|
||||
SrsConfDirective* conf = root->get("vhost", vhost);
|
||||
if (!conf) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("vhost", data);
|
||||
if ((err = _srs_config->vhost_to_json(conf, data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "minimal") {
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("minimal", data);
|
||||
|
||||
// query minimal scope.
|
||||
if ((err = _srs_config->minimal_to_json(data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else {
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("global", data);
|
||||
|
||||
// query global scope.
|
||||
if ((err = _srs_config->global_to_json(data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
}
|
||||
|
||||
return srs_api_response(w, r, obj->dumps());
|
||||
}
|
||||
|
||||
// for rpc=update, to update the configs of server.
|
||||
// @scope the scope to update for config.
|
||||
// @value the updated value for scope.
|
||||
// @param the extra param for scope.
|
||||
// @data the extra data for scope.
|
||||
// possible updates:
|
||||
// @scope @value value-description
|
||||
// listen 1935,1936 the port list.
|
||||
// pid ./objs/srs.pid the pid file of srs.
|
||||
// chunk_size 60000 the global RTMP chunk_size.
|
||||
// ff_log_dir ./objs the dir for ffmpeg log.
|
||||
// srs_log_tank file the tank to log, file or console.
|
||||
// srs_log_level trace the level of log, verbose, info, trace, warn, error.
|
||||
// srs_log_file ./objs/srs.log the log file when tank is file.
|
||||
// max_connections 1000 the max connections of srs.
|
||||
// utc_time false whether enable utc time.
|
||||
// pithy_print_ms 10000 the pithy print interval in ms.
|
||||
// vhost specified updates:
|
||||
// @scope @value @param @data description
|
||||
// vhost ossrs.net create - create vhost ossrs.net
|
||||
// vhost ossrs.net update new.ossrs.net the new name to update vhost
|
||||
// dvr specified updates:
|
||||
// @scope @value @param @data description
|
||||
// dvr ossrs.net enable live/livestream enable the dvr of stream
|
||||
// dvr ossrs.net disable live/livestream disable the dvr of stream
|
||||
if (rpc == "update") {
|
||||
if (!allow_update) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_DISABLED);
|
||||
}
|
||||
|
||||
std::string scope = r->query_get("scope");
|
||||
std::string value = r->query_get("value");
|
||||
if (scope.empty()) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
if (scope != "listen" && scope != "pid" && scope != "chunk_size"
|
||||
&& scope != "ff_log_dir" && scope != "srs_log_tank" && scope != "srs_log_level"
|
||||
&& scope != "srs_log_file" && scope != "max_connections" && scope != "utc_time"
|
||||
&& scope != "pithy_print_ms" && scope != "vhost" && scope != "dvr"
|
||||
) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
bool applied = false;
|
||||
string extra = "";
|
||||
if (scope == "listen") {
|
||||
vector<string> eps = srs_string_split(value, ",");
|
||||
|
||||
bool invalid = eps.empty();
|
||||
for (int i = 0; i < (int)eps.size(); i++) {
|
||||
string ep = eps.at(i);
|
||||
int port = ::atoi(ep.c_str());
|
||||
if (port <= 2 || port >= 65535) {
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_listen(eps, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "pid") {
|
||||
if (value.empty() || !srs_string_starts_with(value, "./", "/tmp/", "/var/") || !srs_string_ends_with(value, ".pid")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_pid(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "chunk_size") {
|
||||
int csv = ::atoi(value.c_str());
|
||||
if (csv < 128 || csv > 65535 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_chunk_size(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "ff_log_dir") {
|
||||
if (value.empty() || (value != "/dev/null" && !srs_string_starts_with(value, "./", "/tmp/", "/var/"))) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_ff_log_dir(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_tank") {
|
||||
if (value.empty() || (value != "file" && value != "console")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_tank(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_level") {
|
||||
if (value != "verbose" && value != "info" && value != "trace" && value != "warn" && value != "error") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_level(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_file") {
|
||||
if (value.empty() || !srs_string_starts_with(value, "./", "/tmp/", "/var/") || !srs_string_ends_with(value, ".log")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_file(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "max_connections") {
|
||||
int mcv = ::atoi(value.c_str());
|
||||
if (mcv < 10 || mcv > 65535 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_max_connections(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "utc_time") {
|
||||
if (!srs_is_boolean(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_utc_time(srs_config_bool2switch(value), applied)) != srs_success) {
|
||||
return srs_api_response_code(w, r, srs_error_wrap(err, "raw api update utc_time=%s", value.c_str()));
|
||||
}
|
||||
} else if (scope == "pithy_print_ms") {
|
||||
int ppmv = ::atoi(value.c_str());
|
||||
if (ppmv < 100 || ppmv > 300000 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_pithy_print_ms(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "vhost") {
|
||||
std::string param = r->query_get("param");
|
||||
std::string data = r->query_get("data");
|
||||
if (param != "create" && param != "update" && param != "delete" && param != "disable" && param != "enable") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
extra += " " + param;
|
||||
|
||||
if (param == "create") {
|
||||
// when create, the vhost must not exists.
|
||||
if (param.empty() || _srs_config->get_vhost(value, false)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_create_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "update") {
|
||||
extra += " to " + data;
|
||||
|
||||
// when update, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (data.empty() || data == value || param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_update_vhost(value, data, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "delete") {
|
||||
// when delete, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_delete_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "disable") {
|
||||
// when disable, the vhost must exists and enabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || !_srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_disable_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "enable") {
|
||||
// when enable, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_enable_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else {
|
||||
// TODO: support other param.
|
||||
}
|
||||
} else {
|
||||
// TODO: support other scope.
|
||||
}
|
||||
|
||||
// whether the config applied.
|
||||
if (applied) {
|
||||
server->on_signal(SRS_SIGNAL_PERSISTENCE_CONFIG);
|
||||
srs_trace("raw api update %s=%s%s ok.", scope.c_str(), value.c_str(), extra.c_str());
|
||||
} else {
|
||||
srs_warn("raw api update not applied %s=%s%s.", scope.c_str(), value.c_str(), extra.c_str());
|
||||
}
|
||||
|
||||
return srs_api_response(w, r, obj->dumps());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -509,7 +509,6 @@ srs_error_t SrsHttpHooks::do_post(SrsHttpClient* hc, std::string url, std::strin
|
|||
}
|
||||
|
||||
// ensure the http status is ok.
|
||||
// https://github.com/ossrs/srs/issues/158
|
||||
if (code != SRS_CONSTS_HTTP_OK && code != SRS_CONSTS_HTTP_Created) {
|
||||
return srs_error_new(ERROR_HTTP_STATUS_INVALID, "http: status %d", code);
|
||||
}
|
||||
|
|
|
@ -928,7 +928,6 @@ srs_error_t SrsHttpStreamServer::http_mount(SrsLiveSource* s, SrsRequest* r)
|
|||
// mount the http flv stream.
|
||||
// we must register the handler, then start the thread,
|
||||
// for the thread will cause thread switch context.
|
||||
// @see https://github.com/ossrs/srs/issues/404
|
||||
if ((err = mux.handle(mount, entry->stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: mount flv stream for vhost=%s failed", sid.c_str());
|
||||
}
|
||||
|
|
|
@ -449,7 +449,6 @@ srs_error_t SrsMpegtsOverUdp::write_h264_ipb_frame(char* frame, int frame_size,
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// when sps or pps not sent, ignore the packet.
|
||||
// @see https://github.com/ossrs/srs/issues/203
|
||||
if (!h264_sps_pps_sent) {
|
||||
return srs_error_new(ERROR_H264_DROP_BEFORE_SPS_PPS, "drop sps/pps");
|
||||
}
|
||||
|
|
|
@ -93,8 +93,6 @@ srs_error_t SrsRecvThread::cycle()
|
|||
// the multiple messages writev improve performance large,
|
||||
// but the timeout recv will cause 33% sys call performance,
|
||||
// to use isolate thread to recv, can improve about 33% performance.
|
||||
// @see https://github.com/ossrs/srs/issues/194
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
rtmp->set_recv_timeout(SRS_UTIME_NO_TIMEOUT);
|
||||
|
||||
pumper->on_start();
|
||||
|
@ -279,7 +277,6 @@ SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest*
|
|||
mr_fd = mr_sock_fd;
|
||||
|
||||
// the mr settings,
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
mr = _srs_config->get_mr_enabled(req->vhost);
|
||||
mr_sleep = _srs_config->get_mr_sleep(req->vhost);
|
||||
|
||||
|
@ -405,7 +402,6 @@ void SrsPublishRecvThread::interrupt(srs_error_t err)
|
|||
recv_error = srs_error_copy(err);
|
||||
|
||||
// when recv thread error, signal the conn thread to process it.
|
||||
// @see https://github.com/ossrs/srs/issues/244
|
||||
srs_cond_signal(error);
|
||||
}
|
||||
|
||||
|
@ -420,7 +416,6 @@ void SrsPublishRecvThread::on_start()
|
|||
set_socket_buffer(mr_sleep);
|
||||
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(true, this);
|
||||
}
|
||||
#endif
|
||||
|
@ -432,13 +427,11 @@ void SrsPublishRecvThread::on_stop()
|
|||
// for we donot set to false yet.
|
||||
|
||||
// when thread stop, signal the conn thread which wait.
|
||||
// @see https://github.com/ossrs/srs/issues/244
|
||||
srs_cond_signal(error);
|
||||
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
if (mr) {
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(false, NULL);
|
||||
}
|
||||
#endif
|
||||
|
@ -459,7 +452,6 @@ void SrsPublishRecvThread::on_read(ssize_t nread)
|
|||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
if (nread < SRS_MR_SMALL_BYTES) {
|
||||
srs_usleep(mr_sleep);
|
||||
|
@ -476,7 +468,6 @@ srs_error_t SrsPublishRecvThread::on_reload_vhost_publish(string vhost)
|
|||
}
|
||||
|
||||
// the mr settings,
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
bool mr_enabled = _srs_config->get_mr_enabled(req->vhost);
|
||||
srs_utime_t sleep_v = _srs_config->get_mr_sleep(req->vhost);
|
||||
|
||||
|
@ -489,13 +480,11 @@ srs_error_t SrsPublishRecvThread::on_reload_vhost_publish(string vhost)
|
|||
// mr enabled=>disabled
|
||||
if (mr && !mr_enabled) {
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(false, NULL);
|
||||
}
|
||||
// mr disabled=>enabled
|
||||
if (!mr && mr_enabled) {
|
||||
// enable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(true, this);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -75,7 +75,6 @@ private:
|
|||
// when source id changed, notice all consumers
|
||||
bool should_update_source_id;
|
||||
// The cond wait for mw.
|
||||
// @see https://github.com/ossrs/srs/issues/251
|
||||
srs_cond_t mw_wait;
|
||||
bool mw_waiting;
|
||||
int mw_min_msgs;
|
||||
|
|
|
@ -429,7 +429,6 @@ srs_error_t SrsRtmpConn::service_cycle()
|
|||
// logical accept and retry stream service.
|
||||
if (srs_error_code(err) == ERROR_CONTROL_RTMP_CLOSE) {
|
||||
// TODO: FIXME: use ping message to anti-death of socket.
|
||||
// @see: https://github.com/ossrs/srs/issues/39
|
||||
// set timeout to a larger value, for user paused.
|
||||
rtmp->set_recv_timeout(SRS_PAUSED_RECV_TIMEOUT);
|
||||
rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT);
|
||||
|
@ -670,7 +669,6 @@ srs_error_t SrsRtmpConn::playing(SrsLiveSource* source)
|
|||
}
|
||||
|
||||
// Use receiving thread to receive packets from peer.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
SrsQueueRecvThread trd(consumer, rtmp, SRS_PERF_MW_SLEEP, _srs_context->get_id());
|
||||
|
||||
if ((err = trd.start()) != srs_success) {
|
||||
|
@ -731,8 +729,6 @@ srs_error_t SrsRtmpConn::do_playing(SrsLiveSource* source, SrsLiveConsumer* cons
|
|||
pprint->elapse();
|
||||
|
||||
// to use isolate thread to recv, can improve about 33% performance.
|
||||
// @see: https://github.com/ossrs/srs/issues/196
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
while (!rtrd->empty()) {
|
||||
SrsCommonMessage* msg = rtrd->pump();
|
||||
if ((err = process_play_control_msg(consumer, msg)) != srs_success) {
|
||||
|
@ -1114,7 +1110,6 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer* consumer, Srs
|
|||
SrsAutoFree(SrsPacket, pkt);
|
||||
|
||||
// for jwplayer/flowplayer, which send close as pause message.
|
||||
// @see https://github.com/ossrs/srs/issues/6
|
||||
SrsCloseStreamPacket* close = dynamic_cast<SrsCloseStreamPacket*>(pkt);
|
||||
if (close) {
|
||||
return srs_error_new(ERROR_CONTROL_RTMP_CLOSE, "rtmp: close stream");
|
||||
|
@ -1122,7 +1117,6 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer* consumer, Srs
|
|||
|
||||
// call msg,
|
||||
// support response null first,
|
||||
// @see https://github.com/ossrs/srs/issues/106
|
||||
// TODO: FIXME: response in right way, or forward in edge mode.
|
||||
SrsCallPacket* call = dynamic_cast<SrsCallPacket*>(pkt);
|
||||
if (call) {
|
||||
|
|
|
@ -82,7 +82,6 @@ private:
|
|||
ISrsWakable* wakable;
|
||||
// The elapsed duration in srs_utime_t
|
||||
// For live play duration, for instance, rtmpdump to record.
|
||||
// @see https://github.com/ossrs/srs/issues/47
|
||||
srs_utime_t duration;
|
||||
// The MR(merged-write) sleep time in srs_utime_t.
|
||||
srs_utime_t mw_sleep;
|
||||
|
|
|
@ -1,785 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2013-2021 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#include <srs_app_rtsp.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_rtsp_stack.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_protocol_amf0.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_raw_avc.hpp>
|
||||
#include <srs_kernel_codec.hpp>
|
||||
#include <srs_app_pithy_print.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_protocol_format.hpp>
|
||||
|
||||
SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p, int sid)
|
||||
{
|
||||
rtsp = r;
|
||||
_port = p;
|
||||
stream_id = sid;
|
||||
// TODO: support listen at <[ip:]port>
|
||||
listener = new SrsUdpListener(this, srs_any_address_for_listener(), p);
|
||||
cache = new SrsRtspPacket();
|
||||
pprint = SrsPithyPrint::create_caster();
|
||||
}
|
||||
|
||||
SrsRtpConn::~SrsRtpConn()
|
||||
{
|
||||
srs_freep(listener);
|
||||
srs_freep(cache);
|
||||
srs_freep(pprint);
|
||||
}
|
||||
|
||||
int SrsRtpConn::port()
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpConn::listen()
|
||||
{
|
||||
return listener->listen();
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpConn::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
pprint->elapse();
|
||||
|
||||
if (true) {
|
||||
SrsBuffer stream(buf, nb_buf);
|
||||
|
||||
SrsRtspPacket pkt;
|
||||
if ((err = pkt.decode(&stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "decode");
|
||||
}
|
||||
|
||||
if (pkt.chunked) {
|
||||
if (!cache) {
|
||||
cache = new SrsRtspPacket();
|
||||
}
|
||||
cache->copy(&pkt);
|
||||
cache->payload->append(pkt.payload->bytes(), pkt.payload->length());
|
||||
if (pprint->can_print()) {
|
||||
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp chunked %dB, age=%d, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB",
|
||||
nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
||||
cache->payload->length()
|
||||
);
|
||||
}
|
||||
|
||||
if (!cache->completed){
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
srs_freep(cache);
|
||||
cache = new SrsRtspPacket();
|
||||
cache->reap(&pkt);
|
||||
}
|
||||
}
|
||||
|
||||
if (pprint->can_print()) {
|
||||
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp #%d %dB, age=%d, vt=%d/%u, sts=%u/%u/%#x, paylod=%dB, chunked=%d",
|
||||
stream_id, nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
||||
cache->payload->length(), cache->chunked
|
||||
);
|
||||
}
|
||||
|
||||
// always free it.
|
||||
SrsAutoFree(SrsRtspPacket, cache);
|
||||
|
||||
err = rtsp->on_rtp_packet(cache, stream_id);
|
||||
if (err != srs_success) {
|
||||
srs_warn("ignore RTP packet err %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsRtspAudioCache::SrsRtspAudioCache()
|
||||
{
|
||||
dts = 0;
|
||||
audio = NULL;
|
||||
payload = NULL;
|
||||
}
|
||||
|
||||
SrsRtspAudioCache::~SrsRtspAudioCache()
|
||||
{
|
||||
srs_freep(audio);
|
||||
srs_freep(payload);
|
||||
}
|
||||
|
||||
SrsRtspJitter::SrsRtspJitter()
|
||||
{
|
||||
delta = 0;
|
||||
previous_timestamp = 0;
|
||||
pts = 0;
|
||||
}
|
||||
|
||||
SrsRtspJitter::~SrsRtspJitter()
|
||||
{
|
||||
}
|
||||
|
||||
int64_t SrsRtspJitter::timestamp()
|
||||
{
|
||||
return pts;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspJitter::correct(int64_t& ts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (previous_timestamp == 0) {
|
||||
previous_timestamp = ts;
|
||||
}
|
||||
|
||||
delta = srs_max(0, (int)(ts - previous_timestamp));
|
||||
if (delta > 90000) {
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
previous_timestamp = ts;
|
||||
|
||||
ts = pts + delta;
|
||||
pts = ts;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, srs_netfd_t fd, std::string o)
|
||||
{
|
||||
output_template = o;
|
||||
|
||||
session = "";
|
||||
video_rtp = NULL;
|
||||
audio_rtp = NULL;
|
||||
|
||||
caster = c;
|
||||
stfd = fd;
|
||||
skt = new SrsStSocket();
|
||||
rtsp = new SrsRtspStack(skt);
|
||||
trd = new SrsSTCoroutine("rtsp", this);
|
||||
|
||||
audio_id = 0;
|
||||
video_id = 0;
|
||||
audio_sample_rate = 0;
|
||||
audio_channel = 0;
|
||||
|
||||
req = NULL;
|
||||
sdk = NULL;
|
||||
vjitter = new SrsRtspJitter();
|
||||
ajitter = new SrsRtspJitter();
|
||||
|
||||
avc = new SrsRawH264Stream();
|
||||
aac = new SrsRawAacStream();
|
||||
acodec = new SrsRawAacStreamCodec();
|
||||
acache = new SrsRtspAudioCache();
|
||||
}
|
||||
|
||||
SrsRtspConn::~SrsRtspConn()
|
||||
{
|
||||
close();
|
||||
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
srs_freep(video_rtp);
|
||||
srs_freep(audio_rtp);
|
||||
|
||||
srs_freep(trd);
|
||||
srs_freep(skt);
|
||||
srs_freep(rtsp);
|
||||
|
||||
srs_freep(sdk);
|
||||
srs_freep(req);
|
||||
|
||||
srs_freep(vjitter);
|
||||
srs_freep(ajitter);
|
||||
|
||||
srs_freep(avc);
|
||||
srs_freep(aac);
|
||||
srs_freep(acodec);
|
||||
srs_freep(acache);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::serve()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = skt->initialize(stfd)) != srs_success) {
|
||||
return srs_error_wrap(err, "socket initialize");
|
||||
}
|
||||
|
||||
if ((err = trd->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp connection");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string SrsRtspConn::remote_ip()
|
||||
{
|
||||
// TODO: FIXME: Implement it.
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string SrsRtspConn::desc()
|
||||
{
|
||||
return "RtspConn";
|
||||
}
|
||||
|
||||
const SrsContextId& SrsRtspConn::get_id()
|
||||
{
|
||||
return _srs_context->get_id();
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::do_cycle()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// retrieve ip of client.
|
||||
int fd = srs_netfd_fileno(stfd);
|
||||
std::string ip = srs_get_peer_ip(fd);
|
||||
int port = srs_get_peer_port(fd);
|
||||
|
||||
if (ip.empty() && !_srs_config->empty_ip_ok()) {
|
||||
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
|
||||
}
|
||||
srs_trace("rtsp: serve %s:%d", ip.c_str(), port);
|
||||
|
||||
// consume all rtsp messages.
|
||||
while (true) {
|
||||
if ((err = trd->pull()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp cycle");
|
||||
}
|
||||
|
||||
SrsRtspRequest* req = NULL;
|
||||
if ((err = rtsp->recv_message(&req)) != srs_success) {
|
||||
return srs_error_wrap(err, "recv message");
|
||||
}
|
||||
SrsAutoFree(SrsRtspRequest, req);
|
||||
srs_info("rtsp: got rtsp request");
|
||||
|
||||
if (req->is_options()) {
|
||||
SrsRtspOptionsResponse* res = new SrsRtspOptionsResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response option");
|
||||
}
|
||||
} else if (req->is_announce()) {
|
||||
if (rtsp_tcUrl.empty()) {
|
||||
rtsp_tcUrl = req->uri;
|
||||
}
|
||||
size_t pos = string::npos;
|
||||
if ((pos = rtsp_tcUrl.rfind(".sdp")) != string::npos) {
|
||||
rtsp_tcUrl = rtsp_tcUrl.substr(0, pos);
|
||||
}
|
||||
srs_parse_rtmp_url(rtsp_tcUrl, rtsp_tcUrl, rtsp_stream);
|
||||
|
||||
srs_assert(req->sdp);
|
||||
video_id = ::atoi(req->sdp->video_stream_id.c_str());
|
||||
audio_id = ::atoi(req->sdp->audio_stream_id.c_str());
|
||||
video_codec = req->sdp->video_codec;
|
||||
audio_codec = req->sdp->audio_codec;
|
||||
audio_sample_rate = ::atoi(req->sdp->audio_sample_rate.c_str());
|
||||
audio_channel = ::atoi(req->sdp->audio_channel.c_str());
|
||||
h264_sps = req->sdp->video_sps;
|
||||
h264_pps = req->sdp->video_pps;
|
||||
aac_specific_config = req->sdp->audio_sh;
|
||||
srs_trace("rtsp: video(#%d, %s, %s/%s), audio(#%d, %s, %s/%s, %dHZ %dchannels), %s/%s",
|
||||
video_id, video_codec.c_str(), req->sdp->video_protocol.c_str(), req->sdp->video_transport_format.c_str(),
|
||||
audio_id, audio_codec.c_str(), req->sdp->audio_protocol.c_str(), req->sdp->audio_transport_format.c_str(),
|
||||
audio_sample_rate, audio_channel, rtsp_tcUrl.c_str(), rtsp_stream.c_str()
|
||||
);
|
||||
|
||||
SrsRtspResponse* res = new SrsRtspResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response announce");
|
||||
}
|
||||
} else if (req->is_setup()) {
|
||||
srs_assert(req->transport);
|
||||
int lpm = 0;
|
||||
if ((err = caster->alloc_port(&lpm)) != srs_success) {
|
||||
return srs_error_wrap(err, "alloc port");
|
||||
}
|
||||
|
||||
SrsRtpConn* rtp = NULL;
|
||||
if (req->stream_id == video_id) {
|
||||
srs_freep(video_rtp);
|
||||
rtp = video_rtp = new SrsRtpConn(this, lpm, video_id);
|
||||
} else {
|
||||
srs_freep(audio_rtp);
|
||||
rtp = audio_rtp = new SrsRtpConn(this, lpm, audio_id);
|
||||
}
|
||||
if ((err = rtp->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtp listen");
|
||||
}
|
||||
srs_trace("rtsp: #%d %s over %s/%s/%s %s client-port=%d-%d, server-port=%d-%d",
|
||||
req->stream_id, (req->stream_id == video_id)? "Video":"Audio",
|
||||
req->transport->transport.c_str(), req->transport->profile.c_str(), req->transport->lower_transport.c_str(),
|
||||
req->transport->cast_type.c_str(), req->transport->client_port_min, req->transport->client_port_max,
|
||||
lpm, lpm + 1);
|
||||
|
||||
// create session.
|
||||
if (session.empty()) {
|
||||
session = "O9EaZ4bf"; // TODO: FIXME: generate session id.
|
||||
}
|
||||
|
||||
SrsRtspSetupResponse* res = new SrsRtspSetupResponse((int)req->seq);
|
||||
res->client_port_min = req->transport->client_port_min;
|
||||
res->client_port_max = req->transport->client_port_max;
|
||||
res->local_port_min = lpm;
|
||||
res->local_port_max = lpm + 1;
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response setup");
|
||||
}
|
||||
} else if (req->is_record()) {
|
||||
SrsRtspResponse* res = new SrsRtspResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response record");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_packet(SrsRtspPacket* pkt, int stream_id)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// ensure rtmp connected.
|
||||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
|
||||
if (stream_id == video_id) {
|
||||
// rtsp tbn is ts tbn.
|
||||
int64_t pts = pkt->timestamp;
|
||||
if ((err = vjitter->correct(pts)) != srs_success) {
|
||||
return srs_error_wrap(err, "jitter");
|
||||
}
|
||||
|
||||
// TODO: FIXME: set dts to pts, please finger out the right dts.
|
||||
int64_t dts = pts;
|
||||
|
||||
return on_rtp_video(pkt, dts, pts);
|
||||
} else {
|
||||
// rtsp tbn is ts tbn.
|
||||
int64_t pts = pkt->timestamp;
|
||||
if ((err = ajitter->correct(pts)) != srs_success) {
|
||||
return srs_error_wrap(err, "jitter");
|
||||
}
|
||||
|
||||
return on_rtp_audio(pkt, pts);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::cycle()
|
||||
{
|
||||
// serve the rtsp client.
|
||||
srs_error_t err = do_cycle();
|
||||
|
||||
caster->remove(this);
|
||||
|
||||
if (err == srs_success) {
|
||||
srs_trace("client finished.");
|
||||
} else if (srs_is_client_gracefully_close(err)) {
|
||||
srs_warn("client disconnect peer. code=%d", srs_error_code(err));
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
if (video_rtp) {
|
||||
caster->free_port(video_rtp->port(), video_rtp->port() + 1);
|
||||
}
|
||||
|
||||
if (audio_rtp) {
|
||||
caster->free_port(audio_rtp->port(), audio_rtp->port() + 1);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_video(SrsRtspPacket* pkt, int64_t dts, int64_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = kickoff_audio_cache(pkt, dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "kickoff audio cache");
|
||||
}
|
||||
|
||||
char* bytes = pkt->payload->bytes();
|
||||
int length = pkt->payload->length();
|
||||
uint32_t fdts = (uint32_t)(dts / 90);
|
||||
uint32_t fpts = (uint32_t)(pts / 90);
|
||||
if ((err = write_h264_ipb_frame(bytes, length, fdts, fpts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write ibp frame");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_audio(SrsRtspPacket* pkt, int64_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = kickoff_audio_cache(pkt, dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "kickoff audio cache");
|
||||
}
|
||||
|
||||
// cache current audio to kickoff.
|
||||
acache->dts = dts;
|
||||
acache->audio = pkt->audio;
|
||||
acache->payload = pkt->payload;
|
||||
|
||||
pkt->audio = NULL;
|
||||
pkt->payload = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::kickoff_audio_cache(SrsRtspPacket* pkt, int64_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// nothing to kick off.
|
||||
if (!acache->payload) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (dts - acache->dts > 0 && acache->audio->nb_samples > 0) {
|
||||
int64_t delta = (dts - acache->dts) / acache->audio->nb_samples;
|
||||
for (int i = 0; i < acache->audio->nb_samples; i++) {
|
||||
char* frame = acache->audio->samples[i].bytes;
|
||||
int nb_frame = acache->audio->samples[i].size;
|
||||
int64_t timestamp = (acache->dts + delta * i) / 90;
|
||||
acodec->aac_packet_type = 1;
|
||||
if ((err = write_audio_raw_frame(frame, nb_frame, acodec, (uint32_t)timestamp)) != srs_success) {
|
||||
return srs_error_wrap(err, "write audio raw frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acache->dts = 0;
|
||||
srs_freep(acache->audio);
|
||||
srs_freep(acache->payload);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_sequence_header()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// use the current dts.
|
||||
int64_t dts = vjitter->timestamp() / 90;
|
||||
|
||||
// send video sps/pps
|
||||
if ((err = write_h264_sps_pps((uint32_t)dts, (uint32_t)dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write sps/pps");
|
||||
}
|
||||
|
||||
// generate audio sh by audio specific config.
|
||||
if (aac_specific_config.empty()) {
|
||||
srs_warn("no audio asc");
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string sh = aac_specific_config;
|
||||
|
||||
SrsFormat* format = new SrsFormat();
|
||||
SrsAutoFree(SrsFormat, format);
|
||||
|
||||
if ((err = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != srs_success) {
|
||||
return srs_error_wrap(err, "on aac sequence header");
|
||||
}
|
||||
|
||||
SrsAudioCodecConfig* dec = format->acodec;
|
||||
|
||||
acodec->sound_format = SrsAudioCodecIdAAC;
|
||||
acodec->sound_type = (dec->aac_channels == 2)? SrsAudioChannelsStereo : SrsAudioChannelsMono;
|
||||
acodec->sound_size = SrsAudioSampleBits16bit;
|
||||
acodec->aac_packet_type = 0;
|
||||
|
||||
static int srs_aac_srates[] = {
|
||||
96000, 88200, 64000, 48000,
|
||||
44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000,
|
||||
7350, 0, 0, 0
|
||||
};
|
||||
switch (srs_aac_srates[dec->aac_sample_rate]) {
|
||||
case 11025:
|
||||
acodec->sound_rate = SrsAudioSampleRate11025;
|
||||
break;
|
||||
case 22050:
|
||||
acodec->sound_rate = SrsAudioSampleRate22050;
|
||||
break;
|
||||
case 44100:
|
||||
acodec->sound_rate = SrsAudioSampleRate44100;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), acodec, (uint32_t)dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write audio raw frame");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_h264_sps_pps(uint32_t dts, uint32_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (h264_sps.empty() || h264_pps.empty()) {
|
||||
srs_warn("no sps=%dB or pps=%dB", (int)h264_sps.size(), (int)h264_pps.size());
|
||||
return err;
|
||||
}
|
||||
|
||||
// h264 raw to h264 packet.
|
||||
std::string sh;
|
||||
if ((err = avc->mux_sequence_header(h264_sps, h264_pps, dts, pts, sh)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux sequence header");
|
||||
}
|
||||
|
||||
// h264 packet to flv packet.
|
||||
int8_t frame_type = SrsVideoAvcFrameTypeKeyFrame;
|
||||
int8_t avc_packet_type = SrsVideoAvcFrameTraitSequenceHeader;
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(sh, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux avc to flv");
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
if ((err = rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "write packet");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// ISO_IEC_14496-10-AVC-2003.pdf, page 44.
|
||||
// 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
|
||||
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(frame[0] & 0x1f);
|
||||
|
||||
// for IDR frame, the frame is keyframe.
|
||||
SrsVideoAvcFrameType frame_type = SrsVideoAvcFrameTypeInterFrame;
|
||||
if (nal_unit_type == SrsAvcNaluTypeIDR) {
|
||||
frame_type = SrsVideoAvcFrameTypeKeyFrame;
|
||||
}
|
||||
|
||||
std::string ibp;
|
||||
if ((err = avc->mux_ipb_frame(frame, frame_size, ibp)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux ibp frame");
|
||||
}
|
||||
|
||||
int8_t avc_packet_type = SrsVideoAvcFrameTraitNALU;
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(ibp, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux avc to flv");
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
return rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
char* data = NULL;
|
||||
int size = 0;
|
||||
if ((err = aac->mux_aac2flv(frame, frame_size, codec, dts, &data, &size)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux aac to flv");
|
||||
}
|
||||
|
||||
return rtmp_write_packet(SrsFrameTypeAudio, dts, data, size);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::rtmp_write_packet(char type, uint32_t timestamp, char* data, int size)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage* msg = NULL;
|
||||
|
||||
if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != srs_success) {
|
||||
return srs_error_wrap(err, "create message");
|
||||
}
|
||||
srs_assert(msg);
|
||||
|
||||
// send out encoded msg.
|
||||
if ((err = sdk->send_and_free_message(msg)) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "write message");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::connect()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Ignore when connected.
|
||||
if (sdk) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// generate rtmp url to connect to.
|
||||
std::string url;
|
||||
if (!req) {
|
||||
std::string schema, host, vhost, app, param;
|
||||
int port;
|
||||
srs_discovery_tc_url(rtsp_tcUrl, schema, host, vhost, app, rtsp_stream, port, param);
|
||||
|
||||
// generate output by template.
|
||||
std::string output = output_template;
|
||||
output = srs_string_replace(output, "[app]", app);
|
||||
output = srs_string_replace(output, "[stream]", rtsp_stream);
|
||||
url = output;
|
||||
}
|
||||
|
||||
// connect host.
|
||||
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk = new SrsSimpleRtmpClient(url, cto, sto);
|
||||
|
||||
if ((err = sdk->connect()) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "connect %s failed, cto=%dms, sto=%dms.", url.c_str(), srsu2msi(cto), srsu2msi(sto));
|
||||
}
|
||||
|
||||
// publish.
|
||||
if ((err = sdk->publish(SRS_CONSTS_RTMP_PROTOCOL_CHUNK_SIZE)) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "publish %s failed", url.c_str());
|
||||
}
|
||||
|
||||
return write_sequence_header();
|
||||
}
|
||||
|
||||
void SrsRtspConn::close()
|
||||
{
|
||||
srs_freep(sdk);
|
||||
}
|
||||
|
||||
SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
|
||||
{
|
||||
// TODO: FIXME: support reload.
|
||||
engine = _srs_config->get_stream_caster_engine(c);
|
||||
output = _srs_config->get_stream_caster_output(c);
|
||||
local_port_min = _srs_config->get_stream_caster_rtp_port_min(c);
|
||||
local_port_max = _srs_config->get_stream_caster_rtp_port_max(c);
|
||||
manager = new SrsResourceManager("CRTSP");
|
||||
}
|
||||
|
||||
SrsRtspCaster::~SrsRtspCaster()
|
||||
{
|
||||
std::vector<SrsRtspConn*>::iterator it;
|
||||
for (it = clients.begin(); it != clients.end(); ++it) {
|
||||
SrsRtspConn* conn = *it;
|
||||
manager->remove(conn);
|
||||
}
|
||||
clients.clear();
|
||||
used_ports.clear();
|
||||
|
||||
srs_freep(manager);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::initialize()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
if ((err = manager->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start manager");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::alloc_port(int* pport)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// use a pair of port.
|
||||
for (int i = local_port_min; i < local_port_max - 1; i += 2) {
|
||||
if (!used_ports[i]) {
|
||||
used_ports[i] = true;
|
||||
used_ports[i + 1] = true;
|
||||
*pport = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
srs_trace("rtsp: %s alloc port=%d-%d", engine.c_str(), *pport, *pport + 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsRtspCaster::free_port(int lpmin, int lpmax)
|
||||
{
|
||||
for (int i = lpmin; i < lpmax; i++) {
|
||||
used_ports[i] = false;
|
||||
}
|
||||
srs_trace("rtsp: %s free rtp port=%d-%d", engine.c_str(), lpmin, lpmax);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::on_tcp_client(srs_netfd_t stfd)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsRtspConn* conn = new SrsRtspConn(this, stfd, output);
|
||||
|
||||
if ((err = conn->serve()) != srs_success) {
|
||||
srs_freep(conn);
|
||||
return srs_error_wrap(err, "serve conn");
|
||||
}
|
||||
|
||||
clients.push_back(conn);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsRtspCaster::remove(SrsRtspConn* conn)
|
||||
{
|
||||
std::vector<SrsRtspConn*>::iterator it = find(clients.begin(), clients.end(), conn);
|
||||
if (it != clients.end()) {
|
||||
clients.erase(it);
|
||||
}
|
||||
srs_info("rtsp: remove connection from caster.");
|
||||
|
||||
manager->remove(conn);
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2013-2021 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_RTSP_HPP
|
||||
#define SRS_APP_RTSP_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_service_conn.hpp>
|
||||
|
||||
class SrsStSocket;
|
||||
class SrsRtspConn;
|
||||
class SrsRtspStack;
|
||||
class SrsRtspCaster;
|
||||
class SrsConfDirective;
|
||||
class SrsRtspPacket;
|
||||
class SrsRequest;
|
||||
class SrsStSocket;
|
||||
class SrsRtmpClient;
|
||||
class SrsRawH264Stream;
|
||||
class SrsRawAacStream;
|
||||
struct SrsRawAacStreamCodec;
|
||||
class SrsSharedPtrMessage;
|
||||
class SrsAudioFrame;
|
||||
class SrsSimpleStream;
|
||||
class SrsPithyPrint;
|
||||
class SrsSimpleRtmpClient;
|
||||
class SrsResourceManager;
|
||||
|
||||
// A rtp connection which transport a stream.
|
||||
class SrsRtpConn: public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsPithyPrint* pprint;
|
||||
SrsUdpListener* listener;
|
||||
SrsRtspConn* rtsp;
|
||||
SrsRtspPacket* cache;
|
||||
int stream_id;
|
||||
int _port;
|
||||
public:
|
||||
SrsRtpConn(SrsRtspConn* r, int p, int sid);
|
||||
virtual ~SrsRtpConn();
|
||||
public:
|
||||
virtual int port();
|
||||
virtual srs_error_t listen();
|
||||
// Interface ISrsUdpHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||
};
|
||||
|
||||
// The audio cache, audio is grouped by frames.
|
||||
struct SrsRtspAudioCache
|
||||
{
|
||||
int64_t dts;
|
||||
SrsAudioFrame* audio;
|
||||
SrsSimpleStream* payload;
|
||||
|
||||
SrsRtspAudioCache();
|
||||
virtual ~SrsRtspAudioCache();
|
||||
};
|
||||
|
||||
// The time jitter correct for rtsp.
|
||||
class SrsRtspJitter
|
||||
{
|
||||
private:
|
||||
int64_t previous_timestamp;
|
||||
int64_t pts;
|
||||
int delta;
|
||||
public:
|
||||
SrsRtspJitter();
|
||||
virtual ~SrsRtspJitter();
|
||||
public:
|
||||
virtual int64_t timestamp();
|
||||
virtual srs_error_t correct(int64_t& ts);
|
||||
};
|
||||
|
||||
// The rtsp connection serve the fd.
|
||||
class SrsRtspConn : public ISrsCoroutineHandler, public ISrsConnection
|
||||
{
|
||||
private:
|
||||
std::string output_template;
|
||||
std::string rtsp_tcUrl;
|
||||
std::string rtsp_stream;
|
||||
private:
|
||||
std::string session;
|
||||
// video stream.
|
||||
int video_id;
|
||||
std::string video_codec;
|
||||
SrsRtpConn* video_rtp;
|
||||
// audio stream.
|
||||
int audio_id;
|
||||
std::string audio_codec;
|
||||
int audio_sample_rate;
|
||||
int audio_channel;
|
||||
SrsRtpConn* audio_rtp;
|
||||
private:
|
||||
srs_netfd_t stfd;
|
||||
SrsStSocket* skt;
|
||||
SrsRtspStack* rtsp;
|
||||
SrsRtspCaster* caster;
|
||||
SrsCoroutine* trd;
|
||||
private:
|
||||
SrsRequest* req;
|
||||
SrsSimpleRtmpClient* sdk;
|
||||
SrsRtspJitter* vjitter;
|
||||
SrsRtspJitter* ajitter;
|
||||
private:
|
||||
SrsRawH264Stream* avc;
|
||||
std::string h264_sps;
|
||||
std::string h264_pps;
|
||||
private:
|
||||
SrsRawAacStream* aac;
|
||||
SrsRawAacStreamCodec* acodec;
|
||||
std::string aac_specific_config;
|
||||
SrsRtspAudioCache* acache;
|
||||
public:
|
||||
SrsRtspConn(SrsRtspCaster* c, srs_netfd_t fd, std::string o);
|
||||
virtual ~SrsRtspConn();
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
// Interface ISrsConnection.
|
||||
public:
|
||||
virtual std::string remote_ip();
|
||||
virtual const SrsContextId& get_id();
|
||||
virtual std::string desc();
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
// internal methods
|
||||
public:
|
||||
virtual srs_error_t on_rtp_packet(SrsRtspPacket* pkt, int stream_id);
|
||||
// Interface ISrsOneCycleThreadHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
private:
|
||||
virtual srs_error_t on_rtp_video(SrsRtspPacket* pkt, int64_t dts, int64_t pts);
|
||||
virtual srs_error_t on_rtp_audio(SrsRtspPacket* pkt, int64_t dts);
|
||||
virtual srs_error_t kickoff_audio_cache(SrsRtspPacket* pkt, int64_t dts);
|
||||
private:
|
||||
virtual srs_error_t write_sequence_header();
|
||||
virtual srs_error_t write_h264_sps_pps(uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts);
|
||||
virtual srs_error_t rtmp_write_packet(char type, uint32_t timestamp, char* data, int size);
|
||||
private:
|
||||
// Connect to RTMP server.
|
||||
virtual srs_error_t connect();
|
||||
// Close the connection to RTMP server.
|
||||
virtual void close();
|
||||
};
|
||||
|
||||
// The caster for rtsp.
|
||||
class SrsRtspCaster : public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
std::string engine;
|
||||
std::string output;
|
||||
int local_port_min;
|
||||
int local_port_max;
|
||||
// The key: port, value: whether used.
|
||||
std::map<int, bool> used_ports;
|
||||
private:
|
||||
std::vector<SrsRtspConn*> clients;
|
||||
SrsResourceManager* manager;
|
||||
public:
|
||||
SrsRtspCaster(SrsConfDirective* c);
|
||||
virtual ~SrsRtspCaster();
|
||||
public:
|
||||
// Alloc a rtp port from local ports pool.
|
||||
// @param pport output the rtp port.
|
||||
virtual srs_error_t alloc_port(int* pport);
|
||||
// Free the alloced rtp port.
|
||||
virtual void free_port(int lpmin, int lpmax);
|
||||
virtual srs_error_t initialize();
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
// internal methods.
|
||||
public:
|
||||
virtual void remove(SrsRtspConn* conn);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
class SrsConfDirective;
|
||||
|
||||
// The security apply on vhost.
|
||||
// @see https://github.com/ossrs/srs/issues/211
|
||||
class SrsSecurity
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -30,7 +30,6 @@ using namespace std;
|
|||
#include <srs_app_utility.hpp>
|
||||
#include <srs_app_heartbeat.hpp>
|
||||
#include <srs_app_mpegts_udp.hpp>
|
||||
#include <srs_app_rtsp.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
#include <srs_app_caster_flv.hpp>
|
||||
#include <srs_kernel_consts.hpp>
|
||||
|
@ -53,8 +52,6 @@ std::string srs_listener_type2string(SrsListenerType type)
|
|||
return "HTTP-Server";
|
||||
case SrsListenerMpegTsOverUdp:
|
||||
return "MPEG-TS over UDP";
|
||||
case SrsListenerRtsp:
|
||||
return "RTSP";
|
||||
case SrsListenerFlv:
|
||||
return "HTTP-FLV";
|
||||
default:
|
||||
|
@ -119,62 +116,6 @@ srs_error_t SrsBufferListener::on_tcp_client(srs_netfd_t stfd)
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
SrsRtspListener::SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
|
||||
{
|
||||
listener = NULL;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(type == SrsListenerRtsp);
|
||||
if (type == SrsListenerRtsp) {
|
||||
caster = new SrsRtspCaster(c);
|
||||
|
||||
// TODO: FIXME: Must check error.
|
||||
caster->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
SrsRtspListener::~SrsRtspListener()
|
||||
{
|
||||
srs_freep(caster);
|
||||
srs_freep(listener);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspListener::listen(string i, int p)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(type == SrsListenerRtsp);
|
||||
|
||||
ip = i;
|
||||
port = p;
|
||||
|
||||
srs_freep(listener);
|
||||
listener = new SrsTcpListener(this, ip, port);
|
||||
|
||||
if ((err = listener->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp listen %s:%d", ip.c_str(), port);
|
||||
}
|
||||
|
||||
string v = srs_listener_type2string(type);
|
||||
srs_trace("%s listen at tcp://%s:%d, fd=%d", v.c_str(), ip.c_str(), port, listener->fd());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspListener::on_tcp_client(srs_netfd_t stfd)
|
||||
{
|
||||
srs_error_t err = caster->on_tcp_client(stfd);
|
||||
if (err != srs_success) {
|
||||
srs_warn("accept client failed, err is %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
|
||||
{
|
||||
listener = NULL;
|
||||
|
@ -629,7 +570,6 @@ void SrsServer::dispose()
|
|||
close_listeners(SrsListenerHttpStream);
|
||||
close_listeners(SrsListenerHttpsStream);
|
||||
close_listeners(SrsListenerMpegTsOverUdp);
|
||||
close_listeners(SrsListenerRtsp);
|
||||
close_listeners(SrsListenerFlv);
|
||||
|
||||
// Fast stop to notify FFMPEG to quit, wait for a while then fast kill.
|
||||
|
@ -656,7 +596,6 @@ void SrsServer::gracefully_dispose()
|
|||
close_listeners(SrsListenerHttpStream);
|
||||
close_listeners(SrsListenerHttpsStream);
|
||||
close_listeners(SrsListenerMpegTsOverUdp);
|
||||
close_listeners(SrsListenerRtsp);
|
||||
close_listeners(SrsListenerFlv);
|
||||
srs_trace("listeners closed");
|
||||
|
||||
|
@ -1359,9 +1298,6 @@ srs_error_t SrsServer::listen_stream_caster()
|
|||
std::string caster = _srs_config->get_stream_caster_engine(stream_caster);
|
||||
if (srs_stream_caster_is_udp(caster)) {
|
||||
listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster);
|
||||
} else if (srs_stream_caster_is_rtsp(caster)) {
|
||||
srs_warn("It's deprecated and will be removed in the future, see https://github.com/ossrs/srs/issues/2304#issuecomment-826009290");
|
||||
listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster);
|
||||
} else if (srs_stream_caster_is_flv(caster)) {
|
||||
listener = new SrsHttpFlvListener(this, SrsListenerFlv, stream_caster);
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,6 @@ class ISrsUdpHandler;
|
|||
class SrsUdpListener;
|
||||
class SrsTcpListener;
|
||||
class SrsAppCasterFlv;
|
||||
class SrsRtspCaster;
|
||||
class SrsResourceManager;
|
||||
class SrsLatestVersion;
|
||||
|
||||
|
@ -50,8 +49,6 @@ enum SrsListenerType
|
|||
SrsListenerHttpStream = 2,
|
||||
// UDP stream, MPEG-TS over udp.
|
||||
SrsListenerMpegTsOverUdp = 3,
|
||||
// TCP stream, RTSP stream.
|
||||
SrsListenerRtsp = 4,
|
||||
// TCP stream, FLV stream over HTTP.
|
||||
SrsListenerFlv = 5,
|
||||
// HTTPS api,
|
||||
|
@ -92,22 +89,6 @@ public:
|
|||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// A TCP listener, for rtsp server.
|
||||
class SrsRtspListener : public SrsListener, public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
SrsTcpListener* listener;
|
||||
SrsRtspCaster* caster;
|
||||
public:
|
||||
SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
|
||||
virtual ~SrsRtspListener();
|
||||
public:
|
||||
virtual srs_error_t listen(std::string i, int p);
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// A TCP listener, for flv stream server.
|
||||
class SrsHttpFlvListener : public SrsListener, public ISrsTcpHandler
|
||||
{
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 4
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 167
|
||||
#define VERSION_REVISION 171
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1078,10 +1078,57 @@ srs_error_t SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp)
|
|||
if ((err = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != srs_success) {
|
||||
return srs_error_wrap(err, "read pic_height_in_map_units_minus1");;
|
||||
}
|
||||
|
||||
vcodec->width = (int)(pic_width_in_mbs_minus1 + 1) * 16;
|
||||
vcodec->height = (int)(pic_height_in_map_units_minus1 + 1) * 16;
|
||||
|
||||
|
||||
int8_t frame_mbs_only_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, frame_mbs_only_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_mbs_only_flag");;
|
||||
}
|
||||
if(!frame_mbs_only_flag) {
|
||||
/* Skip mb_adaptive_frame_field_flag */
|
||||
int8_t mb_adaptive_frame_field_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, mb_adaptive_frame_field_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read mb_adaptive_frame_field_flag");;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip direct_8x8_inference_flag */
|
||||
int8_t direct_8x8_inference_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, direct_8x8_inference_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read direct_8x8_inference_flag");;
|
||||
}
|
||||
|
||||
/* We need the following value to evaluate offsets, if any */
|
||||
int8_t frame_cropping_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, frame_cropping_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_cropping_flag");;
|
||||
}
|
||||
int32_t frame_crop_left_offset = 0, frame_crop_right_offset = 0,
|
||||
frame_crop_top_offset = 0, frame_crop_bottom_offset = 0;
|
||||
if(frame_cropping_flag) {
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_left_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_left_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_right_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_right_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_top_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_top_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_bottom_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_bottom_offset");;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip vui_parameters_present_flag */
|
||||
int8_t vui_parameters_present_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, vui_parameters_present_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read vui_parameters_present_flag");;
|
||||
}
|
||||
|
||||
vcodec->width = ((pic_width_in_mbs_minus1 + 1) * 16) - frame_crop_left_offset * 2 - frame_crop_right_offset * 2;
|
||||
vcodec->height = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) \
|
||||
- (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_kernel_mp3.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
@ -120,7 +119,6 @@ srs_utime_t srs_update_system_time()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// @see: https://github.com/ossrs/srs/issues/35
|
||||
// we must convert the tv_sec/tv_usec to int64_t.
|
||||
int64_t now_us = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec;
|
||||
|
||||
|
@ -140,7 +138,6 @@ srs_utime_t srs_update_system_time()
|
|||
diff = srs_max(0, diff);
|
||||
if (diff < 0 || diff > 1000 * SYS_TIME_RESOLUTION_US) {
|
||||
srs_warn("clock jump, history=%" PRId64 "us, now=%" PRId64 "us, diff=%" PRId64 "us", _srs_system_time_us_cache, now_us, diff);
|
||||
// @see: https://github.com/ossrs/srs/issues/109
|
||||
_srs_system_time_startup_time += diff;
|
||||
}
|
||||
|
||||
|
@ -580,7 +577,6 @@ int srs_do_create_dir_recursively(string dir)
|
|||
}
|
||||
|
||||
// create curren dir.
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifdef _WIN32
|
||||
if (::_mkdir(dir.c_str()) < 0) {
|
||||
#else
|
||||
|
|
|
@ -49,6 +49,7 @@ using namespace std;
|
|||
|
||||
// pre-declare
|
||||
srs_error_t run_directly_or_daemon();
|
||||
srs_error_t srs_detect_docker();
|
||||
srs_error_t run_hybrid_server();
|
||||
void show_macro_features();
|
||||
|
||||
|
@ -95,6 +96,11 @@ srs_error_t do_main(int argc, char** argv)
|
|||
#ifdef SRS_GPERF_MP
|
||||
#warning "gmp is not used for memory leak, please use gmc instead."
|
||||
#endif
|
||||
|
||||
// Ignore any error while detecting docker.
|
||||
if ((err = srs_detect_docker()) != srs_success) {
|
||||
srs_error_reset(err);
|
||||
}
|
||||
|
||||
// never use srs log(srs_trace, srs_error, etc) before config parse the option,
|
||||
// which will load the log config and apply it.
|
||||
|
@ -378,11 +384,6 @@ srs_error_t run_directly_or_daemon()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Ignore any error while detecting docker.
|
||||
if ((err = srs_detect_docker()) != srs_success) {
|
||||
srs_error_reset(err);
|
||||
}
|
||||
|
||||
// Load daemon from config, disable it for docker.
|
||||
// @see https://github.com/ossrs/srs/issues/1594
|
||||
bool run_as_daemon = _srs_config->get_daemon();
|
||||
|
|
|
@ -167,7 +167,6 @@ srs_error_t SrsFastStream::grow(ISrsReader* reader, int required_size)
|
|||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
if (merged_read && _handler) {
|
||||
_handler->on_read(nread);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
@ -349,7 +348,6 @@ srs_error_t srs_write_large_iovs(ISrsProtocolReadWriter* skt, iovec* iovs, int s
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// the limits of writev iovs.
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
// for linux, generally it's 1024.
|
||||
static int limits = (int)sysconf(_SC_IOV_MAX);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
|
|
@ -281,7 +281,6 @@ srs_error_t SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* p
|
|||
// decode the ADTS.
|
||||
// @see ISO_IEC_13818-7-AAC-2004.pdf, page 26
|
||||
// 6.2 Audio Data Transport Stream, ADTS
|
||||
// @see https://github.com/ossrs/srs/issues/212#issuecomment-64145885
|
||||
// byte_alignment()
|
||||
|
||||
// adts_fixed_header:
|
||||
|
@ -342,7 +341,7 @@ srs_error_t SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* p
|
|||
int8_t channel_configuration = (sfiv >> 6) & 0x07;
|
||||
/*int8_t original = (sfiv >> 5) & 0x01;*/
|
||||
/*int8_t home = (sfiv >> 4) & 0x01;*/
|
||||
//int8_t Emphasis; @remark, Emphasis is removed, @see https://github.com/ossrs/srs/issues/212#issuecomment-64154736
|
||||
//int8_t Emphasis; @remark, Emphasis is removed
|
||||
// 4bits left.
|
||||
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
||||
// copyright_identification_bit 1 bslbf
|
||||
|
|
|
@ -571,7 +571,6 @@ namespace srs_internal
|
|||
}
|
||||
|
||||
// directly generate the public key.
|
||||
// @see: https://github.com/ossrs/srs/issues/148
|
||||
int pkey_size = 128;
|
||||
if ((err = dh.copy_shared_key(c1->get_key(), 128, key.key, pkey_size)) != srs_success) {
|
||||
return srs_error_wrap(err, "copy shared key");
|
||||
|
|
|
@ -1036,7 +1036,6 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
// 0x04 where: message_type=4(protocol control user-control message)
|
||||
// 0x00 0x06 where: event Ping(0x06)
|
||||
// 0x00 0x00 0x0d 0x0f where: event data 4bytes ping timestamp.
|
||||
// @see: https://github.com/ossrs/srs/issues/98
|
||||
if (fmt == RTMP_FMT_TYPE1) {
|
||||
srs_warn("fresh chunk starts with fmt=1");
|
||||
} else {
|
||||
|
@ -1175,7 +1174,6 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
pp[0] = *p++;
|
||||
|
||||
// always use 31bits timestamp, for some server may use 32bits extended timestamp.
|
||||
// @see https://github.com/ossrs/srs/issues/111
|
||||
timestamp &= 0x7fffffff;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// For srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
@ -161,7 +160,6 @@ private:
|
|||
std::map<int, SrsChunkStream*> chunk_streams;
|
||||
// Cache some frequently used chunk header.
|
||||
// cs_cache, the chunk stream cache.
|
||||
// @see https://github.com/ossrs/srs/issues/249
|
||||
SrsChunkStream** cs_cache;
|
||||
// The bytes buffer cache, recv from skt, provide services for stream.
|
||||
SrsFastStream* in_buffer;
|
||||
|
@ -179,7 +177,6 @@ private:
|
|||
bool show_debug_info;
|
||||
// Whether auto response when recv messages.
|
||||
// default to true for it's very easy to use the protocol stack.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
bool auto_response_when_recv;
|
||||
// When not auto response message, manual flush the messages in queue.
|
||||
std::vector<SrsPacket*> manual_response_queue;
|
||||
|
@ -208,7 +205,6 @@ public:
|
|||
public:
|
||||
// Set the auto response message when recv for protocol stack.
|
||||
// @param v, whether auto response message when recv message.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
virtual void set_auto_response(bool v);
|
||||
// Flush for manual response when the auto response is disabled
|
||||
// by set_auto_response(false), we default use auto response, so donot
|
||||
|
@ -222,13 +218,11 @@ public:
|
|||
// that is, we merge some data to read together.
|
||||
// @param v true to ename merged read.
|
||||
// @param handler the handler when merge read is enabled.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_merge_read(bool v, IMergeReadHandler* handler);
|
||||
// Create buffer with specifeid size.
|
||||
// @param buffer the size of buffer.
|
||||
// @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
// @remark when buffer changed, the previous ptr maybe invalid.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_recv_buffer(int buffer_size);
|
||||
#endif
|
||||
public:
|
||||
|
@ -429,7 +423,6 @@ public:
|
|||
std::string stream;
|
||||
// For play live stream,
|
||||
// used to specified the stop when exceed the duration.
|
||||
// @see https://github.com/ossrs/srs/issues/45
|
||||
// in srs_utime_t.
|
||||
srs_utime_t duration;
|
||||
// The token in the connect request,
|
||||
|
@ -620,7 +613,6 @@ public:
|
|||
public:
|
||||
// Set the auto response message when recv for protocol stack.
|
||||
// @param v, whether auto response message when recv message.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
virtual void set_auto_response(bool v);
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
// To improve read performance, merge some packets then read,
|
||||
|
@ -628,13 +620,11 @@ public:
|
|||
// that is, we merge some data to read together.
|
||||
// @param v true to ename merged read.
|
||||
// @param handler the handler when merge read is enabled.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_merge_read(bool v, IMergeReadHandler* handler);
|
||||
// Create buffer with specifeid size.
|
||||
// @param buffer the size of buffer.
|
||||
// @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
// @remark when buffer changed, the previous ptr maybe invalid.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_recv_buffer(int buffer_size);
|
||||
#endif
|
||||
// To set/get the recv timeout in srs_utime_t.
|
||||
|
@ -675,7 +665,6 @@ public:
|
|||
// @param stream_id, the stream id of packet to send over, 0 for control message.
|
||||
//
|
||||
// @remark performance issue, to support 6k+ 250kbps client,
|
||||
// @see https://github.com/ossrs/srs/issues/194
|
||||
virtual srs_error_t send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id);
|
||||
// Send the RTMP packet and always free it.
|
||||
// user must never free or use the packet after this method,
|
||||
|
@ -1336,11 +1325,9 @@ public:
|
|||
// Name of command. Set to "|RtmpSampleAccess".
|
||||
std::string command_name;
|
||||
// Whether allow access the sample of video.
|
||||
// @see: https://github.com/ossrs/srs/issues/49
|
||||
// @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#videoSampleAccess
|
||||
bool video_sample_access;
|
||||
// Whether allow access the sample of audio.
|
||||
// @see: https://github.com/ossrs/srs/issues/49
|
||||
// @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#audioSampleAccess
|
||||
bool audio_sample_access;
|
||||
public:
|
||||
|
|
|
@ -97,7 +97,6 @@ srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug)
|
|||
}
|
||||
|
||||
// notify server the edge identity,
|
||||
// @see https://github.com/ossrs/srs/issues/147
|
||||
SrsAmf0Object* data = req->args;
|
||||
data->set("srs_sig", SrsAmf0Any::str(RTMP_SIG_SRS_KEY));
|
||||
data->set("srs_server", SrsAmf0Any::str(RTMP_SIG_SRS_SERVER));
|
||||
|
@ -121,7 +120,6 @@ srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug)
|
|||
req->tcUrl = tc_url;
|
||||
|
||||
// upnode server identity will show in the connect_app of client.
|
||||
// @see https://github.com/ossrs/srs/issues/160
|
||||
// the debug_srs_upnode is config in vhost and default to true.
|
||||
SrsServerInfo si;
|
||||
if ((err = client->connect_app(req->app, tc_url, req, debug, &si)) != srs_success) {
|
||||
|
|
|
@ -41,7 +41,6 @@ srs_error_t srs_st_init()
|
|||
{
|
||||
#ifdef __linux__
|
||||
// check epoll, some old linux donot support epoll.
|
||||
// @see https://github.com/ossrs/srs/issues/162
|
||||
if (!srs_st_epoll_is_supported()) {
|
||||
return srs_error_new(ERROR_ST_SET_EPOLL, "linux epoll disabled");
|
||||
}
|
||||
|
@ -510,7 +509,6 @@ srs_error_t SrsStSocket::read(void* buf, size_t size, ssize_t* nread)
|
|||
// (a value of 0 means the network connection is closed or end of file is reached).
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_read <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_read < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "timeout %d ms", srsu2msi(rtm));
|
||||
}
|
||||
|
@ -546,7 +544,6 @@ srs_error_t SrsStSocket::read_fully(void* buf, size_t size, ssize_t* nread)
|
|||
// (a value less than nbyte means the network connection is closed or end of file is reached)
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_read != (ssize_t)size) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_read < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "timeout %d ms", srsu2msi(rtm));
|
||||
}
|
||||
|
@ -581,7 +578,6 @@ srs_error_t SrsStSocket::write(void* buf, size_t size, ssize_t* nwrite)
|
|||
// On success a non-negative integer equal to nbyte is returned.
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_write <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_write < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "write timeout %d ms", srsu2msi(stm));
|
||||
}
|
||||
|
@ -612,7 +608,6 @@ srs_error_t SrsStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
|||
// On success a non-negative integer equal to nbyte is returned.
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_write <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_write < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "writev timeout %d ms", srsu2msi(stm));
|
||||
}
|
||||
|
|
|
@ -2162,9 +2162,6 @@ VOID TEST(ConfigUnitTest, OperatorEquals)
|
|||
EXPECT_TRUE(srs_stream_caster_is_udp("mpegts_over_udp"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_udp("xxx"));
|
||||
|
||||
EXPECT_TRUE(srs_stream_caster_is_rtsp("rtsp"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_rtsp("xxx"));
|
||||
|
||||
EXPECT_TRUE(srs_stream_caster_is_flv("flv"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_flv("xxx"));
|
||||
|
||||
|
|
|
@ -727,7 +727,6 @@ VOID TEST(ProtocolStackTest, ProtocolRecvMessage)
|
|||
// 0x04 where: message_type=4(protocol control user-control message)
|
||||
// 0x00 0x06 where: event Ping(0x06)
|
||||
// 0x00 0x00 0x0d 0x0f where: event data 4bytes ping timestamp.
|
||||
// @see: https://github.com/ossrs/srs/issues/98
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvMessageBug98)
|
||||
{
|
||||
MockBufferIO bio;
|
||||
|
@ -3824,7 +3823,6 @@ VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage2)
|
|||
* always use 31bits timestamp.
|
||||
*/
|
||||
// always use 31bits timestamp, for some server may use 32bits extended timestamp.
|
||||
// @see https://github.com/ossrs/srs/issues/111
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage3)
|
||||
{
|
||||
MockBufferIO bio;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue