1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

for #738, remove the dvr plan append for it's no use

This commit is contained in:
winlin 2017-02-06 20:22:07 +08:00
parent 8c01f52372
commit 0a054cd6bd
5 changed files with 245 additions and 382 deletions

View file

@ -1120,8 +1120,7 @@ vhost dvr.srs.com {
# the dvr plan. canbe: # the dvr plan. canbe:
# session reap flv/mp4 when session end(unpublish). # session reap flv/mp4 when session end(unpublish).
# segment reap flv/mp4 when flv duration exceed the specified dvr_duration. # segment reap flv/mp4 when flv duration exceed the specified dvr_duration.
# append always append to flv file, never reap it. # @remark The plan append is removed in SRS3+, for it's no use.
# @remark MP4 only support session or segment plan, not suport append plan.
# default: session # default: session
dvr_plan session; dvr_plan session;
# the dvr output path, *.flv or *.mp4. # the dvr output path, *.flv or *.mp4.
@ -1159,8 +1158,8 @@ vhost dvr.srs.com {
# dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].mp4; # dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].mp4;
# => # =>
# dvr_path ./objs/nginx/html/live/livestream.1420254068776.mp4; # dvr_path ./objs/nginx/html/live/livestream.1420254068776.mp4;
# @see https://github.com/ossrs/srs/wiki/v2_CN_DVR#custom-path # @see https://github.com/ossrs/srs/wiki/v3_CN_DVR#custom-path
# @see https://github.com/ossrs/srs/wiki/v2_EN_DVR#custom-path # @see https://github.com/ossrs/srs/wiki/v3_EN_DVR#custom-path
# segment,session apply it. # segment,session apply it.
# default: ./objs/nginx/html/[app]/[stream].[timestamp].flv # default: ./objs/nginx/html/[app]/[stream].[timestamp].flv
dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].flv; dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].flv;

View file

@ -283,11 +283,6 @@ bool srs_config_dvr_is_plan_session(string plan)
return plan == "session"; return plan == "session";
} }
bool srs_config_dvr_is_plan_append(string plan)
{
return plan == "append";
}
bool srs_stream_caster_is_udp(string caster) bool srs_stream_caster_is_udp(string caster)
{ {
return caster == "mpegts_over_udp"; return caster == "mpegts_over_udp";

View file

@ -99,7 +99,6 @@ extern bool srs_config_ingest_is_file(std::string type);
extern bool srs_config_ingest_is_stream(std::string type); extern bool srs_config_ingest_is_stream(std::string type);
extern bool srs_config_dvr_is_plan_segment(std::string plan); extern bool srs_config_dvr_is_plan_segment(std::string plan);
extern bool srs_config_dvr_is_plan_session(std::string plan); extern bool srs_config_dvr_is_plan_session(std::string plan);
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_udp(std::string caster);
extern bool srs_stream_caster_is_rtsp(std::string caster); extern bool srs_stream_caster_is_rtsp(std::string caster);
extern bool srs_stream_caster_is_flv(std::string caster); extern bool srs_stream_caster_is_flv(std::string caster);

View file

@ -76,8 +76,8 @@ int SrsDvrSegmenter::initialize(SrsDvrPlan* p, SrsRequest* r)
req = r; req = r;
plan = p; plan = p;
int jitter = _srs_config->get_dvr_time_jitter(req->vhost); jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(req->vhost);
jitter_algorithm = (SrsRtmpJitterAlgorithm)jitter; wait_keyframe = _srs_config->get_dvr_wait_keyframe(req->vhost);
return ret; return ret;
} }
@ -92,7 +92,7 @@ bool SrsDvrSegmenter::is_overflow(int64_t max_duration)
return duration >= max_duration; return duration >= max_duration;
} }
int SrsDvrSegmenter::open(bool use_tmp_file) int SrsDvrSegmenter::open()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -102,10 +102,7 @@ int SrsDvrSegmenter::open(bool use_tmp_file)
} }
path = generate_path(); path = generate_path();
bool can_append = srs_string_ends_with(path, ".flv"); if (srs_path_exists(path)) {
bool target_exists = srs_path_exists(path);
if (!can_append && target_exists) {
ret = ERROR_DVR_CANNOT_APPEND; ret = ERROR_DVR_CANNOT_APPEND;
srs_error("DVR can't append to exists path=%s. ret=%d", path.c_str(), ret); srs_error("DVR can't append to exists path=%s. ret=%d", path.c_str(), ret);
return ret; return ret;
@ -120,37 +117,23 @@ int SrsDvrSegmenter::open(bool use_tmp_file)
srs_info("create dir=%s ok", dir.c_str()); srs_info("create dir=%s ok", dir.c_str());
// create jitter. // create jitter.
if ((ret = create_jitter(target_exists)) != ERROR_SUCCESS) { if ((ret = create_jitter()) != ERROR_SUCCESS) {
srs_error("create jitter failed, path=%s, exists=%d. ret=%d", path.c_str(), target_exists, ret); srs_error("create jitter failed, path=%s. ret=%d", path.c_str(), ret);
return ret; return ret;
} }
// generate the tmp flv path. // generate the tmp flv path.
if (target_exists || !use_tmp_file) { tmp_dvr_file = path + ".tmp";
// when path exists, always append to it.
// so we must use the target flv path as output flv.
tmp_dvr_file = path;
} else {
// when path not exists, dvr to tmp file.
tmp_dvr_file = path + ".tmp";
}
// open file writer, in append or create mode. // open file writer, in append or create mode.
if (target_exists) { if ((ret = fs->open(tmp_dvr_file)) != ERROR_SUCCESS) {
if ((ret = fs->open_append(tmp_dvr_file)) != ERROR_SUCCESS) { srs_error("open file stream for file %s failed. ret=%d", path.c_str(), ret);
srs_error("append file stream for file %s failed. ret=%d", path.c_str(), ret); return ret;
return ret;
}
srs_trace("dvr: always append to when exists, file=%s.", path.c_str());
} else {
if ((ret = fs->open(tmp_dvr_file)) != ERROR_SUCCESS) {
srs_error("open file stream for file %s failed. ret=%d", path.c_str(), ret);
return ret;
}
} }
// initialize the encoder. // initialize the encoder.
if ((ret = open_encoder()) != ERROR_SUCCESS) { if ((ret = open_encoder()) != ERROR_SUCCESS) {
srs_error("initialize enc by fs for file %s failed. ret=%d", path.c_str(), ret);
return ret; return ret;
} }
@ -159,6 +142,62 @@ int SrsDvrSegmenter::open(bool use_tmp_file)
return ret; return ret;
} }
int SrsDvrSegmenter::write_metadata(SrsSharedPtrMessage* metadata)
{
return encode_metadata(metadata);
}
int SrsDvrSegmenter::write_audio(SrsSharedPtrMessage* shared_audio)
{
int ret = ERROR_SUCCESS;
SrsSharedPtrMessage* audio = shared_audio->copy();
SrsAutoFree(SrsSharedPtrMessage, audio);
if ((jitter->correct(audio, jitter_algorithm)) != ERROR_SUCCESS) {
return ret;
}
int64_t timestamp = plan->filter_timestamp(audio->timestamp);
if ((ret = encode_audio(audio, timestamp)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsDvrSegmenter::write_video(SrsSharedPtrMessage* shared_video)
{
int ret = ERROR_SUCCESS;
SrsSharedPtrMessage* video = shared_video->copy();
SrsAutoFree(SrsSharedPtrMessage, video);
if ((jitter->correct(video, jitter_algorithm)) != ERROR_SUCCESS) {
return ret;
}
char* payload = video->payload;
int size = video->size;
bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(payload, size);
bool is_key_frame = SrsFlvCodec::video_is_h264(payload, size)
&& SrsFlvCodec::video_is_keyframe(payload, size) && !is_sequence_header;
if (is_key_frame) {
if ((ret = plan->on_video_keyframe()) != ERROR_SUCCESS) {
return ret;
}
}
srs_verbose("dvr video is key: %d", is_key_frame);
int64_t timestamp = plan->filter_timestamp(video->timestamp);
if ((ret = encode_video(video, timestamp, is_sequence_header, is_key_frame)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsDvrSegmenter::close() int SrsDvrSegmenter::close()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -214,40 +253,28 @@ string SrsDvrSegmenter::generate_path()
return flv_path; return flv_path;
} }
int SrsDvrSegmenter::create_jitter(bool target_exists) int SrsDvrSegmenter::create_jitter()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// When DVR target file not exists, create new jitter. srs_freep(jitter);
if (!target_exists) {
// jitter when publish, ensure whole stream start from 0.
srs_freep(jitter);
jitter = new SrsRtmpJitter();
duration = 0;
return ret;
}
// when jitter ok, do nothing.
if (jitter) {
return ret;
}
// always ensure the jitter crote.
// for the first time, initialize jitter from exists file.
jitter = new SrsRtmpJitter(); jitter = new SrsRtmpJitter();
// TODO: FIXME: implements it. duration = 0;
return ret; return ret;
} }
int SrsDvrSegmenter::on_reload_vhost_dvr(std::string /*vhost*/) int SrsDvrSegmenter::on_reload_vhost_dvr(std::string vhost)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (req->vhost != vhost) {
return ret;
}
jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(req->vhost); jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(req->vhost);
wait_keyframe = _srs_config->get_dvr_wait_keyframe(req->vhost);
return ret; return ret;
} }
@ -272,73 +299,92 @@ SrsDvrFlvSegmenter::~SrsDvrFlvSegmenter()
srs_freep(enc); srs_freep(enc);
} }
int SrsDvrFlvSegmenter::refresh_metadata()
{
int ret = ERROR_SUCCESS;
// no duration or filesize specified.
if (!duration_offset || !filesize_offset) {
return ret;
}
int64_t cur = fs->tellg();
// buffer to write the size.
char* buf = new char[SrsAmf0Size::number()];
SrsAutoFreeA(char, buf);
SrsBuffer stream;
if ((ret = stream.initialize(buf, SrsAmf0Size::number())) != ERROR_SUCCESS) {
return ret;
}
// filesize to buf.
SrsAmf0Any* size = SrsAmf0Any::number((double)cur);
SrsAutoFree(SrsAmf0Any, size);
stream.skip(-1 * stream.pos());
if ((ret = size->write(&stream)) != ERROR_SUCCESS) {
return ret;
}
// update the flesize.
fs->seek2(filesize_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret;
}
// duration to buf
SrsAmf0Any* dur = SrsAmf0Any::number((double)duration / 1000.0);
SrsAutoFree(SrsAmf0Any, dur);
stream.skip(-1 * stream.pos());
if ((ret = dur->write(&stream)) != ERROR_SUCCESS) {
return ret;
}
// update the duration
fs->seek2(duration_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret;
}
// reset the offset.
fs->seek2(cur);
return ret;
}
int SrsDvrFlvSegmenter::open_encoder() int SrsDvrFlvSegmenter::open_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) { has_keyframe = false;
srs_error("initialize enc by fs for file %s failed. ret=%d", path.c_str(), ret);
return ret;
}
bool target_exists = srs_path_exists(path); // fresh stream starting.
if (target_exists){ starttime = -1;
has_keyframe = false; stream_previous_pkt_time = -1;
stream_starttime = srs_update_system_time_ms();
// fresh stream starting. stream_duration = 0;
starttime = -1;
stream_previous_pkt_time = -1;
stream_starttime = srs_update_system_time_ms();
stream_duration = 0;
// write the flv header to writer.
if ((ret = enc->write_header()) != ERROR_SUCCESS) {
srs_error("write flv header failed. ret=%d", ret);
return ret;
}
}
// update the duration and filesize offset. // update the duration and filesize offset.
duration_offset = 0; duration_offset = 0;
filesize_offset = 0; filesize_offset = 0;
return ret; if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) {
} return ret;
int SrsDvrFlvSegmenter::close_encoder()
{
return refresh_metadata();
}
int SrsDvrFlvSegmenter::on_update_duration(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
// we must assumpt that the stream timestamp is monotonically increase,
// that is, always use time jitter to correct the timestamp.
// except the time jitter is disabled in config.
// set the segment starttime at first time
if (starttime < 0) {
starttime = msg->timestamp;
} }
// no previous packet or timestamp overflow. // write the flv header to writer.
if (stream_previous_pkt_time < 0 || stream_previous_pkt_time > msg->timestamp) { if ((ret = enc->write_header()) != ERROR_SUCCESS) {
stream_previous_pkt_time = msg->timestamp; srs_error("write flv header failed. ret=%d", ret);
return ret;
} }
// collect segment and stream duration, timestamp overflow is ok.
duration += msg->timestamp - stream_previous_pkt_time;
stream_duration += msg->timestamp - stream_previous_pkt_time;
// update previous packet time
stream_previous_pkt_time = msg->timestamp;
return ret; return ret;
} }
int SrsDvrFlvSegmenter::write_metadata(SrsSharedPtrMessage* metadata) int SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage* metadata)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -401,21 +447,13 @@ int SrsDvrFlvSegmenter::write_metadata(SrsSharedPtrMessage* metadata)
return ret; return ret;
} }
int SrsDvrFlvSegmenter::write_audio(SrsSharedPtrMessage* shared_audio) int SrsDvrFlvSegmenter::encode_audio(SrsSharedPtrMessage* audio, int64_t dts)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsSharedPtrMessage* audio = shared_audio->copy();
SrsAutoFree(SrsSharedPtrMessage, audio);
if ((jitter->correct(audio, jitter_algorithm)) != ERROR_SUCCESS) {
return ret;
}
char* payload = audio->payload; char* payload = audio->payload;
int size = audio->size; int size = audio->size;
int64_t timestamp = plan->filter_timestamp(audio->timestamp); if ((ret = enc->write_audio(dts, payload, size)) != ERROR_SUCCESS) {
if ((ret = enc->write_audio(timestamp, payload, size)) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -426,107 +464,67 @@ int SrsDvrFlvSegmenter::write_audio(SrsSharedPtrMessage* shared_audio)
return ret; return ret;
} }
int SrsDvrFlvSegmenter::write_video(SrsSharedPtrMessage* shared_video) int SrsDvrFlvSegmenter::encode_video(SrsSharedPtrMessage* video, int64_t dts, bool sh, bool keyframe)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsSharedPtrMessage* video = shared_video->copy(); if (keyframe) {
SrsAutoFree(SrsSharedPtrMessage, video);
char* payload = video->payload;
int size = video->size;
bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(payload, size);
bool is_key_frame = SrsFlvCodec::video_is_h264(payload, size)
&& SrsFlvCodec::video_is_keyframe(payload, size) && !is_sequence_header;
if (is_key_frame) {
has_keyframe = true; has_keyframe = true;
if ((ret = plan->on_video_keyframe()) != ERROR_SUCCESS) {
return ret;
}
} }
srs_verbose("dvr video is key: %d", is_key_frame);
// accept the sequence header here. // accept the sequence header here.
// when got no keyframe, ignore when should wait keyframe. // when got no keyframe, ignore when should wait keyframe.
if (!has_keyframe && !is_sequence_header) { if (!has_keyframe && !sh) {
bool wait_keyframe = _srs_config->get_dvr_wait_keyframe(req->vhost);
if (wait_keyframe) { if (wait_keyframe) {
srs_info("dvr: ignore when wait keyframe."); srs_info("dvr: ignore when wait keyframe.");
return ret; return ret;
} }
} }
if ((jitter->correct(video, jitter_algorithm)) != ERROR_SUCCESS) {
return ret;
}
// update segment duration, session plan just update the duration, // update segment duration, session plan just update the duration,
// the segment plan will reap segment if exceed, this video will write to next segment. // the segment plan will reap segment if exceed, this video will write to next segment.
if ((ret = on_update_duration(video)) != ERROR_SUCCESS) { if ((ret = on_update_duration(video)) != ERROR_SUCCESS) {
return ret; return ret;
} }
int32_t timestamp = (int32_t)plan->filter_timestamp(video->timestamp); char* payload = video->payload;
if ((ret = enc->write_video(timestamp, payload, size)) != ERROR_SUCCESS) { int size = video->size;
if ((ret = enc->write_video(dts, payload, size)) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int SrsDvrFlvSegmenter::refresh_metadata() int SrsDvrFlvSegmenter::close_encoder()
{
return refresh_metadata();
}
int SrsDvrFlvSegmenter::on_update_duration(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// no duration or filesize specified. // we must assumpt that the stream timestamp is monotonically increase,
if (!duration_offset || !filesize_offset) { // that is, always use time jitter to correct the timestamp.
return ret; // except the time jitter is disabled in config.
// set the segment starttime at first time
if (starttime < 0) {
starttime = msg->timestamp;
} }
int64_t cur = fs->tellg(); // no previous packet or timestamp overflow.
if (stream_previous_pkt_time < 0 || stream_previous_pkt_time > msg->timestamp) {
// buffer to write the size. stream_previous_pkt_time = msg->timestamp;
char* buf = new char[SrsAmf0Size::number()];
SrsAutoFreeA(char, buf);
SrsBuffer stream;
if ((ret = stream.initialize(buf, SrsAmf0Size::number())) != ERROR_SUCCESS) {
return ret;
} }
// filesize to buf. // collect segment and stream duration, timestamp overflow is ok.
SrsAmf0Any* size = SrsAmf0Any::number((double)cur); duration += msg->timestamp - stream_previous_pkt_time;
SrsAutoFree(SrsAmf0Any, size); stream_duration += msg->timestamp - stream_previous_pkt_time;
stream.skip(-1 * stream.pos()); // update previous packet time
if ((ret = size->write(&stream)) != ERROR_SUCCESS) { stream_previous_pkt_time = msg->timestamp;
return ret;
}
// update the flesize.
fs->seek2(filesize_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret;
}
// duration to buf
SrsAmf0Any* dur = SrsAmf0Any::number((double)duration / 1000.0);
SrsAutoFree(SrsAmf0Any, dur);
stream.skip(-1 * stream.pos());
if ((ret = dur->write(&stream)) != ERROR_SUCCESS) {
return ret;
}
// update the duration
fs->seek2(duration_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret;
}
// reset the offset.
fs->seek2(cur);
return ret; return ret;
} }
@ -541,42 +539,42 @@ SrsDvrMp4Segmenter::~SrsDvrMp4Segmenter()
srs_freep(enc); srs_freep(enc);
} }
int SrsDvrMp4Segmenter::refresh_metadata()
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::open_encoder() int SrsDvrMp4Segmenter::open_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
return ret; return ret;
} }
int SrsDvrMp4Segmenter::encode_metadata(SrsSharedPtrMessage* metadata)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, int64_t dts)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage* video, int64_t dts, bool sh, bool keyframe)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::close_encoder() int SrsDvrMp4Segmenter::close_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
return ret; return ret;
} }
int SrsDvrMp4Segmenter::write_metadata(SrsSharedPtrMessage* metadata)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::write_audio(SrsSharedPtrMessage* shared_audio)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::write_video(SrsSharedPtrMessage* shared_video)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsDvrMp4Segmenter::refresh_metadata()
{
int ret = ERROR_SUCCESS;
return ret;
}
SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, string p) SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, string p)
{ {
cid = c; cid = c;
@ -732,23 +730,14 @@ int SrsDvrPlan::create_plan(string vhost, SrsDvrPlan** pplan)
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
std::string plan = _srs_config->get_dvr_plan(vhost); std::string plan = _srs_config->get_dvr_plan(vhost);
std::string path = _srs_config->get_dvr_path(vhost);
bool is_mp4 = srs_string_ends_with(path, ".mp4");
if (srs_config_dvr_is_plan_segment(plan)) { if (srs_config_dvr_is_plan_segment(plan)) {
*pplan = new SrsDvrSegmentPlan(); *pplan = new SrsDvrSegmentPlan();
} else if (srs_config_dvr_is_plan_session(plan)) { } else if (srs_config_dvr_is_plan_session(plan)) {
*pplan = new SrsDvrSessionPlan(); *pplan = new SrsDvrSessionPlan();
} else if (srs_config_dvr_is_plan_append(plan)) {
if (is_mp4) {
ret = ERROR_DVR_ILLEGAL_PLAN;
srs_error("DVR plan append not support MP4. ret=%d", ret);
return ret;
}
*pplan = new SrsDvrAppendPlan();
} else { } else {
srs_error("invalid dvr plan=%s, vhost=%s", plan.c_str(), vhost.c_str()); ret = ERROR_DVR_ILLEGAL_PLAN;
srs_assert(false); srs_error("DVR illegal plan=%s, vhost=%s. ret=%d", plan.c_str(), vhost.c_str(), ret);
return ret;
} }
return ret; return ret;
@ -779,7 +768,7 @@ int SrsDvrSessionPlan::on_publish()
return ret; return ret;
} }
if ((ret = segment->open(true)) != ERROR_SUCCESS) { if ((ret = segment->open()) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -804,98 +793,6 @@ void SrsDvrSessionPlan::on_unpublish()
dvr_enabled = false; dvr_enabled = false;
} }
SrsDvrAppendPlan::SrsDvrAppendPlan()
{
last_update_time = 0;
}
SrsDvrAppendPlan::~SrsDvrAppendPlan()
{
}
int SrsDvrAppendPlan::on_publish()
{
int ret = ERROR_SUCCESS;
// support multiple publish.
if (dvr_enabled) {
return ret;
}
if (!_srs_config->get_dvr_enabled(req->vhost)) {
return ret;
}
if ((ret = segment->open(false)) != ERROR_SUCCESS) {
return ret;
}
dvr_enabled = true;
return ret;
}
void SrsDvrAppendPlan::on_unpublish()
{
}
int SrsDvrAppendPlan::on_audio(SrsSharedPtrMessage* shared_audio)
{
int ret = ERROR_SUCCESS;
if ((ret = update_duration(shared_audio)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = SrsDvrPlan::on_audio(shared_audio)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsDvrAppendPlan::on_video(SrsSharedPtrMessage* shared_video)
{
int ret = ERROR_SUCCESS;
if ((ret = update_duration(shared_video)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = SrsDvrPlan::on_video(shared_video)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsDvrAppendPlan::update_duration(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
if (last_update_time <= 0) {
last_update_time = msg->timestamp;
return ret;
}
if (msg->timestamp < last_update_time) {
last_update_time = msg->timestamp;
return ret;
}
if (SRS_DVR_UPDATE_DURATION_INTERVAL > msg->timestamp - last_update_time) {
return ret;
}
last_update_time = msg->timestamp;
srs_assert(segment);
if ((ret = segment->refresh_metadata()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
SrsDvrSegmentPlan::SrsDvrSegmentPlan() SrsDvrSegmentPlan::SrsDvrSegmentPlan()
{ {
segment_duration = -1; segment_duration = -1;
@ -941,7 +838,7 @@ int SrsDvrSegmentPlan::on_publish()
return ret; return ret;
} }
if ((ret = segment->open(true)) != ERROR_SUCCESS) { if ((ret = segment->open()) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -1042,7 +939,7 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
} }
// open new flv file // open new flv file
if ((ret = segment->open(true)) != ERROR_SUCCESS) { if ((ret = segment->open()) != ERROR_SUCCESS) {
return ret; return ret;
} }

View file

@ -59,62 +59,54 @@ class SrsMp4Encoder;
class SrsDvrSegmenter : public ISrsReloadHandler class SrsDvrSegmenter : public ISrsReloadHandler
{ {
protected: protected:
// The underlayer file object.
SrsFileWriter* fs; SrsFileWriter* fs;
// The path of current segment flv file path.
std::string path;
protected:
SrsRtmpJitter* jitter;
SrsRtmpJitterAlgorithm jitter_algorithm;
// The duration in ms of current segment. // The duration in ms of current segment.
int64_t duration; int64_t duration;
protected: // Whether wait keyframe to reap segment.
bool wait_keyframe;
private:
// The path of current segment flv file path.
std::string path;
SrsRequest* req; SrsRequest* req;
SrsDvrPlan* plan; SrsDvrPlan* plan;
private:
std::string tmp_dvr_file; std::string tmp_dvr_file;
SrsRtmpJitter* jitter;
SrsRtmpJitterAlgorithm jitter_algorithm;
public: public:
SrsDvrSegmenter(); SrsDvrSegmenter();
virtual ~SrsDvrSegmenter(); virtual ~SrsDvrSegmenter();
public: public:
/** // Initialize the segment.
* initialize the segment.
*/
virtual int initialize(SrsDvrPlan* p, SrsRequest* r); virtual int initialize(SrsDvrPlan* p, SrsRequest* r);
/** // Get the current dvr path.
* get the current dvr path.
*/
virtual std::string get_path(); virtual std::string get_path();
/** // Whether segment is overflow.
* whether segment is overflow.
*/
virtual bool is_overflow(int64_t max_duration); virtual bool is_overflow(int64_t max_duration);
/** // Open new segment file.
* open new segment file, timestamp start at 0 for fresh flv file. // @param use_tmp_file Whether use tmp file for DVR, and rename when close.
* @remark ignore when already open. // @remark Ignore when file is already open.
* @param use_tmp_file whether use tmp file if possible. virtual int open();
*/
virtual int open(bool use_tmp_file);
/**
* close current segment.
* @remark ignore when already closed.
*/
virtual int close();
protected:
virtual int open_encoder() = 0;
public:
// Write the metadata. // Write the metadata.
virtual int write_metadata(SrsSharedPtrMessage* metadata) = 0; virtual int write_metadata(SrsSharedPtrMessage* metadata);
// Write audio packet. // Write audio packet.
// @param shared_audio, directly ptr, copy it if need to save it. // @param shared_audio, directly ptr, copy it if need to save it.
virtual int write_audio(SrsSharedPtrMessage* shared_audio) = 0; virtual int write_audio(SrsSharedPtrMessage* shared_audio);
// Write video packet. // Write video packet.
// @param shared_video, directly ptr, copy it if need to save it. // @param shared_video, directly ptr, copy it if need to save it.
virtual int write_video(SrsSharedPtrMessage* shared_video) = 0; virtual int write_video(SrsSharedPtrMessage* shared_video);
// Refresh the metadata. For example, there is duration in flv metadata, // Refresh the metadata. For example, there is duration in flv metadata,
// when DVR in append mode, the duration must be update every some seconds. // when DVR in append mode, the duration must be update every some seconds.
// @remark Maybe ignored by concreate segmenter. // @remark Maybe ignored by concreate segmenter.
virtual int refresh_metadata() = 0; virtual int refresh_metadata() = 0;
// Close current segment.
// @remark ignore when already closed.
virtual int close();
protected: protected:
virtual int open_encoder() = 0;
virtual int encode_metadata(SrsSharedPtrMessage* metadata) = 0;
virtual int encode_audio(SrsSharedPtrMessage* audio, int64_t dts) = 0;
virtual int encode_video(SrsSharedPtrMessage* video, int64_t dts, bool sh, bool keyframe) = 0;
virtual int close_encoder() = 0; virtual int close_encoder() = 0;
private: private:
/** /**
@ -125,7 +117,7 @@ private:
* create flv jitter. load jitter when flv exists. * create flv jitter. load jitter when flv exists.
* @param target_exists whether loads the jitter from exists flv file. * @param target_exists whether loads the jitter from exists flv file.
*/ */
virtual int create_jitter(bool target_exists); virtual int create_jitter();
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual int on_reload_vhost_dvr(std::string vhost); virtual int on_reload_vhost_dvr(std::string vhost);
@ -164,17 +156,17 @@ private:
public: public:
SrsDvrFlvSegmenter(); SrsDvrFlvSegmenter();
virtual ~SrsDvrFlvSegmenter(); virtual ~SrsDvrFlvSegmenter();
public:
virtual int refresh_metadata();
protected: protected:
virtual int open_encoder(); virtual int open_encoder();
virtual int encode_metadata(SrsSharedPtrMessage* metadata);
virtual int encode_audio(SrsSharedPtrMessage* audio, int64_t dts);
virtual int encode_video(SrsSharedPtrMessage* video, int64_t dts, bool sh, bool keyframe);
virtual int close_encoder(); virtual int close_encoder();
private: private:
// When update the duration of segment by rtmp msg. // When update the duration of segment by rtmp msg.
virtual int on_update_duration(SrsSharedPtrMessage* msg); virtual int on_update_duration(SrsSharedPtrMessage* msg);
public:
virtual int write_metadata(SrsSharedPtrMessage* metadata);
virtual int write_audio(SrsSharedPtrMessage* shared_audio);
virtual int write_video(SrsSharedPtrMessage* shared_video);
virtual int refresh_metadata();
}; };
/** /**
@ -188,14 +180,14 @@ private:
public: public:
SrsDvrMp4Segmenter(); SrsDvrMp4Segmenter();
virtual ~SrsDvrMp4Segmenter(); virtual ~SrsDvrMp4Segmenter();
public:
virtual int refresh_metadata();
protected: protected:
virtual int open_encoder(); virtual int open_encoder();
virtual int encode_metadata(SrsSharedPtrMessage* metadata);
virtual int encode_audio(SrsSharedPtrMessage* audio, int64_t dts);
virtual int encode_video(SrsSharedPtrMessage* video, int64_t dts, bool sh, bool keyframe);
virtual int close_encoder(); virtual int close_encoder();
public:
virtual int write_metadata(SrsSharedPtrMessage* metadata);
virtual int write_audio(SrsSharedPtrMessage* shared_audio);
virtual int write_video(SrsSharedPtrMessage* shared_video);
virtual int refresh_metadata();
}; };
/** /**
@ -274,25 +266,6 @@ public:
virtual void on_unpublish(); virtual void on_unpublish();
}; };
/**
* always append to flv file, never reap it.
*/
class SrsDvrAppendPlan : public SrsDvrPlan
{
private:
int64_t last_update_time;
public:
SrsDvrAppendPlan();
virtual ~SrsDvrAppendPlan();
public:
virtual int on_publish();
virtual void on_unpublish();
virtual int on_audio(SrsSharedPtrMessage* shared_audio);
virtual int on_video(SrsSharedPtrMessage* shared_video);
private:
virtual int update_duration(SrsSharedPtrMessage* msg);
};
/** /**
* segment plan: reap flv when duration exceed. * segment plan: reap flv when duration exceed.
*/ */