winlin

for #179, add dvr plan append.

@@ -284,6 +284,7 @@ vhost dvr.srs.com { @@ -284,6 +284,7 @@ vhost dvr.srs.com {
284 # the dvr plan. canbe: 284 # the dvr plan. canbe:
285 # session reap flv when session end(unpublish). 285 # session reap flv when session end(unpublish).
286 # segment reap flv when flv duration exceed the specified dvr_duration. 286 # segment reap flv when flv duration exceed the specified dvr_duration.
  287 + # append always append to flv file, never reap it.
287 # api reap flv when api required. 288 # api reap flv when api required.
288 # default: session 289 # default: session
289 dvr_plan session; 290 dvr_plan session;
@@ -60,6 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -60,6 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60 #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html" 60 #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html"
61 #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" 61 #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session"
62 #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" 62 #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment"
  63 +#define SRS_CONF_DEFAULT_DVR_PLAN_APPEND "append"
63 #define SRS_CONF_DEFAULT_DVR_PLAN_API "api" 64 #define SRS_CONF_DEFAULT_DVR_PLAN_API "api"
64 #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION 65 #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION
65 #define SRS_CONF_DEFAULT_DVR_DURATION 30 66 #define SRS_CONF_DEFAULT_DVR_DURATION 30
@@ -86,7 +86,7 @@ bool SrsFlvSegment::is_overflow(int64_t max_duration) @@ -86,7 +86,7 @@ bool SrsFlvSegment::is_overflow(int64_t max_duration)
86 return duration >= max_duration; 86 return duration >= max_duration;
87 } 87 }
88 88
89 -int SrsFlvSegment::open() 89 +int SrsFlvSegment::open(bool use_tmp_file)
90 { 90 {
91 int ret = ERROR_SUCCESS; 91 int ret = ERROR_SUCCESS;
92 92
@@ -113,7 +113,7 @@ int SrsFlvSegment::open() @@ -113,7 +113,7 @@ int SrsFlvSegment::open()
113 } 113 }
114 114
115 // generate the tmp flv path. 115 // generate the tmp flv path.
116 - if (!fresh_flv_file) { 116 + if (!fresh_flv_file || !use_tmp_file) {
117 // when path exists, always append to it. 117 // when path exists, always append to it.
118 // so we must use the target flv path as output flv. 118 // so we must use the target flv path as output flv.
119 tmp_flv_file = path; 119 tmp_flv_file = path;
@@ -546,8 +546,11 @@ SrsDvrPlan* SrsDvrPlan::create_plan(string vhost) @@ -546,8 +546,11 @@ SrsDvrPlan* SrsDvrPlan::create_plan(string vhost)
546 return new SrsDvrSegmentPlan(); 546 return new SrsDvrSegmentPlan();
547 } else if (plan == SRS_CONF_DEFAULT_DVR_PLAN_SESSION) { 547 } else if (plan == SRS_CONF_DEFAULT_DVR_PLAN_SESSION) {
548 return new SrsDvrSessionPlan(); 548 return new SrsDvrSessionPlan();
  549 + } else if (plan == SRS_CONF_DEFAULT_DVR_PLAN_APPEND) {
  550 + return new SrsDvrAppendPlan();
549 } else { 551 } else {
550 - return new SrsDvrSessionPlan(); 552 + srs_error("invalid dvr plan=%s, vhost=%s", plan.c_str(), vhost.c_str());
  553 + srs_assert(false);
551 } 554 }
552 } 555 }
553 556
@@ -601,6 +604,40 @@ void SrsDvrSessionPlan::on_unpublish() @@ -601,6 +604,40 @@ void SrsDvrSessionPlan::on_unpublish()
601 dvr_enabled = false; 604 dvr_enabled = false;
602 } 605 }
603 606
  607 +SrsDvrAppendPlan::SrsDvrAppendPlan()
  608 +{
  609 +}
  610 +
  611 +SrsDvrAppendPlan::~SrsDvrAppendPlan()
  612 +{
  613 +}
  614 +
  615 +int SrsDvrAppendPlan::on_publish()
  616 +{
  617 + int ret = ERROR_SUCCESS;
  618 +
  619 + // support multiple publish.
  620 + if (dvr_enabled) {
  621 + return ret;
  622 + }
  623 +
  624 + if (!_srs_config->get_dvr_enabled(req->vhost)) {
  625 + return ret;
  626 + }
  627 +
  628 + if ((ret = segment->open(false)) != ERROR_SUCCESS) {
  629 + return ret;
  630 + }
  631 +
  632 + dvr_enabled = true;
  633 +
  634 + return ret;
  635 +}
  636 +
  637 +void SrsDvrAppendPlan::on_unpublish()
  638 +{
  639 +}
  640 +
604 SrsDvrSegmentPlan::SrsDvrSegmentPlan() 641 SrsDvrSegmentPlan::SrsDvrSegmentPlan()
605 { 642 {
606 segment_duration = -1; 643 segment_duration = -1;
@@ -113,8 +113,9 @@ public: @@ -113,8 +113,9 @@ public:
113 /** 113 /**
114 * open new segment file, timestamp start at 0 for fresh flv file. 114 * open new segment file, timestamp start at 0 for fresh flv file.
115 * @remark ignore when already open. 115 * @remark ignore when already open.
  116 + * @param use_tmp_file whether use tmp file if possible.
116 */ 117 */
117 - virtual int open(); 118 + virtual int open(bool use_tmp_file = true);
118 /** 119 /**
119 * close current segment. 120 * close current segment.
120 * @remark ignore when already closed. 121 * @remark ignore when already closed.
@@ -208,6 +209,19 @@ public: @@ -208,6 +209,19 @@ public:
208 }; 209 };
209 210
210 /** 211 /**
  212 +* always append to flv file, never reap it.
  213 +*/
  214 +class SrsDvrAppendPlan : public SrsDvrPlan
  215 +{
  216 +public:
  217 + SrsDvrAppendPlan();
  218 + virtual ~SrsDvrAppendPlan();
  219 +public:
  220 + virtual int on_publish();
  221 + virtual void on_unpublish();
  222 +};
  223 +
  224 +/**
211 * segment plan: reap flv when duration exceed. 225 * segment plan: reap flv when duration exceed.
212 */ 226 */
213 class SrsDvrSegmentPlan : public SrsDvrPlan 227 class SrsDvrSegmentPlan : public SrsDvrPlan