mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #179, dvr suport vhost/app/stream level control. 2.0.125.
This commit is contained in:
parent
1cb8e44b1b
commit
b903a7b436
7 changed files with 72 additions and 15 deletions
|
@ -532,6 +532,7 @@ Supported operating systems and hardware:
|
||||||
|
|
||||||
### SRS 2.0 history
|
### SRS 2.0 history
|
||||||
|
|
||||||
|
* v2.0, 2015-02-24, for [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), dvr suport vhost/app/stream level control. 2.0.125.
|
||||||
* v2.0, 2015-02-24, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), fix hls bug, write pts/dts error. 2.0.124.
|
* v2.0, 2015-02-24, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), fix hls bug, write pts/dts error. 2.0.124.
|
||||||
* v2.0, 2015-02-24, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), support dvr http api. 2.0.123.
|
* v2.0, 2015-02-24, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), support dvr http api. 2.0.123.
|
||||||
* v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122.
|
* v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122.
|
||||||
|
|
|
@ -293,19 +293,24 @@ vhost dvr.srs.com {
|
||||||
# http url to control dvr, for example, http://dev:1985/api/v1/dvrs
|
# http url to control dvr, for example, http://dev:1985/api/v1/dvrs
|
||||||
# method=GET
|
# method=GET
|
||||||
# to query dvrs of server.
|
# to query dvrs of server.
|
||||||
# request params, for example ?vhost=__defaultVhost__, where:
|
# request params, for example ?vhost=__defaultVhost__&&app=live&&stream=livestream, where:
|
||||||
# vhost, query all dvr of this vhost.
|
# vhost, <required>, query all dvr of this vhost.
|
||||||
|
# app, [optinal], query all dvr of this app. query all app if not specified.
|
||||||
|
# stream, [optional], query specified dvr stream. query all stream if not specified.
|
||||||
# response in json, where:
|
# response in json, where:
|
||||||
# {code:0, dvrs: [{path_tmpl:"./[15].[04].[05].[999].flv", path_dvr:"./22.7.43.312.flv",
|
# {code:0, dvrs: [{path_tmpl:"./[15].[04].[05].[999].flv", path_dvr:"./22.7.43.312.flv",
|
||||||
# wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs",
|
# vhost:"__defaultVhost", app:"live", stream:"livestream",
|
||||||
|
# wait_keyframe:true, callback:"http://127.0.0.1:8085/api/v1/dvrs",
|
||||||
# status:"stop"|"start"
|
# status:"stop"|"start"
|
||||||
# }]}
|
# }]}
|
||||||
# method=POST
|
# method=POST
|
||||||
# to start dvr of specified vhost.
|
# to start dvr of specified vhost.
|
||||||
# request should encode in json, specifies the dvr to create, where:
|
# request should encode in json, specifies the dvr to create, where:
|
||||||
# {path_tmpl:"./[15].[04].[05].[999].flv",
|
# {path_tmpl:"./[15].[04].[05].[999].flv",
|
||||||
# wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs"
|
# vhost:"__defaultVhost", app:"live", stream:"livestream",
|
||||||
|
# wait_keyframe:true, callback:"http://127.0.0.1:8085/api/v1/dvrs"
|
||||||
# }
|
# }
|
||||||
|
# @remark, the app and stream is optional.
|
||||||
# response in json, where:
|
# response in json, where:
|
||||||
# {code:0}
|
# {code:0}
|
||||||
# method=DELETE, to stop dvr
|
# method=DELETE, to stop dvr
|
||||||
|
@ -316,7 +321,10 @@ vhost dvr.srs.com {
|
||||||
# {code:0}
|
# {code:0}
|
||||||
# method=PUT, use as RPC(remote process call).
|
# method=PUT, use as RPC(remote process call).
|
||||||
# reap_segment, the request params in json, where:
|
# reap_segment, the request params in json, where:
|
||||||
# {action:"reap_segment", vhost:"__defaultVhost", path_tmpl:"./[15].[04].[05].[999].flv"}
|
# {action:"reap_segment", vhost:"__defaultVhost", app:"live", stream:"livestream",
|
||||||
|
# path_tmpl:"./[15].[04].[05].[999].flv"
|
||||||
|
# }
|
||||||
|
# @remark, the app and stream is optional.
|
||||||
# when reap segment, the callback POST request in json:
|
# when reap segment, the callback POST request in json:
|
||||||
# {action:"on_dvr_reap_segment", client_id:100, vhost:"__defaultVhost__",
|
# {action:"on_dvr_reap_segment", client_id:100, vhost:"__defaultVhost__",
|
||||||
# app:"live", stream:"livestream", cwd:"/home/winlin/srs", file:"./dvr.flv"
|
# app:"live", stream:"livestream", cwd:"/home/winlin/srs", file:"./dvr.flv"
|
||||||
|
|
|
@ -1078,6 +1078,8 @@ int SrsDvrApiPlan::dumps(stringstream& ss)
|
||||||
<< __SRS_JFIELD_STR("path_dvr", segment->get_path()) << __SRS_JFIELD_CONT
|
<< __SRS_JFIELD_STR("path_dvr", segment->get_path()) << __SRS_JFIELD_CONT
|
||||||
<< __SRS_JFIELD_BOOL("wait_keyframe", wait_keyframe) << __SRS_JFIELD_CONT
|
<< __SRS_JFIELD_BOOL("wait_keyframe", wait_keyframe) << __SRS_JFIELD_CONT
|
||||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("stream", req->stream) << __SRS_JFIELD_CONT
|
||||||
<< __SRS_JFIELD_STR("callback", callback) << __SRS_JFIELD_CONT
|
<< __SRS_JFIELD_STR("callback", callback) << __SRS_JFIELD_CONT
|
||||||
<< __SRS_JFIELD_STR("status", (dvr_enabled? "start":"stop"))
|
<< __SRS_JFIELD_STR("status", (dvr_enabled? "start":"stop"))
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
@ -1482,7 +1484,7 @@ int SrsApiDvrPool::add_dvr(SrsDvrApiPlan* dvr)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsApiDvrPool::dumps(string vhost, stringstream& ss)
|
int SrsApiDvrPool::dumps(string vhost, string app, string stream, stringstream& ss)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -1494,6 +1496,12 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss)
|
||||||
if (!vhost.empty() && plan->req->vhost != vhost) {
|
if (!vhost.empty() && plan->req->vhost != vhost) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!app.empty() && plan->req->app != app) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!stream.empty() && plan->req->stream != stream) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
plans.push_back(plan);
|
plans.push_back(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,7 +1512,7 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < (int)dvrs.size() - 1) {
|
if (i < (int)plans.size() - 1) {
|
||||||
ss << __SRS_JFIELD_CONT;
|
ss << __SRS_JFIELD_CONT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1534,19 +1542,33 @@ int SrsApiDvrPool::create(SrsJsonAny* json)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string vhost = prop->to_str();
|
std::string vhost = prop->to_str();
|
||||||
|
std::string app, stream;
|
||||||
|
if ((prop = obj->ensure_property_string("app")) != NULL) {
|
||||||
|
app = prop->to_str();
|
||||||
|
}
|
||||||
|
if ((prop = obj->ensure_property_string("stream")) != NULL) {
|
||||||
|
stream = prop->to_str();
|
||||||
|
}
|
||||||
|
|
||||||
SrsDvrApiPlan* dvr = NULL;
|
SrsDvrApiPlan* dvr = NULL;
|
||||||
for (int i = 0; i < (int)dvrs.size(); i++) {
|
for (int i = 0; i < (int)dvrs.size(); i++) {
|
||||||
SrsDvrApiPlan* plan = dvrs.at(i);
|
SrsDvrApiPlan* plan = dvrs.at(i);
|
||||||
if (!vhost.empty() && plan->req->vhost != vhost) {
|
if (!vhost.empty() && plan->req->vhost != vhost) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!app.empty() && plan->req->app != app) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!stream.empty() && plan->req->stream != stream) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
dvr = plan;
|
dvr = plan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dvr) {
|
if (!dvr) {
|
||||||
ret = ERROR_HTTP_DVR_CREATE_REQUEST;
|
ret = ERROR_HTTP_DVR_NO_TAEGET;
|
||||||
srs_error("dvr: api create dvr request vhost invalid. vhost=%s. ret=%d", vhost.c_str(), ret);
|
srs_error("dvr: create not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,7 +1592,7 @@ int SrsApiDvrPool::create(SrsJsonAny* json)
|
||||||
return dvr->start();
|
return dvr->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsApiDvrPool::stop(string vhost)
|
int SrsApiDvrPool::stop(string vhost, string app, string stream)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -1580,9 +1602,21 @@ int SrsApiDvrPool::stop(string vhost)
|
||||||
if (!vhost.empty() && plan->req->vhost != vhost) {
|
if (!vhost.empty() && plan->req->vhost != vhost) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!app.empty() && plan->req->app != app) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!stream.empty() && plan->req->stream != stream) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
plans.push_back(plan);
|
plans.push_back(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plans.empty()) {
|
||||||
|
ret = ERROR_HTTP_DVR_NO_TAEGET;
|
||||||
|
srs_error("dvr: stop not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < (int)plans.size(); i++) {
|
for (int i = 0; i < (int)plans.size(); i++) {
|
||||||
SrsDvrApiPlan* plan = plans.at(i);
|
SrsDvrApiPlan* plan = plans.at(i);
|
||||||
|
|
||||||
|
@ -1613,6 +1647,13 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
std::string vhost = prop->to_str();
|
std::string vhost = prop->to_str();
|
||||||
|
std::string app, stream;
|
||||||
|
if ((prop = obj->ensure_property_string("app")) != NULL) {
|
||||||
|
app = prop->to_str();
|
||||||
|
}
|
||||||
|
if ((prop = obj->ensure_property_string("stream")) != NULL) {
|
||||||
|
stream = prop->to_str();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<SrsDvrApiPlan*> plans;
|
std::vector<SrsDvrApiPlan*> plans;
|
||||||
for (int i = 0; i < (int)dvrs.size(); i++) {
|
for (int i = 0; i < (int)dvrs.size(); i++) {
|
||||||
|
@ -1623,6 +1664,12 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json)
|
||||||
plans.push_back(plan);
|
plans.push_back(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plans.empty()) {
|
||||||
|
ret = ERROR_HTTP_DVR_NO_TAEGET;
|
||||||
|
srs_error("dvr: rpc not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < (int)plans.size(); i++) {
|
for (int i = 0; i < (int)plans.size(); i++) {
|
||||||
SrsDvrApiPlan* plan = plans.at(i);
|
SrsDvrApiPlan* plan = plans.at(i);
|
||||||
|
|
||||||
|
|
|
@ -394,9 +394,9 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int add_dvr(SrsDvrApiPlan* dvr);
|
virtual int add_dvr(SrsDvrApiPlan* dvr);
|
||||||
public:
|
public:
|
||||||
virtual int dumps(std::string vhost, std::stringstream& ss);
|
virtual int dumps(std::string vhost, std::string app, std::string stream, std::stringstream& ss);
|
||||||
virtual int create(SrsJsonAny* json);
|
virtual int create(SrsJsonAny* json);
|
||||||
virtual int stop(std::string vhost);
|
virtual int stop(std::string vhost, std::string app, std::string stream);
|
||||||
virtual int rpc(SrsJsonAny* json);
|
virtual int rpc(SrsJsonAny* json);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -494,7 +494,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
SrsApiDvrPool* pool = SrsApiDvrPool::instance();
|
SrsApiDvrPool* pool = SrsApiDvrPool::instance();
|
||||||
if (r->is_http_get()) {
|
if (r->is_http_get()) {
|
||||||
std::stringstream data;
|
std::stringstream data;
|
||||||
int ret = pool->dumps(r->query_get("vhost"), data);
|
int ret = pool->dumps(r->query_get("vhost"), r->query_get("app"), r->query_get("stream"), data);
|
||||||
|
|
||||||
ss << __SRS_JOBJECT_START
|
ss << __SRS_JOBJECT_START
|
||||||
<< __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT
|
<< __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT
|
||||||
|
@ -514,7 +514,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
<< __SRS_JFIELD_ERROR(ret)
|
<< __SRS_JFIELD_ERROR(ret)
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
} else if (r->is_http_delete()) {
|
} else if (r->is_http_delete()) {
|
||||||
int ret = pool->stop(r->query_get("vhost"));
|
int ret = pool->stop(r->query_get("vhost"), r->query_get("app"), r->query_get("stream"));
|
||||||
|
|
||||||
ss << __SRS_JOBJECT_START
|
ss << __SRS_JOBJECT_START
|
||||||
<< __SRS_JFIELD_ERROR(ret)
|
<< __SRS_JFIELD_ERROR(ret)
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR 2
|
#define VERSION_MAJOR 2
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 124
|
#define VERSION_REVISION 125
|
||||||
|
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "SRS"
|
#define RTMP_SIG_SRS_KEY "SRS"
|
||||||
|
|
|
@ -213,6 +213,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define ERROR_HTTP_DVR_REQUEST 3051
|
#define ERROR_HTTP_DVR_REQUEST 3051
|
||||||
#define ERROR_HTTP_JSON_REQUIRED 3052
|
#define ERROR_HTTP_JSON_REQUIRED 3052
|
||||||
#define ERROR_HTTP_DVR_CREATE_REQUEST 3053
|
#define ERROR_HTTP_DVR_CREATE_REQUEST 3053
|
||||||
|
#define ERROR_HTTP_DVR_NO_TAEGET 3054
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// HTTP/StreamCaster protocol error.
|
// HTTP/StreamCaster protocol error.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue