support live flashP2P(integrated by chnvideo VDN). 0.9.75

pull/133/head
winlin 11 years ago
parent b276714573
commit 67e1988b81

@ -157,6 +157,7 @@ Supported operating systems and hardware:
1. Support stream ingester using ffmpeg. 1. Support stream ingester using ffmpeg.
1. Support ingest RTSP(RTP, SDP) stream to RTMP. 1. Support ingest RTSP(RTP, SDP) stream to RTMP.
1. Support dvr(record live to flv file for vod) 1. Support dvr(record live to flv file for vod)
1. Support live flashP2P(integrated by chnvideo VDN).
1. [plan] Support file to hls vod stream. 1. [plan] Support file to hls vod stream.
1. [plan] Support system full utest on gtest. 1. [plan] Support system full utest on gtest.
1. [plan] Support RTMP edge server, push/pull stream from any RTMP server 1. [plan] Support RTMP edge server, push/pull stream from any RTMP server
@ -184,6 +185,7 @@ Supported operating systems and hardware:
* 2013-10-17, Created.<br/> * 2013-10-17, Created.<br/>
## History ## History
* v1.0, 2014-04-24, support live flashP2P(integrated by chnvideo VDN). 0.9.75
* v1.0, 2014-04-21, support android app to start srs for internal edge. 0.9.72 * v1.0, 2014-04-21, support android app to start srs for internal edge. 0.9.72
* v1.0, 2014-04-19, support tool over srs-librtmp to ingest flv/rtmp. 0.9.71 * v1.0, 2014-04-19, support tool over srs-librtmp to ingest flv/rtmp. 0.9.71
* v1.0, 2014-04-17, support dvr(record live to flv file for vod). 0.9.69 * v1.0, 2014-04-17, support dvr(record live to flv file for vod). 0.9.69

@ -97,7 +97,7 @@ vhost dvr.srs.com {
# start to record to file when encoder publish, # start to record to file when encoder publish,
# reap flv according by specified dvr_plan. # reap flv according by specified dvr_plan.
# http callbacks: # http callbacks:
# @see http callback on_dvr_keyframe on http_hooks section. # @see http callback on_dvr_reap_flv on http_hooks section.
dvr { dvr {
# whether enabled dvr features # whether enabled dvr features
# default: off # default: off
@ -325,16 +325,22 @@ vhost hooks.callback.srs.com {
# when dvr got an keyframe, call the hook, # when dvr got an keyframe, call the hook,
# the request in the POST data string is a object encode by json: # the request in the POST data string is a object encode by json:
# { # {
# "action": "on_dvr_keyframe", # "action": "on_dvr_reap_flv",
# "vhost": "video.test.com", "app": "live", # "vhost": "video.test.com", "app": "live",
# "stream": "livestream" # "stream": "livestream",
# "segment": {
# "cwd": "/usr/local/srs",
# "path": "./objs/nginx/html/live/livestream.1398315892865.flv",
# "duration": 1001, "offset":0,
# "has_keyframe": true, "pts":1398315895958
# }
# } # }
# if valid, the hook must return HTTP code 200(Stauts OK) and response # if valid, the hook must return HTTP code 200(Stauts OK) and response
# an int value specifies the error code(0 corresponding to success): # an int value specifies the error code(0 corresponding to success):
# 0 # 0
# support multiple api hooks, format: # support multiple api hooks, format:
# on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN
on_dvr_keyframe http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs; on_dvr_reap_flv http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs;
} }
} }

@ -1560,7 +1560,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost)
return conf->get("on_stop"); return conf->get("on_stop");
} }
SrsConfDirective* SrsConfig::get_vhost_on_dvr_keyframe(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_dvr_reap_flv(string vhost)
{ {
SrsConfDirective* conf = get_vhost(vhost); SrsConfDirective* conf = get_vhost(vhost);
@ -1578,7 +1578,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_dvr_keyframe(string vhost)
return NULL; return NULL;
} }
return conf->get("on_dvr_keyframe"); return conf->get("on_dvr_reap_flv");
} }
bool SrsConfig::get_vhost_enabled(string vhost) bool SrsConfig::get_vhost_enabled(string vhost)

@ -175,7 +175,7 @@ public:
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_play(std::string vhost); virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
virtual SrsConfDirective* get_vhost_on_dvr_keyframe(std::string vhost); virtual SrsConfDirective* get_vhost_on_dvr_reap_flv(std::string vhost);
virtual bool get_gop_cache(std::string vhost); virtual bool get_gop_cache(std::string vhost);
virtual bool get_atc(std::string vhost); virtual bool get_atc(std::string vhost);
virtual double get_queue_length(std::string vhost); virtual double get_queue_length(std::string vhost);

@ -138,6 +138,11 @@ int SrsFileStream::write(void* buf, size_t count, ssize_t* pnwrite)
return ret; return ret;
} }
int64_t SrsFileStream::tellg()
{
return (int64_t)::lseek(fd, 0, SEEK_CUR);
}
SrsFlvEncoder::SrsFlvEncoder() SrsFlvEncoder::SrsFlvEncoder()
{ {
_fs = NULL; _fs = NULL;
@ -209,10 +214,12 @@ int SrsFlvEncoder::write_metadata(char* data, int size)
return ret; return ret;
} }
int SrsFlvEncoder::write_audio(int32_t timestamp, char* data, int size) int SrsFlvEncoder::write_audio(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
timestamp &= 0x7fffffff;
static char tag_header[] = { static char tag_header[] = {
(char)8, // TagType UB [5], 8 = audio (char)8, // TagType UB [5], 8 = audio
(char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
@ -238,10 +245,12 @@ int SrsFlvEncoder::write_audio(int32_t timestamp, char* data, int size)
return ret; return ret;
} }
int SrsFlvEncoder::write_video(int32_t timestamp, char* data, int size) int SrsFlvEncoder::write_video(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
timestamp &= 0x7fffffff;
static char tag_header[] = { static char tag_header[] = {
(char)9, // TagType UB [5], 9 = video (char)9, // TagType UB [5], 9 = video
(char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
@ -303,6 +312,7 @@ SrsFlvSegment::SrsFlvSegment()
has_keyframe = false; has_keyframe = false;
duration = 0; duration = 0;
starttime = -1; starttime = -1;
sequence_header_offset = 0;
stream_starttime = 0; stream_starttime = 0;
stream_previous_pkt_time = -1; stream_previous_pkt_time = -1;
stream_duration = 0; stream_duration = 0;
@ -313,6 +323,7 @@ void SrsFlvSegment::reset()
has_keyframe = false; has_keyframe = false;
starttime = -1; starttime = -1;
duration = 0; duration = 0;
sequence_header_offset = 0;
} }
SrsDvrPlan::SrsDvrPlan() SrsDvrPlan::SrsDvrPlan()
@ -396,14 +407,32 @@ int SrsDvrPlan::open_new_segment()
} }
dvr_enabled = true; dvr_enabled = true;
return ret;
}
int SrsDvrPlan::on_dvr_request_sh()
{
int ret = ERROR_SUCCESS;
// the dvr is enabled, notice the source to push the data. // the dvr is enabled, notice the source to push the data.
if ((ret = _source->on_dvr_start()) != ERROR_SUCCESS) { if ((ret = _source->on_dvr_request_sh()) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int SrsDvrPlan::on_video_keyframe()
{
int ret = ERROR_SUCCESS;
return ret;
}
int64_t SrsDvrPlan::filter_timestamp(int64_t timestamp)
{
return timestamp;
}
int SrsDvrPlan::on_meta_data(SrsOnMetaDataPacket* metadata) int SrsDvrPlan::on_meta_data(SrsOnMetaDataPacket* metadata)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -438,9 +467,9 @@ int SrsDvrPlan::on_audio(SrsSharedPtrMessage* audio)
return ret; return ret;
} }
int32_t timestamp = audio->header.timestamp;
char* payload = (char*)audio->payload; char* payload = (char*)audio->payload;
int size = (int)audio->size; int size = (int)audio->size;
int64_t timestamp = filter_timestamp(audio->header.timestamp);
if ((ret = enc->write_audio(timestamp, payload, size)) != ERROR_SUCCESS) { if ((ret = enc->write_audio(timestamp, payload, size)) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -460,25 +489,31 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video)
return ret; return ret;
} }
if ((jitter->correct(video, 0, 0)) != ERROR_SUCCESS) {
return ret;
}
int32_t timestamp = video->header.timestamp;
char* payload = (char*)video->payload; char* payload = (char*)video->payload;
int size = (int)video->size; int size = (int)video->size;
if ((ret = enc->write_video(timestamp, payload, size)) != ERROR_SUCCESS) {
return ret;
}
#ifdef SRS_AUTO_HTTP_CALLBACK #ifdef SRS_AUTO_HTTP_CALLBACK
bool is_key_frame = SrsCodec::video_is_keyframe((int8_t*)payload, size); bool is_key_frame = SrsCodec::video_is_h264((int8_t*)payload, size)
&& SrsCodec::video_is_keyframe((int8_t*)payload, size)
&& !SrsCodec::video_is_sequence_header((int8_t*)payload, size);
if (is_key_frame) { if (is_key_frame) {
segment->has_keyframe = true; segment->has_keyframe = true;
if ((ret = on_video_keyframe()) != ERROR_SUCCESS) {
return ret;
}
} }
srs_verbose("dvr video is key: %d", is_key_frame); srs_verbose("dvr video is key: %d", is_key_frame);
#endif #endif
if ((jitter->correct(video, 0, 0)) != ERROR_SUCCESS) {
return ret;
}
int32_t timestamp = filter_timestamp(video->header.timestamp);
if ((ret = enc->write_video(timestamp, payload, size)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = update_duration(video)) != ERROR_SUCCESS) { if ((ret = update_duration(video)) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -503,8 +538,7 @@ int SrsDvrPlan::flv_open(string stream, string path)
return ret; return ret;
} }
if ((ret = enc->write_header()) != ERROR_SUCCESS) { if ((ret = write_flv_header()) != ERROR_SUCCESS) {
srs_error("write flv header for file %s failed. ret=%d", path.c_str(), ret);
return ret; return ret;
} }
@ -531,10 +565,8 @@ int SrsDvrPlan::flv_close()
} }
#ifdef SRS_AUTO_HTTP_CALLBACK #ifdef SRS_AUTO_HTTP_CALLBACK
if (segment->has_keyframe) { if ((ret = on_dvr_reap_flv()) != ERROR_SUCCESS) {
if ((ret = on_dvr_keyframe()) != ERROR_SUCCESS) { return ret;
return ret;
}
} }
#endif #endif
@ -568,21 +600,33 @@ int SrsDvrPlan::update_duration(SrsSharedPtrMessage* msg)
return ret; return ret;
} }
int SrsDvrPlan::on_dvr_keyframe() int SrsDvrPlan::write_flv_header()
{
int ret = ERROR_SUCCESS;
if ((ret = enc->write_header()) != ERROR_SUCCESS) {
srs_error("write flv header failed. ret=%d", ret);
return ret;
}
return ret;
}
int SrsDvrPlan::on_dvr_reap_flv()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
#ifdef SRS_AUTO_HTTP_CALLBACK #ifdef SRS_AUTO_HTTP_CALLBACK
// HTTP: on_dvr_keyframe // HTTP: on_dvr_reap_flv
SrsConfDirective* on_dvr_keyframe = _srs_config->get_vhost_on_dvr_keyframe(_req->vhost); SrsConfDirective* on_dvr_reap_flv = _srs_config->get_vhost_on_dvr_reap_flv(_req->vhost);
if (!on_dvr_keyframe) { if (!on_dvr_reap_flv) {
srs_info("ignore the empty http callback: on_dvr_keyframe"); srs_info("ignore the empty http callback: on_dvr_reap_flv");
return ret; return ret;
} }
for (int i = 0; i < (int)on_dvr_keyframe->args.size(); i++) { for (int i = 0; i < (int)on_dvr_reap_flv->args.size(); i++) {
std::string url = on_dvr_keyframe->args.at(i); std::string url = on_dvr_reap_flv->args.at(i);
SrsHttpHooks::on_dvr_keyframe(url, _req, segment); SrsHttpHooks::on_dvr_reap_flv(url, _req, segment);
} }
#endif #endif
@ -705,7 +749,6 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
SrsDvrHssPlan::SrsDvrHssPlan() SrsDvrHssPlan::SrsDvrHssPlan()
{ {
segment_duration = -1; segment_duration = -1;
start_deviation = 0;
expect_reap_time = 0; expect_reap_time = 0;
} }
@ -748,8 +791,6 @@ int SrsDvrHssPlan::on_publish()
// expect reap flv time // expect reap flv time
expect_reap_time = segment->stream_starttime + segment_duration; expect_reap_time = segment->stream_starttime + segment_duration;
// the start deviation used ensure the segment starttime in nature clock.
start_deviation = segment->stream_starttime % 1000;
return ret; return ret;
} }
@ -763,6 +804,44 @@ void SrsDvrHssPlan::on_unpublish()
dvr_enabled = false; dvr_enabled = false;
} }
int SrsDvrHssPlan::on_meta_data(SrsOnMetaDataPacket* /*metadata*/)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrHssPlan::write_flv_header()
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrHssPlan::on_dvr_request_sh()
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrHssPlan::on_video_keyframe()
{
int ret = ERROR_SUCCESS;
segment->sequence_header_offset = fs->tellg();
if ((ret = SrsDvrPlan::on_dvr_request_sh()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int64_t SrsDvrHssPlan::filter_timestamp(int64_t timestamp)
{
//return timestamp;
srs_assert(segment);
srs_verbose("filter timestamp from %"PRId64" to %"PRId64, timestamp, segment->stream_starttime + timestamp);
return segment->stream_starttime + timestamp;
}
int SrsDvrHssPlan::update_duration(SrsSharedPtrMessage* msg) int SrsDvrHssPlan::update_duration(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -784,10 +863,9 @@ int SrsDvrHssPlan::update_duration(SrsSharedPtrMessage* msg)
// reap if exceed atc expect time. // reap if exceed atc expect time.
if (segment->stream_starttime + segment->stream_duration > expect_reap_time) { if (segment->stream_starttime + segment->stream_duration > expect_reap_time) {
srs_verbose("hss reap start=%"PRId64", duration=%"PRId64", expect=%"PRId64 srs_verbose("hss reap start=%"PRId64", duration=%"PRId64", expect=%"PRId64
", segment(start=%"PRId64", adjust=%"PRId64", duration=%"PRId64", file=%s", ", segment(start=%"PRId64", duration=%"PRId64", file=%s",
segment->stream_starttime, segment->stream_duration, expect_reap_time, segment->stream_starttime, segment->stream_duration, expect_reap_time,
segment->stream_starttime + segment->starttime, segment->stream_starttime + segment->starttime,
segment->stream_starttime + segment->starttime - start_deviation,
segment->duration, segment->path.c_str()); segment->duration, segment->path.c_str());
// update expect reap time // update expect reap time

@ -62,6 +62,10 @@ public:
* @param pnwrite, return the write size. NULL to ignore. * @param pnwrite, return the write size. NULL to ignore.
*/ */
virtual int write(void* buf, size_t count, ssize_t* pnwrite); virtual int write(void* buf, size_t count, ssize_t* pnwrite);
/**
* tell current offset of stream.
*/
virtual int64_t tellg();
}; };
/** /**
@ -101,8 +105,8 @@ public:
/** /**
* write audio/video packet. * write audio/video packet.
*/ */
virtual int write_audio(int32_t timestamp, char* data, int size); virtual int write_audio(int64_t timestamp, char* data, int size);
virtual int write_video(int32_t timestamp, char* data, int size); virtual int write_video(int64_t timestamp, char* data, int size);
private: private:
virtual int write_tag(char* header, int header_size, char* tag, int tag_size); virtual int write_tag(char* header, int header_size, char* tag, int tag_size);
}; };
@ -122,6 +126,10 @@ public:
*/ */
bool has_keyframe; bool has_keyframe;
/** /**
* sequence header offset in file.
*/
int64_t sequence_header_offset;
/**
* current segment starttime, RTMP pkt time. * current segment starttime, RTMP pkt time.
*/ */
int64_t starttime; int64_t starttime;
@ -184,12 +192,15 @@ protected:
virtual int flv_close(); virtual int flv_close();
virtual int open_new_segment(); virtual int open_new_segment();
virtual int update_duration(SrsSharedPtrMessage* msg); virtual int update_duration(SrsSharedPtrMessage* msg);
virtual int write_flv_header();
virtual int on_dvr_request_sh();
virtual int on_video_keyframe();
virtual int64_t filter_timestamp(int64_t timestamp);
private: private:
/** /**
* when srs reap the flv(close the segment), * when srs reap the flv(close the segment), notice the api.
* if has keyframe, notice the api.
*/ */
virtual int on_dvr_keyframe(); virtual int on_dvr_reap_flv();
public: public:
static SrsDvrPlan* create_plan(std::string vhost); static SrsDvrPlan* create_plan(std::string vhost);
}; };
@ -233,8 +244,6 @@ class SrsDvrHssPlan : public SrsDvrPlan
private: private:
// in config, in ms // in config, in ms
int segment_duration; int segment_duration;
// the deviation of starttime of the nature clock time.
int start_deviation;
int64_t expect_reap_time; int64_t expect_reap_time;
public: public:
SrsDvrHssPlan(); SrsDvrHssPlan();
@ -243,6 +252,12 @@ public:
virtual int initialize(SrsSource* source, SrsRequest* req); virtual int initialize(SrsSource* source, SrsRequest* req);
virtual int on_publish(); virtual int on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
protected:
virtual int write_flv_header();
virtual int on_dvr_request_sh();
virtual int on_video_keyframe();
virtual int64_t filter_timestamp(int64_t timestamp);
private: private:
virtual int update_duration(SrsSharedPtrMessage* msg); virtual int update_duration(SrsSharedPtrMessage* msg);
}; };

@ -459,7 +459,7 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
return; return;
} }
void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req, SrsFlvSegment* segment) void SrsHttpHooks::on_dvr_reap_flv(string url, SrsRequest* req, SrsFlvSegment* segment)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -471,23 +471,24 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req, SrsFlvSegment* s
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_dvr_keyframe url failed, ignored. " srs_warn("http uri parse on_dvr_reap_flv url failed, ignored. "
"url=%s, ret=%d", url.c_str(), ret); "url=%s, ret=%d", url.c_str(), ret);
return; return;
} }
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_dvr_keyframe") << JFIELD_CONT << JFIELD_STR("action", "on_dvr_reap_flv") << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT << JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("stream", req->stream) << JFIELD_CONT << JFIELD_STR("stream", req->stream) << JFIELD_CONT
<< JFIELD_NAME("segment") << JOBJECT_START << JFIELD_NAME("segment") << JOBJECT_START
<< JFIELD_STR("cwd", _srs_config->get_cwd()) << JFIELD_CONT << JFIELD_STR("cwd", _srs_config->get_cwd()) << JFIELD_CONT
<< JFIELD_STR("path", segment->path) << JFIELD_CONT << JFIELD_STR("path", segment->path) << JFIELD_CONT
<< JFIELD_ORG("pts", segment->stream_starttime + segment->starttime) << JFIELD_CONT
<< JFIELD_ORG("duration", segment->duration) << JFIELD_CONT << JFIELD_ORG("duration", segment->duration) << JFIELD_CONT
<< JFIELD_ORG("offset", 0) << JFIELD_ORG("offset", segment->sequence_header_offset) << JFIELD_CONT
<< JFIELD_ORG("has_keyframe", (segment->has_keyframe? "true":"false")) << JFIELD_CONT
<< JFIELD_ORG("pts", segment->stream_starttime + segment->starttime)
<< JOBJECT_END << JOBJECT_END
<< JOBJECT_END; << JOBJECT_END;
std::string data = ss.str(); std::string data = ss.str();
@ -495,7 +496,7 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req, SrsFlvSegment* s
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_dvr_keyframe uri failed, ignored. " srs_warn("http post on_dvr_reap_flv uri failed, ignored. "
"url=%s, request=%s, response=%s, ret=%d", "url=%s, request=%s, response=%s, ret=%d",
url.c_str(), data.c_str(), res.c_str(), ret); url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
@ -503,12 +504,12 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req, SrsFlvSegment* s
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_dvr_keyframe validate failed, ignored. " srs_warn("http hook on_dvr_reap_flv validate failed, ignored. "
"res=%s, ret=%d", res.c_str(), ret); "res=%s, ret=%d", res.c_str(), ret);
return; return;
} }
srs_info("http hook on_dvr_keyframe success. " srs_info("http hook on_dvr_reap_flv success. "
"url=%s, request=%s, response=%s, ret=%d", "url=%s, request=%s, response=%s, ret=%d",
url.c_str(), data.c_str(), res.c_str(), ret); url.c_str(), data.c_str(), res.c_str(), ret);

@ -124,12 +124,12 @@ public:
static void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); static void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
public: public:
/** /**
* on_dvr_keyframe hook, when dvr get keyframe. * on_dvr_reap_flv hook, when dvr close flv file.
* @param url the api server url, to process the event. * @param url the api server url, to process the event.
* ignore if empty. * ignore if empty.
* @param segment the current flv segment. * @param segment the current flv segment.
*/ */
static void on_dvr_keyframe(std::string url, SrsRequest* req, SrsFlvSegment* segment); static void on_dvr_reap_flv(std::string url, SrsRequest* req, SrsFlvSegment* segment);
}; };
#endif #endif

@ -721,14 +721,14 @@ int SrsSource::on_hls_start()
return ret; return ret;
} }
int SrsSource::on_dvr_start() int SrsSource::on_dvr_request_sh()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
#ifdef SRS_AUTO_DVR #ifdef SRS_AUTO_DVR
// feed the dvr the metadata/sequence header, // feed the dvr the metadata/sequence header,
// when reload to start dvr, dvr will never get the sequence header in stream, // when reload to start dvr, dvr will never get the sequence header in stream,
// use the SrsSource.on_dvr_start to push the sequence header to DVR. // use the SrsSource.on_dvr_request_sh to push the sequence header to DVR.
if (cache_metadata) { if (cache_metadata) {
char* payload = (char*)cache_metadata->payload; char* payload = (char*)cache_metadata->payload;
int size = (int)cache_metadata->size; int size = (int)cache_metadata->size;

@ -288,7 +288,7 @@ public:
// for the SrsHls to callback to request the sequence headers. // for the SrsHls to callback to request the sequence headers.
virtual int on_hls_start(); virtual int on_hls_start();
// for the SrsDvr to callback to request the sequence headers. // for the SrsDvr to callback to request the sequence headers.
virtual int on_dvr_start(); virtual int on_dvr_request_sh();
public: public:
virtual bool can_publish(); virtual bool can_publish();
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);

@ -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 "0" #define VERSION_MAJOR "0"
#define VERSION_MINOR "9" #define VERSION_MINOR "9"
#define VERSION_REVISION "74" #define VERSION_REVISION "75"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info. // server info.
#define RTMP_SIG_SRS_KEY "srs" #define RTMP_SIG_SRS_KEY "srs"

Loading…
Cancel
Save