for #179, dvr suport vhost/app/stream level control. 2.0.125.
正在显示
7 个修改的文件
包含
72 行增加
和
15 行删除
| @@ -532,6 +532,7 @@ Supported operating systems and hardware: | @@ -532,6 +532,7 @@ Supported operating systems and hardware: | ||
| 532 | 532 | ||
| 533 | ### SRS 2.0 history | 533 | ### SRS 2.0 history |
| 534 | 534 | ||
| 535 | +* 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. | ||
| 535 | * 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. | 536 | * 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. |
| 536 | * v2.0, 2015-02-24, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), support dvr http api. 2.0.123. | 537 | * v2.0, 2015-02-24, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), support dvr http api. 2.0.123. |
| 537 | * v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122. | 538 | * v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122. |
| @@ -293,19 +293,24 @@ vhost dvr.srs.com { | @@ -293,19 +293,24 @@ vhost dvr.srs.com { | ||
| 293 | # http url to control dvr, for example, http://dev:1985/api/v1/dvrs | 293 | # http url to control dvr, for example, http://dev:1985/api/v1/dvrs |
| 294 | # method=GET | 294 | # method=GET |
| 295 | # to query dvrs of server. | 295 | # to query dvrs of server. |
| 296 | - # request params, for example ?vhost=__defaultVhost__, where: | ||
| 297 | - # vhost, query all dvr of this vhost. | 296 | + # request params, for example ?vhost=__defaultVhost__&&app=live&&stream=livestream, where: |
| 297 | + # vhost, <required>, query all dvr of this vhost. | ||
| 298 | + # app, [optinal], query all dvr of this app. query all app if not specified. | ||
| 299 | + # stream, [optional], query specified dvr stream. query all stream if not specified. | ||
| 298 | # response in json, where: | 300 | # response in json, where: |
| 299 | # {code:0, dvrs: [{path_tmpl:"./[15].[04].[05].[999].flv", path_dvr:"./22.7.43.312.flv", | 301 | # {code:0, dvrs: [{path_tmpl:"./[15].[04].[05].[999].flv", path_dvr:"./22.7.43.312.flv", |
| 300 | - # wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs", | 302 | + # vhost:"__defaultVhost", app:"live", stream:"livestream", |
| 303 | + # wait_keyframe:true, callback:"http://127.0.0.1:8085/api/v1/dvrs", | ||
| 301 | # status:"stop"|"start" | 304 | # status:"stop"|"start" |
| 302 | # }]} | 305 | # }]} |
| 303 | # method=POST | 306 | # method=POST |
| 304 | # to start dvr of specified vhost. | 307 | # to start dvr of specified vhost. |
| 305 | # request should encode in json, specifies the dvr to create, where: | 308 | # request should encode in json, specifies the dvr to create, where: |
| 306 | # {path_tmpl:"./[15].[04].[05].[999].flv", | 309 | # {path_tmpl:"./[15].[04].[05].[999].flv", |
| 307 | - # wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs" | 310 | + # vhost:"__defaultVhost", app:"live", stream:"livestream", |
| 311 | + # wait_keyframe:true, callback:"http://127.0.0.1:8085/api/v1/dvrs" | ||
| 308 | # } | 312 | # } |
| 313 | + # @remark, the app and stream is optional. | ||
| 309 | # response in json, where: | 314 | # response in json, where: |
| 310 | # {code:0} | 315 | # {code:0} |
| 311 | # method=DELETE, to stop dvr | 316 | # method=DELETE, to stop dvr |
| @@ -316,7 +321,10 @@ vhost dvr.srs.com { | @@ -316,7 +321,10 @@ vhost dvr.srs.com { | ||
| 316 | # {code:0} | 321 | # {code:0} |
| 317 | # method=PUT, use as RPC(remote process call). | 322 | # method=PUT, use as RPC(remote process call). |
| 318 | # reap_segment, the request params in json, where: | 323 | # reap_segment, the request params in json, where: |
| 319 | - # {action:"reap_segment", vhost:"__defaultVhost", path_tmpl:"./[15].[04].[05].[999].flv"} | 324 | + # {action:"reap_segment", vhost:"__defaultVhost", app:"live", stream:"livestream", |
| 325 | + # path_tmpl:"./[15].[04].[05].[999].flv" | ||
| 326 | + # } | ||
| 327 | + # @remark, the app and stream is optional. | ||
| 320 | # when reap segment, the callback POST request in json: | 328 | # when reap segment, the callback POST request in json: |
| 321 | # {action:"on_dvr_reap_segment", client_id:100, vhost:"__defaultVhost__", | 329 | # {action:"on_dvr_reap_segment", client_id:100, vhost:"__defaultVhost__", |
| 322 | # app:"live", stream:"livestream", cwd:"/home/winlin/srs", file:"./dvr.flv" | 330 | # app:"live", stream:"livestream", cwd:"/home/winlin/srs", file:"./dvr.flv" |
| @@ -1078,6 +1078,8 @@ int SrsDvrApiPlan::dumps(stringstream& ss) | @@ -1078,6 +1078,8 @@ int SrsDvrApiPlan::dumps(stringstream& ss) | ||
| 1078 | << __SRS_JFIELD_STR("path_dvr", segment->get_path()) << __SRS_JFIELD_CONT | 1078 | << __SRS_JFIELD_STR("path_dvr", segment->get_path()) << __SRS_JFIELD_CONT |
| 1079 | << __SRS_JFIELD_BOOL("wait_keyframe", wait_keyframe) << __SRS_JFIELD_CONT | 1079 | << __SRS_JFIELD_BOOL("wait_keyframe", wait_keyframe) << __SRS_JFIELD_CONT |
| 1080 | << __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT | 1080 | << __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT |
| 1081 | + << __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT | ||
| 1082 | + << __SRS_JFIELD_STR("stream", req->stream) << __SRS_JFIELD_CONT | ||
| 1081 | << __SRS_JFIELD_STR("callback", callback) << __SRS_JFIELD_CONT | 1083 | << __SRS_JFIELD_STR("callback", callback) << __SRS_JFIELD_CONT |
| 1082 | << __SRS_JFIELD_STR("status", (dvr_enabled? "start":"stop")) | 1084 | << __SRS_JFIELD_STR("status", (dvr_enabled? "start":"stop")) |
| 1083 | << __SRS_JOBJECT_END; | 1085 | << __SRS_JOBJECT_END; |
| @@ -1482,7 +1484,7 @@ int SrsApiDvrPool::add_dvr(SrsDvrApiPlan* dvr) | @@ -1482,7 +1484,7 @@ int SrsApiDvrPool::add_dvr(SrsDvrApiPlan* dvr) | ||
| 1482 | return ERROR_SUCCESS; | 1484 | return ERROR_SUCCESS; |
| 1483 | } | 1485 | } |
| 1484 | 1486 | ||
| 1485 | -int SrsApiDvrPool::dumps(string vhost, stringstream& ss) | 1487 | +int SrsApiDvrPool::dumps(string vhost, string app, string stream, stringstream& ss) |
| 1486 | { | 1488 | { |
| 1487 | int ret = ERROR_SUCCESS; | 1489 | int ret = ERROR_SUCCESS; |
| 1488 | 1490 | ||
| @@ -1494,6 +1496,12 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss) | @@ -1494,6 +1496,12 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss) | ||
| 1494 | if (!vhost.empty() && plan->req->vhost != vhost) { | 1496 | if (!vhost.empty() && plan->req->vhost != vhost) { |
| 1495 | continue; | 1497 | continue; |
| 1496 | } | 1498 | } |
| 1499 | + if (!app.empty() && plan->req->app != app) { | ||
| 1500 | + continue; | ||
| 1501 | + } | ||
| 1502 | + if (!stream.empty() && plan->req->stream != stream) { | ||
| 1503 | + continue; | ||
| 1504 | + } | ||
| 1497 | plans.push_back(plan); | 1505 | plans.push_back(plan); |
| 1498 | } | 1506 | } |
| 1499 | 1507 | ||
| @@ -1504,7 +1512,7 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss) | @@ -1504,7 +1512,7 @@ int SrsApiDvrPool::dumps(string vhost, stringstream& ss) | ||
| 1504 | return ret; | 1512 | return ret; |
| 1505 | } | 1513 | } |
| 1506 | 1514 | ||
| 1507 | - if (i < (int)dvrs.size() - 1) { | 1515 | + if (i < (int)plans.size() - 1) { |
| 1508 | ss << __SRS_JFIELD_CONT; | 1516 | ss << __SRS_JFIELD_CONT; |
| 1509 | } | 1517 | } |
| 1510 | } | 1518 | } |
| @@ -1534,19 +1542,33 @@ int SrsApiDvrPool::create(SrsJsonAny* json) | @@ -1534,19 +1542,33 @@ int SrsApiDvrPool::create(SrsJsonAny* json) | ||
| 1534 | } | 1542 | } |
| 1535 | 1543 | ||
| 1536 | std::string vhost = prop->to_str(); | 1544 | std::string vhost = prop->to_str(); |
| 1545 | + std::string app, stream; | ||
| 1546 | + if ((prop = obj->ensure_property_string("app")) != NULL) { | ||
| 1547 | + app = prop->to_str(); | ||
| 1548 | + } | ||
| 1549 | + if ((prop = obj->ensure_property_string("stream")) != NULL) { | ||
| 1550 | + stream = prop->to_str(); | ||
| 1551 | + } | ||
| 1552 | + | ||
| 1537 | SrsDvrApiPlan* dvr = NULL; | 1553 | SrsDvrApiPlan* dvr = NULL; |
| 1538 | for (int i = 0; i < (int)dvrs.size(); i++) { | 1554 | for (int i = 0; i < (int)dvrs.size(); i++) { |
| 1539 | SrsDvrApiPlan* plan = dvrs.at(i); | 1555 | SrsDvrApiPlan* plan = dvrs.at(i); |
| 1540 | if (!vhost.empty() && plan->req->vhost != vhost) { | 1556 | if (!vhost.empty() && plan->req->vhost != vhost) { |
| 1541 | continue; | 1557 | continue; |
| 1542 | } | 1558 | } |
| 1559 | + if (!app.empty() && plan->req->app != app) { | ||
| 1560 | + continue; | ||
| 1561 | + } | ||
| 1562 | + if (!stream.empty() && plan->req->stream != stream) { | ||
| 1563 | + continue; | ||
| 1564 | + } | ||
| 1543 | dvr = plan; | 1565 | dvr = plan; |
| 1544 | break; | 1566 | break; |
| 1545 | } | 1567 | } |
| 1546 | 1568 | ||
| 1547 | if (!dvr) { | 1569 | if (!dvr) { |
| 1548 | - ret = ERROR_HTTP_DVR_CREATE_REQUEST; | ||
| 1549 | - srs_error("dvr: api create dvr request vhost invalid. vhost=%s. ret=%d", vhost.c_str(), ret); | 1570 | + ret = ERROR_HTTP_DVR_NO_TAEGET; |
| 1571 | + srs_error("dvr: create not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret); | ||
| 1550 | return ret; | 1572 | return ret; |
| 1551 | } | 1573 | } |
| 1552 | 1574 | ||
| @@ -1570,7 +1592,7 @@ int SrsApiDvrPool::create(SrsJsonAny* json) | @@ -1570,7 +1592,7 @@ int SrsApiDvrPool::create(SrsJsonAny* json) | ||
| 1570 | return dvr->start(); | 1592 | return dvr->start(); |
| 1571 | } | 1593 | } |
| 1572 | 1594 | ||
| 1573 | -int SrsApiDvrPool::stop(string vhost) | 1595 | +int SrsApiDvrPool::stop(string vhost, string app, string stream) |
| 1574 | { | 1596 | { |
| 1575 | int ret = ERROR_SUCCESS; | 1597 | int ret = ERROR_SUCCESS; |
| 1576 | 1598 | ||
| @@ -1580,9 +1602,21 @@ int SrsApiDvrPool::stop(string vhost) | @@ -1580,9 +1602,21 @@ int SrsApiDvrPool::stop(string vhost) | ||
| 1580 | if (!vhost.empty() && plan->req->vhost != vhost) { | 1602 | if (!vhost.empty() && plan->req->vhost != vhost) { |
| 1581 | continue; | 1603 | continue; |
| 1582 | } | 1604 | } |
| 1605 | + if (!app.empty() && plan->req->app != app) { | ||
| 1606 | + continue; | ||
| 1607 | + } | ||
| 1608 | + if (!stream.empty() && plan->req->stream != stream) { | ||
| 1609 | + continue; | ||
| 1610 | + } | ||
| 1583 | plans.push_back(plan); | 1611 | plans.push_back(plan); |
| 1584 | } | 1612 | } |
| 1585 | 1613 | ||
| 1614 | + if (plans.empty()) { | ||
| 1615 | + ret = ERROR_HTTP_DVR_NO_TAEGET; | ||
| 1616 | + srs_error("dvr: stop not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret); | ||
| 1617 | + return ret; | ||
| 1618 | + } | ||
| 1619 | + | ||
| 1586 | for (int i = 0; i < (int)plans.size(); i++) { | 1620 | for (int i = 0; i < (int)plans.size(); i++) { |
| 1587 | SrsDvrApiPlan* plan = plans.at(i); | 1621 | SrsDvrApiPlan* plan = plans.at(i); |
| 1588 | 1622 | ||
| @@ -1613,6 +1647,13 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json) | @@ -1613,6 +1647,13 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json) | ||
| 1613 | return ret; | 1647 | return ret; |
| 1614 | } | 1648 | } |
| 1615 | std::string vhost = prop->to_str(); | 1649 | std::string vhost = prop->to_str(); |
| 1650 | + std::string app, stream; | ||
| 1651 | + if ((prop = obj->ensure_property_string("app")) != NULL) { | ||
| 1652 | + app = prop->to_str(); | ||
| 1653 | + } | ||
| 1654 | + if ((prop = obj->ensure_property_string("stream")) != NULL) { | ||
| 1655 | + stream = prop->to_str(); | ||
| 1656 | + } | ||
| 1616 | 1657 | ||
| 1617 | std::vector<SrsDvrApiPlan*> plans; | 1658 | std::vector<SrsDvrApiPlan*> plans; |
| 1618 | for (int i = 0; i < (int)dvrs.size(); i++) { | 1659 | for (int i = 0; i < (int)dvrs.size(); i++) { |
| @@ -1623,6 +1664,12 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json) | @@ -1623,6 +1664,12 @@ int SrsApiDvrPool::rpc(SrsJsonAny* json) | ||
| 1623 | plans.push_back(plan); | 1664 | plans.push_back(plan); |
| 1624 | } | 1665 | } |
| 1625 | 1666 | ||
| 1667 | + if (plans.empty()) { | ||
| 1668 | + ret = ERROR_HTTP_DVR_NO_TAEGET; | ||
| 1669 | + srs_error("dvr: rpc not found for url=%s/%s/%s, ret=%d", vhost.c_str(), app.c_str(), stream.c_str(), ret); | ||
| 1670 | + return ret; | ||
| 1671 | + } | ||
| 1672 | + | ||
| 1626 | for (int i = 0; i < (int)plans.size(); i++) { | 1673 | for (int i = 0; i < (int)plans.size(); i++) { |
| 1627 | SrsDvrApiPlan* plan = plans.at(i); | 1674 | SrsDvrApiPlan* plan = plans.at(i); |
| 1628 | 1675 |
| @@ -394,9 +394,9 @@ public: | @@ -394,9 +394,9 @@ public: | ||
| 394 | public: | 394 | public: |
| 395 | virtual int add_dvr(SrsDvrApiPlan* dvr); | 395 | virtual int add_dvr(SrsDvrApiPlan* dvr); |
| 396 | public: | 396 | public: |
| 397 | - virtual int dumps(std::string vhost, std::stringstream& ss); | 397 | + virtual int dumps(std::string vhost, std::string app, std::string stream, std::stringstream& ss); |
| 398 | virtual int create(SrsJsonAny* json); | 398 | virtual int create(SrsJsonAny* json); |
| 399 | - virtual int stop(std::string vhost); | 399 | + virtual int stop(std::string vhost, std::string app, std::string stream); |
| 400 | virtual int rpc(SrsJsonAny* json); | 400 | virtual int rpc(SrsJsonAny* json); |
| 401 | }; | 401 | }; |
| 402 | 402 |
| @@ -494,7 +494,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | @@ -494,7 +494,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 494 | SrsApiDvrPool* pool = SrsApiDvrPool::instance(); | 494 | SrsApiDvrPool* pool = SrsApiDvrPool::instance(); |
| 495 | if (r->is_http_get()) { | 495 | if (r->is_http_get()) { |
| 496 | std::stringstream data; | 496 | std::stringstream data; |
| 497 | - int ret = pool->dumps(r->query_get("vhost"), data); | 497 | + int ret = pool->dumps(r->query_get("vhost"), r->query_get("app"), r->query_get("stream"), data); |
| 498 | 498 | ||
| 499 | ss << __SRS_JOBJECT_START | 499 | ss << __SRS_JOBJECT_START |
| 500 | << __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT | 500 | << __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT |
| @@ -514,7 +514,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | @@ -514,7 +514,7 @@ int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 514 | << __SRS_JFIELD_ERROR(ret) | 514 | << __SRS_JFIELD_ERROR(ret) |
| 515 | << __SRS_JOBJECT_END; | 515 | << __SRS_JOBJECT_END; |
| 516 | } else if (r->is_http_delete()) { | 516 | } else if (r->is_http_delete()) { |
| 517 | - int ret = pool->stop(r->query_get("vhost")); | 517 | + int ret = pool->stop(r->query_get("vhost"), r->query_get("app"), r->query_get("stream")); |
| 518 | 518 | ||
| 519 | ss << __SRS_JOBJECT_START | 519 | ss << __SRS_JOBJECT_START |
| 520 | << __SRS_JFIELD_ERROR(ret) | 520 | << __SRS_JFIELD_ERROR(ret) |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 124 | 34 | +#define VERSION_REVISION 125 |
| 35 | 35 | ||
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
| @@ -213,6 +213,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -213,6 +213,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 213 | #define ERROR_HTTP_DVR_REQUEST 3051 | 213 | #define ERROR_HTTP_DVR_REQUEST 3051 |
| 214 | #define ERROR_HTTP_JSON_REQUIRED 3052 | 214 | #define ERROR_HTTP_JSON_REQUIRED 3052 |
| 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 | 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 |
| 216 | +#define ERROR_HTTP_DVR_NO_TAEGET 3054 | ||
| 216 | 217 | ||
| 217 | /////////////////////////////////////////////////////// | 218 | /////////////////////////////////////////////////////// |
| 218 | // HTTP/StreamCaster protocol error. | 219 | // HTTP/StreamCaster protocol error. |
-
请 注册 或 登录 后发表评论