正在显示
3 个修改的文件
包含
101 行增加
和
4 行删除
| @@ -563,6 +563,7 @@ vhost with-hls.srs.com { | @@ -563,6 +563,7 @@ vhost with-hls.srs.com { | ||
| 563 | # whether use floor for the hls_ts_file path generation. | 563 | # whether use floor for the hls_ts_file path generation. |
| 564 | # if on, use floor(timestamp/hls_fragment) as the variable [timestamp], | 564 | # if on, use floor(timestamp/hls_fragment) as the variable [timestamp], |
| 565 | # and use enahanced algorithm to calc deviation for segment. | 565 | # and use enahanced algorithm to calc deviation for segment. |
| 566 | + # @remark when floor on, recommend the hls_segment>=2*gop. | ||
| 566 | # default: off | 567 | # default: off |
| 567 | hls_ts_floor off; | 568 | hls_ts_floor off; |
| 568 | # the hls entry prefix, which is base url of ts url. | 569 | # the hls entry prefix, which is base url of ts url. |
| @@ -740,7 +741,8 @@ vhost hooks.callback.srs.com { | @@ -740,7 +741,8 @@ vhost hooks.callback.srs.com { | ||
| 740 | # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | 741 | # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", |
| 741 | # "stream": "livestream", | 742 | # "stream": "livestream", |
| 742 | # "cwd": "/usr/local/srs", | 743 | # "cwd": "/usr/local/srs", |
| 743 | - # "file": "./objs/nginx/html/live/livestream.1420254068776-100.ts" | 744 | + # "file": "./objs/nginx/html/live/livestream.1420254068776-100.ts", |
| 745 | + # "seq_no": 100 | ||
| 744 | # } | 746 | # } |
| 745 | # if valid, the hook must return HTTP code 200(Stauts OK) and response | 747 | # if valid, the hook must return HTTP code 200(Stauts OK) and response |
| 746 | # an int value specifies the error code(0 corresponding to success): | 748 | # an int value specifies the error code(0 corresponding to success): |
| @@ -334,6 +334,99 @@ class RESTDvrs(object): | @@ -334,6 +334,99 @@ class RESTDvrs(object): | ||
| 334 | return code | 334 | return code |
| 335 | 335 | ||
| 336 | ''' | 336 | ''' |
| 337 | +handle the hls requests: hls stream. | ||
| 338 | +''' | ||
| 339 | +class RESTHls(object): | ||
| 340 | + exposed = True | ||
| 341 | + | ||
| 342 | + def GET(self): | ||
| 343 | + enable_crossdomain() | ||
| 344 | + | ||
| 345 | + hls = {} | ||
| 346 | + return json.dumps(hls) | ||
| 347 | + | ||
| 348 | + ''' | ||
| 349 | + for SRS hook: on_dvr, on_dvr_reap_segment | ||
| 350 | + on_dvr: | ||
| 351 | + when srs reap a dvr file, call the hook, | ||
| 352 | + the request in the POST data string is a object encode by json: | ||
| 353 | + { | ||
| 354 | + "action": "on_dvr", | ||
| 355 | + "client_id": 1985, | ||
| 356 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 357 | + "stream": "livestream", | ||
| 358 | + "cwd": "/usr/local/srs", | ||
| 359 | + "file": "./objs/nginx/html/live/livestream.1420254068776.flv" | ||
| 360 | + } | ||
| 361 | + on_dvr_reap_segment: | ||
| 362 | + when api dvr specifes the callback when reap flv segment, call the hook, | ||
| 363 | + the request in the POST data string is a object encode by json: | ||
| 364 | + { | ||
| 365 | + "action": "on_dvr_reap_segment", | ||
| 366 | + "client_id": 1985, | ||
| 367 | + "vhost": "video.test.com", "app": "live", | ||
| 368 | + "stream": "livestream", | ||
| 369 | + "cwd": "/usr/local/srs", | ||
| 370 | + "file": "./objs/nginx/html/live/livestream.1420254068776.flv" | ||
| 371 | + } | ||
| 372 | + if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 373 | + an int value specifies the error code(0 corresponding to success): | ||
| 374 | + 0 | ||
| 375 | + ''' | ||
| 376 | + def POST(self): | ||
| 377 | + enable_crossdomain() | ||
| 378 | + | ||
| 379 | + # return the error code in str | ||
| 380 | + code = Error.success | ||
| 381 | + | ||
| 382 | + req = cherrypy.request.body.read() | ||
| 383 | + trace("post to dvrs, req=%s"%(req)) | ||
| 384 | + try: | ||
| 385 | + json_req = json.loads(req) | ||
| 386 | + except Exception, ex: | ||
| 387 | + code = Error.system_parse_json | ||
| 388 | + trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code)) | ||
| 389 | + return str(code) | ||
| 390 | + | ||
| 391 | + action = json_req["action"] | ||
| 392 | + if action == "on_dvr": | ||
| 393 | + code = self.__on_dvr(json_req) | ||
| 394 | + if action == "on_dvr_reap_segment": | ||
| 395 | + code = self.__on_dvr_reap_segment(json_req) | ||
| 396 | + else: | ||
| 397 | + trace("invalid request action: %s"%(json_req["action"])) | ||
| 398 | + code = Error.request_invalid_action | ||
| 399 | + | ||
| 400 | + return str(code) | ||
| 401 | + | ||
| 402 | + def OPTIONS(self, *args, **kwargs): | ||
| 403 | + enable_crossdomain() | ||
| 404 | + | ||
| 405 | + def __on_dvr(self, req): | ||
| 406 | + code = Error.success | ||
| 407 | + | ||
| 408 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s, cwd=%s, file=%s"%( | ||
| 409 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"], | ||
| 410 | + req["cwd"], req["file"] | ||
| 411 | + )) | ||
| 412 | + | ||
| 413 | + # TODO: process the on_dvr event | ||
| 414 | + | ||
| 415 | + return code | ||
| 416 | + | ||
| 417 | + def __on_dvr_reap_segment(self, req): | ||
| 418 | + code = Error.success | ||
| 419 | + | ||
| 420 | + trace("srs %s: client id=%s, vhost=%s, app=%s, stream=%s, cwd=%s, file=%s"%( | ||
| 421 | + req["action"], req["client_id"], req["vhost"], req["app"], req["stream"], | ||
| 422 | + req["cwd"], req["file"] | ||
| 423 | + )) | ||
| 424 | + | ||
| 425 | + # TODO: process the on_dvr event | ||
| 426 | + | ||
| 427 | + return code | ||
| 428 | + | ||
| 429 | +''' | ||
| 337 | handle the sessions requests: client play/stop stream | 430 | handle the sessions requests: client play/stop stream |
| 338 | ''' | 431 | ''' |
| 339 | class RESTSessions(object): | 432 | class RESTSessions(object): |
| @@ -1133,6 +1226,7 @@ class V1(object): | @@ -1133,6 +1226,7 @@ class V1(object): | ||
| 1133 | self.streams = RESTStreams() | 1226 | self.streams = RESTStreams() |
| 1134 | self.sessions = RESTSessions() | 1227 | self.sessions = RESTSessions() |
| 1135 | self.dvrs = RESTDvrs() | 1228 | self.dvrs = RESTDvrs() |
| 1229 | + self.hls = RESTHls() | ||
| 1136 | self.chats = RESTChats() | 1230 | self.chats = RESTChats() |
| 1137 | self.servers = RESTServers() | 1231 | self.servers = RESTServers() |
| 1138 | self.nodes = RESTNodes() | 1232 | self.nodes = RESTNodes() |
| @@ -331,17 +331,18 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | @@ -331,17 +331,18 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | ||
| 331 | std::string ts_file = hls_ts_file; | 331 | std::string ts_file = hls_ts_file; |
| 332 | ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream); | 332 | ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream); |
| 333 | if (hls_ts_floor) { | 333 | if (hls_ts_floor) { |
| 334 | - int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); | 334 | + // we always ensure the piece is increase one by one. |
| 335 | std::stringstream ts_floor; | 335 | std::stringstream ts_floor; |
| 336 | - ts_floor << floor_ts; | 336 | + ts_floor << (int64_t)(previous_floor_ts + 1); |
| 337 | ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str()); | 337 | ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str()); |
| 338 | 338 | ||
| 339 | // dup/jmp detect for ts in floor mode. | 339 | // dup/jmp detect for ts in floor mode. |
| 340 | + int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); | ||
| 340 | if (previous_floor_ts && previous_floor_ts != floor_ts - 1) { | 341 | if (previous_floor_ts && previous_floor_ts != floor_ts - 1) { |
| 341 | srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", ts=%s, deviation=%.2f", | 342 | srs_warn("hls: dup or jmp for floor ts, previous=%"PRId64", current=%"PRId64", ts=%s, deviation=%.2f", |
| 342 | previous_floor_ts, floor_ts, ts_file.c_str(), hls_fragment_deviation); | 343 | previous_floor_ts, floor_ts, ts_file.c_str(), hls_fragment_deviation); |
| 343 | } | 344 | } |
| 344 | - previous_floor_ts = floor_ts; | 345 | + previous_floor_ts++; |
| 345 | } | 346 | } |
| 346 | ts_file = srs_path_build_timestamp(ts_file); | 347 | ts_file = srs_path_build_timestamp(ts_file); |
| 347 | if (true) { | 348 | if (true) { |
-
请 注册 或 登录 后发表评论