mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
refine plan, add stream start time for atc
This commit is contained in:
parent
0c0010d529
commit
e271cb607f
5 changed files with 101 additions and 72 deletions
|
@ -325,6 +325,56 @@ class RESTSessions(object):
|
|||
# TODO: process the on_stop event
|
||||
|
||||
return code
|
||||
|
||||
# the rest dvrs, when dvr got keyframe, call this api.
|
||||
class RESTDvrs(object):
|
||||
exposed = True
|
||||
def __init__(self):
|
||||
pass
|
||||
# the dvrs POST api specified in following.
|
||||
#
|
||||
# when dvr got an keyframe, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
# {
|
||||
# "action": "on_dvr_keyframe",
|
||||
# "vhost": "video.test.com", "app": "live",
|
||||
# "stream": "livestream"
|
||||
# }
|
||||
#
|
||||
# if valid, the hook must return HTTP code 200(Stauts OK) and response
|
||||
# an int value specifies the error code(0 corresponding to success):
|
||||
# 0
|
||||
def POST(self):
|
||||
enable_crossdomain()
|
||||
|
||||
req = cherrypy.request.body.read()
|
||||
trace("post to sessions, req=%s"%(req))
|
||||
try:
|
||||
json_req = json.loads(req)
|
||||
except Exception, ex:
|
||||
code = Error.system_parse_json
|
||||
trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code))
|
||||
return str(code)
|
||||
|
||||
action = json_req["action"]
|
||||
if action == "on_dvr_keyframe":
|
||||
code = self.__on_dvr_keyframe(json_req)
|
||||
else:
|
||||
code = Errors.request_invalid_action
|
||||
trace("invalid request action: %s, code=%s"%(json_req["action"], code))
|
||||
|
||||
return str(code)
|
||||
|
||||
def __on_dvr_keyframe(self, req):
|
||||
code = Error.success
|
||||
|
||||
trace("srs %s: vhost=%s, app=%s, stream=%s"%(
|
||||
req["action"], req["vhost"], req["app"], req["stream"]
|
||||
))
|
||||
|
||||
# TODO: process the on_dvr_keyframe event
|
||||
|
||||
return code
|
||||
|
||||
global_arm_server_id = os.getpid();
|
||||
class ArmServer:
|
||||
|
@ -930,6 +980,7 @@ class V1(object):
|
|||
self.clients = RESTClients()
|
||||
self.streams = RESTStreams()
|
||||
self.sessions = RESTSessions()
|
||||
self.dvrs = RESTDvrs()
|
||||
self.chats = RESTChats()
|
||||
self.servers = RESTServers()
|
||||
self.nodes = RESTNodes()
|
||||
|
|
|
@ -303,10 +303,12 @@ SrsFlvSegment::SrsFlvSegment()
|
|||
segment_has_keyframe = false;
|
||||
duration = 0;
|
||||
starttime = -1;
|
||||
stream_starttime = 0;
|
||||
}
|
||||
|
||||
void SrsFlvSegment::reset()
|
||||
{
|
||||
segment_has_keyframe = false;
|
||||
duration = 0;
|
||||
starttime = -1;
|
||||
}
|
||||
|
@ -319,7 +321,7 @@ SrsDvrPlan::SrsDvrPlan()
|
|||
dvr_enabled = false;
|
||||
fs = new SrsFileStream();
|
||||
enc = new SrsFlvEncoder();
|
||||
segment = NULL;
|
||||
segment = new SrsFlvSegment();
|
||||
}
|
||||
|
||||
SrsDvrPlan::~SrsDvrPlan()
|
||||
|
@ -362,6 +364,22 @@ int SrsDvrPlan::on_publish()
|
|||
// always update time cache.
|
||||
srs_update_system_time_ms();
|
||||
|
||||
// when republish, stream starting.
|
||||
segment->stream_starttime = srs_get_system_time_ms();
|
||||
|
||||
if ((ret = open_new_segment()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsDvrPlan::open_new_segment()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsRequest* req = _req;
|
||||
|
||||
// new flv file
|
||||
std::stringstream path;
|
||||
|
||||
|
@ -468,8 +486,7 @@ int SrsDvrPlan::flv_open(string stream, string path)
|
|||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
srs_freep(segment);
|
||||
segment = new SrsFlvSegment();
|
||||
segment->reset();
|
||||
|
||||
std::string tmp_file = path + ".tmp";
|
||||
if ((ret = fs->open(tmp_file)) != ERROR_SUCCESS) {
|
||||
|
@ -548,7 +565,7 @@ int SrsDvrPlan::on_dvr_keyframe()
|
|||
|
||||
for (int i = 0; i < (int)on_dvr_keyframe->args.size(); i++) {
|
||||
std::string url = on_dvr_keyframe->args.at(i);
|
||||
SrsHttpHooks::on_dvr_keyframe(url, _req);
|
||||
SrsHttpHooks::on_dvr_keyframe(url, _req, segment);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -620,6 +637,9 @@ int SrsDvrSegmentPlan::on_publish()
|
|||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// if already opened, continue to dvr.
|
||||
// the segment plan maybe keep running longer than the encoder.
|
||||
// for example, segment running, encoder restart,
|
||||
// the segment plan will just continue going and donot open new segment.
|
||||
if (fs->is_open()) {
|
||||
dvr_enabled = true;
|
||||
return ret;
|
||||
|
@ -648,15 +668,14 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
|
|||
srs_assert(segment);
|
||||
|
||||
// reap if exceed duration.
|
||||
if (segment->duration > 0 && segment_duration > 0 && segment->duration > segment_duration) {
|
||||
segment->reset();
|
||||
|
||||
if (segment_duration > 0 && segment->duration > segment_duration) {
|
||||
if ((ret = flv_close()) != ERROR_SUCCESS) {
|
||||
segment->reset();
|
||||
return ret;
|
||||
}
|
||||
on_unpublish();
|
||||
|
||||
if ((ret = on_publish()) != ERROR_SUCCESS) {
|
||||
if ((ret = open_new_segment()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,11 +121,15 @@ public:
|
|||
* whether current segment has keyframe.
|
||||
*/
|
||||
bool segment_has_keyframe;
|
||||
/**
|
||||
* current segment duration and starttime.
|
||||
*/
|
||||
/**
|
||||
* current segment duration and starttime.
|
||||
*/
|
||||
int64_t duration;
|
||||
int64_t starttime;
|
||||
/**
|
||||
* stream start time, to generate atc pts.
|
||||
*/
|
||||
int64_t stream_starttime;
|
||||
public:
|
||||
SrsFlvSegment();
|
||||
virtual void reset();
|
||||
|
@ -137,6 +141,7 @@ public:
|
|||
* 1. filename: the filename for record file.
|
||||
* 2. reap flv: when to reap the flv and start new piece.
|
||||
*/
|
||||
// TODO: FIXME: the plan is too fat, refine me.
|
||||
class SrsDvrPlan
|
||||
{
|
||||
protected:
|
||||
|
@ -165,12 +170,13 @@ public:
|
|||
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);
|
||||
private:
|
||||
/**
|
||||
* when srs reap the flv(close the segment),
|
||||
* if has keyframe, notice the api.
|
||||
*/
|
||||
/**
|
||||
* when srs reap the flv(close the segment),
|
||||
* if has keyframe, notice the api.
|
||||
*/
|
||||
virtual int on_dvr_keyframe();
|
||||
public:
|
||||
static SrsDvrPlan* create_plan(std::string vhost);
|
||||
|
|
|
@ -36,6 +36,7 @@ using namespace std;
|
|||
#include <srs_app_socket.hpp>
|
||||
#include <srs_app_http.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_app_dvr.hpp>
|
||||
|
||||
#define SRS_HTTP_RESPONSE_OK "0"
|
||||
|
||||
|
@ -194,14 +195,6 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_connect",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"pageUrl": "http://www.test.com/live.html"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_connect") << JFIELD_CONT
|
||||
|
@ -247,14 +240,6 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_close",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_close") << JFIELD_CONT
|
||||
|
@ -300,14 +285,6 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_publish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_publish") << JFIELD_CONT
|
||||
|
@ -354,14 +331,6 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_unpublish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_unpublish") << JFIELD_CONT
|
||||
|
@ -408,14 +377,6 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_play",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_play") << JFIELD_CONT
|
||||
|
@ -462,14 +423,6 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_stop",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_stop") << JFIELD_CONT
|
||||
|
@ -505,10 +458,15 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
|
|||
return;
|
||||
}
|
||||
|
||||
void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req)
|
||||
void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req, SrsFlvSegment* segment)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
srs_trace("flv segment %s, atc_start=%"PRId64", "
|
||||
"has_key=%d, starttime=%"PRId64", duration=%d",
|
||||
segment->current_flv_path.c_str(), segment->stream_starttime,
|
||||
segment->segment_has_keyframe, segment->starttime, (int)segment->duration);
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_dvr_keyframe url failed, ignored. "
|
||||
|
@ -516,13 +474,6 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req)
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_dvr_keyframe",
|
||||
"vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << JOBJECT_START
|
||||
<< JFIELD_STR("action", "on_dvr_keyframe") << JFIELD_CONT
|
||||
|
|
|
@ -37,6 +37,7 @@ class SrsHttpUri;
|
|||
class SrsSocket;
|
||||
class SrsRequest;
|
||||
class SrsHttpParser;
|
||||
class SrsFlvSegment;
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
|
||||
|
@ -126,8 +127,9 @@ public:
|
|||
* on_dvr_keyframe hook, when dvr get keyframe.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
* @param segment the current flv segment.
|
||||
*/
|
||||
static void on_dvr_keyframe(std::string url, SrsRequest* req);
|
||||
static void on_dvr_keyframe(std::string url, SrsRequest* req, SrsFlvSegment* segment);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue