正在显示
42 个修改的文件
包含
1801 行增加
和
1046 行删除
| @@ -3,7 +3,7 @@ simple-rtmp-server | @@ -3,7 +3,7 @@ simple-rtmp-server | ||
| 3 | 3 | ||
| 4 | srs(simple rtmp origin live server) over state-threads.<br/> | 4 | srs(simple rtmp origin live server) over state-threads.<br/> |
| 5 | srs is a simple, high-performance, running in single process, origin live server.<br/> | 5 | srs is a simple, high-performance, running in single process, origin live server.<br/> |
| 6 | -srs supports rtmp, HLS, transcoding, forward, http hooks. <br/> | 6 | +srs supports vhost, rtmp, HLS, transcoding, forward, http hooks. <br/> |
| 7 | blog: [http://blog.csdn.net/win_lin](http://blog.csdn.net/win_lin) <br/> | 7 | blog: [http://blog.csdn.net/win_lin](http://blog.csdn.net/win_lin) <br/> |
| 8 | see also: [https://github.com/winlinvip/simple-rtmp-server](https://github.com/winlinvip/simple-rtmp-server) <br/> | 8 | see also: [https://github.com/winlinvip/simple-rtmp-server](https://github.com/winlinvip/simple-rtmp-server) <br/> |
| 9 | see also: [http://winlinvip.github.io/simple-rtmp-server](http://winlinvip.github.io/simple-rtmp-server) | 9 | see also: [http://winlinvip.github.io/simple-rtmp-server](http://winlinvip.github.io/simple-rtmp-server) |
| @@ -12,30 +12,36 @@ see also: [http://winlinvip.github.io/simple-rtmp-server](http://winlinvip.githu | @@ -12,30 +12,36 @@ see also: [http://winlinvip.github.io/simple-rtmp-server](http://winlinvip.githu | ||
| 12 | winlin(winterserver): [http://blog.csdn.net/win_lin](http://blog.csdn.net/win_lin) | 12 | winlin(winterserver): [http://blog.csdn.net/win_lin](http://blog.csdn.net/win_lin) |
| 13 | 13 | ||
| 14 | ### Usage | 14 | ### Usage |
| 15 | -step 1: build srs <br/> | 15 | +<strong>step 1:</strong> build srs <br/> |
| 16 | <pre> | 16 | <pre> |
| 17 | tar xf simple-rtmp-server-*.*.tar.gz | 17 | tar xf simple-rtmp-server-*.*.tar.gz |
| 18 | cd simple-rtmp-server-*.*/trunk | 18 | cd simple-rtmp-server-*.*/trunk |
| 19 | ./configure --with-ssl --with-hls --with-ffmpeg --with-http | 19 | ./configure --with-ssl --with-hls --with-ffmpeg --with-http |
| 20 | make | 20 | make |
| 21 | </pre> | 21 | </pre> |
| 22 | -step 2: start srs <br/> | 22 | +or get the latest code:<br/> |
| 23 | <pre> | 23 | <pre> |
| 24 | -./objs/simple_rtmp_server -c conf/srs.conf | 24 | +git clone https://github.com/winlinvip/simple-rtmp-server |
| 25 | +cd simple-rtmp-server/trunk | ||
| 26 | +./configure --with-ssl --with-hls --with-ffmpeg --with-http | ||
| 27 | +</pre> | ||
| 28 | +<strong>step 2:</strong> start srs <br/> | ||
| 29 | +<pre> | ||
| 30 | +./objs/srs -c conf/srs.conf | ||
| 25 | </pre> | 31 | </pre> |
| 26 | -step 3(optinal): start srs listen at 19350 to forward to<br/> | 32 | +<strong>step 3(optinal):</strong> start srs listen at 19350 to forward to<br/> |
| 27 | <pre> | 33 | <pre> |
| 28 | -./objs/simple_rtmp_server -c conf/srs.19350.conf | 34 | +./objs/srs -c conf/srs.19350.conf |
| 29 | </pre> | 35 | </pre> |
| 30 | -step 4(optional): start nginx for HLS <br/> | 36 | +<strong>step 4(optinal):</strong> start nginx for HLS <br/> |
| 31 | <pre> | 37 | <pre> |
| 32 | sudo ./objs/nginx/sbin/nginx | 38 | sudo ./objs/nginx/sbin/nginx |
| 33 | </pre> | 39 | </pre> |
| 34 | -step 5(optional): start http hooks for srs callback <br/> | 40 | +<strong>step 5(optinal):</strong> start http hooks for srs callback <br/> |
| 35 | <pre> | 41 | <pre> |
| 36 | python ./research/api-server/server.py 8085 | 42 | python ./research/api-server/server.py 8085 |
| 37 | </pre> | 43 | </pre> |
| 38 | -step 6: publish live stream <br/> | 44 | +<strong>step 6:</strong> publish live stream <br/> |
| 39 | <pre> | 45 | <pre> |
| 40 | FMS URL: rtmp://127.0.0.1:1935/live | 46 | FMS URL: rtmp://127.0.0.1:1935/live |
| 41 | Stream: livestream | 47 | Stream: livestream |
| @@ -47,7 +53,7 @@ For example, use ffmpeg to publish: | @@ -47,7 +53,7 @@ For example, use ffmpeg to publish: | ||
| 47 | sleep 1; \ | 53 | sleep 1; \ |
| 48 | done | 54 | done |
| 49 | </pre> | 55 | </pre> |
| 50 | -step 7: add server ip to client hosts as demo. <br/> | 56 | +<strong>step 7:</strong> add server ip to client hosts as demo. <br/> |
| 51 | <pre> | 57 | <pre> |
| 52 | # edit the folowing file: | 58 | # edit the folowing file: |
| 53 | # linux: /etc/hosts | 59 | # linux: /etc/hosts |
| @@ -55,26 +61,41 @@ step 7: add server ip to client hosts as demo. <br/> | @@ -55,26 +61,41 @@ step 7: add server ip to client hosts as demo. <br/> | ||
| 55 | # where server ip is 192.168.2.111 | 61 | # where server ip is 192.168.2.111 |
| 56 | 192.168.2.111 demo | 62 | 192.168.2.111 demo |
| 57 | </pre> | 63 | </pre> |
| 58 | -step 8: play live stream. <br/> | 64 | +<strong>step 8:</strong> play live stream. <br/> |
| 59 | <pre> | 65 | <pre> |
| 66 | +players: http://demo:80/players | ||
| 60 | rtmp url: rtmp://demo:1935/live/livestream | 67 | rtmp url: rtmp://demo:1935/live/livestream |
| 61 | m3u8 url: http://demo:80/live/livestream.m3u8 | 68 | m3u8 url: http://demo:80/live/livestream.m3u8 |
| 69 | +for android: http://demo:80/live/livestream.html | ||
| 62 | </pre> | 70 | </pre> |
| 63 | -step 9: play live stream auto transcoded<br/> | 71 | +<strong>step 9(optinal):</strong> play live stream auto transcoded<br/> |
| 64 | <pre> | 72 | <pre> |
| 65 | rtmp url: rtmp://demo:1935/live/livestream_ld | 73 | rtmp url: rtmp://demo:1935/live/livestream_ld |
| 66 | m3u8 url: http://demo:80/live/livestream_ld.m3u8 | 74 | m3u8 url: http://demo:80/live/livestream_ld.m3u8 |
| 75 | +for android: http://demo:80/live/livestream_ld.html | ||
| 67 | rtmp url: rtmp://demo:1935/live/livestream_sd | 76 | rtmp url: rtmp://demo:1935/live/livestream_sd |
| 68 | m3u8 url: http://demo:80/live/livestream_sd.m3u8 | 77 | m3u8 url: http://demo:80/live/livestream_sd.m3u8 |
| 78 | +for android: http://demo:80/live/livestream_sd.html | ||
| 69 | </pre> | 79 | </pre> |
| 70 | -step 10: play live stream auto forwarded, the hls dir change to /forward<br/> | 80 | +<strong>step 10(optinal):</strong> play live stream auto forwarded, the hls dir change to /forward<br/> |
| 71 | <pre> | 81 | <pre> |
| 72 | rtmp url: rtmp://demo:19350/live/livestream | 82 | rtmp url: rtmp://demo:19350/live/livestream |
| 73 | m3u8 url: http://demo:80/forward/live/livestream.m3u8 | 83 | m3u8 url: http://demo:80/forward/live/livestream.m3u8 |
| 84 | +for android: http://demo:80/forward/live/livestream.html | ||
| 74 | rtmp url: rtmp://demo:19350/live/livestream_ld | 85 | rtmp url: rtmp://demo:19350/live/livestream_ld |
| 75 | m3u8 url: http://demo:80/forward/live/livestream_ld.m3u8 | 86 | m3u8 url: http://demo:80/forward/live/livestream_ld.m3u8 |
| 87 | +for android: http://demo:80/forward/live/livestream_ld.html | ||
| 76 | rtmp url: rtmp://demo:19350/live/livestream_sd | 88 | rtmp url: rtmp://demo:19350/live/livestream_sd |
| 77 | m3u8 url: http://demo:80/forward/live/livestream_sd.m3u8 | 89 | m3u8 url: http://demo:80/forward/live/livestream_sd.m3u8 |
| 90 | +for android: http://demo:80/forward/live/livestream_sd.html | ||
| 91 | +</pre> | ||
| 92 | +<strong>step 11(optinal):</strong> modify the config and reload it (all features support reload)<br/> | ||
| 93 | +<pre> | ||
| 94 | +killall -1 srs | ||
| 95 | +</pre> | ||
| 96 | +or use specified signal to reload:<br/> | ||
| 97 | +<pre> | ||
| 98 | +killall -s SIGHUP srs | ||
| 78 | </pre> | 99 | </pre> |
| 79 | 100 | ||
| 80 | ### Architecture | 101 | ### Architecture |
| @@ -192,7 +213,15 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | @@ -192,7 +213,15 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | ||
| 192 | * nginx v1.5.0: 139524 lines <br/> | 213 | * nginx v1.5.0: 139524 lines <br/> |
| 193 | 214 | ||
| 194 | ### History | 215 | ### History |
| 195 | -* v0.8, 2013-12-08, v0.8 released. 19186 lines. | 216 | +* v0.9, 2013-12-15, ensure the HLS(ts) is continous when republish stream. |
| 217 | +* v0.9, 2013-12-15, fix the hls reload bug, feed it the sequence header. | ||
| 218 | +* v0.9, 2013-12-15, refine protocol, use int64_t timestamp for ts and jitter. | ||
| 219 | +* v0.9, 2013-12-15, support set the live queue length(in seconds), drop when full. | ||
| 220 | +* v0.9, 2013-12-15, fix the forwarder reconnect bug, feed it the sequence header. | ||
| 221 | +* v0.9, 2013-12-15, support reload the hls/forwarder/transcoder. | ||
| 222 | +* v0.9, 2013-12-14, refine the thread model for the retry threads. | ||
| 223 | +* v0.9, 2013-12-10, auto install depends tools/libs on centos/ubuntu. | ||
| 224 | +* v0.8, 2013-12-08, [v0.8](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.8) released. 19186 lines. | ||
| 196 | * v0.8, 2013-12-08, support http hooks: on_connect/close/publish/unpublish/play/stop. | 225 | * v0.8, 2013-12-08, support http hooks: on_connect/close/publish/unpublish/play/stop. |
| 197 | * v0.8, 2013-12-08, support multiple http hooks for a event. | 226 | * v0.8, 2013-12-08, support multiple http hooks for a event. |
| 198 | * v0.8, 2013-12-07, support http callback hooks, on_connect. | 227 | * v0.8, 2013-12-07, support http callback hooks, on_connect. |
| @@ -201,32 +230,32 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | @@ -201,32 +230,32 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | ||
| 201 | * v0.8, 2013-12-06, support max_connections, drop if exceed. | 230 | * v0.8, 2013-12-06, support max_connections, drop if exceed. |
| 202 | * v0.8, 2013-12-05, support log_dir, write ffmpeg log to file. | 231 | * v0.8, 2013-12-05, support log_dir, write ffmpeg log to file. |
| 203 | * v0.8, 2013-12-05, fix the forward/hls/encoder bug. | 232 | * v0.8, 2013-12-05, fix the forward/hls/encoder bug. |
| 204 | -* v0.7, 2013-12-03, v0.7 released. 17605 lines. | 233 | +* v0.7, 2013-12-03, [v0.7](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.7) released. 17605 lines. |
| 205 | * v0.7, 2013-12-01, support dead-loop detect for forwarder and transcoder. | 234 | * v0.7, 2013-12-01, support dead-loop detect for forwarder and transcoder. |
| 206 | * v0.7, 2013-12-01, support all ffmpeg filters and params. | 235 | * v0.7, 2013-12-01, support all ffmpeg filters and params. |
| 207 | * v0.7, 2013-11-30, support live stream transcoder by ffmpeg. | 236 | * v0.7, 2013-11-30, support live stream transcoder by ffmpeg. |
| 208 | * v0.7, 2013-11-30, support --with/without -ffmpeg, build ffmpeg-2.1. | 237 | * v0.7, 2013-11-30, support --with/without -ffmpeg, build ffmpeg-2.1. |
| 209 | * v0.7, 2013-11-30, add ffmpeg-2.1, x264-core138, lame-3.99.5, libaacplus-2.0.2. | 238 | * v0.7, 2013-11-30, add ffmpeg-2.1, x264-core138, lame-3.99.5, libaacplus-2.0.2. |
| 210 | -* v0.6, 2013-11-29, v0.6 released. 16094 lines. | 239 | +* v0.6, 2013-11-29, [v0.6](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.6) released. 16094 lines. |
| 211 | * v0.6, 2013-11-29, add performance summary, 1800 clients, 900Mbps, CPU 90.2%, 41MB. | 240 | * v0.6, 2013-11-29, add performance summary, 1800 clients, 900Mbps, CPU 90.2%, 41MB. |
| 212 | * v0.6, 2013-11-29, support forward stream to other edge server. | 241 | * v0.6, 2013-11-29, support forward stream to other edge server. |
| 213 | * v0.6, 2013-11-29, support forward stream to other origin server. | 242 | * v0.6, 2013-11-29, support forward stream to other origin server. |
| 214 | * v0.6, 2013-11-28, fix memory leak bug, aac decode bug. | 243 | * v0.6, 2013-11-28, fix memory leak bug, aac decode bug. |
| 215 | * v0.6, 2013-11-27, support --with or --without -hls and -ssl options. | 244 | * v0.6, 2013-11-27, support --with or --without -hls and -ssl options. |
| 216 | * v0.6, 2013-11-27, support AAC 44100HZ sample rate for iphone, adjust the timestamp. | 245 | * v0.6, 2013-11-27, support AAC 44100HZ sample rate for iphone, adjust the timestamp. |
| 217 | -* v0.5, 2013-11-26, v0.5 released. 14449 lines. | 246 | +* v0.5, 2013-11-26, [v0.5](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.5) released. 14449 lines. |
| 218 | * v0.5, 2013-11-24, support HLS(m3u8), fragment and window. | 247 | * v0.5, 2013-11-24, support HLS(m3u8), fragment and window. |
| 219 | * v0.5, 2013-11-24, support record to ts file for HLS. | 248 | * v0.5, 2013-11-24, support record to ts file for HLS. |
| 220 | * v0.5, 2013-11-21, add ts_info tool to demux ts file. | 249 | * v0.5, 2013-11-21, add ts_info tool to demux ts file. |
| 221 | * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6). | 250 | * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6). |
| 222 | -* v0.4, 2013-11-10, v0.4 released. 12500 lines. | 251 | +* v0.4, 2013-11-10, [v0.4](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.4) released. 12500 lines. |
| 223 | * v0.4, 2013-11-10, support config and reload the pithy print. | 252 | * v0.4, 2013-11-10, support config and reload the pithy print. |
| 224 | * v0.4, 2013-11-09, support reload config(vhost and its detail). | 253 | * v0.4, 2013-11-09, support reload config(vhost and its detail). |
| 225 | * v0.4, 2013-11-09, support reload config(listen and chunk_size) by SIGHUP(1). | 254 | * v0.4, 2013-11-09, support reload config(listen and chunk_size) by SIGHUP(1). |
| 226 | * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play. | 255 | * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play. |
| 227 | * v0.4, 2013-11-09, support config the chunk_size. | 256 | * v0.4, 2013-11-09, support config the chunk_size. |
| 228 | * v0.4, 2013-11-09, support pause for live stream. | 257 | * v0.4, 2013-11-09, support pause for live stream. |
| 229 | -* v0.3, 2013-11-04, v0.3 released. 11773 lines. | 258 | +* v0.3, 2013-11-04, [v0.3](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.3) released. 11773 lines. |
| 230 | * v0.3, 2013-11-04, support refer/play-refer/publish-refer. | 259 | * v0.3, 2013-11-04, support refer/play-refer/publish-refer. |
| 231 | * v0.3, 2013-11-04, support vhosts specified config. | 260 | * v0.3, 2013-11-04, support vhosts specified config. |
| 232 | * v0.3, 2013-11-02, support listen multiple ports. | 261 | * v0.3, 2013-11-02, support listen multiple ports. |
| @@ -234,12 +263,12 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | @@ -234,12 +263,12 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | ||
| 234 | * v0.3, 2013-10-29, support pithy print log message specified by stage. | 263 | * v0.3, 2013-10-29, support pithy print log message specified by stage. |
| 235 | * v0.3, 2013-10-28, support librtmp without extended-timestamp in 0xCX chunk packet. | 264 | * v0.3, 2013-10-28, support librtmp without extended-timestamp in 0xCX chunk packet. |
| 236 | * v0.3, 2013-10-27, support cache last gop for client fast startup. | 265 | * v0.3, 2013-10-27, support cache last gop for client fast startup. |
| 237 | -* v0.2, 2013-10-25, v0.2 released. 10125 lines. | 266 | +* v0.2, 2013-10-25, [v0.2](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.2) released. 10125 lines. |
| 238 | * v0.2, 2013-10-25, support flash publish. | 267 | * v0.2, 2013-10-25, support flash publish. |
| 239 | * v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake. | 268 | * v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake. |
| 240 | * v0.2, 2013-10-24, support time jitter detect and correct algorithm | 269 | * v0.2, 2013-10-24, support time jitter detect and correct algorithm |
| 241 | * v0.2, 2013-10-24, support decode codec type to cache the h264/avc sequence header. | 270 | * v0.2, 2013-10-24, support decode codec type to cache the h264/avc sequence header. |
| 242 | -* v0.1, 2013-10-23, v0.1 released. 8287 lines. | 271 | +* v0.1, 2013-10-23, [v0.1](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.1) released. 8287 lines. |
| 243 | * v0.1, 2013-10-23, support basic amf0 codec, simplify the api using c-style api. | 272 | * v0.1, 2013-10-23, support basic amf0 codec, simplify the api using c-style api. |
| 244 | * v0.1, 2013-10-23, support shared ptr msg for zero memory copy. | 273 | * v0.1, 2013-10-23, support shared ptr msg for zero memory copy. |
| 245 | * v0.1, 2013-10-22, support vp6 codec with rtmp protocol specified simple handshake. | 274 | * v0.1, 2013-10-22, support vp6 codec with rtmp protocol specified simple handshake. |
| @@ -59,7 +59,9 @@ else | @@ -59,7 +59,9 @@ else | ||
| 59 | echo "build x264" | 59 | echo "build x264" |
| 60 | cd $ff_current_dir && | 60 | cd $ff_current_dir && |
| 61 | rm -rf x264-snapshot-20131129-2245-stable && unzip -q ${ff_src_dir}/x264-snapshot-20131129-2245-stable.zip && | 61 | rm -rf x264-snapshot-20131129-2245-stable && unzip -q ${ff_src_dir}/x264-snapshot-20131129-2245-stable.zip && |
| 62 | - cd x264-snapshot-20131129-2245-stable && ./configure --prefix=${ff_release_dir} --bit-depth=8 --enable-static && make && make install | 62 | + cd x264-snapshot-20131129-2245-stable && |
| 63 | + ./configure --prefix=${ff_release_dir} --disable-opencl --bit-depth=8 --enable-static && | ||
| 64 | + make && make install | ||
| 63 | ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build x264 failed"; exit 1; fi | 65 | ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build x264 failed"; exit 1; fi |
| 64 | fi | 66 | fi |
| 65 | 67 | ||
| @@ -86,7 +88,8 @@ else | @@ -86,7 +88,8 @@ else | ||
| 86 | --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ | 88 | --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ |
| 87 | --enable-libfreetype \ | 89 | --enable-libfreetype \ |
| 88 | --enable-libx264 --enable-libmp3lame --enable-libaacplus \ | 90 | --enable-libx264 --enable-libmp3lame --enable-libaacplus \ |
| 89 | - --enable-pthreads --extra-libs=-lpthread --enable-encoders --enable-decoders --enable-avfilter --enable-muxers --enable-demuxers && | 91 | + --enable-pthreads --extra-libs=-lpthread \ |
| 92 | + --enable-encoders --enable-decoders --enable-avfilter --enable-muxers --enable-demuxers && | ||
| 90 | make && make install | 93 | make && make install |
| 91 | - ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build x264 failed"; exit 1; fi | 94 | + ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build ffmpeg failed"; exit 1; fi |
| 92 | fi | 95 | fi |
| @@ -3,6 +3,168 @@ | @@ -3,6 +3,168 @@ | ||
| 3 | # TODO: check gcc/g++ | 3 | # TODO: check gcc/g++ |
| 4 | echo "check gcc/g++/gdb/make/openssl-devel" | 4 | echo "check gcc/g++/gdb/make/openssl-devel" |
| 5 | echo "depends tools are ok" | 5 | echo "depends tools are ok" |
| 6 | +##################################################################################### | ||
| 7 | +# for Ubuntu | ||
| 8 | +##################################################################################### | ||
| 9 | +function Ubuntu_prepare() | ||
| 10 | +{ | ||
| 11 | + uname -v|grep Ubuntu >/dev/null 2>&1 | ||
| 12 | + ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 13 | + return; | ||
| 14 | + fi | ||
| 15 | + | ||
| 16 | + echo "Ubuntu detected, install tools if needed" | ||
| 17 | + | ||
| 18 | + gcc --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 19 | + echo "install gcc" | ||
| 20 | + require_sudoer "sudo apt-get install -y gcc" | ||
| 21 | + sudo apt-get install -y gcc | ||
| 22 | + echo "install gcc success" | ||
| 23 | + fi | ||
| 24 | + | ||
| 25 | + g++ --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 26 | + echo "install g++" | ||
| 27 | + require_sudoer "sudo apt-get install -y g++" | ||
| 28 | + sudo apt-get install -y g++ | ||
| 29 | + echo "install g++ success" | ||
| 30 | + fi | ||
| 31 | + | ||
| 32 | + make --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 33 | + echo "install make" | ||
| 34 | + require_sudoer "sudo apt-get install -y make" | ||
| 35 | + sudo apt-get install -y make | ||
| 36 | + echo "install make success" | ||
| 37 | + fi | ||
| 38 | + | ||
| 39 | + autoconf --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 40 | + echo "install autoconf" | ||
| 41 | + require_sudoer "sudo apt-get install -y autoconf" | ||
| 42 | + sudo apt-get install -y autoconf | ||
| 43 | + echo "install autoconf success" | ||
| 44 | + fi | ||
| 45 | + | ||
| 46 | + libtool --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 47 | + echo "install libtool" | ||
| 48 | + require_sudoer "sudo apt-get install -y libtool" | ||
| 49 | + sudo apt-get install -y libtool | ||
| 50 | + echo "install libtool success" | ||
| 51 | + fi | ||
| 52 | + | ||
| 53 | + if [[ ! -f /usr/include/pcre.h ]]; then | ||
| 54 | + echo "install libpcre3-dev" | ||
| 55 | + require_sudoer "sudo apt-get install -y libpcre3-dev" | ||
| 56 | + sudo apt-get install -y libpcre3-dev | ||
| 57 | + echo "install libpcre3-dev success" | ||
| 58 | + fi | ||
| 59 | + | ||
| 60 | + if [[ ! -f /usr/include/zlib.h ]]; then | ||
| 61 | + echo "install zlib1g-dev" | ||
| 62 | + require_sudoer "sudo apt-get install -y zlib1g-dev" | ||
| 63 | + sudo apt-get install -y zlib1g-dev | ||
| 64 | + echo "install zlib1g-dev success" | ||
| 65 | + fi | ||
| 66 | + | ||
| 67 | + if [[ ! -d /usr/include/freetype2 ]]; then | ||
| 68 | + echo "install libfreetype6-dev" | ||
| 69 | + require_sudoer "sudo apt-get install -y libfreetype6-dev" | ||
| 70 | + sudo apt-get install -y libfreetype6-dev | ||
| 71 | + echo "install libfreetype6-dev success" | ||
| 72 | + fi | ||
| 73 | + | ||
| 74 | + if [[ ! -d /usr/include/openssl ]]; then | ||
| 75 | + echo "install libssl-dev" | ||
| 76 | + require_sudoer "sudo apt-get install -y libssl-dev" | ||
| 77 | + sudo apt-get install -y libssl-dev | ||
| 78 | + echo "install libssl-dev success" | ||
| 79 | + fi | ||
| 80 | + | ||
| 81 | + echo "Ubuntu install tools success" | ||
| 82 | +} | ||
| 83 | +Ubuntu_prepare | ||
| 84 | +##################################################################################### | ||
| 85 | +# for Centos | ||
| 86 | +##################################################################################### | ||
| 87 | +function Centos_prepare() | ||
| 88 | +{ | ||
| 89 | + if [[ ! -f /etc/redhat-release ]]; then | ||
| 90 | + return; | ||
| 91 | + fi | ||
| 92 | + | ||
| 93 | + echo "Centos detected, install tools if needed" | ||
| 94 | + | ||
| 95 | + gcc --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 96 | + echo "install gcc" | ||
| 97 | + require_sudoer "sudo yum install -y gcc" | ||
| 98 | + sudo yum install -y gcc | ||
| 99 | + echo "install gcc success" | ||
| 100 | + fi | ||
| 101 | + | ||
| 102 | + g++ --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 103 | + echo "install gcc-c++" | ||
| 104 | + require_sudoer "sudo yum install -y gcc-c++" | ||
| 105 | + sudo yum install -y gcc-c++ | ||
| 106 | + echo "install gcc-c++ success" | ||
| 107 | + fi | ||
| 108 | + | ||
| 109 | + make --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 110 | + echo "install make" | ||
| 111 | + require_sudoer "sudo yum install -y make" | ||
| 112 | + sudo yum install -y make | ||
| 113 | + echo "install make success" | ||
| 114 | + fi | ||
| 115 | + | ||
| 116 | + automake --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 117 | + echo "install automake" | ||
| 118 | + require_sudoer "sudo yum install -y automake" | ||
| 119 | + sudo yum install -y automake | ||
| 120 | + echo "install automake success" | ||
| 121 | + fi | ||
| 122 | + | ||
| 123 | + autoconf --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 124 | + echo "install autoconf" | ||
| 125 | + require_sudoer "sudo yum install -y autoconf" | ||
| 126 | + sudo yum install -y autoconf | ||
| 127 | + echo "install autoconf success" | ||
| 128 | + fi | ||
| 129 | + | ||
| 130 | + libtool --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 131 | + echo "install libtool" | ||
| 132 | + require_sudoer "sudo yum install -y libtool" | ||
| 133 | + sudo yum install -y libtool | ||
| 134 | + echo "install libtool success" | ||
| 135 | + fi | ||
| 136 | + | ||
| 137 | + if [[ ! -f /usr/include/pcre.h ]]; then | ||
| 138 | + echo "install pcre-devel" | ||
| 139 | + require_sudoer "sudo yum install -y pcre-devel" | ||
| 140 | + sudo yum install -y pcre-devel | ||
| 141 | + echo "install pcre-devel success" | ||
| 142 | + fi | ||
| 143 | + | ||
| 144 | + if [[ ! -f /usr/include/zlib.h ]]; then | ||
| 145 | + echo "install zlib-devel" | ||
| 146 | + require_sudoer "sudo yum install -y zlib-devel" | ||
| 147 | + sudo yum install -y zlib-devel | ||
| 148 | + echo "install zlib-devel success" | ||
| 149 | + fi | ||
| 150 | + | ||
| 151 | + if [[ ! -d /usr/include/freetype2 ]]; then | ||
| 152 | + echo "install freetype-devel" | ||
| 153 | + require_sudoer "sudo yum install -y freetype-devel" | ||
| 154 | + sudo yum install -y freetype-devel | ||
| 155 | + echo "install freetype-devel success" | ||
| 156 | + fi | ||
| 157 | + | ||
| 158 | + if [[ ! -d /usr/include/openssl ]]; then | ||
| 159 | + echo "install openssl-devel" | ||
| 160 | + require_sudoer "sudo yum install -y openssl-devel" | ||
| 161 | + sudo yum install -y openssl-devel | ||
| 162 | + echo "install openssl-devel success" | ||
| 163 | + fi | ||
| 164 | + | ||
| 165 | + echo "Centos install tools success" | ||
| 166 | +} | ||
| 167 | +Centos_prepare | ||
| 6 | 168 | ||
| 7 | ##################################################################################### | 169 | ##################################################################################### |
| 8 | # st-1.9 | 170 | # st-1.9 |
| @@ -48,6 +210,16 @@ fi | @@ -48,6 +210,16 @@ fi | ||
| 48 | ##################################################################################### | 210 | ##################################################################################### |
| 49 | # nginx for HLS, nginx-1.5.0 | 211 | # nginx for HLS, nginx-1.5.0 |
| 50 | ##################################################################################### | 212 | ##################################################################################### |
| 213 | +function write_nginx_html5() | ||
| 214 | +{ | ||
| 215 | + cat<<END >> ${html_file} | ||
| 216 | +<video width="640" height="360" | ||
| 217 | + autoplay controls autobuffer | ||
| 218 | + src="${hls_stream}" | ||
| 219 | + type="application/vnd.apple.mpegurl"> | ||
| 220 | +</video> | ||
| 221 | +END | ||
| 222 | +} | ||
| 51 | if [ $SRS_HLS = YES ]; then | 223 | if [ $SRS_HLS = YES ]; then |
| 52 | if [[ -f ${SRS_OBJS}/nginx/sbin/nginx ]]; then | 224 | if [[ -f ${SRS_OBJS}/nginx/sbin/nginx ]]; then |
| 53 | echo "nginx-1.5.7 is ok."; | 225 | echo "nginx-1.5.7 is ok."; |
| @@ -72,6 +244,17 @@ if [ $SRS_HLS = YES ]; then | @@ -72,6 +244,17 @@ if [ $SRS_HLS = YES ]; then | ||
| 72 | 244 | ||
| 73 | # create forward dir | 245 | # create forward dir |
| 74 | mkdir -p ${SRS_OBJS}/nginx/html/forward | 246 | mkdir -p ${SRS_OBJS}/nginx/html/forward |
| 247 | + | ||
| 248 | + # generate default html pages for android. | ||
| 249 | + html_file=${SRS_OBJS}/nginx/html/live/livestream.html && hls_stream=livestream.m3u8 && write_nginx_html5 | ||
| 250 | + html_file=${SRS_OBJS}/nginx/html/live/livestream_ld.html && hls_stream=livestream_ld.m3u8 && write_nginx_html5 | ||
| 251 | + html_file=${SRS_OBJS}/nginx/html/live/livestream_sd.html && hls_stream=livestream_sd.m3u8 && write_nginx_html5 | ||
| 252 | + html_file=${SRS_OBJS}/nginx/html/forward/live/livestream.html && hls_stream=livestream.m3u8 && write_nginx_html5 | ||
| 253 | + html_file=${SRS_OBJS}/nginx/html/forward/live/livestream_ld.html && hls_stream=livestream_ld.m3u8 && write_nginx_html5 | ||
| 254 | + html_file=${SRS_OBJS}/nginx/html/forward/live/livestream_sd.html && hls_stream=livestream_sd.m3u8 && write_nginx_html5 | ||
| 255 | + | ||
| 256 | + # copy players to nginx html dir. | ||
| 257 | + cp research/players ${SRS_OBJS}/nginx/html/ -r | ||
| 75 | fi | 258 | fi |
| 76 | 259 | ||
| 77 | if [ $SRS_HLS = YES ]; then | 260 | if [ $SRS_HLS = YES ]; then |
| @@ -87,6 +270,7 @@ if [ $SRS_HTTP = YES ]; then | @@ -87,6 +270,7 @@ if [ $SRS_HTTP = YES ]; then | ||
| 87 | if [[ -f ${SRS_OBJS}/CherryPy-3.2.4/setup.py ]]; then | 270 | if [[ -f ${SRS_OBJS}/CherryPy-3.2.4/setup.py ]]; then |
| 88 | echo "CherryPy-3.2.4 is ok."; | 271 | echo "CherryPy-3.2.4 is ok."; |
| 89 | else | 272 | else |
| 273 | + require_sudoer "configure --with-http" | ||
| 90 | echo "install CherryPy-3.2.4"; | 274 | echo "install CherryPy-3.2.4"; |
| 91 | ( | 275 | ( |
| 92 | sudo rm -rf ${SRS_OBJS}/CherryPy-3.2.4 && cd ${SRS_OBJS} && | 276 | sudo rm -rf ${SRS_OBJS}/CherryPy-3.2.4 && cd ${SRS_OBJS} && |
| 1 | # the listen ports, split by space. | 1 | # the listen ports, split by space. |
| 2 | listen 1935; | 2 | listen 1935; |
| 3 | +<<<<<<< HEAD | ||
| 4 | +======= | ||
| 5 | +# the default chunk size is 128, max is 65536, | ||
| 6 | +# some client does not support chunk size change, | ||
| 7 | +# however, most clients supports it and it can improve | ||
| 8 | +# performance about 10%. | ||
| 9 | +# default: 4096 | ||
| 10 | +chunk_size 65000; | ||
| 11 | +>>>>>>> upstream/master | ||
| 3 | # the logs dir. | 12 | # the logs dir. |
| 4 | # if enabled ffmpeg, each stracoding stream will create a log file. | 13 | # if enabled ffmpeg, each stracoding stream will create a log file. |
| 5 | # default: ./objs/logs | 14 | # default: ./objs/logs |
| @@ -21,14 +30,26 @@ vhost __defaultVhost__ { | @@ -21,14 +30,26 @@ vhost __defaultVhost__ { | ||
| 21 | chunk_size 65000; | 30 | chunk_size 65000; |
| 22 | enabled on; | 31 | enabled on; |
| 23 | gop_cache on; | 32 | gop_cache on; |
| 24 | - hls on; | ||
| 25 | - hls_path ./objs/nginx/html; | ||
| 26 | - hls_fragment 5; | ||
| 27 | - hls_window 30; | 33 | + queue_length 30; |
| 28 | forward 127.0.0.1:19350; | 34 | forward 127.0.0.1:19350; |
| 35 | + hls { | ||
| 36 | + enabled on; | ||
| 37 | + hls_path ./objs/nginx/html; | ||
| 38 | + hls_fragment 5; | ||
| 39 | + hls_window 30; | ||
| 40 | + } | ||
| 41 | + http_hooks { | ||
| 42 | + enabled off; | ||
| 43 | + on_connect http://127.0.0.1:8085/api/v1/clients; | ||
| 44 | + on_close http://127.0.0.1:8085/api/v1/clients; | ||
| 45 | + on_publish http://127.0.0.1:8085/api/v1/streams; | ||
| 46 | + on_unpublish http://127.0.0.1:8085/api/v1/streams; | ||
| 47 | + on_play http://127.0.0.1:8085/api/v1/sessions; | ||
| 48 | + on_stop http://127.0.0.1:8085/api/v1/sessions; | ||
| 49 | + } | ||
| 29 | transcode { | 50 | transcode { |
| 30 | - enabled on; | ||
| 31 | - ffmpeg ./objs/ffmpeg/bin/ffmpeg; | 51 | + enabled on; |
| 52 | + ffmpeg ./objs/ffmpeg/bin/ffmpeg; | ||
| 32 | engine ld { | 53 | engine ld { |
| 33 | enabled on; | 54 | enabled on; |
| 34 | vfilter { | 55 | vfilter { |
| @@ -82,11 +103,17 @@ vhost dev { | @@ -82,11 +103,17 @@ vhost dev { | ||
| 82 | chunk_size 65000; | 103 | chunk_size 65000; |
| 83 | enabled on; | 104 | enabled on; |
| 84 | gop_cache on; | 105 | gop_cache on; |
| 85 | - hls on; | ||
| 86 | - hls_path ./objs/nginx/html; | ||
| 87 | - hls_fragment 5; | ||
| 88 | - hls_window 30; | 106 | + queue_length 10; |
| 89 | forward 127.0.0.1:19350; | 107 | forward 127.0.0.1:19350; |
| 108 | +<<<<<<< HEAD | ||
| 109 | +======= | ||
| 110 | + hls { | ||
| 111 | + enabled on; | ||
| 112 | + hls_path ./objs/nginx/html; | ||
| 113 | + hls_fragment 5; | ||
| 114 | + hls_window 30; | ||
| 115 | + } | ||
| 116 | +>>>>>>> upstream/master | ||
| 90 | http_hooks { | 117 | http_hooks { |
| 91 | enabled off; | 118 | enabled off; |
| 92 | on_connect http://127.0.0.1:8085/api/v1/clients; | 119 | on_connect http://127.0.0.1:8085/api/v1/clients; |
| @@ -97,7 +124,7 @@ vhost dev { | @@ -97,7 +124,7 @@ vhost dev { | ||
| 97 | on_stop http://127.0.0.1:8085/api/v1/sessions; | 124 | on_stop http://127.0.0.1:8085/api/v1/sessions; |
| 98 | } | 125 | } |
| 99 | transcode { | 126 | transcode { |
| 100 | - enabled on; | 127 | + enabled off; |
| 101 | ffmpeg ./objs/ffmpeg/bin/ffmpeg; | 128 | ffmpeg ./objs/ffmpeg/bin/ffmpeg; |
| 102 | engine dev { | 129 | engine dev { |
| 103 | enabled on; | 130 | enabled on; |
| @@ -641,36 +668,40 @@ vhost removed.vhost.com { | @@ -641,36 +668,40 @@ vhost removed.vhost.com { | ||
| 641 | enabled off; | 668 | enabled off; |
| 642 | } | 669 | } |
| 643 | # the vhost with hls specified. | 670 | # the vhost with hls specified. |
| 644 | -vhost no-hls.vhost.com { | ||
| 645 | - # whether the hls is enabled. | ||
| 646 | - # if off, donot write hls(ts and m3u8) when publish. | ||
| 647 | - # default: on | ||
| 648 | - hls on; | ||
| 649 | - # the hls output path. | ||
| 650 | - # the app dir is auto created under the hls_path. | ||
| 651 | - # for example, for rtmp stream: | ||
| 652 | - # rtmp://127.0.0.1/live/livestream | ||
| 653 | - # http://127.0.0.1/live/livestream.m3u8 | ||
| 654 | - # where hls_path is /hls, srs will create the following files: | ||
| 655 | - # /hls/live the app dir for all streams. | ||
| 656 | - # /hls/live/livestream.m3u8 the HLS m3u8 file. | ||
| 657 | - # /hls/live/livestream-1.ts the HLS media/ts file. | ||
| 658 | - # in a word, the hls_path is for vhost. | ||
| 659 | - # default: ./objs/nginx/html | ||
| 660 | - hls_path /data/nginx/html; | ||
| 661 | - # the hls fragment in seconds, the duration of a piece of ts. | ||
| 662 | - # default: 10 | ||
| 663 | - hls_fragment 10; | ||
| 664 | - # the hls window in seconds, the number of ts in m3u8. | ||
| 665 | - # default: 60 | ||
| 666 | - hls_window 60; | 671 | +vhost with-hls.vhost.com { |
| 672 | + hls { | ||
| 673 | + # whether the hls is enabled. | ||
| 674 | + # if off, donot write hls(ts and m3u8) when publish. | ||
| 675 | + # default: off | ||
| 676 | + enabled on; | ||
| 677 | + # the hls output path. | ||
| 678 | + # the app dir is auto created under the hls_path. | ||
| 679 | + # for example, for rtmp stream: | ||
| 680 | + # rtmp://127.0.0.1/live/livestream | ||
| 681 | + # http://127.0.0.1/live/livestream.m3u8 | ||
| 682 | + # where hls_path is /hls, srs will create the following files: | ||
| 683 | + # /hls/live the app dir for all streams. | ||
| 684 | + # /hls/live/livestream.m3u8 the HLS m3u8 file. | ||
| 685 | + # /hls/live/livestream-1.ts the HLS media/ts file. | ||
| 686 | + # in a word, the hls_path is for vhost. | ||
| 687 | + # default: ./objs/nginx/html | ||
| 688 | + hls_path /data/nginx/html; | ||
| 689 | + # the hls fragment in seconds, the duration of a piece of ts. | ||
| 690 | + # default: 10 | ||
| 691 | + hls_fragment 10; | ||
| 692 | + # the hls window in seconds, the number of ts in m3u8. | ||
| 693 | + # default: 60 | ||
| 694 | + hls_window 60; | ||
| 695 | + } | ||
| 667 | } | 696 | } |
| 668 | # the vhost with hls disabled. | 697 | # the vhost with hls disabled. |
| 669 | vhost no-hls.vhost.com { | 698 | vhost no-hls.vhost.com { |
| 670 | - # whether the hls is enabled. | ||
| 671 | - # if off, donot write hls(ts and m3u8) when publish. | ||
| 672 | - # default: on | ||
| 673 | - hls off; | 699 | + hls { |
| 700 | + # whether the hls is enabled. | ||
| 701 | + # if off, donot write hls(ts and m3u8) when publish. | ||
| 702 | + # default: off | ||
| 703 | + enabled off; | ||
| 704 | + } | ||
| 674 | } | 705 | } |
| 675 | # the vhost for min delay, donot cache any stream. | 706 | # the vhost for min delay, donot cache any stream. |
| 676 | vhost min.delay.com { | 707 | vhost min.delay.com { |
| @@ -683,6 +714,11 @@ vhost min.delay.com { | @@ -683,6 +714,11 @@ vhost min.delay.com { | ||
| 683 | # set to on if requires client fast startup. | 714 | # set to on if requires client fast startup. |
| 684 | # default: on | 715 | # default: on |
| 685 | gop_cache off; | 716 | gop_cache off; |
| 717 | + # the max live queue length in seconds. | ||
| 718 | + # if the messages in the queue exceed the max length, | ||
| 719 | + # drop the old whole gop. | ||
| 720 | + # default: 30 | ||
| 721 | + queue_length 10; | ||
| 686 | } | 722 | } |
| 687 | # the vhost for antisuck. | 723 | # the vhost for antisuck. |
| 688 | vhost refer.anti_suck.com { | 724 | vhost refer.anti_suck.com { |
| @@ -15,14 +15,15 @@ BLACK="\\e[0m" | @@ -15,14 +15,15 @@ BLACK="\\e[0m" | ||
| 15 | # parse user options. | 15 | # parse user options. |
| 16 | . auto/options.sh | 16 | . auto/options.sh |
| 17 | 17 | ||
| 18 | -# if specifies http, requires sudo to install the CherryPy. | ||
| 19 | -if [ $SRS_HTTP = YES ]; then | 18 | +function require_sudoer() |
| 19 | +{ | ||
| 20 | sudo echo "" >/dev/null 2>&1 | 20 | sudo echo "" >/dev/null 2>&1 |
| 21 | - ret=$?; if [[ 0 -ne $ret ]]; then echo | ||
| 22 | - "--with-http requires sudoer, ret=$ret"; | 21 | + |
| 22 | + ret=$?; if [[ 0 -ne $ret ]]; then | ||
| 23 | + echo "\"$1\" require sudoer failed. ret=$ret"; | ||
| 23 | exit $ret; | 24 | exit $ret; |
| 24 | fi | 25 | fi |
| 25 | -fi | 26 | +} |
| 26 | 27 | ||
| 27 | # clean the exists | 28 | # clean the exists |
| 28 | if [[ -f Makefile ]]; then | 29 | if [[ -f Makefile ]]; then |
| @@ -56,11 +57,11 @@ help: | @@ -56,11 +57,11 @@ help: | ||
| 56 | @echo " server build the srs(simple rtmp server) over st(state-threads)" | 57 | @echo " server build the srs(simple rtmp server) over st(state-threads)" |
| 57 | 58 | ||
| 58 | clean: | 59 | clean: |
| 59 | - (rm -f Makefile; cd ${SRS_OBJS}; rm -rf Makefile *.hpp src st_*_load) | 60 | + (rm -f Makefile; cd ${SRS_OBJS}; rm -rf srs Makefile *.hpp src st_*_load) |
| 60 | 61 | ||
| 61 | server: _prepare_dir | 62 | server: _prepare_dir |
| 62 | @echo "build the srs(simple rtmp server) over st(state-threads)" | 63 | @echo "build the srs(simple rtmp server) over st(state-threads)" |
| 63 | - \$(MAKE) -f ${SRS_OBJS}/${SRS_MAKEFILE} simple_rtmp_server | 64 | + \$(MAKE) -f ${SRS_OBJS}/${SRS_MAKEFILE} srs |
| 64 | 65 | ||
| 65 | # the ./configure will generate it. | 66 | # the ./configure will generate it. |
| 66 | _prepare_dir: | 67 | _prepare_dir: |
| @@ -86,7 +87,7 @@ GCC = g++ | @@ -86,7 +87,7 @@ GCC = g++ | ||
| 86 | LINK = \$(GCC) | 87 | LINK = \$(GCC) |
| 87 | AR = ar | 88 | AR = ar |
| 88 | 89 | ||
| 89 | -.PHONY: default simple_rtmp_server | 90 | +.PHONY: default srs |
| 90 | 91 | ||
| 91 | default: | 92 | default: |
| 92 | 93 | ||
| @@ -115,7 +116,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | @@ -115,7 +116,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | ||
| 115 | "srs_core_handshake" "srs_core_pithy_print" | 116 | "srs_core_handshake" "srs_core_pithy_print" |
| 116 | "srs_core_config" "srs_core_refer" "srs_core_reload" | 117 | "srs_core_config" "srs_core_refer" "srs_core_reload" |
| 117 | "srs_core_hls" "srs_core_forward" "srs_core_encoder" | 118 | "srs_core_hls" "srs_core_forward" "srs_core_encoder" |
| 118 | - "srs_core_http") | 119 | + "srs_core_http" "srs_core_thread") |
| 119 | MODULE_DIR="src/core" . auto/modules.sh | 120 | MODULE_DIR="src/core" . auto/modules.sh |
| 120 | CORE_OBJS="${MODULE_OBJS[@]}" | 121 | CORE_OBJS="${MODULE_OBJS[@]}" |
| 121 | 122 | ||
| @@ -141,7 +142,7 @@ if [ $SRS_SSL = YES ]; then | @@ -141,7 +142,7 @@ if [ $SRS_SSL = YES ]; then | ||
| 141 | else | 142 | else |
| 142 | LINK_OPTIONS="-ldl" | 143 | LINK_OPTIONS="-ldl" |
| 143 | fi | 144 | fi |
| 144 | -BUILD_KEY="simple_rtmp_server" APP_MAIN="srs_main_server" APP_NAME="simple_rtmp_server" SO_PATH="" . auto/apps.sh | 145 | +BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" SO_PATH="" . auto/apps.sh |
| 145 | 146 | ||
| 146 | echo 'configure ok! ' | 147 | echo 'configure ok! ' |
| 147 | 148 | ||
| @@ -179,6 +180,7 @@ echo "\" make \" to build the srs(simple rtmp server)." | @@ -179,6 +180,7 @@ echo "\" make \" to build the srs(simple rtmp server)." | ||
| 179 | echo "\" make help \" to get the usage of make" | 180 | echo "\" make help \" to get the usage of make" |
| 180 | if [ $SRS_HLS = YES ]; then | 181 | if [ $SRS_HLS = YES ]; then |
| 181 | echo "\" sudo ./objs/nginx/sbin/nginx \" to start the nginx http server for hls" | 182 | echo "\" sudo ./objs/nginx/sbin/nginx \" to start the nginx http server for hls" |
| 183 | + echo "\" http://demo:80/players \" rtmp players(OSMF/JWPlayer)" | ||
| 182 | fi | 184 | fi |
| 183 | if [ $SRS_FFMPEG = YES ]; then | 185 | if [ $SRS_FFMPEG = YES ]; then |
| 184 | echo -e "\" ./objs/ffmpeg/bin/ffmpeg \" is used for live stream transcoding" | 186 | echo -e "\" ./objs/ffmpeg/bin/ffmpeg \" is used for live stream transcoding" |
| @@ -186,4 +188,4 @@ fi | @@ -186,4 +188,4 @@ fi | ||
| 186 | if [ $SRS_HTTP = YES ]; then | 188 | if [ $SRS_HTTP = YES ]; then |
| 187 | echo -e "\" python ./research/api-server/server.py 8085 \" to start the api-server" | 189 | echo -e "\" python ./research/api-server/server.py 8085 \" to start the api-server" |
| 188 | fi | 190 | fi |
| 189 | -echo "\" ./objs/simple_rtmp_server -c conf/srs.conf \" to start the srs live server" | 191 | +echo "\" ./objs/srs -c conf/srs.conf \" to start the srs live server" |
trunk/research/players/index.html
100644 → 100755
| @@ -9,4 +9,5 @@ | @@ -9,4 +9,5 @@ | ||
| 9 | <p><a href="osmf/index.html">OSMF播放器</a></p> | 9 | <p><a href="osmf/index.html">OSMF播放器</a></p> |
| 10 | <p><a href="jwplayer5/index.html">JWPlayer5</a></p> | 10 | <p><a href="jwplayer5/index.html">JWPlayer5</a></p> |
| 11 | <p><a href="jwplayer6/index.html">JWPlayer6</a></p> | 11 | <p><a href="jwplayer6/index.html">JWPlayer6</a></p> |
| 12 | + <p><a href="http://www.videolan.org/vlc/">VLC for HLS/rtmp/rtsp/http....</a></p> | ||
| 12 | </body> | 13 | </body> |
trunk/research/players/jwplayer5/index.html
100644 → 100755
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | <div class="main"> | 17 | <div class="main"> |
| 18 | <div id="player"></div> | 18 | <div id="player"></div> |
| 19 | <div class="control" id="control"> | 19 | <div class="control" id="control"> |
| 20 | - Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://dev:1935/live/livestream"></input> | 20 | + Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://demo:1935/live/livestream"></input> |
| 21 | <input type="button" class="play" value="Play" onclick="play()"></input> | 21 | <input type="button" class="play" value="Play" onclick="play()"></input> |
| 22 | </div> | 22 | </div> |
| 23 | </div> | 23 | </div> |
trunk/research/players/jwplayer6/index.html
100644 → 100755
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | <div class="main"> | 17 | <div class="main"> |
| 18 | <div id="player"></div> | 18 | <div id="player"></div> |
| 19 | <div class="control" id="control"> | 19 | <div class="control" id="control"> |
| 20 | - Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://dev:1935/live/livestream"></input> | 20 | + Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://demo:1935/live/livestream"></input> |
| 21 | <input type="button" class="play" value="Play" onclick="play()"></input> | 21 | <input type="button" class="play" value="Play" onclick="play()"></input> |
| 22 | </div> | 22 | </div> |
| 23 | </div> | 23 | </div> |
trunk/research/players/osmf/index.html
100644 → 100755
| @@ -19,7 +19,7 @@ div.control{padding-bottom:10px; background-color:#333333; } | @@ -19,7 +19,7 @@ div.control{padding-bottom:10px; background-color:#333333; } | ||
| 19 | <div class="main" id="main"> | 19 | <div class="main" id="main"> |
| 20 | <div id="player" class="player"></div> | 20 | <div id="player" class="player"></div> |
| 21 | <div class="control" id="control"> | 21 | <div class="control" id="control"> |
| 22 | - Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://dev:1935/live/livestream"></input> | 22 | + Url(RTMP/HTTP): <input id="url" type="text" class="url" value="rtmp://demo:1935/live/livestream"></input> |
| 23 | <select class="type" id="type"> | 23 | <select class="type" id="type"> |
| 24 | <option value="live" selected>live</option> | 24 | <option value="live" selected>live</option> |
| 25 | <option value="recorded">vod</option> | 25 | <option value="recorded">vod</option> |
trunk/research/players/rtmp/RtmpPlayer.swf
100644 → 100755
不能预览此文件类型
trunk/research/players/rtmp/index.html
100644 → 100755
| @@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
| 21 | <script type="text/javascript"> | 21 | <script type="text/javascript"> |
| 22 | var o = new RtmpPlayer("player", "RtmpPlayer.swf", 1350, 1050); | 22 | var o = new RtmpPlayer("player", "RtmpPlayer.swf", 1350, 1050); |
| 23 | 23 | ||
| 24 | - o.setRtmpUrl("rtmp://dev:1935/live/livestream"); | 24 | + o.setRtmpUrl("rtmp://demo:1935/live/livestream"); |
| 25 | o.admin = "admin"; | 25 | o.admin = "admin"; |
| 26 | o.password = "123456"; | 26 | o.password = "123456"; |
| 27 | o.loop = false; | 27 | o.loop = false; |
| @@ -111,3 +111,17 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | @@ -111,3 +111,17 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | ||
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | } | 113 | } |
| 114 | + | ||
| 115 | +void srs_close_stfd(st_netfd_t& stfd) | ||
| 116 | +{ | ||
| 117 | + if (stfd) { | ||
| 118 | + int fd = st_netfd_fileno(stfd); | ||
| 119 | + st_netfd_close(stfd); | ||
| 120 | + stfd = NULL; | ||
| 121 | + | ||
| 122 | + // st does not close it sometimes, | ||
| 123 | + // close it manually. | ||
| 124 | + close(fd); | ||
| 125 | + } | ||
| 126 | +} | ||
| 127 | + |
| @@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 46 | #include <stddef.h> | 46 | #include <stddef.h> |
| 47 | #include <sys/types.h> | 47 | #include <sys/types.h> |
| 48 | 48 | ||
| 49 | +#include <st.h> | ||
| 50 | + | ||
| 49 | // generated by configure. | 51 | // generated by configure. |
| 50 | #include <srs_auto_headers.hpp> | 52 | #include <srs_auto_headers.hpp> |
| 51 | 53 | ||
| @@ -102,4 +104,7 @@ extern std::string srs_dns_resolve(std::string host); | @@ -102,4 +104,7 @@ extern std::string srs_dns_resolve(std::string host); | ||
| 102 | // app...vhost...request_vhost | 104 | // app...vhost...request_vhost |
| 103 | extern void srs_vhost_resolve(std::string& vhost, std::string& app); | 105 | extern void srs_vhost_resolve(std::string& vhost, std::string& app); |
| 104 | 106 | ||
| 107 | +// close the netfd, and close the underlayer fd. | ||
| 108 | +extern void srs_close_stfd(st_netfd_t& stfd); | ||
| 109 | + | ||
| 105 | #endif | 110 | #endif |
| @@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | #include <arpa/inet.h> | 26 | #include <arpa/inet.h> |
| 27 | #include <stdlib.h> | 27 | #include <stdlib.h> |
| 28 | 28 | ||
| 29 | +using namespace std; | ||
| 30 | + | ||
| 29 | #include <srs_core_error.hpp> | 31 | #include <srs_core_error.hpp> |
| 30 | #include <srs_core_log.hpp> | 32 | #include <srs_core_log.hpp> |
| 31 | #include <srs_core_rtmp.hpp> | 33 | #include <srs_core_rtmp.hpp> |
| @@ -55,10 +57,14 @@ SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) | @@ -55,10 +57,14 @@ SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) | ||
| 55 | #ifdef SRS_HTTP | 57 | #ifdef SRS_HTTP |
| 56 | http_hooks = new SrsHttpHooks(); | 58 | http_hooks = new SrsHttpHooks(); |
| 57 | #endif | 59 | #endif |
| 60 | + | ||
| 61 | + config->subscribe(this); | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | SrsClient::~SrsClient() | 64 | SrsClient::~SrsClient() |
| 61 | { | 65 | { |
| 66 | + config->unsubscribe(this); | ||
| 67 | + | ||
| 62 | srs_freepa(ip); | 68 | srs_freepa(ip); |
| 63 | srs_freep(req); | 69 | srs_freep(req); |
| 64 | srs_freep(res); | 70 | srs_freep(res); |
| @@ -113,6 +119,23 @@ int SrsClient::do_cycle() | @@ -113,6 +119,23 @@ int SrsClient::do_cycle() | ||
| 113 | 119 | ||
| 114 | return ret; | 120 | return ret; |
| 115 | } | 121 | } |
| 122 | + | ||
| 123 | +int SrsClient::on_reload_vhost_removed(string vhost) | ||
| 124 | +{ | ||
| 125 | + int ret = ERROR_SUCCESS; | ||
| 126 | + | ||
| 127 | + if (req->vhost != vhost) { | ||
| 128 | + return ret; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + // if the vhost connected is removed, disconnect the client. | ||
| 132 | + srs_trace("vhost %s removed/disabled, close client url=%s", | ||
| 133 | + vhost.c_str(), req->get_stream_url().c_str()); | ||
| 134 | + | ||
| 135 | + srs_close_stfd(stfd); | ||
| 136 | + | ||
| 137 | + return ret; | ||
| 138 | +} | ||
| 116 | 139 | ||
| 117 | int SrsClient::service_cycle() | 140 | int SrsClient::service_cycle() |
| 118 | { | 141 | { |
| @@ -180,11 +203,7 @@ int SrsClient::service_cycle() | @@ -180,11 +203,7 @@ int SrsClient::service_cycle() | ||
| 180 | req->strip(); | 203 | req->strip(); |
| 181 | srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str()); | 204 | srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str()); |
| 182 | 205 | ||
| 183 | - int chunk_size = 4096; | ||
| 184 | - SrsConfDirective* conf = config->get_chunk_size(req->vhost); | ||
| 185 | - if (conf && !conf->arg0().empty()) { | ||
| 186 | - chunk_size = ::atoi(conf->arg0().c_str()); | ||
| 187 | - } | 206 | + int chunk_size = config->get_chunk_size(); |
| 188 | if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { | 207 | if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { |
| 189 | srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); | 208 | srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); |
| 190 | return ret; | 209 | return ret; |
| @@ -192,7 +211,7 @@ int SrsClient::service_cycle() | @@ -192,7 +211,7 @@ int SrsClient::service_cycle() | ||
| 192 | srs_trace("set chunk_size=%d success", chunk_size); | 211 | srs_trace("set chunk_size=%d success", chunk_size); |
| 193 | 212 | ||
| 194 | // find a source to publish. | 213 | // find a source to publish. |
| 195 | - SrsSource* source = SrsSource::find(req->get_stream_url()); | 214 | + SrsSource* source = SrsSource::find(req); |
| 196 | srs_assert(source != NULL); | 215 | srs_assert(source != NULL); |
| 197 | 216 | ||
| 198 | // check publish available. | 217 | // check publish available. |
| @@ -205,14 +224,9 @@ int SrsClient::service_cycle() | @@ -205,14 +224,9 @@ int SrsClient::service_cycle() | ||
| 205 | return ret; | 224 | return ret; |
| 206 | } | 225 | } |
| 207 | 226 | ||
| 208 | - bool enabled_cache = true; | ||
| 209 | - conf = config->get_gop_cache(req->vhost); | ||
| 210 | - if (conf && conf->arg0() == "off") { | ||
| 211 | - enabled_cache = false; | ||
| 212 | - } | ||
| 213 | - source->set_cache(enabled_cache); | ||
| 214 | - | 227 | + bool enabled_cache = config->get_gop_cache(req->vhost); |
| 215 | srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache); | 228 | srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache); |
| 229 | + source->set_cache(enabled_cache); | ||
| 216 | 230 | ||
| 217 | switch (type) { | 231 | switch (type) { |
| 218 | case SrsClientPlay: { | 232 | case SrsClientPlay: { |
| @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | #include <srs_core.hpp> | 31 | #include <srs_core.hpp> |
| 32 | 32 | ||
| 33 | #include <srs_core_conn.hpp> | 33 | #include <srs_core_conn.hpp> |
| 34 | +#include <srs_core_reload.hpp> | ||
| 34 | 35 | ||
| 35 | class SrsRtmp; | 36 | class SrsRtmp; |
| 36 | class SrsRequest; | 37 | class SrsRequest; |
| @@ -46,7 +47,7 @@ class SrsHttpHooks; | @@ -46,7 +47,7 @@ class SrsHttpHooks; | ||
| 46 | /** | 47 | /** |
| 47 | * the client provides the main logic control for RTMP clients. | 48 | * the client provides the main logic control for RTMP clients. |
| 48 | */ | 49 | */ |
| 49 | -class SrsClient : public SrsConnection | 50 | +class SrsClient : public SrsConnection, public ISrsReloadHandler |
| 50 | { | 51 | { |
| 51 | private: | 52 | private: |
| 52 | char* ip; | 53 | char* ip; |
| @@ -62,6 +63,9 @@ public: | @@ -62,6 +63,9 @@ public: | ||
| 62 | virtual ~SrsClient(); | 63 | virtual ~SrsClient(); |
| 63 | protected: | 64 | protected: |
| 64 | virtual int do_cycle(); | 65 | virtual int do_cycle(); |
| 66 | +// interface ISrsReloadHandler | ||
| 67 | +public: | ||
| 68 | + virtual int on_reload_vhost_removed(std::string vhost); | ||
| 65 | private: | 69 | private: |
| 66 | // when valid and connected to vhost/app, service the client. | 70 | // when valid and connected to vhost/app, service the client. |
| 67 | virtual int service_cycle(); | 71 | virtual int service_cycle(); |
| @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 35 | 35 | ||
| 36 | #include <vector> | 36 | #include <vector> |
| 37 | #include <algorithm> | 37 | #include <algorithm> |
| 38 | +using namespace std; | ||
| 38 | 39 | ||
| 39 | #include <srs_core_error.hpp> | 40 | #include <srs_core_error.hpp> |
| 40 | #include <srs_core_log.hpp> | 41 | #include <srs_core_log.hpp> |
| @@ -58,37 +59,84 @@ bool is_common_space(char ch) | @@ -58,37 +59,84 @@ bool is_common_space(char ch) | ||
| 58 | return (ch == ' ' || ch == '\t' || ch == CR || ch == LF); | 59 | return (ch == ' ' || ch == '\t' || ch == CR || ch == LF); |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | -#define CONF_BUFFER_SIZE 1024 * 1024 | 62 | +class SrsFileBuffer |
| 63 | +{ | ||
| 64 | +private: | ||
| 65 | + // last available position. | ||
| 66 | + char* last; | ||
| 67 | + // end of buffer. | ||
| 68 | + char* end; | ||
| 69 | + // start of buffer. | ||
| 70 | + char* start; | ||
| 71 | +public: | ||
| 72 | + // current consumed position. | ||
| 73 | + char* pos; | ||
| 74 | + // current parsed line. | ||
| 75 | + int line; | ||
| 76 | + | ||
| 77 | + SrsFileBuffer(); | ||
| 78 | + virtual ~SrsFileBuffer(); | ||
| 79 | + virtual int fullfill(const char* filename); | ||
| 80 | + virtual bool empty(); | ||
| 81 | +}; | ||
| 62 | 82 | ||
| 63 | SrsFileBuffer::SrsFileBuffer() | 83 | SrsFileBuffer::SrsFileBuffer() |
| 64 | { | 84 | { |
| 65 | - fd = -1; | ||
| 66 | line = 0; | 85 | line = 0; |
| 67 | 86 | ||
| 68 | - pos = last = start = new char[CONF_BUFFER_SIZE]; | ||
| 69 | - end = start + CONF_BUFFER_SIZE; | 87 | + pos = last = start = NULL; |
| 88 | + end = start; | ||
| 70 | } | 89 | } |
| 71 | 90 | ||
| 72 | SrsFileBuffer::~SrsFileBuffer() | 91 | SrsFileBuffer::~SrsFileBuffer() |
| 73 | { | 92 | { |
| 74 | - if (fd > 0) { | ||
| 75 | - close(fd); | ||
| 76 | - } | ||
| 77 | srs_freepa(start); | 93 | srs_freepa(start); |
| 78 | } | 94 | } |
| 79 | 95 | ||
| 80 | -int SrsFileBuffer::open(const char* filename) | 96 | +int SrsFileBuffer::fullfill(const char* filename) |
| 81 | { | 97 | { |
| 82 | - assert(fd == -1); | 98 | + int ret = ERROR_SUCCESS; |
| 99 | + | ||
| 100 | + int fd = -1; | ||
| 101 | + int nread = 0; | ||
| 102 | + int filesize = 0; | ||
| 83 | 103 | ||
| 84 | if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { | 104 | if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { |
| 85 | - srs_error("open conf file error. errno=%d(%s)", errno, strerror(errno)); | ||
| 86 | - return ERROR_SYSTEM_CONFIG_INVALID; | 105 | + ret = ERROR_SYSTEM_CONFIG_INVALID; |
| 106 | + srs_error("open conf file error. ret=%d", ret); | ||
| 107 | + goto finish; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + if ((filesize = FILE_SIZE(fd) - FILE_OFFSET(fd)) <= 0) { | ||
| 111 | + ret = ERROR_SYSTEM_CONFIG_EOF; | ||
| 112 | + srs_error("read conf file error. ret=%d", ret); | ||
| 113 | + goto finish; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + srs_freepa(start); | ||
| 117 | + pos = last = start = new char[filesize]; | ||
| 118 | + end = start + filesize; | ||
| 119 | + | ||
| 120 | + if ((nread = read(fd, start, filesize)) != filesize) { | ||
| 121 | + ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 122 | + srs_error("read file read error. expect %d, actual %d bytes, ret=%d", | ||
| 123 | + filesize, nread, ret); | ||
| 124 | + goto finish; | ||
| 87 | } | 125 | } |
| 88 | 126 | ||
| 89 | line = 1; | 127 | line = 1; |
| 90 | 128 | ||
| 91 | - return ERROR_SUCCESS; | 129 | +finish: |
| 130 | + if (fd > 0) { | ||
| 131 | + ::close(fd); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + return ret; | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +bool SrsFileBuffer::empty() | ||
| 138 | +{ | ||
| 139 | + return pos >= end; | ||
| 92 | } | 140 | } |
| 93 | 141 | ||
| 94 | SrsConfDirective::SrsConfDirective() | 142 | SrsConfDirective::SrsConfDirective() |
| @@ -105,7 +153,7 @@ SrsConfDirective::~SrsConfDirective() | @@ -105,7 +153,7 @@ SrsConfDirective::~SrsConfDirective() | ||
| 105 | directives.clear(); | 153 | directives.clear(); |
| 106 | } | 154 | } |
| 107 | 155 | ||
| 108 | -std::string SrsConfDirective::arg0() | 156 | +string SrsConfDirective::arg0() |
| 109 | { | 157 | { |
| 110 | if (args.size() > 0) { | 158 | if (args.size() > 0) { |
| 111 | return args.at(0); | 159 | return args.at(0); |
| @@ -114,7 +162,7 @@ std::string SrsConfDirective::arg0() | @@ -114,7 +162,7 @@ std::string SrsConfDirective::arg0() | ||
| 114 | return ""; | 162 | return ""; |
| 115 | } | 163 | } |
| 116 | 164 | ||
| 117 | -std::string SrsConfDirective::arg1() | 165 | +string SrsConfDirective::arg1() |
| 118 | { | 166 | { |
| 119 | if (args.size() > 1) { | 167 | if (args.size() > 1) { |
| 120 | return args.at(1); | 168 | return args.at(1); |
| @@ -123,7 +171,7 @@ std::string SrsConfDirective::arg1() | @@ -123,7 +171,7 @@ std::string SrsConfDirective::arg1() | ||
| 123 | return ""; | 171 | return ""; |
| 124 | } | 172 | } |
| 125 | 173 | ||
| 126 | -std::string SrsConfDirective::arg2() | 174 | +string SrsConfDirective::arg2() |
| 127 | { | 175 | { |
| 128 | if (args.size() > 2) { | 176 | if (args.size() > 2) { |
| 129 | return args.at(2); | 177 | return args.at(2); |
| @@ -137,7 +185,7 @@ SrsConfDirective* SrsConfDirective::at(int index) | @@ -137,7 +185,7 @@ SrsConfDirective* SrsConfDirective::at(int index) | ||
| 137 | return directives.at(index); | 185 | return directives.at(index); |
| 138 | } | 186 | } |
| 139 | 187 | ||
| 140 | -SrsConfDirective* SrsConfDirective::get(std::string _name) | 188 | +SrsConfDirective* SrsConfDirective::get(string _name) |
| 141 | { | 189 | { |
| 142 | std::vector<SrsConfDirective*>::iterator it; | 190 | std::vector<SrsConfDirective*>::iterator it; |
| 143 | for (it = directives.begin(); it != directives.end(); ++it) { | 191 | for (it = directives.begin(); it != directives.end(); ++it) { |
| @@ -150,13 +198,26 @@ SrsConfDirective* SrsConfDirective::get(std::string _name) | @@ -150,13 +198,26 @@ SrsConfDirective* SrsConfDirective::get(std::string _name) | ||
| 150 | return NULL; | 198 | return NULL; |
| 151 | } | 199 | } |
| 152 | 200 | ||
| 201 | +SrsConfDirective* SrsConfDirective::get(string _name, string _arg0) | ||
| 202 | +{ | ||
| 203 | + std::vector<SrsConfDirective*>::iterator it; | ||
| 204 | + for (it = directives.begin(); it != directives.end(); ++it) { | ||
| 205 | + SrsConfDirective* directive = *it; | ||
| 206 | + if (directive->name == _name && directive->arg0() == _arg0) { | ||
| 207 | + return directive; | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + return NULL; | ||
| 212 | +} | ||
| 213 | + | ||
| 153 | int SrsConfDirective::parse(const char* filename) | 214 | int SrsConfDirective::parse(const char* filename) |
| 154 | { | 215 | { |
| 155 | int ret = ERROR_SUCCESS; | 216 | int ret = ERROR_SUCCESS; |
| 156 | 217 | ||
| 157 | SrsFileBuffer buffer; | 218 | SrsFileBuffer buffer; |
| 158 | 219 | ||
| 159 | - if ((ret = buffer.open(filename)) != ERROR_SUCCESS) { | 220 | + if ((ret = buffer.fullfill(filename)) != ERROR_SUCCESS) { |
| 160 | return ret; | 221 | return ret; |
| 161 | } | 222 | } |
| 162 | 223 | ||
| @@ -169,7 +230,7 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) | @@ -169,7 +230,7 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) | ||
| 169 | int ret = ERROR_SUCCESS; | 230 | int ret = ERROR_SUCCESS; |
| 170 | 231 | ||
| 171 | while (true) { | 232 | while (true) { |
| 172 | - std::vector<std::string> args; | 233 | + std::vector<string> args; |
| 173 | ret = read_token(buffer, args); | 234 | ret = read_token(buffer, args); |
| 174 | 235 | ||
| 175 | /** | 236 | /** |
| @@ -224,7 +285,7 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) | @@ -224,7 +285,7 @@ int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) | ||
| 224 | } | 285 | } |
| 225 | 286 | ||
| 226 | // see: ngx_conf_read_token | 287 | // see: ngx_conf_read_token |
| 227 | -int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>& args) | 288 | +int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<string>& args) |
| 228 | { | 289 | { |
| 229 | int ret = ERROR_SUCCESS; | 290 | int ret = ERROR_SUCCESS; |
| 230 | 291 | ||
| @@ -240,11 +301,15 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | @@ -240,11 +301,15 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | ||
| 240 | bool last_space = true; | 301 | bool last_space = true; |
| 241 | 302 | ||
| 242 | while (true) { | 303 | while (true) { |
| 243 | - if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) { | 304 | + if (buffer->empty()) { |
| 305 | + ret = ERROR_SYSTEM_CONFIG_EOF; | ||
| 306 | + | ||
| 244 | if (!args.empty() || !last_space) { | 307 | if (!args.empty() || !last_space) { |
| 245 | srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line); | 308 | srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line); |
| 246 | return ERROR_SYSTEM_CONFIG_INVALID; | 309 | return ERROR_SYSTEM_CONFIG_INVALID; |
| 247 | } | 310 | } |
| 311 | + srs_error("end of file. ret=%d", ret); | ||
| 312 | + | ||
| 248 | return ret; | 313 | return ret; |
| 249 | } | 314 | } |
| 250 | 315 | ||
| @@ -344,7 +409,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | @@ -344,7 +409,7 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | ||
| 344 | memcpy(word, pstart, len); | 409 | memcpy(word, pstart, len); |
| 345 | word[len - 1] = 0; | 410 | word[len - 1] = 0; |
| 346 | 411 | ||
| 347 | - std::string word_str = word; | 412 | + string word_str = word; |
| 348 | if (!word_str.empty()) { | 413 | if (!word_str.empty()) { |
| 349 | args.push_back(word_str); | 414 | args.push_back(word_str); |
| 350 | } | 415 | } |
| @@ -363,59 +428,6 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | @@ -363,59 +428,6 @@ int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string> | ||
| 363 | return ret; | 428 | return ret; |
| 364 | } | 429 | } |
| 365 | 430 | ||
| 366 | -int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart) | ||
| 367 | -{ | ||
| 368 | - int ret = ERROR_SUCCESS; | ||
| 369 | - | ||
| 370 | - if (buffer->pos < buffer->last) { | ||
| 371 | - return ret; | ||
| 372 | - } | ||
| 373 | - | ||
| 374 | - int size = FILE_SIZE(buffer->fd) - FILE_OFFSET(buffer->fd); | ||
| 375 | - if (size > CONF_BUFFER_SIZE) { | ||
| 376 | - ret = ERROR_SYSTEM_CONFIG_TOO_LARGE; | ||
| 377 | - srs_error("config file too large, max=%d, actual=%d, ret=%d", | ||
| 378 | - CONF_BUFFER_SIZE, size, ret); | ||
| 379 | - return ret; | ||
| 380 | - } | ||
| 381 | - | ||
| 382 | - if (size <= 0) { | ||
| 383 | - return ERROR_SYSTEM_CONFIG_EOF; | ||
| 384 | - } | ||
| 385 | - | ||
| 386 | - int len = buffer->pos - buffer->start; | ||
| 387 | - if (len >= CONF_BUFFER_SIZE) { | ||
| 388 | - buffer->line = startline; | ||
| 389 | - | ||
| 390 | - if (!d_quoted && !s_quoted) { | ||
| 391 | - srs_error("line %d: too long parameter \"%*s...\" started", | ||
| 392 | - buffer->line, 10, buffer->start); | ||
| 393 | - | ||
| 394 | - } else { | ||
| 395 | - srs_error("line %d: too long parameter, " | ||
| 396 | - "probably missing terminating '%c' character", buffer->line, d_quoted? '"':'\''); | ||
| 397 | - } | ||
| 398 | - return ERROR_SYSTEM_CONFIG_INVALID; | ||
| 399 | - } | ||
| 400 | - | ||
| 401 | - if (len) { | ||
| 402 | - memmove(buffer->start, pstart, len); | ||
| 403 | - } | ||
| 404 | - | ||
| 405 | - size = srs_min(size, buffer->end - (buffer->start + len)); | ||
| 406 | - int n = read(buffer->fd, buffer->start + len, size); | ||
| 407 | - if (n != size) { | ||
| 408 | - srs_error("read file read error. expect %d, actual %d bytes.", size, n); | ||
| 409 | - return ERROR_SYSTEM_CONFIG_INVALID; | ||
| 410 | - } | ||
| 411 | - | ||
| 412 | - buffer->pos = buffer->start + len; | ||
| 413 | - buffer->last = buffer->pos + n; | ||
| 414 | - pstart = buffer->start; | ||
| 415 | - | ||
| 416 | - return ret; | ||
| 417 | -} | ||
| 418 | - | ||
| 419 | SrsConfig* config = new SrsConfig(); | 431 | SrsConfig* config = new SrsConfig(); |
| 420 | 432 | ||
| 421 | SrsConfig::SrsConfig() | 433 | SrsConfig::SrsConfig() |
| @@ -453,12 +465,12 @@ int SrsConfig::reload() | @@ -453,12 +465,12 @@ int SrsConfig::reload() | ||
| 453 | conf.root = NULL; | 465 | conf.root = NULL; |
| 454 | 466 | ||
| 455 | // merge config. | 467 | // merge config. |
| 456 | - std::vector<SrsReloadHandler*>::iterator it; | 468 | + std::vector<ISrsReloadHandler*>::iterator it; |
| 457 | 469 | ||
| 458 | // merge config: listen | 470 | // merge config: listen |
| 459 | if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { | 471 | if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { |
| 460 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 472 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
| 461 | - SrsReloadHandler* subscribe = *it; | 473 | + ISrsReloadHandler* subscribe = *it; |
| 462 | if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) { | 474 | if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) { |
| 463 | srs_error("notify subscribes reload listen failed. ret=%d", ret); | 475 | srs_error("notify subscribes reload listen failed. ret=%d", ret); |
| 464 | return ret; | 476 | return ret; |
| @@ -466,10 +478,11 @@ int SrsConfig::reload() | @@ -466,10 +478,11 @@ int SrsConfig::reload() | ||
| 466 | } | 478 | } |
| 467 | srs_trace("reload listen success."); | 479 | srs_trace("reload listen success."); |
| 468 | } | 480 | } |
| 481 | + | ||
| 469 | // merge config: pithy_print | 482 | // merge config: pithy_print |
| 470 | if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) { | 483 | if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) { |
| 471 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 484 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
| 472 | - SrsReloadHandler* subscribe = *it; | 485 | + ISrsReloadHandler* subscribe = *it; |
| 473 | if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) { | 486 | if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) { |
| 474 | srs_error("notify subscribes pithy_print listen failed. ret=%d", ret); | 487 | srs_error("notify subscribes pithy_print listen failed. ret=%d", ret); |
| 475 | return ret; | 488 | return ret; |
| @@ -477,15 +490,121 @@ int SrsConfig::reload() | @@ -477,15 +490,121 @@ int SrsConfig::reload() | ||
| 477 | } | 490 | } |
| 478 | srs_trace("reload pithy_print success."); | 491 | srs_trace("reload pithy_print success."); |
| 479 | } | 492 | } |
| 480 | - | ||
| 481 | - // TODO: suppor reload hls/forward/ffmpeg/http | 493 | + |
| 494 | + // merge config: vhost added, directly supported. | ||
| 495 | + | ||
| 496 | + // merge config: vhost removed/disabled/modified. | ||
| 497 | + for (int i = 0; i < (int)old_root->directives.size(); i++) { | ||
| 498 | + SrsConfDirective* old_vhost = old_root->at(i); | ||
| 499 | + // only process vhost directives. | ||
| 500 | + if (old_vhost->name != "vhost") { | ||
| 501 | + continue; | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | + std::string vhost = old_vhost->arg0(); | ||
| 505 | + | ||
| 506 | + SrsConfDirective* new_vhost = root->get("vhost", vhost); | ||
| 507 | + // ignore if absolutely equal | ||
| 508 | + if (new_vhost && srs_directive_equals(old_vhost, new_vhost)) { | ||
| 509 | + srs_trace("vhost %s absolutely equal, ignore.", vhost.c_str()); | ||
| 510 | + continue; | ||
| 511 | + } | ||
| 512 | + // ignore if enable the new vhost when old vhost is disabled. | ||
| 513 | + if (get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { | ||
| 514 | + srs_trace("vhost %s disabled=>enabled, ignore.", vhost.c_str()); | ||
| 515 | + continue; | ||
| 516 | + } | ||
| 517 | + // ignore if both old and new vhost are disabled. | ||
| 518 | + if (!get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { | ||
| 519 | + srs_trace("vhost %s disabled=>disabled, ignore.", vhost.c_str()); | ||
| 520 | + continue; | ||
| 521 | + } | ||
| 522 | + | ||
| 523 | + // merge config: vhost removed/disabled. | ||
| 524 | + if (!get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { | ||
| 525 | + srs_trace("vhost %s disabled, reload it.", vhost.c_str()); | ||
| 526 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 527 | + ISrsReloadHandler* subscribe = *it; | ||
| 528 | + if ((ret = subscribe->on_reload_vhost_removed(vhost)) != ERROR_SUCCESS) { | ||
| 529 | + srs_error("notify subscribes pithy_print remove " | ||
| 530 | + "vhost %s failed. ret=%d", vhost.c_str(), ret); | ||
| 531 | + return ret; | ||
| 532 | + } | ||
| 533 | + } | ||
| 534 | + srs_trace("reload remove vhost %s success.", vhost.c_str()); | ||
| 535 | + } | ||
| 536 | + | ||
| 537 | + // merge config: vhost modified. | ||
| 538 | + srs_trace("vhost %s modified, reload its detail.", vhost.c_str()); | ||
| 539 | + if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { | ||
| 540 | + // gop_cache | ||
| 541 | + if (!srs_directive_equals(new_vhost->get("gop_cache"), old_vhost->get("gop_cache"))) { | ||
| 542 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 543 | + ISrsReloadHandler* subscribe = *it; | ||
| 544 | + if ((ret = subscribe->on_reload_gop_cache(vhost)) != ERROR_SUCCESS) { | ||
| 545 | + srs_error("vhost %s notify subscribes gop_cache failed. ret=%d", vhost.c_str(), ret); | ||
| 546 | + return ret; | ||
| 547 | + } | ||
| 548 | + } | ||
| 549 | + srs_trace("vhost %s reload gop_cache success.", vhost.c_str()); | ||
| 550 | + } | ||
| 551 | + // queue_length | ||
| 552 | + if (!srs_directive_equals(new_vhost->get("queue_length"), old_vhost->get("queue_length"))) { | ||
| 553 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 554 | + ISrsReloadHandler* subscribe = *it; | ||
| 555 | + if ((ret = subscribe->on_reload_queue_length(vhost)) != ERROR_SUCCESS) { | ||
| 556 | + srs_error("vhost %s notify subscribes queue_length failed. ret=%d", vhost.c_str(), ret); | ||
| 557 | + return ret; | ||
| 558 | + } | ||
| 559 | + } | ||
| 560 | + srs_trace("vhost %s reload queue_length success.", vhost.c_str()); | ||
| 561 | + } | ||
| 562 | + // forward | ||
| 563 | + if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { | ||
| 564 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 565 | + ISrsReloadHandler* subscribe = *it; | ||
| 566 | + if ((ret = subscribe->on_reload_forward(vhost)) != ERROR_SUCCESS) { | ||
| 567 | + srs_error("vhost %s notify subscribes forward failed. ret=%d", vhost.c_str(), ret); | ||
| 568 | + return ret; | ||
| 569 | + } | ||
| 570 | + } | ||
| 571 | + srs_trace("vhost %s reload forward success.", vhost.c_str()); | ||
| 572 | + } | ||
| 573 | + // hls | ||
| 574 | + if (!srs_directive_equals(new_vhost->get("hls"), old_vhost->get("hls"))) { | ||
| 575 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 576 | + ISrsReloadHandler* subscribe = *it; | ||
| 577 | + if ((ret = subscribe->on_reload_hls(vhost)) != ERROR_SUCCESS) { | ||
| 578 | + srs_error("vhost %s notify subscribes hls failed. ret=%d", vhost.c_str(), ret); | ||
| 579 | + return ret; | ||
| 580 | + } | ||
| 581 | + } | ||
| 582 | + srs_trace("vhost %s reload hls success.", vhost.c_str()); | ||
| 583 | + } | ||
| 584 | + // transcode | ||
| 585 | + if (!srs_directive_equals(new_vhost->get("transcode"), old_vhost->get("transcode"))) { | ||
| 586 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 587 | + ISrsReloadHandler* subscribe = *it; | ||
| 588 | + if ((ret = subscribe->on_reload_transcode(vhost)) != ERROR_SUCCESS) { | ||
| 589 | + srs_error("vhost %s notify subscribes transcode failed. ret=%d", vhost.c_str(), ret); | ||
| 590 | + return ret; | ||
| 591 | + } | ||
| 592 | + } | ||
| 593 | + srs_trace("vhost %s reload transcode success.", vhost.c_str()); | ||
| 594 | + } | ||
| 595 | + // TODO: suppor reload hls/forward/ffmpeg/http | ||
| 596 | + continue; | ||
| 597 | + } | ||
| 598 | + srs_warn("invalid reload path, enabled old: %d, new: %d", | ||
| 599 | + get_vhost_enabled(old_vhost), get_vhost_enabled(new_vhost)); | ||
| 600 | + } | ||
| 482 | 601 | ||
| 483 | return ret; | 602 | return ret; |
| 484 | } | 603 | } |
| 485 | 604 | ||
| 486 | -void SrsConfig::subscribe(SrsReloadHandler* handler) | 605 | +void SrsConfig::subscribe(ISrsReloadHandler* handler) |
| 487 | { | 606 | { |
| 488 | - std::vector<SrsReloadHandler*>::iterator it; | 607 | + std::vector<ISrsReloadHandler*>::iterator it; |
| 489 | 608 | ||
| 490 | it = std::find(subscribes.begin(), subscribes.end(), handler); | 609 | it = std::find(subscribes.begin(), subscribes.end(), handler); |
| 491 | if (it != subscribes.end()) { | 610 | if (it != subscribes.end()) { |
| @@ -495,9 +614,9 @@ void SrsConfig::subscribe(SrsReloadHandler* handler) | @@ -495,9 +614,9 @@ void SrsConfig::subscribe(SrsReloadHandler* handler) | ||
| 495 | subscribes.push_back(handler); | 614 | subscribes.push_back(handler); |
| 496 | } | 615 | } |
| 497 | 616 | ||
| 498 | -void SrsConfig::unsubscribe(SrsReloadHandler* handler) | 617 | +void SrsConfig::unsubscribe(ISrsReloadHandler* handler) |
| 499 | { | 618 | { |
| 500 | - std::vector<SrsReloadHandler*>::iterator it; | 619 | + std::vector<ISrsReloadHandler*>::iterator it; |
| 501 | 620 | ||
| 502 | it = std::find(subscribes.begin(), subscribes.end(), handler); | 621 | it = std::find(subscribes.begin(), subscribes.end(), handler); |
| 503 | if (it == subscribes.end()) { | 622 | if (it == subscribes.end()) { |
| @@ -539,7 +658,102 @@ int SrsConfig::parse_options(int argc, char** argv) | @@ -539,7 +658,102 @@ int SrsConfig::parse_options(int argc, char** argv) | ||
| 539 | return parse_file(config_file.c_str()); | 658 | return parse_file(config_file.c_str()); |
| 540 | } | 659 | } |
| 541 | 660 | ||
| 542 | -SrsConfDirective* SrsConfig::get_vhost(const std::string& vhost) | 661 | +int SrsConfig::parse_file(const char* filename) |
| 662 | +{ | ||
| 663 | + int ret = ERROR_SUCCESS; | ||
| 664 | + | ||
| 665 | + config_file = filename; | ||
| 666 | + | ||
| 667 | + if (config_file.empty()) { | ||
| 668 | + return ERROR_SYSTEM_CONFIG_INVALID; | ||
| 669 | + } | ||
| 670 | + | ||
| 671 | + if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) { | ||
| 672 | + return ret; | ||
| 673 | + } | ||
| 674 | + | ||
| 675 | + SrsConfDirective* conf = NULL; | ||
| 676 | + if ((conf = get_listen()) == NULL || conf->args.size() == 0) { | ||
| 677 | + ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 678 | + srs_error("line %d: conf error, " | ||
| 679 | + "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret); | ||
| 680 | + return ret; | ||
| 681 | + } | ||
| 682 | + | ||
| 683 | + // TODO: check the hls. | ||
| 684 | + // TODO: check forward. | ||
| 685 | + // TODO: check ffmpeg. | ||
| 686 | + // TODO: check http. | ||
| 687 | + | ||
| 688 | + return ret; | ||
| 689 | +} | ||
| 690 | + | ||
| 691 | +int SrsConfig::parse_argv(int& i, char** argv) | ||
| 692 | +{ | ||
| 693 | + int ret = ERROR_SUCCESS; | ||
| 694 | + | ||
| 695 | + char* p = argv[i]; | ||
| 696 | + | ||
| 697 | + if (*p++ != '-') { | ||
| 698 | + ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 699 | + srs_error("invalid options(index=%d, value=%s), " | ||
| 700 | + "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret); | ||
| 701 | + return ret; | ||
| 702 | + } | ||
| 703 | + | ||
| 704 | + while (*p) { | ||
| 705 | + switch (*p++) { | ||
| 706 | + case '?': | ||
| 707 | + case 'h': | ||
| 708 | + show_help = true; | ||
| 709 | + break; | ||
| 710 | + case 'v': | ||
| 711 | + case 'V': | ||
| 712 | + show_version = true; | ||
| 713 | + break; | ||
| 714 | + case 'c': | ||
| 715 | + if (*p) { | ||
| 716 | + config_file = p; | ||
| 717 | + return ret; | ||
| 718 | + } | ||
| 719 | + if (argv[++i]) { | ||
| 720 | + config_file = argv[i]; | ||
| 721 | + return ret; | ||
| 722 | + } | ||
| 723 | + ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 724 | + srs_error("option \"-c\" requires parameter, ret=%d", ret); | ||
| 725 | + return ret; | ||
| 726 | + default: | ||
| 727 | + ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 728 | + srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret); | ||
| 729 | + return ret; | ||
| 730 | + } | ||
| 731 | + } | ||
| 732 | + | ||
| 733 | + return ret; | ||
| 734 | +} | ||
| 735 | + | ||
| 736 | +void SrsConfig::print_help(char** argv) | ||
| 737 | +{ | ||
| 738 | + printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION | ||
| 739 | + " Copyright (c) 2013 winlin\n" | ||
| 740 | + "Contributors: "RTMP_SIG_SRS_CONTRIBUTOR"\n" | ||
| 741 | + "Build: "SRS_BUILD_DATE" Configuration: "SRS_CONFIGURE"\n" | ||
| 742 | + "Usage: %s [-h?vV] [-c <filename>]\n" | ||
| 743 | + "\n" | ||
| 744 | + "Options:\n" | ||
| 745 | + " -?-h : show help\n" | ||
| 746 | + " -v-V : show version and exit\n" | ||
| 747 | + " -c filename : set configuration file\n" | ||
| 748 | + "\n" | ||
| 749 | + RTMP_SIG_SRS_WEB"\n" | ||
| 750 | + RTMP_SIG_SRS_URL"\n" | ||
| 751 | + "Email: "RTMP_SIG_SRS_EMAIL"\n" | ||
| 752 | + "\n", | ||
| 753 | + argv[0]); | ||
| 754 | +} | ||
| 755 | + | ||
| 756 | +SrsConfDirective* SrsConfig::get_vhost(string vhost) | ||
| 543 | { | 757 | { |
| 544 | srs_assert(root); | 758 | srs_assert(root); |
| 545 | 759 | ||
| @@ -562,7 +776,7 @@ SrsConfDirective* SrsConfig::get_vhost(const std::string& vhost) | @@ -562,7 +776,7 @@ SrsConfDirective* SrsConfig::get_vhost(const std::string& vhost) | ||
| 562 | return NULL; | 776 | return NULL; |
| 563 | } | 777 | } |
| 564 | 778 | ||
| 565 | -SrsConfDirective* SrsConfig::get_vhost_on_connect(const std::string &vhost) | 779 | +SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost) |
| 566 | { | 780 | { |
| 567 | SrsConfDirective* conf = get_vhost(vhost); | 781 | SrsConfDirective* conf = get_vhost(vhost); |
| 568 | 782 | ||
| @@ -583,7 +797,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(const std::string &vhost) | @@ -583,7 +797,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(const std::string &vhost) | ||
| 583 | return conf->get("on_connect"); | 797 | return conf->get("on_connect"); |
| 584 | } | 798 | } |
| 585 | 799 | ||
| 586 | -SrsConfDirective* SrsConfig::get_vhost_on_close(const std::string &vhost) | 800 | +SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost) |
| 587 | { | 801 | { |
| 588 | SrsConfDirective* conf = get_vhost(vhost); | 802 | SrsConfDirective* conf = get_vhost(vhost); |
| 589 | 803 | ||
| @@ -604,7 +818,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(const std::string &vhost) | @@ -604,7 +818,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(const std::string &vhost) | ||
| 604 | return conf->get("on_close"); | 818 | return conf->get("on_close"); |
| 605 | } | 819 | } |
| 606 | 820 | ||
| 607 | -SrsConfDirective* SrsConfig::get_vhost_on_publish(const std::string &vhost) | 821 | +SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost) |
| 608 | { | 822 | { |
| 609 | SrsConfDirective* conf = get_vhost(vhost); | 823 | SrsConfDirective* conf = get_vhost(vhost); |
| 610 | 824 | ||
| @@ -625,7 +839,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(const std::string &vhost) | @@ -625,7 +839,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(const std::string &vhost) | ||
| 625 | return conf->get("on_publish"); | 839 | return conf->get("on_publish"); |
| 626 | } | 840 | } |
| 627 | 841 | ||
| 628 | -SrsConfDirective* SrsConfig::get_vhost_on_unpublish(const std::string &vhost) | 842 | +SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost) |
| 629 | { | 843 | { |
| 630 | SrsConfDirective* conf = get_vhost(vhost); | 844 | SrsConfDirective* conf = get_vhost(vhost); |
| 631 | 845 | ||
| @@ -646,7 +860,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(const std::string &vhost) | @@ -646,7 +860,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(const std::string &vhost) | ||
| 646 | return conf->get("on_unpublish"); | 860 | return conf->get("on_unpublish"); |
| 647 | } | 861 | } |
| 648 | 862 | ||
| 649 | -SrsConfDirective* SrsConfig::get_vhost_on_play(const std::string &vhost) | 863 | +SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost) |
| 650 | { | 864 | { |
| 651 | SrsConfDirective* conf = get_vhost(vhost); | 865 | SrsConfDirective* conf = get_vhost(vhost); |
| 652 | 866 | ||
| @@ -667,7 +881,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(const std::string &vhost) | @@ -667,7 +881,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(const std::string &vhost) | ||
| 667 | return conf->get("on_play"); | 881 | return conf->get("on_play"); |
| 668 | } | 882 | } |
| 669 | 883 | ||
| 670 | -SrsConfDirective* SrsConfig::get_vhost_on_stop(const std::string &vhost) | 884 | +SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost) |
| 671 | { | 885 | { |
| 672 | SrsConfDirective* conf = get_vhost(vhost); | 886 | SrsConfDirective* conf = get_vhost(vhost); |
| 673 | 887 | ||
| @@ -688,15 +902,20 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(const std::string &vhost) | @@ -688,15 +902,20 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(const std::string &vhost) | ||
| 688 | return conf->get("on_stop"); | 902 | return conf->get("on_stop"); |
| 689 | } | 903 | } |
| 690 | 904 | ||
| 691 | -bool SrsConfig::get_vhost_enabled(const std::string &vhost) | 905 | +bool SrsConfig::get_vhost_enabled(string vhost) |
| 692 | { | 906 | { |
| 693 | SrsConfDirective* vhost_conf = get_vhost(vhost); | 907 | SrsConfDirective* vhost_conf = get_vhost(vhost); |
| 908 | + | ||
| 909 | + return get_vhost_enabled(vhost_conf); | ||
| 910 | +} | ||
| 694 | 911 | ||
| 695 | - if (!vhost_conf) { | ||
| 696 | - return true; | 912 | +bool SrsConfig::get_vhost_enabled(SrsConfDirective* vhost) |
| 913 | +{ | ||
| 914 | + if (!vhost) { | ||
| 915 | + return false; | ||
| 697 | } | 916 | } |
| 698 | 917 | ||
| 699 | - SrsConfDirective* conf = vhost_conf->get("enabled"); | 918 | + SrsConfDirective* conf = vhost->get("enabled"); |
| 700 | if (!conf) { | 919 | if (!conf) { |
| 701 | return true; | 920 | return true; |
| 702 | } | 921 | } |
| @@ -708,7 +927,7 @@ bool SrsConfig::get_vhost_enabled(const std::string &vhost) | @@ -708,7 +927,7 @@ bool SrsConfig::get_vhost_enabled(const std::string &vhost) | ||
| 708 | return true; | 927 | return true; |
| 709 | } | 928 | } |
| 710 | 929 | ||
| 711 | -SrsConfDirective* SrsConfig::get_transcode(const std::string &vhost, const std::string &scope) | 930 | +SrsConfDirective* SrsConfig::get_transcode(string vhost, string scope) |
| 712 | { | 931 | { |
| 713 | SrsConfDirective* conf = get_vhost(vhost); | 932 | SrsConfDirective* conf = get_vhost(vhost); |
| 714 | 933 | ||
| @@ -742,7 +961,7 @@ bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode) | @@ -742,7 +961,7 @@ bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode) | ||
| 742 | return true; | 961 | return true; |
| 743 | } | 962 | } |
| 744 | 963 | ||
| 745 | -std::string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode) | 964 | +string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode) |
| 746 | { | 965 | { |
| 747 | if (!transcode) { | 966 | if (!transcode) { |
| 748 | return ""; | 967 | return ""; |
| @@ -787,7 +1006,7 @@ bool SrsConfig::get_engine_enabled(SrsConfDirective* engine) | @@ -787,7 +1006,7 @@ bool SrsConfig::get_engine_enabled(SrsConfDirective* engine) | ||
| 787 | return true; | 1006 | return true; |
| 788 | } | 1007 | } |
| 789 | 1008 | ||
| 790 | -std::string SrsConfig::get_engine_vcodec(SrsConfDirective* engine) | 1009 | +string SrsConfig::get_engine_vcodec(SrsConfDirective* engine) |
| 791 | { | 1010 | { |
| 792 | if (!engine) { | 1011 | if (!engine) { |
| 793 | return ""; | 1012 | return ""; |
| @@ -871,7 +1090,7 @@ int SrsConfig::get_engine_vthreads(SrsConfDirective* engine) | @@ -871,7 +1090,7 @@ int SrsConfig::get_engine_vthreads(SrsConfDirective* engine) | ||
| 871 | return ::atoi(conf->arg0().c_str()); | 1090 | return ::atoi(conf->arg0().c_str()); |
| 872 | } | 1091 | } |
| 873 | 1092 | ||
| 874 | -std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine) | 1093 | +string SrsConfig::get_engine_vprofile(SrsConfDirective* engine) |
| 875 | { | 1094 | { |
| 876 | if (!engine) { | 1095 | if (!engine) { |
| 877 | return ""; | 1096 | return ""; |
| @@ -885,7 +1104,7 @@ std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine) | @@ -885,7 +1104,7 @@ std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine) | ||
| 885 | return conf->arg0(); | 1104 | return conf->arg0(); |
| 886 | } | 1105 | } |
| 887 | 1106 | ||
| 888 | -std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine) | 1107 | +string SrsConfig::get_engine_vpreset(SrsConfDirective* engine) |
| 889 | { | 1108 | { |
| 890 | if (!engine) { | 1109 | if (!engine) { |
| 891 | return ""; | 1110 | return ""; |
| @@ -899,7 +1118,7 @@ std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine) | @@ -899,7 +1118,7 @@ std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine) | ||
| 899 | return conf->arg0(); | 1118 | return conf->arg0(); |
| 900 | } | 1119 | } |
| 901 | 1120 | ||
| 902 | -void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams) | 1121 | +void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<string>& vparams) |
| 903 | { | 1122 | { |
| 904 | if (!engine) { | 1123 | if (!engine) { |
| 905 | return; | 1124 | return; |
| @@ -921,7 +1140,7 @@ void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<std::st | @@ -921,7 +1140,7 @@ void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<std::st | ||
| 921 | } | 1140 | } |
| 922 | } | 1141 | } |
| 923 | 1142 | ||
| 924 | -void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter) | 1143 | +void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<string>& vfilter) |
| 925 | { | 1144 | { |
| 926 | if (!engine) { | 1145 | if (!engine) { |
| 927 | return; | 1146 | return; |
| @@ -943,7 +1162,7 @@ void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<std::st | @@ -943,7 +1162,7 @@ void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<std::st | ||
| 943 | } | 1162 | } |
| 944 | } | 1163 | } |
| 945 | 1164 | ||
| 946 | -std::string SrsConfig::get_engine_acodec(SrsConfDirective* engine) | 1165 | +string SrsConfig::get_engine_acodec(SrsConfDirective* engine) |
| 947 | { | 1166 | { |
| 948 | if (!engine) { | 1167 | if (!engine) { |
| 949 | return ""; | 1168 | return ""; |
| @@ -999,7 +1218,7 @@ int SrsConfig::get_engine_achannels(SrsConfDirective* engine) | @@ -999,7 +1218,7 @@ int SrsConfig::get_engine_achannels(SrsConfDirective* engine) | ||
| 999 | return ::atoi(conf->arg0().c_str()); | 1218 | return ::atoi(conf->arg0().c_str()); |
| 1000 | } | 1219 | } |
| 1001 | 1220 | ||
| 1002 | -void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams) | 1221 | +void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<string>& aparams) |
| 1003 | { | 1222 | { |
| 1004 | if (!engine) { | 1223 | if (!engine) { |
| 1005 | return; | 1224 | return; |
| @@ -1021,7 +1240,7 @@ void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<std::st | @@ -1021,7 +1240,7 @@ void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<std::st | ||
| 1021 | } | 1240 | } |
| 1022 | } | 1241 | } |
| 1023 | 1242 | ||
| 1024 | -std::string SrsConfig::get_engine_output(SrsConfDirective* engine) | 1243 | +string SrsConfig::get_engine_output(SrsConfDirective* engine) |
| 1025 | { | 1244 | { |
| 1026 | if (!engine) { | 1245 | if (!engine) { |
| 1027 | return ""; | 1246 | return ""; |
| @@ -1035,7 +1254,7 @@ std::string SrsConfig::get_engine_output(SrsConfDirective* engine) | @@ -1035,7 +1254,7 @@ std::string SrsConfig::get_engine_output(SrsConfDirective* engine) | ||
| 1035 | return conf->arg0(); | 1254 | return conf->arg0(); |
| 1036 | } | 1255 | } |
| 1037 | 1256 | ||
| 1038 | -std::string SrsConfig::get_log_dir() | 1257 | +string SrsConfig::get_log_dir() |
| 1039 | { | 1258 | { |
| 1040 | srs_assert(root); | 1259 | srs_assert(root); |
| 1041 | 1260 | ||
| @@ -1059,18 +1278,39 @@ int SrsConfig::get_max_connections() | @@ -1059,18 +1278,39 @@ int SrsConfig::get_max_connections() | ||
| 1059 | return ::atoi(conf->arg0().c_str()); | 1278 | return ::atoi(conf->arg0().c_str()); |
| 1060 | } | 1279 | } |
| 1061 | 1280 | ||
| 1062 | -SrsConfDirective* SrsConfig::get_gop_cache(const std::string &vhost) | 1281 | +bool SrsConfig::get_gop_cache(string vhost) |
| 1063 | { | 1282 | { |
| 1064 | SrsConfDirective* conf = get_vhost(vhost); | 1283 | SrsConfDirective* conf = get_vhost(vhost); |
| 1065 | 1284 | ||
| 1066 | if (!conf) { | 1285 | if (!conf) { |
| 1067 | - return NULL; | 1286 | + return true; |
| 1287 | + } | ||
| 1288 | + | ||
| 1289 | + conf = conf->get("gop_cache"); | ||
| 1290 | + if (conf && conf->arg0() == "off") { | ||
| 1291 | + return false; | ||
| 1068 | } | 1292 | } |
| 1069 | 1293 | ||
| 1070 | - return conf->get("gop_cache"); | 1294 | + return true; |
| 1071 | } | 1295 | } |
| 1072 | 1296 | ||
| 1073 | -SrsConfDirective* SrsConfig::get_forward(const std::string &vhost) | 1297 | +double SrsConfig::get_queue_length(string vhost) |
| 1298 | +{ | ||
| 1299 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 1300 | + | ||
| 1301 | + if (!conf) { | ||
| 1302 | + return SRS_CONF_DEFAULT_QUEUE_LENGTH; | ||
| 1303 | + } | ||
| 1304 | + | ||
| 1305 | + conf = conf->get("queue_length"); | ||
| 1306 | + if (!conf || conf->arg0().empty()) { | ||
| 1307 | + return SRS_CONF_DEFAULT_QUEUE_LENGTH; | ||
| 1308 | + } | ||
| 1309 | + | ||
| 1310 | + return ::atoi(conf->arg0().c_str()); | ||
| 1311 | +} | ||
| 1312 | + | ||
| 1313 | +SrsConfDirective* SrsConfig::get_forward(string vhost) | ||
| 1074 | { | 1314 | { |
| 1075 | SrsConfDirective* conf = get_vhost(vhost); | 1315 | SrsConfDirective* conf = get_vhost(vhost); |
| 1076 | 1316 | ||
| @@ -1081,7 +1321,7 @@ SrsConfDirective* SrsConfig::get_forward(const std::string &vhost) | @@ -1081,7 +1321,7 @@ SrsConfDirective* SrsConfig::get_forward(const std::string &vhost) | ||
| 1081 | return conf->get("forward"); | 1321 | return conf->get("forward"); |
| 1082 | } | 1322 | } |
| 1083 | 1323 | ||
| 1084 | -SrsConfDirective* SrsConfig::get_hls(const std::string &vhost) | 1324 | +SrsConfDirective* SrsConfig::get_hls(string vhost) |
| 1085 | { | 1325 | { |
| 1086 | SrsConfDirective* conf = get_vhost(vhost); | 1326 | SrsConfDirective* conf = get_vhost(vhost); |
| 1087 | 1327 | ||
| @@ -1092,55 +1332,79 @@ SrsConfDirective* SrsConfig::get_hls(const std::string &vhost) | @@ -1092,55 +1332,79 @@ SrsConfDirective* SrsConfig::get_hls(const std::string &vhost) | ||
| 1092 | return conf->get("hls"); | 1332 | return conf->get("hls"); |
| 1093 | } | 1333 | } |
| 1094 | 1334 | ||
| 1095 | -bool SrsConfig::get_hls_enabled(const std::string &vhost) | 1335 | +bool SrsConfig::get_hls_enabled(string vhost) |
| 1096 | { | 1336 | { |
| 1097 | SrsConfDirective* hls = get_hls(vhost); | 1337 | SrsConfDirective* hls = get_hls(vhost); |
| 1098 | 1338 | ||
| 1099 | if (!hls) { | 1339 | if (!hls) { |
| 1100 | - return true; | 1340 | + return false; |
| 1101 | } | 1341 | } |
| 1102 | 1342 | ||
| 1103 | - if (hls->arg0() == "off") { | 1343 | + SrsConfDirective* conf = hls->get("enabled"); |
| 1344 | + | ||
| 1345 | + if (!conf) { | ||
| 1104 | return false; | 1346 | return false; |
| 1105 | } | 1347 | } |
| 1106 | 1348 | ||
| 1107 | - return true; | 1349 | + if (conf->arg0() == "on") { |
| 1350 | + return true; | ||
| 1351 | + } | ||
| 1352 | + | ||
| 1353 | + return false; | ||
| 1108 | } | 1354 | } |
| 1109 | 1355 | ||
| 1110 | -SrsConfDirective* SrsConfig::get_hls_path(const std::string &vhost) | 1356 | +string SrsConfig::get_hls_path(string vhost) |
| 1111 | { | 1357 | { |
| 1112 | - SrsConfDirective* conf = get_vhost(vhost); | ||
| 1113 | - | ||
| 1114 | - if (!conf) { | ||
| 1115 | - return NULL; | 1358 | + SrsConfDirective* hls = get_hls(vhost); |
| 1359 | + | ||
| 1360 | + if (!hls) { | ||
| 1361 | + return SRS_CONF_DEFAULT_HLS_PATH; | ||
| 1116 | } | 1362 | } |
| 1117 | 1363 | ||
| 1118 | - return conf->get("hls_path"); | 1364 | + SrsConfDirective* conf = hls->get("hls_path"); |
| 1365 | + | ||
| 1366 | + if (!conf) { | ||
| 1367 | + return SRS_CONF_DEFAULT_HLS_PATH; | ||
| 1368 | + } | ||
| 1369 | + | ||
| 1370 | + return conf->arg0(); | ||
| 1119 | } | 1371 | } |
| 1120 | 1372 | ||
| 1121 | -SrsConfDirective* SrsConfig::get_hls_fragment(const std::string &vhost) | 1373 | +double SrsConfig::get_hls_fragment(string vhost) |
| 1122 | { | 1374 | { |
| 1123 | - SrsConfDirective* conf = get_vhost(vhost); | ||
| 1124 | - | ||
| 1125 | - if (!conf) { | ||
| 1126 | - return NULL; | 1375 | + SrsConfDirective* hls = get_hls(vhost); |
| 1376 | + | ||
| 1377 | + if (!hls) { | ||
| 1378 | + return SRS_CONF_DEFAULT_HLS_FRAGMENT; | ||
| 1127 | } | 1379 | } |
| 1128 | 1380 | ||
| 1129 | - return conf->get("hls_fragment"); | 1381 | + SrsConfDirective* conf = hls->get("hls_fragment"); |
| 1382 | + | ||
| 1383 | + if (!conf) { | ||
| 1384 | + return SRS_CONF_DEFAULT_HLS_FRAGMENT; | ||
| 1385 | + } | ||
| 1386 | + | ||
| 1387 | + return ::atof(conf->arg0().c_str()); | ||
| 1130 | } | 1388 | } |
| 1131 | 1389 | ||
| 1132 | -SrsConfDirective* SrsConfig::get_hls_window(const std::string &vhost) | 1390 | +double SrsConfig::get_hls_window(string vhost) |
| 1133 | { | 1391 | { |
| 1134 | - SrsConfDirective* conf = get_vhost(vhost); | ||
| 1135 | - | ||
| 1136 | - if (!conf) { | ||
| 1137 | - return NULL; | 1392 | + SrsConfDirective* hls = get_hls(vhost); |
| 1393 | + | ||
| 1394 | + if (!hls) { | ||
| 1395 | + return SRS_CONF_DEFAULT_HLS_WINDOW; | ||
| 1138 | } | 1396 | } |
| 1139 | 1397 | ||
| 1140 | - return conf->get("hls_window"); | 1398 | + SrsConfDirective* conf = hls->get("hls_window"); |
| 1399 | + | ||
| 1400 | + if (!conf) { | ||
| 1401 | + return SRS_CONF_DEFAULT_HLS_WINDOW; | ||
| 1402 | + } | ||
| 1403 | + | ||
| 1404 | + return ::atof(conf->arg0().c_str()); | ||
| 1141 | } | 1405 | } |
| 1142 | 1406 | ||
| 1143 | -SrsConfDirective* SrsConfig::get_refer(const std::string &vhost) | 1407 | +SrsConfDirective* SrsConfig::get_refer(string vhost) |
| 1144 | { | 1408 | { |
| 1145 | SrsConfDirective* conf = get_vhost(vhost); | 1409 | SrsConfDirective* conf = get_vhost(vhost); |
| 1146 | 1410 | ||
| @@ -1151,7 +1415,7 @@ SrsConfDirective* SrsConfig::get_refer(const std::string &vhost) | @@ -1151,7 +1415,7 @@ SrsConfDirective* SrsConfig::get_refer(const std::string &vhost) | ||
| 1151 | return conf->get("refer"); | 1415 | return conf->get("refer"); |
| 1152 | } | 1416 | } |
| 1153 | 1417 | ||
| 1154 | -SrsConfDirective* SrsConfig::get_refer_play(const std::string &vhost) | 1418 | +SrsConfDirective* SrsConfig::get_refer_play(string vhost) |
| 1155 | { | 1419 | { |
| 1156 | SrsConfDirective* conf = get_vhost(vhost); | 1420 | SrsConfDirective* conf = get_vhost(vhost); |
| 1157 | 1421 | ||
| @@ -1162,7 +1426,7 @@ SrsConfDirective* SrsConfig::get_refer_play(const std::string &vhost) | @@ -1162,7 +1426,7 @@ SrsConfDirective* SrsConfig::get_refer_play(const std::string &vhost) | ||
| 1162 | return conf->get("refer_play"); | 1426 | return conf->get("refer_play"); |
| 1163 | } | 1427 | } |
| 1164 | 1428 | ||
| 1165 | -SrsConfDirective* SrsConfig::get_refer_publish(const std::string &vhost) | 1429 | +SrsConfDirective* SrsConfig::get_refer_publish(string vhost) |
| 1166 | { | 1430 | { |
| 1167 | SrsConfDirective* conf = get_vhost(vhost); | 1431 | SrsConfDirective* conf = get_vhost(vhost); |
| 1168 | 1432 | ||
| @@ -1178,65 +1442,59 @@ SrsConfDirective* SrsConfig::get_listen() | @@ -1178,65 +1442,59 @@ SrsConfDirective* SrsConfig::get_listen() | ||
| 1178 | return root->get("listen"); | 1442 | return root->get("listen"); |
| 1179 | } | 1443 | } |
| 1180 | 1444 | ||
| 1181 | -SrsConfDirective* SrsConfig::get_chunk_size(const std::string &vhost) | 1445 | +int SrsConfig::get_chunk_size() |
| 1182 | { | 1446 | { |
| 1183 | - SrsConfDirective* conf = get_vhost(vhost); | ||
| 1184 | - | ||
| 1185 | - if (!conf) { | ||
| 1186 | - return NULL; | ||
| 1187 | - } | ||
| 1188 | - | ||
| 1189 | - return conf->get("chunk_size"); | 1447 | + SrsConfDirective* conf = root->get("chunk_size"); |
| 1448 | + if (!conf) { | ||
| 1449 | + return SRS_CONF_DEFAULT_CHUNK_SIZE; | ||
| 1450 | + } | ||
| 1451 | + | ||
| 1452 | + return ::atoi(conf->arg0().c_str()); | ||
| 1190 | } | 1453 | } |
| 1191 | 1454 | ||
| 1192 | -SrsConfDirective* SrsConfig::get_pithy_print_publish() | 1455 | +int SrsConfig::get_pithy_print_publish() |
| 1193 | { | 1456 | { |
| 1194 | SrsConfDirective* pithy = root->get("pithy_print"); | 1457 | SrsConfDirective* pithy = root->get("pithy_print"); |
| 1195 | if (!pithy) { | 1458 | if (!pithy) { |
| 1196 | - return NULL; | 1459 | + return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; |
| 1197 | } | 1460 | } |
| 1198 | 1461 | ||
| 1199 | - return pithy->get("publish"); | ||
| 1200 | -} | ||
| 1201 | - | ||
| 1202 | -SrsConfDirective* SrsConfig::get_pithy_print_forwarder() | ||
| 1203 | -{ | ||
| 1204 | - SrsConfDirective* pithy = root->get("pithy_print"); | 1462 | + pithy = pithy->get("publish"); |
| 1205 | if (!pithy) { | 1463 | if (!pithy) { |
| 1206 | - return NULL; | 1464 | + return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; |
| 1207 | } | 1465 | } |
| 1208 | 1466 | ||
| 1209 | - return pithy->get("forwarder"); | 1467 | + return ::atoi(pithy->arg0().c_str()); |
| 1210 | } | 1468 | } |
| 1211 | 1469 | ||
| 1212 | -SrsConfDirective* SrsConfig::get_pithy_print_hls() | 1470 | +int SrsConfig::get_pithy_print_forwarder() |
| 1213 | { | 1471 | { |
| 1214 | SrsConfDirective* pithy = root->get("pithy_print"); | 1472 | SrsConfDirective* pithy = root->get("pithy_print"); |
| 1215 | if (!pithy) { | 1473 | if (!pithy) { |
| 1216 | - return NULL; | 1474 | + return SRS_STAGE_FORWARDER_INTERVAL_MS; |
| 1217 | } | 1475 | } |
| 1218 | 1476 | ||
| 1219 | - return pithy->get("hls"); | ||
| 1220 | -} | ||
| 1221 | - | ||
| 1222 | -SrsConfDirective* SrsConfig::get_pithy_print_encoder() | ||
| 1223 | -{ | ||
| 1224 | - SrsConfDirective* pithy = root->get("encoder"); | 1477 | + pithy = pithy->get("forwarder"); |
| 1225 | if (!pithy) { | 1478 | if (!pithy) { |
| 1226 | - return NULL; | 1479 | + return SRS_STAGE_FORWARDER_INTERVAL_MS; |
| 1227 | } | 1480 | } |
| 1228 | 1481 | ||
| 1229 | - return pithy->get("forwarder"); | 1482 | + return ::atoi(pithy->arg0().c_str()); |
| 1230 | } | 1483 | } |
| 1231 | 1484 | ||
| 1232 | -SrsConfDirective* SrsConfig::get_pithy_print_play() | 1485 | +int SrsConfig::get_pithy_print_hls() |
| 1233 | { | 1486 | { |
| 1234 | SrsConfDirective* pithy = root->get("pithy_print"); | 1487 | SrsConfDirective* pithy = root->get("pithy_print"); |
| 1235 | if (!pithy) { | 1488 | if (!pithy) { |
| 1236 | - return NULL; | 1489 | + return SRS_STAGE_HLS_INTERVAL_MS; |
| 1490 | + } | ||
| 1491 | + | ||
| 1492 | + pithy = pithy->get("hls"); | ||
| 1493 | + if (!pithy) { | ||
| 1494 | + return SRS_STAGE_HLS_INTERVAL_MS; | ||
| 1237 | } | 1495 | } |
| 1238 | 1496 | ||
| 1239 | - return pithy->get("play"); | 1497 | + return ::atoi(pithy->arg0().c_str()); |
| 1240 | } | 1498 | } |
| 1241 | 1499 | ||
| 1242 | bool SrsConfig::get_bw_check_enabled(const std::string &vhost, const std::string &key) | 1500 | bool SrsConfig::get_bw_check_enabled(const std::string &vhost, const std::string &key) |
| @@ -1295,104 +1553,43 @@ void SrsConfig::get_bw_check_settings(const std::string &vhost, int64_t &interva | @@ -1295,104 +1553,43 @@ void SrsConfig::get_bw_check_settings(const std::string &vhost, int64_t &interva | ||
| 1295 | pub_kbps = ::atoi(pub_conf->arg0().c_str()); | 1553 | pub_kbps = ::atoi(pub_conf->arg0().c_str()); |
| 1296 | } | 1554 | } |
| 1297 | 1555 | ||
| 1298 | -int SrsConfig::parse_file(const char* filename) | 1556 | +int SrsConfig::get_pithy_print_encoder() |
| 1299 | { | 1557 | { |
| 1300 | - int ret = ERROR_SUCCESS; | ||
| 1301 | - | ||
| 1302 | - config_file = filename; | ||
| 1303 | - | ||
| 1304 | - if (config_file.empty()) { | ||
| 1305 | - return ERROR_SYSTEM_CONFIG_INVALID; | ||
| 1306 | - } | ||
| 1307 | - | ||
| 1308 | - if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) { | ||
| 1309 | - return ret; | 1558 | + SrsConfDirective* pithy = root->get("encoder"); |
| 1559 | + if (!pithy) { | ||
| 1560 | + return SRS_STAGE_ENCODER_INTERVAL_MS; | ||
| 1310 | } | 1561 | } |
| 1311 | 1562 | ||
| 1312 | - SrsConfDirective* conf = NULL; | ||
| 1313 | - if ((conf = get_listen()) == NULL || conf->args.size() == 0) { | ||
| 1314 | - ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 1315 | - srs_error("line %d: conf error, " | ||
| 1316 | - "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret); | ||
| 1317 | - return ret; | 1563 | + pithy = pithy->get("forwarder"); |
| 1564 | + if (!pithy) { | ||
| 1565 | + return SRS_STAGE_ENCODER_INTERVAL_MS; | ||
| 1318 | } | 1566 | } |
| 1319 | - // TODO: check the hls. | ||
| 1320 | - // TODO: check other config. | ||
| 1321 | - // TODO: check hls. | ||
| 1322 | - // TODO: check ssl. | ||
| 1323 | - // TODO: check ffmpeg. | ||
| 1324 | - // TODO: check http. | ||
| 1325 | 1567 | ||
| 1326 | - return ret; | 1568 | + return ::atoi(pithy->arg0().c_str()); |
| 1327 | } | 1569 | } |
| 1328 | 1570 | ||
| 1329 | -int SrsConfig::parse_argv(int& i, char** argv) | 1571 | +int SrsConfig::get_pithy_print_play() |
| 1330 | { | 1572 | { |
| 1331 | - int ret = ERROR_SUCCESS; | ||
| 1332 | - | ||
| 1333 | - char* p = argv[i]; | ||
| 1334 | - | ||
| 1335 | - if (*p++ != '-') { | ||
| 1336 | - ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 1337 | - srs_error("invalid options(index=%d, value=%s), " | ||
| 1338 | - "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret); | ||
| 1339 | - return ret; | 1573 | + SrsConfDirective* pithy = root->get("pithy_print"); |
| 1574 | + if (!pithy) { | ||
| 1575 | + return SRS_STAGE_PLAY_USER_INTERVAL_MS; | ||
| 1340 | } | 1576 | } |
| 1341 | 1577 | ||
| 1342 | - while (*p) { | ||
| 1343 | - switch (*p++) { | ||
| 1344 | - case '?': | ||
| 1345 | - case 'h': | ||
| 1346 | - show_help = true; | ||
| 1347 | - break; | ||
| 1348 | - case 'v': | ||
| 1349 | - case 'V': | ||
| 1350 | - show_version = true; | ||
| 1351 | - break; | ||
| 1352 | - case 'c': | ||
| 1353 | - if (*p) { | ||
| 1354 | - config_file = p; | ||
| 1355 | - return ret; | ||
| 1356 | - } | ||
| 1357 | - if (argv[++i]) { | ||
| 1358 | - config_file = argv[i]; | ||
| 1359 | - return ret; | ||
| 1360 | - } | ||
| 1361 | - ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 1362 | - srs_error("option \"-c\" requires parameter, ret=%d", ret); | ||
| 1363 | - return ret; | ||
| 1364 | - default: | ||
| 1365 | - ret = ERROR_SYSTEM_CONFIG_INVALID; | ||
| 1366 | - srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret); | ||
| 1367 | - return ret; | ||
| 1368 | - } | 1578 | + pithy = pithy->get("play"); |
| 1579 | + if (!pithy) { | ||
| 1580 | + return SRS_STAGE_PLAY_USER_INTERVAL_MS; | ||
| 1369 | } | 1581 | } |
| 1370 | 1582 | ||
| 1371 | - return ret; | ||
| 1372 | -} | ||
| 1373 | - | ||
| 1374 | -void SrsConfig::print_help(char** argv) | ||
| 1375 | -{ | ||
| 1376 | - printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION | ||
| 1377 | - " Copyright (c) 2013 winlin\n" | ||
| 1378 | - "Contributors: "RTMP_SIG_SRS_CONTRIBUTOR"\n" | ||
| 1379 | - "Build: "SRS_BUILD_DATE" Configuration: "SRS_CONFIGURE"\n" | ||
| 1380 | - "Usage: %s [-h?vV] [-c <filename>]\n" | ||
| 1381 | - "\n" | ||
| 1382 | - "Options:\n" | ||
| 1383 | - " -?-h : show help\n" | ||
| 1384 | - " -v-V : show version and exit\n" | ||
| 1385 | - " -c filename : set configuration file\n" | ||
| 1386 | - "\n" | ||
| 1387 | - RTMP_SIG_SRS_WEB"\n" | ||
| 1388 | - RTMP_SIG_SRS_URL"\n" | ||
| 1389 | - "Email: "RTMP_SIG_SRS_EMAIL"\n" | ||
| 1390 | - "\n", | ||
| 1391 | - argv[0]); | 1583 | + return ::atoi(pithy->arg0().c_str()); |
| 1392 | } | 1584 | } |
| 1393 | 1585 | ||
| 1394 | bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b) | 1586 | bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b) |
| 1395 | { | 1587 | { |
| 1588 | + // both NULL, equal. | ||
| 1589 | + if (!a && !b) { | ||
| 1590 | + return true; | ||
| 1591 | + } | ||
| 1592 | + | ||
| 1396 | if (!a || !b) { | 1593 | if (!a || !b) { |
| 1397 | return false; | 1594 | return false; |
| 1398 | } | 1595 | } |
| @@ -48,25 +48,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -48,25 +48,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 48 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 | 48 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 |
| 49 | // in ms, for HLS aac flush the audio | 49 | // in ms, for HLS aac flush the audio |
| 50 | #define SRS_CONF_DEFAULT_AAC_DELAY 300 | 50 | #define SRS_CONF_DEFAULT_AAC_DELAY 300 |
| 51 | +// in seconds, the live queue length. | ||
| 52 | +#define SRS_CONF_DEFAULT_QUEUE_LENGTH 30 | ||
| 53 | +// in seconds, the paused queue length. | ||
| 54 | +#define SRS_CONF_DEFAULT_PAUSED_LENGTH 10 | ||
| 51 | 55 | ||
| 52 | -class SrsFileBuffer | ||
| 53 | -{ | ||
| 54 | -public: | ||
| 55 | - int fd; | ||
| 56 | - int line; | ||
| 57 | - // start of buffer. | ||
| 58 | - char* start; | ||
| 59 | - // end of buffer. | ||
| 60 | - char* end; | ||
| 61 | - // current consumed position. | ||
| 62 | - char* pos; | ||
| 63 | - // last available position. | ||
| 64 | - char* last; | ||
| 65 | - | ||
| 66 | - SrsFileBuffer(); | ||
| 67 | - virtual ~SrsFileBuffer(); | ||
| 68 | - virtual int open(const char* filename); | ||
| 69 | -}; | 56 | +#define SRS_CONF_DEFAULT_CHUNK_SIZE 4096 |
| 57 | + | ||
| 58 | +#define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300 | ||
| 59 | +#define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100 | ||
| 60 | +#define SRS_STAGE_FORWARDER_INTERVAL_MS 2000 | ||
| 61 | +#define SRS_STAGE_ENCODER_INTERVAL_MS 2000 | ||
| 62 | +#define SRS_STAGE_HLS_INTERVAL_MS 2000 | ||
| 63 | + | ||
| 64 | +class SrsFileBuffer; | ||
| 70 | 65 | ||
| 71 | class SrsConfDirective | 66 | class SrsConfDirective |
| 72 | { | 67 | { |
| @@ -83,13 +78,13 @@ public: | @@ -83,13 +78,13 @@ public: | ||
| 83 | std::string arg2(); | 78 | std::string arg2(); |
| 84 | SrsConfDirective* at(int index); | 79 | SrsConfDirective* at(int index); |
| 85 | SrsConfDirective* get(std::string _name); | 80 | SrsConfDirective* get(std::string _name); |
| 81 | + SrsConfDirective* get(std::string _name, std::string _arg0); | ||
| 86 | public: | 82 | public: |
| 87 | virtual int parse(const char* filename); | 83 | virtual int parse(const char* filename); |
| 88 | public: | 84 | public: |
| 89 | enum SrsDirectiveType{parse_file, parse_block}; | 85 | enum SrsDirectiveType{parse_file, parse_block}; |
| 90 | virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type); | 86 | virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type); |
| 91 | virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args); | 87 | virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args); |
| 92 | - virtual int refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart); | ||
| 93 | }; | 88 | }; |
| 94 | 89 | ||
| 95 | /** | 90 | /** |
| @@ -106,71 +101,76 @@ private: | @@ -106,71 +101,76 @@ private: | ||
| 106 | bool show_version; | 101 | bool show_version; |
| 107 | std::string config_file; | 102 | std::string config_file; |
| 108 | SrsConfDirective* root; | 103 | SrsConfDirective* root; |
| 109 | - std::vector<SrsReloadHandler*> subscribes; | 104 | + std::vector<ISrsReloadHandler*> subscribes; |
| 110 | public: | 105 | public: |
| 111 | SrsConfig(); | 106 | SrsConfig(); |
| 112 | virtual ~SrsConfig(); | 107 | virtual ~SrsConfig(); |
| 113 | public: | 108 | public: |
| 114 | virtual int reload(); | 109 | virtual int reload(); |
| 115 | - virtual void subscribe(SrsReloadHandler* handler); | ||
| 116 | - virtual void unsubscribe(SrsReloadHandler* handler); | 110 | + virtual void subscribe(ISrsReloadHandler* handler); |
| 111 | + virtual void unsubscribe(ISrsReloadHandler* handler); | ||
| 117 | public: | 112 | public: |
| 118 | virtual int parse_options(int argc, char** argv); | 113 | virtual int parse_options(int argc, char** argv); |
| 119 | -public: | ||
| 120 | - virtual SrsConfDirective* get_vhost(const std::string &vhost); | ||
| 121 | - virtual bool get_vhost_enabled(const std::string& vhost); | ||
| 122 | - virtual SrsConfDirective* get_vhost_on_connect(const std::string& vhost); | ||
| 123 | - virtual SrsConfDirective* get_vhost_on_close(const std::string& vhost); | ||
| 124 | - virtual SrsConfDirective* get_vhost_on_publish(const std::string& vhost); | ||
| 125 | - virtual SrsConfDirective* get_vhost_on_unpublish(const std::string& vhost); | ||
| 126 | - virtual SrsConfDirective* get_vhost_on_play(const std::string& vhost); | ||
| 127 | - virtual SrsConfDirective* get_vhost_on_stop(const std::string& vhost); | ||
| 128 | - virtual SrsConfDirective* get_transcode(const std::string& vhost, const std::string& scope); | ||
| 129 | - virtual bool get_transcode_enabled(SrsConfDirective* transcode); | ||
| 130 | - virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); | ||
| 131 | - virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); | ||
| 132 | - virtual bool get_engine_enabled(SrsConfDirective* engine); | ||
| 133 | - virtual std::string get_engine_vcodec(SrsConfDirective* engine); | ||
| 134 | - virtual int get_engine_vbitrate(SrsConfDirective* engine); | ||
| 135 | - virtual double get_engine_vfps(SrsConfDirective* engine); | ||
| 136 | - virtual int get_engine_vwidth(SrsConfDirective* engine); | ||
| 137 | - virtual int get_engine_vheight(SrsConfDirective* engine); | ||
| 138 | - virtual int get_engine_vthreads(SrsConfDirective* engine); | ||
| 139 | - virtual std::string get_engine_vprofile(SrsConfDirective* engine); | ||
| 140 | - virtual std::string get_engine_vpreset(SrsConfDirective* engine); | ||
| 141 | - virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams); | ||
| 142 | - virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter); | ||
| 143 | - virtual std::string get_engine_acodec(SrsConfDirective* engine); | ||
| 144 | - virtual int get_engine_abitrate(SrsConfDirective* engine); | ||
| 145 | - virtual int get_engine_asample_rate(SrsConfDirective* engine); | ||
| 146 | - virtual int get_engine_achannels(SrsConfDirective* engine); | ||
| 147 | - virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams); | ||
| 148 | - virtual std::string get_engine_output(SrsConfDirective* engine); | ||
| 149 | - virtual std::string get_log_dir(); | ||
| 150 | - virtual int get_max_connections(); | ||
| 151 | - virtual SrsConfDirective* get_gop_cache(const std::string& vhost); | ||
| 152 | - virtual SrsConfDirective* get_forward(const std::string& vhost); | ||
| 153 | - virtual SrsConfDirective* get_hls(const std::string &vhost); | ||
| 154 | - virtual bool get_hls_enabled(const std::string& vhost); | ||
| 155 | - virtual SrsConfDirective* get_hls_path(const std::string& vhost); | ||
| 156 | - virtual SrsConfDirective* get_hls_fragment(const std::string& vhost); | ||
| 157 | - virtual SrsConfDirective* get_hls_window(const std::string& vhost); | ||
| 158 | - virtual SrsConfDirective* get_refer(const std::string& vhost); | ||
| 159 | - virtual SrsConfDirective* get_refer_play(const std::string& vhost); | ||
| 160 | - virtual SrsConfDirective* get_refer_publish(const std::string& vhost); | ||
| 161 | - virtual SrsConfDirective* get_listen(); | ||
| 162 | - virtual SrsConfDirective* get_chunk_size(const std::string &vhost); | ||
| 163 | - virtual SrsConfDirective* get_pithy_print_publish(); | ||
| 164 | - virtual SrsConfDirective* get_pithy_print_forwarder(); | ||
| 165 | - virtual SrsConfDirective* get_pithy_print_encoder(); | ||
| 166 | - virtual SrsConfDirective* get_pithy_print_hls(); | ||
| 167 | - virtual SrsConfDirective* get_pithy_print_play(); | ||
| 168 | - virtual bool get_bw_check_enabled(const std::string &vhost, const std::string &key); | ||
| 169 | - virtual void get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps); | 114 | + |
| 170 | private: | 115 | private: |
| 171 | virtual int parse_file(const char* filename); | 116 | virtual int parse_file(const char* filename); |
| 172 | virtual int parse_argv(int& i, char** argv); | 117 | virtual int parse_argv(int& i, char** argv); |
| 173 | virtual void print_help(char** argv); | 118 | virtual void print_help(char** argv); |
| 119 | +public: | ||
| 120 | + virtual SrsConfDirective* get_vhost(std::string vhost); | ||
| 121 | + virtual bool get_vhost_enabled(std::string vhost); | ||
| 122 | + virtual bool get_vhost_enabled(SrsConfDirective* vhost); | ||
| 123 | + virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); | ||
| 124 | + virtual SrsConfDirective* get_vhost_on_close(std::string vhost); | ||
| 125 | + virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); | ||
| 126 | + virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); | ||
| 127 | + virtual SrsConfDirective* get_vhost_on_play(std::string vhost); | ||
| 128 | + virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); | ||
| 129 | + virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); | ||
| 130 | + virtual bool get_transcode_enabled(SrsConfDirective* transcode); | ||
| 131 | + virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); | ||
| 132 | + virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); | ||
| 133 | + virtual bool get_engine_enabled(SrsConfDirective* engine); | ||
| 134 | + virtual std::string get_engine_vcodec(SrsConfDirective* engine); | ||
| 135 | + virtual int get_engine_vbitrate(SrsConfDirective* engine); | ||
| 136 | + virtual double get_engine_vfps(SrsConfDirective* engine); | ||
| 137 | + virtual int get_engine_vwidth(SrsConfDirective* engine); | ||
| 138 | + virtual int get_engine_vheight(SrsConfDirective* engine); | ||
| 139 | + virtual int get_engine_vthreads(SrsConfDirective* engine); | ||
| 140 | + virtual std::string get_engine_vprofile(SrsConfDirective* engine); | ||
| 141 | + virtual std::string get_engine_vpreset(SrsConfDirective* engine); | ||
| 142 | + virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams); | ||
| 143 | + virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter); | ||
| 144 | + virtual std::string get_engine_acodec(SrsConfDirective* engine); | ||
| 145 | + virtual int get_engine_abitrate(SrsConfDirective* engine); | ||
| 146 | + virtual int get_engine_asample_rate(SrsConfDirective* engine); | ||
| 147 | + virtual int get_engine_achannels(SrsConfDirective* engine); | ||
| 148 | + virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams); | ||
| 149 | + virtual std::string get_engine_output(SrsConfDirective* engine); | ||
| 150 | + virtual std::string get_log_dir(); | ||
| 151 | + virtual int get_max_connections(); | ||
| 152 | + virtual bool get_gop_cache(std::string vhost); | ||
| 153 | + virtual double get_queue_length(std::string vhost); | ||
| 154 | + virtual SrsConfDirective* get_forward(std::string vhost); | ||
| 155 | +private: | ||
| 156 | + virtual SrsConfDirective* get_hls(std::string vhost); | ||
| 157 | +public: | ||
| 158 | + virtual bool get_hls_enabled(std::string vhost); | ||
| 159 | + virtual std::string get_hls_path(std::string vhost); | ||
| 160 | + virtual double get_hls_fragment(std::string vhost); | ||
| 161 | + virtual double get_hls_window(std::string vhost); | ||
| 162 | + virtual SrsConfDirective* get_refer(std::string vhost); | ||
| 163 | + virtual SrsConfDirective* get_refer_play(std::string vhost); | ||
| 164 | + virtual SrsConfDirective* get_refer_publish(std::string vhost); | ||
| 165 | + virtual SrsConfDirective* get_listen(); | ||
| 166 | + virtual int get_chunk_size(); | ||
| 167 | + virtual int get_pithy_print_publish(); | ||
| 168 | + virtual int get_pithy_print_forwarder(); | ||
| 169 | + virtual int get_pithy_print_encoder(); | ||
| 170 | + virtual int get_pithy_print_hls(); | ||
| 171 | + virtual int get_pithy_print_play(); | ||
| 172 | + virtual bool get_bw_check_enabled(const std::string &vhost, const std::string &key); | ||
| 173 | + virtual void get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps); | ||
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | /** | 176 | /** |
| @@ -36,15 +36,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | @@ -36,15 +36,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | ||
| 36 | 36 | ||
| 37 | SrsConnection::~SrsConnection() | 37 | SrsConnection::~SrsConnection() |
| 38 | { | 38 | { |
| 39 | - if (stfd) { | ||
| 40 | - int fd = st_netfd_fileno(stfd); | ||
| 41 | - st_netfd_close(stfd); | ||
| 42 | - stfd = NULL; | ||
| 43 | - | ||
| 44 | - // st does not close it sometimes, | ||
| 45 | - // close it manually. | ||
| 46 | - close(fd); | ||
| 47 | - } | 39 | + srs_close_stfd(stfd); |
| 48 | } | 40 | } |
| 49 | 41 | ||
| 50 | int SrsConnection::start() | 42 | int SrsConnection::start() |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <srs_core.hpp> | 31 | #include <srs_core.hpp> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | class SrsServer; | 33 | class SrsServer; |
| 36 | class SrsConnection | 34 | class SrsConnection |
| 37 | { | 35 | { |
| @@ -483,52 +483,15 @@ void SrsFFMPEG::stop() | @@ -483,52 +483,15 @@ void SrsFFMPEG::stop() | ||
| 483 | 483 | ||
| 484 | SrsEncoder::SrsEncoder() | 484 | SrsEncoder::SrsEncoder() |
| 485 | { | 485 | { |
| 486 | - tid = NULL; | ||
| 487 | - loop = false; | 486 | + pthread = new SrsThread(this, SRS_ENCODER_SLEEP_MS); |
| 487 | + pithy_print = new SrsPithyPrint(SRS_STAGE_ENCODER); | ||
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | SrsEncoder::~SrsEncoder() | 490 | SrsEncoder::~SrsEncoder() |
| 491 | { | 491 | { |
| 492 | on_unpublish(); | 492 | on_unpublish(); |
| 493 | -} | ||
| 494 | - | ||
| 495 | -int SrsEncoder::parse_scope_engines(SrsRequest* req) | ||
| 496 | -{ | ||
| 497 | - int ret = ERROR_SUCCESS; | ||
| 498 | 493 | ||
| 499 | - // parse all transcode engines. | ||
| 500 | - SrsConfDirective* conf = NULL; | ||
| 501 | - | ||
| 502 | - // parse vhost scope engines | ||
| 503 | - std::string scope = ""; | ||
| 504 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 505 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 506 | - srs_error("parse vhost scope=%s transcode engines failed. " | ||
| 507 | - "ret=%d", scope.c_str(), ret); | ||
| 508 | - return ret; | ||
| 509 | - } | ||
| 510 | - } | ||
| 511 | - // parse app scope engines | ||
| 512 | - scope = req->app; | ||
| 513 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 514 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 515 | - srs_error("parse app scope=%s transcode engines failed. " | ||
| 516 | - "ret=%d", scope.c_str(), ret); | ||
| 517 | - return ret; | ||
| 518 | - } | ||
| 519 | - } | ||
| 520 | - // parse stream scope engines | ||
| 521 | - scope += "/"; | ||
| 522 | - scope += req->stream; | ||
| 523 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 524 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 525 | - srs_error("parse stream scope=%s transcode engines failed. " | ||
| 526 | - "ret=%d", scope.c_str(), ret); | ||
| 527 | - return ret; | ||
| 528 | - } | ||
| 529 | - } | ||
| 530 | - | ||
| 531 | - return ret; | 494 | + srs_freep(pthread); |
| 532 | } | 495 | } |
| 533 | 496 | ||
| 534 | int SrsEncoder::on_publish(SrsRequest* req) | 497 | int SrsEncoder::on_publish(SrsRequest* req) |
| @@ -539,6 +502,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -539,6 +502,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 539 | 502 | ||
| 540 | // ignore the loop encoder | 503 | // ignore the loop encoder |
| 541 | if (ret == ERROR_ENCODER_LOOP) { | 504 | if (ret == ERROR_ENCODER_LOOP) { |
| 505 | + clear_engines(); | ||
| 542 | ret = ERROR_SUCCESS; | 506 | ret = ERROR_SUCCESS; |
| 543 | } | 507 | } |
| 544 | 508 | ||
| @@ -548,9 +512,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -548,9 +512,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 548 | } | 512 | } |
| 549 | 513 | ||
| 550 | // start thread to run all encoding engines. | 514 | // start thread to run all encoding engines. |
| 551 | - srs_assert(!tid); | ||
| 552 | - if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL) { | ||
| 553 | - ret = ERROR_ST_CREATE_FORWARD_THREAD; | 515 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { |
| 554 | srs_error("st_thread_create failed. ret=%d", ret); | 516 | srs_error("st_thread_create failed. ret=%d", ret); |
| 555 | return ret; | 517 | return ret; |
| 556 | } | 518 | } |
| @@ -560,23 +522,58 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -560,23 +522,58 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 560 | 522 | ||
| 561 | void SrsEncoder::on_unpublish() | 523 | void SrsEncoder::on_unpublish() |
| 562 | { | 524 | { |
| 563 | - if (tid) { | ||
| 564 | - loop = false; | ||
| 565 | - st_thread_interrupt(tid); | ||
| 566 | - st_thread_join(tid, NULL); | ||
| 567 | - tid = NULL; | 525 | + pthread->stop(); |
| 526 | + clear_engines(); | ||
| 527 | +} | ||
| 528 | + | ||
| 529 | +int SrsEncoder::cycle() | ||
| 530 | +{ | ||
| 531 | + int ret = ERROR_SUCCESS; | ||
| 532 | + | ||
| 533 | + std::vector<SrsFFMPEG*>::iterator it; | ||
| 534 | + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 535 | + SrsFFMPEG* ffmpeg = *it; | ||
| 536 | + | ||
| 537 | + // start all ffmpegs. | ||
| 538 | + if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { | ||
| 539 | + srs_error("ffmpeg start failed. ret=%d", ret); | ||
| 540 | + return ret; | ||
| 541 | + } | ||
| 542 | + | ||
| 543 | + // check ffmpeg status. | ||
| 544 | + if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { | ||
| 545 | + srs_error("ffmpeg cycle failed. ret=%d", ret); | ||
| 546 | + return ret; | ||
| 547 | + } | ||
| 568 | } | 548 | } |
| 569 | 549 | ||
| 570 | - clear_engines(); | 550 | + // pithy print |
| 551 | + encoder(); | ||
| 552 | + pithy_print->elapse(SRS_ENCODER_SLEEP_MS); | ||
| 553 | + | ||
| 554 | + return ret; | ||
| 555 | +} | ||
| 556 | + | ||
| 557 | +void SrsEncoder::on_leave_loop() | ||
| 558 | +{ | ||
| 559 | + // kill ffmpeg when finished and it alive | ||
| 560 | + std::vector<SrsFFMPEG*>::iterator it; | ||
| 561 | + | ||
| 562 | + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 563 | + SrsFFMPEG* ffmpeg = *it; | ||
| 564 | + ffmpeg->stop(); | ||
| 565 | + } | ||
| 571 | } | 566 | } |
| 572 | 567 | ||
| 573 | void SrsEncoder::clear_engines() | 568 | void SrsEncoder::clear_engines() |
| 574 | { | 569 | { |
| 575 | std::vector<SrsFFMPEG*>::iterator it; | 570 | std::vector<SrsFFMPEG*>::iterator it; |
| 571 | + | ||
| 576 | for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | 572 | for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { |
| 577 | SrsFFMPEG* ffmpeg = *it; | 573 | SrsFFMPEG* ffmpeg = *it; |
| 578 | srs_freep(ffmpeg); | 574 | srs_freep(ffmpeg); |
| 579 | } | 575 | } |
| 576 | + | ||
| 580 | ffmpegs.clear(); | 577 | ffmpegs.clear(); |
| 581 | } | 578 | } |
| 582 | 579 | ||
| @@ -585,6 +582,45 @@ SrsFFMPEG* SrsEncoder::at(int index) | @@ -585,6 +582,45 @@ SrsFFMPEG* SrsEncoder::at(int index) | ||
| 585 | return ffmpegs[index]; | 582 | return ffmpegs[index]; |
| 586 | } | 583 | } |
| 587 | 584 | ||
| 585 | +int SrsEncoder::parse_scope_engines(SrsRequest* req) | ||
| 586 | +{ | ||
| 587 | + int ret = ERROR_SUCCESS; | ||
| 588 | + | ||
| 589 | + // parse all transcode engines. | ||
| 590 | + SrsConfDirective* conf = NULL; | ||
| 591 | + | ||
| 592 | + // parse vhost scope engines | ||
| 593 | + std::string scope = ""; | ||
| 594 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 595 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 596 | + srs_error("parse vhost scope=%s transcode engines failed. " | ||
| 597 | + "ret=%d", scope.c_str(), ret); | ||
| 598 | + return ret; | ||
| 599 | + } | ||
| 600 | + } | ||
| 601 | + // parse app scope engines | ||
| 602 | + scope = req->app; | ||
| 603 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 604 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 605 | + srs_error("parse app scope=%s transcode engines failed. " | ||
| 606 | + "ret=%d", scope.c_str(), ret); | ||
| 607 | + return ret; | ||
| 608 | + } | ||
| 609 | + } | ||
| 610 | + // parse stream scope engines | ||
| 611 | + scope += "/"; | ||
| 612 | + scope += req->stream; | ||
| 613 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 614 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 615 | + srs_error("parse stream scope=%s transcode engines failed. " | ||
| 616 | + "ret=%d", scope.c_str(), ret); | ||
| 617 | + return ret; | ||
| 618 | + } | ||
| 619 | + } | ||
| 620 | + | ||
| 621 | + return ret; | ||
| 622 | +} | ||
| 623 | + | ||
| 588 | int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | 624 | int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) |
| 589 | { | 625 | { |
| 590 | int ret = ERROR_SUCCESS; | 626 | int ret = ERROR_SUCCESS; |
| @@ -631,7 +667,6 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | @@ -631,7 +667,6 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | ||
| 631 | 667 | ||
| 632 | // if got a loop, donot transcode the whole stream. | 668 | // if got a loop, donot transcode the whole stream. |
| 633 | if (ret == ERROR_ENCODER_LOOP) { | 669 | if (ret == ERROR_ENCODER_LOOP) { |
| 634 | - clear_engines(); | ||
| 635 | break; | 670 | break; |
| 636 | } | 671 | } |
| 637 | 672 | ||
| @@ -646,85 +681,14 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | @@ -646,85 +681,14 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | ||
| 646 | return ret; | 681 | return ret; |
| 647 | } | 682 | } |
| 648 | 683 | ||
| 649 | -int SrsEncoder::cycle() | ||
| 650 | -{ | ||
| 651 | - int ret = ERROR_SUCCESS; | ||
| 652 | - | ||
| 653 | - std::vector<SrsFFMPEG*>::iterator it; | ||
| 654 | - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 655 | - SrsFFMPEG* ffmpeg = *it; | ||
| 656 | - | ||
| 657 | - // start all ffmpegs. | ||
| 658 | - if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { | ||
| 659 | - srs_error("ffmpeg start failed. ret=%d", ret); | ||
| 660 | - return ret; | ||
| 661 | - } | ||
| 662 | - | ||
| 663 | - // check ffmpeg status. | ||
| 664 | - if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { | ||
| 665 | - srs_error("ffmpeg cycle failed. ret=%d", ret); | ||
| 666 | - return ret; | ||
| 667 | - } | ||
| 668 | - } | ||
| 669 | - | ||
| 670 | - return ret; | ||
| 671 | -} | ||
| 672 | - | ||
| 673 | -void SrsEncoder::encoder_cycle() | ||
| 674 | -{ | ||
| 675 | - int ret = ERROR_SUCCESS; | ||
| 676 | - | ||
| 677 | - log_context->generate_id(); | ||
| 678 | - srs_trace("encoder cycle start"); | ||
| 679 | - | ||
| 680 | - SrsPithyPrint pithy_print(SRS_STAGE_ENCODER); | ||
| 681 | - | ||
| 682 | - while (loop) { | ||
| 683 | - if ((ret = cycle()) != ERROR_SUCCESS) { | ||
| 684 | - srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret); | ||
| 685 | - } else { | ||
| 686 | - srs_info("encoder cycle success, retry"); | ||
| 687 | - } | ||
| 688 | - | ||
| 689 | - if (!loop) { | ||
| 690 | - break; | ||
| 691 | - } | ||
| 692 | - | ||
| 693 | - encoder(&pithy_print); | ||
| 694 | - pithy_print.elapse(SRS_ENCODER_SLEEP_MS); | ||
| 695 | - | ||
| 696 | - st_usleep(SRS_ENCODER_SLEEP_MS * 1000); | ||
| 697 | - } | ||
| 698 | - | ||
| 699 | - // kill ffmpeg when finished and it alive | ||
| 700 | - std::vector<SrsFFMPEG*>::iterator it; | ||
| 701 | - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 702 | - SrsFFMPEG* ffmpeg = *it; | ||
| 703 | - ffmpeg->stop(); | ||
| 704 | - } | ||
| 705 | - | ||
| 706 | - srs_trace("encoder cycle finished"); | ||
| 707 | -} | ||
| 708 | - | ||
| 709 | -void SrsEncoder::encoder(SrsPithyPrint* pithy_print) | 684 | +void SrsEncoder::encoder() |
| 710 | { | 685 | { |
| 711 | // reportable | 686 | // reportable |
| 712 | if (pithy_print->can_print()) { | 687 | if (pithy_print->can_print()) { |
| 713 | - srs_trace("-> time=%"PRId64", encoders=%d", | ||
| 714 | - pithy_print->get_age(), (int)ffmpegs.size()); | 688 | + // TODO: FIXME: show more info. |
| 689 | + srs_trace("-> time=%"PRId64", encoders=%d", pithy_print->get_age(), (int)ffmpegs.size()); | ||
| 715 | } | 690 | } |
| 716 | } | 691 | } |
| 717 | 692 | ||
| 718 | -void* SrsEncoder::encoder_thread(void* arg) | ||
| 719 | -{ | ||
| 720 | - SrsEncoder* obj = (SrsEncoder*)arg; | ||
| 721 | - srs_assert(obj != NULL); | ||
| 722 | - | ||
| 723 | - obj->loop = true; | ||
| 724 | - obj->encoder_cycle(); | ||
| 725 | - | ||
| 726 | - return NULL; | ||
| 727 | -} | ||
| 728 | - | ||
| 729 | #endif | 693 | #endif |
| 730 | 694 |
| @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | #include <string> | 32 | #include <string> |
| 33 | #include <vector> | 33 | #include <vector> |
| 34 | 34 | ||
| 35 | -#include <st.h> | 35 | +#include <srs_core_thread.hpp> |
| 36 | 36 | ||
| 37 | class SrsConfDirective; | 37 | class SrsConfDirective; |
| 38 | class SrsRequest; | 38 | class SrsRequest; |
| @@ -85,28 +85,29 @@ public: | @@ -85,28 +85,29 @@ public: | ||
| 85 | * the encoder for a stream, | 85 | * the encoder for a stream, |
| 86 | * may use multiple ffmpegs to transcode the specified stream. | 86 | * may use multiple ffmpegs to transcode the specified stream. |
| 87 | */ | 87 | */ |
| 88 | -class SrsEncoder | 88 | +class SrsEncoder : public ISrsThreadHandler |
| 89 | { | 89 | { |
| 90 | private: | 90 | private: |
| 91 | std::vector<SrsFFMPEG*> ffmpegs; | 91 | std::vector<SrsFFMPEG*> ffmpegs; |
| 92 | private: | 92 | private: |
| 93 | - st_thread_t tid; | ||
| 94 | - bool loop; | 93 | + SrsThread* pthread; |
| 94 | + SrsPithyPrint* pithy_print; | ||
| 95 | public: | 95 | public: |
| 96 | SrsEncoder(); | 96 | SrsEncoder(); |
| 97 | virtual ~SrsEncoder(); | 97 | virtual ~SrsEncoder(); |
| 98 | public: | 98 | public: |
| 99 | virtual int on_publish(SrsRequest* req); | 99 | virtual int on_publish(SrsRequest* req); |
| 100 | virtual void on_unpublish(); | 100 | virtual void on_unpublish(); |
| 101 | +// interface ISrsThreadHandler. | ||
| 102 | +public: | ||
| 103 | + virtual int cycle(); | ||
| 104 | + virtual void on_leave_loop(); | ||
| 101 | private: | 105 | private: |
| 102 | - virtual int parse_scope_engines(SrsRequest* req); | ||
| 103 | virtual void clear_engines(); | 106 | virtual void clear_engines(); |
| 104 | virtual SrsFFMPEG* at(int index); | 107 | virtual SrsFFMPEG* at(int index); |
| 108 | + virtual int parse_scope_engines(SrsRequest* req); | ||
| 105 | virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); | 109 | virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); |
| 106 | - virtual int cycle(); | ||
| 107 | - virtual void encoder_cycle(); | ||
| 108 | - virtual void encoder(SrsPithyPrint* pithy_print); | ||
| 109 | - static void* encoder_thread(void* arg); | 110 | + virtual void encoder(); |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| 112 | #endif | 113 | #endif |
| @@ -37,8 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,8 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | #define ERROR_ST_OPEN_SOCKET 102 | 37 | #define ERROR_ST_OPEN_SOCKET 102 |
| 38 | #define ERROR_ST_CREATE_LISTEN_THREAD 103 | 38 | #define ERROR_ST_CREATE_LISTEN_THREAD 103 |
| 39 | #define ERROR_ST_CREATE_CYCLE_THREAD 104 | 39 | #define ERROR_ST_CREATE_CYCLE_THREAD 104 |
| 40 | -#define ERROR_ST_CREATE_FORWARD_THREAD 105 | ||
| 41 | -#define ERROR_ST_CONNECT 106 | 40 | +#define ERROR_ST_CONNECT 105 |
| 42 | 41 | ||
| 43 | #define ERROR_SOCKET_CREATE 200 | 42 | #define ERROR_SOCKET_CREATE 200 |
| 44 | #define ERROR_SOCKET_SETREUSE 201 | 43 | #define ERROR_SOCKET_SETREUSE 201 |
| @@ -85,9 +84,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -85,9 +84,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 85 | #define ERROR_SYSTEM_CONFIG_EOF 409 | 84 | #define ERROR_SYSTEM_CONFIG_EOF 409 |
| 86 | #define ERROR_SYSTEM_STREAM_BUSY 410 | 85 | #define ERROR_SYSTEM_STREAM_BUSY 410 |
| 87 | #define ERROR_SYSTEM_IP_INVALID 411 | 86 | #define ERROR_SYSTEM_IP_INVALID 411 |
| 88 | -#define ERROR_SYSTEM_CONFIG_TOO_LARGE 412 | ||
| 89 | -#define ERROR_SYSTEM_FORWARD_LOOP 413 | ||
| 90 | -#define ERROR_SYSTEM_WAITPID 414 | 87 | +#define ERROR_SYSTEM_FORWARD_LOOP 412 |
| 88 | +#define ERROR_SYSTEM_WAITPID 413 | ||
| 91 | 89 | ||
| 92 | // see librtmp. | 90 | // see librtmp. |
| 93 | // failed when open ssl create the dh | 91 | // failed when open ssl create the dh |
| @@ -35,32 +35,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -35,32 +35,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 35 | #include <srs_core_pithy_print.hpp> | 35 | #include <srs_core_pithy_print.hpp> |
| 36 | #include <srs_core_rtmp.hpp> | 36 | #include <srs_core_rtmp.hpp> |
| 37 | #include <srs_core_config.hpp> | 37 | #include <srs_core_config.hpp> |
| 38 | +#include <srs_core_source.hpp> | ||
| 39 | +#include <srs_core_autofree.hpp> | ||
| 38 | 40 | ||
| 39 | #define SRS_PULSE_TIMEOUT_MS 100 | 41 | #define SRS_PULSE_TIMEOUT_MS 100 |
| 40 | #define SRS_FORWARDER_SLEEP_MS 2000 | 42 | #define SRS_FORWARDER_SLEEP_MS 2000 |
| 41 | #define SRS_SEND_TIMEOUT_US 3000000L | 43 | #define SRS_SEND_TIMEOUT_US 3000000L |
| 42 | #define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US | 44 | #define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US |
| 43 | 45 | ||
| 44 | -SrsForwarder::SrsForwarder() | 46 | +SrsForwarder::SrsForwarder(SrsSource* _source) |
| 45 | { | 47 | { |
| 48 | + source = _source; | ||
| 49 | + | ||
| 46 | client = NULL; | 50 | client = NULL; |
| 47 | stfd = NULL; | 51 | stfd = NULL; |
| 48 | stream_id = 0; | 52 | stream_id = 0; |
| 49 | - | ||
| 50 | - tid = NULL; | ||
| 51 | - loop = false; | 53 | + |
| 54 | + pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_MS); | ||
| 55 | + queue = new SrsMessageQueue(); | ||
| 56 | + jitter = new SrsRtmpJitter(); | ||
| 52 | } | 57 | } |
| 53 | 58 | ||
| 54 | SrsForwarder::~SrsForwarder() | 59 | SrsForwarder::~SrsForwarder() |
| 55 | { | 60 | { |
| 56 | on_unpublish(); | 61 | on_unpublish(); |
| 57 | 62 | ||
| 58 | - std::vector<SrsSharedPtrMessage*>::iterator it; | ||
| 59 | - for (it = msgs.begin(); it != msgs.end(); ++it) { | ||
| 60 | - SrsSharedPtrMessage* msg = *it; | ||
| 61 | - srs_freep(msg); | ||
| 62 | - } | ||
| 63 | - msgs.clear(); | 63 | + srs_freep(pthread); |
| 64 | + srs_freep(queue); | ||
| 65 | + srs_freep(jitter); | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +void SrsForwarder::set_queue_size(double queue_size) | ||
| 69 | +{ | ||
| 70 | + queue->set_queue_size(queue_size); | ||
| 64 | } | 71 | } |
| 65 | 72 | ||
| 66 | int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) | 73 | int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) |
| @@ -110,41 +117,19 @@ int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) | @@ -110,41 +117,19 @@ int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) | ||
| 110 | source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), | 117 | source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), |
| 111 | stream_name.c_str()); | 118 | stream_name.c_str()); |
| 112 | 119 | ||
| 113 | - // TODO: seems bug when republish and reforward. | ||
| 114 | - | ||
| 115 | - // start forward | ||
| 116 | - if ((ret = open_socket()) != ERROR_SUCCESS) { | ||
| 117 | - return ret; | ||
| 118 | - } | ||
| 119 | - | ||
| 120 | - srs_assert(!tid); | ||
| 121 | - if((tid = st_thread_create(forward_thread, this, 1, 0)) == NULL){ | ||
| 122 | - ret = ERROR_ST_CREATE_FORWARD_THREAD; | ||
| 123 | - srs_error("st_thread_create failed. ret=%d", ret); | 120 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { |
| 121 | + srs_error("start srs thread failed. ret=%d", ret); | ||
| 124 | return ret; | 122 | return ret; |
| 125 | - } | 123 | + } |
| 126 | 124 | ||
| 127 | return ret; | 125 | return ret; |
| 128 | } | 126 | } |
| 129 | 127 | ||
| 130 | void SrsForwarder::on_unpublish() | 128 | void SrsForwarder::on_unpublish() |
| 131 | { | 129 | { |
| 132 | - if (tid) { | ||
| 133 | - loop = false; | ||
| 134 | - st_thread_interrupt(tid); | ||
| 135 | - st_thread_join(tid, NULL); | ||
| 136 | - tid = NULL; | ||
| 137 | - } | 130 | + pthread->stop(); |
| 138 | 131 | ||
| 139 | - if (stfd) { | ||
| 140 | - int fd = st_netfd_fileno(stfd); | ||
| 141 | - st_netfd_close(stfd); | ||
| 142 | - stfd = NULL; | ||
| 143 | - | ||
| 144 | - // st does not close it sometimes, | ||
| 145 | - // close it manually. | ||
| 146 | - close(fd); | ||
| 147 | - } | 132 | + close_underlayer_socket(); |
| 148 | 133 | ||
| 149 | srs_freep(client); | 134 | srs_freep(client); |
| 150 | } | 135 | } |
| @@ -153,7 +138,14 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | @@ -153,7 +138,14 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | ||
| 153 | { | 138 | { |
| 154 | int ret = ERROR_SUCCESS; | 139 | int ret = ERROR_SUCCESS; |
| 155 | 140 | ||
| 156 | - msgs.push_back(metadata); | 141 | + if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { |
| 142 | + srs_freep(metadata); | ||
| 143 | + return ret; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) { | ||
| 147 | + return ret; | ||
| 148 | + } | ||
| 157 | 149 | ||
| 158 | return ret; | 150 | return ret; |
| 159 | } | 151 | } |
| @@ -162,7 +154,14 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | @@ -162,7 +154,14 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | ||
| 162 | { | 154 | { |
| 163 | int ret = ERROR_SUCCESS; | 155 | int ret = ERROR_SUCCESS; |
| 164 | 156 | ||
| 165 | - msgs.push_back(msg); | 157 | + if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { |
| 158 | + srs_freep(msg); | ||
| 159 | + return ret; | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { | ||
| 163 | + return ret; | ||
| 164 | + } | ||
| 166 | 165 | ||
| 167 | return ret; | 166 | return ret; |
| 168 | } | 167 | } |
| @@ -171,15 +170,74 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | @@ -171,15 +170,74 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | ||
| 171 | { | 170 | { |
| 172 | int ret = ERROR_SUCCESS; | 171 | int ret = ERROR_SUCCESS; |
| 173 | 172 | ||
| 174 | - msgs.push_back(msg); | 173 | + if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { |
| 174 | + srs_freep(msg); | ||
| 175 | + return ret; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { | ||
| 179 | + return ret; | ||
| 180 | + } | ||
| 175 | 181 | ||
| 176 | return ret; | 182 | return ret; |
| 177 | } | 183 | } |
| 178 | 184 | ||
| 179 | -int SrsForwarder::open_socket() | 185 | +int SrsForwarder::cycle() |
| 186 | +{ | ||
| 187 | + int ret = ERROR_SUCCESS; | ||
| 188 | + | ||
| 189 | + if ((ret = connect_server()) != ERROR_SUCCESS) { | ||
| 190 | + return ret; | ||
| 191 | + } | ||
| 192 | + srs_assert(client); | ||
| 193 | + | ||
| 194 | + client->set_recv_timeout(SRS_RECV_TIMEOUT_US); | ||
| 195 | + client->set_send_timeout(SRS_SEND_TIMEOUT_US); | ||
| 196 | + | ||
| 197 | + if ((ret = client->handshake()) != ERROR_SUCCESS) { | ||
| 198 | + srs_error("handshake with server failed. ret=%d", ret); | ||
| 199 | + return ret; | ||
| 200 | + } | ||
| 201 | + if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { | ||
| 202 | + srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); | ||
| 203 | + return ret; | ||
| 204 | + } | ||
| 205 | + if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { | ||
| 206 | + srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); | ||
| 207 | + return ret; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { | ||
| 211 | + srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", | ||
| 212 | + stream_name.c_str(), stream_id, ret); | ||
| 213 | + return ret; | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) { | ||
| 217 | + srs_error("callback the source to feed the sequence header failed. ret=%d", ret); | ||
| 218 | + return ret; | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + if ((ret = forward()) != ERROR_SUCCESS) { | ||
| 222 | + return ret; | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + return ret; | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +void SrsForwarder::close_underlayer_socket() | ||
| 229 | +{ | ||
| 230 | + srs_close_stfd(stfd); | ||
| 231 | +} | ||
| 232 | + | ||
| 233 | +int SrsForwarder::connect_server() | ||
| 180 | { | 234 | { |
| 181 | int ret = ERROR_SUCCESS; | 235 | int ret = ERROR_SUCCESS; |
| 182 | 236 | ||
| 237 | + // reopen | ||
| 238 | + close_underlayer_socket(); | ||
| 239 | + | ||
| 240 | + // open socket. | ||
| 183 | srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", | 241 | srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", |
| 184 | stream_name.c_str(), tc_url.c_str(), server.c_str(), port); | 242 | stream_name.c_str(), tc_url.c_str(), server.c_str(), port); |
| 185 | 243 | ||
| @@ -190,6 +248,7 @@ int SrsForwarder::open_socket() | @@ -190,6 +248,7 @@ int SrsForwarder::open_socket() | ||
| 190 | return ret; | 248 | return ret; |
| 191 | } | 249 | } |
| 192 | 250 | ||
| 251 | + srs_assert(!stfd); | ||
| 193 | stfd = st_netfd_open_socket(sock); | 252 | stfd = st_netfd_open_socket(sock); |
| 194 | if(stfd == NULL){ | 253 | if(stfd == NULL){ |
| 195 | ret = ERROR_ST_OPEN_SOCKET; | 254 | ret = ERROR_ST_OPEN_SOCKET; |
| @@ -200,13 +259,7 @@ int SrsForwarder::open_socket() | @@ -200,13 +259,7 @@ int SrsForwarder::open_socket() | ||
| 200 | srs_freep(client); | 259 | srs_freep(client); |
| 201 | client = new SrsRtmpClient(stfd); | 260 | client = new SrsRtmpClient(stfd); |
| 202 | 261 | ||
| 203 | - return ret; | ||
| 204 | -} | ||
| 205 | - | ||
| 206 | -int SrsForwarder::connect_server() | ||
| 207 | -{ | ||
| 208 | - int ret = ERROR_SUCCESS; | ||
| 209 | - | 262 | + // connect to server. |
| 210 | std::string ip = srs_dns_resolve(server); | 263 | std::string ip = srs_dns_resolve(server); |
| 211 | if (ip.empty()) { | 264 | if (ip.empty()) { |
| 212 | ret = ERROR_SYSTEM_IP_INVALID; | 265 | ret = ERROR_SYSTEM_IP_INVALID; |
| @@ -229,43 +282,6 @@ int SrsForwarder::connect_server() | @@ -229,43 +282,6 @@ int SrsForwarder::connect_server() | ||
| 229 | return ret; | 282 | return ret; |
| 230 | } | 283 | } |
| 231 | 284 | ||
| 232 | -int SrsForwarder::cycle() | ||
| 233 | -{ | ||
| 234 | - int ret = ERROR_SUCCESS; | ||
| 235 | - | ||
| 236 | - client->set_recv_timeout(SRS_RECV_TIMEOUT_US); | ||
| 237 | - client->set_send_timeout(SRS_SEND_TIMEOUT_US); | ||
| 238 | - | ||
| 239 | - if ((ret = connect_server()) != ERROR_SUCCESS) { | ||
| 240 | - return ret; | ||
| 241 | - } | ||
| 242 | - srs_assert(client); | ||
| 243 | - | ||
| 244 | - if ((ret = client->handshake()) != ERROR_SUCCESS) { | ||
| 245 | - srs_error("handshake with server failed. ret=%d", ret); | ||
| 246 | - return ret; | ||
| 247 | - } | ||
| 248 | - if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { | ||
| 249 | - srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); | ||
| 250 | - return ret; | ||
| 251 | - } | ||
| 252 | - if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { | ||
| 253 | - srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); | ||
| 254 | - return ret; | ||
| 255 | - } | ||
| 256 | - if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { | ||
| 257 | - srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", | ||
| 258 | - stream_name.c_str(), stream_id, ret); | ||
| 259 | - return ret; | ||
| 260 | - } | ||
| 261 | - | ||
| 262 | - if ((ret = forward()) != ERROR_SUCCESS) { | ||
| 263 | - return ret; | ||
| 264 | - } | ||
| 265 | - | ||
| 266 | - return ret; | ||
| 267 | -} | ||
| 268 | - | ||
| 269 | int SrsForwarder::forward() | 285 | int SrsForwarder::forward() |
| 270 | { | 286 | { |
| 271 | int ret = ERROR_SUCCESS; | 287 | int ret = ERROR_SUCCESS; |
| @@ -274,9 +290,7 @@ int SrsForwarder::forward() | @@ -274,9 +290,7 @@ int SrsForwarder::forward() | ||
| 274 | 290 | ||
| 275 | SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); | 291 | SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); |
| 276 | 292 | ||
| 277 | - while (loop) { | ||
| 278 | - pithy_print.elapse(SRS_PULSE_TIMEOUT_MS); | ||
| 279 | - | 293 | + while (true) { |
| 280 | // switch to other st-threads. | 294 | // switch to other st-threads. |
| 281 | st_usleep(0); | 295 | st_usleep(0); |
| 282 | 296 | ||
| @@ -292,91 +306,42 @@ int SrsForwarder::forward() | @@ -292,91 +306,42 @@ int SrsForwarder::forward() | ||
| 292 | } | 306 | } |
| 293 | } | 307 | } |
| 294 | 308 | ||
| 309 | + // forward all messages. | ||
| 310 | + int count = 0; | ||
| 311 | + SrsSharedPtrMessage** msgs = NULL; | ||
| 312 | + if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { | ||
| 313 | + srs_error("get message to forward failed. ret=%d", ret); | ||
| 314 | + return ret; | ||
| 315 | + } | ||
| 316 | + | ||
| 295 | // ignore when no messages. | 317 | // ignore when no messages. |
| 296 | - int count = (int)msgs.size(); | ||
| 297 | - if (msgs.empty()) { | 318 | + if (count <= 0) { |
| 319 | + srs_verbose("no packets to forward."); | ||
| 298 | continue; | 320 | continue; |
| 299 | } | 321 | } |
| 322 | + SrsAutoFree(SrsSharedPtrMessage*, msgs, true); | ||
| 300 | 323 | ||
| 301 | - // reportable | 324 | + // pithy print |
| 325 | + pithy_print.elapse(SRS_PULSE_TIMEOUT_MS); | ||
| 302 | if (pithy_print.can_print()) { | 326 | if (pithy_print.can_print()) { |
| 303 | srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", | 327 | srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", |
| 304 | pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); | 328 | pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); |
| 305 | } | 329 | } |
| 306 | 330 | ||
| 307 | // all msgs to forward. | 331 | // all msgs to forward. |
| 308 | - int i = 0; | ||
| 309 | - for (i = 0; i < count; i++) { | 332 | + for (int i = 0; i < count; i++) { |
| 310 | SrsSharedPtrMessage* msg = msgs[i]; | 333 | SrsSharedPtrMessage* msg = msgs[i]; |
| 311 | - msgs[i] = NULL; | ||
| 312 | - | ||
| 313 | - // we erased the sendout messages, the msg must not be NULL. | 334 | + |
| 314 | srs_assert(msg); | 335 | srs_assert(msg); |
| 336 | + msgs[i] = NULL; | ||
| 315 | 337 | ||
| 316 | - ret = client->send_message(msg); | ||
| 317 | - if (ret != ERROR_SUCCESS) { | 338 | + if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { |
| 318 | srs_error("forwarder send message to server failed. ret=%d", ret); | 339 | srs_error("forwarder send message to server failed. ret=%d", ret); |
| 319 | - | ||
| 320 | - // convert the index to count when error. | ||
| 321 | - i++; | ||
| 322 | - | ||
| 323 | - break; | 340 | + return ret; |
| 324 | } | 341 | } |
| 325 | } | 342 | } |
| 326 | - | ||
| 327 | - // clear sendout mesages. | ||
| 328 | - if (i < count) { | ||
| 329 | - srs_warn("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 330 | - } else { | ||
| 331 | - srs_info("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 332 | - } | ||
| 333 | - msgs.erase(msgs.begin(), msgs.begin() + i); | ||
| 334 | - | ||
| 335 | - if (ret != ERROR_SUCCESS) { | ||
| 336 | - break; | ||
| 337 | - } | ||
| 338 | } | 343 | } |
| 339 | 344 | ||
| 340 | return ret; | 345 | return ret; |
| 341 | } | 346 | } |
| 342 | 347 | ||
| 343 | -void SrsForwarder::forward_cycle() | ||
| 344 | -{ | ||
| 345 | - int ret = ERROR_SUCCESS; | ||
| 346 | - | ||
| 347 | - log_context->generate_id(); | ||
| 348 | - srs_trace("forward cycle start"); | ||
| 349 | - | ||
| 350 | - while (loop) { | ||
| 351 | - if ((ret = cycle()) != ERROR_SUCCESS) { | ||
| 352 | - srs_warn("forward cycle failed, ignored and retry, ret=%d", ret); | ||
| 353 | - } else { | ||
| 354 | - srs_info("forward cycle success, retry"); | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - if (!loop) { | ||
| 358 | - break; | ||
| 359 | - } | ||
| 360 | - | ||
| 361 | - st_usleep(SRS_FORWARDER_SLEEP_MS * 1000); | ||
| 362 | - | ||
| 363 | - if ((ret = open_socket()) != ERROR_SUCCESS) { | ||
| 364 | - srs_warn("forward cycle reopen failed, ignored and retry, ret=%d", ret); | ||
| 365 | - } else { | ||
| 366 | - srs_info("forward cycle reopen success"); | ||
| 367 | - } | ||
| 368 | - } | ||
| 369 | - srs_trace("forward cycle finished"); | ||
| 370 | -} | ||
| 371 | - | ||
| 372 | -void* SrsForwarder::forward_thread(void* arg) | ||
| 373 | -{ | ||
| 374 | - SrsForwarder* obj = (SrsForwarder*)arg; | ||
| 375 | - srs_assert(obj != NULL); | ||
| 376 | - | ||
| 377 | - obj->loop = true; | ||
| 378 | - obj->forward_cycle(); | ||
| 379 | - | ||
| 380 | - return NULL; | ||
| 381 | -} | ||
| 382 | - |
| @@ -30,19 +30,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,19 +30,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | #include <srs_core.hpp> | 30 | #include <srs_core.hpp> |
| 31 | 31 | ||
| 32 | #include <string> | 32 | #include <string> |
| 33 | -#include <vector> | ||
| 34 | 33 | ||
| 35 | -#include <st.h> | 34 | +#include <srs_core_thread.hpp> |
| 36 | 35 | ||
| 37 | class SrsSharedPtrMessage; | 36 | class SrsSharedPtrMessage; |
| 38 | class SrsOnMetaDataPacket; | 37 | class SrsOnMetaDataPacket; |
| 38 | +class SrsMessageQueue; | ||
| 39 | +class SrsRtmpJitter; | ||
| 39 | class SrsRtmpClient; | 40 | class SrsRtmpClient; |
| 40 | class SrsRequest; | 41 | class SrsRequest; |
| 42 | +class SrsSource; | ||
| 41 | 43 | ||
| 42 | /** | 44 | /** |
| 43 | * forward the stream to other servers. | 45 | * forward the stream to other servers. |
| 44 | */ | 46 | */ |
| 45 | -class SrsForwarder | 47 | +class SrsForwarder : public ISrsThreadHandler |
| 46 | { | 48 | { |
| 47 | private: | 49 | private: |
| 48 | std::string app; | 50 | std::string app; |
| @@ -53,28 +55,30 @@ private: | @@ -53,28 +55,30 @@ private: | ||
| 53 | int port; | 55 | int port; |
| 54 | private: | 56 | private: |
| 55 | st_netfd_t stfd; | 57 | st_netfd_t stfd; |
| 56 | - st_thread_t tid; | ||
| 57 | - bool loop; | 58 | + SrsThread* pthread; |
| 58 | private: | 59 | private: |
| 60 | + SrsSource* source; | ||
| 59 | SrsRtmpClient* client; | 61 | SrsRtmpClient* client; |
| 60 | - std::vector<SrsSharedPtrMessage*> msgs; | 62 | + SrsRtmpJitter* jitter; |
| 63 | + SrsMessageQueue* queue; | ||
| 61 | public: | 64 | public: |
| 62 | - SrsForwarder(); | 65 | + SrsForwarder(SrsSource* _source); |
| 63 | virtual ~SrsForwarder(); | 66 | virtual ~SrsForwarder(); |
| 64 | public: | 67 | public: |
| 68 | + virtual void set_queue_size(double queue_size); | ||
| 69 | +public: | ||
| 65 | virtual int on_publish(SrsRequest* req, std::string forward_server); | 70 | virtual int on_publish(SrsRequest* req, std::string forward_server); |
| 66 | virtual void on_unpublish(); | 71 | virtual void on_unpublish(); |
| 67 | virtual int on_meta_data(SrsSharedPtrMessage* metadata); | 72 | virtual int on_meta_data(SrsSharedPtrMessage* metadata); |
| 68 | virtual int on_audio(SrsSharedPtrMessage* msg); | 73 | virtual int on_audio(SrsSharedPtrMessage* msg); |
| 69 | virtual int on_video(SrsSharedPtrMessage* msg); | 74 | virtual int on_video(SrsSharedPtrMessage* msg); |
| 75 | +// interface ISrsThreadHandler. | ||
| 76 | +public: | ||
| 77 | + virtual int cycle(); | ||
| 70 | private: | 78 | private: |
| 71 | - virtual int open_socket(); | 79 | + virtual void close_underlayer_socket(); |
| 72 | virtual int connect_server(); | 80 | virtual int connect_server(); |
| 73 | -private: | ||
| 74 | - virtual int cycle(); | ||
| 75 | virtual int forward(); | 81 | virtual int forward(); |
| 76 | - virtual void forward_cycle(); | ||
| 77 | - static void* forward_thread(void* arg); | ||
| 78 | }; | 82 | }; |
| 79 | 83 | ||
| 80 | #endif | 84 | #endif |
| @@ -1109,10 +1109,11 @@ int SrsTSCache::cache_video(SrsCodec* codec, SrsCodecSample* sample) | @@ -1109,10 +1109,11 @@ int SrsTSCache::cache_video(SrsCodec* codec, SrsCodecSample* sample) | ||
| 1109 | return ret; | 1109 | return ret; |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
| 1112 | -SrsHls::SrsHls() | 1112 | +SrsHls::SrsHls(SrsSource* _source) |
| 1113 | { | 1113 | { |
| 1114 | hls_enabled = false; | 1114 | hls_enabled = false; |
| 1115 | 1115 | ||
| 1116 | + source = _source; | ||
| 1116 | codec = new SrsCodec(); | 1117 | codec = new SrsCodec(); |
| 1117 | sample = new SrsCodecSample(); | 1118 | sample = new SrsCodecSample(); |
| 1118 | jitter = new SrsRtmpJitter(); | 1119 | jitter = new SrsRtmpJitter(); |
| @@ -1148,7 +1149,6 @@ int SrsHls::on_publish(SrsRequest* req) | @@ -1148,7 +1149,6 @@ int SrsHls::on_publish(SrsRequest* req) | ||
| 1148 | std::string stream = req->stream; | 1149 | std::string stream = req->stream; |
| 1149 | std::string app = req->app; | 1150 | std::string app = req->app; |
| 1150 | 1151 | ||
| 1151 | - // TODO: support reload. | ||
| 1152 | if (!config->get_hls_enabled(vhost)) { | 1152 | if (!config->get_hls_enabled(vhost)) { |
| 1153 | return ret; | 1153 | return ret; |
| 1154 | } | 1154 | } |
| @@ -1156,30 +1156,11 @@ int SrsHls::on_publish(SrsRequest* req) | @@ -1156,30 +1156,11 @@ int SrsHls::on_publish(SrsRequest* req) | ||
| 1156 | // if enabled, open the muxer. | 1156 | // if enabled, open the muxer. |
| 1157 | hls_enabled = true; | 1157 | hls_enabled = true; |
| 1158 | 1158 | ||
| 1159 | - // TODO: subscribe the reload event. | ||
| 1160 | - int hls_fragment = 0; | ||
| 1161 | - int hls_window = 0; | ||
| 1162 | - | ||
| 1163 | - SrsConfDirective* conf = NULL; | ||
| 1164 | - if ((conf = config->get_hls_fragment(vhost)) != NULL && !conf->arg0().empty()) { | ||
| 1165 | - hls_fragment = ::atoi(conf->arg0().c_str()); | ||
| 1166 | - } | ||
| 1167 | - if (hls_fragment <= 0) { | ||
| 1168 | - hls_fragment = SRS_CONF_DEFAULT_HLS_FRAGMENT; | ||
| 1169 | - } | ||
| 1170 | - | ||
| 1171 | - if ((conf = config->get_hls_window(vhost)) != NULL && !conf->arg0().empty()) { | ||
| 1172 | - hls_window = ::atoi(conf->arg0().c_str()); | ||
| 1173 | - } | ||
| 1174 | - if (hls_window <= 0) { | ||
| 1175 | - hls_window = SRS_CONF_DEFAULT_HLS_WINDOW; | ||
| 1176 | - } | 1159 | + int hls_fragment = config->get_hls_fragment(vhost); |
| 1160 | + int hls_window = config->get_hls_window(vhost); | ||
| 1177 | 1161 | ||
| 1178 | // get the hls path config | 1162 | // get the hls path config |
| 1179 | - std::string hls_path = SRS_CONF_DEFAULT_HLS_PATH; | ||
| 1180 | - if ((conf = config->get_hls_path(vhost)) != NULL) { | ||
| 1181 | - hls_path = conf->arg0(); | ||
| 1182 | - } | 1163 | + std::string hls_path = config->get_hls_path(vhost); |
| 1183 | 1164 | ||
| 1184 | // open muxer | 1165 | // open muxer |
| 1185 | if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { | 1166 | if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { |
| @@ -1191,6 +1172,12 @@ int SrsHls::on_publish(SrsRequest* req) | @@ -1191,6 +1172,12 @@ int SrsHls::on_publish(SrsRequest* req) | ||
| 1191 | srs_error("m3u8 muxer open segment failed. ret=%d", ret); | 1172 | srs_error("m3u8 muxer open segment failed. ret=%d", ret); |
| 1192 | return ret; | 1173 | return ret; |
| 1193 | } | 1174 | } |
| 1175 | + | ||
| 1176 | + // notice the source to get the cached sequence header. | ||
| 1177 | + if ((ret = source->on_hls_start()) != ERROR_SUCCESS) { | ||
| 1178 | + srs_error("callback source hls start failed. ret=%d", ret); | ||
| 1179 | + return ret; | ||
| 1180 | + } | ||
| 1194 | 1181 | ||
| 1195 | return ret; | 1182 | return ret; |
| 1196 | } | 1183 | } |
| @@ -1215,16 +1202,16 @@ void SrsHls::on_unpublish() | @@ -1215,16 +1202,16 @@ void SrsHls::on_unpublish() | ||
| 1215 | hls_enabled = false; | 1202 | hls_enabled = false; |
| 1216 | } | 1203 | } |
| 1217 | 1204 | ||
| 1218 | -int SrsHls::on_meta_data(SrsOnMetaDataPacket* metadata) | 1205 | +int SrsHls::on_meta_data(SrsAmf0Object* metadata) |
| 1219 | { | 1206 | { |
| 1220 | int ret = ERROR_SUCCESS; | 1207 | int ret = ERROR_SUCCESS; |
| 1221 | 1208 | ||
| 1222 | - if (!metadata || !metadata->metadata) { | 1209 | + if (!metadata) { |
| 1223 | srs_trace("no metadata persent, hls ignored it."); | 1210 | srs_trace("no metadata persent, hls ignored it."); |
| 1224 | return ret; | 1211 | return ret; |
| 1225 | } | 1212 | } |
| 1226 | 1213 | ||
| 1227 | - SrsAmf0Object* obj = metadata->metadata; | 1214 | + SrsAmf0Object* obj = metadata; |
| 1228 | if (obj->size() <= 0) { | 1215 | if (obj->size() <= 0) { |
| 1229 | srs_trace("no metadata persent, hls ignored it."); | 1216 | srs_trace("no metadata persent, hls ignored it."); |
| 1230 | return ret; | 1217 | return ret; |
| @@ -1273,7 +1260,6 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -1273,7 +1260,6 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
| 1273 | 1260 | ||
| 1274 | SrsAutoFree(SrsSharedPtrMessage, audio, false); | 1261 | SrsAutoFree(SrsSharedPtrMessage, audio, false); |
| 1275 | 1262 | ||
| 1276 | - // TODO: maybe donot need to demux the aac? | ||
| 1277 | if (!hls_enabled) { | 1263 | if (!hls_enabled) { |
| 1278 | return ret; | 1264 | return ret; |
| 1279 | } | 1265 | } |
| @@ -1293,14 +1279,13 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -1293,14 +1279,13 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
| 1293 | return ret; | 1279 | return ret; |
| 1294 | } | 1280 | } |
| 1295 | 1281 | ||
| 1296 | - int64_t corrected_time = 0; | ||
| 1297 | - if ((ret = jitter->correct(audio, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | 1282 | + if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { |
| 1298 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); | 1283 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); |
| 1299 | return ret; | 1284 | return ret; |
| 1300 | } | 1285 | } |
| 1301 | 1286 | ||
| 1302 | // the pts calc from rtmp/flv header. | 1287 | // the pts calc from rtmp/flv header. |
| 1303 | - int64_t pts = corrected_time * 90; | 1288 | + int64_t pts = audio->header.timestamp * 90; |
| 1304 | 1289 | ||
| 1305 | if ((ret = ts_cache->write_audio(codec, muxer, pts, sample)) != ERROR_SUCCESS) { | 1290 | if ((ret = ts_cache->write_audio(codec, muxer, pts, sample)) != ERROR_SUCCESS) { |
| 1306 | srs_error("ts cache write audio failed. ret=%d", ret); | 1291 | srs_error("ts cache write audio failed. ret=%d", ret); |
| @@ -1316,7 +1301,6 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -1316,7 +1301,6 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
| 1316 | 1301 | ||
| 1317 | SrsAutoFree(SrsSharedPtrMessage, video, false); | 1302 | SrsAutoFree(SrsSharedPtrMessage, video, false); |
| 1318 | 1303 | ||
| 1319 | - // TODO: maybe donot need to demux the avc? | ||
| 1320 | if (!hls_enabled) { | 1304 | if (!hls_enabled) { |
| 1321 | return ret; | 1305 | return ret; |
| 1322 | } | 1306 | } |
| @@ -1337,24 +1321,23 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -1337,24 +1321,23 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
| 1337 | return ret; | 1321 | return ret; |
| 1338 | } | 1322 | } |
| 1339 | 1323 | ||
| 1340 | - int64_t corrected_time = 0; | ||
| 1341 | - if ((ret = jitter->correct(video, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | 1324 | + if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { |
| 1342 | srs_error("rtmp jitter correct video failed. ret=%d", ret); | 1325 | srs_error("rtmp jitter correct video failed. ret=%d", ret); |
| 1343 | return ret; | 1326 | return ret; |
| 1344 | } | 1327 | } |
| 1345 | 1328 | ||
| 1346 | - int64_t dts = corrected_time * 90; | 1329 | + int64_t dts = video->header.timestamp * 90; |
| 1347 | if ((ret = ts_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) { | 1330 | if ((ret = ts_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) { |
| 1348 | srs_error("ts cache write video failed. ret=%d", ret); | 1331 | srs_error("ts cache write video failed. ret=%d", ret); |
| 1349 | return ret; | 1332 | return ret; |
| 1350 | } | 1333 | } |
| 1351 | 1334 | ||
| 1352 | - _mpegts(); | 1335 | + hls_mux(); |
| 1353 | 1336 | ||
| 1354 | return ret; | 1337 | return ret; |
| 1355 | } | 1338 | } |
| 1356 | 1339 | ||
| 1357 | -void SrsHls::_mpegts() | 1340 | +void SrsHls::hls_mux() |
| 1358 | { | 1341 | { |
| 1359 | // reportable | 1342 | // reportable |
| 1360 | if (pithy_print->can_print()) { | 1343 | if (pithy_print->can_print()) { |
| @@ -34,16 +34,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -34,16 +34,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 34 | #include <string> | 34 | #include <string> |
| 35 | #include <vector> | 35 | #include <vector> |
| 36 | 36 | ||
| 37 | -class SrsOnMetaDataPacket; | ||
| 38 | class SrsSharedPtrMessage; | 37 | class SrsSharedPtrMessage; |
| 39 | class SrsCodecSample; | 38 | class SrsCodecSample; |
| 40 | class SrsCodecBuffer; | 39 | class SrsCodecBuffer; |
| 41 | class SrsMpegtsFrame; | 40 | class SrsMpegtsFrame; |
| 41 | +class SrsAmf0Object; | ||
| 42 | class SrsRtmpJitter; | 42 | class SrsRtmpJitter; |
| 43 | class SrsTSMuxer; | 43 | class SrsTSMuxer; |
| 44 | class SrsCodec; | 44 | class SrsCodec; |
| 45 | class SrsRequest; | 45 | class SrsRequest; |
| 46 | class SrsPithyPrint; | 46 | class SrsPithyPrint; |
| 47 | +class SrsSource; | ||
| 47 | 48 | ||
| 48 | /** | 49 | /** |
| 49 | * jitter correct for audio, | 50 | * jitter correct for audio, |
| @@ -207,21 +208,39 @@ private: | @@ -207,21 +208,39 @@ private: | ||
| 207 | SrsTSCache* ts_cache; | 208 | SrsTSCache* ts_cache; |
| 208 | private: | 209 | private: |
| 209 | bool hls_enabled; | 210 | bool hls_enabled; |
| 211 | + SrsSource* source; | ||
| 210 | SrsCodec* codec; | 212 | SrsCodec* codec; |
| 211 | SrsCodecSample* sample; | 213 | SrsCodecSample* sample; |
| 212 | SrsRtmpJitter* jitter; | 214 | SrsRtmpJitter* jitter; |
| 213 | SrsPithyPrint* pithy_print; | 215 | SrsPithyPrint* pithy_print; |
| 214 | public: | 216 | public: |
| 215 | - SrsHls(); | 217 | + SrsHls(SrsSource* _source); |
| 216 | virtual ~SrsHls(); | 218 | virtual ~SrsHls(); |
| 217 | public: | 219 | public: |
| 220 | + /** | ||
| 221 | + * publish stream event, continue to write the m3u8, | ||
| 222 | + * for the muxer object not destroyed. | ||
| 223 | + */ | ||
| 218 | virtual int on_publish(SrsRequest* req); | 224 | virtual int on_publish(SrsRequest* req); |
| 225 | + /** | ||
| 226 | + * the unpublish event, only close the muxer, donot destroy the | ||
| 227 | + * muxer, for when we continue to publish, the m3u8 will continue. | ||
| 228 | + */ | ||
| 219 | virtual void on_unpublish(); | 229 | virtual void on_unpublish(); |
| 220 | - virtual int on_meta_data(SrsOnMetaDataPacket* metadata); | 230 | + /** |
| 231 | + * get some information from metadata, it's optinal. | ||
| 232 | + */ | ||
| 233 | + virtual int on_meta_data(SrsAmf0Object* metadata); | ||
| 234 | + /** | ||
| 235 | + * mux the audio packets to ts. | ||
| 236 | + */ | ||
| 221 | virtual int on_audio(SrsSharedPtrMessage* audio); | 237 | virtual int on_audio(SrsSharedPtrMessage* audio); |
| 238 | + /** | ||
| 239 | + * mux the video packets to ts. | ||
| 240 | + */ | ||
| 222 | virtual int on_video(SrsSharedPtrMessage* video); | 241 | virtual int on_video(SrsSharedPtrMessage* video); |
| 223 | private: | 242 | private: |
| 224 | - virtual void _mpegts(); | 243 | + virtual void hls_mux(); |
| 225 | }; | 244 | }; |
| 226 | 245 | ||
| 227 | #endif | 246 | #endif |
| @@ -184,15 +184,7 @@ void SrsHttpClient::disconnect() | @@ -184,15 +184,7 @@ void SrsHttpClient::disconnect() | ||
| 184 | { | 184 | { |
| 185 | connected = false; | 185 | connected = false; |
| 186 | 186 | ||
| 187 | - if (stfd) { | ||
| 188 | - int fd = st_netfd_fileno(stfd); | ||
| 189 | - st_netfd_close(stfd); | ||
| 190 | - stfd = NULL; | ||
| 191 | - | ||
| 192 | - // st does not close it sometimes, | ||
| 193 | - // close it manually. | ||
| 194 | - ::close(fd); | ||
| 195 | - } | 187 | + srs_close_stfd(stfd); |
| 196 | } | 188 | } |
| 197 | 189 | ||
| 198 | int SrsHttpClient::connect(SrsHttpUri* uri) | 190 | int SrsHttpClient::connect(SrsHttpUri* uri) |
| @@ -29,8 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -29,8 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 29 | #include <string> | 29 | #include <string> |
| 30 | #include <map> | 30 | #include <map> |
| 31 | 31 | ||
| 32 | -#include <st.h> | ||
| 33 | - | ||
| 34 | ILogContext::ILogContext() | 32 | ILogContext::ILogContext() |
| 35 | { | 33 | { |
| 36 | } | 34 | } |
| @@ -32,13 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,13 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | #include <srs_core_error.hpp> | 32 | #include <srs_core_error.hpp> |
| 33 | 33 | ||
| 34 | #define SRS_STAGE_DEFAULT_INTERVAL_MS 1200 | 34 | #define SRS_STAGE_DEFAULT_INTERVAL_MS 1200 |
| 35 | -#define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300 | ||
| 36 | -#define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100 | ||
| 37 | -#define SRS_STAGE_FORWARDER_INTERVAL_MS 2000 | ||
| 38 | -#define SRS_STAGE_ENCODER_INTERVAL_MS 2000 | ||
| 39 | -#define SRS_STAGE_HLS_INTERVAL_MS 2000 | ||
| 40 | 35 | ||
| 41 | -struct SrsStageInfo : public SrsReloadHandler | 36 | +struct SrsStageInfo : public ISrsReloadHandler |
| 42 | { | 37 | { |
| 43 | int stage_id; | 38 | int stage_id; |
| 44 | int pithy_print_time_ms; | 39 | int pithy_print_time_ms; |
| @@ -61,43 +56,23 @@ struct SrsStageInfo : public SrsReloadHandler | @@ -61,43 +56,23 @@ struct SrsStageInfo : public SrsReloadHandler | ||
| 61 | { | 56 | { |
| 62 | switch (stage_id) { | 57 | switch (stage_id) { |
| 63 | case SRS_STAGE_PLAY_USER: { | 58 | case SRS_STAGE_PLAY_USER: { |
| 64 | - pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS; | ||
| 65 | - SrsConfDirective* conf = config->get_pithy_print_play(); | ||
| 66 | - if (conf && !conf->arg0().empty()) { | ||
| 67 | - pithy_print_time_ms = ::atoi(conf->arg0().c_str()); | ||
| 68 | - } | 59 | + pithy_print_time_ms = config->get_pithy_print_play(); |
| 69 | break; | 60 | break; |
| 70 | } | 61 | } |
| 71 | case SRS_STAGE_PUBLISH_USER: { | 62 | case SRS_STAGE_PUBLISH_USER: { |
| 72 | - pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS; | ||
| 73 | - SrsConfDirective* conf = config->get_pithy_print_publish(); | ||
| 74 | - if (conf && !conf->arg0().empty()) { | ||
| 75 | - pithy_print_time_ms = ::atoi(conf->arg0().c_str()); | ||
| 76 | - } | 63 | + pithy_print_time_ms = config->get_pithy_print_publish(); |
| 77 | break; | 64 | break; |
| 78 | } | 65 | } |
| 79 | case SRS_STAGE_FORWARDER: { | 66 | case SRS_STAGE_FORWARDER: { |
| 80 | - pithy_print_time_ms = SRS_STAGE_FORWARDER_INTERVAL_MS; | ||
| 81 | - SrsConfDirective* conf = config->get_pithy_print_forwarder(); | ||
| 82 | - if (conf && !conf->arg0().empty()) { | ||
| 83 | - pithy_print_time_ms = ::atoi(conf->arg0().c_str()); | ||
| 84 | - } | 67 | + pithy_print_time_ms = config->get_pithy_print_forwarder(); |
| 85 | break; | 68 | break; |
| 86 | } | 69 | } |
| 87 | case SRS_STAGE_ENCODER: { | 70 | case SRS_STAGE_ENCODER: { |
| 88 | - pithy_print_time_ms = SRS_STAGE_ENCODER_INTERVAL_MS; | ||
| 89 | - SrsConfDirective* conf = config->get_pithy_print_encoder(); | ||
| 90 | - if (conf && !conf->arg0().empty()) { | ||
| 91 | - pithy_print_time_ms = ::atoi(conf->arg0().c_str()); | ||
| 92 | - } | 71 | + pithy_print_time_ms = config->get_pithy_print_encoder(); |
| 93 | break; | 72 | break; |
| 94 | } | 73 | } |
| 95 | case SRS_STAGE_HLS: { | 74 | case SRS_STAGE_HLS: { |
| 96 | - pithy_print_time_ms = SRS_STAGE_HLS_INTERVAL_MS; | ||
| 97 | - SrsConfDirective* conf = config->get_pithy_print_hls(); | ||
| 98 | - if (conf && !conf->arg0().empty()) { | ||
| 99 | - pithy_print_time_ms = ::atoi(conf->arg0().c_str()); | ||
| 100 | - } | 75 | + pithy_print_time_ms = config->get_pithy_print_hls(); |
| 101 | break; | 76 | break; |
| 102 | } | 77 | } |
| 103 | default: { | 78 | default: { |
| @@ -307,6 +307,11 @@ void SrsProtocol::set_send_timeout(int64_t timeout_us) | @@ -307,6 +307,11 @@ void SrsProtocol::set_send_timeout(int64_t timeout_us) | ||
| 307 | return skt->set_send_timeout(timeout_us); | 307 | return skt->set_send_timeout(timeout_us); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | +int64_t SrsProtocol::get_send_timeout() | ||
| 311 | +{ | ||
| 312 | + return skt->get_send_timeout(); | ||
| 313 | +} | ||
| 314 | + | ||
| 310 | int64_t SrsProtocol::get_recv_bytes() | 315 | int64_t SrsProtocol::get_recv_bytes() |
| 311 | { | 316 | { |
| 312 | return skt->get_recv_bytes(); | 317 | return skt->get_recv_bytes(); |
| @@ -349,7 +354,7 @@ int SrsProtocol::recv_message(SrsCommonMessage** pmsg) | @@ -349,7 +354,7 @@ int SrsProtocol::recv_message(SrsCommonMessage** pmsg) | ||
| 349 | } | 354 | } |
| 350 | 355 | ||
| 351 | if (msg->size <= 0 || msg->header.payload_length <= 0) { | 356 | if (msg->size <= 0 || msg->header.payload_length <= 0) { |
| 352 | - srs_trace("ignore empty message(type=%d, size=%d, time=%d, sid=%d).", | 357 | + srs_trace("ignore empty message(type=%d, size=%d, time=%"PRId64", sid=%d).", |
| 353 | msg->header.message_type, msg->header.payload_length, | 358 | msg->header.message_type, msg->header.payload_length, |
| 354 | msg->header.timestamp, msg->header.stream_id); | 359 | msg->header.timestamp, msg->header.stream_id); |
| 355 | srs_freep(msg); | 360 | srs_freep(msg); |
| @@ -400,12 +405,13 @@ int SrsProtocol::send_message(ISrsMessage* msg) | @@ -400,12 +405,13 @@ int SrsProtocol::send_message(ISrsMessage* msg) | ||
| 400 | 405 | ||
| 401 | // chunk message header, 11 bytes | 406 | // chunk message header, 11 bytes |
| 402 | // timestamp, 3bytes, big-endian | 407 | // timestamp, 3bytes, big-endian |
| 403 | - if (msg->header.timestamp >= RTMP_EXTENDED_TIMESTAMP) { | 408 | + u_int32_t timestamp = (u_int32_t)msg->header.timestamp; |
| 409 | + if (timestamp >= RTMP_EXTENDED_TIMESTAMP) { | ||
| 404 | *pheader++ = 0xFF; | 410 | *pheader++ = 0xFF; |
| 405 | *pheader++ = 0xFF; | 411 | *pheader++ = 0xFF; |
| 406 | *pheader++ = 0xFF; | 412 | *pheader++ = 0xFF; |
| 407 | } else { | 413 | } else { |
| 408 | - pp = (char*)&msg->header.timestamp; | 414 | + pp = (char*)×tamp; |
| 409 | *pheader++ = pp[2]; | 415 | *pheader++ = pp[2]; |
| 410 | *pheader++ = pp[1]; | 416 | *pheader++ = pp[1]; |
| 411 | *pheader++ = pp[0]; | 417 | *pheader++ = pp[0]; |
| @@ -428,8 +434,8 @@ int SrsProtocol::send_message(ISrsMessage* msg) | @@ -428,8 +434,8 @@ int SrsProtocol::send_message(ISrsMessage* msg) | ||
| 428 | *pheader++ = pp[3]; | 434 | *pheader++ = pp[3]; |
| 429 | 435 | ||
| 430 | // chunk extended timestamp header, 0 or 4 bytes, big-endian | 436 | // chunk extended timestamp header, 0 or 4 bytes, big-endian |
| 431 | - if(msg->header.timestamp >= RTMP_EXTENDED_TIMESTAMP){ | ||
| 432 | - pp = (char*)&msg->header.timestamp; | 437 | + if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ |
| 438 | + pp = (char*)×tamp; | ||
| 433 | *pheader++ = pp[3]; | 439 | *pheader++ = pp[3]; |
| 434 | *pheader++ = pp[2]; | 440 | *pheader++ = pp[2]; |
| 435 | *pheader++ = pp[1]; | 441 | *pheader++ = pp[1]; |
| @@ -456,8 +462,9 @@ int SrsProtocol::send_message(ISrsMessage* msg) | @@ -456,8 +462,9 @@ int SrsProtocol::send_message(ISrsMessage* msg) | ||
| 456 | // must send the extended-timestamp to flash-player. | 462 | // must send the extended-timestamp to flash-player. |
| 457 | // @see: ngx_rtmp_prepare_message | 463 | // @see: ngx_rtmp_prepare_message |
| 458 | // @see: http://blog.csdn.net/win_lin/article/details/13363699 | 464 | // @see: http://blog.csdn.net/win_lin/article/details/13363699 |
| 459 | - if(msg->header.timestamp >= RTMP_EXTENDED_TIMESTAMP){ | ||
| 460 | - pp = (char*)&msg->header.timestamp; | 465 | + u_int32_t timestamp = (u_int32_t)msg->header.timestamp; |
| 466 | + if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ | ||
| 467 | + pp = (char*)×tamp; | ||
| 461 | *pheader++ = pp[3]; | 468 | *pheader++ = pp[3]; |
| 462 | *pheader++ = pp[2]; | 469 | *pheader++ = pp[2]; |
| 463 | *pheader++ = pp[1]; | 470 | *pheader++ = pp[1]; |
| @@ -697,7 +704,7 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | @@ -697,7 +704,7 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | ||
| 697 | srs_verbose("cache new chunk stream: fmt=%d, cid=%d", fmt, cid); | 704 | srs_verbose("cache new chunk stream: fmt=%d, cid=%d", fmt, cid); |
| 698 | } else { | 705 | } else { |
| 699 | chunk = chunk_streams[cid]; | 706 | chunk = chunk_streams[cid]; |
| 700 | - srs_verbose("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)", | 707 | + srs_verbose("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", |
| 701 | chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length, | 708 | chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length, |
| 702 | chunk->header.timestamp, chunk->header.stream_id); | 709 | chunk->header.timestamp, chunk->header.stream_id); |
| 703 | } | 710 | } |
| @@ -711,7 +718,7 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | @@ -711,7 +718,7 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | ||
| 711 | return ret; | 718 | return ret; |
| 712 | } | 719 | } |
| 713 | srs_verbose("read message header success. " | 720 | srs_verbose("read message header success. " |
| 714 | - "fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)", | 721 | + "fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", |
| 715 | fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, | 722 | fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, |
| 716 | chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); | 723 | chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); |
| 717 | 724 | ||
| @@ -733,14 +740,14 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | @@ -733,14 +740,14 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) | ||
| 733 | 740 | ||
| 734 | // not got an entire RTMP message, try next chunk. | 741 | // not got an entire RTMP message, try next chunk. |
| 735 | if (!msg) { | 742 | if (!msg) { |
| 736 | - srs_verbose("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)", | 743 | + srs_verbose("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", |
| 737 | payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, | 744 | payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, |
| 738 | chunk->header.timestamp, chunk->header.stream_id); | 745 | chunk->header.timestamp, chunk->header.stream_id); |
| 739 | return ret; | 746 | return ret; |
| 740 | } | 747 | } |
| 741 | 748 | ||
| 742 | *pmsg = msg; | 749 | *pmsg = msg; |
| 743 | - srs_info("get entire message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)", | 750 | + srs_info("get entire message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", |
| 744 | payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, | 751 | payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, |
| 745 | chunk->header.timestamp, chunk->header.stream_id); | 752 | chunk->header.timestamp, chunk->header.stream_id); |
| 746 | 753 | ||
| @@ -947,16 +954,16 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -947,16 +954,16 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 947 | pp[1] = *p++; | 954 | pp[1] = *p++; |
| 948 | pp[2] = *p++; | 955 | pp[2] = *p++; |
| 949 | pp[3] = *p++; | 956 | pp[3] = *p++; |
| 950 | - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d, payload=%d, type=%d, sid=%d", | 957 | + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d, sid=%d", |
| 951 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, | 958 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, |
| 952 | chunk->header.message_type, chunk->header.stream_id); | 959 | chunk->header.message_type, chunk->header.stream_id); |
| 953 | } else { | 960 | } else { |
| 954 | - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d, payload=%d, type=%d", | 961 | + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d", |
| 955 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, | 962 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, |
| 956 | chunk->header.message_type); | 963 | chunk->header.message_type); |
| 957 | } | 964 | } |
| 958 | } else { | 965 | } else { |
| 959 | - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d", | 966 | + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64"", |
| 960 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp); | 967 | fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp); |
| 961 | } | 968 | } |
| 962 | } else { | 969 | } else { |
| @@ -981,7 +988,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -981,7 +988,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 981 | 988 | ||
| 982 | // ffmpeg/librtmp may donot send this filed, need to detect the value. | 989 | // ffmpeg/librtmp may donot send this filed, need to detect the value. |
| 983 | // @see also: http://blog.csdn.net/win_lin/article/details/13363699 | 990 | // @see also: http://blog.csdn.net/win_lin/article/details/13363699 |
| 984 | - int32_t timestamp = 0x00; | 991 | + u_int32_t timestamp = 0x00; |
| 985 | char* pp = (char*)×tamp; | 992 | char* pp = (char*)×tamp; |
| 986 | pp[3] = *p++; | 993 | pp[3] = *p++; |
| 987 | pp[2] = *p++; | 994 | pp[2] = *p++; |
| @@ -990,14 +997,14 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -990,14 +997,14 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 990 | 997 | ||
| 991 | // compare to the chunk timestamp, which is set by chunk message header | 998 | // compare to the chunk timestamp, which is set by chunk message header |
| 992 | // type 0,1 or 2. | 999 | // type 0,1 or 2. |
| 993 | - int32_t chunk_timestamp = chunk->header.timestamp; | 1000 | + u_int32_t chunk_timestamp = chunk->header.timestamp; |
| 994 | if (chunk_timestamp > RTMP_EXTENDED_TIMESTAMP && chunk_timestamp != timestamp) { | 1001 | if (chunk_timestamp > RTMP_EXTENDED_TIMESTAMP && chunk_timestamp != timestamp) { |
| 995 | mh_size -= 4; | 1002 | mh_size -= 4; |
| 996 | srs_verbose("ignore the 4bytes extended timestamp. mh_size=%d", mh_size); | 1003 | srs_verbose("ignore the 4bytes extended timestamp. mh_size=%d", mh_size); |
| 997 | } else { | 1004 | } else { |
| 998 | chunk->header.timestamp = timestamp; | 1005 | chunk->header.timestamp = timestamp; |
| 999 | } | 1006 | } |
| 1000 | - srs_verbose("header read ext_time completed. time=%d", chunk->header.timestamp); | 1007 | + srs_verbose("header read ext_time completed. time=%"PRId64"", chunk->header.timestamp); |
| 1001 | } | 1008 | } |
| 1002 | 1009 | ||
| 1003 | // valid message | 1010 | // valid message |
| @@ -1027,7 +1034,7 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh | @@ -1027,7 +1034,7 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh | ||
| 1027 | buffer->erase(bh_size + mh_size); | 1034 | buffer->erase(bh_size + mh_size); |
| 1028 | 1035 | ||
| 1029 | srs_trace("get an empty RTMP " | 1036 | srs_trace("get an empty RTMP " |
| 1030 | - "message(type=%d, size=%d, time=%d, sid=%d)", chunk->header.message_type, | 1037 | + "message(type=%d, size=%d, time=%"PRId64", sid=%d)", chunk->header.message_type, |
| 1031 | chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); | 1038 | chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); |
| 1032 | 1039 | ||
| 1033 | *pmsg = chunk->msg; | 1040 | *pmsg = chunk->msg; |
| @@ -1068,13 +1075,13 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh | @@ -1068,13 +1075,13 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh | ||
| 1068 | if (chunk->header.payload_length == chunk->msg->size) { | 1075 | if (chunk->header.payload_length == chunk->msg->size) { |
| 1069 | *pmsg = chunk->msg; | 1076 | *pmsg = chunk->msg; |
| 1070 | chunk->msg = NULL; | 1077 | chunk->msg = NULL; |
| 1071 | - srs_verbose("get entire RTMP message(type=%d, size=%d, time=%d, sid=%d)", | 1078 | + srs_verbose("get entire RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d)", |
| 1072 | chunk->header.message_type, chunk->header.payload_length, | 1079 | chunk->header.message_type, chunk->header.payload_length, |
| 1073 | chunk->header.timestamp, chunk->header.stream_id); | 1080 | chunk->header.timestamp, chunk->header.stream_id); |
| 1074 | return ret; | 1081 | return ret; |
| 1075 | } | 1082 | } |
| 1076 | 1083 | ||
| 1077 | - srs_verbose("get partial RTMP message(type=%d, size=%d, time=%d, sid=%d), partial size=%d", | 1084 | + srs_verbose("get partial RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d), partial size=%d", |
| 1078 | chunk->header.message_type, chunk->header.payload_length, | 1085 | chunk->header.message_type, chunk->header.payload_length, |
| 1079 | chunk->header.timestamp, chunk->header.stream_id, | 1086 | chunk->header.timestamp, chunk->header.stream_id, |
| 1080 | chunk->msg->size); | 1087 | chunk->msg->size); |
| @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | #include <map> | 33 | #include <map> |
| 34 | #include <string> | 34 | #include <string> |
| 35 | 35 | ||
| 36 | -#include <st.h> | ||
| 37 | - | ||
| 38 | #include <srs_core_log.hpp> | 36 | #include <srs_core_log.hpp> |
| 39 | #include <srs_core_error.hpp> | 37 | #include <srs_core_error.hpp> |
| 40 | 38 | ||
| @@ -117,6 +115,7 @@ public: | @@ -117,6 +115,7 @@ public: | ||
| 117 | virtual void set_recv_timeout(int64_t timeout_us); | 115 | virtual void set_recv_timeout(int64_t timeout_us); |
| 118 | virtual int64_t get_recv_timeout(); | 116 | virtual int64_t get_recv_timeout(); |
| 119 | virtual void set_send_timeout(int64_t timeout_us); | 117 | virtual void set_send_timeout(int64_t timeout_us); |
| 118 | + virtual int64_t get_send_timeout(); | ||
| 120 | virtual int64_t get_recv_bytes(); | 119 | virtual int64_t get_recv_bytes(); |
| 121 | virtual int64_t get_send_bytes(); | 120 | virtual int64_t get_send_bytes(); |
| 122 | virtual int get_recv_kbps(); | 121 | virtual int get_recv_kbps(); |
| @@ -205,8 +204,9 @@ struct SrsMessageHeader | @@ -205,8 +204,9 @@ struct SrsMessageHeader | ||
| 205 | * Four-byte field that contains a timestamp of the message. | 204 | * Four-byte field that contains a timestamp of the message. |
| 206 | * The 4 bytes are packed in the big-endian order. | 205 | * The 4 bytes are packed in the big-endian order. |
| 207 | * @remark, used as calc timestamp when decode and encode time. | 206 | * @remark, used as calc timestamp when decode and encode time. |
| 207 | + * @remark, we use 64bits for large time for jitter detect and hls. | ||
| 208 | */ | 208 | */ |
| 209 | - u_int32_t timestamp; | 209 | + int64_t timestamp; |
| 210 | 210 | ||
| 211 | SrsMessageHeader(); | 211 | SrsMessageHeader(); |
| 212 | virtual ~SrsMessageHeader(); | 212 | virtual ~SrsMessageHeader(); |
| @@ -1156,7 +1156,7 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** | @@ -1156,7 +1156,7 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** | ||
| 1156 | T* pkt = dynamic_cast<T*>(msg->get_packet()); | 1156 | T* pkt = dynamic_cast<T*>(msg->get_packet()); |
| 1157 | if (!pkt) { | 1157 | if (!pkt) { |
| 1158 | delete msg; | 1158 | delete msg; |
| 1159 | - srs_trace("drop message(type=%d, size=%d, time=%d, sid=%d).", | 1159 | + srs_trace("drop message(type=%d, size=%d, time=%"PRId64", sid=%d).", |
| 1160 | msg->header.message_type, msg->header.payload_length, | 1160 | msg->header.message_type, msg->header.payload_length, |
| 1161 | msg->header.timestamp, msg->header.stream_id); | 1161 | msg->header.timestamp, msg->header.stream_id); |
| 1162 | continue; | 1162 | continue; |
| @@ -23,22 +23,54 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -23,22 +23,54 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | 23 | ||
| 24 | #include <srs_core_reload.hpp> | 24 | #include <srs_core_reload.hpp> |
| 25 | 25 | ||
| 26 | +using namespace std; | ||
| 27 | + | ||
| 26 | #include <srs_core_error.hpp> | 28 | #include <srs_core_error.hpp> |
| 27 | 29 | ||
| 28 | -SrsReloadHandler::SrsReloadHandler() | 30 | +ISrsReloadHandler::ISrsReloadHandler() |
| 31 | +{ | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +ISrsReloadHandler::~ISrsReloadHandler() | ||
| 29 | { | 35 | { |
| 30 | } | 36 | } |
| 31 | 37 | ||
| 32 | -SrsReloadHandler::~SrsReloadHandler() | 38 | +int ISrsReloadHandler::on_reload_listen() |
| 33 | { | 39 | { |
| 40 | + return ERROR_SUCCESS; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +int ISrsReloadHandler::on_reload_pithy_print() | ||
| 44 | +{ | ||
| 45 | + return ERROR_SUCCESS; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/) | ||
| 49 | +{ | ||
| 50 | + return ERROR_SUCCESS; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/) | ||
| 54 | +{ | ||
| 55 | + return ERROR_SUCCESS; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/) | ||
| 59 | +{ | ||
| 60 | + return ERROR_SUCCESS; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +int ISrsReloadHandler::on_reload_forward(string /*vhost*/) | ||
| 64 | +{ | ||
| 65 | + return ERROR_SUCCESS; | ||
| 34 | } | 66 | } |
| 35 | 67 | ||
| 36 | -int SrsReloadHandler::on_reload_listen() | 68 | +int ISrsReloadHandler::on_reload_hls(string /*vhost*/) |
| 37 | { | 69 | { |
| 38 | return ERROR_SUCCESS; | 70 | return ERROR_SUCCESS; |
| 39 | } | 71 | } |
| 40 | 72 | ||
| 41 | -int SrsReloadHandler::on_reload_pithy_print() | 73 | +int ISrsReloadHandler::on_reload_transcode(string /*vhost*/) |
| 42 | { | 74 | { |
| 43 | return ERROR_SUCCESS; | 75 | return ERROR_SUCCESS; |
| 44 | } | 76 | } |
| @@ -29,17 +29,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -29,17 +29,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 29 | */ | 29 | */ |
| 30 | #include <srs_core.hpp> | 30 | #include <srs_core.hpp> |
| 31 | 31 | ||
| 32 | +#include <string> | ||
| 33 | + | ||
| 32 | /** | 34 | /** |
| 33 | * the handler for config reload. | 35 | * the handler for config reload. |
| 34 | */ | 36 | */ |
| 35 | -class SrsReloadHandler | 37 | +class ISrsReloadHandler |
| 36 | { | 38 | { |
| 37 | public: | 39 | public: |
| 38 | - SrsReloadHandler(); | ||
| 39 | - virtual ~SrsReloadHandler(); | 40 | + ISrsReloadHandler(); |
| 41 | + virtual ~ISrsReloadHandler(); | ||
| 40 | public: | 42 | public: |
| 41 | virtual int on_reload_listen(); | 43 | virtual int on_reload_listen(); |
| 42 | virtual int on_reload_pithy_print(); | 44 | virtual int on_reload_pithy_print(); |
| 45 | + virtual int on_reload_vhost_removed(std::string vhost); | ||
| 46 | + virtual int on_reload_gop_cache(std::string vhost); | ||
| 47 | + virtual int on_reload_queue_length(std::string vhost); | ||
| 48 | + virtual int on_reload_forward(std::string vhost); | ||
| 49 | + virtual int on_reload_hls(std::string vhost); | ||
| 50 | + virtual int on_reload_transcode(std::string vhost); | ||
| 43 | }; | 51 | }; |
| 44 | 52 | ||
| 45 | #endif | 53 | #endif |
| @@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | #include <srs_core_handshake.hpp> | 33 | #include <srs_core_handshake.hpp> |
| 34 | #include <srs_core_config.hpp> | 34 | #include <srs_core_config.hpp> |
| 35 | 35 | ||
| 36 | +using namespace std; | ||
| 37 | + | ||
| 36 | /** | 38 | /** |
| 37 | * the signature for packets to client. | 39 | * the signature for packets to client. |
| 38 | */ | 40 | */ |
| @@ -79,6 +81,23 @@ SrsRequest::~SrsRequest() | @@ -79,6 +81,23 @@ SrsRequest::~SrsRequest() | ||
| 79 | { | 81 | { |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 84 | +SrsRequest* SrsRequest::copy() | ||
| 85 | +{ | ||
| 86 | + SrsRequest* cp = new SrsRequest(); | ||
| 87 | + | ||
| 88 | + cp->app = app; | ||
| 89 | + cp->objectEncoding = objectEncoding; | ||
| 90 | + cp->pageUrl = pageUrl; | ||
| 91 | + cp->port = port; | ||
| 92 | + cp->schema = schema; | ||
| 93 | + cp->stream = stream; | ||
| 94 | + cp->swfUrl = swfUrl; | ||
| 95 | + cp->tcUrl = tcUrl; | ||
| 96 | + cp->vhost = vhost; | ||
| 97 | + | ||
| 98 | + return cp; | ||
| 99 | +} | ||
| 100 | + | ||
| 82 | int SrsRequest::discovery_app() | 101 | int SrsRequest::discovery_app() |
| 83 | { | 102 | { |
| 84 | int ret = ERROR_SUCCESS; | 103 | int ret = ERROR_SUCCESS; |
| @@ -125,6 +144,8 @@ int SrsRequest::discovery_app() | @@ -125,6 +144,8 @@ int SrsRequest::discovery_app() | ||
| 125 | if (parsed_vhost) { | 144 | if (parsed_vhost) { |
| 126 | vhost = parsed_vhost->arg0(); | 145 | vhost = parsed_vhost->arg0(); |
| 127 | } | 146 | } |
| 147 | + | ||
| 148 | + // TODO: discovery the params of vhost. | ||
| 128 | 149 | ||
| 129 | srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", | 150 | srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", |
| 130 | schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); | 151 | schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); |
| @@ -142,7 +163,7 @@ int SrsRequest::discovery_app() | @@ -142,7 +163,7 @@ int SrsRequest::discovery_app() | ||
| 142 | return ret; | 163 | return ret; |
| 143 | } | 164 | } |
| 144 | 165 | ||
| 145 | -std::string SrsRequest::get_stream_url() | 166 | +string SrsRequest::get_stream_url() |
| 146 | { | 167 | { |
| 147 | std::string url = ""; | 168 | std::string url = ""; |
| 148 | 169 | ||
| @@ -162,7 +183,7 @@ void SrsRequest::strip() | @@ -162,7 +183,7 @@ void SrsRequest::strip() | ||
| 162 | trim(stream, "/ \n\r\t"); | 183 | trim(stream, "/ \n\r\t"); |
| 163 | } | 184 | } |
| 164 | 185 | ||
| 165 | -std::string& SrsRequest::trim(std::string& str, std::string chs) | 186 | +std::string& SrsRequest::trim(string& str, string chs) |
| 166 | { | 187 | { |
| 167 | for (int i = 0; i < (int)chs.length(); i++) { | 188 | for (int i = 0; i < (int)chs.length(); i++) { |
| 168 | char ch = chs.at(i); | 189 | char ch = chs.at(i); |
| @@ -245,6 +266,9 @@ int SrsRtmpClient::handshake() | @@ -245,6 +266,9 @@ int SrsRtmpClient::handshake() | ||
| 245 | 266 | ||
| 246 | SrsSocket skt(stfd); | 267 | SrsSocket skt(stfd); |
| 247 | 268 | ||
| 269 | + skt.set_recv_timeout(protocol->get_recv_timeout()); | ||
| 270 | + skt.set_send_timeout(protocol->get_send_timeout()); | ||
| 271 | + | ||
| 248 | SrsComplexHandshake complex_hs; | 272 | SrsComplexHandshake complex_hs; |
| 249 | SrsSimpleHandshake simple_hs; | 273 | SrsSimpleHandshake simple_hs; |
| 250 | if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { | 274 | if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { |
| @@ -436,6 +460,11 @@ void SrsRtmp::set_send_timeout(int64_t timeout_us) | @@ -436,6 +460,11 @@ void SrsRtmp::set_send_timeout(int64_t timeout_us) | ||
| 436 | protocol->set_send_timeout(timeout_us); | 460 | protocol->set_send_timeout(timeout_us); |
| 437 | } | 461 | } |
| 438 | 462 | ||
| 463 | +int64_t SrsRtmp::get_send_timeout() | ||
| 464 | +{ | ||
| 465 | + return protocol->get_send_timeout(); | ||
| 466 | +} | ||
| 467 | + | ||
| 439 | int64_t SrsRtmp::get_recv_bytes() | 468 | int64_t SrsRtmp::get_recv_bytes() |
| 440 | { | 469 | { |
| 441 | return protocol->get_recv_bytes(); | 470 | return protocol->get_recv_bytes(); |
| @@ -472,6 +501,9 @@ int SrsRtmp::handshake() | @@ -472,6 +501,9 @@ int SrsRtmp::handshake() | ||
| 472 | 501 | ||
| 473 | SrsSocket skt(stfd); | 502 | SrsSocket skt(stfd); |
| 474 | 503 | ||
| 504 | + skt.set_recv_timeout(protocol->get_recv_timeout()); | ||
| 505 | + skt.set_send_timeout(protocol->get_send_timeout()); | ||
| 506 | + | ||
| 475 | SrsComplexHandshake complex_hs; | 507 | SrsComplexHandshake complex_hs; |
| 476 | SrsSimpleHandshake simple_hs; | 508 | SrsSimpleHandshake simple_hs; |
| 477 | if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { | 509 | if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { |
| @@ -1127,7 +1159,7 @@ int SrsRtmp::start_bandwidth_check(int max_play_kbps, int max_pub_kbps) | @@ -1127,7 +1159,7 @@ int SrsRtmp::start_bandwidth_check(int max_play_kbps, int max_pub_kbps) | ||
| 1127 | return ret; | 1159 | return ret; |
| 1128 | } | 1160 | } |
| 1129 | 1161 | ||
| 1130 | -int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) | 1162 | +int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, string& stream_name) |
| 1131 | { | 1163 | { |
| 1132 | int ret = ERROR_SUCCESS; | 1164 | int ret = ERROR_SUCCESS; |
| 1133 | 1165 | ||
| @@ -1184,7 +1216,7 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea | @@ -1184,7 +1216,7 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea | ||
| 1184 | return ret; | 1216 | return ret; |
| 1185 | } | 1217 | } |
| 1186 | 1218 | ||
| 1187 | -int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name) | 1219 | +int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, string& stream_name) |
| 1188 | { | 1220 | { |
| 1189 | int ret = ERROR_SUCCESS; | 1221 | int ret = ERROR_SUCCESS; |
| 1190 | 1222 | ||
| @@ -1208,7 +1240,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType | @@ -1208,7 +1240,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType | ||
| 1208 | return ret; | 1240 | return ret; |
| 1209 | } | 1241 | } |
| 1210 | 1242 | ||
| 1211 | -int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name) | 1243 | +int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, string& stream_name) |
| 1212 | { | 1244 | { |
| 1213 | int ret = ERROR_SUCCESS; | 1245 | int ret = ERROR_SUCCESS; |
| 1214 | 1246 |
| @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | 33 | ||
| 34 | #include <string> | 34 | #include <string> |
| 35 | 35 | ||
| 36 | -#include <st.h> | ||
| 37 | - | ||
| 38 | class SrsProtocol; | 36 | class SrsProtocol; |
| 39 | class ISrsMessage; | 37 | class ISrsMessage; |
| 40 | class SrsCommonMessage; | 38 | class SrsCommonMessage; |
| @@ -69,6 +67,13 @@ struct SrsRequest | @@ -69,6 +67,13 @@ struct SrsRequest | ||
| 69 | 67 | ||
| 70 | SrsRequest(); | 68 | SrsRequest(); |
| 71 | virtual ~SrsRequest(); | 69 | virtual ~SrsRequest(); |
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * deep copy the request, for source to use it to support reload, | ||
| 73 | + * for when initialize the source, the request is valid, | ||
| 74 | + * when reload it, the request maybe invalid, so need to copy it. | ||
| 75 | + */ | ||
| 76 | + virtual SrsRequest* copy(); | ||
| 72 | 77 | ||
| 73 | /** | 78 | /** |
| 74 | * disconvery vhost/app from tcUrl. | 79 | * disconvery vhost/app from tcUrl. |
| @@ -148,6 +153,7 @@ public: | @@ -148,6 +153,7 @@ public: | ||
| 148 | virtual void set_recv_timeout(int64_t timeout_us); | 153 | virtual void set_recv_timeout(int64_t timeout_us); |
| 149 | virtual int64_t get_recv_timeout(); | 154 | virtual int64_t get_recv_timeout(); |
| 150 | virtual void set_send_timeout(int64_t timeout_us); | 155 | virtual void set_send_timeout(int64_t timeout_us); |
| 156 | + virtual int64_t get_send_timeout(); | ||
| 151 | virtual int64_t get_recv_bytes(); | 157 | virtual int64_t get_recv_bytes(); |
| 152 | virtual int64_t get_send_bytes(); | 158 | virtual int64_t get_send_bytes(); |
| 153 | virtual int get_recv_kbps(); | 159 | virtual int get_recv_kbps(); |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <algorithm> | 31 | #include <algorithm> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | #include <srs_core_log.hpp> | 33 | #include <srs_core_log.hpp> |
| 36 | #include <srs_core_error.hpp> | 34 | #include <srs_core_error.hpp> |
| 37 | #include <srs_core_client.hpp> | 35 | #include <srs_core_client.hpp> |
| @@ -48,24 +46,16 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) | @@ -48,24 +46,16 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) | ||
| 48 | port = 0; | 46 | port = 0; |
| 49 | server = _server; | 47 | server = _server; |
| 50 | type = _type; | 48 | type = _type; |
| 51 | - | ||
| 52 | - tid = NULL; | ||
| 53 | - loop = false; | 49 | + |
| 50 | + pthread = new SrsThread(this, 0); | ||
| 54 | } | 51 | } |
| 55 | 52 | ||
| 56 | SrsListener::~SrsListener() | 53 | SrsListener::~SrsListener() |
| 57 | { | 54 | { |
| 58 | - if (stfd) { | ||
| 59 | - st_netfd_close(stfd); | ||
| 60 | - stfd = NULL; | ||
| 61 | - } | 55 | + srs_close_stfd(stfd); |
| 62 | 56 | ||
| 63 | - if (tid) { | ||
| 64 | - loop = false; | ||
| 65 | - st_thread_interrupt(tid); | ||
| 66 | - st_thread_join(tid, NULL); | ||
| 67 | - tid = NULL; | ||
| 68 | - } | 57 | + pthread->stop(); |
| 58 | + srs_freep(pthread); | ||
| 69 | 59 | ||
| 70 | // st does not close it sometimes, | 60 | // st does not close it sometimes, |
| 71 | // close it manually. | 61 | // close it manually. |
| @@ -118,8 +108,7 @@ int SrsListener::listen(int _port) | @@ -118,8 +108,7 @@ int SrsListener::listen(int _port) | ||
| 118 | } | 108 | } |
| 119 | srs_verbose("st open socket success. fd=%d", fd); | 109 | srs_verbose("st open socket success. fd=%d", fd); |
| 120 | 110 | ||
| 121 | - if ((tid = st_thread_create(listen_thread, this, 1, 0)) == NULL) { | ||
| 122 | - ret = ERROR_ST_CREATE_LISTEN_THREAD; | 111 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { |
| 123 | srs_error("st_thread_create listen thread error. ret=%d", ret); | 112 | srs_error("st_thread_create listen thread error. ret=%d", ret); |
| 124 | return ret; | 113 | return ret; |
| 125 | } | 114 | } |
| @@ -130,41 +119,32 @@ int SrsListener::listen(int _port) | @@ -130,41 +119,32 @@ int SrsListener::listen(int _port) | ||
| 130 | return ret; | 119 | return ret; |
| 131 | } | 120 | } |
| 132 | 121 | ||
| 133 | -void SrsListener::listen_cycle() | 122 | +void SrsListener::on_enter_loop() |
| 134 | { | 123 | { |
| 135 | - int ret = ERROR_SUCCESS; | ||
| 136 | - | ||
| 137 | - log_context->generate_id(); | ||
| 138 | srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); | 124 | srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); |
| 139 | - | ||
| 140 | - while (loop) { | ||
| 141 | - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); | ||
| 142 | - | ||
| 143 | - if(client_stfd == NULL){ | ||
| 144 | - // ignore error. | ||
| 145 | - srs_warn("ignore accept thread stoppped for accept client error"); | ||
| 146 | - continue; | ||
| 147 | - } | ||
| 148 | - srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); | ||
| 149 | - | ||
| 150 | - if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { | ||
| 151 | - srs_warn("accept client error. ret=%d", ret); | ||
| 152 | - continue; | ||
| 153 | - } | ||
| 154 | - | ||
| 155 | - srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); | ||
| 156 | - } | ||
| 157 | } | 125 | } |
| 158 | 126 | ||
| 159 | -void* SrsListener::listen_thread(void* arg) | 127 | +int SrsListener::cycle() |
| 160 | { | 128 | { |
| 161 | - SrsListener* obj = (SrsListener*)arg; | ||
| 162 | - srs_assert(obj != NULL); | 129 | + int ret = ERROR_SUCCESS; |
| 130 | + | ||
| 131 | + st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); | ||
| 132 | + | ||
| 133 | + if(client_stfd == NULL){ | ||
| 134 | + // ignore error. | ||
| 135 | + srs_warn("ignore accept thread stoppped for accept client error"); | ||
| 136 | + return ret; | ||
| 137 | + } | ||
| 138 | + srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); | ||
| 163 | 139 | ||
| 164 | - obj->loop = true; | ||
| 165 | - obj->listen_cycle(); | 140 | + if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { |
| 141 | + srs_warn("accept client error. ret=%d", ret); | ||
| 142 | + return ret; | ||
| 143 | + } | ||
| 166 | 144 | ||
| 167 | - return NULL; | 145 | + srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); |
| 146 | + | ||
| 147 | + return ret; | ||
| 168 | } | 148 | } |
| 169 | 149 | ||
| 170 | SrsServer::SrsServer() | 150 | SrsServer::SrsServer() |
| @@ -312,8 +292,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | @@ -312,8 +292,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | ||
| 312 | srs_error("exceed the max connections, drop client: " | 292 | srs_error("exceed the max connections, drop client: " |
| 313 | "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); | 293 | "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); |
| 314 | 294 | ||
| 315 | - st_netfd_close(client_stfd); | ||
| 316 | - ::close(fd); | 295 | + srs_close_stfd(client_stfd); |
| 317 | 296 | ||
| 318 | return ret; | 297 | return ret; |
| 319 | } | 298 | } |
| @@ -32,9 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,9 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | 32 | ||
| 33 | #include <vector> | 33 | #include <vector> |
| 34 | 34 | ||
| 35 | -#include <st.h> | ||
| 36 | - | ||
| 37 | #include <srs_core_reload.hpp> | 35 | #include <srs_core_reload.hpp> |
| 36 | +#include <srs_core_thread.hpp> | ||
| 38 | 37 | ||
| 39 | class SrsServer; | 38 | class SrsServer; |
| 40 | class SrsConnection; | 39 | class SrsConnection; |
| @@ -45,7 +44,7 @@ enum SrsListenerType | @@ -45,7 +44,7 @@ enum SrsListenerType | ||
| 45 | SrsListenerApi | 44 | SrsListenerApi |
| 46 | }; | 45 | }; |
| 47 | 46 | ||
| 48 | -class SrsListener | 47 | +class SrsListener : public ISrsThreadHandler |
| 49 | { | 48 | { |
| 50 | public: | 49 | public: |
| 51 | SrsListenerType type; | 50 | SrsListenerType type; |
| @@ -54,19 +53,19 @@ private: | @@ -54,19 +53,19 @@ private: | ||
| 54 | st_netfd_t stfd; | 53 | st_netfd_t stfd; |
| 55 | int port; | 54 | int port; |
| 56 | SrsServer* server; | 55 | SrsServer* server; |
| 57 | - st_thread_t tid; | ||
| 58 | - bool loop; | 56 | + SrsThread* pthread; |
| 59 | public: | 57 | public: |
| 60 | SrsListener(SrsServer* _server, SrsListenerType _type); | 58 | SrsListener(SrsServer* _server, SrsListenerType _type); |
| 61 | virtual ~SrsListener(); | 59 | virtual ~SrsListener(); |
| 62 | public: | 60 | public: |
| 63 | virtual int listen(int port); | 61 | virtual int listen(int port); |
| 64 | -private: | ||
| 65 | - virtual void listen_cycle(); | ||
| 66 | - static void* listen_thread(void* arg); | 62 | +// interface ISrsThreadHandler. |
| 63 | +public: | ||
| 64 | + virtual void on_enter_loop(); | ||
| 65 | + virtual int cycle(); | ||
| 67 | }; | 66 | }; |
| 68 | 67 | ||
| 69 | -class SrsServer : public SrsReloadHandler | 68 | +class SrsServer : public ISrsReloadHandler |
| 70 | { | 69 | { |
| 71 | friend class SrsListener; | 70 | friend class SrsListener; |
| 72 | private: | 71 | private: |
| @@ -52,6 +52,11 @@ void SrsSocket::set_send_timeout(int64_t timeout_us) | @@ -52,6 +52,11 @@ void SrsSocket::set_send_timeout(int64_t timeout_us) | ||
| 52 | send_timeout = timeout_us; | 52 | send_timeout = timeout_us; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | +int64_t SrsSocket::get_send_timeout() | ||
| 56 | +{ | ||
| 57 | + return send_timeout; | ||
| 58 | +} | ||
| 59 | + | ||
| 55 | int64_t SrsSocket::get_recv_bytes() | 60 | int64_t SrsSocket::get_recv_bytes() |
| 56 | { | 61 | { |
| 57 | return recv_bytes; | 62 | return recv_bytes; |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <srs_core.hpp> | 31 | #include <srs_core.hpp> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | /** | 33 | /** |
| 36 | * the socket provides TCP socket over st, | 34 | * the socket provides TCP socket over st, |
| 37 | * that is, the sync socket mechanism. | 35 | * that is, the sync socket mechanism. |
| @@ -52,6 +50,7 @@ public: | @@ -52,6 +50,7 @@ public: | ||
| 52 | virtual void set_recv_timeout(int64_t timeout_us); | 50 | virtual void set_recv_timeout(int64_t timeout_us); |
| 53 | virtual int64_t get_recv_timeout(); | 51 | virtual int64_t get_recv_timeout(); |
| 54 | virtual void set_send_timeout(int64_t timeout_us); | 52 | virtual void set_send_timeout(int64_t timeout_us); |
| 53 | + virtual int64_t get_send_timeout(); | ||
| 55 | virtual int64_t get_recv_bytes(); | 54 | virtual int64_t get_recv_bytes(); |
| 56 | virtual int64_t get_send_bytes(); | 55 | virtual int64_t get_send_bytes(); |
| 57 | virtual int get_recv_kbps(); | 56 | virtual int get_recv_kbps(); |
| @@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 24 | #include <srs_core_source.hpp> | 24 | #include <srs_core_source.hpp> |
| 25 | 25 | ||
| 26 | #include <algorithm> | 26 | #include <algorithm> |
| 27 | +using namespace std; | ||
| 27 | 28 | ||
| 28 | #include <srs_core_log.hpp> | 29 | #include <srs_core_log.hpp> |
| 29 | #include <srs_core_protocol.hpp> | 30 | #include <srs_core_protocol.hpp> |
| @@ -37,8 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,8 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | #include <srs_core_rtmp.hpp> | 38 | #include <srs_core_rtmp.hpp> |
| 38 | 39 | ||
| 39 | #define CONST_MAX_JITTER_MS 500 | 40 | #define CONST_MAX_JITTER_MS 500 |
| 40 | -#define DEFAULT_FRAME_TIME_MS 10 | ||
| 41 | -#define PAUSED_SHRINK_SIZE 250 | 41 | +#define DEFAULT_FRAME_TIME_MS 40 |
| 42 | 42 | ||
| 43 | SrsRtmpJitter::SrsRtmpJitter() | 43 | SrsRtmpJitter::SrsRtmpJitter() |
| 44 | { | 44 | { |
| @@ -49,9 +49,15 @@ SrsRtmpJitter::~SrsRtmpJitter() | @@ -49,9 +49,15 @@ SrsRtmpJitter::~SrsRtmpJitter() | ||
| 49 | { | 49 | { |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | -int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time) | 52 | +int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) |
| 53 | { | 53 | { |
| 54 | int ret = ERROR_SUCCESS; | 54 | int ret = ERROR_SUCCESS; |
| 55 | + | ||
| 56 | + // set to 0 for metadata. | ||
| 57 | + if (!msg->header.is_video() && !msg->header.is_audio()) { | ||
| 58 | + msg->header.timestamp = 0; | ||
| 59 | + return ret; | ||
| 60 | + } | ||
| 55 | 61 | ||
| 56 | int sample_rate = tba; | 62 | int sample_rate = tba; |
| 57 | int frame_rate = tbv; | 63 | int frame_rate = tbv; |
| @@ -66,16 +72,16 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* | @@ -66,16 +72,16 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* | ||
| 66 | * 3. last_pkt_correct_time: simply add the positive delta, | 72 | * 3. last_pkt_correct_time: simply add the positive delta, |
| 67 | * and enforce the time monotonically. | 73 | * and enforce the time monotonically. |
| 68 | */ | 74 | */ |
| 69 | - u_int32_t time = msg->header.timestamp; | ||
| 70 | - int32_t delta = time - last_pkt_time; | 75 | + int64_t time = msg->header.timestamp; |
| 76 | + int64_t delta = time - last_pkt_time; | ||
| 71 | 77 | ||
| 72 | // if jitter detected, reset the delta. | 78 | // if jitter detected, reset the delta. |
| 73 | if (delta < 0 || delta > CONST_MAX_JITTER_MS) { | 79 | if (delta < 0 || delta > CONST_MAX_JITTER_MS) { |
| 74 | // calc the right diff by audio sample rate | 80 | // calc the right diff by audio sample rate |
| 75 | if (msg->header.is_audio() && sample_rate > 0) { | 81 | if (msg->header.is_audio() && sample_rate > 0) { |
| 76 | - delta = (int32_t)(delta * 1000.0 / sample_rate); | 82 | + delta = (int64_t)(delta * 1000.0 / sample_rate); |
| 77 | } else if (msg->header.is_video() && frame_rate > 0) { | 83 | } else if (msg->header.is_video() && frame_rate > 0) { |
| 78 | - delta = (int32_t)(delta * 1.0 / frame_rate); | 84 | + delta = (int64_t)(delta * 1.0 / frame_rate); |
| 79 | } else { | 85 | } else { |
| 80 | delta = DEFAULT_FRAME_TIME_MS; | 86 | delta = DEFAULT_FRAME_TIME_MS; |
| 81 | } | 87 | } |
| @@ -85,20 +91,16 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* | @@ -85,20 +91,16 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* | ||
| 85 | delta = DEFAULT_FRAME_TIME_MS; | 91 | delta = DEFAULT_FRAME_TIME_MS; |
| 86 | } | 92 | } |
| 87 | 93 | ||
| 88 | - srs_info("jitter detected, last_pts=%d, pts=%d, diff=%d, last_time=%d, time=%d, diff=%d", | 94 | + srs_info("jitter detected, last_pts=%"PRId64", pts=%"PRId64", diff=%"PRId64", last_time=%"PRId64", time=%"PRId64", diff=%"PRId64"", |
| 89 | last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta); | 95 | last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta); |
| 90 | } else { | 96 | } else { |
| 91 | - srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d", | 97 | + srs_verbose("timestamp no jitter. time=%"PRId64", last_pkt=%"PRId64", correct_to=%"PRId64"", |
| 92 | time, last_pkt_time, last_pkt_correct_time + delta); | 98 | time, last_pkt_time, last_pkt_correct_time + delta); |
| 93 | } | 99 | } |
| 94 | 100 | ||
| 95 | last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); | 101 | last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); |
| 96 | 102 | ||
| 97 | - if (corrected_time) { | ||
| 98 | - *corrected_time = last_pkt_correct_time; | ||
| 99 | - } | ||
| 100 | msg->header.timestamp = last_pkt_correct_time; | 103 | msg->header.timestamp = last_pkt_correct_time; |
| 101 | - | ||
| 102 | last_pkt_time = time; | 104 | last_pkt_time = time; |
| 103 | 105 | ||
| 104 | return ret; | 106 | return ret; |
| @@ -109,61 +111,60 @@ int SrsRtmpJitter::get_time() | @@ -109,61 +111,60 @@ int SrsRtmpJitter::get_time() | ||
| 109 | return (int)last_pkt_correct_time; | 111 | return (int)last_pkt_correct_time; |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | -SrsConsumer::SrsConsumer(SrsSource* _source) | 114 | +SrsMessageQueue::SrsMessageQueue() |
| 113 | { | 115 | { |
| 114 | - source = _source; | ||
| 115 | - paused = false; | ||
| 116 | - jitter = new SrsRtmpJitter(); | 116 | + queue_size_ms = 0; |
| 117 | + av_start_time = av_end_time = -1; | ||
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | -SrsConsumer::~SrsConsumer() | 120 | +SrsMessageQueue::~SrsMessageQueue() |
| 120 | { | 121 | { |
| 121 | clear(); | 122 | clear(); |
| 122 | - | ||
| 123 | - source->on_consumer_destroy(this); | ||
| 124 | - srs_freep(jitter); | ||
| 125 | } | 123 | } |
| 126 | 124 | ||
| 127 | -int SrsConsumer::get_time() | 125 | +void SrsMessageQueue::set_queue_size(double queue_size) |
| 128 | { | 126 | { |
| 129 | - return jitter->get_time(); | 127 | + queue_size_ms = (int)(queue_size * 1000); |
| 130 | } | 128 | } |
| 131 | 129 | ||
| 132 | -int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) | 130 | +int SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg) |
| 133 | { | 131 | { |
| 134 | int ret = ERROR_SUCCESS; | 132 | int ret = ERROR_SUCCESS; |
| 135 | 133 | ||
| 136 | - if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { | ||
| 137 | - srs_freep(msg); | ||
| 138 | - return ret; | 134 | + if (msg->header.is_video() || msg->header.is_audio()) { |
| 135 | + if (av_start_time == -1) { | ||
| 136 | + av_start_time = msg->header.timestamp; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + av_end_time = msg->header.timestamp; | ||
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | - // TODO: check the queue size and drop packets if overflow. | ||
| 142 | msgs.push_back(msg); | 142 | msgs.push_back(msg); |
| 143 | + | ||
| 144 | + while (av_end_time - av_start_time > queue_size_ms) { | ||
| 145 | + shrink(); | ||
| 146 | + } | ||
| 143 | 147 | ||
| 144 | return ret; | 148 | return ret; |
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | -int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count) | 151 | +int SrsMessageQueue::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count) |
| 148 | { | 152 | { |
| 149 | int ret = ERROR_SUCCESS; | 153 | int ret = ERROR_SUCCESS; |
| 150 | 154 | ||
| 151 | if (msgs.empty()) { | 155 | if (msgs.empty()) { |
| 152 | return ret; | 156 | return ret; |
| 153 | } | 157 | } |
| 154 | - | ||
| 155 | - if (paused) { | ||
| 156 | - if ((int)msgs.size() >= PAUSED_SHRINK_SIZE) { | ||
| 157 | - shrink(); | ||
| 158 | - } | ||
| 159 | - return ret; | ||
| 160 | - } | ||
| 161 | 158 | ||
| 162 | if (max_count == 0) { | 159 | if (max_count == 0) { |
| 163 | count = (int)msgs.size(); | 160 | count = (int)msgs.size(); |
| 164 | } else { | 161 | } else { |
| 165 | count = srs_min(max_count, (int)msgs.size()); | 162 | count = srs_min(max_count, (int)msgs.size()); |
| 166 | } | 163 | } |
| 164 | + | ||
| 165 | + if (count <= 0) { | ||
| 166 | + return ret; | ||
| 167 | + } | ||
| 167 | 168 | ||
| 168 | pmsgs = new SrsSharedPtrMessage*[count]; | 169 | pmsgs = new SrsSharedPtrMessage*[count]; |
| 169 | 170 | ||
| @@ -171,6 +172,9 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | @@ -171,6 +172,9 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | ||
| 171 | pmsgs[i] = msgs[i]; | 172 | pmsgs[i] = msgs[i]; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 175 | + SrsSharedPtrMessage* last = msgs[count - 1]; | ||
| 176 | + av_start_time = last->header.timestamp; | ||
| 177 | + | ||
| 174 | if (count == (int)msgs.size()) { | 178 | if (count == (int)msgs.size()) { |
| 175 | msgs.clear(); | 179 | msgs.clear(); |
| 176 | } else { | 180 | } else { |
| @@ -180,76 +184,120 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | @@ -180,76 +184,120 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c | ||
| 180 | return ret; | 184 | return ret; |
| 181 | } | 185 | } |
| 182 | 186 | ||
| 183 | -int SrsConsumer::on_play_client_pause(bool is_pause) | 187 | +void SrsMessageQueue::shrink() |
| 184 | { | 188 | { |
| 185 | - int ret = ERROR_SUCCESS; | ||
| 186 | - | ||
| 187 | - srs_trace("stream consumer change pause state %d=>%d", paused, is_pause); | ||
| 188 | - paused = is_pause; | ||
| 189 | - | ||
| 190 | - return ret; | ||
| 191 | -} | ||
| 192 | - | ||
| 193 | -void SrsConsumer::shrink() | ||
| 194 | -{ | ||
| 195 | - int i = 0; | ||
| 196 | - std::vector<SrsSharedPtrMessage*>::iterator it; | ||
| 197 | - | ||
| 198 | - // issue the last video iframe. | ||
| 199 | - bool has_video = false; | ||
| 200 | - int frame_to_remove = 0; | ||
| 201 | - std::vector<SrsSharedPtrMessage*>::iterator iframe = msgs.end(); | ||
| 202 | - for (i = 0, it = msgs.begin(); it != msgs.end(); ++it, i++) { | ||
| 203 | - SrsSharedPtrMessage* msg = *it; | 189 | + int iframe_index = -1; |
| 190 | + | ||
| 191 | + // issue the first iframe. | ||
| 192 | + // skip the first frame, whatever the type of it, | ||
| 193 | + // for when we shrinked, the first is the iframe, | ||
| 194 | + // we will directly remove the gop next time. | ||
| 195 | + for (int i = 1; i < (int)msgs.size(); i++) { | ||
| 196 | + SrsSharedPtrMessage* msg = msgs[i]; | ||
| 197 | + | ||
| 204 | if (msg->header.is_video()) { | 198 | if (msg->header.is_video()) { |
| 205 | - has_video = true; | ||
| 206 | if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) { | 199 | if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) { |
| 207 | - iframe = it; | ||
| 208 | - frame_to_remove = i + 1; | 200 | + // the max frame index to remove. |
| 201 | + iframe_index = i; | ||
| 202 | + | ||
| 203 | + // set the start time, we will remove until this frame. | ||
| 204 | + av_start_time = msg->header.timestamp; | ||
| 205 | + | ||
| 206 | + break; | ||
| 209 | } | 207 | } |
| 210 | } | 208 | } |
| 211 | } | 209 | } |
| 212 | 210 | ||
| 213 | - // last iframe is the first elem, ignore it. | ||
| 214 | - if (iframe == msgs.begin()) { | ||
| 215 | - return; | ||
| 216 | - } | ||
| 217 | - | ||
| 218 | - // recalc the frame to remove | ||
| 219 | - if (iframe == msgs.end()) { | ||
| 220 | - frame_to_remove = 0; | ||
| 221 | - } | ||
| 222 | - if (!has_video) { | ||
| 223 | - frame_to_remove = (int)msgs.size(); | ||
| 224 | - } | ||
| 225 | - | ||
| 226 | - srs_trace("shrink the cache queue, has_video=%d, has_iframe=%d, size=%d, removed=%d", | ||
| 227 | - has_video, iframe != msgs.end(), (int)msgs.size(), frame_to_remove); | ||
| 228 | - | ||
| 229 | - // if no video, remove all audio. | ||
| 230 | - if (!has_video) { | 211 | + // no iframe, clear the queue. |
| 212 | + if (iframe_index < 0) { | ||
| 231 | clear(); | 213 | clear(); |
| 232 | return; | 214 | return; |
| 233 | } | 215 | } |
| 234 | 216 | ||
| 235 | - // if exists video Iframe, remove the frames before it. | ||
| 236 | - if (iframe != msgs.end()) { | ||
| 237 | - for (it = msgs.begin(); it != iframe; ++it) { | ||
| 238 | - SrsSharedPtrMessage* msg = *it; | ||
| 239 | - srs_freep(msg); | ||
| 240 | - } | ||
| 241 | - msgs.erase(msgs.begin(), iframe); | 217 | + srs_trace("shrink the cache queue, size=%d, removed=%d, max=%.2f", |
| 218 | + (int)msgs.size(), iframe_index, queue_size_ms / 1000.0); | ||
| 219 | + | ||
| 220 | + // remove the first gop from the front | ||
| 221 | + for (int i = 0; i < iframe_index; i++) { | ||
| 222 | + SrsSharedPtrMessage* msg = msgs[i]; | ||
| 223 | + srs_freep(msg); | ||
| 242 | } | 224 | } |
| 225 | + msgs.erase(msgs.begin(), msgs.begin() + iframe_index); | ||
| 243 | } | 226 | } |
| 244 | 227 | ||
| 245 | -void SrsConsumer::clear() | 228 | +void SrsMessageQueue::clear() |
| 246 | { | 229 | { |
| 247 | std::vector<SrsSharedPtrMessage*>::iterator it; | 230 | std::vector<SrsSharedPtrMessage*>::iterator it; |
| 231 | + | ||
| 248 | for (it = msgs.begin(); it != msgs.end(); ++it) { | 232 | for (it = msgs.begin(); it != msgs.end(); ++it) { |
| 249 | SrsSharedPtrMessage* msg = *it; | 233 | SrsSharedPtrMessage* msg = *it; |
| 250 | srs_freep(msg); | 234 | srs_freep(msg); |
| 251 | } | 235 | } |
| 236 | + | ||
| 252 | msgs.clear(); | 237 | msgs.clear(); |
| 238 | + | ||
| 239 | + av_start_time = av_end_time = -1; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +SrsConsumer::SrsConsumer(SrsSource* _source) | ||
| 243 | +{ | ||
| 244 | + source = _source; | ||
| 245 | + paused = false; | ||
| 246 | + jitter = new SrsRtmpJitter(); | ||
| 247 | + queue = new SrsMessageQueue(); | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +SrsConsumer::~SrsConsumer() | ||
| 251 | +{ | ||
| 252 | + source->on_consumer_destroy(this); | ||
| 253 | + srs_freep(jitter); | ||
| 254 | + srs_freep(queue); | ||
| 255 | +} | ||
| 256 | + | ||
| 257 | +void SrsConsumer::set_queue_size(double queue_size) | ||
| 258 | +{ | ||
| 259 | + queue->set_queue_size(queue_size); | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +int SrsConsumer::get_time() | ||
| 263 | +{ | ||
| 264 | + return jitter->get_time(); | ||
| 265 | +} | ||
| 266 | + | ||
| 267 | +int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) | ||
| 268 | +{ | ||
| 269 | + int ret = ERROR_SUCCESS; | ||
| 270 | + | ||
| 271 | + if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { | ||
| 272 | + srs_freep(msg); | ||
| 273 | + return ret; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { | ||
| 277 | + return ret; | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + return ret; | ||
| 281 | +} | ||
| 282 | + | ||
| 283 | +int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count) | ||
| 284 | +{ | ||
| 285 | + // paused, return nothing. | ||
| 286 | + if (paused) { | ||
| 287 | + return ERROR_SUCCESS; | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + return queue->get_packets(max_count, pmsgs, count); | ||
| 291 | +} | ||
| 292 | + | ||
| 293 | +int SrsConsumer::on_play_client_pause(bool is_pause) | ||
| 294 | +{ | ||
| 295 | + int ret = ERROR_SUCCESS; | ||
| 296 | + | ||
| 297 | + srs_trace("stream consumer change pause state %d=>%d", paused, is_pause); | ||
| 298 | + paused = is_pause; | ||
| 299 | + | ||
| 300 | + return ret; | ||
| 253 | } | 301 | } |
| 254 | 302 | ||
| 255 | SrsGopCache::SrsGopCache() | 303 | SrsGopCache::SrsGopCache() |
| @@ -344,22 +392,25 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | @@ -344,22 +392,25 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | ||
| 344 | 392 | ||
| 345 | std::map<std::string, SrsSource*> SrsSource::pool; | 393 | std::map<std::string, SrsSource*> SrsSource::pool; |
| 346 | 394 | ||
| 347 | -SrsSource* SrsSource::find(const std::string &stream_url) | 395 | +SrsSource* SrsSource::find(SrsRequest* req) |
| 348 | { | 396 | { |
| 397 | + string stream_url = req->get_stream_url(); | ||
| 398 | + string vhost = req->vhost; | ||
| 399 | + | ||
| 349 | if (pool.find(stream_url) == pool.end()) { | 400 | if (pool.find(stream_url) == pool.end()) { |
| 350 | - pool[stream_url] = new SrsSource(stream_url); | ||
| 351 | - srs_verbose("create new source for url=%s", stream_url.c_str()); | 401 | + pool[stream_url] = new SrsSource(req); |
| 402 | + srs_verbose("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); | ||
| 352 | } | 403 | } |
| 353 | 404 | ||
| 354 | return pool[stream_url]; | 405 | return pool[stream_url]; |
| 355 | } | 406 | } |
| 356 | 407 | ||
| 357 | -SrsSource::SrsSource(std::string _stream_url) | 408 | +SrsSource::SrsSource(SrsRequest* _req) |
| 358 | { | 409 | { |
| 359 | - stream_url = _stream_url; | 410 | + req = _req->copy(); |
| 360 | 411 | ||
| 361 | #ifdef SRS_HLS | 412 | #ifdef SRS_HLS |
| 362 | - hls = new SrsHls(); | 413 | + hls = new SrsHls(this); |
| 363 | #endif | 414 | #endif |
| 364 | #ifdef SRS_FFMPEG | 415 | #ifdef SRS_FFMPEG |
| 365 | encoder = new SrsEncoder(); | 416 | encoder = new SrsEncoder(); |
| @@ -371,10 +422,14 @@ SrsSource::SrsSource(std::string _stream_url) | @@ -371,10 +422,14 @@ SrsSource::SrsSource(std::string _stream_url) | ||
| 371 | _can_publish = true; | 422 | _can_publish = true; |
| 372 | 423 | ||
| 373 | gop_cache = new SrsGopCache(); | 424 | gop_cache = new SrsGopCache(); |
| 425 | + | ||
| 426 | + config->subscribe(this); | ||
| 374 | } | 427 | } |
| 375 | 428 | ||
| 376 | SrsSource::~SrsSource() | 429 | SrsSource::~SrsSource() |
| 377 | { | 430 | { |
| 431 | + config->unsubscribe(this); | ||
| 432 | + | ||
| 378 | if (true) { | 433 | if (true) { |
| 379 | std::vector<SrsConsumer*>::iterator it; | 434 | std::vector<SrsConsumer*>::iterator it; |
| 380 | for (it = consumers.begin(); it != consumers.end(); ++it) { | 435 | for (it = consumers.begin(); it != consumers.end(); ++it) { |
| @@ -405,6 +460,167 @@ SrsSource::~SrsSource() | @@ -405,6 +460,167 @@ SrsSource::~SrsSource() | ||
| 405 | #ifdef SRS_FFMPEG | 460 | #ifdef SRS_FFMPEG |
| 406 | srs_freep(encoder); | 461 | srs_freep(encoder); |
| 407 | #endif | 462 | #endif |
| 463 | + | ||
| 464 | + srs_freep(req); | ||
| 465 | +} | ||
| 466 | + | ||
| 467 | +int SrsSource::on_reload_gop_cache(string vhost) | ||
| 468 | +{ | ||
| 469 | + int ret = ERROR_SUCCESS; | ||
| 470 | + | ||
| 471 | + if (req->vhost != vhost) { | ||
| 472 | + return ret; | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + // gop cache changed. | ||
| 476 | + bool enabled_cache = config->get_gop_cache(vhost); | ||
| 477 | + | ||
| 478 | + srs_trace("vhost %s gop_cache changed to %d, source url=%s", | ||
| 479 | + vhost.c_str(), enabled_cache, req->get_stream_url().c_str()); | ||
| 480 | + | ||
| 481 | + set_cache(enabled_cache); | ||
| 482 | + | ||
| 483 | + return ret; | ||
| 484 | +} | ||
| 485 | + | ||
| 486 | +int SrsSource::on_reload_queue_length(string vhost) | ||
| 487 | +{ | ||
| 488 | + int ret = ERROR_SUCCESS; | ||
| 489 | + | ||
| 490 | + if (req->vhost != vhost) { | ||
| 491 | + return ret; | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + double queue_size = config->get_queue_length(req->vhost); | ||
| 495 | + | ||
| 496 | + if (true) { | ||
| 497 | + std::vector<SrsConsumer*>::iterator it; | ||
| 498 | + | ||
| 499 | + for (it = consumers.begin(); it != consumers.end(); ++it) { | ||
| 500 | + SrsConsumer* consumer = *it; | ||
| 501 | + consumer->set_queue_size(queue_size); | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | + srs_trace("consumers reload queue size success."); | ||
| 505 | + } | ||
| 506 | + | ||
| 507 | + if (true) { | ||
| 508 | + std::vector<SrsForwarder*>::iterator it; | ||
| 509 | + | ||
| 510 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 511 | + SrsForwarder* forwarder = *it; | ||
| 512 | + forwarder->set_queue_size(queue_size); | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + srs_trace("forwarders reload queue size success."); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + return ret; | ||
| 519 | +} | ||
| 520 | + | ||
| 521 | +int SrsSource::on_reload_forward(string vhost) | ||
| 522 | +{ | ||
| 523 | + int ret = ERROR_SUCCESS; | ||
| 524 | + | ||
| 525 | + if (req->vhost != vhost) { | ||
| 526 | + return ret; | ||
| 527 | + } | ||
| 528 | + | ||
| 529 | + // forwarders | ||
| 530 | + destroy_forwarders(); | ||
| 531 | + if ((ret = create_forwarders()) != ERROR_SUCCESS) { | ||
| 532 | + srs_error("create forwarders failed. ret=%d", ret); | ||
| 533 | + return ret; | ||
| 534 | + } | ||
| 535 | + | ||
| 536 | + srs_trace("vhost %s forwarders reload success", vhost.c_str()); | ||
| 537 | + | ||
| 538 | + return ret; | ||
| 539 | +} | ||
| 540 | + | ||
| 541 | +int SrsSource::on_reload_hls(string vhost) | ||
| 542 | +{ | ||
| 543 | + int ret = ERROR_SUCCESS; | ||
| 544 | + | ||
| 545 | + if (req->vhost != vhost) { | ||
| 546 | + return ret; | ||
| 547 | + } | ||
| 548 | + | ||
| 549 | +#ifdef SRS_HLS | ||
| 550 | + hls->on_unpublish(); | ||
| 551 | + if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { | ||
| 552 | + srs_error("hls publish failed. ret=%d", ret); | ||
| 553 | + return ret; | ||
| 554 | + } | ||
| 555 | + srs_trace("vhost %s hls reload success", vhost.c_str()); | ||
| 556 | +#endif | ||
| 557 | + | ||
| 558 | + return ret; | ||
| 559 | +} | ||
| 560 | + | ||
| 561 | +int SrsSource::on_reload_transcode(string vhost) | ||
| 562 | +{ | ||
| 563 | + int ret = ERROR_SUCCESS; | ||
| 564 | + | ||
| 565 | + if (req->vhost != vhost) { | ||
| 566 | + return ret; | ||
| 567 | + } | ||
| 568 | + | ||
| 569 | +#ifdef SRS_FFMPEG | ||
| 570 | + encoder->on_unpublish(); | ||
| 571 | + if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | ||
| 572 | + srs_error("start encoder failed. ret=%d", ret); | ||
| 573 | + return ret; | ||
| 574 | + } | ||
| 575 | + srs_trace("vhost %s transcode reload success", vhost.c_str()); | ||
| 576 | +#endif | ||
| 577 | + | ||
| 578 | + return ret; | ||
| 579 | +} | ||
| 580 | + | ||
| 581 | +int SrsSource::on_forwarder_start(SrsForwarder* forwarder) | ||
| 582 | +{ | ||
| 583 | + int ret = ERROR_SUCCESS; | ||
| 584 | + | ||
| 585 | + // feed the forwarder the metadata/sequence header, | ||
| 586 | + // when reload to enable the forwarder. | ||
| 587 | + if (cache_metadata && (ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { | ||
| 588 | + srs_error("forwarder process onMetaData message failed. ret=%d", ret); | ||
| 589 | + return ret; | ||
| 590 | + } | ||
| 591 | + if (cache_sh_video && (ret = forwarder->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { | ||
| 592 | + srs_error("forwarder process video sequence header message failed. ret=%d", ret); | ||
| 593 | + return ret; | ||
| 594 | + } | ||
| 595 | + if (cache_sh_audio && (ret = forwarder->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { | ||
| 596 | + srs_error("forwarder process audio sequence header message failed. ret=%d", ret); | ||
| 597 | + return ret; | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | + return ret; | ||
| 601 | +} | ||
| 602 | + | ||
| 603 | +int SrsSource::on_hls_start() | ||
| 604 | +{ | ||
| 605 | + int ret = ERROR_SUCCESS; | ||
| 606 | + | ||
| 607 | +#ifdef SRS_HLS | ||
| 608 | + | ||
| 609 | + // feed the hls the metadata/sequence header, | ||
| 610 | + // when reload to enable the hls. | ||
| 611 | + // TODO: maybe need to decode the metadata? | ||
| 612 | + if (cache_sh_video && (ret = hls->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { | ||
| 613 | + srs_error("hls process video sequence header message failed. ret=%d", ret); | ||
| 614 | + return ret; | ||
| 615 | + } | ||
| 616 | + if (cache_sh_audio && (ret = hls->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { | ||
| 617 | + srs_error("hls process audio sequence header message failed. ret=%d", ret); | ||
| 618 | + return ret; | ||
| 619 | + } | ||
| 620 | + | ||
| 621 | +#endif | ||
| 622 | + | ||
| 623 | + return ret; | ||
| 408 | } | 624 | } |
| 409 | 625 | ||
| 410 | bool SrsSource::can_publish() | 626 | bool SrsSource::can_publish() |
| @@ -417,7 +633,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | @@ -417,7 +633,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | ||
| 417 | int ret = ERROR_SUCCESS; | 633 | int ret = ERROR_SUCCESS; |
| 418 | 634 | ||
| 419 | #ifdef SRS_HLS | 635 | #ifdef SRS_HLS |
| 420 | - if ((ret = hls->on_meta_data(metadata)) != ERROR_SUCCESS) { | 636 | + if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { |
| 421 | srs_error("hls process onMetaData message failed. ret=%d", ret); | 637 | srs_error("hls process onMetaData message failed. ret=%d", ret); |
| 422 | return ret; | 638 | return ret; |
| 423 | } | 639 | } |
| @@ -425,6 +641,8 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | @@ -425,6 +641,8 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | ||
| 425 | 641 | ||
| 426 | metadata->metadata->set("server", new SrsAmf0String( | 642 | metadata->metadata->set("server", new SrsAmf0String( |
| 427 | RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); | 643 | RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); |
| 644 | + metadata->metadata->set("contributor", | ||
| 645 | + new SrsAmf0String(RTMP_SIG_SRS_CONTRIBUTOR)); | ||
| 428 | 646 | ||
| 429 | SrsAmf0Any* prop = NULL; | 647 | SrsAmf0Any* prop = NULL; |
| 430 | if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { | 648 | if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { |
| @@ -620,7 +838,7 @@ int SrsSource::on_video(SrsCommonMessage* video) | @@ -620,7 +838,7 @@ int SrsSource::on_video(SrsCommonMessage* video) | ||
| 620 | 838 | ||
| 621 | // cache the last gop packets | 839 | // cache the last gop packets |
| 622 | if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { | 840 | if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { |
| 623 | - srs_error("shrink gop cache failed. ret=%d", ret); | 841 | + srs_error("gop cache msg failed. ret=%d", ret); |
| 624 | return ret; | 842 | return ret; |
| 625 | } | 843 | } |
| 626 | srs_verbose("cache gop success."); | 844 | srs_verbose("cache gop success."); |
| @@ -628,39 +846,33 @@ int SrsSource::on_video(SrsCommonMessage* video) | @@ -628,39 +846,33 @@ int SrsSource::on_video(SrsCommonMessage* video) | ||
| 628 | return ret; | 846 | return ret; |
| 629 | } | 847 | } |
| 630 | 848 | ||
| 631 | -int SrsSource::on_publish(SrsRequest* req) | 849 | +int SrsSource::on_publish(SrsRequest* _req) |
| 632 | { | 850 | { |
| 633 | int ret = ERROR_SUCCESS; | 851 | int ret = ERROR_SUCCESS; |
| 634 | 852 | ||
| 853 | + // update the request object. | ||
| 854 | + srs_freep(req); | ||
| 855 | + req = _req->copy(); | ||
| 856 | + srs_assert(req); | ||
| 857 | + | ||
| 635 | _can_publish = false; | 858 | _can_publish = false; |
| 636 | - | ||
| 637 | - // TODO: support reload. | ||
| 638 | 859 | ||
| 639 | // create forwarders | 860 | // create forwarders |
| 640 | - SrsConfDirective* conf = config->get_forward(req->vhost); | ||
| 641 | - for (int i = 0; conf && i < (int)conf->args.size(); i++) { | ||
| 642 | - std::string forward_server = conf->args.at(i); | ||
| 643 | - | ||
| 644 | - SrsForwarder* forwarder = new SrsForwarder(); | ||
| 645 | - forwarders.push_back(forwarder); | ||
| 646 | - | ||
| 647 | - if ((ret = forwarder->on_publish(req, forward_server)) != ERROR_SUCCESS) { | ||
| 648 | - srs_error("start forwarder failed. " | ||
| 649 | - "vhost=%s, app=%s, stream=%s, forward-to=%s", | ||
| 650 | - req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), | ||
| 651 | - forward_server.c_str()); | ||
| 652 | - return ret; | ||
| 653 | - } | 861 | + if ((ret = create_forwarders()) != ERROR_SUCCESS) { |
| 862 | + srs_error("create forwarders failed. ret=%d", ret); | ||
| 863 | + return ret; | ||
| 654 | } | 864 | } |
| 655 | - | 865 | + |
| 656 | #ifdef SRS_FFMPEG | 866 | #ifdef SRS_FFMPEG |
| 657 | if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | 867 | if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { |
| 868 | + srs_error("start encoder failed. ret=%d", ret); | ||
| 658 | return ret; | 869 | return ret; |
| 659 | } | 870 | } |
| 660 | #endif | 871 | #endif |
| 661 | 872 | ||
| 662 | #ifdef SRS_HLS | 873 | #ifdef SRS_HLS |
| 663 | if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { | 874 | if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { |
| 875 | + srs_error("start hls failed. ret=%d", ret); | ||
| 664 | return ret; | 876 | return ret; |
| 665 | } | 877 | } |
| 666 | #endif | 878 | #endif |
| @@ -670,19 +882,14 @@ int SrsSource::on_publish(SrsRequest* req) | @@ -670,19 +882,14 @@ int SrsSource::on_publish(SrsRequest* req) | ||
| 670 | 882 | ||
| 671 | void SrsSource::on_unpublish() | 883 | void SrsSource::on_unpublish() |
| 672 | { | 884 | { |
| 673 | - // close all forwarders | ||
| 674 | - std::vector<SrsForwarder*>::iterator it; | ||
| 675 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 676 | - SrsForwarder* forwarder = *it; | ||
| 677 | - forwarder->on_unpublish(); | ||
| 678 | - srs_freep(forwarder); | ||
| 679 | - } | ||
| 680 | - forwarders.clear(); | 885 | + // destroy all forwarders |
| 886 | + destroy_forwarders(); | ||
| 681 | 887 | ||
| 682 | #ifdef SRS_FFMPEG | 888 | #ifdef SRS_FFMPEG |
| 683 | encoder->on_unpublish(); | 889 | encoder->on_unpublish(); |
| 684 | #endif | 890 | #endif |
| 685 | 891 | ||
| 892 | + // TODO: HLS should continue previous sequence and stream. | ||
| 686 | #ifdef SRS_HLS | 893 | #ifdef SRS_HLS |
| 687 | hls->on_unpublish(); | 894 | hls->on_unpublish(); |
| 688 | #endif | 895 | #endif |
| @@ -706,6 +913,9 @@ void SrsSource::on_unpublish() | @@ -706,6 +913,9 @@ void SrsSource::on_unpublish() | ||
| 706 | 913 | ||
| 707 | consumer = new SrsConsumer(this); | 914 | consumer = new SrsConsumer(this); |
| 708 | consumers.push_back(consumer); | 915 | consumers.push_back(consumer); |
| 916 | + | ||
| 917 | + double queue_size = config->get_queue_length(req->vhost); | ||
| 918 | + consumer->set_queue_size(queue_size); | ||
| 709 | 919 | ||
| 710 | if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { | 920 | if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { |
| 711 | srs_error("dispatch metadata failed. ret=%d", ret); | 921 | srs_error("dispatch metadata failed. ret=%d", ret); |
| @@ -729,6 +939,8 @@ void SrsSource::on_unpublish() | @@ -729,6 +939,8 @@ void SrsSource::on_unpublish() | ||
| 729 | return ret; | 939 | return ret; |
| 730 | } | 940 | } |
| 731 | 941 | ||
| 942 | + srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate); | ||
| 943 | + | ||
| 732 | return ret; | 944 | return ret; |
| 733 | } | 945 | } |
| 734 | 946 | ||
| @@ -747,3 +959,40 @@ void SrsSource::set_cache(bool enabled) | @@ -747,3 +959,40 @@ void SrsSource::set_cache(bool enabled) | ||
| 747 | gop_cache->set(enabled); | 959 | gop_cache->set(enabled); |
| 748 | } | 960 | } |
| 749 | 961 | ||
| 962 | +int SrsSource::create_forwarders() | ||
| 963 | +{ | ||
| 964 | + int ret = ERROR_SUCCESS; | ||
| 965 | + | ||
| 966 | + SrsConfDirective* conf = config->get_forward(req->vhost); | ||
| 967 | + for (int i = 0; conf && i < (int)conf->args.size(); i++) { | ||
| 968 | + std::string forward_server = conf->args.at(i); | ||
| 969 | + | ||
| 970 | + SrsForwarder* forwarder = new SrsForwarder(this); | ||
| 971 | + forwarders.push_back(forwarder); | ||
| 972 | + | ||
| 973 | + double queue_size = config->get_queue_length(req->vhost); | ||
| 974 | + forwarder->set_queue_size(queue_size); | ||
| 975 | + | ||
| 976 | + if ((ret = forwarder->on_publish(req, forward_server)) != ERROR_SUCCESS) { | ||
| 977 | + srs_error("start forwarder failed. " | ||
| 978 | + "vhost=%s, app=%s, stream=%s, forward-to=%s", | ||
| 979 | + req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), | ||
| 980 | + forward_server.c_str()); | ||
| 981 | + return ret; | ||
| 982 | + } | ||
| 983 | + } | ||
| 984 | + | ||
| 985 | + return ret; | ||
| 986 | +} | ||
| 987 | + | ||
| 988 | +void SrsSource::destroy_forwarders() | ||
| 989 | +{ | ||
| 990 | + std::vector<SrsForwarder*>::iterator it; | ||
| 991 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 992 | + SrsForwarder* forwarder = *it; | ||
| 993 | + forwarder->on_unpublish(); | ||
| 994 | + srs_freep(forwarder); | ||
| 995 | + } | ||
| 996 | + forwarders.clear(); | ||
| 997 | +} | ||
| 998 | + |
trunk/src/core/srs_core_source.hpp
100644 → 100755
| @@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 34 | #include <vector> | 34 | #include <vector> |
| 35 | #include <string> | 35 | #include <string> |
| 36 | 36 | ||
| 37 | +#include <srs_core_reload.hpp> | ||
| 38 | + | ||
| 37 | class SrsSource; | 39 | class SrsSource; |
| 38 | class SrsCommonMessage; | 40 | class SrsCommonMessage; |
| 39 | class SrsOnMetaDataPacket; | 41 | class SrsOnMetaDataPacket; |
| @@ -54,18 +56,16 @@ class SrsEncoder; | @@ -54,18 +56,16 @@ class SrsEncoder; | ||
| 54 | class SrsRtmpJitter | 56 | class SrsRtmpJitter |
| 55 | { | 57 | { |
| 56 | private: | 58 | private: |
| 57 | - u_int32_t last_pkt_time; | ||
| 58 | - u_int32_t last_pkt_correct_time; | 59 | + int64_t last_pkt_time; |
| 60 | + int64_t last_pkt_correct_time; | ||
| 59 | public: | 61 | public: |
| 60 | SrsRtmpJitter(); | 62 | SrsRtmpJitter(); |
| 61 | virtual ~SrsRtmpJitter(); | 63 | virtual ~SrsRtmpJitter(); |
| 62 | public: | 64 | public: |
| 63 | /** | 65 | /** |
| 64 | * detect the time jitter and correct it. | 66 | * detect the time jitter and correct it. |
| 65 | - * @param corrected_time output the 64bits time. | ||
| 66 | - * ignore if NULL. | ||
| 67 | */ | 67 | */ |
| 68 | - virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time = NULL); | 68 | + virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); |
| 69 | /** | 69 | /** |
| 70 | * get current client time, the last packet time. | 70 | * get current client time, the last packet time. |
| 71 | */ | 71 | */ |
| @@ -73,6 +73,48 @@ public: | @@ -73,6 +73,48 @@ public: | ||
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | /** | 75 | /** |
| 76 | +* the message queue for the consumer(client), forwarder. | ||
| 77 | +* we limit the size in seconds, drop old messages(the whole gop) if full. | ||
| 78 | +*/ | ||
| 79 | +class SrsMessageQueue | ||
| 80 | +{ | ||
| 81 | +private: | ||
| 82 | + int64_t av_start_time; | ||
| 83 | + int64_t av_end_time; | ||
| 84 | + int queue_size_ms; | ||
| 85 | + std::vector<SrsSharedPtrMessage*> msgs; | ||
| 86 | +public: | ||
| 87 | + SrsMessageQueue(); | ||
| 88 | + virtual ~SrsMessageQueue(); | ||
| 89 | +public: | ||
| 90 | + /** | ||
| 91 | + * set the queue size | ||
| 92 | + * @param queue_size the queue size in seconds. | ||
| 93 | + */ | ||
| 94 | + virtual void set_queue_size(double queue_size); | ||
| 95 | +public: | ||
| 96 | + /** | ||
| 97 | + * enqueue the message, the timestamp always monotonically. | ||
| 98 | + * @param msg, the msg to enqueue, user never free it whatever the return code. | ||
| 99 | + */ | ||
| 100 | + virtual int enqueue(SrsSharedPtrMessage* msg); | ||
| 101 | + /** | ||
| 102 | + * get packets in consumer queue. | ||
| 103 | + * @pmsgs SrsMessages*[], output the prt array. | ||
| 104 | + * @count the count in array. | ||
| 105 | + * @max_count the max count to dequeue, 0 to dequeue all. | ||
| 106 | + */ | ||
| 107 | + virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); | ||
| 108 | +private: | ||
| 109 | + /** | ||
| 110 | + * remove a gop from the front. | ||
| 111 | + * if no iframe found, clear it. | ||
| 112 | + */ | ||
| 113 | + virtual void shrink(); | ||
| 114 | + virtual void clear(); | ||
| 115 | +}; | ||
| 116 | + | ||
| 117 | +/** | ||
| 76 | * the consumer for SrsSource, that is a play client. | 118 | * the consumer for SrsSource, that is a play client. |
| 77 | */ | 119 | */ |
| 78 | class SrsConsumer | 120 | class SrsConsumer |
| @@ -80,12 +122,14 @@ class SrsConsumer | @@ -80,12 +122,14 @@ class SrsConsumer | ||
| 80 | private: | 122 | private: |
| 81 | SrsRtmpJitter* jitter; | 123 | SrsRtmpJitter* jitter; |
| 82 | SrsSource* source; | 124 | SrsSource* source; |
| 83 | - std::vector<SrsSharedPtrMessage*> msgs; | 125 | + SrsMessageQueue* queue; |
| 84 | bool paused; | 126 | bool paused; |
| 85 | public: | 127 | public: |
| 86 | SrsConsumer(SrsSource* _source); | 128 | SrsConsumer(SrsSource* _source); |
| 87 | virtual ~SrsConsumer(); | 129 | virtual ~SrsConsumer(); |
| 88 | public: | 130 | public: |
| 131 | + virtual void set_queue_size(double queue_size); | ||
| 132 | +public: | ||
| 89 | /** | 133 | /** |
| 90 | * get current client time, the last packet time. | 134 | * get current client time, the last packet time. |
| 91 | */ | 135 | */ |
| @@ -109,13 +153,6 @@ public: | @@ -109,13 +153,6 @@ public: | ||
| 109 | * when client send the pause message. | 153 | * when client send the pause message. |
| 110 | */ | 154 | */ |
| 111 | virtual int on_play_client_pause(bool is_pause); | 155 | virtual int on_play_client_pause(bool is_pause); |
| 112 | -private: | ||
| 113 | - /** | ||
| 114 | - * when paused, shrink the cache queue, | ||
| 115 | - * remove to cache only one gop. | ||
| 116 | - */ | ||
| 117 | - virtual void shrink(); | ||
| 118 | - virtual void clear(); | ||
| 119 | }; | 156 | }; |
| 120 | 157 | ||
| 121 | /** | 158 | /** |
| @@ -158,20 +195,21 @@ public: | @@ -158,20 +195,21 @@ public: | ||
| 158 | /** | 195 | /** |
| 159 | * live streaming source. | 196 | * live streaming source. |
| 160 | */ | 197 | */ |
| 161 | -class SrsSource | 198 | +class SrsSource : public ISrsReloadHandler |
| 162 | { | 199 | { |
| 163 | private: | 200 | private: |
| 164 | static std::map<std::string, SrsSource*> pool; | 201 | static std::map<std::string, SrsSource*> pool; |
| 165 | public: | 202 | public: |
| 166 | /** | 203 | /** |
| 167 | * find stream by vhost/app/stream. | 204 | * find stream by vhost/app/stream. |
| 168 | - * @stream_url the stream url, for example, myserver.xxx.com/app/stream | 205 | + * @param req the client request. |
| 169 | * @return the matched source, never be NULL. | 206 | * @return the matched source, never be NULL. |
| 170 | * @remark stream_url should without port and schema. | 207 | * @remark stream_url should without port and schema. |
| 171 | */ | 208 | */ |
| 172 | - static SrsSource* find(const std::string& stream_url); | 209 | + static SrsSource* find(SrsRequest* req); |
| 173 | private: | 210 | private: |
| 174 | - std::string stream_url; | 211 | + // deep copy of client request. |
| 212 | + SrsRequest* req; | ||
| 175 | // to delivery stream to clients. | 213 | // to delivery stream to clients. |
| 176 | std::vector<SrsConsumer*> consumers; | 214 | std::vector<SrsConsumer*> consumers; |
| 177 | // hls handler. | 215 | // hls handler. |
| @@ -206,19 +244,43 @@ private: | @@ -206,19 +244,43 @@ private: | ||
| 206 | // the cached audio sequence header. | 244 | // the cached audio sequence header. |
| 207 | SrsSharedPtrMessage* cache_sh_audio; | 245 | SrsSharedPtrMessage* cache_sh_audio; |
| 208 | public: | 246 | public: |
| 209 | - SrsSource(std::string _stream_url); | 247 | + /** |
| 248 | + * @param _req the client request object, | ||
| 249 | + * this object will deep copy it for reload. | ||
| 250 | + */ | ||
| 251 | + SrsSource(SrsRequest* _req); | ||
| 210 | virtual ~SrsSource(); | 252 | virtual ~SrsSource(); |
| 253 | +// interface ISrsReloadHandler | ||
| 254 | +public: | ||
| 255 | + virtual int on_reload_gop_cache(std::string vhost); | ||
| 256 | + virtual int on_reload_queue_length(std::string vhost); | ||
| 257 | + virtual int on_reload_forward(std::string vhost); | ||
| 258 | + virtual int on_reload_hls(std::string vhost); | ||
| 259 | + virtual int on_reload_transcode(std::string vhost); | ||
| 260 | +public: | ||
| 261 | + // for the SrsForwarder to callback to request the sequence headers. | ||
| 262 | + virtual int on_forwarder_start(SrsForwarder* forwarder); | ||
| 263 | + // for the SrsHls to callback to request the sequence headers. | ||
| 264 | + virtual int on_hls_start(); | ||
| 211 | public: | 265 | public: |
| 212 | virtual bool can_publish(); | 266 | virtual bool can_publish(); |
| 213 | virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); | 267 | virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); |
| 214 | virtual int on_audio(SrsCommonMessage* audio); | 268 | virtual int on_audio(SrsCommonMessage* audio); |
| 215 | virtual int on_video(SrsCommonMessage* video); | 269 | virtual int on_video(SrsCommonMessage* video); |
| 216 | - virtual int on_publish(SrsRequest* req); | 270 | + /** |
| 271 | + * publish stream event notify. | ||
| 272 | + * @param _req the request from client, the source will deep copy it, | ||
| 273 | + * for when reload the request of client maybe invalid. | ||
| 274 | + */ | ||
| 275 | + virtual int on_publish(SrsRequest* _req); | ||
| 217 | virtual void on_unpublish(); | 276 | virtual void on_unpublish(); |
| 218 | public: | 277 | public: |
| 219 | virtual int create_consumer(SrsConsumer*& consumer); | 278 | virtual int create_consumer(SrsConsumer*& consumer); |
| 220 | virtual void on_consumer_destroy(SrsConsumer* consumer); | 279 | virtual void on_consumer_destroy(SrsConsumer* consumer); |
| 221 | virtual void set_cache(bool enabled); | 280 | virtual void set_cache(bool enabled); |
| 281 | +private: | ||
| 282 | + virtual int create_forwarders(); | ||
| 283 | + virtual void destroy_forwarders(); | ||
| 222 | }; | 284 | }; |
| 223 | 285 | ||
| 224 | #endif | 286 | #endif |
-
请 注册 或 登录 后发表评论