Skip to content

Commit

Permalink
for #459, dvr support apply filter for ng-control dvr module.
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Sep 15, 2015
1 parent 8f9cfcd commit 2a1b2b6
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 98 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,9 @@ Remark:

## History

* v3.0, 2015-09-14, fix [#319][bug #319], http raw api support update global and vhost. 3.0.4
* v3.0, 2015-08-31, fix [#319][bug #319], http raw api support query global and vhost. 3.0.3
* v3.0, 2015-09-14, fix [#459][bug #459], dvr support apply filter for ng-control dvr module.
* v3.0, 2015-09-14, fix [#319][bug #319], http raw api support update global and vhost. 3.0.3
* v3.0, 2015-08-31, fix [#319][bug #319], http raw api support query global and vhost.
* v3.0, 2015-08-28, fix [#471][bug #471], api response the width and height. 3.0.2
* v3.0, 2015-08-25, fix [#367][bug #367], support nginx-rtmp exec. 3.0.1
* <strong>v2.0, 2015-08-23, [2.0 alpha0(2.0.185)][r2.0a0] released. 89022 lines.</strong>
Expand Down
7 changes: 7 additions & 0 deletions trunk/conf/full.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,13 @@ vhost dvr.srs.com {
# whether enabled dvr features
# default: off
enabled on;
# the filter for dvr to aplly to.
# all, dvr all streams of all apps.
# <app>/<stream>, apply to specified stream of app.
# for example, to dvr the following two streams:
# live/stream1 live/stream2
# default: all
dvr_apply all;
# the dvr plan. canbe:
# session reap flv when session end(unpublish).
# segment reap flv when flv duration exceed the specified dvr_duration.
Expand Down
107 changes: 103 additions & 4 deletions trunk/src/app/srs_app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,8 +832,8 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
srs_trace("vhost %s reload hds success.", vhost.c_str());
}

// dvr, only one per vhost
if (!srs_directive_equals(new_vhost->get("dvr"), old_vhost->get("dvr"))) {
// dvr, only one per vhost, except the dvr_apply
if (!srs_directive_equals(new_vhost->get("dvr"), old_vhost->get("dvr"), "dvr_apply")) {
for (it = subscribes.begin(); it != subscribes.end(); ++it) {
ISrsReloadHandler* subscribe = *it;
if ((ret = subscribe->on_reload_vhost_dvr(vhost)) != ERROR_SUCCESS) {
Expand All @@ -843,6 +843,24 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
}
srs_trace("vhost %s reload dvr success.", vhost.c_str());
}
// dvr_apply, the dynamic dvr filter.
if (true) {
// we must reload the dvr_apply, for it's apply to specified stream,
// and we donot want one stream reload take effect on another one.
// @see https://github.com/simple-rtmp-server/srs/issues/459#issuecomment-140296597
SrsConfDirective* nda = new_vhost->get("dvr")? new_vhost->get("dvr")->get("dvr_apply") : NULL;
SrsConfDirective* oda = old_vhost->get("dvr")? old_vhost->get("dvr")->get("dvr_apply") : NULL;
if (!srs_directive_equals(nda, oda)) {
for (it = subscribes.begin(); it != subscribes.end(); ++it) {
ISrsReloadHandler* subscribe = *it;
if ((ret = subscribe->on_reload_vhost_dvr_apply(vhost)) != ERROR_SUCCESS) {
srs_error("vhost %s notify subscribes dvr_apply failed. ret=%d", vhost.c_str(), ret);
return ret;
}
}
srs_trace("vhost %s reload dvr_apply success.", vhost.c_str());
}
}

// exec, only one per vhost
if (!srs_directive_equals(new_vhost->get("exec"), old_vhost->get("exec"))) {
Expand Down Expand Up @@ -2070,6 +2088,8 @@ int SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj)

if (sdir->name == "dvr_plan") {
dvr->set("dvr_plan", sdir->dumps_arg0_to_str());
} else if (sdir->name == "dvr_apply") {
dvr->set("dvr_apply", sdir->dumps_args());
} else if (sdir->name == "dvr_path") {
dvr->set("dvr_path", sdir->dumps_arg0_to_str());
} else if (sdir->name == "dvr_duration") {
Expand Down Expand Up @@ -3141,7 +3161,7 @@ int SrsConfig::check_config()
if (n == "dvr") {
for (int j = 0; j < (int)conf->directives.size(); j++) {
string m = conf->at(j)->name.c_str();
if (m != "enabled" && m != "dvr_path" && m != "dvr_plan"
if (m != "enabled" && m != "dvr_apply" && m != "dvr_path" && m != "dvr_plan"
&& m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter"
) {
ret = ERROR_SYSTEM_CONFIG_INVALID;
Expand Down Expand Up @@ -5558,6 +5578,22 @@ bool SrsConfig::get_dvr_enabled(string vhost)
return SRS_CONF_PERFER_FALSE(conf->arg0());
}

SrsConfDirective* SrsConfig::get_dvr_apply(string vhost)
{
SrsConfDirective* conf = get_dvr(vhost);
if (!conf) {
return NULL;
}

conf = conf->get("dvr_apply");
if (!conf || conf->arg0().empty()) {
return NULL;
}

return conf;

}

string SrsConfig::get_dvr_path(string vhost)
{
static string DEFAULT = "./objs/nginx/html/[app]/[stream].[timestamp].flv";
Expand Down Expand Up @@ -6179,7 +6215,7 @@ namespace _srs_internal
}
};

bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
bool srs_directive_equals_self(SrsConfDirective* a, SrsConfDirective* b)
{
// both NULL, equal.
if (!a && !b) {
Expand Down Expand Up @@ -6208,6 +6244,20 @@ bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
return false;
}

return true;
}

bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
{
// both NULL, equal.
if (!a && !b) {
return true;
}

if (!srs_directive_equals_self(a, b)) {
return false;
}

for (int i = 0; i < (int)a->directives.size(); i++) {
SrsConfDirective* a0 = a->at(i);
SrsConfDirective* b0 = b->at(i);
Expand All @@ -6220,6 +6270,34 @@ bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
return true;
}

bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b, string except)
{
// both NULL, equal.
if (!a && !b) {
return true;
}

if (!srs_directive_equals_self(a, b)) {
return false;
}

for (int i = 0; i < (int)a->directives.size(); i++) {
SrsConfDirective* a0 = a->at(i);
SrsConfDirective* b0 = b->at(i);

// donot compare the except child directive.
if (a0->name == except) {
continue;
}

if (!srs_directive_equals(a0, b0, except)) {
return false;
}
}

return true;
}

bool srs_config_hls_is_on_error_ignore(string strategy)
{
return strategy == "ignore";
Expand Down Expand Up @@ -6270,6 +6348,27 @@ bool srs_stream_caster_is_flv(string caster)
return caster == "flv";
}

bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req)
{
static bool DEFAULT = true;

if (!dvr_apply || dvr_apply->args.empty()) {
return DEFAULT;
}

vector<string>& args = dvr_apply->args;
if (args.size() == 1 && dvr_apply->arg0() == "all") {
return true;
}

string id = req->app + "/" + req->stream;
if (::find(args.begin(), args.end(), id) != args.end()) {
return true;
}

return false;
}

string srs_config_bool2switch(const string& sbool)
{
return sbool == "true"? "on":"off";
Expand Down
11 changes: 10 additions & 1 deletion trunk/src/app/srs_app_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <srs_app_reload.hpp>

class SrsRequest;
class SrsFileWriter;
class SrsAmf0Object;
class SrsAmf0StrictArray;
Expand Down Expand Up @@ -1115,6 +1116,11 @@ class SrsConfig
* whether dvr is enabled.
*/
virtual bool get_dvr_enabled(std::string vhost);
/**
* get the filter of dvr to apply to.
* @remark user can use srs_config_apply_filter(conf, req):bool to check it.
*/
virtual SrsConfDirective* get_dvr_apply(std::string vhost);
/**
* get the dvr path, the flv file to save in.
*/
Expand Down Expand Up @@ -1308,8 +1314,9 @@ namespace _srs_internal

/**
* deep compare directive.
*/
*/
extern bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b);
extern bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b, std::string except);

/**
* helper utilities, used for compare the consts values.
Expand All @@ -1324,6 +1331,8 @@ extern bool srs_config_dvr_is_plan_append(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);

/**
* convert bool in str to on/off
Expand Down
58 changes: 53 additions & 5 deletions trunk/src/app/srs_app_dvr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,41 +972,56 @@ SrsDvr::SrsDvr()
{
source = NULL;
plan = NULL;
req = NULL;
actived = false;

_srs_config->subscribe(this);
}

SrsDvr::~SrsDvr()
{
_srs_config->unsubscribe(this);

srs_freep(plan);
}

int SrsDvr::initialize(SrsSource* s, SrsRequest* r)
{
int ret = ERROR_SUCCESS;

req = r;
source = s;

SrsConfDirective* conf = _srs_config->get_dvr_apply(r->vhost);
actived = srs_config_apply_filter(conf, r);

srs_freep(plan);
plan = SrsDvrPlan::create_plan(r->vhost);

if ((ret = plan->initialize(r)) != ERROR_SUCCESS) {
return ret;
}

if ((ret = source->on_dvr_request_sh()) != ERROR_SUCCESS) {
return ret;
}

return ret;
}

int SrsDvr::on_publish(SrsRequest* /*r*/)
int SrsDvr::on_publish(bool fetch_sequence_header)
{
int ret = ERROR_SUCCESS;

// the dvr for this stream is not actived.
if (!actived) {
return ret;
}

if ((ret = plan->on_publish()) != ERROR_SUCCESS) {
return ret;
}

if (fetch_sequence_header && (ret = source->on_dvr_request_sh()) != ERROR_SUCCESS) {
return ret;
}

return ret;
}

Expand All @@ -1019,6 +1034,11 @@ void SrsDvr::on_unpublish()
int SrsDvr::on_meta_data(SrsOnMetaDataPacket* m)
{
int ret = ERROR_SUCCESS;

// the dvr for this stream is not actived.
if (!actived) {
return ret;
}

int size = 0;
char* payload = NULL;
Expand All @@ -1040,14 +1060,42 @@ int SrsDvr::on_meta_data(SrsOnMetaDataPacket* m)

int SrsDvr::on_audio(SrsSharedPtrMessage* shared_audio)
{
// the dvr for this stream is not actived.
if (!actived) {
return ERROR_SUCCESS;
}

return plan->on_audio(shared_audio);
}

int SrsDvr::on_video(SrsSharedPtrMessage* shared_video)
{
// the dvr for this stream is not actived.
if (!actived) {
return ERROR_SUCCESS;
}

return plan->on_video(shared_video);
}

int SrsDvr::on_reload_vhost_dvr_apply(string vhost)
{
int ret = ERROR_SUCCESS;

SrsConfDirective* conf = _srs_config->get_dvr_apply(req->vhost);
bool v = srs_config_apply_filter(conf, req);

// the apply changed, republish the dvr.
if (v != actived) {
actived = v;

on_unpublish();
return on_publish(true);
}

return ret;
}

#endif


Loading

0 comments on commit 2a1b2b6

Please sign in to comment.