正在显示
17 个修改的文件
包含
416 行增加
和
177 行删除
| @@ -566,6 +566,7 @@ Supported operating systems and hardware: | @@ -566,6 +566,7 @@ Supported operating systems and hardware: | ||
| 566 | 566 | ||
| 567 | ### SRS 2.0 history | 567 | ### SRS 2.0 history |
| 568 | 568 | ||
| 569 | +* v2.0, 2015-03-31, support on_hls for http hooks. 2.0.152. | ||
| 569 | * v2.0, 2015-03-31, enhanced hls, support deviation for duration. 2.0.151. | 570 | * v2.0, 2015-03-31, enhanced hls, support deviation for duration. 2.0.151. |
| 570 | * v2.0, 2015-03-30, for [#351](https://github.com/winlinvip/simple-rtmp-server/issues/351), support config the m3u8/ts path for hls. 2.0.149. | 571 | * v2.0, 2015-03-30, for [#351](https://github.com/winlinvip/simple-rtmp-server/issues/351), support config the m3u8/ts path for hls. 2.0.149. |
| 571 | * v2.0, 2015-03-17, for [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), osx(darwin) support demo with nginx and ffmpeg. 2.0.143. | 572 | * v2.0, 2015-03-17, for [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), osx(darwin) support demo with nginx and ffmpeg. 2.0.143. |
| @@ -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): |
| @@ -174,7 +174,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then | @@ -174,7 +174,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then | ||
| 174 | "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" | 174 | "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" |
| 175 | "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" | 175 | "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" |
| 176 | "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds" | 176 | "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds" |
| 177 | - "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener") | 177 | + "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call") |
| 178 | DEFINES="" | 178 | DEFINES="" |
| 179 | # add each modules for app | 179 | # add each modules for app |
| 180 | for SRS_MODULE in $SRS_MODULES; do | 180 | for SRS_MODULE in $SRS_MODULES; do |
| @@ -64,6 +64,8 @@ file | @@ -64,6 +64,8 @@ file | ||
| 64 | ../../src/protocol/srs_rtmp_utility.hpp, | 64 | ../../src/protocol/srs_rtmp_utility.hpp, |
| 65 | ../../src/protocol/srs_rtmp_utility.cpp, | 65 | ../../src/protocol/srs_rtmp_utility.cpp, |
| 66 | app readonly separator, | 66 | app readonly separator, |
| 67 | + ../../src/app/srs_app_async_call.hpp, | ||
| 68 | + ../../src/app/srs_app_async_call.cpp, | ||
| 67 | ../../src/app/srs_app_bandwidth.hpp, | 69 | ../../src/app/srs_app_bandwidth.hpp, |
| 68 | ../../src/app/srs_app_bandwidth.cpp, | 70 | ../../src/app/srs_app_bandwidth.cpp, |
| 69 | ../../src/app/srs_app_conn.hpp, | 71 | ../../src/app/srs_app_conn.hpp, |
| @@ -97,6 +97,7 @@ | @@ -97,6 +97,7 @@ | ||
| 97 | 3C689F9F1AB6AAC800C9CEEE /* sched.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9B1AB6AAC800C9CEEE /* sched.c */; }; | 97 | 3C689F9F1AB6AAC800C9CEEE /* sched.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9B1AB6AAC800C9CEEE /* sched.c */; }; |
| 98 | 3C689FA01AB6AAC800C9CEEE /* stk.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9C1AB6AAC800C9CEEE /* stk.c */; }; | 98 | 3C689FA01AB6AAC800C9CEEE /* stk.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9C1AB6AAC800C9CEEE /* stk.c */; }; |
| 99 | 3C689FA11AB6AAC800C9CEEE /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9D1AB6AAC800C9CEEE /* sync.c */; }; | 99 | 3C689FA11AB6AAC800C9CEEE /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C689F9D1AB6AAC800C9CEEE /* sync.c */; }; |
| 100 | + 3CD88B3F1ACA9C58000359E0 /* srs_app_async_call.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */; }; | ||
| 100 | /* End PBXBuildFile section */ | 101 | /* End PBXBuildFile section */ |
| 101 | 102 | ||
| 102 | /* Begin PBXCopyFilesBuildPhase section */ | 103 | /* Begin PBXCopyFilesBuildPhase section */ |
| @@ -337,6 +338,8 @@ | @@ -337,6 +338,8 @@ | ||
| 337 | 3C689F9B1AB6AAC800C9CEEE /* sched.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sched.c; path = "../../objs/st-1.9/sched.c"; sourceTree = "<group>"; }; | 338 | 3C689F9B1AB6AAC800C9CEEE /* sched.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sched.c; path = "../../objs/st-1.9/sched.c"; sourceTree = "<group>"; }; |
| 338 | 3C689F9C1AB6AAC800C9CEEE /* stk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = stk.c; path = "../../objs/st-1.9/stk.c"; sourceTree = "<group>"; }; | 339 | 3C689F9C1AB6AAC800C9CEEE /* stk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = stk.c; path = "../../objs/st-1.9/stk.c"; sourceTree = "<group>"; }; |
| 339 | 3C689F9D1AB6AAC800C9CEEE /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync.c; path = "../../objs/st-1.9/sync.c"; sourceTree = "<group>"; }; | 340 | 3C689F9D1AB6AAC800C9CEEE /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync.c; path = "../../objs/st-1.9/sync.c"; sourceTree = "<group>"; }; |
| 341 | + 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_async_call.cpp; path = ../../../src/app/srs_app_async_call.cpp; sourceTree = "<group>"; }; | ||
| 342 | + 3CD88B3E1ACA9C58000359E0 /* srs_app_async_call.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_async_call.hpp; path = ../../../src/app/srs_app_async_call.hpp; sourceTree = "<group>"; }; | ||
| 340 | /* End PBXFileReference section */ | 343 | /* End PBXFileReference section */ |
| 341 | 344 | ||
| 342 | /* Begin PBXFrameworksBuildPhase section */ | 345 | /* Begin PBXFrameworksBuildPhase section */ |
| @@ -483,6 +486,8 @@ | @@ -483,6 +486,8 @@ | ||
| 483 | 3C12324B1AAE81CE00CE8F6C /* app */ = { | 486 | 3C12324B1AAE81CE00CE8F6C /* app */ = { |
| 484 | isa = PBXGroup; | 487 | isa = PBXGroup; |
| 485 | children = ( | 488 | children = ( |
| 489 | + 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */, | ||
| 490 | + 3CD88B3E1ACA9C58000359E0 /* srs_app_async_call.hpp */, | ||
| 486 | 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */, | 491 | 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */, |
| 487 | 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */, | 492 | 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */, |
| 488 | 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */, | 493 | 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */, |
| @@ -789,6 +794,7 @@ | @@ -789,6 +794,7 @@ | ||
| 789 | 3C1232951AAE81D900CE8F6C /* srs_app_config.cpp in Sources */, | 794 | 3C1232951AAE81D900CE8F6C /* srs_app_config.cpp in Sources */, |
| 790 | 3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */, | 795 | 3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */, |
| 791 | 3C689FA01AB6AAC800C9CEEE /* stk.c in Sources */, | 796 | 3C689FA01AB6AAC800C9CEEE /* stk.c in Sources */, |
| 797 | + 3CD88B3F1ACA9C58000359E0 /* srs_app_async_call.cpp in Sources */, | ||
| 792 | 3C1232961AAE81D900CE8F6C /* srs_app_conn.cpp in Sources */, | 798 | 3C1232961AAE81D900CE8F6C /* srs_app_conn.cpp in Sources */, |
| 793 | 3C12322A1AAE814D00CE8F6C /* srs_kernel_ts.cpp in Sources */, | 799 | 3C12322A1AAE814D00CE8F6C /* srs_kernel_ts.cpp in Sources */, |
| 794 | 3C12329E1AAE81D900CE8F6C /* srs_app_hls.cpp in Sources */, | 800 | 3C12329E1AAE81D900CE8F6C /* srs_app_hls.cpp in Sources */, |
| @@ -253,7 +253,7 @@ class RESTDvrs(object): | @@ -253,7 +253,7 @@ class RESTDvrs(object): | ||
| 253 | return json.dumps(dvrs) | 253 | return json.dumps(dvrs) |
| 254 | 254 | ||
| 255 | ''' | 255 | ''' |
| 256 | - for SRS hook: on_dvr, on_dvr_reap_segment | 256 | + for SRS hook: on_dvr |
| 257 | on_dvr: | 257 | on_dvr: |
| 258 | when srs reap a dvr file, call the hook, | 258 | when srs reap a dvr file, call the hook, |
| 259 | the request in the POST data string is a object encode by json: | 259 | the request in the POST data string is a object encode by json: |
| @@ -265,17 +265,6 @@ class RESTDvrs(object): | @@ -265,17 +265,6 @@ class RESTDvrs(object): | ||
| 265 | "cwd": "/usr/local/srs", | 265 | "cwd": "/usr/local/srs", |
| 266 | "file": "./objs/nginx/html/live/livestream.1420254068776.flv" | 266 | "file": "./objs/nginx/html/live/livestream.1420254068776.flv" |
| 267 | } | 267 | } |
| 268 | - on_dvr_reap_segment: | ||
| 269 | - when api dvr specifes the callback when reap flv segment, call the hook, | ||
| 270 | - the request in the POST data string is a object encode by json: | ||
| 271 | - { | ||
| 272 | - "action": "on_dvr_reap_segment", | ||
| 273 | - "client_id": 1985, | ||
| 274 | - "vhost": "video.test.com", "app": "live", | ||
| 275 | - "stream": "livestream", | ||
| 276 | - "cwd": "/usr/local/srs", | ||
| 277 | - "file": "./objs/nginx/html/live/livestream.1420254068776.flv" | ||
| 278 | - } | ||
| 279 | if valid, the hook must return HTTP code 200(Stauts OK) and response | 268 | if valid, the hook must return HTTP code 200(Stauts OK) and response |
| 280 | an int value specifies the error code(0 corresponding to success): | 269 | an int value specifies the error code(0 corresponding to success): |
| 281 | 0 | 270 | 0 |
| @@ -298,8 +287,6 @@ class RESTDvrs(object): | @@ -298,8 +287,6 @@ class RESTDvrs(object): | ||
| 298 | action = json_req["action"] | 287 | action = json_req["action"] |
| 299 | if action == "on_dvr": | 288 | if action == "on_dvr": |
| 300 | code = self.__on_dvr(json_req) | 289 | code = self.__on_dvr(json_req) |
| 301 | - if action == "on_dvr_reap_segment": | ||
| 302 | - code = self.__on_dvr_reap_segment(json_req) | ||
| 303 | else: | 290 | else: |
| 304 | trace("invalid request action: %s"%(json_req["action"])) | 291 | trace("invalid request action: %s"%(json_req["action"])) |
| 305 | code = Error.request_invalid_action | 292 | code = Error.request_invalid_action |
| @@ -321,15 +308,72 @@ class RESTDvrs(object): | @@ -321,15 +308,72 @@ class RESTDvrs(object): | ||
| 321 | 308 | ||
| 322 | return code | 309 | return code |
| 323 | 310 | ||
| 324 | - def __on_dvr_reap_segment(self, req): | 311 | +''' |
| 312 | +handle the hls requests: hls stream. | ||
| 313 | +''' | ||
| 314 | +class RESTHls(object): | ||
| 315 | + exposed = True | ||
| 316 | + | ||
| 317 | + def GET(self): | ||
| 318 | + enable_crossdomain() | ||
| 319 | + | ||
| 320 | + hls = {} | ||
| 321 | + return json.dumps(hls) | ||
| 322 | + | ||
| 323 | + ''' | ||
| 324 | + for SRS hook: on_hls | ||
| 325 | + on_hls: | ||
| 326 | + when srs reap a dvr file, call the hook, | ||
| 327 | + the request in the POST data string is a object encode by json: | ||
| 328 | + { | ||
| 329 | + "action": "on_dvr", | ||
| 330 | + "client_id": 1985, | ||
| 331 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 332 | + "stream": "livestream", | ||
| 333 | + "cwd": "/usr/local/srs", | ||
| 334 | + "file": "./objs/nginx/html/live/livestream.1420254068776-100.ts", | ||
| 335 | + "seq_no": 100 | ||
| 336 | + } | ||
| 337 | + if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 338 | + an int value specifies the error code(0 corresponding to success): | ||
| 339 | + 0 | ||
| 340 | + ''' | ||
| 341 | + def POST(self): | ||
| 342 | + enable_crossdomain() | ||
| 343 | + | ||
| 344 | + # return the error code in str | ||
| 325 | code = Error.success | 345 | code = Error.success |
| 326 | 346 | ||
| 327 | - trace("srs %s: client id=%s, vhost=%s, app=%s, stream=%s, cwd=%s, file=%s"%( | ||
| 328 | - req["action"], req["client_id"], req["vhost"], req["app"], req["stream"], | ||
| 329 | - req["cwd"], req["file"] | 347 | + req = cherrypy.request.body.read() |
| 348 | + trace("post to hls, req=%s"%(req)) | ||
| 349 | + try: | ||
| 350 | + json_req = json.loads(req) | ||
| 351 | + except Exception, ex: | ||
| 352 | + code = Error.system_parse_json | ||
| 353 | + trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code)) | ||
| 354 | + return str(code) | ||
| 355 | + | ||
| 356 | + action = json_req["action"] | ||
| 357 | + if action == "on_hls": | ||
| 358 | + code = self.__on_hls(json_req) | ||
| 359 | + else: | ||
| 360 | + trace("invalid request action: %s"%(json_req["action"])) | ||
| 361 | + code = Error.request_invalid_action | ||
| 362 | + | ||
| 363 | + return str(code) | ||
| 364 | + | ||
| 365 | + def OPTIONS(self, *args, **kwargs): | ||
| 366 | + enable_crossdomain() | ||
| 367 | + | ||
| 368 | + def __on_hls(self, req): | ||
| 369 | + code = Error.success | ||
| 370 | + | ||
| 371 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s, cwd=%s, file=%s, seq_no=%s"%( | ||
| 372 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"], | ||
| 373 | + req["cwd"], req["file"], req["seq_no"] | ||
| 330 | )) | 374 | )) |
| 331 | 375 | ||
| 332 | - # TODO: process the on_dvr event | 376 | + # TODO: process the on_hls event |
| 333 | 377 | ||
| 334 | return code | 378 | return code |
| 335 | 379 | ||
| @@ -1133,6 +1177,7 @@ class V1(object): | @@ -1133,6 +1177,7 @@ class V1(object): | ||
| 1133 | self.streams = RESTStreams() | 1177 | self.streams = RESTStreams() |
| 1134 | self.sessions = RESTSessions() | 1178 | self.sessions = RESTSessions() |
| 1135 | self.dvrs = RESTDvrs() | 1179 | self.dvrs = RESTDvrs() |
| 1180 | + self.hls = RESTHls() | ||
| 1136 | self.chats = RESTChats() | 1181 | self.chats = RESTChats() |
| 1137 | self.servers = RESTServers() | 1182 | self.servers = RESTServers() |
| 1138 | self.nodes = RESTNodes() | 1183 | self.nodes = RESTNodes() |
trunk/src/app/srs_app_async_call.cpp
0 → 100644
| 1 | +/* | ||
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013-2015 winlin | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | +this software and associated documentation files (the "Software"), to deal in | ||
| 8 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#include <srs_app_async_call.hpp> | ||
| 25 | + | ||
| 26 | +using namespace std; | ||
| 27 | + | ||
| 28 | +#include <srs_kernel_error.hpp> | ||
| 29 | +#include <srs_kernel_log.hpp> | ||
| 30 | + | ||
| 31 | +// the sleep interval for http async callback. | ||
| 32 | +#define SRS_AUTO_ASYNC_CALLBACL_SLEEP_US 300000 | ||
| 33 | + | ||
| 34 | +ISrsDvrAsyncCall::ISrsDvrAsyncCall() | ||
| 35 | +{ | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +ISrsDvrAsyncCall::~ISrsDvrAsyncCall() | ||
| 39 | +{ | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +SrsDvrAsyncCallThread::SrsDvrAsyncCallThread() | ||
| 43 | +{ | ||
| 44 | + pthread = new SrsThread("async", this, SRS_AUTO_ASYNC_CALLBACL_SLEEP_US, true); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +SrsDvrAsyncCallThread::~SrsDvrAsyncCallThread() | ||
| 48 | +{ | ||
| 49 | + stop(); | ||
| 50 | + srs_freep(pthread); | ||
| 51 | + | ||
| 52 | + std::vector<ISrsDvrAsyncCall*>::iterator it; | ||
| 53 | + for (it = callbacks.begin(); it != callbacks.end(); ++it) { | ||
| 54 | + ISrsDvrAsyncCall* call = *it; | ||
| 55 | + srs_freep(call); | ||
| 56 | + } | ||
| 57 | + callbacks.clear(); | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +int SrsDvrAsyncCallThread::call(ISrsDvrAsyncCall* c) | ||
| 61 | +{ | ||
| 62 | + int ret = ERROR_SUCCESS; | ||
| 63 | + | ||
| 64 | + callbacks.push_back(c); | ||
| 65 | + | ||
| 66 | + return ret; | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +int SrsDvrAsyncCallThread::start() | ||
| 70 | +{ | ||
| 71 | + return pthread->start(); | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +void SrsDvrAsyncCallThread::stop() | ||
| 75 | +{ | ||
| 76 | + pthread->stop(); | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +int SrsDvrAsyncCallThread::cycle() | ||
| 80 | +{ | ||
| 81 | + int ret = ERROR_SUCCESS; | ||
| 82 | + | ||
| 83 | + std::vector<ISrsDvrAsyncCall*> copies = callbacks; | ||
| 84 | + callbacks.clear(); | ||
| 85 | + | ||
| 86 | + std::vector<ISrsDvrAsyncCall*>::iterator it; | ||
| 87 | + for (it = copies.begin(); it != copies.end(); ++it) { | ||
| 88 | + ISrsDvrAsyncCall* call = *it; | ||
| 89 | + if ((ret = call->call()) != ERROR_SUCCESS) { | ||
| 90 | + srs_warn("dvr: ignore callback %s, ret=%d", call->to_string().c_str(), ret); | ||
| 91 | + } | ||
| 92 | + srs_freep(call); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + return ret; | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | + |
trunk/src/app/srs_app_async_call.hpp
0 → 100644
| 1 | +/* | ||
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013-2015 winlin | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | +this software and associated documentation files (the "Software"), to deal in | ||
| 8 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#ifndef SRS_APP_ASYNC_CALL_HPP | ||
| 25 | +#define SRS_APP_ASYNC_CALL_HPP | ||
| 26 | + | ||
| 27 | +/* | ||
| 28 | +#include <srs_app_async_call.hpp> | ||
| 29 | +*/ | ||
| 30 | +#include <srs_core.hpp> | ||
| 31 | + | ||
| 32 | +#include <string> | ||
| 33 | +#include <vector> | ||
| 34 | + | ||
| 35 | +#include <srs_app_thread.hpp> | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * the async call for http hooks, | ||
| 39 | + * for the http hooks will switch st-thread, | ||
| 40 | + * so we must use isolate thread to avoid the thread corrupt, | ||
| 41 | + * for example, when dvr call http hooks, the video receive thread got | ||
| 42 | + * a video and pass it to the dvr again. | ||
| 43 | + * futhurmore, the aync call never block the main worker thread. | ||
| 44 | + */ | ||
| 45 | +class ISrsDvrAsyncCall | ||
| 46 | +{ | ||
| 47 | +public: | ||
| 48 | + ISrsDvrAsyncCall(); | ||
| 49 | + virtual ~ISrsDvrAsyncCall(); | ||
| 50 | +public: | ||
| 51 | + virtual int call() = 0; | ||
| 52 | + virtual std::string to_string() = 0; | ||
| 53 | +}; | ||
| 54 | + | ||
| 55 | +/** | ||
| 56 | +* the async callback for dvr. | ||
| 57 | +*/ | ||
| 58 | +class SrsDvrAsyncCallThread : public ISrsThreadHandler | ||
| 59 | +{ | ||
| 60 | +private: | ||
| 61 | + SrsThread* pthread; | ||
| 62 | + std::vector<ISrsDvrAsyncCall*> callbacks; | ||
| 63 | +public: | ||
| 64 | + SrsDvrAsyncCallThread(); | ||
| 65 | + virtual ~SrsDvrAsyncCallThread(); | ||
| 66 | +public: | ||
| 67 | + virtual int call(ISrsDvrAsyncCall* c); | ||
| 68 | +public: | ||
| 69 | + virtual int start(); | ||
| 70 | + virtual void stop(); | ||
| 71 | + virtual int cycle(); | ||
| 72 | +}; | ||
| 73 | + | ||
| 74 | +#endif | ||
| 75 | + |
| @@ -1494,7 +1494,7 @@ int SrsConfig::check_config() | @@ -1494,7 +1494,7 @@ int SrsConfig::check_config() | ||
| 1494 | string m = conf->at(j)->name.c_str(); | 1494 | string m = conf->at(j)->name.c_str(); |
| 1495 | if (m != "enabled" && m != "on_connect" && m != "on_close" && m != "on_publish" | 1495 | if (m != "enabled" && m != "on_connect" && m != "on_close" && m != "on_publish" |
| 1496 | && m != "on_unpublish" && m != "on_play" && m != "on_stop" | 1496 | && m != "on_unpublish" && m != "on_play" && m != "on_stop" |
| 1497 | - && m != "on_dvr" | 1497 | + && m != "on_dvr" && m != "on_hls" |
| 1498 | ) { | 1498 | ) { |
| 1499 | ret = ERROR_SYSTEM_CONFIG_INVALID; | 1499 | ret = ERROR_SYSTEM_CONFIG_INVALID; |
| 1500 | srs_error("unsupported vhost http_hooks directive %s, ret=%d", m.c_str(), ret); | 1500 | srs_error("unsupported vhost http_hooks directive %s, ret=%d", m.c_str(), ret); |
| @@ -2411,6 +2411,17 @@ SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost) | @@ -2411,6 +2411,17 @@ SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost) | ||
| 2411 | return conf->get("on_dvr"); | 2411 | return conf->get("on_dvr"); |
| 2412 | } | 2412 | } |
| 2413 | 2413 | ||
| 2414 | +SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost) | ||
| 2415 | +{ | ||
| 2416 | + SrsConfDirective* conf = get_vhost_http_hooks(vhost); | ||
| 2417 | + | ||
| 2418 | + if (!conf) { | ||
| 2419 | + return NULL; | ||
| 2420 | + } | ||
| 2421 | + | ||
| 2422 | + return conf->get("on_hls"); | ||
| 2423 | +} | ||
| 2424 | + | ||
| 2414 | bool SrsConfig::get_bw_check_enabled(string vhost) | 2425 | bool SrsConfig::get_bw_check_enabled(string vhost) |
| 2415 | { | 2426 | { |
| 2416 | SrsConfDirective* conf = get_vhost(vhost); | 2427 | SrsConfDirective* conf = get_vhost(vhost); |
| @@ -631,6 +631,11 @@ public: | @@ -631,6 +631,11 @@ public: | ||
| 631 | * @return the on_dvr callback directive, the args is the url to callback. | 631 | * @return the on_dvr callback directive, the args is the url to callback. |
| 632 | */ | 632 | */ |
| 633 | virtual SrsConfDirective* get_vhost_on_dvr(std::string vhost); | 633 | virtual SrsConfDirective* get_vhost_on_dvr(std::string vhost); |
| 634 | + /** | ||
| 635 | + * get the on_hls callbacks of vhost. | ||
| 636 | + * @return the on_hls callback directive, the args is the url to callback. | ||
| 637 | + */ | ||
| 638 | + virtual SrsConfDirective* get_vhost_on_hls(std::string vhost); | ||
| 634 | // bwct(bandwidth check tool) section | 639 | // bwct(bandwidth check tool) section |
| 635 | public: | 640 | public: |
| 636 | /** | 641 | /** |
| @@ -46,12 +46,6 @@ using namespace std; | @@ -46,12 +46,6 @@ using namespace std; | ||
| 46 | // update the flv duration and filesize every this interval in ms. | 46 | // update the flv duration and filesize every this interval in ms. |
| 47 | #define SRS_DVR_UPDATE_DURATION_INTERVAL 60000 | 47 | #define SRS_DVR_UPDATE_DURATION_INTERVAL 60000 |
| 48 | 48 | ||
| 49 | -// the sleep interval for http async callback. | ||
| 50 | -#define SRS_AUTO_ASYNC_CALLBACL_SLEEP_US 300000 | ||
| 51 | - | ||
| 52 | -// the use raction for dvr rpc. | ||
| 53 | -#define SRS_DVR_USER_ACTION_REAP_SEGMENT "reap_segment" | ||
| 54 | - | ||
| 55 | SrsFlvSegment::SrsFlvSegment(SrsDvrPlan* p) | 49 | SrsFlvSegment::SrsFlvSegment(SrsDvrPlan* p) |
| 56 | { | 50 | { |
| 57 | req = NULL; | 51 | req = NULL; |
| @@ -502,14 +496,6 @@ int SrsFlvSegment::on_reload_vhost_dvr(std::string /*vhost*/) | @@ -502,14 +496,6 @@ int SrsFlvSegment::on_reload_vhost_dvr(std::string /*vhost*/) | ||
| 502 | return ret; | 496 | return ret; |
| 503 | } | 497 | } |
| 504 | 498 | ||
| 505 | -ISrsDvrAsyncCall::ISrsDvrAsyncCall() | ||
| 506 | -{ | ||
| 507 | -} | ||
| 508 | - | ||
| 509 | -ISrsDvrAsyncCall::~ISrsDvrAsyncCall() | ||
| 510 | -{ | ||
| 511 | -} | ||
| 512 | - | ||
| 513 | SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(SrsRequest* r, string p) | 499 | SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(SrsRequest* r, string p) |
| 514 | { | 500 | { |
| 515 | req = r; | 501 | req = r; |
| @@ -534,13 +520,10 @@ int SrsDvrAsyncCallOnDvr::call() | @@ -534,13 +520,10 @@ int SrsDvrAsyncCallOnDvr::call() | ||
| 534 | return ret; | 520 | return ret; |
| 535 | } | 521 | } |
| 536 | 522 | ||
| 537 | - int connection_id = _srs_context->get_id(); | ||
| 538 | - std::string ip = req->ip; | ||
| 539 | - std::string cwd = _srs_config->cwd(); | ||
| 540 | std::string file = path; | 523 | std::string file = path; |
| 541 | for (int i = 0; i < (int)on_dvr->args.size(); i++) { | 524 | for (int i = 0; i < (int)on_dvr->args.size(); i++) { |
| 542 | std::string url = on_dvr->args.at(i); | 525 | std::string url = on_dvr->args.at(i); |
| 543 | - if ((ret = SrsHttpHooks::on_dvr(url, connection_id, ip, req, cwd, file)) != ERROR_SUCCESS) { | 526 | + if ((ret = SrsHttpHooks::on_dvr(url, req, file)) != ERROR_SUCCESS) { |
| 544 | srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret); | 527 | srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret); |
| 545 | return ret; | 528 | return ret; |
| 546 | } | 529 | } |
| @@ -558,62 +541,6 @@ string SrsDvrAsyncCallOnDvr::to_string() | @@ -558,62 +541,6 @@ string SrsDvrAsyncCallOnDvr::to_string() | ||
| 558 | return ss.str(); | 541 | return ss.str(); |
| 559 | } | 542 | } |
| 560 | 543 | ||
| 561 | -SrsDvrAsyncCallThread::SrsDvrAsyncCallThread() | ||
| 562 | -{ | ||
| 563 | - pthread = new SrsThread("async", this, SRS_AUTO_ASYNC_CALLBACL_SLEEP_US, true); | ||
| 564 | -} | ||
| 565 | - | ||
| 566 | -SrsDvrAsyncCallThread::~SrsDvrAsyncCallThread() | ||
| 567 | -{ | ||
| 568 | - stop(); | ||
| 569 | - srs_freep(pthread); | ||
| 570 | - | ||
| 571 | - std::vector<ISrsDvrAsyncCall*>::iterator it; | ||
| 572 | - for (it = callbacks.begin(); it != callbacks.end(); ++it) { | ||
| 573 | - ISrsDvrAsyncCall* call = *it; | ||
| 574 | - srs_freep(call); | ||
| 575 | - } | ||
| 576 | - callbacks.clear(); | ||
| 577 | -} | ||
| 578 | - | ||
| 579 | -int SrsDvrAsyncCallThread::call(ISrsDvrAsyncCall* c) | ||
| 580 | -{ | ||
| 581 | - int ret = ERROR_SUCCESS; | ||
| 582 | - | ||
| 583 | - callbacks.push_back(c); | ||
| 584 | - | ||
| 585 | - return ret; | ||
| 586 | -} | ||
| 587 | - | ||
| 588 | -int SrsDvrAsyncCallThread::start() | ||
| 589 | -{ | ||
| 590 | - return pthread->start(); | ||
| 591 | -} | ||
| 592 | - | ||
| 593 | -void SrsDvrAsyncCallThread::stop() | ||
| 594 | -{ | ||
| 595 | - pthread->stop(); | ||
| 596 | -} | ||
| 597 | - | ||
| 598 | -int SrsDvrAsyncCallThread::cycle() | ||
| 599 | -{ | ||
| 600 | - int ret = ERROR_SUCCESS; | ||
| 601 | - | ||
| 602 | - std::vector<ISrsDvrAsyncCall*> copies = callbacks; | ||
| 603 | - callbacks.clear(); | ||
| 604 | - | ||
| 605 | - std::vector<ISrsDvrAsyncCall*>::iterator it; | ||
| 606 | - for (it = copies.begin(); it != copies.end(); ++it) { | ||
| 607 | - ISrsDvrAsyncCall* call = *it; | ||
| 608 | - if ((ret = call->call()) != ERROR_SUCCESS) { | ||
| 609 | - srs_warn("dvr: ignore callback %s, ret=%d", call->to_string().c_str(), ret); | ||
| 610 | - } | ||
| 611 | - srs_freep(call); | ||
| 612 | - } | ||
| 613 | - | ||
| 614 | - return ret; | ||
| 615 | -} | ||
| 616 | - | ||
| 617 | SrsDvrPlan::SrsDvrPlan() | 544 | SrsDvrPlan::SrsDvrPlan() |
| 618 | { | 545 | { |
| 619 | req = NULL; | 546 | req = NULL; |
| @@ -49,7 +49,7 @@ class SrsThread; | @@ -49,7 +49,7 @@ class SrsThread; | ||
| 49 | 49 | ||
| 50 | #include <srs_app_source.hpp> | 50 | #include <srs_app_source.hpp> |
| 51 | #include <srs_app_reload.hpp> | 51 | #include <srs_app_reload.hpp> |
| 52 | -#include <srs_app_thread.hpp> | 52 | +#include <srs_app_async_call.hpp> |
| 53 | 53 | ||
| 54 | /** | 54 | /** |
| 55 | * a piece of flv segment. | 55 | * a piece of flv segment. |
| @@ -178,15 +178,6 @@ public: | @@ -178,15 +178,6 @@ public: | ||
| 178 | /** | 178 | /** |
| 179 | * the dvr async call. | 179 | * the dvr async call. |
| 180 | */ | 180 | */ |
| 181 | -class ISrsDvrAsyncCall | ||
| 182 | -{ | ||
| 183 | -public: | ||
| 184 | - ISrsDvrAsyncCall(); | ||
| 185 | - virtual ~ISrsDvrAsyncCall(); | ||
| 186 | -public: | ||
| 187 | - virtual int call() = 0; | ||
| 188 | - virtual std::string to_string() = 0; | ||
| 189 | -}; | ||
| 190 | class SrsDvrAsyncCallOnDvr : public ISrsDvrAsyncCall | 181 | class SrsDvrAsyncCallOnDvr : public ISrsDvrAsyncCall |
| 191 | { | 182 | { |
| 192 | private: | 183 | private: |
| @@ -201,25 +192,6 @@ public: | @@ -201,25 +192,6 @@ public: | ||
| 201 | }; | 192 | }; |
| 202 | 193 | ||
| 203 | /** | 194 | /** |
| 204 | -* the async callback for dvr. | ||
| 205 | -*/ | ||
| 206 | -class SrsDvrAsyncCallThread : public ISrsThreadHandler | ||
| 207 | -{ | ||
| 208 | -private: | ||
| 209 | - SrsThread* pthread; | ||
| 210 | - std::vector<ISrsDvrAsyncCall*> callbacks; | ||
| 211 | -public: | ||
| 212 | - SrsDvrAsyncCallThread(); | ||
| 213 | - virtual ~SrsDvrAsyncCallThread(); | ||
| 214 | -public: | ||
| 215 | - virtual int call(ISrsDvrAsyncCall* c); | ||
| 216 | -public: | ||
| 217 | - virtual int start(); | ||
| 218 | - virtual void stop(); | ||
| 219 | - virtual int cycle(); | ||
| 220 | -}; | ||
| 221 | - | ||
| 222 | -/** | ||
| 223 | * the plan for dvr. | 195 | * the plan for dvr. |
| 224 | * use to control the following dvr params: | 196 | * use to control the following dvr params: |
| 225 | * 1. filename: the filename for record file. | 197 | * 1. filename: the filename for record file. |
| @@ -54,6 +54,7 @@ using namespace std; | @@ -54,6 +54,7 @@ using namespace std; | ||
| 54 | #include <srs_rtmp_buffer.hpp> | 54 | #include <srs_rtmp_buffer.hpp> |
| 55 | #include <srs_kernel_ts.hpp> | 55 | #include <srs_kernel_ts.hpp> |
| 56 | #include <srs_app_utility.hpp> | 56 | #include <srs_app_utility.hpp> |
| 57 | +#include <srs_app_http_hooks.hpp> | ||
| 57 | 58 | ||
| 58 | // drop the segment when duration of ts too small. | 59 | // drop the segment when duration of ts too small. |
| 59 | #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 | 60 | #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 |
| @@ -169,6 +170,53 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) | @@ -169,6 +170,53 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) | ||
| 169 | return; | 170 | return; |
| 170 | } | 171 | } |
| 171 | 172 | ||
| 173 | +SrsDvrAsyncCallOnHls::SrsDvrAsyncCallOnHls(SrsRequest* r, string p, int s) | ||
| 174 | +{ | ||
| 175 | + req = r; | ||
| 176 | + path = p; | ||
| 177 | + seq_no = s; | ||
| 178 | +} | ||
| 179 | + | ||
| 180 | +SrsDvrAsyncCallOnHls::~SrsDvrAsyncCallOnHls() | ||
| 181 | +{ | ||
| 182 | +} | ||
| 183 | + | ||
| 184 | +int SrsDvrAsyncCallOnHls::call() | ||
| 185 | +{ | ||
| 186 | + int ret = ERROR_SUCCESS; | ||
| 187 | + | ||
| 188 | +#ifdef SRS_AUTO_HTTP_CALLBACK | ||
| 189 | + // http callback for on_hls in config. | ||
| 190 | + if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) { | ||
| 191 | + // HTTP: on_hls | ||
| 192 | + SrsConfDirective* on_hls = _srs_config->get_vhost_on_hls(req->vhost); | ||
| 193 | + if (!on_hls) { | ||
| 194 | + srs_info("ignore the empty http callback: on_hls"); | ||
| 195 | + return ret; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + std::string file = path; | ||
| 199 | + int sn = seq_no; | ||
| 200 | + for (int i = 0; i < (int)on_hls->args.size(); i++) { | ||
| 201 | + std::string url = on_hls->args.at(i); | ||
| 202 | + if ((ret = SrsHttpHooks::on_hls(url, req, file, sn)) != ERROR_SUCCESS) { | ||
| 203 | + srs_error("hook client on_hls failed. url=%s, ret=%d", url.c_str(), ret); | ||
| 204 | + return ret; | ||
| 205 | + } | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | +#endif | ||
| 209 | + | ||
| 210 | + return ret; | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +string SrsDvrAsyncCallOnHls::to_string() | ||
| 214 | +{ | ||
| 215 | + std::stringstream ss; | ||
| 216 | + ss << "vhost=" << req->vhost << ", file=" << path; | ||
| 217 | + return ss.str(); | ||
| 218 | +} | ||
| 219 | + | ||
| 172 | SrsHlsMuxer::SrsHlsMuxer() | 220 | SrsHlsMuxer::SrsHlsMuxer() |
| 173 | { | 221 | { |
| 174 | req = NULL; | 222 | req = NULL; |
| @@ -177,6 +225,7 @@ SrsHlsMuxer::SrsHlsMuxer() | @@ -177,6 +225,7 @@ SrsHlsMuxer::SrsHlsMuxer() | ||
| 177 | hls_aof_ratio = 1.0; | 225 | hls_aof_ratio = 1.0; |
| 178 | hls_fragment_deviation = 0; | 226 | hls_fragment_deviation = 0; |
| 179 | previous_floor_ts = 0; | 227 | previous_floor_ts = 0; |
| 228 | + accept_floor_ts = 0; | ||
| 180 | hls_ts_floor = false; | 229 | hls_ts_floor = false; |
| 181 | target_duration = 0; | 230 | target_duration = 0; |
| 182 | _sequence_no = 0; | 231 | _sequence_no = 0; |
| @@ -184,6 +233,7 @@ SrsHlsMuxer::SrsHlsMuxer() | @@ -184,6 +233,7 @@ SrsHlsMuxer::SrsHlsMuxer() | ||
| 184 | acodec = SrsCodecAudioReserved1; | 233 | acodec = SrsCodecAudioReserved1; |
| 185 | should_write_cache = false; | 234 | should_write_cache = false; |
| 186 | should_write_file = true; | 235 | should_write_file = true; |
| 236 | + async = new SrsDvrAsyncCallThread(); | ||
| 187 | } | 237 | } |
| 188 | 238 | ||
| 189 | SrsHlsMuxer::~SrsHlsMuxer() | 239 | SrsHlsMuxer::~SrsHlsMuxer() |
| @@ -197,6 +247,7 @@ SrsHlsMuxer::~SrsHlsMuxer() | @@ -197,6 +247,7 @@ SrsHlsMuxer::~SrsHlsMuxer() | ||
| 197 | 247 | ||
| 198 | srs_freep(current); | 248 | srs_freep(current); |
| 199 | srs_freep(req); | 249 | srs_freep(req); |
| 250 | + srs_freep(async); | ||
| 200 | } | 251 | } |
| 201 | 252 | ||
| 202 | int SrsHlsMuxer::initialize(ISrsHlsHandler* h) | 253 | int SrsHlsMuxer::initialize(ISrsHlsHandler* h) |
| @@ -205,6 +256,10 @@ int SrsHlsMuxer::initialize(ISrsHlsHandler* h) | @@ -205,6 +256,10 @@ int SrsHlsMuxer::initialize(ISrsHlsHandler* h) | ||
| 205 | 256 | ||
| 206 | handler = h; | 257 | handler = h; |
| 207 | 258 | ||
| 259 | + if ((ret = async->start()) != ERROR_SUCCESS) { | ||
| 260 | + return ret; | ||
| 261 | + } | ||
| 262 | + | ||
| 208 | return ret; | 263 | return ret; |
| 209 | } | 264 | } |
| 210 | 265 | ||
| @@ -244,6 +299,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | @@ -244,6 +299,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | ||
| 244 | hls_aof_ratio = aof_ratio; | 299 | hls_aof_ratio = aof_ratio; |
| 245 | hls_ts_floor = ts_floor; | 300 | hls_ts_floor = ts_floor; |
| 246 | previous_floor_ts = 0; | 301 | previous_floor_ts = 0; |
| 302 | + accept_floor_ts = 0; | ||
| 247 | hls_window = window; | 303 | hls_window = window; |
| 248 | // for the first time, we set to -N% of fragment, | 304 | // for the first time, we set to -N% of fragment, |
| 249 | // that is, the first piece always smaller. | 305 | // that is, the first piece always smaller. |
| @@ -331,9 +387,17 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | @@ -331,9 +387,17 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | ||
| 331 | std::string ts_file = hls_ts_file; | 387 | std::string ts_file = hls_ts_file; |
| 332 | ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream); | 388 | ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream); |
| 333 | if (hls_ts_floor) { | 389 | if (hls_ts_floor) { |
| 390 | + // accept the floor ts for the first piece. | ||
| 334 | int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); | 391 | int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); |
| 392 | + if (!accept_floor_ts) { | ||
| 393 | + accept_floor_ts = floor_ts - 1; | ||
| 394 | + } else { | ||
| 395 | + accept_floor_ts++; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + // we always ensure the piece is increase one by one. | ||
| 335 | std::stringstream ts_floor; | 399 | std::stringstream ts_floor; |
| 336 | - ts_floor << floor_ts; | 400 | + ts_floor << accept_floor_ts; |
| 337 | ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str()); | 401 | ts_file = srs_string_replace(ts_file, "[timestamp]", ts_floor.str()); |
| 338 | 402 | ||
| 339 | // dup/jmp detect for ts in floor mode. | 403 | // dup/jmp detect for ts in floor mode. |
| @@ -514,6 +578,11 @@ int SrsHlsMuxer::segment_close(string log_desc) | @@ -514,6 +578,11 @@ int SrsHlsMuxer::segment_close(string log_desc) | ||
| 514 | hls_fragment_deviation += (double)(hls_fragment - current->duration); | 578 | hls_fragment_deviation += (double)(hls_fragment - current->duration); |
| 515 | } | 579 | } |
| 516 | 580 | ||
| 581 | + // use async to call the http hooks, for it will cause thread switch. | ||
| 582 | + if ((ret = async->call(new SrsDvrAsyncCallOnHls(req, current->full_path, current->sequence_no))) != ERROR_SUCCESS) { | ||
| 583 | + return ret; | ||
| 584 | + } | ||
| 585 | + | ||
| 517 | srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64", deviation=%.2f", | 586 | srs_info("%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64", deviation=%.2f", |
| 518 | log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration, | 587 | log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration, |
| 519 | current->segment_start_dts, hls_fragment_deviation); | 588 | current->segment_start_dts, hls_fragment_deviation); |
| @@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 39 | 39 | ||
| 40 | #include <srs_kernel_codec.hpp> | 40 | #include <srs_kernel_codec.hpp> |
| 41 | #include <srs_kernel_file.hpp> | 41 | #include <srs_kernel_file.hpp> |
| 42 | +#include <srs_app_async_call.hpp> | ||
| 42 | 43 | ||
| 43 | class SrsSharedPtrMessage; | 44 | class SrsSharedPtrMessage; |
| 44 | class SrsCodecSample; | 45 | class SrsCodecSample; |
| @@ -155,6 +156,23 @@ public: | @@ -155,6 +156,23 @@ public: | ||
| 155 | }; | 156 | }; |
| 156 | 157 | ||
| 157 | /** | 158 | /** |
| 159 | + * the dvr async call. | ||
| 160 | + */ | ||
| 161 | +class SrsDvrAsyncCallOnHls : public ISrsDvrAsyncCall | ||
| 162 | +{ | ||
| 163 | +private: | ||
| 164 | + std::string path; | ||
| 165 | + int seq_no; | ||
| 166 | + SrsRequest* req; | ||
| 167 | +public: | ||
| 168 | + SrsDvrAsyncCallOnHls(SrsRequest* r, std::string p, int s); | ||
| 169 | + virtual ~SrsDvrAsyncCallOnHls(); | ||
| 170 | +public: | ||
| 171 | + virtual int call(); | ||
| 172 | + virtual std::string to_string(); | ||
| 173 | +}; | ||
| 174 | + | ||
| 175 | +/** | ||
| 158 | * muxer the HLS stream(m3u8 and ts files). | 176 | * muxer the HLS stream(m3u8 and ts files). |
| 159 | * generally, the m3u8 muxer only provides methods to open/close segments, | 177 | * generally, the m3u8 muxer only provides methods to open/close segments, |
| 160 | * to flush video/audio, without any mechenisms. | 178 | * to flush video/audio, without any mechenisms. |
| @@ -174,6 +192,7 @@ private: | @@ -174,6 +192,7 @@ private: | ||
| 174 | double hls_aof_ratio; | 192 | double hls_aof_ratio; |
| 175 | double hls_fragment; | 193 | double hls_fragment; |
| 176 | double hls_window; | 194 | double hls_window; |
| 195 | + SrsDvrAsyncCallThread* async; | ||
| 177 | private: | 196 | private: |
| 178 | // whether use floor algorithm for timestamp. | 197 | // whether use floor algorithm for timestamp. |
| 179 | bool hls_ts_floor; | 198 | bool hls_ts_floor; |
| @@ -182,6 +201,7 @@ private: | @@ -182,6 +201,7 @@ private: | ||
| 182 | double hls_fragment_deviation; | 201 | double hls_fragment_deviation; |
| 183 | // the previous reap floor timestamp, | 202 | // the previous reap floor timestamp, |
| 184 | // used to detect the dup or jmp or ts. | 203 | // used to detect the dup or jmp or ts. |
| 204 | + int64_t accept_floor_ts; | ||
| 185 | int64_t previous_floor_ts; | 205 | int64_t previous_floor_ts; |
| 186 | private: | 206 | private: |
| 187 | int _sequence_no; | 207 | int _sequence_no; |
| @@ -36,6 +36,7 @@ using namespace std; | @@ -36,6 +36,7 @@ using namespace std; | ||
| 36 | #include <srs_app_dvr.hpp> | 36 | #include <srs_app_dvr.hpp> |
| 37 | #include <srs_app_http_client.hpp> | 37 | #include <srs_app_http_client.hpp> |
| 38 | #include <srs_core_autofree.hpp> | 38 | #include <srs_core_autofree.hpp> |
| 39 | +#include <srs_app_config.hpp> | ||
| 39 | 40 | ||
| 40 | #define SRS_HTTP_RESPONSE_OK SRS_XSTR(ERROR_SUCCESS) | 41 | #define SRS_HTTP_RESPONSE_OK SRS_XSTR(ERROR_SUCCESS) |
| 41 | 42 | ||
| @@ -50,15 +51,17 @@ SrsHttpHooks::~SrsHttpHooks() | @@ -50,15 +51,17 @@ SrsHttpHooks::~SrsHttpHooks() | ||
| 50 | { | 51 | { |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | -int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* req) | 54 | +int SrsHttpHooks::on_connect(string url, SrsRequest* req) |
| 54 | { | 55 | { |
| 55 | int ret = ERROR_SUCCESS; | 56 | int ret = ERROR_SUCCESS; |
| 56 | 57 | ||
| 58 | + int client_id = _srs_context->get_id(); | ||
| 59 | + | ||
| 57 | std::stringstream ss; | 60 | std::stringstream ss; |
| 58 | ss << SRS_JOBJECT_START | 61 | ss << SRS_JOBJECT_START |
| 59 | << SRS_JFIELD_STR("action", "on_connect") << SRS_JFIELD_CONT | 62 | << SRS_JFIELD_STR("action", "on_connect") << SRS_JFIELD_CONT |
| 60 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 63 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 61 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 64 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 62 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 65 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 63 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 66 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 64 | << SRS_JFIELD_STR("tcUrl", req->tcUrl) << SRS_JFIELD_CONT | 67 | << SRS_JFIELD_STR("tcUrl", req->tcUrl) << SRS_JFIELD_CONT |
| @@ -82,15 +85,17 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r | @@ -82,15 +85,17 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r | ||
| 82 | return ret; | 85 | return ret; |
| 83 | } | 86 | } |
| 84 | 87 | ||
| 85 | -void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* req, int64_t send_bytes, int64_t recv_bytes) | 88 | +void SrsHttpHooks::on_close(string url, SrsRequest* req, int64_t send_bytes, int64_t recv_bytes) |
| 86 | { | 89 | { |
| 87 | int ret = ERROR_SUCCESS; | 90 | int ret = ERROR_SUCCESS; |
| 88 | 91 | ||
| 92 | + int client_id = _srs_context->get_id(); | ||
| 93 | + | ||
| 89 | std::stringstream ss; | 94 | std::stringstream ss; |
| 90 | ss << SRS_JOBJECT_START | 95 | ss << SRS_JOBJECT_START |
| 91 | << SRS_JFIELD_STR("action", "on_close") << SRS_JFIELD_CONT | 96 | << SRS_JFIELD_STR("action", "on_close") << SRS_JFIELD_CONT |
| 92 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 97 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 93 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 98 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 94 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 99 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 95 | << SRS_JFIELD_ORG("send_bytes", send_bytes) << SRS_JFIELD_CONT | 100 | << SRS_JFIELD_ORG("send_bytes", send_bytes) << SRS_JFIELD_CONT |
| 96 | << SRS_JFIELD_ORG("recv_bytes", recv_bytes) << SRS_JFIELD_CONT | 101 | << SRS_JFIELD_ORG("recv_bytes", recv_bytes) << SRS_JFIELD_CONT |
| @@ -114,15 +119,17 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re | @@ -114,15 +119,17 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re | ||
| 114 | return; | 119 | return; |
| 115 | } | 120 | } |
| 116 | 121 | ||
| 117 | -int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* req) | 122 | +int SrsHttpHooks::on_publish(string url, SrsRequest* req) |
| 118 | { | 123 | { |
| 119 | int ret = ERROR_SUCCESS; | 124 | int ret = ERROR_SUCCESS; |
| 120 | 125 | ||
| 126 | + int client_id = _srs_context->get_id(); | ||
| 127 | + | ||
| 121 | std::stringstream ss; | 128 | std::stringstream ss; |
| 122 | ss << SRS_JOBJECT_START | 129 | ss << SRS_JOBJECT_START |
| 123 | << SRS_JFIELD_STR("action", "on_publish") << SRS_JFIELD_CONT | 130 | << SRS_JFIELD_STR("action", "on_publish") << SRS_JFIELD_CONT |
| 124 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 131 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 125 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 132 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 126 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 133 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 127 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 134 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 128 | << SRS_JFIELD_STR("stream", req->stream) | 135 | << SRS_JFIELD_STR("stream", req->stream) |
| @@ -145,15 +152,17 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r | @@ -145,15 +152,17 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r | ||
| 145 | return ret; | 152 | return ret; |
| 146 | } | 153 | } |
| 147 | 154 | ||
| 148 | -void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest* req) | 155 | +void SrsHttpHooks::on_unpublish(string url, SrsRequest* req) |
| 149 | { | 156 | { |
| 150 | int ret = ERROR_SUCCESS; | 157 | int ret = ERROR_SUCCESS; |
| 151 | 158 | ||
| 159 | + int client_id = _srs_context->get_id(); | ||
| 160 | + | ||
| 152 | std::stringstream ss; | 161 | std::stringstream ss; |
| 153 | ss << SRS_JOBJECT_START | 162 | ss << SRS_JOBJECT_START |
| 154 | << SRS_JFIELD_STR("action", "on_unpublish") << SRS_JFIELD_CONT | 163 | << SRS_JFIELD_STR("action", "on_unpublish") << SRS_JFIELD_CONT |
| 155 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 164 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 156 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 165 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 157 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 166 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 158 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 167 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 159 | << SRS_JFIELD_STR("stream", req->stream) | 168 | << SRS_JFIELD_STR("stream", req->stream) |
| @@ -176,15 +185,17 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest | @@ -176,15 +185,17 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest | ||
| 176 | return; | 185 | return; |
| 177 | } | 186 | } |
| 178 | 187 | ||
| 179 | -int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req) | 188 | +int SrsHttpHooks::on_play(string url, SrsRequest* req) |
| 180 | { | 189 | { |
| 181 | int ret = ERROR_SUCCESS; | 190 | int ret = ERROR_SUCCESS; |
| 182 | 191 | ||
| 192 | + int client_id = _srs_context->get_id(); | ||
| 193 | + | ||
| 183 | std::stringstream ss; | 194 | std::stringstream ss; |
| 184 | ss << SRS_JOBJECT_START | 195 | ss << SRS_JOBJECT_START |
| 185 | << SRS_JFIELD_STR("action", "on_play") << SRS_JFIELD_CONT | 196 | << SRS_JFIELD_STR("action", "on_play") << SRS_JFIELD_CONT |
| 186 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 197 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 187 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 198 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 188 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 199 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 189 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 200 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 190 | << SRS_JFIELD_STR("stream", req->stream) | 201 | << SRS_JFIELD_STR("stream", req->stream) |
| @@ -207,15 +218,17 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req) | @@ -207,15 +218,17 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req) | ||
| 207 | return ret; | 218 | return ret; |
| 208 | } | 219 | } |
| 209 | 220 | ||
| 210 | -void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req) | 221 | +void SrsHttpHooks::on_stop(string url, SrsRequest* req) |
| 211 | { | 222 | { |
| 212 | int ret = ERROR_SUCCESS; | 223 | int ret = ERROR_SUCCESS; |
| 213 | 224 | ||
| 225 | + int client_id = _srs_context->get_id(); | ||
| 226 | + | ||
| 214 | std::stringstream ss; | 227 | std::stringstream ss; |
| 215 | ss << SRS_JOBJECT_START | 228 | ss << SRS_JOBJECT_START |
| 216 | << SRS_JFIELD_STR("action", "on_stop") << SRS_JFIELD_CONT | 229 | << SRS_JFIELD_STR("action", "on_stop") << SRS_JFIELD_CONT |
| 217 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 230 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 218 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 231 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 219 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 232 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 220 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 233 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 221 | << SRS_JFIELD_STR("stream", req->stream) | 234 | << SRS_JFIELD_STR("stream", req->stream) |
| @@ -238,15 +251,18 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req | @@ -238,15 +251,18 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req | ||
| 238 | return; | 251 | return; |
| 239 | } | 252 | } |
| 240 | 253 | ||
| 241 | -int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, string cwd, string file) | 254 | +int SrsHttpHooks::on_dvr(string url, SrsRequest* req, string file) |
| 242 | { | 255 | { |
| 243 | int ret = ERROR_SUCCESS; | 256 | int ret = ERROR_SUCCESS; |
| 244 | 257 | ||
| 258 | + int client_id = _srs_context->get_id(); | ||
| 259 | + std::string cwd = _srs_config->cwd(); | ||
| 260 | + | ||
| 245 | std::stringstream ss; | 261 | std::stringstream ss; |
| 246 | ss << SRS_JOBJECT_START | 262 | ss << SRS_JOBJECT_START |
| 247 | << SRS_JFIELD_STR("action", "on_dvr") << SRS_JFIELD_CONT | 263 | << SRS_JFIELD_STR("action", "on_dvr") << SRS_JFIELD_CONT |
| 248 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 264 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 249 | - << SRS_JFIELD_STR("ip", ip) << SRS_JFIELD_CONT | 265 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT |
| 250 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 266 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 251 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 267 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 252 | << SRS_JFIELD_STR("stream", req->stream) << SRS_JFIELD_CONT | 268 | << SRS_JFIELD_STR("stream", req->stream) << SRS_JFIELD_CONT |
| @@ -271,32 +287,37 @@ int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, | @@ -271,32 +287,37 @@ int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, | ||
| 271 | return ret; | 287 | return ret; |
| 272 | } | 288 | } |
| 273 | 289 | ||
| 274 | -int SrsHttpHooks::on_dvr_reap_segment(string url, int client_id, SrsRequest* req, string cwd, string file) | 290 | +int SrsHttpHooks::on_hls(string url, SrsRequest* req, string file, int sn) |
| 275 | { | 291 | { |
| 276 | int ret = ERROR_SUCCESS; | 292 | int ret = ERROR_SUCCESS; |
| 277 | 293 | ||
| 294 | + int client_id = _srs_context->get_id(); | ||
| 295 | + std::string cwd = _srs_config->cwd(); | ||
| 296 | + | ||
| 278 | std::stringstream ss; | 297 | std::stringstream ss; |
| 279 | ss << SRS_JOBJECT_START | 298 | ss << SRS_JOBJECT_START |
| 280 | - << SRS_JFIELD_STR("action", "on_dvr_reap_segment") << SRS_JFIELD_CONT | 299 | + << SRS_JFIELD_STR("action", "on_hls") << SRS_JFIELD_CONT |
| 281 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT | 300 | << SRS_JFIELD_ORG("client_id", client_id) << SRS_JFIELD_CONT |
| 301 | + << SRS_JFIELD_STR("ip", req->ip) << SRS_JFIELD_CONT | ||
| 282 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT | 302 | << SRS_JFIELD_STR("vhost", req->vhost) << SRS_JFIELD_CONT |
| 283 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT | 303 | << SRS_JFIELD_STR("app", req->app) << SRS_JFIELD_CONT |
| 284 | << SRS_JFIELD_STR("stream", req->stream) << SRS_JFIELD_CONT | 304 | << SRS_JFIELD_STR("stream", req->stream) << SRS_JFIELD_CONT |
| 285 | << SRS_JFIELD_STR("cwd", cwd) << SRS_JFIELD_CONT | 305 | << SRS_JFIELD_STR("cwd", cwd) << SRS_JFIELD_CONT |
| 286 | - << SRS_JFIELD_STR("file", file) | 306 | + << SRS_JFIELD_STR("file", file) << SRS_JFIELD_CONT |
| 307 | + << SRS_JFIELD_ORG("seq_no", sn) | ||
| 287 | << SRS_JOBJECT_END; | 308 | << SRS_JOBJECT_END; |
| 288 | 309 | ||
| 289 | std::string data = ss.str(); | 310 | std::string data = ss.str(); |
| 290 | std::string res; | 311 | std::string res; |
| 291 | int status_code; | 312 | int status_code; |
| 292 | if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { | 313 | if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { |
| 293 | - srs_error("http post on_dvr_reap_segment uri failed, ignored. " | 314 | + srs_error("http post on_hls uri failed, ignored. " |
| 294 | "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", | 315 | "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", |
| 295 | client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); | 316 | client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); |
| 296 | return ret; | 317 | return ret; |
| 297 | } | 318 | } |
| 298 | 319 | ||
| 299 | - srs_trace("http hook on_dvr_reap_segment success. " | 320 | + srs_trace("http hook on_hls success. " |
| 300 | "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | 321 | "client_id=%d, url=%s, request=%s, response=%s, ret=%d", |
| 301 | client_id, url.c_str(), data.c_str(), res.c_str(), ret); | 322 | client_id, url.c_str(), data.c_str(), res.c_str(), ret); |
| 302 | 323 |
| @@ -55,64 +55,55 @@ public: | @@ -55,64 +55,55 @@ public: | ||
| 55 | public: | 55 | public: |
| 56 | /** | 56 | /** |
| 57 | * on_connect hook, when client connect to srs. | 57 | * on_connect hook, when client connect to srs. |
| 58 | - * @param client_id the id of client on server. | ||
| 59 | * @param url the api server url, to valid the client. | 58 | * @param url the api server url, to valid the client. |
| 60 | * ignore if empty. | 59 | * ignore if empty. |
| 61 | */ | 60 | */ |
| 62 | - static int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req); | 61 | + static int on_connect(std::string url, SrsRequest* req); |
| 63 | /** | 62 | /** |
| 64 | * on_close hook, when client disconnect to srs, where client is valid by on_connect. | 63 | * on_close hook, when client disconnect to srs, where client is valid by on_connect. |
| 65 | - * @param client_id the id of client on server. | ||
| 66 | * @param url the api server url, to process the event. | 64 | * @param url the api server url, to process the event. |
| 67 | * ignore if empty. | 65 | * ignore if empty. |
| 68 | */ | 66 | */ |
| 69 | - static void on_close(std::string url, int client_id, std::string ip, SrsRequest* req, int64_t send_bytes, int64_t recv_bytes); | 67 | + static void on_close(std::string url, SrsRequest* req, int64_t send_bytes, int64_t recv_bytes); |
| 70 | /** | 68 | /** |
| 71 | * on_publish hook, when client(encoder) start to publish stream | 69 | * on_publish hook, when client(encoder) start to publish stream |
| 72 | - * @param client_id the id of client on server. | ||
| 73 | * @param url the api server url, to valid the client. | 70 | * @param url the api server url, to valid the client. |
| 74 | * ignore if empty. | 71 | * ignore if empty. |
| 75 | */ | 72 | */ |
| 76 | - static int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req); | 73 | + static int on_publish(std::string url, SrsRequest* req); |
| 77 | /** | 74 | /** |
| 78 | * on_unpublish hook, when client(encoder) stop publish stream. | 75 | * on_unpublish hook, when client(encoder) stop publish stream. |
| 79 | - * @param client_id the id of client on server. | ||
| 80 | * @param url the api server url, to process the event. | 76 | * @param url the api server url, to process the event. |
| 81 | * ignore if empty. | 77 | * ignore if empty. |
| 82 | */ | 78 | */ |
| 83 | - static void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req); | 79 | + static void on_unpublish(std::string url, SrsRequest* req); |
| 84 | /** | 80 | /** |
| 85 | * on_play hook, when client start to play stream. | 81 | * on_play hook, when client start to play stream. |
| 86 | - * @param client_id the id of client on server. | ||
| 87 | * @param url the api server url, to valid the client. | 82 | * @param url the api server url, to valid the client. |
| 88 | * ignore if empty. | 83 | * ignore if empty. |
| 89 | */ | 84 | */ |
| 90 | - static int on_play(std::string url, int client_id, std::string ip, SrsRequest* req); | 85 | + static int on_play(std::string url, SrsRequest* req); |
| 91 | /** | 86 | /** |
| 92 | * on_stop hook, when client stop to play the stream. | 87 | * on_stop hook, when client stop to play the stream. |
| 93 | - * @param client_id the id of client on server. | ||
| 94 | * @param url the api server url, to process the event. | 88 | * @param url the api server url, to process the event. |
| 95 | * ignore if empty. | 89 | * ignore if empty. |
| 96 | */ | 90 | */ |
| 97 | - static void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); | 91 | + static void on_stop(std::string url, SrsRequest* req); |
| 98 | /** | 92 | /** |
| 99 | * on_dvr hook, when reap a dvr file. | 93 | * on_dvr hook, when reap a dvr file. |
| 100 | - * @param client_id the id of client on server. | ||
| 101 | * @param url the api server url, to process the event. | 94 | * @param url the api server url, to process the event. |
| 102 | * ignore if empty. | 95 | * ignore if empty. |
| 103 | - * @param cwd the current work directory, used to resolve the reltive file path. | ||
| 104 | * @param file the file path, can be relative or absolute path. | 96 | * @param file the file path, can be relative or absolute path. |
| 105 | */ | 97 | */ |
| 106 | - static int on_dvr(std::string url, int client_id, std::string ip, SrsRequest* req, std::string cwd, std::string file); | 98 | + static int on_dvr(std::string url, SrsRequest* req, std::string file); |
| 107 | /** | 99 | /** |
| 108 | - * when dvr reap segment, callback. | ||
| 109 | - * @param client_id the id of client on server. | 100 | + * when hls reap segment, callback. |
| 110 | * @param url the api server url, to process the event. | 101 | * @param url the api server url, to process the event. |
| 111 | * ignore if empty. | 102 | * ignore if empty. |
| 112 | - * @param cwd the current work directory, used to resolve the reltive file path. | ||
| 113 | - * @param file the file path, can be relative or absolute path. | 103 | + * @param file the ts file path, can be relative or absolute path. |
| 104 | + * @param sn the seq_no, the sequence number of ts in hls/m3u8. | ||
| 114 | */ | 105 | */ |
| 115 | - static int on_dvr_reap_segment(std::string url, int client_id, SrsRequest* req, std::string cwd, std::string file); | 106 | + static int on_hls(std::string url, SrsRequest* req, std::string file, int sn); |
| 116 | private: | 107 | private: |
| 117 | static int do_post(std::string url, std::string req, int& code, std::string& res); | 108 | static int do_post(std::string url, std::string req, int& code, std::string& res); |
| 118 | }; | 109 | }; |
| @@ -1265,10 +1265,9 @@ int SrsRtmpConn::http_hooks_on_connect() | @@ -1265,10 +1265,9 @@ int SrsRtmpConn::http_hooks_on_connect() | ||
| 1265 | return ret; | 1265 | return ret; |
| 1266 | } | 1266 | } |
| 1267 | 1267 | ||
| 1268 | - int connection_id = _srs_context->get_id(); | ||
| 1269 | for (int i = 0; i < (int)on_connect->args.size(); i++) { | 1268 | for (int i = 0; i < (int)on_connect->args.size(); i++) { |
| 1270 | std::string url = on_connect->args.at(i); | 1269 | std::string url = on_connect->args.at(i); |
| 1271 | - if ((ret = SrsHttpHooks::on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) { | 1270 | + if ((ret = SrsHttpHooks::on_connect(url, req)) != ERROR_SUCCESS) { |
| 1272 | srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); | 1271 | srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); |
| 1273 | return ret; | 1272 | return ret; |
| 1274 | } | 1273 | } |
| @@ -1291,10 +1290,9 @@ void SrsRtmpConn::http_hooks_on_close() | @@ -1291,10 +1290,9 @@ void SrsRtmpConn::http_hooks_on_close() | ||
| 1291 | return; | 1290 | return; |
| 1292 | } | 1291 | } |
| 1293 | 1292 | ||
| 1294 | - int connection_id = _srs_context->get_id(); | ||
| 1295 | for (int i = 0; i < (int)on_close->args.size(); i++) { | 1293 | for (int i = 0; i < (int)on_close->args.size(); i++) { |
| 1296 | std::string url = on_close->args.at(i); | 1294 | std::string url = on_close->args.at(i); |
| 1297 | - SrsHttpHooks::on_close(url, connection_id, ip, req, kbps->get_send_bytes(), kbps->get_recv_bytes()); | 1295 | + SrsHttpHooks::on_close(url, req, kbps->get_send_bytes(), kbps->get_recv_bytes()); |
| 1298 | } | 1296 | } |
| 1299 | } | 1297 | } |
| 1300 | #endif | 1298 | #endif |
| @@ -1313,10 +1311,9 @@ int SrsRtmpConn::http_hooks_on_publish() | @@ -1313,10 +1311,9 @@ int SrsRtmpConn::http_hooks_on_publish() | ||
| 1313 | return ret; | 1311 | return ret; |
| 1314 | } | 1312 | } |
| 1315 | 1313 | ||
| 1316 | - int connection_id = _srs_context->get_id(); | ||
| 1317 | for (int i = 0; i < (int)on_publish->args.size(); i++) { | 1314 | for (int i = 0; i < (int)on_publish->args.size(); i++) { |
| 1318 | std::string url = on_publish->args.at(i); | 1315 | std::string url = on_publish->args.at(i); |
| 1319 | - if ((ret = SrsHttpHooks::on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) { | 1316 | + if ((ret = SrsHttpHooks::on_publish(url, req)) != ERROR_SUCCESS) { |
| 1320 | srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); | 1317 | srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); |
| 1321 | return ret; | 1318 | return ret; |
| 1322 | } | 1319 | } |
| @@ -1339,10 +1336,9 @@ void SrsRtmpConn::http_hooks_on_unpublish() | @@ -1339,10 +1336,9 @@ void SrsRtmpConn::http_hooks_on_unpublish() | ||
| 1339 | return; | 1336 | return; |
| 1340 | } | 1337 | } |
| 1341 | 1338 | ||
| 1342 | - int connection_id = _srs_context->get_id(); | ||
| 1343 | for (int i = 0; i < (int)on_unpublish->args.size(); i++) { | 1339 | for (int i = 0; i < (int)on_unpublish->args.size(); i++) { |
| 1344 | std::string url = on_unpublish->args.at(i); | 1340 | std::string url = on_unpublish->args.at(i); |
| 1345 | - SrsHttpHooks::on_unpublish(url, connection_id, ip, req); | 1341 | + SrsHttpHooks::on_unpublish(url, req); |
| 1346 | } | 1342 | } |
| 1347 | } | 1343 | } |
| 1348 | #endif | 1344 | #endif |
| @@ -1361,10 +1357,9 @@ int SrsRtmpConn::http_hooks_on_play() | @@ -1361,10 +1357,9 @@ int SrsRtmpConn::http_hooks_on_play() | ||
| 1361 | return ret; | 1357 | return ret; |
| 1362 | } | 1358 | } |
| 1363 | 1359 | ||
| 1364 | - int connection_id = _srs_context->get_id(); | ||
| 1365 | for (int i = 0; i < (int)on_play->args.size(); i++) { | 1360 | for (int i = 0; i < (int)on_play->args.size(); i++) { |
| 1366 | std::string url = on_play->args.at(i); | 1361 | std::string url = on_play->args.at(i); |
| 1367 | - if ((ret = SrsHttpHooks::on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) { | 1362 | + if ((ret = SrsHttpHooks::on_play(url, req)) != ERROR_SUCCESS) { |
| 1368 | srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); | 1363 | srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); |
| 1369 | return ret; | 1364 | return ret; |
| 1370 | } | 1365 | } |
| @@ -1387,10 +1382,9 @@ void SrsRtmpConn::http_hooks_on_stop() | @@ -1387,10 +1382,9 @@ void SrsRtmpConn::http_hooks_on_stop() | ||
| 1387 | return; | 1382 | return; |
| 1388 | } | 1383 | } |
| 1389 | 1384 | ||
| 1390 | - int connection_id = _srs_context->get_id(); | ||
| 1391 | for (int i = 0; i < (int)on_stop->args.size(); i++) { | 1385 | for (int i = 0; i < (int)on_stop->args.size(); i++) { |
| 1392 | std::string url = on_stop->args.at(i); | 1386 | std::string url = on_stop->args.at(i); |
| 1393 | - SrsHttpHooks::on_stop(url, connection_id, ip, req); | 1387 | + SrsHttpHooks::on_stop(url, req); |
| 1394 | } | 1388 | } |
| 1395 | } | 1389 | } |
| 1396 | #endif | 1390 | #endif |
-
请 注册 或 登录 后发表评论