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

refine plan, add stream start time for atc

This commit is contained in:
winlin 2014-04-23 17:53:14 +08:00
parent 0c0010d529
commit e271cb607f
5 changed files with 101 additions and 72 deletions

View file

@ -326,6 +326,56 @@ class RESTSessions(object):
return code 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(); global_arm_server_id = os.getpid();
class ArmServer: class ArmServer:
def __init__(self): def __init__(self):
@ -930,6 +980,7 @@ class V1(object):
self.clients = RESTClients() self.clients = RESTClients()
self.streams = RESTStreams() self.streams = RESTStreams()
self.sessions = RESTSessions() self.sessions = RESTSessions()
self.dvrs = RESTDvrs()
self.chats = RESTChats() self.chats = RESTChats()
self.servers = RESTServers() self.servers = RESTServers()
self.nodes = RESTNodes() self.nodes = RESTNodes()

View file

@ -303,10 +303,12 @@ SrsFlvSegment::SrsFlvSegment()
segment_has_keyframe = false; segment_has_keyframe = false;
duration = 0; duration = 0;
starttime = -1; starttime = -1;
stream_starttime = 0;
} }
void SrsFlvSegment::reset() void SrsFlvSegment::reset()
{ {
segment_has_keyframe = false;
duration = 0; duration = 0;
starttime = -1; starttime = -1;
} }
@ -319,7 +321,7 @@ SrsDvrPlan::SrsDvrPlan()
dvr_enabled = false; dvr_enabled = false;
fs = new SrsFileStream(); fs = new SrsFileStream();
enc = new SrsFlvEncoder(); enc = new SrsFlvEncoder();
segment = NULL; segment = new SrsFlvSegment();
} }
SrsDvrPlan::~SrsDvrPlan() SrsDvrPlan::~SrsDvrPlan()
@ -362,6 +364,22 @@ int SrsDvrPlan::on_publish()
// always update time cache. // always update time cache.
srs_update_system_time_ms(); 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 // new flv file
std::stringstream path; std::stringstream path;
@ -468,8 +486,7 @@ int SrsDvrPlan::flv_open(string stream, string path)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_freep(segment); segment->reset();
segment = new SrsFlvSegment();
std::string tmp_file = path + ".tmp"; std::string tmp_file = path + ".tmp";
if ((ret = fs->open(tmp_file)) != ERROR_SUCCESS) { 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++) { for (int i = 0; i < (int)on_dvr_keyframe->args.size(); i++) {
std::string url = on_dvr_keyframe->args.at(i); std::string url = on_dvr_keyframe->args.at(i);
SrsHttpHooks::on_dvr_keyframe(url, _req); SrsHttpHooks::on_dvr_keyframe(url, _req, segment);
} }
#endif #endif
@ -620,6 +637,9 @@ int SrsDvrSegmentPlan::on_publish()
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// if already opened, continue to dvr. // 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()) { if (fs->is_open()) {
dvr_enabled = true; dvr_enabled = true;
return ret; return ret;
@ -648,15 +668,14 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
srs_assert(segment); srs_assert(segment);
// reap if exceed duration. // reap if exceed duration.
if (segment->duration > 0 && segment_duration > 0 && segment->duration > segment_duration) { if (segment_duration > 0 && segment->duration > segment_duration) {
segment->reset();
if ((ret = flv_close()) != ERROR_SUCCESS) { if ((ret = flv_close()) != ERROR_SUCCESS) {
segment->reset();
return ret; return ret;
} }
on_unpublish(); on_unpublish();
if ((ret = on_publish()) != ERROR_SUCCESS) { if ((ret = open_new_segment()) != ERROR_SUCCESS) {
return ret; return ret;
} }
} }

View file

@ -126,6 +126,10 @@ public:
*/ */
int64_t duration; int64_t duration;
int64_t starttime; int64_t starttime;
/**
* stream start time, to generate atc pts.
*/
int64_t stream_starttime;
public: public:
SrsFlvSegment(); SrsFlvSegment();
virtual void reset(); virtual void reset();
@ -137,6 +141,7 @@ public:
* 1. filename: the filename for record file. * 1. filename: the filename for record file.
* 2. reap flv: when to reap the flv and start new piece. * 2. reap flv: when to reap the flv and start new piece.
*/ */
// TODO: FIXME: the plan is too fat, refine me.
class SrsDvrPlan class SrsDvrPlan
{ {
protected: protected:
@ -165,6 +170,7 @@ public:
protected: protected:
virtual int flv_open(std::string stream, std::string path); virtual int flv_open(std::string stream, std::string path);
virtual int flv_close(); virtual int flv_close();
virtual int open_new_segment();
virtual int update_duration(SrsSharedPtrMessage* msg); virtual int update_duration(SrsSharedPtrMessage* msg);
private: private:
/** /**

View file

@ -36,6 +36,7 @@ using namespace std;
#include <srs_app_socket.hpp> #include <srs_app_socket.hpp>
#include <srs_app_http.hpp> #include <srs_app_http.hpp>
#include <srs_app_json.hpp> #include <srs_app_json.hpp>
#include <srs_app_dvr.hpp>
#define SRS_HTTP_RESPONSE_OK "0" #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; 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; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_connect") << JFIELD_CONT << 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; return;
} }
/**
{
"action": "on_close",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_close") << JFIELD_CONT << 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; return ret;
} }
/**
{
"action": "on_publish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_publish") << JFIELD_CONT << JFIELD_STR("action", "on_publish") << JFIELD_CONT
@ -354,14 +331,6 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest
return; return;
} }
/**
{
"action": "on_unpublish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_unpublish") << JFIELD_CONT << 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; return ret;
} }
/**
{
"action": "on_play",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_play") << JFIELD_CONT << 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; return;
} }
/**
{
"action": "on_stop",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss; std::stringstream ss;
ss << JOBJECT_START ss << JOBJECT_START
<< JFIELD_STR("action", "on_stop") << JFIELD_CONT << 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; 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; 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; 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_keyframe url failed, ignored. "
@ -516,13 +474,6 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req)
return; return;
} }
/**
{
"action": "on_dvr_keyframe",
"vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
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_keyframe") << JFIELD_CONT

View file

@ -37,6 +37,7 @@ class SrsHttpUri;
class SrsSocket; class SrsSocket;
class SrsRequest; class SrsRequest;
class SrsHttpParser; class SrsHttpParser;
class SrsFlvSegment;
#include <srs_app_st.hpp> #include <srs_app_st.hpp>
@ -126,8 +127,9 @@ public:
* on_dvr_keyframe hook, when dvr get keyframe. * on_dvr_keyframe hook, when dvr get keyframe.
* @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.
*/ */
static void on_dvr_keyframe(std::string url, SrsRequest* req); static void on_dvr_keyframe(std::string url, SrsRequest* req, SrsFlvSegment* segment);
}; };
#endif #endif