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

fix #177, dvr segment add config dvr_wait_keyframe. 0.9.213.

This commit is contained in:
winlin 2014-09-25 10:59:29 +08:00
parent 87aac3ddd4
commit 83f266b9e2
8 changed files with 110 additions and 20 deletions

View file

@ -1301,7 +1301,7 @@ int SrsConfig::check_config()
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"
&& m != "dvr_duration" && m != "time_jitter"
&& m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter"
) {
ret = ERROR_SYSTEM_CONFIG_INVALID;
srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret);
@ -2968,6 +2968,23 @@ int SrsConfig::get_dvr_duration(string vhost)
return ::atoi(conf->arg0().c_str());
}
bool SrsConfig::get_dvr_wait_keyframe(string vhost)
{
SrsConfDirective* dvr = get_dvr(vhost);
if (!dvr) {
return true;
}
SrsConfDirective* conf = dvr->get("dvr_wait_keyframe");
if (!conf || conf->arg0() != "off") {
return true;
}
return false;
}
int SrsConfig::get_dvr_time_jitter(string vhost)
{
SrsConfDirective* dvr = get_dvr(vhost);

View file

@ -850,6 +850,10 @@ public:
*/
virtual int get_dvr_duration(std::string vhost);
/**
* whether wait keyframe to reap segment, for segment plan.
*/
virtual bool get_dvr_wait_keyframe(std::string vhost);
/**
* get the time_jitter algorithm for dvr.
*/
virtual int get_dvr_time_jitter(std::string vhost);

View file

@ -256,12 +256,14 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video)
return ret;
}
int32_t timestamp = filter_timestamp(video->header.timestamp);
if ((ret = enc->write_video(timestamp, payload, size)) != ERROR_SUCCESS) {
// update segment duration, session plan just update the duration,
// the segment plan will reap segment if exceed, this video will write to next segment.
if ((ret = update_duration(video)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = update_duration(video)) != ERROR_SUCCESS) {
int32_t timestamp = filter_timestamp(video->header.timestamp);
if ((ret = enc->write_video(timestamp, payload, size)) != ERROR_SUCCESS) {
return ret;
}
@ -478,28 +480,48 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
srs_assert(segment);
// reap if exceed duration.
if (segment_duration > 0 && segment->duration > segment_duration) {
if ((ret = flv_close()) != ERROR_SUCCESS) {
segment->reset();
return ret;
}
on_unpublish();
// open new flv file
if ((ret = open_new_segment()) != ERROR_SUCCESS) {
// ignore if duration ok.
if (segment_duration <= 0 || segment->duration < segment_duration) {
return ret;
}
// when wait keyframe, ignore if no frame arrived.
// @see https://github.com/winlinvip/simple-rtmp-server/issues/177
if (_srs_config->get_dvr_wait_keyframe(_req->vhost)) {
if (!msg->header.is_video()) {
return ret;
}
// update sequence header
if (sh_video && (ret = SrsDvrPlan::on_video(sh_video)) != ERROR_SUCCESS) {
return ret;
}
if (sh_audio && (ret = SrsDvrPlan::on_audio(sh_audio)) != ERROR_SUCCESS) {
char* payload = (char*)msg->payload;
int size = (int)msg->size;
bool is_key_frame = SrsFlvCodec::video_is_h264(payload, size)
&& SrsFlvCodec::video_is_keyframe(payload, size)
&& !SrsFlvCodec::video_is_sequence_header(payload, size);
if (!is_key_frame) {
return ret;
}
}
// reap segment
if ((ret = flv_close()) != ERROR_SUCCESS) {
segment->reset();
return ret;
}
on_unpublish();
// open new flv file
if ((ret = open_new_segment()) != ERROR_SUCCESS) {
return ret;
}
// update sequence header
if (sh_video && (ret = SrsDvrPlan::on_video(sh_video)) != ERROR_SUCCESS) {
return ret;
}
if (sh_audio && (ret = SrsDvrPlan::on_audio(sh_audio)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}