1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

for #179, refine dvr code to more simple.

This commit is contained in:
winlin 2015-02-21 16:25:04 +08:00
parent 3d225e1bc7
commit 95b4baee7c
6 changed files with 609 additions and 429 deletions

View file

@ -281,6 +281,12 @@ vhost dvr.srs.com {
# whether enabled dvr features # whether enabled dvr features
# default: off # default: off
enabled on; enabled on;
# the dvr plan. canbe:
# session reap flv when session end(unpublish).
# segment reap flv when flv duration exceed the specified dvr_duration.
# api reap flv when api required.
# default: session
dvr_plan session;
# the dvr output path. # the dvr output path.
# we supports some variables to generate the filename. # we supports some variables to generate the filename.
# [vhost], the vhost of stream. # [vhost], the vhost of stream.
@ -314,22 +320,28 @@ vhost dvr.srs.com {
# dvr_path /data/ossrs.net/live/2015/01/livestream-03-10.57.30.776.flv; # dvr_path /data/ossrs.net/live/2015/01/livestream-03-10.57.30.776.flv;
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path # @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path # @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path
# segment,session apply it.
# api apply before api specified the path.
# default: ./objs/nginx/html # default: ./objs/nginx/html
dvr_path ./objs/nginx/html; dvr_path ./objs/nginx/html;
# the dvr plan. canbe: # the duration for dvr file, reap if exeed, in seconds.
# session reap flv when session end(unpublish). # segment apply it.
# segment reap flv when flv duration exceed the specified dvr_duration. # session,api ignore.
# default: session
dvr_plan session;
# the param for plan(segment), in seconds.
# default: 30 # default: 30
dvr_duration 30; dvr_duration 30;
# the param for plan(segment),
# whether wait keyframe to reap segment, # whether wait keyframe to reap segment,
# if off, reap segment when duration exceed the dvr_duration, # if off, reap segment when duration exceed the dvr_duration,
# if on, reap segment when duration exceed and got keyframe. # if on, reap segment when duration exceed and got keyframe.
# segment apply it.
# session,api ignore.
# default: on # default: on
dvr_wait_keyframe on; dvr_wait_keyframe on;
# whether dvr auto start when publish.
# if off, dvr wait for api to start it.
# api apply it.
# segment,session ignore.
# default: on
dvr_autostart on;
# about the stream monotonically increasing: # about the stream monotonically increasing:
# 1. video timestamp is monotonically increasing, # 1. video timestamp is monotonically increasing,
# 2. audio timestamp is monotonically increasing, # 2. audio timestamp is monotonically increasing,
@ -340,10 +352,11 @@ vhost dvr.srs.com {
# 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing.
# 2. zero, only ensure sttream start at zero, ignore timestamp jitter. # 2. zero, only ensure sttream start at zero, ignore timestamp jitter.
# 3. off, disable the time jitter algorithm, like atc. # 3. off, disable the time jitter algorithm, like atc.
# apply for all dvr plan.
# default: full # default: full
time_jitter full; time_jitter full;
# on_dvr # on_dvr, never config in here, should config in http_hooks.
# for the dvr http callback, @see http_hooks.on_dvr of vhost hooks.callback.srs.com # for the dvr http callback, @see http_hooks.on_dvr of vhost hooks.callback.srs.com
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#http-callback # @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#http-callback
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#http-callback # @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#http-callback

View file

@ -1418,6 +1418,7 @@ int SrsConfig::check_config()
string m = conf->at(j)->name.c_str(); string m = conf->at(j)->name.c_str();
if (m != "enabled" && m != "dvr_path" && m != "dvr_plan" if (m != "enabled" && m != "dvr_path" && m != "dvr_plan"
&& m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter" && m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter"
&& m != "dvr_autostart"
) { ) {
ret = ERROR_SYSTEM_CONFIG_INVALID; ret = ERROR_SYSTEM_CONFIG_INVALID;
srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret); srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret);
@ -3377,6 +3378,23 @@ bool SrsConfig::get_dvr_wait_keyframe(string vhost)
return false; return false;
} }
bool SrsConfig::get_dvr_autostart(string vhost)
{
SrsConfDirective* dvr = get_dvr(vhost);
if (!dvr) {
return true;
}
SrsConfDirective* conf = dvr->get("dvr_autostart");
if (!conf || conf->arg0() != "off") {
return true;
}
return false;
}
int SrsConfig::get_dvr_time_jitter(string vhost) int SrsConfig::get_dvr_time_jitter(string vhost)
{ {
SrsConfDirective* dvr = get_dvr(vhost); SrsConfDirective* dvr = get_dvr(vhost);

View file

@ -60,6 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html" #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html"
#define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session"
#define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment"
#define SRS_CONF_DEFAULT_DVR_PLAN_API "api"
#define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION
#define SRS_CONF_DEFAULT_DVR_DURATION 30 #define SRS_CONF_DEFAULT_DVR_DURATION 30
#define SRS_CONF_DEFAULT_TIME_JITTER "full" #define SRS_CONF_DEFAULT_TIME_JITTER "full"
@ -921,14 +922,18 @@ public:
*/ */
virtual std::string get_dvr_plan(std::string vhost); virtual std::string get_dvr_plan(std::string vhost);
/** /**
* get the duration of dvr flv, for segment plan. * get the duration of dvr flv.
*/ */
virtual int get_dvr_duration(std::string vhost); virtual int get_dvr_duration(std::string vhost);
/** /**
* whether wait keyframe to reap segment, for segment plan. * whether wait keyframe to reap segment.
*/ */
virtual bool get_dvr_wait_keyframe(std::string vhost); virtual bool get_dvr_wait_keyframe(std::string vhost);
/** /**
* whether autostart for dvr. wait api to start dvr if false.
*/
virtual bool get_dvr_autostart(std::string vhost);
/**
* get the time_jitter algorithm for dvr. * get the time_jitter algorithm for dvr.
*/ */
virtual int get_dvr_time_jitter(std::string vhost); virtual int get_dvr_time_jitter(std::string vhost);

File diff suppressed because it is too large Load diff

View file

@ -41,16 +41,34 @@ class SrsOnMetaDataPacket;
class SrsSharedPtrMessage; class SrsSharedPtrMessage;
class SrsFileWriter; class SrsFileWriter;
class SrsFlvEncoder; class SrsFlvEncoder;
class SrsDvrPlan;
#include <srs_app_source.hpp> #include <srs_app_source.hpp>
#include <srs_app_reload.hpp> #include <srs_app_reload.hpp>
/** /**
* a piece of flv segment. * a piece of flv segment.
* when open segment, support start at 0 or not.
*/ */
class SrsFlvSegment class SrsFlvSegment : public ISrsReloadHandler
{ {
public: private:
SrsSource* source;
SrsRequest* req;
SrsDvrPlan* plan;
private:
/**
* the underlayer dvr stream.
* if close, the flv is reap and closed.
* if open, new flv file is crote.
*/
SrsFlvEncoder* enc;
SrsRtmpJitter* jitter;
SrsRtmpJitterAlgorithm jitter_algorithm;
SrsFileWriter* fs;
private:
std::string tmp_flv_file;
private:
/** /**
* current segment flv file path. * current segment flv file path.
*/ */
@ -81,10 +99,56 @@ public:
*/ */
int64_t stream_previous_pkt_time; int64_t stream_previous_pkt_time;
public: public:
SrsFlvSegment(); SrsFlvSegment(SrsDvrPlan* p);
virtual ~SrsFlvSegment(); virtual ~SrsFlvSegment();
public: public:
virtual void reset(); /**
* initialize the segment.
*/
virtual int initialize(SrsSource* s, SrsRequest* r);
/**
* whether segment is overflow.
*/
virtual bool is_overflow(int64_t max_duration);
/**
* open new segment file, timestamp start at 0 for fresh flv file.
* @remark ignore when already open.
*/
virtual int open();
/**
* close current segment.
* @remark ignore when already closed.
*/
virtual int close();
/**
* write the metadata to segment.
*/
virtual int write_metadata(SrsOnMetaDataPacket* metadata);
/**
* @param __audio, directly ptr, copy it if need to save it.
*/
virtual int write_audio(SrsSharedPtrMessage* __audio);
/**
* @param __video, directly ptr, copy it if need to save it.
*/
virtual int write_video(SrsSharedPtrMessage* __video);
private:
/**
* generate the flv segment path.
*/
virtual std::string generate_path();
/**
* create flv jitter. load jitter when flv exists.
* @param loads_from_flv whether loads the jitter from exists flv file.
*/
virtual int create_jitter(bool loads_from_flv);
/**
* when update the duration of segment by rtmp msg.
*/
virtual int on_update_duration(SrsSharedPtrMessage* msg);
// interface ISrsReloadHandler
public:
virtual int on_reload_vhost_dvr(std::string vhost);
}; };
/** /**
@ -94,32 +158,25 @@ public:
* 2. reap flv: when to reap the flv and start new piece. * 2. reap flv: when to reap the flv and start new piece.
*/ */
// TODO: FIXME: the plan is too fat, refine me. // TODO: FIXME: the plan is too fat, refine me.
class SrsDvrPlan : public ISrsReloadHandler class SrsDvrPlan
{ {
private: public:
/** friend class SrsFlvSegment;
* the underlayer dvr stream.
* if close, the flv is reap and closed.
* if open, new flv file is crote.
*/
SrsFlvEncoder* enc;
SrsSource* _source;
SrsRtmpJitter* jitter;
SrsRtmpJitterAlgorithm jitter_algorithm;
protected: protected:
SrsSource* source;
SrsRequest* req;
SrsFlvSegment* segment; SrsFlvSegment* segment;
SrsRequest* _req;
bool dvr_enabled; bool dvr_enabled;
SrsFileWriter* fs;
private:
std::string tmp_flv_file;
public: public:
SrsDvrPlan(); SrsDvrPlan();
virtual ~SrsDvrPlan(); virtual ~SrsDvrPlan();
public: public:
virtual int initialize(SrsSource* source, SrsRequest* req); virtual int initialize(SrsSource* s, SrsRequest* r);
virtual int on_publish(); virtual int on_publish() = 0;
virtual void on_unpublish() = 0; virtual void on_unpublish() = 0;
/**
* when got metadata.
*/
virtual int on_meta_data(SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
/** /**
* @param __audio, directly ptr, copy it if need to save it. * @param __audio, directly ptr, copy it if need to save it.
@ -129,15 +186,7 @@ public:
* @param __video, directly ptr, copy it if need to save it. * @param __video, directly ptr, copy it if need to save it.
*/ */
virtual int on_video(SrsSharedPtrMessage* __video); virtual int on_video(SrsSharedPtrMessage* __video);
// interface ISrsReloadHandler
public:
virtual int on_reload_vhost_dvr(std::string vhost);
protected: protected:
virtual int flv_open(std::string stream, std::string path);
virtual int flv_close();
virtual int open_new_segment();
virtual int update_duration(SrsSharedPtrMessage* msg);
virtual int write_flv_header();
virtual int on_dvr_request_sh(); virtual int on_dvr_request_sh();
virtual int on_video_keyframe(); virtual int on_video_keyframe();
virtual int64_t filter_timestamp(int64_t timestamp); virtual int64_t filter_timestamp(int64_t timestamp);
@ -154,6 +203,7 @@ public:
SrsDvrSessionPlan(); SrsDvrSessionPlan();
virtual ~SrsDvrSessionPlan(); virtual ~SrsDvrSessionPlan();
public: public:
virtual int on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
}; };
@ -193,11 +243,11 @@ private:
class SrsDvr class SrsDvr
{ {
private: private:
SrsSource* _source; SrsSource* source;
private: private:
SrsDvrPlan* plan; SrsDvrPlan* plan;
public: public:
SrsDvr(SrsSource* source); SrsDvr(SrsSource* s);
virtual ~SrsDvr(); virtual ~SrsDvr();
public: public:
/** /**
@ -205,12 +255,12 @@ public:
* when system initialize(encoder publish at first time, or reload), * when system initialize(encoder publish at first time, or reload),
* initialize the dvr will reinitialize the plan, the whole dvr framework. * initialize the dvr will reinitialize the plan, the whole dvr framework.
*/ */
virtual int initialize(SrsRequest* req); virtual int initialize(SrsRequest* r);
/** /**
* publish stream event, * publish stream event,
* when encoder start to publish RTMP stream. * when encoder start to publish RTMP stream.
*/ */
virtual int on_publish(SrsRequest* req); virtual int on_publish(SrsRequest* r);
/** /**
* the unpublish event., * the unpublish event.,
* when encoder stop(unpublish) to publish RTMP stream. * when encoder stop(unpublish) to publish RTMP stream.
@ -219,7 +269,7 @@ public:
/** /**
* get some information from metadata, it's optinal. * get some information from metadata, it's optinal.
*/ */
virtual int on_meta_data(SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsOnMetaDataPacket* m);
/** /**
* mux the audio packets to dvr. * mux the audio packets to dvr.
* @param __audio, directly ptr, copy it if need to save it. * @param __audio, directly ptr, copy it if need to save it.

View file

@ -106,7 +106,8 @@ int SrsGoApiV1::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
<< __SRS_JFIELD_STR("authors", "the primary authors and contributors") << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("authors", "the primary authors and contributors") << __SRS_JFIELD_CONT
<< __SRS_JFIELD_STR("requests", "the request itself, for http debug") << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("requests", "the request itself, for http debug") << __SRS_JFIELD_CONT
<< __SRS_JFIELD_STR("vhosts", "dumps vhost to json") << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("vhosts", "dumps vhost to json") << __SRS_JFIELD_CONT
<< __SRS_JFIELD_STR("streams", "dumps streams to json") << __SRS_JFIELD_STR("streams", "dumps streams to json") << __SRS_JFIELD_CONT
<< __SRS_JFIELD_STR("dvrs", "query or control the dvr plan")
<< __SRS_JOBJECT_END << __SRS_JOBJECT_END
<< __SRS_JOBJECT_END; << __SRS_JOBJECT_END;