diff --git a/DONATIONS.txt b/DONATIONS.txt index c404c221d..bec0ed9c9 100644 --- a/DONATIONS.txt +++ b/DONATIONS.txt @@ -3,18 +3,22 @@ Donations ordered by first donation. =========================================================== 2015 -RMB 1000+ +RMB 10000+ +* [2015-03-03 13:25] 郭强 + +RMB 1000-9999 * [2015-xx-xx xx:xx] xxx RMB 500-999 * [2015-xx-xx xx:xx] xxx RMB 100-499 +* [2015-03-11 09:44] 叶发养 * [2015-02-08 21:10] 韩友洪 * [2015-01-09 16:08] 李理 RMB 50-99 -* [2015-xx-xx xx:xx] xxx +* [2015-03-03 17:30] flybird RMB 0.01-49 * [2015-xx-xx xx:xx] xxx diff --git a/README.md b/README.md index 58b9c76ec..39341c337 100755 --- a/README.md +++ b/README.md @@ -12,11 +12,32 @@ Download from ossrs.net: [Centos6-x86_64](http://www.ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.27.zip) [more...](http://www.ossrs.net/srs.release/releases/) +## Why SRS? + +1. Completely rewrite HLS following m3u8/ts spec, and HLS support h.264+aac/mp3. +1. High efficient RTMP deliverying support 7k+ concurrency, vhost based, both origin and edge. +1. Embeded simplified media HTTP server for HLS, api and HTTP flv/ts/mp3/aac streaming. +1. Variety input: RTMP, pull by ingest file or stream(HTTP/RTMP/RTSP), push by stream caster +RTSP/MPEGTS-over-UDP. +1. Popular internet delivery: RTMP for flash, HLS for mobile(IOS/IPad/MAC/Android), HTTP +flv/ts/mp3/aac streaming for user prefered. +1. Enhanced DVR: segment/session/append plan, customer path and HTTP callback. +1. Multiple feature: transcode, forward, ingest, http hooks, dvr, hls, rtsp, http streaming, +http api, refer, log, bandwith test and srs-librtmp. +1. Best maintainess: simple arch over state-threads(coroutine), single thread, single process +and for linux/osx platform, common server x86-64/i386/arm/mips cpus, rich comments, strictly +follows RTMP/HLS/RTSP spec. +1. Easy to use: both English and Chinese wiki, typically config files in trunk/conf, traceable +and session based log, linux service script and install script. +1. MIT license, open source with product management and evolution. + +Enjoy it! + ## About SRS(SIMPLE RTMP Server) over state-threads created in 2013.10. -SRS delivers rtmp/hls/http live on x86/x64/arm/mips linux, +SRS delivers rtmp/hls/http live on x86/x64/arm/mips linux/osx, supports origin/edge/vhost and transcode/ingest and dvr/forward and http-api/http-callback/reload, introduces tracable session-oriented log, exports client srs-librtmp, @@ -486,14 +507,12 @@ Supported operating systems and hardware: ). 1. Support HLS(h.264+mp3) streaming, read [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301). -1. Support push MPEG-TS over UDP to SRS, read -[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250). 1. Rewrite HLS(h.264+aac/mp3) streaming, read [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304). -1. Support push RTSP to SRS, read +1. [experiment] Support push MPEG-TS over UDP to SRS, read +[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250). +1. [experiment] Support push RTSP to SRS, read [#133](https://github.com/winlinvip/simple-rtmp-server/issues/133). -1. Support DVR http api, read -[#179](https://github.com/winlinvip/simple-rtmp-server/issues/179). 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). 1. [no-plan] Support multiple processes, for both origin and edge @@ -503,7 +522,6 @@ Supported operating systems and hardware: 1. [no-plan] Support encryption: RTMPE/RTMPS, HLS DRM 1. [no-plan] Support RTMPT, http to tranverse firewalls 1. [no-plan] Support file source, transcoding file to live stream -1. [no-plan] Support RTP/RTSP server. ## Releases * 2015-02-12, [Release v1.0r2](https://github.com/winlinvip/simple-rtmp-server/releases/tag/1.0r2), bug fixed, 1.0.27, 59507 lines.
@@ -532,8 +550,13 @@ Supported operating systems and hardware: ### SRS 2.0 history -* v2.0, 2015-02-24, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), fix hls bug, write pts/dts error. 2.0.124. -* v2.0, 2015-02-24, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), support dvr http api. 2.0.123. +* v2.0, 2015-03-10, fix [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), support osx(darwin) for mac pro. 2.0.137. +* v2.0, 2015-03-08, fix [#316](https://github.com/winlinvip/simple-rtmp-server/issues/316), http api provides stream/vhost/srs/server bytes, codec and count. 2.0.136. +* v2.0, 2015-03-08, fix [#310](https://github.com/winlinvip/simple-rtmp-server/issues/310), refine aac LC, support aac HE/HEv2. 2.0.134. +* v2.0, 2015-03-06, for [#322](https://github.com/winlinvip/simple-rtmp-server/issues/322), fix http-flv stream bug, support multiple streams. 2.0.133. +* v2.0, 2015-03-06, refine http request parse. 2.0.132. +* v2.0, 2015-03-01, for [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), revert dvr http api. 2.0.128. +* v2.0, 2015-02-24, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), fix hls bug, write pts/dts error. 2.0.124 * v2.0, 2015-02-19, refine dvr, append file when dvr file exists. 2.0.122. * v2.0, 2015-02-19, refine pithy print to more easyer to use. 2.0.121. * v2.0, 2015-02-18, fix [#133](https://github.com/winlinvip/simple-rtmp-server/issues/133), support push rtsp to srs. 2.0.120. diff --git a/trunk/3rdparty/libaacplus-2.0.2.zip b/trunk/3rdparty/libaacplus-2.0.2.zip deleted file mode 100644 index ecf78dbf8..000000000 Binary files a/trunk/3rdparty/libaacplus-2.0.2.zip and /dev/null differ diff --git a/trunk/3rdparty/libaacplus-patch-26410-800.zip b/trunk/3rdparty/libaacplus-patch-26410-800.zip deleted file mode 100644 index bef52eb6e..000000000 Binary files a/trunk/3rdparty/libaacplus-patch-26410-800.zip and /dev/null differ diff --git a/trunk/3rdparty/patches/2.http.parser.patch b/trunk/3rdparty/patches/2.http.parser.patch new file mode 100644 index 000000000..596d5972b --- /dev/null +++ b/trunk/3rdparty/patches/2.http.parser.patch @@ -0,0 +1,17 @@ +diff -r -c ./Makefile ../http-parser-2.1/Makefile +*** ./Makefile Tue Mar 10 10:44:19 2015 +--- ../http-parser-2.1/Makefile Wed Mar 27 06:35:20 2013 +*************** +*** 12,22 **** + CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA) + CFLAGS_LIB = $(CFLAGS_FAST) -fPIC + +- # patch by winlin +- CPPFLAGS_FAST = $(CPPFLAGS_DEBUG) +- CFLAGS_FAST = $(CFLAGS_DEBUG) +- CFLAGS_LIB = $(CFLAGS_FAST) -fPIC +- + test: test_g test_fast + ./test_g + ./test_fast +--- 12,17 ---- diff --git a/trunk/3rdparty/readme.txt b/trunk/3rdparty/readme.txt index 6b7d071b1..094504d8c 100644 --- a/trunk/3rdparty/readme.txt +++ b/trunk/3rdparty/readme.txt @@ -16,8 +16,6 @@ CherryPy-3.2.4.zip ffmpeg-2.1.1.tar.gz yasm-1.2.0.tar.gz lame-3.99.5.tar.gz -libaacplus-2.0.2.tar.gz -libaacplus-patch-26410-800.zip (26410-800.zip) speex-1.2rc1.zip x264-snapshot-20131129-2245-stable.tar.bz2 (core.138) for srs to support live stream transcoding. @@ -55,12 +53,6 @@ links: lame: http://sourceforge.net/projects/lame/ http://nchc.dl.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz - aacplus: - http://217.20.164.161/~tipok/aacplus/ - http://217.20.164.161/~tipok/aacplus/libaacplus-2.0.2.tar.gz - aacplus-patch: - http://www.3gpp.org/DynaReport/26410.htm - http://www.3gpp.org/ftp/Specs/archive/26_series/26.410/26410-800.zip yasm: http://yasm.tortall.net/ http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz diff --git a/trunk/auto/auto_headers.sh b/trunk/auto/auto_headers.sh new file mode 100755 index 000000000..c559c3dfb --- /dev/null +++ b/trunk/auto/auto_headers.sh @@ -0,0 +1,251 @@ +#!/bin/bash + +# output variables: +# SRS_AUTO_HEADERS_H: the auto generated header file. + +SRS_AUTO_HEADERS_H="${SRS_OBJS}/srs_auto_headers.hpp" + +# write user options to headers +echo "// auto generated by configure" > $SRS_AUTO_HEADERS_H +echo "#ifndef SRS_AUTO_HEADER_HPP" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_HEADER_HPP" >> $SRS_AUTO_HEADERS_H +echo "" >> $SRS_AUTO_HEADERS_H + +echo "#define SRS_AUTO_BUILD_TS \"`date +%s`\"" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_BUILD_DATE \"`date \"+%Y-%m-%d %H:%M:%S\"`\"" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_UNAME \"`uname -a`\"" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_USER_CONFIGURE \"${SRS_AUTO_USER_CONFIGURE}\"" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_CONFIGURE \"${SRS_AUTO_CONFIGURE}\"" >> $SRS_AUTO_HEADERS_H +echo "" >> $SRS_AUTO_HEADERS_H + +# export the preset. +if [ $SRS_OSX = YES ]; then + echo "#define SRS_OSX" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_X86_X64 = YES ]; then + echo "#define SRS_X86_X64" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_ARM_UBUNTU12 = YES ]; then + echo "#define SRS_ARM_UBUNTU12" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_MIPS_UBUNTU12 = YES ]; then + echo "#define SRS_MIPS_UBUNTU12" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_PI = YES ]; then + echo "#define SRS_PI" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_CUBIE = YES ]; then + echo "#define SRS_CUBIE" >> $SRS_AUTO_HEADERS_H +fi + +echo "" >> $SRS_AUTO_HEADERS_H + +##################################################################################### +# generate auto headers file, depends on the finished of options.sh +##################################################################################### +if [ $SRS_ARM_UBUNTU12 = YES ]; then + __SrsArmCC="arm-linux-gnueabi-gcc"; + __SrsArmGCC="arm-linux-gnueabi-gcc"; + __SrsArmCXX="arm-linux-gnueabi-g++"; + __SrsArmAR="arm-linux-gnueabi-ar"; + __SrsArmLD="arm-linux-gnueabi-ld"; + __SrsArmRANDLIB="arm-linux-gnueabi-ranlib"; +fi +if [ $SRS_MIPS_UBUNTU12 = YES ]; then + __SrsArmCC="mipsel-openwrt-linux-gcc"; + __SrsArmGCC="mipsel-openwrt-linux-gcc"; + __SrsArmCXX="mipsel-openwrt-linux-g++"; + __SrsArmAR="mipsel-openwrt-linux-ar"; + __SrsArmLD="mipsel-openwrt-linux-ld"; + __SrsArmRANDLIB="mipsel-openwrt-linux-ranlib"; +fi +# the arm-ubuntu12 options for make for depends +if [[ -z $SrsArmCC ]]; then SrsArmCC=$__SrsArmCC; fi +if [[ -z $SrsArmGCC ]]; then SrsArmGCC=$__SrsArmGCC; fi +if [[ -z $SrsArmCXX ]]; then SrsArmCXX=$__SrsArmCXX; fi +if [[ -z $SrsArmAR ]]; then SrsArmAR=$__SrsArmAR; fi +if [[ -z $SrsArmLD ]]; then SrsArmLD=$__SrsArmLD; fi +if [[ -z $SrsArmRANDLIB ]]; then SrsArmRANDLIB=$__SrsArmRANDLIB; fi +# write to source file +if [ $SRS_EMBEDED_CPU = YES ]; then + echo "cc=$SrsArmCC gcc=$SrsArmGCC g++=$SrsArmCXX ar=$SrsArmAR ld=$SrsArmLD randlib=$SrsArmRANDLIB" + echo "#define SRS_AUTO_EMBEDED_TOOL_CHAIN \"cc=$SrsArmCC gcc=$SrsArmGCC g++=$SrsArmCXX ar=$SrsArmAR ld=$SrsArmLD randlib=$SrsArmRANDLIB\"" >> $SRS_AUTO_HEADERS_H +else + echo "#define SRS_AUTO_EMBEDED_TOOL_CHAIN \"normal x86/x64 gcc\"" >> $SRS_AUTO_HEADERS_H +fi +echo "" >> $SRS_AUTO_HEADERS_H + +# auto headers in depends. +if [ $SRS_HTTP_PARSER = YES ]; then + echo "#define SRS_AUTO_HTTP_PARSER" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_HTTP_PARSER" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_HTTP_SERVER = YES ]; then + echo "#define SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_STREAM_CASTER = YES ]; then + echo "#define SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_HTTP_API = YES ]; then + echo "#define SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_NGINX = YES ]; then + echo "#define SRS_AUTO_NGINX" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_NGINX" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_DVR = YES ]; then + echo "#define SRS_AUTO_DVR" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_DVR" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_HLS = YES ]; then + echo "#define SRS_AUTO_HLS" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_HLS" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_HTTP_CALLBACK = YES ]; then + echo "#define SRS_AUTO_HTTP_CALLBACK" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_HTTP_CALLBACK" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_SSL = YES ]; then + echo "#define SRS_AUTO_SSL" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_SSL" >> $SRS_AUTO_HEADERS_H +fi + +# whether compile ffmpeg tool +if [ $SRS_FFMPEG_TOOL = YES ]; then + echo "#define SRS_AUTO_FFMPEG_TOOL" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_FFMPEG_TOOL" >> $SRS_AUTO_HEADERS_H +fi + +# whatever the FFMPEG tools, if transcode and ingest specified, +# srs always compile the FFMPEG tool stub which used to start the FFMPEG process. +if [ $SRS_FFMPEG_STUB = YES ]; then + echo "#define SRS_AUTO_FFMPEG_STUB" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_FFMPEG_STUB" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_TRANSCODE = YES ]; then + echo "#define SRS_AUTO_TRANSCODE" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_TRANSCODE" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_INGEST = YES ]; then + echo "#define SRS_AUTO_INGEST" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_INGEST" >> $SRS_AUTO_HEADERS_H +fi + +# for statistic. +if [ $SRS_STAT = YES ]; then + echo "#define SRS_AUTO_STAT" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_STAT" >> $SRS_AUTO_HEADERS_H +fi + +if [ $SRS_GPERF = YES ]; then + echo "#define SRS_AUTO_GPERF" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_GPERF" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_GPERF_MC = YES ]; then + echo "#define SRS_AUTO_GPERF_MC" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_GPERF_MC" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_GPERF_MP = YES ]; then + echo "#define SRS_AUTO_GPERF_MP" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_GPERF_MP" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_GPERF_CP = YES ]; then + echo "#define SRS_AUTO_GPERF_CP" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_GPERF_CP" >> $SRS_AUTO_HEADERS_H +fi + +##################################################################################### +# for embeded. +##################################################################################### +if [ $SRS_EMBEDED_CPU = YES ]; then + echo "#define SRS_AUTO_EMBEDED_CPU" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_EMBEDED_CPU" >> $SRS_AUTO_HEADERS_H +fi + +# arm +if [ $SRS_ARM_UBUNTU12 = YES ]; then + echo "#define SRS_AUTO_ARM_UBUNTU12" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_ARM_UBUNTU12" >> $SRS_AUTO_HEADERS_H +fi + +# mips +if [ $SRS_MIPS_UBUNTU12 = YES ]; then + echo "#define SRS_AUTO_MIPS_UBUNTU12" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_MIPS_UBUNTU12" >> $SRS_AUTO_HEADERS_H +fi + +echo "" >> $SRS_AUTO_HEADERS_H +# for log level compile settings +if [ $SRS_LOG_VERBOSE = YES ]; then + echo "#define SRS_AUTO_VERBOSE" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_VERBOSE" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_LOG_INFO = YES ]; then + echo "#define SRS_AUTO_INFO" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_INFO" >> $SRS_AUTO_HEADERS_H +fi +if [ $SRS_LOG_TRACE = YES ]; then + echo "#define SRS_AUTO_TRACE" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_TRACE" >> $SRS_AUTO_HEADERS_H +fi + +# prefix +echo "" >> $SRS_AUTO_HEADERS_H +echo "#define SRS_AUTO_PREFIX \"${SRS_PREFIX}\"" >> $SRS_AUTO_HEADERS_H + +echo "" >> $SRS_AUTO_HEADERS_H + +##################################################################################### +# generated the contributors from AUTHORS.txt +##################################################################################### +SRS_CONSTRIBUTORS=`cat ../AUTHORS.txt|grep "*"|awk '{print $2}'` +echo "#define SRS_AUTO_CONSTRIBUTORS \"\\" >> $SRS_AUTO_HEADERS_H +for CONTRIBUTOR in $SRS_CONSTRIBUTORS; do + echo "${CONTRIBUTOR} \\" >> $SRS_AUTO_HEADERS_H +done +echo "\"" >> $SRS_AUTO_HEADERS_H + +# new empty line to auto headers file. +echo "" >> $SRS_AUTO_HEADERS_H + +# auto header EOF. +echo "#endif" >> $SRS_AUTO_HEADERS_H +echo "" >> $SRS_AUTO_HEADERS_H + diff --git a/trunk/auto/build_ffmpeg.sh b/trunk/auto/build_ffmpeg.sh index b52d4ce94..19f6f7245 100755 --- a/trunk/auto/build_ffmpeg.sh +++ b/trunk/auto/build_ffmpeg.sh @@ -3,7 +3,7 @@ ff_src_dir="../../3rdparty" # the jobs to make ffmpeg -if [[ "" -eq SRS_JOBS ]]; then +if [[ "" == $SRS_JOBS ]]; then export SRS_JOBS="--jobs=1" fi @@ -38,9 +38,6 @@ fi # ffmpeg can specifies the yasm path when configure it. export PATH=${PATH}:${ff_release_dir}/bin -# the aac command for ffmepg. -AAC_FOR_FFMPEG="--enable-libfdk-aac" - # libfdk-aac if [[ -f ${ff_release_dir}/lib/libfdk-aac.a ]]; then echo "libfdk_aac is ok" @@ -52,24 +49,6 @@ else ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build fdk-aac-0.1.3 failed"; exit 1; fi fi -# libaacplus -if [ $UBUNTU14 = NO ]; then - AAC_FOR_FFMPEG="$AAC_FOR_FFMPEG --enable-libaacplus" - - if [[ -f ${ff_release_dir}/lib/libaacplus.a ]]; then - echo "libaacplus is ok" - else - echo "build libaacplus-2.0.2" - cd $ff_current_dir && - rm -rf libaacplus-2.0.2 && unzip -q ${ff_src_dir}/libaacplus-2.0.2.zip && - cd libaacplus-2.0.2 && cp ../${ff_src_dir}/libaacplus-patch-26410-800.zip src/26410-800.zip && - bash autogen.sh && ./configure --prefix=${ff_release_dir} --enable-static && make && make install - ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build libaacplus-2.0.2 failed"; exit 1; fi - fi -fi - -echo "aac for ffmepg: $AAC_FOR_FFMPEG" - # lame-3.99 if [[ -f ${ff_release_dir}/lib/libmp3lame.a ]]; then echo "libmp3lame is ok" @@ -128,7 +107,7 @@ else --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \ --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc \ --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ - --enable-libx264 --enable-libmp3lame $AAC_FOR_FFMPEG --enable-libspeex \ + --enable-libx264 --enable-libmp3lame --enable-libfdk-aac --enable-libspeex \ --enable-pthreads --extra-libs=-lpthread \ --enable-encoders --enable-decoders --enable-avfilter --enable-muxers --enable-demuxers && make ${SRS_JOBS} && make install diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index becd2c311..8aee3c73d 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -3,7 +3,6 @@ # variables, parent script must set it: # SRS_JOBS: the build jobs. # SrsArmMakeOptions: the arm make options for ubuntu12(armhf, v7cpu) -# SRS_AUTO_HEADERS_H: the auto generated header file. ##################################################################################### ##################################################################################### @@ -42,6 +41,24 @@ function Ubuntu_prepare() return 0; fi fi + + # for arm, install the cross build tool chain. + if [ $SRS_ARM_UBUNTU12 = YES ]; then + $SrsArmCC --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi" + require_sudoer "sudo apt-get install -y --force-yes gcc-arm-linux-gnueabi g++-arm-linux-gnueabi" + sudo apt-get install -y --force-yes gcc-arm-linux-gnueabi g++-arm-linux-gnueabi; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi success" + fi + fi + + # for mips, user must installed the tool chain. + if [ $SRS_MIPS_UBUNTU12 = YES ]; then + $SrsArmCC --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "user must install the tool chain: $SrsArmCC" + return 2 + fi + fi OS_IS_UBUNTU=YES echo "Ubuntu detected, install tools if needed" @@ -74,6 +91,13 @@ function Ubuntu_prepare() echo "install patch success" fi + unzip --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install unzip" + require_sudoer "sudo apt-get install -y --force-yes unzip" + sudo apt-get install -y --force-yes unzip; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install unzip success" + fi + if [ $SRS_FFMPEG_TOOL = YES ]; then autoconf --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then echo "install autoconf" @@ -104,24 +128,6 @@ function Ubuntu_prepare() fi fi - # for arm, install the cross build tool chain. - if [ $SRS_ARM_UBUNTU12 = YES ]; then - $SrsArmCC --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then - echo "install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi" - require_sudoer "sudo apt-get install -y --force-yes gcc-arm-linux-gnueabi g++-arm-linux-gnueabi" - sudo apt-get install -y --force-yes gcc-arm-linux-gnueabi g++-arm-linux-gnueabi; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi - echo "install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi success" - fi - fi - - # for mips, user must installed the tool chain. - if [ $SRS_MIPS_UBUNTU12 = YES ]; then - $SrsArmCC --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then - echo "user must install the tool chain: $SrsArmCC" - return 2 - fi - fi - echo "Ubuntu install tools success" return 0 } @@ -138,6 +144,12 @@ function Centos_prepare() if [[ ! -f /etc/redhat-release ]]; then return 0; fi + + # for arm, install the cross build tool chain. + if [ $SRS_EMBEDED_CPU = YES ]; then + echo "embeded(arm/mips) is invalid for CentOS" + return 1 + fi OS_IS_CENTOS=YES echo "Centos detected, install tools if needed" @@ -170,6 +182,13 @@ function Centos_prepare() echo "install patch success" fi + unzip --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install unzip" + require_sudoer "sudo yum install -y unzip" + sudo yum install -y unzip; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install unzip success" + fi + if [ $SRS_FFMPEG_TOOL = YES ]; then automake --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then echo "install automake" @@ -207,12 +226,6 @@ function Centos_prepare() fi fi - # for arm, install the cross build tool chain. - if [ $SRS_EMBEDED_CPU = YES ]; then - echo "embeded(arm/mips) is invalid for CentOS" - return 1 - fi - echo "Centos install tools success" return 0 } @@ -220,13 +233,151 @@ function Centos_prepare() if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then Centos_prepare; ret=$?; if [[ 0 -ne $ret ]]; then echo "CentOS prepare failed, ret=$ret"; exit $ret; fi fi +##################################################################################### +# for Centos, auto install tools by yum +##################################################################################### +OS_IS_OSX=NO +function OSX_prepare() +{ + uname -s|grep Darwin >/dev/null 2>&1 + ret=$?; if [[ 0 -ne $ret ]]; then + if [ $SRS_OSX = YES ]; then + echo "OSX check failed, actual is `uname -s`" + exit 1; + fi + return 0; + fi + + # for arm, install the cross build tool chain. + if [ $SRS_EMBEDED_CPU = YES ]; then + echo "embeded(arm/mips) is invalid for OSX" + return 1 + fi + + OS_IS_OSX=YES + echo "OSX detected, install tools if needed" + + brew --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install brew" + echo "ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"" + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install brew success" + fi + + gcc --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install gcc" + echo "brew install gcc" + brew install gcc; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install gcc success" + fi + + g++ --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install gcc-c++" + echo "brew install gcc-c++" + brew install gcc-c++; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install gcc-c++ success" + fi + + make --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install make" + echo "brew install make" + brew install make; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install make success" + fi + + patch --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install patch" + echo "brew install patch" + brew install patch; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install patch success" + fi + + unzip --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install unzip" + echo "brew install unzip" + brew install unzip; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install unzip success" + fi + + if [ $SRS_FFMPEG_TOOL = YES ]; then + automake --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install automake" + echo "brew install automake" + brew install automake; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install automake success" + fi + + autoconf --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install autoconf" + echo "brew install autoconf" + brew install autoconf; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install autoconf success" + fi + + libtool --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "install libtool" + echo "brew install libtool" + brew install libtool; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install libtool success" + fi + + if [[ ! -f /usr/include/pcre.h ]]; then + echo "install pcre-devel" + echo "brew install pcre-devel" + brew install pcre-devel; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install pcre-devel success" + fi + + if [[ ! -f /usr/include/zlib.h ]]; then + echo "install zlib-devel" + echo "brew install zlib-devel" + brew install zlib-devel; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi + echo "install zlib-devel success" + fi + fi + + echo "OSX install tools success" + return 0 +} +# donot prepare tools, for srs-librtmp depends only gcc and g++. +if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then + OSX_prepare; ret=$?; if [[ 0 -ne $ret ]]; then echo "OSX prepare failed, ret=$ret"; exit $ret; fi +fi +# requires the osx when os +if [ $OS_IS_OSX = YES ]; then + if [ $SRS_OSX = NO ]; then + echo "OSX detected, must specifies the --osx" + exit 1 + fi + # TODO: FIXME: support following features. + if [ $SRS_HTTP_API = YES ]; then + echo "OSX does not support http-api, use --without-http-api" + exit 1 + fi + if [ $SRS_STAT = YES ]; then + echo "OSX does not support stat, use --without-stat" + exit 1 + fi + if [ $SRS_FFMPEG_TOOL = YES ]; then + echo "OSX does not support ffmpeg, use --without-ffmpeg" + exit 1 + fi + if [ $SRS_NGINX = YES ]; then + echo "OSX does not support nginx, use --without-nginx" + exit 1 + fi +fi ##################################################################################### # st-1.9 ##################################################################################### if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then # check the arm flag file, if flag changed, need to rebuild the st. - _ST_MAKE=linux-debug + _ST_MAKE=linux-debug && _ST_EXTRA_CFLAGS="-DMD_HAVE_EPOLL" + # for osx, use darwin for st, donot use epoll. + if [ $OS_IS_OSX = YES ]; then + _ST_MAKE=darwin-debug && _ST_EXTRA_CFLAGS="" + fi # memory leak for linux-optimized # @see: https://github.com/winlinvip/simple-rtmp-server/issues/197 if [ $SRS_EMBEDED_CPU = YES ]; then @@ -240,9 +391,9 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then ( rm -rf ${SRS_OBJS}/st-1.9 && cd ${SRS_OBJS} && unzip -q ../3rdparty/st-1.9.zip && cd st-1.9 && - patch -p0 < ../../3rdparty/patches/1.st.arm.patch && + patch -p0 -R < ../../3rdparty/patches/1.st.arm.patch && make CC=${SrsArmCC} AR=${SrsArmAR} LD=${SrsArmLD} RANDLIB=${SrsArmRANDLIB} \ - EXTRA_CFLAGS="-DMD_HAVE_EPOLL" ${_ST_MAKE} && + EXTRA_CFLAGS=${_ST_EXTRA_CFLAGS} ${_ST_MAKE} && cd .. && rm -rf st && ln -sf st-1.9/obj st && cd .. && touch ${SRS_OBJS}/_flag.st.arm.tmp ) @@ -255,7 +406,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then ( rm -rf ${SRS_OBJS}/st-1.9 && cd ${SRS_OBJS} && unzip -q ../3rdparty/st-1.9.zip && cd st-1.9 && - make ${_ST_MAKE} EXTRA_CFLAGS="-DMD_HAVE_EPOLL" && + make ${_ST_MAKE} ${_ST_EXTRA_CFLAGS} && cd .. && rm -rf st && ln -sf st-1.9/obj st && cd .. && rm -f ${SRS_OBJS}/_flag.st.arm.tmp ) @@ -280,6 +431,7 @@ if [ $SRS_HTTP_PARSER = YES ]; then ( rm -rf ${SRS_OBJS}/http-parser-2.1 && cd ${SRS_OBJS} && unzip -q ../3rdparty/http-parser-2.1.zip && cd http-parser-2.1 && + patch -p0 -R < ../../3rdparty/patches/2.http.parser.patch && sed -i "s/CPPFLAGS_FAST +=.*$/CPPFLAGS_FAST = \$\(CPPFLAGS_DEBUG\)/g" Makefile && sed -i "s/CFLAGS_FAST =.*$/CFLAGS_FAST = \$\(CFLAGS_DEBUG\)/g" Makefile && make CC=${SrsArmCC} AR=${SrsArmAR} package && @@ -296,8 +448,7 @@ if [ $SRS_HTTP_PARSER = YES ]; then ( rm -rf ${SRS_OBJS}/http-parser-2.1 && cd ${SRS_OBJS} && unzip -q ../3rdparty/http-parser-2.1.zip && cd http-parser-2.1 && - sed -i "s/CPPFLAGS_FAST +=.*$/CPPFLAGS_FAST = \$\(CPPFLAGS_DEBUG\)/g" Makefile && - sed -i "s/CFLAGS_FAST =.*$/CFLAGS_FAST = \$\(CFLAGS_DEBUG\)/g" Makefile && + patch -p0 -R < ../../3rdparty/patches/2.http.parser.patch && make package && cd .. && rm -rf hp && ln -sf http-parser-2.1 hp && cd .. && rm -f ${SRS_OBJS}/_flag.st.hp.tmp @@ -311,30 +462,6 @@ if [ $SRS_HTTP_PARSER = YES ]; then if [[ ! -f ${SRS_OBJS}/hp/libhttp_parser.a ]]; then echo "build http-parser-2.1 failed"; exit -1; fi fi -if [ $SRS_HTTP_PARSER = YES ]; then - echo "#define SRS_AUTO_HTTP_PARSER" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_HTTP_PARSER" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_HTTP_SERVER = YES ]; then - echo "#define SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_STREAM_CASTER = YES ]; then - echo "#define SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_HTTP_API = YES ]; then - echo "#define SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H -fi - ##################################################################################### # nginx for HLS, nginx-1.5.0 ##################################################################################### @@ -406,24 +533,6 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then echo "nginx is ok" > ${SRS_OBJS}/nginx/html/nginx.html fi -if [ $SRS_NGINX = YES ]; then - echo "#define SRS_AUTO_NGINX" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_NGINX" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_DVR = YES ]; then - echo "#define SRS_AUTO_DVR" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_DVR" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_HLS = YES ]; then - echo "#define SRS_AUTO_HLS" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_HLS" >> $SRS_AUTO_HEADERS_H -fi - ##################################################################################### # cherrypy for http hooks callback, CherryPy-3.2.4 ##################################################################################### @@ -431,7 +540,7 @@ if [ $SRS_HTTP_CALLBACK = YES ]; then if [[ -f ${SRS_OBJS}/CherryPy-3.2.4/setup.py ]]; then echo "CherryPy-3.2.4 is ok."; else - require_sudoer "configure --with-http-callback" + require_sudoer "install CherryPy-3.2.4" echo "install CherryPy-3.2.4"; ( sudo rm -rf ${SRS_OBJS}/CherryPy-3.2.4 && cd ${SRS_OBJS} && @@ -444,12 +553,6 @@ if [ $SRS_HTTP_CALLBACK = YES ]; then if [ ! -f ${SRS_OBJS}/CherryPy-3.2.4/setup.py ]; then echo "build CherryPy-3.2.4 failed."; exit -1; fi fi -if [ $SRS_HTTP_CALLBACK = YES ]; then - echo "#define SRS_AUTO_HTTP_CALLBACK" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_HTTP_CALLBACK" >> $SRS_AUTO_HEADERS_H -fi - if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then echo "link players to cherrypy static-dir" rm -rf research/api-server/static-dir/players && @@ -489,9 +592,11 @@ fi ##################################################################################### # extra configure options CONFIGURE_TOOL="./config" -EXTRA_CONFIGURE="" if [ $SRS_EMBEDED_CPU = YES ]; then - CONFIGURE_TOOL="./Configure" + CONFIGURE_TOOL="./Configure linux-armv4" +fi +if [ $SRS_OSX = YES ]; then + CONFIGURE_TOOL="./Configure darwin64-`uname -m`-cc" fi # @see http://www.openssl.org/news/secadv_20140407.txt # Affected users should upgrade to OpenSSL 1.0.1g. Users unable to immediately @@ -510,7 +615,7 @@ if [ $SRS_SSL = YES ]; then ( rm -rf ${SRS_OBJS}/openssl-1.0.1f && cd ${SRS_OBJS} && unzip -q ../3rdparty/openssl-1.0.1f.zip && cd openssl-1.0.1f && - $CONFIGURE_TOOL --prefix=`pwd`/_release -no-shared no-asm linux-armv4 -DOPENSSL_NO_HEARTBEATS ${EXTRA_CONFIGURE} && + $CONFIGURE_TOOL --prefix=`pwd`/_release -no-shared no-asm && make CC=${SrsArmCC} GCC=${SrsArmGCC} AR="${SrsArmAR} r" \ LD=${SrsArmLD} LINK=${SrsArmGCC} RANDLIB=${SrsArmRANDLIB} && make install_sw && @@ -527,7 +632,7 @@ if [ $SRS_SSL = YES ]; then ( rm -rf ${SRS_OBJS}/openssl-1.0.1f && cd ${SRS_OBJS} && unzip -q ../3rdparty/openssl-1.0.1f.zip && cd openssl-1.0.1f && - $CONFIGURE_TOOL --prefix=`pwd`/_release -no-shared -DOPENSSL_NO_HEARTBEATS ${EXTRA_CONFIGURE} && + $CONFIGURE_TOOL --prefix=`pwd`/_release -no-shared && make && make install_sw && cd .. && rm -rf openssl && ln -sf openssl-1.0.1f/_release openssl && cd .. && rm -f ${SRS_OBJS}/_flag.ssl.arm.tmp @@ -540,12 +645,6 @@ if [ $SRS_SSL = YES ]; then fi fi -if [ $SRS_SSL = YES ]; then - echo "#define SRS_AUTO_SSL" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_SSL" >> $SRS_AUTO_HEADERS_H -fi - ##################################################################################### # live transcoding, ffmpeg-2.1, x264-core138, lame-3.99.5, libaacplus-2.0.2. ##################################################################################### @@ -566,40 +665,6 @@ if [ $SRS_FFMPEG_TOOL = YES ]; then if [ ! -f ${SRS_OBJS}/ffmpeg/bin/ffmpeg ]; then echo "build ffmpeg-2.1 failed."; exit -1; fi fi -# whether compile ffmpeg tool -if [ $SRS_FFMPEG_TOOL = YES ]; then - echo "#define SRS_AUTO_FFMPEG_TOOL" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_FFMPEG_TOOL" >> $SRS_AUTO_HEADERS_H -fi - -# whatever the FFMPEG tools, if transcode and ingest specified, -# srs always compile the FFMPEG tool stub which used to start the FFMPEG process. -if [ $SRS_FFMPEG_STUB = YES ]; then - echo "#define SRS_AUTO_FFMPEG_STUB" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_FFMPEG_STUB" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_TRANSCODE = YES ]; then - echo "#define SRS_AUTO_TRANSCODE" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_TRANSCODE" >> $SRS_AUTO_HEADERS_H -fi - -if [ $SRS_INGEST = YES ]; then - echo "#define SRS_AUTO_INGEST" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_INGEST" >> $SRS_AUTO_HEADERS_H -fi - -# for statistic. -if [ $SRS_STAT = YES ]; then - echo "#define SRS_AUTO_STAT" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_STAT" >> $SRS_AUTO_HEADERS_H -fi - ##################################################################################### # build research code, librtmp ##################################################################################### @@ -663,89 +728,8 @@ if [ $SRS_GPERF = YES ]; then if [ ! -f ${SRS_OBJS}/gperf/bin/pprof ]; then echo "build gperftools-2.1 failed."; exit -1; fi fi -if [ $SRS_GPERF = YES ]; then - echo "#define SRS_AUTO_GPERF" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_GPERF" >> $SRS_AUTO_HEADERS_H -fi -if [ $SRS_GPERF_MC = YES ]; then - echo "#define SRS_AUTO_GPERF_MC" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_GPERF_MC" >> $SRS_AUTO_HEADERS_H -fi -if [ $SRS_GPERF_MP = YES ]; then - echo "#define SRS_AUTO_GPERF_MP" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_GPERF_MP" >> $SRS_AUTO_HEADERS_H -fi -if [ $SRS_GPERF_CP = YES ]; then - echo "#define SRS_AUTO_GPERF_CP" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_GPERF_CP" >> $SRS_AUTO_HEADERS_H -fi - -##################################################################################### -# for embeded. -##################################################################################### -if [ $SRS_EMBEDED_CPU = YES ]; then - echo "#define SRS_AUTO_EMBEDED_CPU" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_EMBEDED_CPU" >> $SRS_AUTO_HEADERS_H -fi - -# arm -if [ $SRS_ARM_UBUNTU12 = YES ]; then - echo "#define SRS_AUTO_ARM_UBUNTU12" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_ARM_UBUNTU12" >> $SRS_AUTO_HEADERS_H -fi - -# mips -if [ $SRS_MIPS_UBUNTU12 = YES ]; then - echo "#define SRS_AUTO_MIPS_UBUNTU12" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_MIPS_UBUNTU12" >> $SRS_AUTO_HEADERS_H -fi - -echo "" >> $SRS_AUTO_HEADERS_H - -# for log level compile settings -if [ $SRS_LOG_VERBOSE = YES ]; then - echo "#define SRS_AUTO_VERBOSE" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_VERBOSE" >> $SRS_AUTO_HEADERS_H -fi -if [ $SRS_LOG_INFO = YES ]; then - echo "#define SRS_AUTO_INFO" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_INFO" >> $SRS_AUTO_HEADERS_H -fi -if [ $SRS_LOG_TRACE = YES ]; then - echo "#define SRS_AUTO_TRACE" >> $SRS_AUTO_HEADERS_H -else - echo "#undef SRS_AUTO_TRACE" >> $SRS_AUTO_HEADERS_H -fi - -# prefix -echo "" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_PREFIX \"${SRS_PREFIX}\"" >> $SRS_AUTO_HEADERS_H - -echo "" >> $SRS_AUTO_HEADERS_H - -##################################################################################### -# generated the contributors from AUTHORS.txt -##################################################################################### -SRS_CONSTRIBUTORS=`cat ../AUTHORS.txt|grep "*"|awk '{print $2}'` -echo "#define SRS_AUTO_CONSTRIBUTORS \"\\" >> $SRS_AUTO_HEADERS_H -for CONTRIBUTOR in $SRS_CONSTRIBUTORS; do - echo "${CONTRIBUTOR} \\" >> $SRS_AUTO_HEADERS_H -done -echo "\"" >> $SRS_AUTO_HEADERS_H - -# new empty line to auto headers file. -echo "" >> $SRS_AUTO_HEADERS_H - ##################################################################################### # generated the test script ##################################################################################### rm -rf ${SRS_OBJS}/srs.test && ln -sf `pwd`/scripts/srs.test objs/srs.test + diff --git a/trunk/auto/libs.sh b/trunk/auto/libs.sh index 6e1eedaf9..2795aed7e 100755 --- a/trunk/auto/libs.sh +++ b/trunk/auto/libs.sh @@ -57,7 +57,7 @@ done echo "" >> ${FILE} # parent Makefile, to create module output dir before compile it. -echo " mkdir -p ${SRS_OBJS_DIR}/include" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} -echo " mkdir -p ${SRS_OBJS_DIR}/lib" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +echo " @mkdir -p ${SRS_OBJS_DIR}/include" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +echo " @mkdir -p ${SRS_OBJS_DIR}/lib" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} echo -n "generate lib ${LIB_NAME} ok"; echo '!'; diff --git a/trunk/auto/modules.sh b/trunk/auto/modules.sh index 9b4af71b5..ed91b611e 100755 --- a/trunk/auto/modules.sh +++ b/trunk/auto/modules.sh @@ -85,6 +85,6 @@ done echo "" >> ${FILE} # parent Makefile, to create module output dir before compile it. -echo " mkdir -p ${SRS_OBJS_DIR}/${MODULE_DIR}" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +echo " @mkdir -p ${SRS_OBJS_DIR}/${MODULE_DIR}" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} echo -n "generate module ${MODULE_ID} ok"; echo '!'; diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index adec4828a..d4e8b723d 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -68,6 +68,8 @@ SRS_EXPORT_LIBRTMP_SINGLE=NO # presets # for x86/x64 pc/servers SRS_X86_X64=NO +# for osx system +SRS_OSX=NO # armhf(v7cpu) built on ubuntu12 SRS_ARM_UBUNTU12=NO # mips built on ubuntu12 @@ -166,6 +168,7 @@ Options: Presets: --x86-x64 [default] for x86/x64 cpu, common pc and servers. + --osx for osx(darwin) system to build SRS. --pi for raspberry-pi(directly build), open features hls/ssl/static. --cubie for cubieboard(directly build), open features except ffmpeg/nginx. --arm alias for --with-arm-ubuntu12, for ubuntu12, arm crossbuild @@ -260,6 +263,7 @@ function parse_user_option() { --log-trace) SRS_LOG_TRACE=YES ;; --x86-x64) SRS_X86_X64=YES ;; + --osx) SRS_OSX=YES ;; --arm) SRS_ARM_UBUNTU12=YES ;; --mips) SRS_MIPS_UBUNTU12=YES ;; --pi) SRS_PI=YES ;; @@ -331,7 +335,9 @@ function apply_user_presets() { if [ $SRS_PI = NO ]; then if [ $SRS_CUBIE = NO ]; then if [ $SRS_X86_X64 = NO ]; then - SRS_X86_X64=YES; opt="--x86-x64 $opt"; + if [ $SRS_OSX = NO ]; then + SRS_X86_X64=YES; opt="--x86-x64 $opt"; + fi fi fi fi @@ -563,6 +569,32 @@ function apply_user_presets() { SRS_STATIC=NO fi + # for osx(darwin) + if [ $SRS_OSX = YES ]; then + SRS_HLS=YES + SRS_DVR=YES + SRS_NGINX=NO + SRS_SSL=YES + SRS_FFMPEG_TOOL=NO + SRS_TRANSCODE=YES + SRS_INGEST=YES + SRS_STAT=NO + SRS_HTTP_PARSER=YES + SRS_HTTP_CALLBACK=YES + SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES + SRS_HTTP_API=NO + SRS_LIBRTMP=YES + SRS_RESEARCH=NO + SRS_UTEST=NO + SRS_GPERF=NO + SRS_GPERF_MC=NO + SRS_GPERF_MP=NO + SRS_GPERF_CP=NO + SRS_GPROF=NO + SRS_STATIC=NO + fi + # if dev specified, open features if possible. if [ $SRS_DEV = YES ]; then SRS_HLS=YES diff --git a/trunk/auto/utest.sh b/trunk/auto/utest.sh index 79477686f..f789e8a84 100755 --- a/trunk/auto/utest.sh +++ b/trunk/auto/utest.sh @@ -176,6 +176,6 @@ END ##################################################################################### # parent Makefile, to create module output dir before compile it. -echo " mkdir -p ${SRS_OBJS_DIR}/utest" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +echo " @mkdir -p ${SRS_OBJS_DIR}/utest" >> ${SRS_WORKDIR}/${SRS_MAKEFILE} echo -n "generate utest ok"; echo '!'; diff --git a/trunk/conf/demo.conf b/trunk/conf/demo.conf index 06d7ee4ad..362fb9d0a 100644 --- a/trunk/conf/demo.conf +++ b/trunk/conf/demo.conf @@ -82,7 +82,7 @@ vhost demo.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -105,7 +105,7 @@ vhost demo.srs.com { vpreset fast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 40; asample_rate 44100; achannels 2; @@ -151,7 +151,7 @@ vhost players { vparams { g 100; } - acodec libaacplus; + acodec libfdk_aac; abitrate 30; asample_rate 44100; achannels 2; diff --git a/trunk/conf/ffmpeg.transcode.conf b/trunk/conf/ffmpeg.transcode.conf index 04c434982..66c63cfbc 100644 --- a/trunk/conf/ffmpeg.transcode.conf +++ b/trunk/conf/ffmpeg.transcode.conf @@ -22,7 +22,7 @@ vhost __defaultVhost__ { vpreset medium; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 70; asample_rate 44100; achannels 2; diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 2d875e0ee..d95954c5f 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -180,6 +180,8 @@ stream_caster { caster rtsp; output rtmp://127.0.0.1/[app]/[stream]; listen 554; + rtp_port_min 57200; + rtp_port_max 57300; } ############################################################################################# @@ -288,44 +290,7 @@ vhost dvr.srs.com { # session reap flv when session end(unpublish). # segment reap flv when flv duration exceed the specified dvr_duration. # append always append to flv file, never reap it. - # api reap flv when api required. - # about the api plan, the HTTP api to dvr, - # http url to control dvr, for example, http://dev:1985/api/v1/dvrs - # method=GET - # to query dvrs of server. - # request params, for example ?vhost=__defaultVhost__, where: - # vhost, query all dvr of this vhost. - # response in json, where: - # {code:0, dvrs: [{path_tmpl:"./[15].[04].[05].[999].flv", path_dvr:"./22.7.43.312.flv", - # wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs", - # status:"stop"|"start" - # }]} - # method=POST - # to start dvr of specified vhost. - # request should encode in json, specifies the dvr to create, where: - # {path_tmpl:"./[15].[04].[05].[999].flv", - # wait_keyframe:true, vhost:"__defaultVhost", callback:"http://127.0.0.1:8085/api/v1/dvrs" - # } - # response in json, where: - # {code:0} - # method=DELETE, to stop dvr - # to stop dvr of specified vhost. - # request params, for example ?vhost=__defaultVhost__, where: - # vhost, stop all dvr of this vhost. - # response in json, where: - # {code:0} - # method=PUT, use as RPC(remote process call). - # reap_segment, the request params in json, where: - # {action:"reap_segment", vhost:"__defaultVhost", path_tmpl:"./[15].[04].[05].[999].flv"} - # when reap segment, the callback POST request in json: - # {action:"on_dvr_reap_segment", client_id:100, vhost:"__defaultVhost__", - # app:"live", stream:"livestream", cwd:"/home/winlin/srs", file:"./dvr.flv" - # } - # for the dvr http callback, @see http_hooks.on_dvr of vhost hooks.callback.srs.com - # @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#http-callback - # @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#http-callback # default: session - # TODO: FIXME: update wiki for the api plan. dvr_plan session; # the dvr output path. # we supports some variables to generate the filename. @@ -361,27 +326,20 @@ vhost dvr.srs.com { # @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path # @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path # segment,session apply it. - # api apply before api specified the path. # default: ./objs/nginx/html dvr_path ./objs/nginx/html; # the duration for dvr file, reap if exeed, in seconds. # segment apply it. - # session,api ignore. + # session,append ignore. # default: 30 dvr_duration 30; # whether wait keyframe to reap segment, # if off, reap segment when duration exceed the dvr_duration, # if on, reap segment when duration exceed and got keyframe. # segment apply it. - # session,api ignore. + # session,append ignore. # default: on dvr_wait_keyframe on; - # whether dvr auto start when publish. - # if off, dvr wait for api to start it. - # api apply it. - # segment,session ignore. - # default: on - dvr_autostart on; # about the stream monotonically increasing: # 1. video timestamp is monotonically increasing, # 2. audio timestamp is monotonically increasing, @@ -576,7 +534,6 @@ vhost with-hls.srs.com { # the available audio codec: # aac, mp3 # default: aac - # TODO: FIXME: update wiki for it. hls_acodec aac; # the default video codec of hls. # when codec changed, write the PAT/PMT table, but maybe ok util next ts. @@ -584,7 +541,6 @@ vhost with-hls.srs.com { # the available video codec: # h264, vn # default: h264 - # TODO: FIXME: update wiki for it. hls_vcodec h264; } } @@ -832,12 +788,11 @@ vhost example.transcode.srs.com { refs 10; } # audio encoder name. can be: - # libaacplus: use aac(libaacplus) audio encoder. # libfdk_aac: use aac(libfdk_aac) audio encoder. # copy: donot encoder the audio stream, copy it. # an: disable audio output. - acodec libaacplus; - # audio bitrate, in kbps. [16, 72] for libaacplus. + acodec libfdk_aac; + # audio bitrate, in kbps. [16, 72] for libfdk_aac. abitrate 70; # audio sample rate. for flv/rtmp, it must be: # 44100,22050,11025,5512 @@ -847,6 +802,7 @@ vhost example.transcode.srs.com { # other ffmpeg audio params aparams { # audio params, @see: http://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders + # @remark SRS supported aac profile for HLS is: aac_low, aac_he, aac_he_v2 profile:a aac_low; } # output format, can be: @@ -885,7 +841,7 @@ vhost mirror.transcode.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -918,7 +874,7 @@ vhost crop.transcode.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -949,7 +905,7 @@ vhost logo.transcode.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -969,7 +925,7 @@ vhost audio.transcode.srs.com { engine acodec { enabled on; vcodec copy; - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -988,7 +944,7 @@ vhost vn.transcode.srs.com { engine vn { enabled on; vcodec vn; - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -1040,7 +996,7 @@ vhost all.transcode.srs.com { bf 3; refs 10; } - acodec libaacplus; + acodec libfdk_aac; abitrate 70; asample_rate 44100; achannels 2; @@ -1062,7 +1018,7 @@ vhost all.transcode.srs.com { vpreset medium; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 70; asample_rate 44100; achannels 2; @@ -1082,7 +1038,7 @@ vhost all.transcode.srs.com { vpreset fast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 60; asample_rate 44100; achannels 2; @@ -1102,7 +1058,7 @@ vhost all.transcode.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -1113,7 +1069,7 @@ vhost all.transcode.srs.com { engine vcopy { enabled on; vcodec copy; - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; @@ -1161,7 +1117,7 @@ vhost ffempty.transcode.srs.com { vpreset superfast; vparams { } - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; diff --git a/trunk/conf/hds.conf b/trunk/conf/hds.conf new file mode 100644 index 000000000..ade6f5b27 --- /dev/null +++ b/trunk/conf/hds.conf @@ -0,0 +1,19 @@ +# the config for srs to delivery hds +# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_SampleHDS +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; + +daemon off; +srs_log_tank console; +srs_log_level trace; + +vhost __defaultVhost__ { + hds { + enabled on; + hds_fragment 10; + hds_window 60; + hds_path ./objs/nginx/html; + } +} diff --git a/trunk/conf/mac.dev.conf b/trunk/conf/mac.dev.conf new file mode 100644 index 000000000..e624e165b --- /dev/null +++ b/trunk/conf/mac.dev.conf @@ -0,0 +1,36 @@ +# no-daemon and write log to console config for srs. +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; +http_api { + enabled on; + listen 1985; +} +http_server { + enabled on; + listen 8080; +} +vhost __defaultVhost__ { + hls { + enabled on; + hls_fragment 10; + hls_window 60; + hls_path ./objs/nginx/html; + } + ingest livestream { + enabled on; + input { + type file; + url ./doc/source.200kbps.768x320.flv; + } + #ffmpeg ./objs/ffmpeg/bin/ffmpeg; + ffmpeg ./objs/research/librtmp/srs_ingest_flv; + engine { + enabled off; + output rtmp://127.0.0.1:[port]/live?vhost=[vhost]/livestream; + } + } +} diff --git a/trunk/conf/push.rtsp.conf b/trunk/conf/push.rtsp.conf new file mode 100644 index 000000000..ab3486b68 --- /dev/null +++ b/trunk/conf/push.rtsp.conf @@ -0,0 +1,17 @@ +# push MPEG-TS over UDP to SRS. +# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_Streamer#push-mpeg-ts-over-udp +# @see https://github.com/winlinvip/simple-rtmp-server/issues/250#issuecomment-72321769 +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +stream_caster { + enabled on; + caster rtsp; + output rtmp://127.0.0.1/[app]/[stream]; + listen 554; + rtp_port_min 57200; + rtp_port_max 57300; +} +vhost __defaultVhost__ { +} diff --git a/trunk/conf/transcode2hls.audio.only.conf b/trunk/conf/transcode2hls.audio.only.conf index 69eb9525c..addd00e43 100644 --- a/trunk/conf/transcode2hls.audio.only.conf +++ b/trunk/conf/transcode2hls.audio.only.conf @@ -17,7 +17,7 @@ vhost __defaultVhost__ { engine ff { enabled on; vcodec copy; - acodec libaacplus; + acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; diff --git a/trunk/configure b/trunk/configure index 636289872..e94cc15d8 100755 --- a/trunk/configure +++ b/trunk/configure @@ -7,14 +7,24 @@ SRS_WORKDIR="." SRS_OBJS_DIR="objs" SRS_OBJS="${SRS_WORKDIR}/${SRS_OBJS_DIR}" -mkdir -p ${SRS_OBJS} +SRS_MAKEFILE="Makefile" -##################################################################################### # linux shell color support. -RED="\\e[31m" -GREEN="\\e[32m" -YELLOW="\\e[33m" -BLACK="\\e[0m" +RED="\\033[31m" +GREEN="\\033[32m" +YELLOW="\\033[33m" +BLACK="\\033[0m" + +# clean the exists, when not export srs-librtmp. +# do this only when the options is ok. +if [[ -f Makefile ]]; then + make clean +fi +# remove makefile +rm -f ${SRS_WORKDIR}/${SRS_MAKEFILE} + +# create objs +mkdir -p ${SRS_OBJS} ##################################################################################### # parse user options, set the variables like: @@ -27,82 +37,18 @@ BLACK="\\e[0m" # for export srs-librtmp, change target to it. . auto/generate-srs-librtmp-project.sh -# the auto generated variables. -SRS_AUTO_HEADERS_H="${SRS_OBJS}/srs_auto_headers.hpp" - -# clean the exists, when not export srs-librtmp. -# do this only when the options is ok. -if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then - if [[ -f Makefile ]]; then - make clean - fi -fi - -# write user options to headers -echo "// auto generated by configure" > $SRS_AUTO_HEADERS_H -echo "#ifndef SRS_AUTO_HEADER_HPP" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_HEADER_HPP" >> $SRS_AUTO_HEADERS_H -echo "" >> $SRS_AUTO_HEADERS_H - -echo "#define SRS_AUTO_BUILD_TS \"`date +%s`\"" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_BUILD_DATE \"`date \"+%Y-%m-%d %H:%M:%S\"`\"" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_UNAME \"`uname -a`\"" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_USER_CONFIGURE \"${SRS_AUTO_USER_CONFIGURE}\"" >> $SRS_AUTO_HEADERS_H -echo "#define SRS_AUTO_CONFIGURE \"${SRS_AUTO_CONFIGURE}\"" >> $SRS_AUTO_HEADERS_H - -# new empty line to auto headers file. -echo "" >> $SRS_AUTO_HEADERS_H - -##################################################################################### -# generate auto headers file, depends on the finished of options.sh -##################################################################################### -if [ $SRS_ARM_UBUNTU12 = YES ]; then - __SrsArmCC="arm-linux-gnueabi-gcc"; - __SrsArmGCC="arm-linux-gnueabi-gcc"; - __SrsArmCXX="arm-linux-gnueabi-g++"; - __SrsArmAR="arm-linux-gnueabi-ar"; - __SrsArmLD="arm-linux-gnueabi-ld"; - __SrsArmRANDLIB="arm-linux-gnueabi-ranlib"; -fi -if [ $SRS_MIPS_UBUNTU12 = YES ]; then - __SrsArmCC="mipsel-openwrt-linux-gcc"; - __SrsArmGCC="mipsel-openwrt-linux-gcc"; - __SrsArmCXX="mipsel-openwrt-linux-g++"; - __SrsArmAR="mipsel-openwrt-linux-ar"; - __SrsArmLD="mipsel-openwrt-linux-ld"; - __SrsArmRANDLIB="mipsel-openwrt-linux-ranlib"; -fi -# the arm-ubuntu12 options for make for depends -if [[ -z $SrsArmCC ]]; then SrsArmCC=$__SrsArmCC; fi -if [[ -z $SrsArmGCC ]]; then SrsArmGCC=$__SrsArmGCC; fi -if [[ -z $SrsArmCXX ]]; then SrsArmCXX=$__SrsArmCXX; fi -if [[ -z $SrsArmAR ]]; then SrsArmAR=$__SrsArmAR; fi -if [[ -z $SrsArmLD ]]; then SrsArmLD=$__SrsArmLD; fi -if [[ -z $SrsArmRANDLIB ]]; then SrsArmRANDLIB=$__SrsArmRANDLIB; fi -# write to source file -if [ $SRS_EMBEDED_CPU = YES ]; then - echo "cc=$SrsArmCC gcc=$SrsArmGCC g++=$SrsArmCXX ar=$SrsArmAR ld=$SrsArmLD randlib=$SrsArmRANDLIB" - echo "#define SRS_AUTO_EMBEDED_TOOL_CHAIN \"cc=$SrsArmCC gcc=$SrsArmGCC g++=$SrsArmCXX ar=$SrsArmAR ld=$SrsArmLD randlib=$SrsArmRANDLIB\"" >> $SRS_AUTO_HEADERS_H -else - echo "#define SRS_AUTO_EMBEDED_TOOL_CHAIN \"normal x86/x64 gcc\"" >> $SRS_AUTO_HEADERS_H -fi -echo "" >> $SRS_AUTO_HEADERS_H - # apply user options. . auto/depends.sh -# auto header EOF. -echo "#endif" >> $SRS_AUTO_HEADERS_H -echo "" >> $SRS_AUTO_HEADERS_H +# the auto generated variables. +. auto/auto_headers.sh ##################################################################################### # generate Makefile. ##################################################################################### -SRS_MAKEFILE="Makefile" # ubuntu echo in Makefile cannot display color, use bash instead SRS_BUILD_SUMMARY="_srs_build_summary.sh" -##################################################################################### # srs-librtmp sample entry SrsLibrtmpSampleEntry="nossl" if [ $SRS_SSL = YES ]; then SrsLibrtmpSampleEntry="ssl";fi @@ -110,6 +56,203 @@ if [ $SRS_SSL = YES ]; then SrsLibrtmpSampleEntry="ssl";fi SrsUtestMakeEntry="@echo -e \"ignore utest for it's disabled\"" if [ $SRS_UTEST = YES ]; then SrsUtestMakeEntry="(cd ${SRS_OBJS_DIR}/utest; \$(MAKE))"; fi +##################################################################################### +# finger out modules to install. +# where srs module is a dir which contains a config file. +SRS_MODULES=() +__mfiles=`find modules -name "config"` && for __mfile in $__mfiles; do + SRS_MODULES+="`dirname $__mfile`" +done + +# variables for makefile for all modules. +__mphonys="" && __mdefaults="" && __mcleanups="" +# add each modules for application +for SRS_MODULE in $SRS_MODULES; do + echo "install module at: $SRS_MODULE" + . $SRS_MODULE/config + __mphonys="$__mphonys $SRS_MODULE_NAME" + __mdefaults="$__mdefaults $SRS_MODULE_NAME" + __mcleanups="$__mcleanups $SRS_MODULE_NAME" +done + +##################################################################################### +# build tools or compiler args. +# enable gdb debug +GDBDebug=" -g -O0" +# the warning level. +WarnLevel=" -Wall" +# the compile standard. +CppStd="-ansi" +# for library compile +LibraryCompile=" -fPIC" +# performance of gprof +SrsGprof=""; SrsGprofLink=""; if [ $SRS_GPROF = YES ]; then SrsGprof=" -pg -lc_p"; SrsGprofLink=" -pg"; fi +# performance of gperf +SrsGperf=""; SrsGperfLink=""; if [ $SRS_GPERF = YES ]; then SrsGperfLink=" -lpthread"; fi +# the cxx flag generated. +CXXFLAGS="${CppStd}${WarnLevel}${GDBDebug}${LibraryCompile}${SrsGprof}" +if [ $SRS_GPERF = YES ]; then CXXFLAGS="${CXXFLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free"; fi +cat << END > ${SRS_OBJS}/${SRS_MAKEFILE} +GCC = gcc +CXX = g++ +AR = ar +LINK = g++ +CXXFLAGS = ${CXXFLAGS} + +.PHONY: default srs librtmp + +default: + +END + +##################################################################################### +# Libraries, external library to build in srs, +# header(.h): add to ModuleLibIncs if need the specified library. for example, LibSTRoot +# library(.a): add to ModuleLibFiles if binary need the specifeid library. for example, LibSTfile +# +# st(state-threads) the basic network library for SRS. +LibSTRoot="${SRS_OBJS_DIR}/st"; LibSTfile="${LibSTRoot}/libst.a" +# hp(http-parser) the http request/url parser, for SRS to support HTTP callback. +LibHttpParserRoot=""; LibHttpParserfile="" +if [ $SRS_HTTP_PARSER = YES ]; then LibHttpParserRoot="${SRS_OBJS_DIR}/hp"; LibHttpParserfile="${LibHttpParserRoot}/libhttp_parser.a"; fi +# openssl-1.0.1f, for the RTMP complex handshake. +LibSSLRoot="";LibSSLfile="" +if [ $SRS_SSL = YES ]; then if [ $SRS_USE_SYS_SSL = NO ]; then LibSSLRoot="${SRS_OBJS_DIR}/openssl/include"; LibSSLfile="${SRS_OBJS_DIR}/openssl/lib/libssl.a ${SRS_OBJS_DIR}/openssl/lib/libcrypto.a"; fi fi +# gperftools-2.1, for mem check and mem/cpu profile +LibGperfRoot=""; LibGperfFile="" +if [ $SRS_GPERF = YES ]; then LibGperfRoot="${SRS_OBJS_DIR}/gperf/include"; LibGperfFile="${SRS_OBJS_DIR}/gperf/lib/libtcmalloc_and_profiler.a"; fi +# the link options, always use static link +SrsLinkOptions="-ldl"; +if [ $SRS_SSL = YES ]; then if [ $SRS_USE_SYS_SSL = YES ]; then SrsLinkOptions="${SrsLinkOptions} -lssl"; fi fi +# if static specified, add static +# TODO: FIXME: remove static. +if [ $SRS_STATIC = YES ]; then SrsLinkOptions="${SrsLinkOptions} -static"; fi +# if mips, add -lgcc_eh, or stl compile failed. +if [ $SRS_MIPS_UBUNTU12 = YES ]; then SrsLinkOptions="${SrsLinkOptions} -lgcc_eh"; fi + +##################################################################################### +# Modules, compile each module, then link to binary +# +#Core, depends only on system apis. +MODULE_ID="CORE" +MODULE_DEPENDS=() +ModuleLibIncs=(${SRS_OBJS_DIR}) +MODULE_FILES=("srs_core" "srs_core_autofree" "srs_core_performance") +CORE_INCS="src/core"; MODULE_DIR=${CORE_INCS} . auto/modules.sh +CORE_OBJS="${MODULE_OBJS[@]}" +# +#Kernel, depends on core, provides error/log/config, nothing about stream information. +MODULE_ID="KERNEL" +MODULE_DEPENDS=("CORE") +ModuleLibIncs=(${SRS_OBJS_DIR}) +MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" + "srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_file" + "srs_kernel_consts" "srs_kernel_aac" "srs_kernel_mp3" "srs_kernel_ts" + "srs_kernel_buffer") +KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh +KERNEL_OBJS="${MODULE_OBJS[@]}" +# +#RTMP Protocol, depends on core/kernel, provides rtmp/htttp protocol features. +MODULE_ID="RTMP" +MODULE_DEPENDS=("CORE" "KERNEL") +ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) +MODULE_FILES=("srs_rtmp_amf0" "srs_rtmp_io" "srs_rtmp_stack" "srs_rtmp_sdk" + "srs_rtmp_handshake" "srs_rtmp_utility" "srs_rtmp_msg_array" "srs_rtmp_buffer" + "srs_raw_avc" "srs_rtsp_stack") +RTMP_INCS="src/protocol"; MODULE_DIR=${RTMP_INCS} . auto/modules.sh +RTMP_OBJS="${MODULE_OBJS[@]}" +# +#App Module +if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then + MODULE_ID="APP" + MODULE_DEPENDS=("CORE" "KERNEL" "RTMP") + ModuleLibIncs=(${LibSTRoot} ${LibHttpParserRoot} ${SRS_OBJS_DIR}) + MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_st_socket" "srs_app_source" + "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" "srs_app_http" + "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" + "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" + "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" + "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" + "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" + "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener") + # add each modules for app + for SRS_MODULE in $SRS_MODULES; do + . $SRS_MODULE/config + MODULE_FILES+=($SRS_MODULE_APP) + done + APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh + APP_OBJS="${MODULE_OBJS[@]}" +fi +# +#LIBS Module, build libsrs.a for static link. +MODULE_ID="LIBS" +MODULE_DEPENDS=("CORE" "KERNEL" "RTMP") +ModuleLibIncs=(${SRS_OBJS_DIR}) +MODULE_FILES=("srs_librtmp" "srs_lib_simple_socket" "srs_lib_bandwidth") +LIBS_INCS="src/libs"; MODULE_DIR=${LIBS_INCS} . auto/modules.sh +LIBS_OBJS="${MODULE_OBJS[@]}" +# +#Main Module +if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then + MODULE_ID="MAIN" + MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") + ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibHttpParserRoot}) + MODULE_FILES=("srs_main_server") + # add each modules for main + for SRS_MODULE in $SRS_MODULES; do + . $SRS_MODULE/config + MODULE_FILES+=($SRS_MODULE_MAIN) + done + MAIN_INCS="src/main"; MODULE_DIR=${MAIN_INCS} . auto/modules.sh + MAIN_OBJS="${MODULE_OBJS[@]}" +fi + +##################################################################################### +# Binaries, main entrances, link the module and its depends modules, +# then link to a binary, for example, objs/srs +# +# disable all app when export librtmp +if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then + # all main entrances + MAIN_ENTRANCES=("srs_main_server") + # add each modules for main + for SRS_MODULE in $SRS_MODULES; do + . $SRS_MODULE/config + MAIN_ENTRANCES+=($SRS_MODULE_MAIN) + done + # + # all depends libraries + ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile} ${LibSSLfile} ${LibGperfFile}) + # all depends objects + MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${APP_OBJS[@]} ${MAIN_OBJS[@]}" + LINK_OPTIONS="${SrsLinkOptions}${SrsGprofLink}${SrsGperfLink}" + # + # srs: srs(simple rtmp server) over st(state-threads) + BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" . auto/apps.sh + # add each modules for application + for SRS_MODULE in $SRS_MODULES; do + . $SRS_MODULE/config + BUILD_KEY="$SRS_MODULE_NAME" APP_MAIN="$SRS_MODULE_MAIN" APP_NAME="$SRS_MODULE_NAME" . auto/apps.sh + done +fi +# srs librtmp +if [ $SRS_LIBRTMP = YES ]; then + MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${LIBS_OBJS[@]}" + BUILD_KEY="librtmp" LIB_NAME="lib/srs_librtmp" . auto/libs.sh +fi +# +# utest, the unit-test cases of srs, base on gtest1.6 +if [ $SRS_UTEST = YES ]; then + MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_protocol" + "srs_utest_kernel" "srs_utest_core" "srs_utest_config" + "srs_utest_reload") + ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibSSLRoot}) + ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile} ${LibSSLfile}) + MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") + MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${APP_OBJS[@]}" + LINK_OPTIONS="-lpthread ${SrsLinkOptions}" MODULE_DIR="src/utest" APP_NAME="srs_utest" . auto/utest.sh +fi + ##################################################################################### # generate colorful summary script . auto/summary.sh @@ -117,8 +260,14 @@ if [ $SRS_UTEST = YES ]; then SrsUtestMakeEntry="(cd ${SRS_OBJS_DIR}/utest; \$(M ##################################################################################### # makefile echo "generate Makefile" + +# backup old makefile. +rm -f ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk && +mv ${SRS_WORKDIR}/${SRS_MAKEFILE} ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk + +# generate phony header cat << END > ${SRS_WORKDIR}/${SRS_MAKEFILE} -.PHONY: default _default install install-api help clean server librtmp utest _prepare_dir +.PHONY: default _default install install-api help clean server librtmp utest _prepare_dir $__mphonys # install prefix. SRS_PREFIX=${SRS_PREFIX} @@ -146,23 +295,27 @@ fi # the server, librtmp and utest # where the bellow will check and disable some entry by only echo. cat << END >> ${SRS_WORKDIR}/${SRS_MAKEFILE} -_default: server librtmp utest +_default: server librtmp utest $__mdefaults @bash objs/_srs_build_summary.sh help: @echo "Usage: make |||||||" - @echo " help display this help menu" - @echo " clean cleanup project" - @echo " server build the srs(simple rtmp server) over st(state-threads)" - @echo " librtmp build the client publish/play library, and samples" - @echo " utest build the utest for srs" - @echo " install install srs to the prefix path" - @echo " install-api install srs and api-server to the prefix path" - @echo " uninstall uninstall srs from prefix path" + @echo " help display this help menu" + @echo " clean cleanup project" + @echo " server build the srs(simple rtmp server) over st(state-threads)" + @echo " librtmp build the client publish/play library, and samples" + @echo " utest build the utest for srs" + @echo " install install srs to the prefix path" + @echo " install-api install srs and api-server to the prefix path" + @echo " uninstall uninstall srs from prefix path" + @echo "@remark all modules will auto genearted and build" + @echo "For example:" + @echo " make" + @echo " make help" clean: - (cd ${SRS_OBJS_DIR}; rm -rf srs srs_utest) - (cd ${SRS_OBJS_DIR}; rm -rf src research include lib) + (cd ${SRS_OBJS_DIR}; rm -rf srs srs_utest $__mcleanups) + (cd ${SRS_OBJS_DIR}; rm -rf src include lib) (cd ${SRS_OBJS_DIR}/utest; rm -rf *.o *.a) (cd research/librtmp; make clean) (cd research/api-server/static-dir; rm -rf crossdomain.xml forward live players) @@ -184,6 +337,25 @@ server: _prepare_dir END fi +# generate all modules entry +for SRS_MODULE in $SRS_MODULES; do + . $SRS_MODULE/config + # if export librtmp, donot build the bravo-ingest. + if [ $SRS_EXPORT_LIBRTMP_PROJECT != NO ]; then + cat << END >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +$SRS_MODULE_NAME: _prepare_dir + @echo "donot build the $SRS_MODULE_NAME for srs-librtmp" + +END + else + cat << END >> ${SRS_WORKDIR}/${SRS_MAKEFILE} +$SRS_MODULE_NAME: _prepare_dir + @echo "build the $SRS_MODULE_NAME over SRS" + \$(MAKE) -f ${SRS_OBJS_DIR}/${SRS_MAKEFILE} $SRS_MODULE_NAME + +END + fi +done # disable install entry for srs-librtmp if [ $SRS_EXPORT_LIBRTMP_PROJECT != NO ]; then @@ -293,164 +465,9 @@ _prepare_dir: @mkdir -p ${SRS_OBJS_DIR} END -##################################################################################### -# build tools or compiler args. -# enable gdb debug -GDBDebug=" -g -O0" -# the warning level. -WarnLevel=" -Wall" -# the compile standard. -CppStd="-ansi" -# for library compile -LibraryCompile=" -fPIC" -# performance of gprof -SrsGprof=""; SrsGprofLink=""; if [ $SRS_GPROF = YES ]; then SrsGprof=" -pg -lc_p"; SrsGprofLink=" -pg"; fi -# performance of gperf -SrsGperf=""; SrsGperfLink=""; if [ $SRS_GPERF = YES ]; then SrsGperfLink=" -lpthread"; fi -# the cxx flag generated. -CXXFLAGS="${CppStd}${WarnLevel}${GDBDebug}${LibraryCompile}${SrsGprof}" -if [ $SRS_GPERF = YES ]; then CXXFLAGS="${CXXFLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free"; fi -cat << END > ${SRS_OBJS}/${SRS_MAKEFILE} -GCC = gcc -CXX = g++ -AR = ar -LINK = g++ -CXXFLAGS = ${CXXFLAGS} - -.PHONY: default srs librtmp - -default: - -END - -##################################################################################### -# Libraries, external library to build in srs, -# header(.h): add to ModuleLibIncs if need the specified library. for example, LibSTRoot -# library(.a): add to ModuleLibFiles if binary need the specifeid library. for example, LibSTfile -# -# st(state-threads) the basic network library for SRS. -LibSTRoot="${SRS_OBJS_DIR}/st"; LibSTfile="${LibSTRoot}/libst.a" -# hp(http-parser) the http request/url parser, for SRS to support HTTP callback. -LibHttpParserRoot=""; LibHttpParserfile="" -if [ $SRS_HTTP_PARSER = YES ]; then LibHttpParserRoot="${SRS_OBJS_DIR}/hp"; LibHttpParserfile="${LibHttpParserRoot}/libhttp_parser.a"; fi -# openssl-1.0.1f, for the RTMP complex handshake. -LibSSLRoot="";LibSSLfile="" -if [ $SRS_SSL = YES ]; then if [ $SRS_USE_SYS_SSL = NO ]; then LibSSLRoot="${SRS_OBJS_DIR}/openssl/include"; LibSSLfile="${SRS_OBJS_DIR}/openssl/lib/libssl.a ${SRS_OBJS_DIR}/openssl/lib/libcrypto.a"; fi fi -# gperftools-2.1, for mem check and mem/cpu profile -LibGperfRoot=""; LibGperfFile="" -if [ $SRS_GPERF = YES ]; then LibGperfRoot="${SRS_OBJS_DIR}/gperf/include"; LibGperfFile="${SRS_OBJS_DIR}/gperf/lib/libtcmalloc_and_profiler.a"; fi -# the link options, always use static link -SrsLinkOptions="-ldl"; -if [ $SRS_SSL = YES ]; then if [ $SRS_USE_SYS_SSL = YES ]; then SrsLinkOptions="${SrsLinkOptions} -lssl"; fi fi -# if static specified, add static -# TODO: FIXME: remove static. -if [ $SRS_STATIC = YES ]; then SrsLinkOptions="${SrsLinkOptions} -static"; fi -# if mips, add -lgcc_eh, or stl compile failed. -if [ $SRS_MIPS_UBUNTU12 = YES ]; then SrsLinkOptions="${SrsLinkOptions} -lgcc_eh"; fi - -##################################################################################### -# Modules, compile each module, then link to binary -# -#Core, depends only on system apis. -MODULE_ID="CORE" -MODULE_DEPENDS=() -ModuleLibIncs=(${SRS_OBJS_DIR}) -MODULE_FILES=("srs_core" "srs_core_autofree" "srs_core_performance") -CORE_INCS="src/core"; MODULE_DIR=${CORE_INCS} . auto/modules.sh -CORE_OBJS="${MODULE_OBJS[@]}" -# -#Kernel, depends on core, provides error/log/config, nothing about stream information. -MODULE_ID="KERNEL" -MODULE_DEPENDS=("CORE") -ModuleLibIncs=(${SRS_OBJS_DIR}) -MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" - "srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_file" - "srs_kernel_consts" "srs_kernel_aac" "srs_kernel_mp3" "srs_kernel_ts" - "srs_kernel_buffer") -KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh -KERNEL_OBJS="${MODULE_OBJS[@]}" -# -#RTMP Protocol, depends on core/kernel, provides rtmp/htttp protocol features. -MODULE_ID="RTMP" -MODULE_DEPENDS=("CORE" "KERNEL") -ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) -MODULE_FILES=("srs_rtmp_amf0" "srs_rtmp_io" "srs_rtmp_stack" "srs_rtmp_sdk" - "srs_rtmp_handshake" "srs_rtmp_utility" "srs_rtmp_msg_array" "srs_rtmp_buffer" - "srs_raw_avc" "srs_rtsp_stack") -RTMP_INCS="src/protocol"; MODULE_DIR=${RTMP_INCS} . auto/modules.sh -RTMP_OBJS="${MODULE_OBJS[@]}" -# -#App Module -if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then - MODULE_ID="APP" - MODULE_DEPENDS=("CORE" "KERNEL" "RTMP") - ModuleLibIncs=(${LibSTRoot} ${LibHttpParserRoot} ${SRS_OBJS_DIR}) - MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_st_socket" "srs_app_source" - "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" "srs_app_http" - "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" - "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" - "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" - "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" - "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" - "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_hds") - APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh - APP_OBJS="${MODULE_OBJS[@]}" -fi -# -#LIBS Module, build libsrs.a for static link. -MODULE_ID="LIBS" -MODULE_DEPENDS=("CORE" "KERNEL" "RTMP") -ModuleLibIncs=(${SRS_OBJS_DIR}) -MODULE_FILES=("srs_librtmp" "srs_lib_simple_socket" "srs_lib_bandwidth") -LIBS_INCS="src/libs"; MODULE_DIR=${LIBS_INCS} . auto/modules.sh -LIBS_OBJS="${MODULE_OBJS[@]}" -# -#Main Module -if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then - MODULE_ID="MAIN" - MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") - ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot}) - MODULE_FILES=("srs_main_server") - MAIN_INCS="src/main"; MODULE_DIR=${MAIN_INCS} . auto/modules.sh - MAIN_OBJS="${MODULE_OBJS[@]}" -fi - -##################################################################################### -# Binaries, main entrances, link the module and its depends modules, -# then link to a binary, for example, objs/srs -# -# disable all app when export librtmp -if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then - # all main entrances - MAIN_ENTRANCES=("srs_main_server") - # - # all depends libraries - ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile} ${LibSSLfile} ${LibGperfFile}) - # all depends objects - MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${APP_OBJS[@]} ${MAIN_OBJS[@]}" - LINK_OPTIONS="${SrsLinkOptions}${SrsGprofLink}${SrsGperfLink}" - # - # srs: - # srs(simple rtmp server) over st(state-threads) - BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" . auto/apps.sh -fi -# srs librtmp -if [ $SRS_LIBRTMP = YES ]; then - MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${LIBS_OBJS[@]}" - BUILD_KEY="librtmp" LIB_NAME="lib/srs_librtmp" . auto/libs.sh -fi -# -# utest, the unit-test cases of srs, base on gtest1.6 -if [ $SRS_UTEST = YES ]; then - MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_protocol" - "srs_utest_kernel" "srs_utest_core" "srs_utest_config" - "srs_utest_reload") - ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibSSLRoot}) - ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile} ${LibSSLfile}) - MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") - MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${RTMP_OBJS[@]} ${APP_OBJS[@]}" - LINK_OPTIONS="-lpthread ${SrsLinkOptions}" MODULE_DIR="src/utest" APP_NAME="srs_utest" . auto/utest.sh -fi +# generate makefile ok, append the tails. +cat ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk >> ${SRS_WORKDIR}/${SRS_MAKEFILE} && +rm -f ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk echo 'configure ok! ' @@ -571,6 +588,10 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then else echo -e "${GREEN}note: mips-ubuntu12 for srs are not builded${BLACK}" fi + # add each modules for application + for SRS_MODULE in $SRS_MODULES; do + echo -e "${GREEN}module: $SRS_MODULE${BLACK}" + done fi ##################################################################################### diff --git a/trunk/etc/init.d/srs b/trunk/etc/init.d/srs index f49039649..f25d8bb9b 100755 --- a/trunk/etc/init.d/srs +++ b/trunk/etc/init.d/srs @@ -21,11 +21,11 @@ DEFAULT_LOG_FILE='./objs/srs.log' ######################################################################## # utility functions ######################################################################## -RED="\\e[31m" -GREEN="\\e[32m" -YELLOW="\\e[33m" -BLACK="\\e[0m" -POS="\\e[60G" +RED="\\033[31m" +GREEN="\\033[32m" +YELLOW="\\033[33m" +BLACK="\\033[0m" +POS="\\033[60G" ok_msg() { echo -e "${1}${POS}${BLACK}[${GREEN} OK ${BLACK}]" diff --git a/trunk/ide/readme.txt b/trunk/ide/readme.txt new file mode 100644 index 000000000..a97910071 --- /dev/null +++ b/trunk/ide/readme.txt @@ -0,0 +1,5 @@ +提供了各种ide。 + +1. UPP添加Assembly时,路径指向ide即可,譬如:\\dev\winlin\srs\ide + +2015.3 winlin diff --git a/trunk/ide/srs_qt/srs-qt.pro.user b/trunk/ide/srs_qt/srs-qt.pro.user index 572bbe375..5d891ca10 100755 --- a/trunk/ide/srs_qt/srs-qt.pro.user +++ b/trunk/ide/srs_qt/srs-qt.pro.user @@ -1,6 +1,6 @@ - + ProjectExplorer.Project.ActiveTarget @@ -56,12 +56,12 @@ Desktop Desktop - {fa2d28f9-85de-4a75-8e79-69d805f974bf} + {fdda5a74-8ef6-4e67-b28c-c5be6c667578} 0 0 0 - /home/winlin/git/simple-rtmp-server/trunk/src/build-qt-Desktop-Debug + /home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Debug true @@ -119,7 +119,66 @@ 2 true - 1 + + /home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 2 0 @@ -172,13 +231,13 @@ 2 srs-qt - srs-qt2 + Qt4ProjectManager.Qt4RunConfiguration:/home/winlin/git/simple-rtmp-server/trunk/ide/srs_qt/srs-qt.pro - -c console.conf + srs-qt.pro false true - /home/winlin/srs + 3768 false true diff --git a/trunk/ide/srs_upp/init b/trunk/ide/srs_upp/init old mode 100644 new mode 100755 index 9489480dc..cf8175cb4 --- a/trunk/ide/srs_upp/init +++ b/trunk/ide/srs_upp/init @@ -1,3 +1,3 @@ -#ifndef _srs_icpp_init_stub -#define _srs_icpp_init_stub +#ifndef _ide_srs_upp_icpp_init_stub +#define _ide_srs_upp_icpp_init_stub #endif diff --git a/trunk/ide/srs_upp/srs_upp.upp b/trunk/ide/srs_upp/srs_upp.upp index a27b7b635..c52bd3391 100755 --- a/trunk/ide/srs_upp/srs_upp.upp +++ b/trunk/ide/srs_upp/srs_upp.upp @@ -36,8 +36,8 @@ file ../../src/kernel/srs_kernel_log.cpp, ../../src/kernel/srs_kernel_mp3.hpp, ../../src/kernel/srs_kernel_mp3.cpp, - ../../src/kernel/srs_rtsp_stack.hpp, - ../../src/kernel/srs_rtsp_stack.cpp, + ../../src/kernel/srs_rtsp_stack.hpp, + ../../src/kernel/srs_rtsp_stack.cpp, ../../src/kernel/srs_kernel_stream.hpp, ../../src/kernel/srs_kernel_stream.cpp, ../../src/kernel/srs_kernel_ts.cpp, @@ -45,8 +45,8 @@ file ../../src/kernel/srs_kernel_utility.hpp, ../../src/kernel/srs_kernel_utility.cpp, protocol readonly separator, - ../../src/protocol/srs_raw_avc.hpp, - ../../src/protocol/srs_raw_avc.cpp, + ../../src/protocol/srs_raw_avc.hpp, + ../../src/protocol/srs_raw_avc.cpp, ../../src/protocol/srs_rtmp_amf0.hpp, ../../src/protocol/srs_rtmp_amf0.cpp, ../../src/protocol/srs_rtmp_buffer.hpp, @@ -102,8 +102,8 @@ file ../../src/app/srs_app_json.cpp, ../../src/app/srs_app_kbps.hpp, ../../src/app/srs_app_kbps.cpp, - ../../src/app/srs_app_listener.hpp, - ../../src/app/srs_app_listener.cpp, + ../../src/app/srs_app_listener.hpp, + ../../src/app/srs_app_listener.cpp, ../../src/app/srs_app_log.hpp, ../../src/app/srs_app_log.cpp, ../../src/app/srs_app_mpegts_udp.hpp, @@ -116,8 +116,8 @@ file ../../src/app/srs_app_reload.cpp, ../../src/app/srs_app_rtmp_conn.hpp, ../../src/app/srs_app_rtmp_conn.cpp, - ../../src/app/srs_app_rtsp.hpp, - ../../src/app/srs_app_rtsp.cpp, + ../../src/app/srs_app_rtsp.hpp, + ../../src/app/srs_app_rtsp.cpp, ../../src/app/srs_app_pithy_print.hpp, ../../src/app/srs_app_pithy_print.cpp, ../../src/app/srs_app_security.hpp, diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj new file mode 100644 index 000000000..867df88b9 --- /dev/null +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -0,0 +1,844 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3C1231F61AAE652D00CE8F6C /* srs_core_autofree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1231F01AAE652C00CE8F6C /* srs_core_autofree.cpp */; }; + 3C1231F71AAE652D00CE8F6C /* srs_core_performance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1231F21AAE652C00CE8F6C /* srs_core_performance.cpp */; }; + 3C1231F81AAE652D00CE8F6C /* srs_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1231F41AAE652D00CE8F6C /* srs_core.cpp */; }; + 3C1232061AAE812C00CE8F6C /* srs_main_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232051AAE812C00CE8F6C /* srs_main_server.cpp */; }; + 3C1232201AAE814D00CE8F6C /* srs_kernel_aac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232081AAE814D00CE8F6C /* srs_kernel_aac.cpp */; }; + 3C1232211AAE814D00CE8F6C /* srs_kernel_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12320A1AAE814D00CE8F6C /* srs_kernel_buffer.cpp */; }; + 3C1232221AAE814D00CE8F6C /* srs_kernel_codec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12320C1AAE814D00CE8F6C /* srs_kernel_codec.cpp */; }; + 3C1232231AAE814D00CE8F6C /* srs_kernel_consts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12320E1AAE814D00CE8F6C /* srs_kernel_consts.cpp */; }; + 3C1232241AAE814D00CE8F6C /* srs_kernel_error.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232101AAE814D00CE8F6C /* srs_kernel_error.cpp */; }; + 3C1232251AAE814D00CE8F6C /* srs_kernel_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232121AAE814D00CE8F6C /* srs_kernel_file.cpp */; }; + 3C1232261AAE814D00CE8F6C /* srs_kernel_flv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232141AAE814D00CE8F6C /* srs_kernel_flv.cpp */; }; + 3C1232271AAE814D00CE8F6C /* srs_kernel_log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232161AAE814D00CE8F6C /* srs_kernel_log.cpp */; }; + 3C1232281AAE814D00CE8F6C /* srs_kernel_mp3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232181AAE814D00CE8F6C /* srs_kernel_mp3.cpp */; }; + 3C1232291AAE814D00CE8F6C /* srs_kernel_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12321A1AAE814D00CE8F6C /* srs_kernel_stream.cpp */; }; + 3C12322A1AAE814D00CE8F6C /* srs_kernel_ts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12321C1AAE814D00CE8F6C /* srs_kernel_ts.cpp */; }; + 3C12322B1AAE814D00CE8F6C /* srs_kernel_utility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12321E1AAE814D00CE8F6C /* srs_kernel_utility.cpp */; }; + 3C1232411AAE81A400CE8F6C /* srs_raw_avc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12322D1AAE81A400CE8F6C /* srs_raw_avc.cpp */; }; + 3C1232421AAE81A400CE8F6C /* srs_rtmp_amf0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12322F1AAE81A400CE8F6C /* srs_rtmp_amf0.cpp */; }; + 3C1232431AAE81A400CE8F6C /* srs_rtmp_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232311AAE81A400CE8F6C /* srs_rtmp_buffer.cpp */; }; + 3C1232441AAE81A400CE8F6C /* srs_rtmp_handshake.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232331AAE81A400CE8F6C /* srs_rtmp_handshake.cpp */; }; + 3C1232451AAE81A400CE8F6C /* srs_rtmp_io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232351AAE81A400CE8F6C /* srs_rtmp_io.cpp */; }; + 3C1232461AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232371AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp */; }; + 3C1232471AAE81A400CE8F6C /* srs_rtmp_sdk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232391AAE81A400CE8F6C /* srs_rtmp_sdk.cpp */; }; + 3C1232481AAE81A400CE8F6C /* srs_rtmp_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12323B1AAE81A400CE8F6C /* srs_rtmp_stack.cpp */; }; + 3C1232491AAE81A400CE8F6C /* srs_rtmp_utility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12323D1AAE81A400CE8F6C /* srs_rtmp_utility.cpp */; }; + 3C12324A1AAE81A400CE8F6C /* srs_rtsp_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12323F1AAE81A400CE8F6C /* srs_rtsp_stack.cpp */; }; + 3C1232941AAE81D900CE8F6C /* srs_app_bandwidth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */; }; + 3C1232951AAE81D900CE8F6C /* srs_app_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */; }; + 3C1232961AAE81D900CE8F6C /* srs_app_conn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */; }; + 3C1232971AAE81D900CE8F6C /* srs_app_dvr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232521AAE81D900CE8F6C /* srs_app_dvr.cpp */; }; + 3C1232981AAE81D900CE8F6C /* srs_app_edge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232541AAE81D900CE8F6C /* srs_app_edge.cpp */; }; + 3C1232991AAE81D900CE8F6C /* srs_app_empty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232561AAE81D900CE8F6C /* srs_app_empty.cpp */; }; + 3C12329A1AAE81D900CE8F6C /* srs_app_encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232581AAE81D900CE8F6C /* srs_app_encoder.cpp */; }; + 3C12329B1AAE81D900CE8F6C /* srs_app_ffmpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12325A1AAE81D900CE8F6C /* srs_app_ffmpeg.cpp */; }; + 3C12329C1AAE81D900CE8F6C /* srs_app_forward.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */; }; + 3C12329D1AAE81D900CE8F6C /* srs_app_heartbeat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */; }; + 3C12329E1AAE81D900CE8F6C /* srs_app_hls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */; }; + 3C12329F1AAE81D900CE8F6C /* srs_app_http_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */; }; + 3C1232A01AAE81D900CE8F6C /* srs_app_http_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232641AAE81D900CE8F6C /* srs_app_http_client.cpp */; }; + 3C1232A11AAE81D900CE8F6C /* srs_app_http_conn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232661AAE81D900CE8F6C /* srs_app_http_conn.cpp */; }; + 3C1232A21AAE81D900CE8F6C /* srs_app_http_hooks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */; }; + 3C1232A31AAE81D900CE8F6C /* srs_app_http.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12326A1AAE81D900CE8F6C /* srs_app_http.cpp */; }; + 3C1232A41AAE81D900CE8F6C /* srs_app_ingest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */; }; + 3C1232A51AAE81D900CE8F6C /* srs_app_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */; }; + 3C1232A61AAE81D900CE8F6C /* srs_app_kbps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232701AAE81D900CE8F6C /* srs_app_kbps.cpp */; }; + 3C1232A71AAE81D900CE8F6C /* srs_app_listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */; }; + 3C1232A81AAE81D900CE8F6C /* srs_app_log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */; }; + 3C1232A91AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232761AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp */; }; + 3C1232AA1AAE81D900CE8F6C /* srs_app_pithy_print.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232781AAE81D900CE8F6C /* srs_app_pithy_print.cpp */; }; + 3C1232AB1AAE81D900CE8F6C /* srs_app_recv_thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12327A1AAE81D900CE8F6C /* srs_app_recv_thread.cpp */; }; + 3C1232AC1AAE81D900CE8F6C /* srs_app_refer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12327C1AAE81D900CE8F6C /* srs_app_refer.cpp */; }; + 3C1232AD1AAE81D900CE8F6C /* srs_app_reload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12327E1AAE81D900CE8F6C /* srs_app_reload.cpp */; }; + 3C1232AE1AAE81D900CE8F6C /* srs_app_rtmp_conn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232801AAE81D900CE8F6C /* srs_app_rtmp_conn.cpp */; }; + 3C1232AF1AAE81D900CE8F6C /* srs_app_rtsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232821AAE81D900CE8F6C /* srs_app_rtsp.cpp */; }; + 3C1232B01AAE81D900CE8F6C /* srs_app_security.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232841AAE81D900CE8F6C /* srs_app_security.cpp */; }; + 3C1232B11AAE81D900CE8F6C /* srs_app_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232861AAE81D900CE8F6C /* srs_app_server.cpp */; }; + 3C1232B21AAE81D900CE8F6C /* srs_app_source.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232881AAE81D900CE8F6C /* srs_app_source.cpp */; }; + 3C1232B31AAE81D900CE8F6C /* srs_app_st_socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12328A1AAE81D900CE8F6C /* srs_app_st_socket.cpp */; }; + 3C1232B41AAE81D900CE8F6C /* srs_app_st.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12328C1AAE81D900CE8F6C /* srs_app_st.cpp */; }; + 3C1232B51AAE81D900CE8F6C /* srs_app_statistic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12328E1AAE81D900CE8F6C /* srs_app_statistic.cpp */; }; + 3C1232B61AAE81D900CE8F6C /* srs_app_thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232901AAE81D900CE8F6C /* srs_app_thread.cpp */; }; + 3C1232B71AAE81D900CE8F6C /* srs_app_utility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232921AAE81D900CE8F6C /* srs_app_utility.cpp */; }; + 3C1232D31AAEA56B00CE8F6C /* libst.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C1232D21AAEA56B00CE8F6C /* libst.a */; }; + 3C1232E91AAEA5D000CE8F6C /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C1232E71AAEA5D000CE8F6C /* libcrypto.a */; }; + 3C1232EA1AAEA5D000CE8F6C /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C1232E81AAEA5D000CE8F6C /* libssl.a */; }; + 3C1232ED1AAEA70F00CE8F6C /* libhttp_parser.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C1232EC1AAEA70F00CE8F6C /* libhttp_parser.a */; }; + 3C663F0E1AB0155100286D8B /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F011AB0155100286D8B /* Makefile */; }; + 3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */; }; + 3C663F101AB0155100286D8B /* srs_audio_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */; }; + 3C663F111AB0155100286D8B /* srs_bandwidth_check.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F041AB0155100286D8B /* srs_bandwidth_check.c */; }; + 3C663F121AB0155100286D8B /* srs_detect_rtmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F051AB0155100286D8B /* srs_detect_rtmp.c */; }; + 3C663F131AB0155100286D8B /* srs_flv_injecter.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F061AB0155100286D8B /* srs_flv_injecter.c */; }; + 3C663F141AB0155100286D8B /* srs_flv_parser.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F071AB0155100286D8B /* srs_flv_parser.c */; }; + 3C663F151AB0155100286D8B /* srs_h264_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F081AB0155100286D8B /* srs_h264_raw_publish.c */; }; + 3C663F161AB0155100286D8B /* srs_ingest_flv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F091AB0155100286D8B /* srs_ingest_flv.c */; }; + 3C663F171AB0155100286D8B /* srs_ingest_rtmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F0A1AB0155100286D8B /* srs_ingest_rtmp.c */; }; + 3C663F181AB0155100286D8B /* srs_play.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F0B1AB0155100286D8B /* srs_play.c */; }; + 3C663F191AB0155100286D8B /* srs_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F0C1AB0155100286D8B /* srs_publish.c */; }; + 3C663F1A1AB0155100286D8B /* srs_rtmp_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F0D1AB0155100286D8B /* srs_rtmp_dump.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 3C1231E31AAE64A400CE8F6C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 3C1231E51AAE64A400CE8F6C /* srs_xcode */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; includeInIndex = 0; path = srs_xcode; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C1231F01AAE652C00CE8F6C /* srs_core_autofree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core_autofree.cpp; path = ../../../src/core/srs_core_autofree.cpp; sourceTree = ""; }; + 3C1231F11AAE652C00CE8F6C /* srs_core_autofree.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core_autofree.hpp; path = ../../../src/core/srs_core_autofree.hpp; sourceTree = ""; }; + 3C1231F21AAE652C00CE8F6C /* srs_core_performance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core_performance.cpp; path = ../../../src/core/srs_core_performance.cpp; sourceTree = ""; }; + 3C1231F31AAE652C00CE8F6C /* srs_core_performance.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core_performance.hpp; path = ../../../src/core/srs_core_performance.hpp; sourceTree = ""; }; + 3C1231F41AAE652D00CE8F6C /* srs_core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core.cpp; path = ../../../src/core/srs_core.cpp; sourceTree = ""; }; + 3C1231F51AAE652D00CE8F6C /* srs_core.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core.hpp; path = ../../../src/core/srs_core.hpp; sourceTree = ""; }; + 3C1231FB1AAE673100CE8F6C /* srs_auto_headers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_auto_headers.hpp; path = ../../../objs/srs_auto_headers.hpp; sourceTree = ""; }; + 3C1232051AAE812C00CE8F6C /* srs_main_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_main_server.cpp; path = ../../../src/main/srs_main_server.cpp; sourceTree = ""; }; + 3C1232081AAE814D00CE8F6C /* srs_kernel_aac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_aac.cpp; path = ../../../src/kernel/srs_kernel_aac.cpp; sourceTree = ""; }; + 3C1232091AAE814D00CE8F6C /* srs_kernel_aac.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_aac.hpp; path = ../../../src/kernel/srs_kernel_aac.hpp; sourceTree = ""; }; + 3C12320A1AAE814D00CE8F6C /* srs_kernel_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_buffer.cpp; path = ../../../src/kernel/srs_kernel_buffer.cpp; sourceTree = ""; }; + 3C12320B1AAE814D00CE8F6C /* srs_kernel_buffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_buffer.hpp; path = ../../../src/kernel/srs_kernel_buffer.hpp; sourceTree = ""; }; + 3C12320C1AAE814D00CE8F6C /* srs_kernel_codec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_codec.cpp; path = ../../../src/kernel/srs_kernel_codec.cpp; sourceTree = ""; }; + 3C12320D1AAE814D00CE8F6C /* srs_kernel_codec.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_codec.hpp; path = ../../../src/kernel/srs_kernel_codec.hpp; sourceTree = ""; }; + 3C12320E1AAE814D00CE8F6C /* srs_kernel_consts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_consts.cpp; path = ../../../src/kernel/srs_kernel_consts.cpp; sourceTree = ""; }; + 3C12320F1AAE814D00CE8F6C /* srs_kernel_consts.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_consts.hpp; path = ../../../src/kernel/srs_kernel_consts.hpp; sourceTree = ""; }; + 3C1232101AAE814D00CE8F6C /* srs_kernel_error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_error.cpp; path = ../../../src/kernel/srs_kernel_error.cpp; sourceTree = ""; }; + 3C1232111AAE814D00CE8F6C /* srs_kernel_error.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_error.hpp; path = ../../../src/kernel/srs_kernel_error.hpp; sourceTree = ""; }; + 3C1232121AAE814D00CE8F6C /* srs_kernel_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_file.cpp; path = ../../../src/kernel/srs_kernel_file.cpp; sourceTree = ""; }; + 3C1232131AAE814D00CE8F6C /* srs_kernel_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_file.hpp; path = ../../../src/kernel/srs_kernel_file.hpp; sourceTree = ""; }; + 3C1232141AAE814D00CE8F6C /* srs_kernel_flv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_flv.cpp; path = ../../../src/kernel/srs_kernel_flv.cpp; sourceTree = ""; }; + 3C1232151AAE814D00CE8F6C /* srs_kernel_flv.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_flv.hpp; path = ../../../src/kernel/srs_kernel_flv.hpp; sourceTree = ""; }; + 3C1232161AAE814D00CE8F6C /* srs_kernel_log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_log.cpp; path = ../../../src/kernel/srs_kernel_log.cpp; sourceTree = ""; }; + 3C1232171AAE814D00CE8F6C /* srs_kernel_log.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_log.hpp; path = ../../../src/kernel/srs_kernel_log.hpp; sourceTree = ""; }; + 3C1232181AAE814D00CE8F6C /* srs_kernel_mp3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_mp3.cpp; path = ../../../src/kernel/srs_kernel_mp3.cpp; sourceTree = ""; }; + 3C1232191AAE814D00CE8F6C /* srs_kernel_mp3.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_mp3.hpp; path = ../../../src/kernel/srs_kernel_mp3.hpp; sourceTree = ""; }; + 3C12321A1AAE814D00CE8F6C /* srs_kernel_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_stream.cpp; path = ../../../src/kernel/srs_kernel_stream.cpp; sourceTree = ""; }; + 3C12321B1AAE814D00CE8F6C /* srs_kernel_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_stream.hpp; path = ../../../src/kernel/srs_kernel_stream.hpp; sourceTree = ""; }; + 3C12321C1AAE814D00CE8F6C /* srs_kernel_ts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_ts.cpp; path = ../../../src/kernel/srs_kernel_ts.cpp; sourceTree = ""; }; + 3C12321D1AAE814D00CE8F6C /* srs_kernel_ts.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_ts.hpp; path = ../../../src/kernel/srs_kernel_ts.hpp; sourceTree = ""; }; + 3C12321E1AAE814D00CE8F6C /* srs_kernel_utility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_utility.cpp; path = ../../../src/kernel/srs_kernel_utility.cpp; sourceTree = ""; }; + 3C12321F1AAE814D00CE8F6C /* srs_kernel_utility.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_utility.hpp; path = ../../../src/kernel/srs_kernel_utility.hpp; sourceTree = ""; }; + 3C12322D1AAE81A400CE8F6C /* srs_raw_avc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_raw_avc.cpp; path = ../../../src/protocol/srs_raw_avc.cpp; sourceTree = ""; }; + 3C12322E1AAE81A400CE8F6C /* srs_raw_avc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_raw_avc.hpp; path = ../../../src/protocol/srs_raw_avc.hpp; sourceTree = ""; }; + 3C12322F1AAE81A400CE8F6C /* srs_rtmp_amf0.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_amf0.cpp; path = ../../../src/protocol/srs_rtmp_amf0.cpp; sourceTree = ""; }; + 3C1232301AAE81A400CE8F6C /* srs_rtmp_amf0.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_amf0.hpp; path = ../../../src/protocol/srs_rtmp_amf0.hpp; sourceTree = ""; }; + 3C1232311AAE81A400CE8F6C /* srs_rtmp_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_buffer.cpp; path = ../../../src/protocol/srs_rtmp_buffer.cpp; sourceTree = ""; }; + 3C1232321AAE81A400CE8F6C /* srs_rtmp_buffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_buffer.hpp; path = ../../../src/protocol/srs_rtmp_buffer.hpp; sourceTree = ""; }; + 3C1232331AAE81A400CE8F6C /* srs_rtmp_handshake.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_handshake.cpp; path = ../../../src/protocol/srs_rtmp_handshake.cpp; sourceTree = ""; }; + 3C1232341AAE81A400CE8F6C /* srs_rtmp_handshake.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_handshake.hpp; path = ../../../src/protocol/srs_rtmp_handshake.hpp; sourceTree = ""; }; + 3C1232351AAE81A400CE8F6C /* srs_rtmp_io.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_io.cpp; path = ../../../src/protocol/srs_rtmp_io.cpp; sourceTree = ""; }; + 3C1232361AAE81A400CE8F6C /* srs_rtmp_io.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_io.hpp; path = ../../../src/protocol/srs_rtmp_io.hpp; sourceTree = ""; }; + 3C1232371AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_msg_array.cpp; path = ../../../src/protocol/srs_rtmp_msg_array.cpp; sourceTree = ""; }; + 3C1232381AAE81A400CE8F6C /* srs_rtmp_msg_array.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_msg_array.hpp; path = ../../../src/protocol/srs_rtmp_msg_array.hpp; sourceTree = ""; }; + 3C1232391AAE81A400CE8F6C /* srs_rtmp_sdk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_sdk.cpp; path = ../../../src/protocol/srs_rtmp_sdk.cpp; sourceTree = ""; }; + 3C12323A1AAE81A400CE8F6C /* srs_rtmp_sdk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_sdk.hpp; path = ../../../src/protocol/srs_rtmp_sdk.hpp; sourceTree = ""; }; + 3C12323B1AAE81A400CE8F6C /* srs_rtmp_stack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_stack.cpp; path = ../../../src/protocol/srs_rtmp_stack.cpp; sourceTree = ""; }; + 3C12323C1AAE81A400CE8F6C /* srs_rtmp_stack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_stack.hpp; path = ../../../src/protocol/srs_rtmp_stack.hpp; sourceTree = ""; }; + 3C12323D1AAE81A400CE8F6C /* srs_rtmp_utility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtmp_utility.cpp; path = ../../../src/protocol/srs_rtmp_utility.cpp; sourceTree = ""; }; + 3C12323E1AAE81A400CE8F6C /* srs_rtmp_utility.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtmp_utility.hpp; path = ../../../src/protocol/srs_rtmp_utility.hpp; sourceTree = ""; }; + 3C12323F1AAE81A400CE8F6C /* srs_rtsp_stack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_rtsp_stack.cpp; path = ../../../src/protocol/srs_rtsp_stack.cpp; sourceTree = ""; }; + 3C1232401AAE81A400CE8F6C /* srs_rtsp_stack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_rtsp_stack.hpp; path = ../../../src/protocol/srs_rtsp_stack.hpp; sourceTree = ""; }; + 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_bandwidth.cpp; path = ../../../src/app/srs_app_bandwidth.cpp; sourceTree = ""; }; + 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_bandwidth.hpp; path = ../../../src/app/srs_app_bandwidth.hpp; sourceTree = ""; }; + 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_config.cpp; path = ../../../src/app/srs_app_config.cpp; sourceTree = ""; }; + 3C12324F1AAE81D900CE8F6C /* srs_app_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_config.hpp; path = ../../../src/app/srs_app_config.hpp; sourceTree = ""; }; + 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_conn.cpp; path = ../../../src/app/srs_app_conn.cpp; sourceTree = ""; }; + 3C1232511AAE81D900CE8F6C /* srs_app_conn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_conn.hpp; path = ../../../src/app/srs_app_conn.hpp; sourceTree = ""; }; + 3C1232521AAE81D900CE8F6C /* srs_app_dvr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_dvr.cpp; path = ../../../src/app/srs_app_dvr.cpp; sourceTree = ""; }; + 3C1232531AAE81D900CE8F6C /* srs_app_dvr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_dvr.hpp; path = ../../../src/app/srs_app_dvr.hpp; sourceTree = ""; }; + 3C1232541AAE81D900CE8F6C /* srs_app_edge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_edge.cpp; path = ../../../src/app/srs_app_edge.cpp; sourceTree = ""; }; + 3C1232551AAE81D900CE8F6C /* srs_app_edge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_edge.hpp; path = ../../../src/app/srs_app_edge.hpp; sourceTree = ""; }; + 3C1232561AAE81D900CE8F6C /* srs_app_empty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_empty.cpp; path = ../../../src/app/srs_app_empty.cpp; sourceTree = ""; }; + 3C1232571AAE81D900CE8F6C /* srs_app_empty.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_empty.hpp; path = ../../../src/app/srs_app_empty.hpp; sourceTree = ""; }; + 3C1232581AAE81D900CE8F6C /* srs_app_encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_encoder.cpp; path = ../../../src/app/srs_app_encoder.cpp; sourceTree = ""; }; + 3C1232591AAE81D900CE8F6C /* srs_app_encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_encoder.hpp; path = ../../../src/app/srs_app_encoder.hpp; sourceTree = ""; }; + 3C12325A1AAE81D900CE8F6C /* srs_app_ffmpeg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_ffmpeg.cpp; path = ../../../src/app/srs_app_ffmpeg.cpp; sourceTree = ""; }; + 3C12325B1AAE81D900CE8F6C /* srs_app_ffmpeg.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_ffmpeg.hpp; path = ../../../src/app/srs_app_ffmpeg.hpp; sourceTree = ""; }; + 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_forward.cpp; path = ../../../src/app/srs_app_forward.cpp; sourceTree = ""; }; + 3C12325D1AAE81D900CE8F6C /* srs_app_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_forward.hpp; path = ../../../src/app/srs_app_forward.hpp; sourceTree = ""; }; + 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_heartbeat.cpp; path = ../../../src/app/srs_app_heartbeat.cpp; sourceTree = ""; }; + 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_heartbeat.hpp; path = ../../../src/app/srs_app_heartbeat.hpp; sourceTree = ""; }; + 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_hls.cpp; path = ../../../src/app/srs_app_hls.cpp; sourceTree = ""; }; + 3C1232611AAE81D900CE8F6C /* srs_app_hls.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_hls.hpp; path = ../../../src/app/srs_app_hls.hpp; sourceTree = ""; }; + 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_api.cpp; path = ../../../src/app/srs_app_http_api.cpp; sourceTree = ""; }; + 3C1232631AAE81D900CE8F6C /* srs_app_http_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_api.hpp; path = ../../../src/app/srs_app_http_api.hpp; sourceTree = ""; }; + 3C1232641AAE81D900CE8F6C /* srs_app_http_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_client.cpp; path = ../../../src/app/srs_app_http_client.cpp; sourceTree = ""; }; + 3C1232651AAE81D900CE8F6C /* srs_app_http_client.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_client.hpp; path = ../../../src/app/srs_app_http_client.hpp; sourceTree = ""; }; + 3C1232661AAE81D900CE8F6C /* srs_app_http_conn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_conn.cpp; path = ../../../src/app/srs_app_http_conn.cpp; sourceTree = ""; }; + 3C1232671AAE81D900CE8F6C /* srs_app_http_conn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_conn.hpp; path = ../../../src/app/srs_app_http_conn.hpp; sourceTree = ""; }; + 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_hooks.cpp; path = ../../../src/app/srs_app_http_hooks.cpp; sourceTree = ""; }; + 3C1232691AAE81D900CE8F6C /* srs_app_http_hooks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_hooks.hpp; path = ../../../src/app/srs_app_http_hooks.hpp; sourceTree = ""; }; + 3C12326A1AAE81D900CE8F6C /* srs_app_http.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http.cpp; path = ../../../src/app/srs_app_http.cpp; sourceTree = ""; }; + 3C12326B1AAE81D900CE8F6C /* srs_app_http.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http.hpp; path = ../../../src/app/srs_app_http.hpp; sourceTree = ""; }; + 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_ingest.cpp; path = ../../../src/app/srs_app_ingest.cpp; sourceTree = ""; }; + 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_ingest.hpp; path = ../../../src/app/srs_app_ingest.hpp; sourceTree = ""; }; + 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_json.cpp; path = ../../../src/app/srs_app_json.cpp; sourceTree = ""; }; + 3C12326F1AAE81D900CE8F6C /* srs_app_json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_json.hpp; path = ../../../src/app/srs_app_json.hpp; sourceTree = ""; }; + 3C1232701AAE81D900CE8F6C /* srs_app_kbps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_kbps.cpp; path = ../../../src/app/srs_app_kbps.cpp; sourceTree = ""; }; + 3C1232711AAE81D900CE8F6C /* srs_app_kbps.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_kbps.hpp; path = ../../../src/app/srs_app_kbps.hpp; sourceTree = ""; }; + 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_listener.cpp; path = ../../../src/app/srs_app_listener.cpp; sourceTree = ""; }; + 3C1232731AAE81D900CE8F6C /* srs_app_listener.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_listener.hpp; path = ../../../src/app/srs_app_listener.hpp; sourceTree = ""; }; + 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_log.cpp; path = ../../../src/app/srs_app_log.cpp; sourceTree = ""; }; + 3C1232751AAE81D900CE8F6C /* srs_app_log.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_log.hpp; path = ../../../src/app/srs_app_log.hpp; sourceTree = ""; }; + 3C1232761AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_mpegts_udp.cpp; path = ../../../src/app/srs_app_mpegts_udp.cpp; sourceTree = ""; }; + 3C1232771AAE81D900CE8F6C /* srs_app_mpegts_udp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_mpegts_udp.hpp; path = ../../../src/app/srs_app_mpegts_udp.hpp; sourceTree = ""; }; + 3C1232781AAE81D900CE8F6C /* srs_app_pithy_print.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_pithy_print.cpp; path = ../../../src/app/srs_app_pithy_print.cpp; sourceTree = ""; }; + 3C1232791AAE81D900CE8F6C /* srs_app_pithy_print.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_pithy_print.hpp; path = ../../../src/app/srs_app_pithy_print.hpp; sourceTree = ""; }; + 3C12327A1AAE81D900CE8F6C /* srs_app_recv_thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_recv_thread.cpp; path = ../../../src/app/srs_app_recv_thread.cpp; sourceTree = ""; }; + 3C12327B1AAE81D900CE8F6C /* srs_app_recv_thread.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_recv_thread.hpp; path = ../../../src/app/srs_app_recv_thread.hpp; sourceTree = ""; }; + 3C12327C1AAE81D900CE8F6C /* srs_app_refer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_refer.cpp; path = ../../../src/app/srs_app_refer.cpp; sourceTree = ""; }; + 3C12327D1AAE81D900CE8F6C /* srs_app_refer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_refer.hpp; path = ../../../src/app/srs_app_refer.hpp; sourceTree = ""; }; + 3C12327E1AAE81D900CE8F6C /* srs_app_reload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_reload.cpp; path = ../../../src/app/srs_app_reload.cpp; sourceTree = ""; }; + 3C12327F1AAE81D900CE8F6C /* srs_app_reload.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_reload.hpp; path = ../../../src/app/srs_app_reload.hpp; sourceTree = ""; }; + 3C1232801AAE81D900CE8F6C /* srs_app_rtmp_conn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_rtmp_conn.cpp; path = ../../../src/app/srs_app_rtmp_conn.cpp; sourceTree = ""; }; + 3C1232811AAE81D900CE8F6C /* srs_app_rtmp_conn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_rtmp_conn.hpp; path = ../../../src/app/srs_app_rtmp_conn.hpp; sourceTree = ""; }; + 3C1232821AAE81D900CE8F6C /* srs_app_rtsp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_rtsp.cpp; path = ../../../src/app/srs_app_rtsp.cpp; sourceTree = ""; }; + 3C1232831AAE81D900CE8F6C /* srs_app_rtsp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_rtsp.hpp; path = ../../../src/app/srs_app_rtsp.hpp; sourceTree = ""; }; + 3C1232841AAE81D900CE8F6C /* srs_app_security.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_security.cpp; path = ../../../src/app/srs_app_security.cpp; sourceTree = ""; }; + 3C1232851AAE81D900CE8F6C /* srs_app_security.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_security.hpp; path = ../../../src/app/srs_app_security.hpp; sourceTree = ""; }; + 3C1232861AAE81D900CE8F6C /* srs_app_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_server.cpp; path = ../../../src/app/srs_app_server.cpp; sourceTree = ""; }; + 3C1232871AAE81D900CE8F6C /* srs_app_server.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_server.hpp; path = ../../../src/app/srs_app_server.hpp; sourceTree = ""; }; + 3C1232881AAE81D900CE8F6C /* srs_app_source.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_source.cpp; path = ../../../src/app/srs_app_source.cpp; sourceTree = ""; }; + 3C1232891AAE81D900CE8F6C /* srs_app_source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_source.hpp; path = ../../../src/app/srs_app_source.hpp; sourceTree = ""; }; + 3C12328A1AAE81D900CE8F6C /* srs_app_st_socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_st_socket.cpp; path = ../../../src/app/srs_app_st_socket.cpp; sourceTree = ""; }; + 3C12328B1AAE81D900CE8F6C /* srs_app_st_socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_st_socket.hpp; path = ../../../src/app/srs_app_st_socket.hpp; sourceTree = ""; }; + 3C12328C1AAE81D900CE8F6C /* srs_app_st.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_st.cpp; path = ../../../src/app/srs_app_st.cpp; sourceTree = ""; }; + 3C12328D1AAE81D900CE8F6C /* srs_app_st.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_st.hpp; path = ../../../src/app/srs_app_st.hpp; sourceTree = ""; }; + 3C12328E1AAE81D900CE8F6C /* srs_app_statistic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_statistic.cpp; path = ../../../src/app/srs_app_statistic.cpp; sourceTree = ""; }; + 3C12328F1AAE81D900CE8F6C /* srs_app_statistic.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_statistic.hpp; path = ../../../src/app/srs_app_statistic.hpp; sourceTree = ""; }; + 3C1232901AAE81D900CE8F6C /* srs_app_thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_thread.cpp; path = ../../../src/app/srs_app_thread.cpp; sourceTree = ""; }; + 3C1232911AAE81D900CE8F6C /* srs_app_thread.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_thread.hpp; path = ../../../src/app/srs_app_thread.hpp; sourceTree = ""; }; + 3C1232921AAE81D900CE8F6C /* srs_app_utility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_utility.cpp; path = ../../../src/app/srs_app_utility.cpp; sourceTree = ""; }; + 3C1232931AAE81D900CE8F6C /* srs_app_utility.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_utility.hpp; path = ../../../src/app/srs_app_utility.hpp; sourceTree = ""; }; + 3C1232B81AAE824500CE8F6C /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = configure; path = ../../../configure; sourceTree = ""; }; + 3C1232BB1AAE827E00CE8F6C /* apps.sh */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; name = apps.sh; path = ../../../auto/apps.sh; sourceTree = ""; }; + 3C1232BC1AAE827E00CE8F6C /* auto_headers.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = auto_headers.sh; path = ../../../auto/auto_headers.sh; sourceTree = ""; }; + 3C1232BD1AAE827E00CE8F6C /* build_ffmpeg.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = build_ffmpeg.sh; path = ../../../auto/build_ffmpeg.sh; sourceTree = ""; }; + 3C1232BE1AAE827E00CE8F6C /* depends.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = depends.sh; path = ../../../auto/depends.sh; sourceTree = ""; }; + 3C1232BF1AAE827E00CE8F6C /* generate_header.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = generate_header.sh; path = ../../../auto/generate_header.sh; sourceTree = ""; }; + 3C1232C01AAE827E00CE8F6C /* generate-srs-librtmp-project.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "generate-srs-librtmp-project.sh"; path = "../../../auto/generate-srs-librtmp-project.sh"; sourceTree = ""; }; + 3C1232C11AAE827E00CE8F6C /* generate-srs-librtmp-single.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "generate-srs-librtmp-single.sh"; path = "../../../auto/generate-srs-librtmp-single.sh"; sourceTree = ""; }; + 3C1232C21AAE827E00CE8F6C /* libs.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = libs.sh; path = ../../../auto/libs.sh; sourceTree = ""; }; + 3C1232C31AAE827E00CE8F6C /* local_ip.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = local_ip.sh; path = ../../../auto/local_ip.sh; sourceTree = ""; }; + 3C1232C41AAE827E00CE8F6C /* modules.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = modules.sh; path = ../../../auto/modules.sh; sourceTree = ""; }; + 3C1232C51AAE827E00CE8F6C /* options.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = options.sh; path = ../../../auto/options.sh; sourceTree = ""; }; + 3C1232C61AAE827E00CE8F6C /* summary.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = summary.sh; path = ../../../auto/summary.sh; sourceTree = ""; }; + 3C1232C71AAE827E00CE8F6C /* utest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = utest.sh; path = ../../../auto/utest.sh; sourceTree = ""; }; + 3C1232C81AAE833300CE8F6C /* _log.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = _log.sh; path = ../../../scripts/_log.sh; sourceTree = ""; }; + 3C1232C91AAE833300CE8F6C /* build.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = build.sh; path = ../../../scripts/build.sh; sourceTree = ""; }; + 3C1232CA1AAE833300CE8F6C /* git.commit.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = git.commit.sh; path = ../../../scripts/git.commit.sh; sourceTree = ""; }; + 3C1232CB1AAE833300CE8F6C /* git2unix.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = git2unix.sh; path = ../../../scripts/git2unix.sh; sourceTree = ""; }; + 3C1232CC1AAE833300CE8F6C /* install.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = install.sh; path = ../../../scripts/install.sh; sourceTree = ""; }; + 3C1232CD1AAE833300CE8F6C /* package.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = package.sh; path = ../../../scripts/package.sh; sourceTree = ""; }; + 3C1232CE1AAE833300CE8F6C /* run.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = run.sh; path = ../../../scripts/run.sh; sourceTree = ""; }; + 3C1232CF1AAE833300CE8F6C /* srs.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = srs.test; path = ../../../scripts/srs.test; sourceTree = ""; }; + 3C1232D01AAE833300CE8F6C /* stop.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = stop.sh; path = ../../../scripts/stop.sh; sourceTree = ""; }; + 3C1232D11AAE833300CE8F6C /* test_configure.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = test_configure.sh; path = ../../../scripts/test_configure.sh; sourceTree = ""; }; + 3C1232D21AAEA56B00CE8F6C /* libst.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libst.a; path = "../../objs/st-1.9/DARWIN_14.0.0_DBG/libst.a"; sourceTree = ""; }; + 3C1232E71AAEA5D000CE8F6C /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = "../../objs/openssl-1.0.1f/_release/lib/libcrypto.a"; sourceTree = ""; }; + 3C1232E81AAEA5D000CE8F6C /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = "../../objs/openssl-1.0.1f/_release/lib/libssl.a"; sourceTree = ""; }; + 3C1232EC1AAEA70F00CE8F6C /* libhttp_parser.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhttp_parser.a; path = "../../objs/http-parser-2.1/libhttp_parser.a"; sourceTree = ""; }; + 3C1232F11AAEAC7000CE8F6C /* srs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = srs; path = ../../../etc/init.d/srs; sourceTree = ""; }; + 3C1232F21AAEAC7000CE8F6C /* srs-api */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "srs-api"; path = "../../../etc/init.d/srs-api"; sourceTree = ""; }; + 3C1232F31AAEAC7000CE8F6C /* srs-demo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "srs-demo"; path = "../../../etc/init.d/srs-demo"; sourceTree = ""; }; + 3C1232F41AAEAC7000CE8F6C /* srs-demo-19350 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "srs-demo-19350"; path = "../../../etc/init.d/srs-demo-19350"; sourceTree = ""; }; + 3C663F011AB0155100286D8B /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = ../../../research/librtmp/Makefile; sourceTree = ""; }; + 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_aac_raw_publish.c; path = ../../../research/librtmp/srs_aac_raw_publish.c; sourceTree = ""; }; + 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_audio_raw_publish.c; path = ../../../research/librtmp/srs_audio_raw_publish.c; sourceTree = ""; }; + 3C663F041AB0155100286D8B /* srs_bandwidth_check.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_bandwidth_check.c; path = ../../../research/librtmp/srs_bandwidth_check.c; sourceTree = ""; }; + 3C663F051AB0155100286D8B /* srs_detect_rtmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_detect_rtmp.c; path = ../../../research/librtmp/srs_detect_rtmp.c; sourceTree = ""; }; + 3C663F061AB0155100286D8B /* srs_flv_injecter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_flv_injecter.c; path = ../../../research/librtmp/srs_flv_injecter.c; sourceTree = ""; }; + 3C663F071AB0155100286D8B /* srs_flv_parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_flv_parser.c; path = ../../../research/librtmp/srs_flv_parser.c; sourceTree = ""; }; + 3C663F081AB0155100286D8B /* srs_h264_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_h264_raw_publish.c; path = ../../../research/librtmp/srs_h264_raw_publish.c; sourceTree = ""; }; + 3C663F091AB0155100286D8B /* srs_ingest_flv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_ingest_flv.c; path = ../../../research/librtmp/srs_ingest_flv.c; sourceTree = ""; }; + 3C663F0A1AB0155100286D8B /* srs_ingest_rtmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_ingest_rtmp.c; path = ../../../research/librtmp/srs_ingest_rtmp.c; sourceTree = ""; }; + 3C663F0B1AB0155100286D8B /* srs_play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_play.c; path = ../../../research/librtmp/srs_play.c; sourceTree = ""; }; + 3C663F0C1AB0155100286D8B /* srs_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_publish.c; path = ../../../research/librtmp/srs_publish.c; sourceTree = ""; }; + 3C663F0D1AB0155100286D8B /* srs_rtmp_dump.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_rtmp_dump.c; path = ../../../research/librtmp/srs_rtmp_dump.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3C1231E21AAE64A400CE8F6C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C1232ED1AAEA70F00CE8F6C /* libhttp_parser.a in Frameworks */, + 3C1232E91AAEA5D000CE8F6C /* libcrypto.a in Frameworks */, + 3C1232EA1AAEA5D000CE8F6C /* libssl.a in Frameworks */, + 3C1232D31AAEA56B00CE8F6C /* libst.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3C1231DC1AAE64A400CE8F6C = { + isa = PBXGroup; + children = ( + 3C1231E61AAE64A400CE8F6C /* Products */, + 3C1232EE1AAEA71C00CE8F6C /* links */, + 3C1231E71AAE64A400CE8F6C /* srs_xcode */, + 3C663F001AB014B500286D8B /* research */, + ); + sourceTree = ""; + }; + 3C1231E61AAE64A400CE8F6C /* Products */ = { + isa = PBXGroup; + children = ( + 3C1231E51AAE64A400CE8F6C /* srs_xcode */, + ); + name = Products; + sourceTree = ""; + }; + 3C1231E71AAE64A400CE8F6C /* srs_xcode */ = { + isa = PBXGroup; + children = ( + 3C1232B81AAE824500CE8F6C /* configure */, + 3C1232EF1AAEAC5800CE8F6C /* etc */, + 3C1232BA1AAE826F00CE8F6C /* auto */, + 3C1232B91AAE825100CE8F6C /* scripts */, + 3C12324B1AAE81CE00CE8F6C /* app */, + 3C12322C1AAE819900CE8F6C /* protocol */, + 3C1232071AAE814200CE8F6C /* kernel */, + 3C1232041AAE80CB00CE8F6C /* main */, + 3C1231F91AAE670E00CE8F6C /* objs */, + 3C1231EF1AAE651100CE8F6C /* core */, + ); + path = srs_xcode; + sourceTree = ""; + }; + 3C1231EF1AAE651100CE8F6C /* core */ = { + isa = PBXGroup; + children = ( + 3C1231F01AAE652C00CE8F6C /* srs_core_autofree.cpp */, + 3C1231F11AAE652C00CE8F6C /* srs_core_autofree.hpp */, + 3C1231F21AAE652C00CE8F6C /* srs_core_performance.cpp */, + 3C1231F31AAE652C00CE8F6C /* srs_core_performance.hpp */, + 3C1231F41AAE652D00CE8F6C /* srs_core.cpp */, + 3C1231F51AAE652D00CE8F6C /* srs_core.hpp */, + ); + name = core; + sourceTree = ""; + }; + 3C1231F91AAE670E00CE8F6C /* objs */ = { + isa = PBXGroup; + children = ( + 3C1231FB1AAE673100CE8F6C /* srs_auto_headers.hpp */, + ); + name = objs; + sourceTree = ""; + }; + 3C1232041AAE80CB00CE8F6C /* main */ = { + isa = PBXGroup; + children = ( + 3C1232051AAE812C00CE8F6C /* srs_main_server.cpp */, + ); + name = main; + sourceTree = ""; + }; + 3C1232071AAE814200CE8F6C /* kernel */ = { + isa = PBXGroup; + children = ( + 3C1232081AAE814D00CE8F6C /* srs_kernel_aac.cpp */, + 3C1232091AAE814D00CE8F6C /* srs_kernel_aac.hpp */, + 3C12320A1AAE814D00CE8F6C /* srs_kernel_buffer.cpp */, + 3C12320B1AAE814D00CE8F6C /* srs_kernel_buffer.hpp */, + 3C12320C1AAE814D00CE8F6C /* srs_kernel_codec.cpp */, + 3C12320D1AAE814D00CE8F6C /* srs_kernel_codec.hpp */, + 3C12320E1AAE814D00CE8F6C /* srs_kernel_consts.cpp */, + 3C12320F1AAE814D00CE8F6C /* srs_kernel_consts.hpp */, + 3C1232101AAE814D00CE8F6C /* srs_kernel_error.cpp */, + 3C1232111AAE814D00CE8F6C /* srs_kernel_error.hpp */, + 3C1232121AAE814D00CE8F6C /* srs_kernel_file.cpp */, + 3C1232131AAE814D00CE8F6C /* srs_kernel_file.hpp */, + 3C1232141AAE814D00CE8F6C /* srs_kernel_flv.cpp */, + 3C1232151AAE814D00CE8F6C /* srs_kernel_flv.hpp */, + 3C1232161AAE814D00CE8F6C /* srs_kernel_log.cpp */, + 3C1232171AAE814D00CE8F6C /* srs_kernel_log.hpp */, + 3C1232181AAE814D00CE8F6C /* srs_kernel_mp3.cpp */, + 3C1232191AAE814D00CE8F6C /* srs_kernel_mp3.hpp */, + 3C12321A1AAE814D00CE8F6C /* srs_kernel_stream.cpp */, + 3C12321B1AAE814D00CE8F6C /* srs_kernel_stream.hpp */, + 3C12321C1AAE814D00CE8F6C /* srs_kernel_ts.cpp */, + 3C12321D1AAE814D00CE8F6C /* srs_kernel_ts.hpp */, + 3C12321E1AAE814D00CE8F6C /* srs_kernel_utility.cpp */, + 3C12321F1AAE814D00CE8F6C /* srs_kernel_utility.hpp */, + ); + name = kernel; + sourceTree = ""; + }; + 3C12322C1AAE819900CE8F6C /* protocol */ = { + isa = PBXGroup; + children = ( + 3C12322D1AAE81A400CE8F6C /* srs_raw_avc.cpp */, + 3C12322E1AAE81A400CE8F6C /* srs_raw_avc.hpp */, + 3C12322F1AAE81A400CE8F6C /* srs_rtmp_amf0.cpp */, + 3C1232301AAE81A400CE8F6C /* srs_rtmp_amf0.hpp */, + 3C1232311AAE81A400CE8F6C /* srs_rtmp_buffer.cpp */, + 3C1232321AAE81A400CE8F6C /* srs_rtmp_buffer.hpp */, + 3C1232331AAE81A400CE8F6C /* srs_rtmp_handshake.cpp */, + 3C1232341AAE81A400CE8F6C /* srs_rtmp_handshake.hpp */, + 3C1232351AAE81A400CE8F6C /* srs_rtmp_io.cpp */, + 3C1232361AAE81A400CE8F6C /* srs_rtmp_io.hpp */, + 3C1232371AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp */, + 3C1232381AAE81A400CE8F6C /* srs_rtmp_msg_array.hpp */, + 3C1232391AAE81A400CE8F6C /* srs_rtmp_sdk.cpp */, + 3C12323A1AAE81A400CE8F6C /* srs_rtmp_sdk.hpp */, + 3C12323B1AAE81A400CE8F6C /* srs_rtmp_stack.cpp */, + 3C12323C1AAE81A400CE8F6C /* srs_rtmp_stack.hpp */, + 3C12323D1AAE81A400CE8F6C /* srs_rtmp_utility.cpp */, + 3C12323E1AAE81A400CE8F6C /* srs_rtmp_utility.hpp */, + 3C12323F1AAE81A400CE8F6C /* srs_rtsp_stack.cpp */, + 3C1232401AAE81A400CE8F6C /* srs_rtsp_stack.hpp */, + ); + name = protocol; + sourceTree = ""; + }; + 3C12324B1AAE81CE00CE8F6C /* app */ = { + isa = PBXGroup; + children = ( + 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */, + 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */, + 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */, + 3C12324F1AAE81D900CE8F6C /* srs_app_config.hpp */, + 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */, + 3C1232511AAE81D900CE8F6C /* srs_app_conn.hpp */, + 3C1232521AAE81D900CE8F6C /* srs_app_dvr.cpp */, + 3C1232531AAE81D900CE8F6C /* srs_app_dvr.hpp */, + 3C1232541AAE81D900CE8F6C /* srs_app_edge.cpp */, + 3C1232551AAE81D900CE8F6C /* srs_app_edge.hpp */, + 3C1232561AAE81D900CE8F6C /* srs_app_empty.cpp */, + 3C1232571AAE81D900CE8F6C /* srs_app_empty.hpp */, + 3C1232581AAE81D900CE8F6C /* srs_app_encoder.cpp */, + 3C1232591AAE81D900CE8F6C /* srs_app_encoder.hpp */, + 3C12325A1AAE81D900CE8F6C /* srs_app_ffmpeg.cpp */, + 3C12325B1AAE81D900CE8F6C /* srs_app_ffmpeg.hpp */, + 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */, + 3C12325D1AAE81D900CE8F6C /* srs_app_forward.hpp */, + 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */, + 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */, + 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */, + 3C1232611AAE81D900CE8F6C /* srs_app_hls.hpp */, + 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */, + 3C1232631AAE81D900CE8F6C /* srs_app_http_api.hpp */, + 3C1232641AAE81D900CE8F6C /* srs_app_http_client.cpp */, + 3C1232651AAE81D900CE8F6C /* srs_app_http_client.hpp */, + 3C1232661AAE81D900CE8F6C /* srs_app_http_conn.cpp */, + 3C1232671AAE81D900CE8F6C /* srs_app_http_conn.hpp */, + 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */, + 3C1232691AAE81D900CE8F6C /* srs_app_http_hooks.hpp */, + 3C12326A1AAE81D900CE8F6C /* srs_app_http.cpp */, + 3C12326B1AAE81D900CE8F6C /* srs_app_http.hpp */, + 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */, + 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */, + 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */, + 3C12326F1AAE81D900CE8F6C /* srs_app_json.hpp */, + 3C1232701AAE81D900CE8F6C /* srs_app_kbps.cpp */, + 3C1232711AAE81D900CE8F6C /* srs_app_kbps.hpp */, + 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */, + 3C1232731AAE81D900CE8F6C /* srs_app_listener.hpp */, + 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */, + 3C1232751AAE81D900CE8F6C /* srs_app_log.hpp */, + 3C1232761AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp */, + 3C1232771AAE81D900CE8F6C /* srs_app_mpegts_udp.hpp */, + 3C1232781AAE81D900CE8F6C /* srs_app_pithy_print.cpp */, + 3C1232791AAE81D900CE8F6C /* srs_app_pithy_print.hpp */, + 3C12327A1AAE81D900CE8F6C /* srs_app_recv_thread.cpp */, + 3C12327B1AAE81D900CE8F6C /* srs_app_recv_thread.hpp */, + 3C12327C1AAE81D900CE8F6C /* srs_app_refer.cpp */, + 3C12327D1AAE81D900CE8F6C /* srs_app_refer.hpp */, + 3C12327E1AAE81D900CE8F6C /* srs_app_reload.cpp */, + 3C12327F1AAE81D900CE8F6C /* srs_app_reload.hpp */, + 3C1232801AAE81D900CE8F6C /* srs_app_rtmp_conn.cpp */, + 3C1232811AAE81D900CE8F6C /* srs_app_rtmp_conn.hpp */, + 3C1232821AAE81D900CE8F6C /* srs_app_rtsp.cpp */, + 3C1232831AAE81D900CE8F6C /* srs_app_rtsp.hpp */, + 3C1232841AAE81D900CE8F6C /* srs_app_security.cpp */, + 3C1232851AAE81D900CE8F6C /* srs_app_security.hpp */, + 3C1232861AAE81D900CE8F6C /* srs_app_server.cpp */, + 3C1232871AAE81D900CE8F6C /* srs_app_server.hpp */, + 3C1232881AAE81D900CE8F6C /* srs_app_source.cpp */, + 3C1232891AAE81D900CE8F6C /* srs_app_source.hpp */, + 3C12328A1AAE81D900CE8F6C /* srs_app_st_socket.cpp */, + 3C12328B1AAE81D900CE8F6C /* srs_app_st_socket.hpp */, + 3C12328C1AAE81D900CE8F6C /* srs_app_st.cpp */, + 3C12328D1AAE81D900CE8F6C /* srs_app_st.hpp */, + 3C12328E1AAE81D900CE8F6C /* srs_app_statistic.cpp */, + 3C12328F1AAE81D900CE8F6C /* srs_app_statistic.hpp */, + 3C1232901AAE81D900CE8F6C /* srs_app_thread.cpp */, + 3C1232911AAE81D900CE8F6C /* srs_app_thread.hpp */, + 3C1232921AAE81D900CE8F6C /* srs_app_utility.cpp */, + 3C1232931AAE81D900CE8F6C /* srs_app_utility.hpp */, + ); + name = app; + sourceTree = ""; + }; + 3C1232B91AAE825100CE8F6C /* scripts */ = { + isa = PBXGroup; + children = ( + 3C1232C81AAE833300CE8F6C /* _log.sh */, + 3C1232C91AAE833300CE8F6C /* build.sh */, + 3C1232CA1AAE833300CE8F6C /* git.commit.sh */, + 3C1232CB1AAE833300CE8F6C /* git2unix.sh */, + 3C1232CC1AAE833300CE8F6C /* install.sh */, + 3C1232CD1AAE833300CE8F6C /* package.sh */, + 3C1232CE1AAE833300CE8F6C /* run.sh */, + 3C1232CF1AAE833300CE8F6C /* srs.test */, + 3C1232D01AAE833300CE8F6C /* stop.sh */, + 3C1232D11AAE833300CE8F6C /* test_configure.sh */, + ); + name = scripts; + sourceTree = ""; + }; + 3C1232BA1AAE826F00CE8F6C /* auto */ = { + isa = PBXGroup; + children = ( + 3C1232BB1AAE827E00CE8F6C /* apps.sh */, + 3C1232BC1AAE827E00CE8F6C /* auto_headers.sh */, + 3C1232BD1AAE827E00CE8F6C /* build_ffmpeg.sh */, + 3C1232BE1AAE827E00CE8F6C /* depends.sh */, + 3C1232BF1AAE827E00CE8F6C /* generate_header.sh */, + 3C1232C01AAE827E00CE8F6C /* generate-srs-librtmp-project.sh */, + 3C1232C11AAE827E00CE8F6C /* generate-srs-librtmp-single.sh */, + 3C1232C21AAE827E00CE8F6C /* libs.sh */, + 3C1232C31AAE827E00CE8F6C /* local_ip.sh */, + 3C1232C41AAE827E00CE8F6C /* modules.sh */, + 3C1232C51AAE827E00CE8F6C /* options.sh */, + 3C1232C61AAE827E00CE8F6C /* summary.sh */, + 3C1232C71AAE827E00CE8F6C /* utest.sh */, + ); + name = auto; + sourceTree = ""; + }; + 3C1232EE1AAEA71C00CE8F6C /* links */ = { + isa = PBXGroup; + children = ( + 3C1232EC1AAEA70F00CE8F6C /* libhttp_parser.a */, + 3C1232D21AAEA56B00CE8F6C /* libst.a */, + 3C1232E81AAEA5D000CE8F6C /* libssl.a */, + 3C1232E71AAEA5D000CE8F6C /* libcrypto.a */, + ); + name = links; + sourceTree = ""; + }; + 3C1232EF1AAEAC5800CE8F6C /* etc */ = { + isa = PBXGroup; + children = ( + 3C1232F01AAEAC5D00CE8F6C /* init.d */, + ); + name = etc; + sourceTree = ""; + }; + 3C1232F01AAEAC5D00CE8F6C /* init.d */ = { + isa = PBXGroup; + children = ( + 3C1232F11AAEAC7000CE8F6C /* srs */, + 3C1232F21AAEAC7000CE8F6C /* srs-api */, + 3C1232F31AAEAC7000CE8F6C /* srs-demo */, + 3C1232F41AAEAC7000CE8F6C /* srs-demo-19350 */, + ); + name = init.d; + sourceTree = ""; + }; + 3C663F001AB014B500286D8B /* research */ = { + isa = PBXGroup; + children = ( + 3C663F011AB0155100286D8B /* Makefile */, + 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */, + 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */, + 3C663F041AB0155100286D8B /* srs_bandwidth_check.c */, + 3C663F051AB0155100286D8B /* srs_detect_rtmp.c */, + 3C663F061AB0155100286D8B /* srs_flv_injecter.c */, + 3C663F071AB0155100286D8B /* srs_flv_parser.c */, + 3C663F081AB0155100286D8B /* srs_h264_raw_publish.c */, + 3C663F091AB0155100286D8B /* srs_ingest_flv.c */, + 3C663F0A1AB0155100286D8B /* srs_ingest_rtmp.c */, + 3C663F0B1AB0155100286D8B /* srs_play.c */, + 3C663F0C1AB0155100286D8B /* srs_publish.c */, + 3C663F0D1AB0155100286D8B /* srs_rtmp_dump.c */, + ); + name = research; + path = srs_xcode; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3C1231E41AAE64A400CE8F6C /* srs_xcode */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3C1231EC1AAE64A400CE8F6C /* Build configuration list for PBXNativeTarget "srs_xcode" */; + buildPhases = ( + 3C1231E11AAE64A400CE8F6C /* Sources */, + 3C1231E21AAE64A400CE8F6C /* Frameworks */, + 3C1231E31AAE64A400CE8F6C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = srs_xcode; + productName = srs_xcode; + productReference = 3C1231E51AAE64A400CE8F6C /* srs_xcode */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3C1231DD1AAE64A400CE8F6C /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = winlin; + TargetAttributes = { + 3C1231E41AAE64A400CE8F6C = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = 3C1231E01AAE64A400CE8F6C /* Build configuration list for PBXProject "srs_xcode" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 3C1231DC1AAE64A400CE8F6C; + productRefGroup = 3C1231E61AAE64A400CE8F6C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3C1231E41AAE64A400CE8F6C /* srs_xcode */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 3C1231E11AAE64A400CE8F6C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C1232951AAE81D900CE8F6C /* srs_app_config.cpp in Sources */, + 3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */, + 3C1232961AAE81D900CE8F6C /* srs_app_conn.cpp in Sources */, + 3C12322A1AAE814D00CE8F6C /* srs_kernel_ts.cpp in Sources */, + 3C12329E1AAE81D900CE8F6C /* srs_app_hls.cpp in Sources */, + 3C663F171AB0155100286D8B /* srs_ingest_rtmp.c in Sources */, + 3C663F131AB0155100286D8B /* srs_flv_injecter.c in Sources */, + 3C1232971AAE81D900CE8F6C /* srs_app_dvr.cpp in Sources */, + 3C1232271AAE814D00CE8F6C /* srs_kernel_log.cpp in Sources */, + 3C1232A81AAE81D900CE8F6C /* srs_app_log.cpp in Sources */, + 3C1232A41AAE81D900CE8F6C /* srs_app_ingest.cpp in Sources */, + 3C1232B41AAE81D900CE8F6C /* srs_app_st.cpp in Sources */, + 3C1232481AAE81A400CE8F6C /* srs_rtmp_stack.cpp in Sources */, + 3C1232B01AAE81D900CE8F6C /* srs_app_security.cpp in Sources */, + 3C12322B1AAE814D00CE8F6C /* srs_kernel_utility.cpp in Sources */, + 3C12324A1AAE81A400CE8F6C /* srs_rtsp_stack.cpp in Sources */, + 3C1232A51AAE81D900CE8F6C /* srs_app_json.cpp in Sources */, + 3C12329F1AAE81D900CE8F6C /* srs_app_http_api.cpp in Sources */, + 3C663F101AB0155100286D8B /* srs_audio_raw_publish.c in Sources */, + 3C663F111AB0155100286D8B /* srs_bandwidth_check.c in Sources */, + 3C1232A11AAE81D900CE8F6C /* srs_app_http_conn.cpp in Sources */, + 3C1232AC1AAE81D900CE8F6C /* srs_app_refer.cpp in Sources */, + 3C1232991AAE81D900CE8F6C /* srs_app_empty.cpp in Sources */, + 3C1232201AAE814D00CE8F6C /* srs_kernel_aac.cpp in Sources */, + 3C1232941AAE81D900CE8F6C /* srs_app_bandwidth.cpp in Sources */, + 3C1232221AAE814D00CE8F6C /* srs_kernel_codec.cpp in Sources */, + 3C1232B71AAE81D900CE8F6C /* srs_app_utility.cpp in Sources */, + 3C1232AB1AAE81D900CE8F6C /* srs_app_recv_thread.cpp in Sources */, + 3C663F151AB0155100286D8B /* srs_h264_raw_publish.c in Sources */, + 3C1231F61AAE652D00CE8F6C /* srs_core_autofree.cpp in Sources */, + 3C1232411AAE81A400CE8F6C /* srs_raw_avc.cpp in Sources */, + 3C1232491AAE81A400CE8F6C /* srs_rtmp_utility.cpp in Sources */, + 3C663F191AB0155100286D8B /* srs_publish.c in Sources */, + 3C1232A01AAE81D900CE8F6C /* srs_app_http_client.cpp in Sources */, + 3C12329B1AAE81D900CE8F6C /* srs_app_ffmpeg.cpp in Sources */, + 3C1232421AAE81A400CE8F6C /* srs_rtmp_amf0.cpp in Sources */, + 3C1232AA1AAE81D900CE8F6C /* srs_app_pithy_print.cpp in Sources */, + 3C12329C1AAE81D900CE8F6C /* srs_app_forward.cpp in Sources */, + 3C1232251AAE814D00CE8F6C /* srs_kernel_file.cpp in Sources */, + 3C1232AD1AAE81D900CE8F6C /* srs_app_reload.cpp in Sources */, + 3C1231F81AAE652D00CE8F6C /* srs_core.cpp in Sources */, + 3C1232A21AAE81D900CE8F6C /* srs_app_http_hooks.cpp in Sources */, + 3C663F121AB0155100286D8B /* srs_detect_rtmp.c in Sources */, + 3C1232B11AAE81D900CE8F6C /* srs_app_server.cpp in Sources */, + 3C1232B31AAE81D900CE8F6C /* srs_app_st_socket.cpp in Sources */, + 3C1232061AAE812C00CE8F6C /* srs_main_server.cpp in Sources */, + 3C1232281AAE814D00CE8F6C /* srs_kernel_mp3.cpp in Sources */, + 3C1232B21AAE81D900CE8F6C /* srs_app_source.cpp in Sources */, + 3C1231F71AAE652D00CE8F6C /* srs_core_performance.cpp in Sources */, + 3C1232981AAE81D900CE8F6C /* srs_app_edge.cpp in Sources */, + 3C1232461AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp in Sources */, + 3C1232A71AAE81D900CE8F6C /* srs_app_listener.cpp in Sources */, + 3C1232261AAE814D00CE8F6C /* srs_kernel_flv.cpp in Sources */, + 3C663F1A1AB0155100286D8B /* srs_rtmp_dump.c in Sources */, + 3C1232241AAE814D00CE8F6C /* srs_kernel_error.cpp in Sources */, + 3C1232441AAE81A400CE8F6C /* srs_rtmp_handshake.cpp in Sources */, + 3C1232291AAE814D00CE8F6C /* srs_kernel_stream.cpp in Sources */, + 3C663F181AB0155100286D8B /* srs_play.c in Sources */, + 3C1232B61AAE81D900CE8F6C /* srs_app_thread.cpp in Sources */, + 3C1232A91AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp in Sources */, + 3C1232AE1AAE81D900CE8F6C /* srs_app_rtmp_conn.cpp in Sources */, + 3C1232B51AAE81D900CE8F6C /* srs_app_statistic.cpp in Sources */, + 3C663F161AB0155100286D8B /* srs_ingest_flv.c in Sources */, + 3C663F141AB0155100286D8B /* srs_flv_parser.c in Sources */, + 3C1232451AAE81A400CE8F6C /* srs_rtmp_io.cpp in Sources */, + 3C1232431AAE81A400CE8F6C /* srs_rtmp_buffer.cpp in Sources */, + 3C663F0E1AB0155100286D8B /* Makefile in Sources */, + 3C1232211AAE814D00CE8F6C /* srs_kernel_buffer.cpp in Sources */, + 3C1232471AAE81A400CE8F6C /* srs_rtmp_sdk.cpp in Sources */, + 3C1232A61AAE81D900CE8F6C /* srs_app_kbps.cpp in Sources */, + 3C12329D1AAE81D900CE8F6C /* srs_app_heartbeat.cpp in Sources */, + 3C1232231AAE814D00CE8F6C /* srs_kernel_consts.cpp in Sources */, + 3C1232AF1AAE81D900CE8F6C /* srs_app_rtsp.cpp in Sources */, + 3C1232A31AAE81D900CE8F6C /* srs_app_http.cpp in Sources */, + 3C12329A1AAE81D900CE8F6C /* srs_app_encoder.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 3C1231EA1AAE64A400CE8F6C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 3C1231EB1AAE64A400CE8F6C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 3C1231ED1AAE64A400CE8F6C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libstdc++"; + LIBRARY_SEARCH_PATHS = ( + "../../objs/**", + "/Users/winlin/Desktop/git/simple-rtmp-server/trunk/objs/http-parser-2.1", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + "USER_HEADER_SEARCH_PATHS[arch=*]" = "../../src/** ../../objs ../../objs/st ../../objs/hp ../../objs/openssl"; + }; + name = Debug; + }; + 3C1231EE1AAE64A400CE8F6C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++98"; + CLANG_CXX_LIBRARY = "libstdc++"; + LIBRARY_SEARCH_PATHS = ( + "../../objs/**", + "/Users/winlin/Desktop/git/simple-rtmp-server/trunk/objs/http-parser-2.1", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3C1231E01AAE64A400CE8F6C /* Build configuration list for PBXProject "srs_xcode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3C1231EA1AAE64A400CE8F6C /* Debug */, + 3C1231EB1AAE64A400CE8F6C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3C1231EC1AAE64A400CE8F6C /* Build configuration list for PBXNativeTarget "srs_xcode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3C1231ED1AAE64A400CE8F6C /* Debug */, + 3C1231EE1AAE64A400CE8F6C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3C1231DD1AAE64A400CE8F6C /* Project object */; +} diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..60847b6bd --- /dev/null +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/trunk/ide/srs_xcode/srs_xcode/readme.txt b/trunk/ide/srs_xcode/srs_xcode/readme.txt new file mode 100644 index 000000000..94cb20b46 --- /dev/null +++ b/trunk/ide/srs_xcode/srs_xcode/readme.txt @@ -0,0 +1 @@ +the xcode project for osx. diff --git a/trunk/modules/readme.txt b/trunk/modules/readme.txt new file mode 100644 index 000000000..18be774ed --- /dev/null +++ b/trunk/modules/readme.txt @@ -0,0 +1,11 @@ +SRS模块规则: +1. 一个模块一个目录 +2. 目录下放一个config文件 +3. 所有的configure中的变量模块中可以使用 + +模块中需要定义变量,例如: +1. SRS_MODULE_NAME:模块名称,用来做Makefile的phony以及执行binary文件名。 +2. SRS_MODULE_MAIN:模块的main函数所在的cpp文件,在src/main目录。 +3. SRS_MODULE_APP:模块在src/app目录的源文件列表。 + +winlin, 2015.3 diff --git a/trunk/research/librtmp/srs_ingest_flv.c b/trunk/research/librtmp/srs_ingest_flv.c index 04de28629..7d8ce132c 100644 --- a/trunk/research/librtmp/srs_ingest_flv.c +++ b/trunk/research/librtmp/srs_ingest_flv.c @@ -53,7 +53,8 @@ int main(int argc, char** argv) // user option parse index. int opt = 0; // user options. - char* in_flv_file; char* out_rtmp_url; + char* in_flv_file = NULL; + char* out_rtmp_url = NULL; // rtmp handler srs_rtmp_t ortmp; // flv handler @@ -75,18 +76,35 @@ int main(int argc, char** argv) exit(-1); } - // parse options in FFMPEG format. - while ((opt = getopt(argc, argv, "i:y:")) != -1) { - switch (opt) { - case 'i': - in_flv_file = optarg; - break; - case 'y': - out_rtmp_url = optarg; - break; - default: - break; + for (opt = 0; opt < argc; opt++) { + srs_human_trace("argv[%d]=%s", opt, argv[opt]); + } + + // fill the options for mac + for (opt = 0; opt < argc - 1; opt++) { + // ignore all options except -i and -y. + char* p = argv[opt]; + + // only accept -x + if (p[0] != '-' || p[1] == 0 || p[2] != 0) { + continue; } + + // parse according the option name. + switch (p[1]) { + case 'i': in_flv_file = argv[opt + 1]; break; + case 'y': out_rtmp_url = argv[opt + 1]; break; + default: break; + } + } + + if (!in_flv_file) { + srs_human_trace("input invalid, use -i "); + return -1; + } + if (!out_rtmp_url) { + srs_human_trace("output invalid, use -y "); + return -1; } srs_human_trace("input: %s", in_flv_file); diff --git a/trunk/research/librtmp/srs_ingest_rtmp.c b/trunk/research/librtmp/srs_ingest_rtmp.c index d5ce75aac..d4c8606cd 100644 --- a/trunk/research/librtmp/srs_ingest_rtmp.c +++ b/trunk/research/librtmp/srs_ingest_rtmp.c @@ -41,7 +41,8 @@ int main(int argc, char** argv) // user option parse index. int opt = 0; // user options. - char* in_rtmp_url; char* out_rtmp_url; + char* in_rtmp_url = NULL; + char* out_rtmp_url = NULL; // rtmp handler srs_rtmp_t irtmp, ortmp; @@ -60,18 +61,31 @@ int main(int argc, char** argv) exit(-1); } - // parse options in FFMPEG format. - while ((opt = getopt(argc, argv, "i:y:")) != -1) { - switch (opt) { - case 'i': - in_rtmp_url = optarg; - break; - case 'y': - out_rtmp_url = optarg; - break; - default: - break; + // fill the options for mac + for (opt = 0; opt < argc - 1; opt++) { + // ignore all options except -i and -y. + char* p = argv[opt]; + + // only accept -x + if (p[0] != '-' || p[1] == 0 || p[2] != 0) { + continue; } + + // parse according the option name. + switch (p[1]) { + case 'i': in_rtmp_url = argv[opt + 1]; break; + case 'y': out_rtmp_url = argv[opt + 1]; break; + default: break; + } + } + + if (!in_rtmp_url) { + srs_human_trace("input invalid, use -i "); + return -1; + } + if (!out_rtmp_url) { + srs_human_trace("output invalid, use -y "); + return -1; } srs_human_trace("input: %s", in_rtmp_url); diff --git a/trunk/scripts/_log.sh b/trunk/scripts/_log.sh index 89453aadd..8990c0b80 100755 --- a/trunk/scripts/_log.sh +++ b/trunk/scripts/_log.sh @@ -4,11 +4,11 @@ ####################################### # color echo. ####################################### -RED="\\e[31m" -GREEN="\\e[32m" -YELLOW="\\e[33m" -BLACK="\\e[0m" -POS="\\e[103G" +RED="\\033[31m" +GREEN="\\033[32m" +YELLOW="\\033[33m" +BLACK="\\033[0m" +POS="\\033[103G" # if need to log to file, change the log path. if [[ ! $log ]]; then diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index d748b864e..189aa168f 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1419,7 +1419,6 @@ int SrsConfig::check_config() string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "dvr_path" && m != "dvr_plan" && m != "dvr_duration" && m != "dvr_wait_keyframe" && m != "time_jitter" - && m != "dvr_autostart" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost dvr directive %s, ret=%d", m.c_str(), ret); @@ -1978,38 +1977,6 @@ int SrsConfig::get_stream_caster_rtp_port_max(SrsConfDirective* sc) return ::atoi(conf->arg0().c_str()); } -SrsConfDirective* SrsConfig::create_directive(string vhost, string directive, string sub_directive) -{ - SrsConfDirective* vhost_conf = get_vhost(vhost); - - if (!vhost_conf) { - vhost_conf = new SrsConfDirective(); - root->directives.push_back(vhost_conf); - } - - if (directive.empty()) { - return vhost_conf; - } - - SrsConfDirective* dir = vhost_conf->get(directive); - if (!dir) { - dir = new SrsConfDirective(); - vhost_conf->directives.push_back(dir); - } - - if (sub_directive.empty()) { - return dir; - } - - SrsConfDirective* sdir = dir->get(sub_directive); - if (!sdir) { - sdir = new SrsConfDirective(); - dir->directives.push_back(sdir); - } - - return sdir; -} - SrsConfDirective* SrsConfig::get_vhost(string vhost) { srs_assert(root); @@ -3422,13 +3389,6 @@ bool SrsConfig::get_dvr_enabled(string vhost) return false; } -void SrsConfig::set_dvr_enabled(string vhost, bool enabled) -{ - SrsConfDirective* conf = create_directive(vhost, "dvr", "enabled"); - conf->args.clear(); - conf->args.push_back(enabled? "on":"off"); -} - string SrsConfig::get_dvr_path(string vhost) { SrsConfDirective* dvr = get_dvr(vhost); @@ -3446,13 +3406,6 @@ string SrsConfig::get_dvr_path(string vhost) return conf->arg0(); } -void SrsConfig::set_dvr_path(string vhost, string path) -{ - SrsConfDirective* conf = create_directive(vhost, "dvr", "dvr_path"); - conf->args.clear(); - conf->args.push_back(path); -} - string SrsConfig::get_dvr_plan(string vhost) { SrsConfDirective* dvr = get_dvr(vhost); @@ -3504,30 +3457,6 @@ bool SrsConfig::get_dvr_wait_keyframe(string vhost) return false; } -void SrsConfig::set_dvr_wait_keyframe(string vhost, bool wait_keyframe) -{ - SrsConfDirective* conf = create_directive(vhost, "dvr", "dvr_wait_keyframe"); - conf->args.clear(); - conf->args.push_back(wait_keyframe? "on":"off"); -} - -bool SrsConfig::get_dvr_autostart(string vhost) -{ - SrsConfDirective* dvr = get_dvr(vhost); - - if (!dvr) { - return true; - } - - SrsConfDirective* conf = dvr->get("dvr_autostart"); - - if (!conf || conf->arg0() != "off") { - return true; - } - - return false; -} - int SrsConfig::get_dvr_time_jitter(string vhost) { SrsConfDirective* dvr = get_dvr(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 59fe0eda7..055b4a06f 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -61,7 +61,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" #define SRS_CONF_DEFAULT_DVR_PLAN_APPEND "append" -#define SRS_CONF_DEFAULT_DVR_PLAN_API "api" #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION #define SRS_CONF_DEFAULT_DVR_DURATION 30 #define SRS_CONF_DEFAULT_TIME_JITTER "full" @@ -357,11 +356,11 @@ private: * print help and exit. */ virtual void print_help(char** argv); +public: /** * parse the config file, which is specified by cli. */ virtual int parse_file(const char* filename); -public: /** * check the parsed config. */ @@ -457,14 +456,6 @@ public: * get the max udp port for rtp of stream caster rtsp. */ virtual int get_stream_caster_rtp_port_max(SrsConfDirective* sc); -private: - /** - * create directive under vhost. - * @param directive, get the directive of vhost. get vhost if directive is empty. - * @param sub_directive, get the sub directive of vhost. get directive if sub-directive is empty. - * @return the vhost(empty directive and sub-directive); the directive(empty sub-directive); the sub-directive. - */ - virtual SrsConfDirective* create_directive(std::string vhost, std::string directive, std::string sub_directive); // vhost specified section public: /** @@ -954,12 +945,10 @@ public: * whether dvr is enabled. */ virtual bool get_dvr_enabled(std::string vhost); - virtual void set_dvr_enabled(std::string vhost, bool enabled); /** * get the dvr path, the flv file to save in. */ virtual std::string get_dvr_path(std::string vhost); - virtual void set_dvr_path(std::string vhost, std::string path); /** * get the plan of dvr, how to reap the flv file. */ @@ -972,11 +961,6 @@ public: * whether wait keyframe to reap segment. */ virtual bool get_dvr_wait_keyframe(std::string vhost); - virtual void set_dvr_wait_keyframe(std::string vhost, bool wait_keyframe); - /** - * whether autostart for dvr. wait api to start dvr if false. - */ - virtual bool get_dvr_autostart(std::string vhost); /** * get the time_jitter algorithm for dvr. */ @@ -1148,3 +1132,4 @@ bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b); extern SrsConfig* _srs_config; #endif + diff --git a/trunk/src/app/srs_app_conn.cpp b/trunk/src/app/srs_app_conn.cpp index 07282e764..f9372359b 100644 --- a/trunk/src/app/srs_app_conn.cpp +++ b/trunk/src/app/srs_app_conn.cpp @@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) { + id = 0; server = srs_server; stfd = client_stfd; @@ -55,6 +56,8 @@ int SrsConnection::cycle() int ret = ERROR_SUCCESS; _srs_context->generate_id(); + id = _srs_context->get_id(); + ip = srs_get_peer_ip(st_netfd_fileno(stfd)); ret = do_cycle(); @@ -86,6 +89,11 @@ void SrsConnection::on_thread_stop() server->remove(this); } +int SrsConnection::srs_id() +{ + return id; +} + void SrsConnection::stop() { srs_close_stfd(stfd); diff --git a/trunk/src/app/srs_app_conn.hpp b/trunk/src/app/srs_app_conn.hpp index 148e36edc..e13d93649 100644 --- a/trunk/src/app/srs_app_conn.hpp +++ b/trunk/src/app/srs_app_conn.hpp @@ -51,6 +51,10 @@ private: * when thread stop, the connection will be delete by server. */ SrsThread* pthread; + /** + * the id of connection. + */ + int id; protected: /** * the server object to manage the connection. @@ -92,13 +96,9 @@ public: virtual void on_thread_stop(); public: /** - * when server to get the kbps of connection, - * it cannot wait the connection terminated then get the kbps, - * it must sample the kbps every some interval, for instance, 9s to sample all connections kbps, - * all connections will extends from IKbpsDelta which provides the bytes delta, - * while the delta must be update by the sample which invoke by the kbps_resample(). + * get the srs id which identify the client. */ - virtual void kbps_resample() = 0; + virtual int srs_id(); protected: /** * for concrete connection to do the cycle. diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index 6ed944b6e..ef4b759ba 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include using namespace std; #include @@ -54,7 +55,6 @@ using namespace std; SrsFlvSegment::SrsFlvSegment(SrsDvrPlan* p) { req = NULL; - source = NULL; jitter = NULL; plan = p; @@ -85,11 +85,10 @@ SrsFlvSegment::~SrsFlvSegment() srs_freep(enc); } -int SrsFlvSegment::initialize(SrsSource* s, SrsRequest* r) +int SrsFlvSegment::initialize(SrsRequest* r) { int ret = ERROR_SUCCESS; - source = s; req = r; jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(req->vhost); @@ -308,10 +307,10 @@ int SrsFlvSegment::write_video(SrsSharedPtrMessage* __video) char* payload = video->payload; int size = video->size; + bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(payload, size); #ifdef SRS_AUTO_HTTP_CALLBACK bool is_key_frame = SrsFlvCodec::video_is_h264(payload, size) - && SrsFlvCodec::video_is_keyframe(payload, size) - && !SrsFlvCodec::video_is_sequence_header(payload, size); + && SrsFlvCodec::video_is_keyframe(payload, size) && !is_sequence_header; if (is_key_frame) { has_keyframe = true; if ((ret = plan->on_video_keyframe()) != ERROR_SUCCESS) { @@ -320,6 +319,16 @@ int SrsFlvSegment::write_video(SrsSharedPtrMessage* __video) } srs_verbose("dvr video is key: %d", is_key_frame); #endif + + // accept the sequence header here. + // when got no keyframe, ignore when should wait keyframe. + if (!has_keyframe && !is_sequence_header) { + bool wait_keyframe = _srs_config->get_dvr_wait_keyframe(req->vhost); + if (wait_keyframe) { + srs_info("dvr: ignore when wait keyframe."); + return ret; + } + } if ((jitter->correct(video, 0, 0, jitter_algorithm)) != ERROR_SUCCESS) { return ret; @@ -617,48 +626,6 @@ string SrsDvrAsyncCallOnDvr::to_string() return ss.str(); } -SrsDvrAsyncCallOnSegment::SrsDvrAsyncCallOnSegment(SrsRequest* r, string c, string p) -{ - req = r; - callback = c; - path = p; -} - -SrsDvrAsyncCallOnSegment::~SrsDvrAsyncCallOnSegment() -{ -} - -int SrsDvrAsyncCallOnSegment::call() -{ - int ret = ERROR_SUCCESS; - -#ifdef SRS_AUTO_HTTP_CALLBACK - // HTTP: callback - if (callback.empty()) { - srs_warn("dvr: ignore for callback empty, vhost=%s", req->vhost.c_str()); - return ret; - } - - int connection_id = _srs_context->get_id(); - std::string cwd = _srs_config->cwd(); - std::string file = path; - std::string url = callback; - if ((ret = SrsHttpHooks::on_dvr_reap_segment(url, connection_id, req, cwd, file)) != ERROR_SUCCESS) { - srs_error("hook client on_dvr_reap_segment failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } -#endif - - return ret; -} - -string SrsDvrAsyncCallOnSegment::to_string() -{ - std::stringstream ss; - ss << "vhost=" << req->vhost << ", file=" << path << "callback=" << callback; - return ss.str(); -} - SrsDvrAsyncCallThread::SrsDvrAsyncCallThread() { pthread = new SrsThread("async", this, SRS_AUTO_ASYNC_CALLBACL_SLEEP_US, true); @@ -717,7 +684,6 @@ int SrsDvrAsyncCallThread::cycle() SrsDvrPlan::SrsDvrPlan() { - source = NULL; req = NULL; dvr_enabled = false; @@ -731,14 +697,13 @@ SrsDvrPlan::~SrsDvrPlan() srs_freep(async); } -int SrsDvrPlan::initialize(SrsSource* s, SrsRequest* r) +int SrsDvrPlan::initialize(SrsRequest* r) { int ret = ERROR_SUCCESS; - - source = s; + req = r; - if ((ret = segment->initialize(s, r)) != ERROR_SUCCESS) { + if ((ret = segment->initialize(r)) != ERROR_SUCCESS) { return ret; } @@ -749,18 +714,6 @@ int SrsDvrPlan::initialize(SrsSource* s, SrsRequest* r) return ret; } -int SrsDvrPlan::on_dvr_request_sh() -{ - int ret = ERROR_SUCCESS; - - // the dvr is enabled, notice the source to push the data. - if ((ret = source->on_dvr_request_sh()) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - int SrsDvrPlan::on_video_keyframe() { return ERROR_SUCCESS; @@ -832,8 +785,6 @@ SrsDvrPlan* SrsDvrPlan::create_plan(string vhost) return new SrsDvrSessionPlan(); } else if (plan == SRS_CONF_DEFAULT_DVR_PLAN_APPEND) { return new SrsDvrAppendPlan(); - } else if (plan == SRS_CONF_DEFAULT_DVR_PLAN_API) { - return new SrsDvrApiPlan(); } else { srs_error("invalid dvr plan=%s, vhost=%s", plan.c_str(), vhost.c_str()); srs_assert(false); @@ -890,320 +841,6 @@ void SrsDvrSessionPlan::on_unpublish() dvr_enabled = false; } -SrsDvrApiPlan::SrsDvrApiPlan() -{ - autostart = false; - started = false; - - metadata = sh_audio = sh_video = NULL; -} - -SrsDvrApiPlan::~SrsDvrApiPlan() -{ - srs_freep(metadata); - srs_freep(sh_audio); - srs_freep(sh_video); -} - -int SrsDvrApiPlan::initialize(SrsSource* s, SrsRequest* r) -{ - int ret = ERROR_SUCCESS; - - if ((ret = SrsDvrPlan::initialize(s, r)) != ERROR_SUCCESS) { - return ret; - } - - SrsApiDvrPool* pool = SrsApiDvrPool::instance(); - if ((ret = pool->add_dvr(this)) != ERROR_SUCCESS) { - return ret; - } - - autostart = _srs_config->get_dvr_autostart(r->vhost); - - return ret; -} - -int SrsDvrApiPlan::on_publish() -{ - int ret = ERROR_SUCCESS; - - // support multiple publish. - if (dvr_enabled) { - return ret; - } - - if (!_srs_config->get_dvr_enabled(req->vhost)) { - return ret; - } - - // api disabled dvr when not autostart. - bool autostart = _srs_config->get_dvr_autostart(req->vhost); - if (!autostart && !started) { - srs_warn("dvr: api not start and disabled for not autostart."); - return ret; - } - - dvr_enabled = true; - - if ((ret = segment->close()) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = segment->open()) != ERROR_SUCCESS) { - return ret; - } - - // update sequence header - if (metadata && (ret = SrsDvrPlan::on_meta_data(metadata)) != ERROR_SUCCESS) { - return ret; - } - if (sh_video && (ret = SrsDvrPlan::on_video(sh_video)) != ERROR_SUCCESS) { - return ret; - } - if (sh_audio && (ret = SrsDvrPlan::on_audio(sh_audio)) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -void SrsDvrApiPlan::on_unpublish() -{ -} - -int SrsDvrApiPlan::on_meta_data(SrsSharedPtrMessage* __metadata) -{ - int ret = ERROR_SUCCESS; - - srs_freep(metadata); - metadata = __metadata->copy(); - - return ret; -} - -int SrsDvrApiPlan::on_audio(SrsSharedPtrMessage* __audio) -{ - int ret = ERROR_SUCCESS; - - if (SrsFlvCodec::audio_is_sequence_header(__audio->payload, __audio->size)) { - srs_freep(sh_audio); - sh_audio = __audio->copy(); - } - - if ((ret = SrsDvrPlan::on_audio(__audio)) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -int SrsDvrApiPlan::on_video(SrsSharedPtrMessage* __video) -{ - int ret = ERROR_SUCCESS; - - if (SrsFlvCodec::video_is_sequence_header(__video->payload, __video->size)) { - srs_freep(sh_video); - sh_video = __video->copy(); - } - - if ((ret = check_user_actions(__video)) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = SrsDvrPlan::on_video(__video)) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -int SrsDvrApiPlan::set_path_tmpl(string path_tmpl) -{ - _srs_config->set_dvr_path(req->vhost, path_tmpl); - return ERROR_SUCCESS; -} - -int SrsDvrApiPlan::set_callback(string value) -{ - callback = value; - return ERROR_SUCCESS; -} - -int SrsDvrApiPlan::set_wait_keyframe(bool wait_keyframe) -{ - _srs_config->set_dvr_wait_keyframe(req->vhost, wait_keyframe); - return ERROR_SUCCESS; -} - -int SrsDvrApiPlan::start() -{ - int ret = ERROR_SUCCESS; - - if (started) { - return ret; - } - - // enable the config. - _srs_config->set_dvr_enabled(req->vhost, true); - - // stop dvr - if (dvr_enabled) { - // ignore error. - int ret = segment->close(); - if (ret != ERROR_SUCCESS) { - srs_warn("ignore flv close error. ret=%d", ret); - } - - dvr_enabled = false; - } - - // start dvr - if ((ret = on_publish()) != ERROR_SUCCESS) { - return ret; - } - - started = true; - return ret; -} - -int SrsDvrApiPlan::dumps(stringstream& ss) -{ - int ret = ERROR_SUCCESS; - - bool wait_keyframe = _srs_config->get_dvr_wait_keyframe(req->vhost); - std::string path_template = _srs_config->get_dvr_path(req->vhost); - - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_STR("path_tmpl", path_template) << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("path_dvr", segment->get_path()) << __SRS_JFIELD_CONT - << __SRS_JFIELD_BOOL("wait_keyframe", wait_keyframe) << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("callback", callback) << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("status", (dvr_enabled? "start":"stop")) - << __SRS_JOBJECT_END; - - return ret; -} - -int SrsDvrApiPlan::stop() -{ - int ret = ERROR_SUCCESS; - - _srs_config->set_dvr_enabled(req->vhost, false); - started = false; - - // stop dvr - if (dvr_enabled) { - // ignore error. - int ret = segment->close(); - if (ret != ERROR_SUCCESS) { - srs_warn("ignore flv close error. ret=%d", ret); - } - - dvr_enabled = false; - } - - srs_trace("dvr: stop dvr of vhost=%s", req->vhost.c_str()); - - return ret; -} - -int SrsDvrApiPlan::rpc(SrsJsonObject* obj) -{ - int ret = ERROR_SUCCESS; - - SrsJsonAny* prop = NULL; - if ((prop = obj->ensure_property_string("action")) == NULL) { - ret = ERROR_HTTP_DVR_REQUEST; - srs_error("dvr: rpc required action request. ret=%d", ret); - return ret; - } - - action = prop->to_str(); - if (action == SRS_DVR_USER_ACTION_REAP_SEGMENT) { - if ((prop = obj->ensure_property_string("path_tmpl")) != NULL) { - path_template = prop->to_str(); - } - } else { - ret = ERROR_HTTP_DVR_REQUEST; - } - - return ret; -} - -int SrsDvrApiPlan::on_reap_segment() -{ - int ret = ERROR_SUCCESS; - - if ((ret = SrsDvrPlan::on_reap_segment()) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = async->call(new SrsDvrAsyncCallOnSegment(req, callback, segment->get_path()))) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -int SrsDvrApiPlan::check_user_actions(SrsSharedPtrMessage* msg) -{ - int ret = ERROR_SUCCESS; - - srs_assert(segment); - - if (action == SRS_DVR_USER_ACTION_REAP_SEGMENT) { - // when wait keyframe, ignore if no frame arrived. - // @see https://github.com/winlinvip/simple-rtmp-server/issues/177 - if (_srs_config->get_dvr_wait_keyframe(req->vhost)) { - if (!msg->is_video()) { - return ret; - } - - char* payload = msg->payload; - int size = msg->size; - bool is_key_frame = SrsFlvCodec::video_is_h264(payload, size) - && SrsFlvCodec::video_is_keyframe(payload, size) - && !SrsFlvCodec::video_is_sequence_header(payload, size); - if (!is_key_frame) { - return ret; - } - } - - // reap segment - if ((ret = segment->close()) != ERROR_SUCCESS) { - return ret; - } - - // use new path template if user specified. - if (!path_template.empty() && (ret = set_path_tmpl(path_template)) != ERROR_SUCCESS) { - return ret; - } - - // open new flv file - if ((ret = segment->open()) != ERROR_SUCCESS) { - return ret; - } - - // update sequence header - if (metadata && (ret = SrsDvrPlan::on_meta_data(metadata)) != ERROR_SUCCESS) { - return ret; - } - if (sh_video && (ret = SrsDvrPlan::on_video(sh_video)) != ERROR_SUCCESS) { - return ret; - } - if (sh_audio && (ret = SrsDvrPlan::on_audio(sh_audio)) != ERROR_SUCCESS) { - return ret; - } - } - - // reset rcp params. - action = ""; - path_template = ""; - - return ret; -} - SrsDvrAppendPlan::SrsDvrAppendPlan() { last_update_time = 0; @@ -1309,11 +946,11 @@ SrsDvrSegmentPlan::~SrsDvrSegmentPlan() srs_freep(metadata); } -int SrsDvrSegmentPlan::initialize(SrsSource* source, SrsRequest* req) +int SrsDvrSegmentPlan::initialize(SrsRequest* req) { int ret = ERROR_SUCCESS; - if ((ret = SrsDvrPlan::initialize(source, req)) != ERROR_SUCCESS) { + if ((ret = SrsDvrPlan::initialize(req)) != ERROR_SUCCESS) { return ret; } @@ -1460,183 +1097,9 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg) return ret; } -SrsApiDvrPool* SrsApiDvrPool::_instance = new SrsApiDvrPool(); - -SrsApiDvrPool* SrsApiDvrPool::instance() +SrsDvr::SrsDvr() { - return SrsApiDvrPool::_instance; -} - -SrsApiDvrPool::SrsApiDvrPool() -{ -} - -SrsApiDvrPool::~SrsApiDvrPool() -{ - dvrs.clear(); -} - -int SrsApiDvrPool::add_dvr(SrsDvrApiPlan* dvr) -{ - dvrs.push_back(dvr); - return ERROR_SUCCESS; -} - -int SrsApiDvrPool::dumps(string vhost, stringstream& ss) -{ - int ret = ERROR_SUCCESS; - - ss << __SRS_JARRAY_START; - - std::vector plans; - for (int i = 0; i < (int)dvrs.size(); i++) { - SrsDvrApiPlan* plan = dvrs.at(i); - if (!vhost.empty() && plan->req->vhost != vhost) { - continue; - } - plans.push_back(plan); - } - - for (int i = 0; i < (int)plans.size(); i++) { - SrsDvrApiPlan* plan = plans.at(i); - - if ((ret = plan->dumps(ss)) != ERROR_SUCCESS) { - return ret; - } - - if (i < (int)dvrs.size() - 1) { - ss << __SRS_JFIELD_CONT; - } - } - - ss << __SRS_JARRAY_END; - - return ret; -} - -int SrsApiDvrPool::create(SrsJsonAny* json) -{ - int ret = ERROR_SUCCESS; - - srs_assert(json); - if (!json->is_object()) { - ret = ERROR_HTTP_DVR_CREATE_REQUEST; - srs_error("dvr: api create dvr request requires json object. ret=%d", ret); - return ret; - } - - SrsJsonObject* obj = json->to_object(); - SrsJsonAny* prop = NULL; - if ((prop = obj->ensure_property_string("vhost")) == NULL) { - ret = ERROR_HTTP_DVR_CREATE_REQUEST; - srs_error("dvr: api create dvr request requires vhost. ret=%d", ret); - return ret; - } - - std::string vhost = prop->to_str(); - SrsDvrApiPlan* dvr = NULL; - for (int i = 0; i < (int)dvrs.size(); i++) { - SrsDvrApiPlan* plan = dvrs.at(i); - if (!vhost.empty() && plan->req->vhost != vhost) { - continue; - } - dvr = plan; - break; - } - - if (!dvr) { - ret = ERROR_HTTP_DVR_CREATE_REQUEST; - srs_error("dvr: api create dvr request vhost invalid. vhost=%s. ret=%d", vhost.c_str(), ret); - return ret; - } - - // update optional parameters for plan. - if ((prop = obj->ensure_property_string("path_tmpl")) != NULL) { - if ((ret = dvr->set_path_tmpl(prop->to_str())) != ERROR_SUCCESS) { - return ret; - } - } - if ((prop = obj->ensure_property_boolean("wait_keyframe")) != NULL) { - if ((ret = dvr->set_wait_keyframe(prop->to_boolean())) != ERROR_SUCCESS) { - return ret; - } - } - if ((prop = obj->ensure_property_string("callback")) != NULL) { - if ((ret = dvr->set_callback(prop->to_str())) != ERROR_SUCCESS) { - return ret; - } - } - - return dvr->start(); -} - -int SrsApiDvrPool::stop(string vhost) -{ - int ret = ERROR_SUCCESS; - - std::vector plans; - for (int i = 0; i < (int)dvrs.size(); i++) { - SrsDvrApiPlan* plan = dvrs.at(i); - if (!vhost.empty() && plan->req->vhost != vhost) { - continue; - } - plans.push_back(plan); - } - - for (int i = 0; i < (int)plans.size(); i++) { - SrsDvrApiPlan* plan = plans.at(i); - - if ((ret = plan->stop()) != ERROR_SUCCESS) { - return ret; - } - } - - return ret; -} - -int SrsApiDvrPool::rpc(SrsJsonAny* json) -{ - int ret = ERROR_SUCCESS; - - if (!json->is_object()) { - ret = ERROR_HTTP_DVR_REQUEST; - srs_error("dvr: rpc required object request. ret=%d", ret); - return ret; - } - - SrsJsonObject* obj = json->to_object(); - - SrsJsonAny* prop = NULL; - if ((prop = obj->ensure_property_string("vhost")) == NULL) { - ret = ERROR_HTTP_DVR_REQUEST; - srs_error("dvr: rpc required vhost request. ret=%d", ret); - return ret; - } - std::string vhost = prop->to_str(); - - std::vector plans; - for (int i = 0; i < (int)dvrs.size(); i++) { - SrsDvrApiPlan* plan = dvrs.at(i); - if (!vhost.empty() && plan->req->vhost != vhost) { - continue; - } - plans.push_back(plan); - } - - for (int i = 0; i < (int)plans.size(); i++) { - SrsDvrApiPlan* plan = plans.at(i); - - if ((ret = plan->rpc(obj)) != ERROR_SUCCESS) { - return ret; - } - } - - return ret; -} - -SrsDvr::SrsDvr(SrsSource* s) -{ - source = s; + source = NULL; plan = NULL; } @@ -1645,14 +1108,20 @@ SrsDvr::~SrsDvr() srs_freep(plan); } -int SrsDvr::initialize(SrsRequest* r) +int SrsDvr::initialize(SrsSource* s, SrsRequest* r) { int ret = ERROR_SUCCESS; + + source = s; srs_freep(plan); plan = SrsDvrPlan::create_plan(r->vhost); - if ((ret = plan->initialize(source, r)) != ERROR_SUCCESS) { + if ((ret = plan->initialize(r)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = source->on_dvr_request_sh()) != ERROR_SUCCESS) { return ret; } @@ -1675,6 +1144,7 @@ void SrsDvr::on_unpublish() plan->on_unpublish(); } +// TODO: FIXME: source should use shared message instead. int SrsDvr::on_meta_data(SrsOnMetaDataPacket* m) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp index c1619c767..a29a25081 100644 --- a/trunk/src/app/srs_app_dvr.hpp +++ b/trunk/src/app/srs_app_dvr.hpp @@ -58,7 +58,6 @@ class SrsThread; class SrsFlvSegment : public ISrsReloadHandler { private: - SrsSource* source; SrsRequest* req; SrsDvrPlan* plan; private: @@ -121,7 +120,7 @@ public: /** * initialize the segment. */ - virtual int initialize(SrsSource* s, SrsRequest* r); + virtual int initialize(SrsRequest* r); /** * whether segment is overflow. */ @@ -200,19 +199,6 @@ public: virtual int call(); virtual std::string to_string(); }; -class SrsDvrAsyncCallOnSegment : public ISrsDvrAsyncCall -{ -private: - std::string callback; - std::string path; - SrsRequest* req; -public: - SrsDvrAsyncCallOnSegment(SrsRequest* r, std::string c, std::string p); - virtual ~SrsDvrAsyncCallOnSegment(); -public: - virtual int call(); - virtual std::string to_string(); -}; /** * the async callback for dvr. @@ -247,7 +233,6 @@ public: public: SrsRequest* req; protected: - SrsSource* source; SrsFlvSegment* segment; SrsDvrAsyncCallThread* async; bool dvr_enabled; @@ -255,7 +240,7 @@ public: SrsDvrPlan(); virtual ~SrsDvrPlan(); public: - virtual int initialize(SrsSource* s, SrsRequest* r); + virtual int initialize(SrsRequest* r); virtual int on_publish() = 0; virtual void on_unpublish() = 0; /** @@ -272,7 +257,6 @@ public: virtual int on_video(SrsSharedPtrMessage* __video); protected: virtual int on_reap_segment(); - virtual int on_dvr_request_sh(); virtual int on_video_keyframe(); virtual int64_t filter_timestamp(int64_t timestamp); public: @@ -292,48 +276,6 @@ public: virtual void on_unpublish(); }; -/** -* api plan: reap flv by api. -*/ -class SrsDvrApiPlan : public SrsDvrPlan -{ -private: - // cache the metadata and sequence header, for new segment maybe opened. - SrsSharedPtrMessage* sh_audio; - SrsSharedPtrMessage* sh_video; - SrsSharedPtrMessage* metadata; -private: - std::string callback; - bool autostart; - bool started; -private: - // user action, reap_segment. - std::string action; - std::string path_template; -public: - SrsDvrApiPlan(); - virtual ~SrsDvrApiPlan(); -public: - virtual int initialize(SrsSource* s, SrsRequest* r); - virtual int on_publish(); - virtual void on_unpublish(); - virtual int on_meta_data(SrsSharedPtrMessage* __metadata); - virtual int on_audio(SrsSharedPtrMessage* __audio); - virtual int on_video(SrsSharedPtrMessage* __video); -public: - virtual int set_path_tmpl(std::string path_tmpl); - virtual int set_callback(std::string value); - virtual int set_wait_keyframe(bool wait_keyframe); - virtual int start(); - virtual int dumps(std::stringstream& ss); - virtual int stop(); - virtual int rpc(SrsJsonObject* obj); -protected: - virtual int on_reap_segment(); -private: - virtual int check_user_actions(SrsSharedPtrMessage* msg); -}; - /** * always append to flv file, never reap it. */ @@ -368,7 +310,7 @@ public: SrsDvrSegmentPlan(); virtual ~SrsDvrSegmentPlan(); public: - virtual int initialize(SrsSource* source, SrsRequest* req); + virtual int initialize(SrsRequest* req); virtual int on_publish(); virtual void on_unpublish(); virtual int on_meta_data(SrsSharedPtrMessage* __metadata); @@ -378,28 +320,6 @@ private: virtual int update_duration(SrsSharedPtrMessage* msg); }; -/** -* the api dvr pool. -*/ -class SrsApiDvrPool -{ -private: - std::vector dvrs; - static SrsApiDvrPool* _instance; -private: - SrsApiDvrPool(); -public: - static SrsApiDvrPool* instance(); - virtual ~SrsApiDvrPool(); -public: - virtual int add_dvr(SrsDvrApiPlan* dvr); -public: - virtual int dumps(std::string vhost, std::stringstream& ss); - virtual int create(SrsJsonAny* json); - virtual int stop(std::string vhost); - virtual int rpc(SrsJsonAny* json); -}; - /** * dvr(digital video recorder) to record RTMP stream to flv file. * TODO: FIXME: add utest for it. @@ -411,7 +331,7 @@ private: private: SrsDvrPlan* plan; public: - SrsDvr(SrsSource* s); + SrsDvr(); virtual ~SrsDvr(); public: /** @@ -419,7 +339,7 @@ public: * when system initialize(encoder publish at first time, or reload), * initialize the dvr will reinitialize the plan, the whole dvr framework. */ - virtual int initialize(SrsRequest* r); + virtual int initialize(SrsSource* s, SrsRequest* r); /** * publish stream event, * when encoder start to publish RTMP stream. diff --git a/trunk/src/app/srs_app_ffmpeg.cpp b/trunk/src/app/srs_app_ffmpeg.cpp index 473fbdfb5..16badcea7 100644 --- a/trunk/src/app/srs_app_ffmpeg.cpp +++ b/trunk/src/app/srs_app_ffmpeg.cpp @@ -432,8 +432,8 @@ int SrsFFMPEG::start() // memory leak in child process, it's ok. char** charpv_params = new char*[params.size() + 1]; for (int i = 0; i < (int)params.size(); i++) { - std::string p = params[i]; - charpv_params[i] = (char*)p.c_str(); + std::string& p = params[i]; + charpv_params[i] = (char*)p.data(); } // EOF: NULL charpv_params[params.size()] = NULL; diff --git a/trunk/src/app/srs_app_heartbeat.cpp b/trunk/src/app/srs_app_heartbeat.cpp index a8828c1d8..bc62853df 100644 --- a/trunk/src/app/srs_app_heartbeat.cpp +++ b/trunk/src/app/srs_app_heartbeat.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include SrsHttpHeartbeat::SrsHttpHeartbeat() { @@ -73,21 +74,31 @@ void SrsHttpHeartbeat::heartbeat() srs_api_dump_summaries(ss); } ss << __SRS_JOBJECT_END; - std::string data = ss.str(); - std::string res; - int status_code; + + std::string req = ss.str(); SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = http.initialize(uri.get_host(), uri.get_port())) != ERROR_SUCCESS) { + return; + } + + SrsHttpMessage* msg = NULL; + if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { srs_info("http post hartbeart uri failed. " "url=%s, request=%s, response=%s, ret=%d", - url.c_str(), data.c_str(), res.c_str(), ret); + url.c_str(), req.c_str(), res.c_str(), ret); + return; + } + SrsAutoFree(SrsHttpMessage, msg); + + std::string res; + if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { return; } srs_info("http hook hartbeart success. " "url=%s, request=%s, status_code=%d, response=%s, ret=%d", - url.c_str(), data.c_str(), status_code, res.c_str(), ret); + url.c_str(), req.c_str(), status_code, res.c_str(), ret); return; } diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 7c7e9a764..8cf8dc74c 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -163,10 +163,10 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) return; } -SrsHlsMuxer::SrsHlsMuxer(ISrsHlsHandler* h) +SrsHlsMuxer::SrsHlsMuxer() { req = NULL; - handler = h; + handler = NULL; hls_fragment = hls_window = 0; target_duration = 0; _sequence_no = 0; @@ -189,6 +189,15 @@ SrsHlsMuxer::~SrsHlsMuxer() srs_freep(req); } +int SrsHlsMuxer::initialize(ISrsHlsHandler* h) +{ + int ret = ERROR_SUCCESS; + + handler = h; + + return ret; +} + int SrsHlsMuxer::sequence_no() { return _sequence_no; @@ -811,10 +820,10 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme return ret; } -SrsHls::SrsHls(SrsSource* s, ISrsHlsHandler* h) +SrsHls::SrsHls() { - source = s; - handler = h; + source = NULL; + handler = NULL; hls_enabled = false; @@ -822,7 +831,7 @@ SrsHls::SrsHls(SrsSource* s, ISrsHlsHandler* h) sample = new SrsCodecSample(); jitter = new SrsRtmpJitter(); - muxer = new SrsHlsMuxer(h); + muxer = new SrsHlsMuxer(); hls_cache = new SrsHlsCache(); pprint = SrsPithyPrint::create_hls(); @@ -841,6 +850,20 @@ SrsHls::~SrsHls() srs_freep(pprint); } +int SrsHls::initialize(SrsSource* s, ISrsHlsHandler* h) +{ + int ret = ERROR_SUCCESS; + + source = s; + handler = h; + + if ((ret = muxer->initialize(h)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + int SrsHls::on_publish(SrsRequest* req) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 11a81deb1..62660b3a7 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -195,11 +195,15 @@ private: */ SrsCodecAudio acodec; public: - SrsHlsMuxer(ISrsHlsHandler* h); + SrsHlsMuxer(); virtual ~SrsHlsMuxer(); public: virtual int sequence_no(); public: + /** + * initialize the hls muxer. + */ + virtual int initialize(ISrsHlsHandler* h); /** * when publish, update the config for muxer. */ @@ -325,9 +329,13 @@ private: */ int64_t stream_dts; public: - SrsHls(SrsSource* s, ISrsHlsHandler* h); + SrsHls(); virtual ~SrsHls(); public: + /** + * initialize the hls by handler and source. + */ + virtual int initialize(SrsSource* s, ISrsHlsHandler* h); /** * publish stream event, continue to write the m3u8, * for the muxer object not destroyed. diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 30ff9908a..ae4e09bd5 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -39,11 +39,10 @@ using namespace std; #include #include #include +#include #define SRS_DEFAULT_HTTP_PORT 80 -#define SRS_HTTP_HEADER_BUFFER 1024 - // for http parser macros #define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS #define SRS_CONSTS_HTTP_GET HTTP_GET @@ -53,7 +52,7 @@ using namespace std; #define SRS_HTTP_DEFAULT_PAGE "index.html" -int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data) +int srs_go_http_response_json(ISrsHttpResponseWriter* w, string data) { w->header()->set_content_length(data.length()); w->header()->set_content_type("application/json"); @@ -147,7 +146,7 @@ string srs_go_http_detect(char* data, int size) // Error replies to the request with the specified error message and HTTP code. // The error message should be plain text. -int srs_go_http_error(ISrsGoHttpResponseWriter* w, int code, string error) +int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error) { int ret = ERROR_SUCCESS; @@ -159,20 +158,20 @@ int srs_go_http_error(ISrsGoHttpResponseWriter* w, int code, string error) return ret; } -SrsGoHttpHeader::SrsGoHttpHeader() +SrsHttpHeader::SrsHttpHeader() { } -SrsGoHttpHeader::~SrsGoHttpHeader() +SrsHttpHeader::~SrsHttpHeader() { } -void SrsGoHttpHeader::set(string key, string value) +void SrsHttpHeader::set(string key, string value) { headers[key] = value; } -string SrsGoHttpHeader::get(string key) +string SrsHttpHeader::get(string key) { std::string v; @@ -183,7 +182,7 @@ string SrsGoHttpHeader::get(string key) return v; } -int64_t SrsGoHttpHeader::content_length() +int64_t SrsHttpHeader::content_length() { std::string cl = get("Content-Length"); @@ -194,24 +193,24 @@ int64_t SrsGoHttpHeader::content_length() return (int64_t)::atof(cl.c_str()); } -void SrsGoHttpHeader::set_content_length(int64_t size) +void SrsHttpHeader::set_content_length(int64_t size) { char buf[64]; snprintf(buf, sizeof(buf), "%"PRId64, size); set("Content-Length", buf); } -string SrsGoHttpHeader::content_type() +string SrsHttpHeader::content_type() { return get("Content-Type"); } -void SrsGoHttpHeader::set_content_type(string ct) +void SrsHttpHeader::set_content_type(string ct) { set("Content-Type", ct); } -void SrsGoHttpHeader::write(stringstream& ss) +void SrsHttpHeader::write(stringstream& ss) { std::map::iterator it; for (it = headers.begin(); it != headers.end(); ++it) { @@ -219,64 +218,72 @@ void SrsGoHttpHeader::write(stringstream& ss) } } -ISrsGoHttpResponseWriter::ISrsGoHttpResponseWriter() +ISrsHttpResponseWriter::ISrsHttpResponseWriter() { } -ISrsGoHttpResponseWriter::~ISrsGoHttpResponseWriter() +ISrsHttpResponseWriter::~ISrsHttpResponseWriter() { } -ISrsGoHttpHandler::ISrsGoHttpHandler() +ISrsHttpResponseReader::ISrsHttpResponseReader() +{ +} + +ISrsHttpResponseReader::~ISrsHttpResponseReader() +{ +} + +ISrsHttpHandler::ISrsHttpHandler() { entry = NULL; } -ISrsGoHttpHandler::~ISrsGoHttpHandler() +ISrsHttpHandler::~ISrsHttpHandler() { } -SrsGoHttpRedirectHandler::SrsGoHttpRedirectHandler(string u, int c) +SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c) { url = u; code = c; } -SrsGoHttpRedirectHandler::~SrsGoHttpRedirectHandler() +SrsHttpRedirectHandler::~SrsHttpRedirectHandler() { } -int SrsGoHttpRedirectHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; // TODO: FIXME: implements it. return ret; } -SrsGoHttpNotFoundHandler::SrsGoHttpNotFoundHandler() +SrsHttpNotFoundHandler::SrsHttpNotFoundHandler() { } -SrsGoHttpNotFoundHandler::~SrsGoHttpNotFoundHandler() +SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler() { } -int SrsGoHttpNotFoundHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { return srs_go_http_error(w, SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); } -SrsGoHttpFileServer::SrsGoHttpFileServer(string root_dir) +SrsHttpFileServer::SrsHttpFileServer(string root_dir) { dir = root_dir; } -SrsGoHttpFileServer::~SrsGoHttpFileServer() +SrsHttpFileServer::~SrsHttpFileServer() { } -int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { string upath = r->path(); @@ -300,7 +307,7 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* if (!srs_path_exists(fullpath)) { srs_warn("http miss file=%s, pattern=%s, upath=%s", fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); - return SrsGoHttpNotFoundHandler().serve_http(w, r); + return SrsHttpNotFoundHandler().serve_http(w, r); } srs_trace("http match file=%s, pattern=%s, upath=%s", fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); @@ -317,7 +324,7 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return serve_file(w, r, fullpath); } -int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) +int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) { int ret = ERROR_SUCCESS; @@ -391,7 +398,7 @@ int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return w->final_request(); } -int SrsGoHttpFileServer::serve_flv_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) +int SrsHttpFileServer::serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) { std::string start = r->query_get("start"); if (start.empty()) { @@ -406,7 +413,7 @@ int SrsGoHttpFileServer::serve_flv_file(ISrsGoHttpResponseWriter* w, SrsHttpMess return serve_flv_stream(w, r, fullpath, offset); } -int SrsGoHttpFileServer::serve_mp4_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) +int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) { // for flash to request mp4 range in query string. // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd @@ -443,17 +450,17 @@ int SrsGoHttpFileServer::serve_mp4_file(ISrsGoHttpResponseWriter* w, SrsHttpMess return serve_mp4_stream(w, r, fullpath, start, end); } -int SrsGoHttpFileServer::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) +int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) { return serve_file(w, r, fullpath); } -int SrsGoHttpFileServer::serve_mp4_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) +int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) { return serve_file(w, r, fullpath); } -int SrsGoHttpFileServer::copy(ISrsGoHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size) +int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size) { int ret = ERROR_SUCCESS; @@ -476,27 +483,27 @@ int SrsGoHttpFileServer::copy(ISrsGoHttpResponseWriter* w, SrsFileReader* fs, Sr return ret; } -SrsGoHttpMuxEntry::SrsGoHttpMuxEntry() +SrsHttpMuxEntry::SrsHttpMuxEntry() { enabled = true; explicit_match = false; handler = NULL; } -SrsGoHttpMuxEntry::~SrsGoHttpMuxEntry() +SrsHttpMuxEntry::~SrsHttpMuxEntry() { srs_freep(handler); } -SrsGoHttpServeMux::SrsGoHttpServeMux() +SrsHttpServeMux::SrsHttpServeMux() { } -SrsGoHttpServeMux::~SrsGoHttpServeMux() +SrsHttpServeMux::~SrsHttpServeMux() { - std::map::iterator it; + std::map::iterator it; for (it = entries.begin(); it != entries.end(); ++it) { - SrsGoHttpMuxEntry* entry = it->second; + SrsHttpMuxEntry* entry = it->second; srs_freep(entry); } entries.clear(); @@ -504,14 +511,14 @@ SrsGoHttpServeMux::~SrsGoHttpServeMux() vhosts.clear(); } -int SrsGoHttpServeMux::initialize() +int SrsHttpServeMux::initialize() { int ret = ERROR_SUCCESS; // TODO: FIXME: implements it. return ret; } -int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) +int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler) { int ret = ERROR_SUCCESS; @@ -524,7 +531,7 @@ int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) } if (entries.find(pattern) != entries.end()) { - SrsGoHttpMuxEntry* exists = entries[pattern]; + SrsHttpMuxEntry* exists = entries[pattern]; if (exists->explicit_match) { ret = ERROR_HTTP_PATTERN_DUPLICATED; srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret); @@ -541,14 +548,14 @@ int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) } if (true) { - SrsGoHttpMuxEntry* entry = new SrsGoHttpMuxEntry(); + SrsHttpMuxEntry* entry = new SrsHttpMuxEntry(); entry->explicit_match = true; entry->handler = handler; entry->pattern = pattern; entry->handler->entry = entry; if (entries.find(pattern) != entries.end()) { - SrsGoHttpMuxEntry* exists = entries[pattern]; + SrsHttpMuxEntry* exists = entries[pattern]; srs_freep(exists); } entries[pattern] = entry; @@ -559,11 +566,11 @@ int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) // It can be overridden by an explicit registration. if (pattern != "/" && !pattern.empty() && pattern.at(pattern.length() - 1) == '/') { std::string rpattern = pattern.substr(0, pattern.length() - 1); - SrsGoHttpMuxEntry* entry = NULL; + SrsHttpMuxEntry* entry = NULL; // free the exists not explicit entry if (entries.find(rpattern) != entries.end()) { - SrsGoHttpMuxEntry* exists = entries[rpattern]; + SrsHttpMuxEntry* exists = entries[rpattern]; if (!exists->explicit_match) { entry = exists; } @@ -573,9 +580,9 @@ int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) if (!entry || entry->explicit_match) { srs_freep(entry); - entry = new SrsGoHttpMuxEntry(); + entry = new SrsHttpMuxEntry(); entry->explicit_match = false; - entry->handler = new SrsGoHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently); + entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently); entry->pattern = pattern; entry->handler->entry = entry; @@ -586,11 +593,11 @@ int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) return ret; } -int SrsGoHttpServeMux::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; - ISrsGoHttpHandler* h = NULL; + ISrsHttpHandler* h = NULL; if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) { srs_error("find handler failed. ret=%d", ret); return ret; @@ -607,7 +614,7 @@ int SrsGoHttpServeMux::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r return ret; } -int SrsGoHttpServeMux::find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph) +int SrsHttpServeMux::find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph) { int ret = ERROR_SUCCESS; @@ -624,13 +631,13 @@ int SrsGoHttpServeMux::find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph) } if (*ph == NULL) { - *ph = new SrsGoHttpNotFoundHandler(); + *ph = new SrsHttpNotFoundHandler(); } return ret; } -int SrsGoHttpServeMux::match(SrsHttpMessage* r, ISrsGoHttpHandler** ph) +int SrsHttpServeMux::match(SrsHttpMessage* r, ISrsHttpHandler** ph) { int ret = ERROR_SUCCESS; @@ -642,12 +649,12 @@ int SrsGoHttpServeMux::match(SrsHttpMessage* r, ISrsGoHttpHandler** ph) } int nb_matched = 0; - ISrsGoHttpHandler* h = NULL; + ISrsHttpHandler* h = NULL; - std::map::iterator it; + std::map::iterator it; for (it = entries.begin(); it != entries.end(); ++it) { std::string pattern = it->first; - SrsGoHttpMuxEntry* entry = it->second; + SrsHttpMuxEntry* entry = it->second; if (!entry->enabled) { continue; @@ -668,7 +675,7 @@ int SrsGoHttpServeMux::match(SrsHttpMessage* r, ISrsGoHttpHandler** ph) return ret; } -bool SrsGoHttpServeMux::path_match(string pattern, string path) +bool SrsHttpServeMux::path_match(string pattern, string path) { if (pattern.empty()) { return false; @@ -692,10 +699,10 @@ bool SrsGoHttpServeMux::path_match(string pattern, string path) return false; } -SrsGoHttpResponseWriter::SrsGoHttpResponseWriter(SrsStSocket* io) +SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io) { skt = io; - hdr = new SrsGoHttpHeader(); + hdr = new SrsHttpHeader(); header_wrote = false; status = SRS_CONSTS_HTTP_OK; content_length = -1; @@ -703,12 +710,12 @@ SrsGoHttpResponseWriter::SrsGoHttpResponseWriter(SrsStSocket* io) header_sent = false; } -SrsGoHttpResponseWriter::~SrsGoHttpResponseWriter() +SrsHttpResponseWriter::~SrsHttpResponseWriter() { srs_freep(hdr); } -int SrsGoHttpResponseWriter::final_request() +int SrsHttpResponseWriter::final_request() { // complete the chunked encoding. if (content_length == -1) { @@ -722,12 +729,12 @@ int SrsGoHttpResponseWriter::final_request() return write(NULL, 0); } -SrsGoHttpHeader* SrsGoHttpResponseWriter::header() +SrsHttpHeader* SrsHttpResponseWriter::header() { return hdr; } -int SrsGoHttpResponseWriter::write(char* data, int size) +int SrsHttpResponseWriter::write(char* data, int size) { int ret = ERROR_SUCCESS; @@ -774,7 +781,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size) return ret; } -void SrsGoHttpResponseWriter::write_header(int code) +void SrsHttpResponseWriter::write_header(int code) { if (header_wrote) { srs_warn("http: multiple write_header calls, code=%d", code); @@ -788,7 +795,7 @@ void SrsGoHttpResponseWriter::write_header(int code) content_length = hdr->content_length(); } -int SrsGoHttpResponseWriter::send_header(char* data, int size) +int SrsHttpResponseWriter::send_header(char* data, int size) { int ret = ERROR_SUCCESS; @@ -833,11 +840,166 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size) return skt->write((void*)buf.c_str(), buf.length(), NULL); } -SrsHttpMessage::SrsHttpMessage() +SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io) { - _body = new SrsSimpleBuffer(); - _state = SrsHttpParseStateInit; + skt = io; + owner = msg; + is_eof = false; + nb_read = 0; + buffer = NULL; +} + +SrsHttpResponseReader::~SrsHttpResponseReader() +{ +} + +int SrsHttpResponseReader::initialize(SrsFastBuffer* body) +{ + int ret = ERROR_SUCCESS; + + buffer = body; + + return ret; +} + +bool SrsHttpResponseReader::eof() +{ + return is_eof; +} + +int SrsHttpResponseReader::read(std::string& data) +{ + int ret = ERROR_SUCCESS; + + if (is_eof) { + ret = ERROR_HTTP_RESPONSE_EOF; + srs_error("http: response EOF. ret=%d", ret); + return ret; + } + + // chunked encoding. + if (owner->is_chunked()) { + return read_chunked(data); + } + + // read by specified content-length + int max = (int)owner->content_length() - nb_read; + if (max <= 0) { + is_eof = true; + return ret; + } + return read_specified(max, data); +} + +int SrsHttpResponseReader::read_chunked(std::string& data) +{ + int ret = ERROR_SUCCESS; + + // parse the chunk length first. + char* at = NULL; + int length = 0; + while (!at) { + // find the CRLF of chunk header end. + char* start = buffer->bytes(); + char* end = start + buffer->size(); + for (char* p = start; p < end - 1; p++) { + if (p[0] == __SRS_HTTP_CR && p[1] == __SRS_HTTP_LF) { + // invalid chunk, ignore. + if (p == start) { + ret = ERROR_HTTP_INVALID_CHUNK_HEADER; + srs_error("chunk header start with CRLF. ret=%d", ret); + return ret; + } + length = p - start + 2; + at = buffer->read_slice(length); + break; + } + } + + // got at, ok. + if (at) { + break; + } + + // when empty, only grow 1bytes, but the buffer will cache more. + if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) { + if (!srs_is_client_gracefully_close(ret)) { + srs_error("read body from server failed. ret=%d", ret); + } + return ret; + } + } + srs_assert(length >= 3); + + // it's ok to set the pos and pos+1 to NULL. + at[length - 1] = NULL; + at[length - 2] = NULL; + + // size is the bytes size, excludes the chunk header and end CRLF. + int ilength = ::strtol(at, NULL, 16); + if (ilength < 0) { + ret = ERROR_HTTP_INVALID_CHUNK_HEADER; + srs_error("chunk header negative, length=%d. ret=%d", ilength, ret); + return ret; + } + + // when empty, only grow 1bytes, but the buffer will cache more. + if ((ret = buffer->grow(skt, ilength + 2)) != ERROR_SUCCESS) { + if (!srs_is_client_gracefully_close(ret)) { + srs_error("read body from server failed. ret=%d", ret); + } + return ret; + } + srs_info("http: read %d chunk", ilength); + + // read payload when length specifies some payload. + if (ilength <= 0) { + is_eof = true; + } else { + srs_assert(ilength); + data.append(buffer->read_slice(ilength), ilength); + nb_read += ilength; + } + + // the CRLF of chunk payload end. + buffer->read_slice(2); + + return ret; +} + +int SrsHttpResponseReader::read_specified(int max, std::string& data) +{ + int ret = ERROR_SUCCESS; + + if (buffer->size() <= 0) { + // when empty, only grow 1bytes, but the buffer will cache more. + if ((ret = buffer->grow(skt, 1)) != ERROR_SUCCESS) { + if (!srs_is_client_gracefully_close(ret)) { + srs_error("read body from server failed. ret=%d", ret); + } + return ret; + } + } + + int nb_bytes = srs_min(max, buffer->size()); + + srs_assert(nb_bytes); + data.append(buffer->read_slice(nb_bytes), nb_bytes); + nb_read += nb_bytes; + + // when read completed, eof. + if (nb_read >= (int)owner->content_length()) { + is_eof = true; + } + + return ret; +} + +SrsHttpMessage::SrsHttpMessage(SrsStSocket* io) +{ + chunked = false; _uri = new SrsHttpUri(); + _body = new SrsHttpResponseReader(this, io); _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE]; } @@ -848,10 +1010,24 @@ SrsHttpMessage::~SrsHttpMessage() srs_freep(_http_ts_send_buffer); } -int SrsHttpMessage::initialize() +int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector& headers) { int ret = ERROR_SUCCESS; + _url = url; + _header = *header; + _headers = headers; + + // whether chunked. + std::string transfer_encoding = get_request_header("Transfer-Encoding"); + chunked = (transfer_encoding == "chunked"); + + // set the buffer. + if ((ret = _body->initialize(body)) != ERROR_SUCCESS) { + return ret; + } + + // parse uri from url. std::string host = get_request_header("Host"); // donot parse the empty host for uri, @@ -898,18 +1074,6 @@ char* SrsHttpMessage::http_ts_send_buffer() return _http_ts_send_buffer; } -void SrsHttpMessage::reset() -{ - _state = SrsHttpParseStateInit; - _body->erase(_body->length()); - _url = ""; -} - -bool SrsHttpMessage::is_complete() -{ - return _state == SrsHttpParseStateComplete; -} - u_int8_t SrsHttpMessage::method() { return (u_int8_t)_header.method; @@ -966,6 +1130,11 @@ bool SrsHttpMessage::is_http_options() return _header.method == SRS_CONSTS_HTTP_OPTIONS; } +bool SrsHttpMessage::is_chunked() +{ + return chunked; +} + string SrsHttpMessage::uri() { std::string uri = _uri->get_schema(); @@ -993,25 +1162,23 @@ string SrsHttpMessage::path() return _uri->get_path(); } -string SrsHttpMessage::body() +int SrsHttpMessage::body_read_all(string& body) { - std::string b; + int ret = ERROR_SUCCESS; - if (_body && _body->length() > 0) { - b.append(_body->bytes(), _body->length()); + // whatever, read util EOF. + while (!_body->eof()) { + if ((ret = _body->read(body)) != ERROR_SUCCESS) { + return ret; + } } - return b; + return ret; } -char* SrsHttpMessage::body_raw() +ISrsHttpResponseReader* SrsHttpMessage::body_reader() { - return _body? _body->bytes() : NULL; -} - -int64_t SrsHttpMessage::body_size() -{ - return (int64_t)_body->length(); + return _body; } int64_t SrsHttpMessage::content_length() @@ -1019,26 +1186,6 @@ int64_t SrsHttpMessage::content_length() return _header.content_length; } -void SrsHttpMessage::set_url(string url) -{ - _url = url; -} - -void SrsHttpMessage::set_state(SrsHttpParseState state) -{ - _state = state; -} - -void SrsHttpMessage::set_header(http_parser* header) -{ - memcpy(&_header, header, sizeof(http_parser)); -} - -void SrsHttpMessage::append_body(const char* body, int length) -{ - _body->append(body, length); -} - string SrsHttpMessage::query_get(string key) { std::string v; @@ -1052,33 +1199,28 @@ string SrsHttpMessage::query_get(string key) int SrsHttpMessage::request_header_count() { - return (int)headers.size(); + return (int)_headers.size(); } string SrsHttpMessage::request_header_key_at(int index) { srs_assert(index < request_header_count()); - SrsHttpHeaderField item = headers[index]; + SrsHttpHeaderField item = _headers[index]; return item.first; } string SrsHttpMessage::request_header_value_at(int index) { srs_assert(index < request_header_count()); - SrsHttpHeaderField item = headers[index]; + SrsHttpHeaderField item = _headers[index]; return item.second; } -void SrsHttpMessage::set_request_header(string key, string value) -{ - headers.push_back(std::make_pair(key, value)); -} - string SrsHttpMessage::get_request_header(string name) { std::vector::iterator it; - for (it = headers.begin(); it != headers.end(); ++it) { + for (it = _headers.begin(); it != _headers.end(); ++it) { SrsHttpHeaderField& elem = *it; std::string key = elem.first; std::string value = elem.second; @@ -1092,12 +1234,12 @@ string SrsHttpMessage::get_request_header(string name) SrsHttpParser::SrsHttpParser() { - msg = NULL; + buffer = new SrsFastBuffer(); } SrsHttpParser::~SrsHttpParser() { - srs_freep(msg); + srs_freep(buffer); } int SrsHttpParser::initialize(enum http_parser_type type) @@ -1125,28 +1267,30 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg) *ppmsg = NULL; int ret = ERROR_SUCCESS; - - // the msg must be always NULL - srs_assert(msg == NULL); - msg = new SrsHttpMessage(); // reset request data. filed_name = ""; - - // reset response header. - msg->reset(); + field_value = ""; + expect_filed_name = true; + state = SrsHttpParseStateInit; + header = http_parser(); + url = ""; + headers.clear(); + body_parsed = 0; // do parse if ((ret = parse_message_imp(skt)) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret)) { srs_error("parse http msg failed. ret=%d", ret); } - srs_freep(msg); return ret; } + // create msg + SrsHttpMessage* msg = new SrsHttpMessage(skt); + // initalize http msg, parse url. - if ((ret = msg->initialize()) != ERROR_SUCCESS) { + if ((ret = msg->update(url, &header, buffer, headers)) != ERROR_SUCCESS) { srs_error("initialize http msg failed. ret=%d", ret); srs_freep(msg); return ret; @@ -1154,7 +1298,6 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg) // parse ok, return the msg. *ppmsg = msg; - msg = NULL; return ret; } @@ -1163,42 +1306,52 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt) { int ret = ERROR_SUCCESS; - // the msg should never be NULL - srs_assert(msg != NULL); - - // parser header. - char buf[SRS_HTTP_HEADER_BUFFER]; - for (;;) { - ssize_t nread; - if ((ret = skt->read(buf, (size_t)sizeof(buf), &nread)) != ERROR_SUCCESS) { - if (!srs_is_client_gracefully_close(ret)) { - srs_error("read body from server failed. ret=%d", ret); - } - return ret; + while (true) { + ssize_t nparsed = 0; + + // when buffer not empty, parse it. + if (buffer->size() > 0) { + nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size()); + srs_info("buffer=%d, nparsed=%d, body=%d", buffer->size(), (int)nparsed, body_parsed); } - ssize_t nparsed = http_parser_execute(&parser, &settings, buf, nread); - srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed); + // consume the parsed bytes. + if (nparsed && nparsed - body_parsed > 0) { + buffer->read_slice(nparsed - body_parsed); + } - // check header size. - if (msg->is_complete()) { - return ret; + // ok atleast header completed, + // never wait for body completed, for maybe chunked. + if (state == SrsHttpParseStateHeaderComplete || state == SrsHttpParseStateMessageComplete) { + break; } - if (nparsed != nread) { - ret = ERROR_HTTP_PARSE_HEADER; - srs_error("parse response error, parsed(%d)!=read(%d), ret=%d", (int)nparsed, (int)nread, ret); - return ret; + // when nothing parsed, read more to parse. + if (nparsed == 0) { + // when requires more, only grow 1bytes, but the buffer will cache more. + if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) { + if (!srs_is_client_gracefully_close(ret)) { + srs_error("read body from server failed. ret=%d", ret); + } + return ret; + } } } + // parse last header. + if (!filed_name.empty() && !field_value.empty()) { + headers.push_back(std::make_pair(filed_name, field_value)); + } + return ret; } int SrsHttpParser::on_message_begin(http_parser* parser) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; - obj->msg->set_state(SrsHttpParseStateStart); + srs_assert(obj); + + obj->state = SrsHttpParseStateStart; srs_info("***MESSAGE BEGIN***"); @@ -1208,7 +1361,11 @@ int SrsHttpParser::on_message_begin(http_parser* parser) int SrsHttpParser::on_headers_complete(http_parser* parser) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; - obj->msg->set_header(parser); + srs_assert(obj); + + obj->header = *parser; + // save the parser when header parse completed. + obj->state = SrsHttpParseStateHeaderComplete; srs_info("***HEADERS COMPLETE***"); @@ -1219,8 +1376,10 @@ int SrsHttpParser::on_headers_complete(http_parser* parser) int SrsHttpParser::on_message_complete(http_parser* parser) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; - // save the parser when header parse completed. - obj->msg->set_state(SrsHttpParseStateComplete); + srs_assert(obj); + + // save the parser when body parse completed. + obj->state = SrsHttpParseStateMessageComplete; srs_info("***MESSAGE COMPLETE***\n"); @@ -1230,13 +1389,10 @@ int SrsHttpParser::on_message_complete(http_parser* parser) int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; + srs_assert(obj); if (length > 0) { - std::string url; - - url.append(at, (int)length); - - obj->msg->set_url(url); + obj->url.append(at, (int)length); } srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at); @@ -1247,45 +1403,46 @@ int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length) int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t length) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; + srs_assert(obj); + + // field value=>name, reap the field. + if (!obj->expect_filed_name) { + obj->headers.push_back(std::make_pair(obj->filed_name, obj->field_value)); + + // reset the field name when parsed. + obj->filed_name = ""; + obj->field_value = ""; + } + obj->expect_filed_name = true; if (length > 0) { - srs_assert(obj); obj->filed_name.append(at, (int)length); } - srs_info("Header field: %.*s", (int)length, at); + srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at); return 0; } int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t length) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; + srs_assert(obj); if (length > 0) { - srs_assert(obj); - srs_assert(obj->msg); - - std::string field_value; - field_value.append(at, (int)length); - - obj->msg->set_request_header(obj->filed_name, field_value); - obj->filed_name = ""; + obj->field_value.append(at, (int)length); } + obj->expect_filed_name = false; - srs_info("Header value: %.*s", (int)length, at); + srs_info("Header value(%d bytes): %.*s", (int)length, (int)length, at); return 0; } int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length) { SrsHttpParser* obj = (SrsHttpParser*)parser->data; + srs_assert(obj); - if (length > 0) { - srs_assert(obj); - srs_assert(obj->msg); - - obj->msg->append_body(at, (int)length); - } + obj->body_parsed += length; srs_info("Body: %.*s", (int)length, at); diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index b0745fd8e..786cfdbf0 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -47,8 +47,9 @@ class SrsHttpUri; class SrsHttpMessage; class SrsFileReader; class SrsSimpleBuffer; -class SrsGoHttpMuxEntry; -class ISrsGoHttpResponseWriter; +class SrsHttpMuxEntry; +class ISrsHttpResponseWriter; +class SrsFastBuffer; // http specification // CR = @@ -70,23 +71,24 @@ class ISrsGoHttpResponseWriter; #define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 // helper function: response in json format. -extern int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, std::string data); +extern int srs_go_http_response_json(ISrsHttpResponseWriter* w, std::string data); // state of message enum SrsHttpParseState { SrsHttpParseStateInit = 0, SrsHttpParseStateStart, - SrsHttpParseStateComplete + SrsHttpParseStateHeaderComplete, + SrsHttpParseStateMessageComplete }; // A Header represents the key-value pairs in an HTTP header. -class SrsGoHttpHeader +class SrsHttpHeader { private: std::map headers; public: - SrsGoHttpHeader(); - virtual ~SrsGoHttpHeader(); + SrsHttpHeader(); + virtual ~SrsHttpHeader(); public: // Add adds the key, value pair to the header. // It appends to any existing values associated with key. @@ -124,7 +126,7 @@ public: // A ResponseWriter interface is used by an HTTP handler to // construct an HTTP response. // Usage 1, response with specified length content: -// ISrsGoHttpResponseWriter* w; // create or get response. +// ISrsHttpResponseWriter* w; // create or get response. // std::string msg = "Hello, HTTP!"; // w->header()->set_content_type("text/plain; charset=utf-8"); // w->header()->set_content_length(msg.length()); @@ -132,12 +134,12 @@ public: // w->write((char*)msg.data(), (int)msg.length()); // w->final_request(); // optional flush. // Usage 2, response with HTTP code only, zero content length. -// ISrsGoHttpResponseWriter* w; // create or get response. +// ISrsHttpResponseWriter* w; // create or get response. // w->header()->set_content_length(0); // w->write_header(SRS_CONSTS_HTTP_OK); // w->final_request(); // Usage 3, response in chunked encoding. -// ISrsGoHttpResponseWriter* w; // create or get response. +// ISrsHttpResponseWriter* w; // create or get response. // std::string msg = "Hello, HTTP!"; // w->header()->set_content_type("application/octet-stream"); // w->write_header(SRS_CONSTS_HTTP_OK); @@ -146,20 +148,22 @@ public: // w->write((char*)msg.data(), (int)msg.length()); // w->write((char*)msg.data(), (int)msg.length()); // w->final_request(); // required to end the chunked and flush. -class ISrsGoHttpResponseWriter +class ISrsHttpResponseWriter { public: - ISrsGoHttpResponseWriter(); - virtual ~ISrsGoHttpResponseWriter(); + ISrsHttpResponseWriter(); + virtual ~ISrsHttpResponseWriter(); public: // when chunked mode, // final the request to complete the chunked encoding. + // for no-chunked mode, + // final to send request, for example, content-length is 0. virtual int final_request() = 0; // Header returns the header map that will be sent by WriteHeader. // Changing the header after a call to WriteHeader (or Write) has // no effect. - virtual SrsGoHttpHeader* header() = 0; + virtual SrsHttpHeader* header() = 0; // Write writes the data to the connection as part of an HTTP reply. // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) @@ -178,6 +182,26 @@ public: virtual void write_header(int code) = 0; }; +/** +* the reader interface for http response. +*/ +class ISrsHttpResponseReader +{ +public: + ISrsHttpResponseReader(); + virtual ~ISrsHttpResponseReader(); +public: + /** + * whether response read EOF. + */ + virtual bool eof() = 0; + /** + * read from the response body. + * @remark when eof(), return error. + */ + virtual int read(std::string& data) = 0; +}; + // Objects implementing the Handler interface can be // registered to serve a particular path or subtree // in the HTTP server. @@ -186,38 +210,38 @@ public: // and then return. Returning signals that the request is finished // and that the HTTP server can move on to the next request on // the connection. -class ISrsGoHttpHandler +class ISrsHttpHandler { public: - SrsGoHttpMuxEntry* entry; + SrsHttpMuxEntry* entry; public: - ISrsGoHttpHandler(); - virtual ~ISrsGoHttpHandler(); + ISrsHttpHandler(); + virtual ~ISrsHttpHandler(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) = 0; + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) = 0; }; // Redirect to a fixed URL -class SrsGoHttpRedirectHandler : public ISrsGoHttpHandler +class SrsHttpRedirectHandler : public ISrsHttpHandler { private: std::string url; int code; public: - SrsGoHttpRedirectHandler(std::string u, int c); - virtual ~SrsGoHttpRedirectHandler(); + SrsHttpRedirectHandler(std::string u, int c); + virtual ~SrsHttpRedirectHandler(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; // NotFound replies to the request with an HTTP 404 not found error. -class SrsGoHttpNotFoundHandler : public ISrsGoHttpHandler +class SrsHttpNotFoundHandler : public ISrsHttpHandler { public: - SrsGoHttpNotFoundHandler(); - virtual ~SrsGoHttpNotFoundHandler(); + SrsHttpNotFoundHandler(); + virtual ~SrsHttpNotFoundHandler(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; // FileServer returns a handler that serves HTTP requests @@ -226,54 +250,54 @@ public: // To use the operating system's file system implementation, // use http.Dir: // -// http.Handle("/", SrsGoHttpFileServer("/tmp")) -// http.Handle("/", SrsGoHttpFileServer("static-dir")) -class SrsGoHttpFileServer : public ISrsGoHttpHandler +// http.Handle("/", SrsHttpFileServer("/tmp")) +// http.Handle("/", SrsHttpFileServer("static-dir")) +class SrsHttpFileServer : public ISrsHttpHandler { protected: std::string dir; public: - SrsGoHttpFileServer(std::string root_dir); - virtual ~SrsGoHttpFileServer(); + SrsHttpFileServer(std::string root_dir); + virtual ~SrsHttpFileServer(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); private: /** * serve the file by specified path */ - virtual int serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); - virtual int serve_flv_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); - virtual int serve_mp4_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); + virtual int serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); + virtual int serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); + virtual int serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); protected: /** * when access flv file with x.flv?start=xxx */ - virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); /** * when access mp4 file with x.mp4?range=start-end * @param start the start offset in bytes. * @param end the end offset in bytes. -1 to end of file. * @remark response data in [start, end]. */ - virtual int serve_mp4_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); protected: /** * copy the fs to response writer in size bytes. */ - virtual int copy(ISrsGoHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size); + virtual int copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size); }; // the mux entry for server mux. -class SrsGoHttpMuxEntry +class SrsHttpMuxEntry { public: bool explicit_match; - ISrsGoHttpHandler* handler; + ISrsHttpHandler* handler; std::string pattern; bool enabled; public: - SrsGoHttpMuxEntry(); - virtual ~SrsGoHttpMuxEntry(); + SrsHttpMuxEntry(); + virtual ~SrsHttpMuxEntry(); }; // ServeMux is an HTTP request multiplexer. @@ -303,16 +327,16 @@ public: // ServeMux also takes care of sanitizing the URL request path, // redirecting any request containing . or .. elements to an // equivalent .- and ..-free URL. -class SrsGoHttpServeMux +class SrsHttpServeMux { private: // the pattern handler. - std::map entries; + std::map entries; // the vhost handler. - std::map vhosts; + std::map vhosts; public: - SrsGoHttpServeMux(); - virtual ~SrsGoHttpServeMux(); + SrsHttpServeMux(); + virtual ~SrsHttpServeMux(); public: /** * initialize the http serve mux. @@ -321,24 +345,24 @@ public: public: // Handle registers the handler for the given pattern. // If a handler already exists for pattern, Handle panics. - virtual int handle(std::string pattern, ISrsGoHttpHandler* handler); -// interface ISrsGoHttpHandler + virtual int handle(std::string pattern, ISrsHttpHandler* handler); +// interface ISrsHttpHandler public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); private: - virtual int find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph); - virtual int match(SrsHttpMessage* r, ISrsGoHttpHandler** ph); + virtual int find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph); + virtual int match(SrsHttpMessage* r, ISrsHttpHandler** ph); virtual bool path_match(std::string pattern, std::string path); }; /** * response writer use st socket */ -class SrsGoHttpResponseWriter : public ISrsGoHttpResponseWriter +class SrsHttpResponseWriter : public ISrsHttpResponseWriter { private: SrsStSocket* skt; - SrsGoHttpHeader* hdr; + SrsHttpHeader* hdr; private: // reply header has been (logically) written bool header_wrote; @@ -356,16 +380,47 @@ private: // logically written. bool header_sent; public: - SrsGoHttpResponseWriter(SrsStSocket* io); - virtual ~SrsGoHttpResponseWriter(); + SrsHttpResponseWriter(SrsStSocket* io); + virtual ~SrsHttpResponseWriter(); public: virtual int final_request(); - virtual SrsGoHttpHeader* header(); + virtual SrsHttpHeader* header(); virtual int write(char* data, int size); virtual void write_header(int code); virtual int send_header(char* data, int size); }; +/** +* response reader use st socket. +*/ +class SrsHttpResponseReader : virtual public ISrsHttpResponseReader +{ +private: + SrsStSocket* skt; + SrsHttpMessage* owner; + SrsFastBuffer* buffer; + bool is_eof; + int64_t nb_read; +public: + SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io); + virtual ~SrsHttpResponseReader(); +public: + /** + * initialize the response reader with buffer. + */ + virtual int initialize(SrsFastBuffer* buffer); +// interface ISrsHttpResponseReader +public: + virtual bool eof(); + virtual int read(std::string& data); +private: + virtual int read_chunked(std::string& data); + virtual int read_specified(int max, std::string& data); +}; + +// for http header. +typedef std::pair SrsHttpHeaderField; + // A Request represents an HTTP request received by a server // or to be sent by a client. // @@ -387,15 +442,14 @@ private: */ http_parser _header; /** - * body object, in bytes. + * body object, reader object. * @remark, user can get body in string by get_body(). */ - SrsSimpleBuffer* _body; + SrsHttpResponseReader* _body; /** - * parser state - * @remark, user can use is_complete() to determine the state. + * whether the body is chunked. */ - SrsHttpParseState _state; + bool chunked; /** * uri parser */ @@ -403,53 +457,77 @@ private: /** * use a buffer to read and send ts file. */ + // TODO: FIXME: remove it. char* _http_ts_send_buffer; // http headers - typedef std::pair SrsHttpHeaderField; - std::vector headers; + std::vector _headers; // the query map std::map _query; public: - SrsHttpMessage(); + SrsHttpMessage(SrsStSocket* io); virtual ~SrsHttpMessage(); public: - virtual int initialize(); + /** + * set the original messages, then update the message. + */ + virtual int update(std::string url, http_parser* header, + SrsFastBuffer* body, std::vector& headers + ); public: virtual char* http_ts_send_buffer(); - virtual void reset(); public: - virtual bool is_complete(); virtual u_int8_t method(); virtual u_int16_t status_code(); + /** + * method helpers. + */ virtual std::string method_str(); virtual bool is_http_get(); virtual bool is_http_put(); virtual bool is_http_post(); virtual bool is_http_delete(); virtual bool is_http_options(); + /** + * whether body is chunked encoding, for reader only. + */ + virtual bool is_chunked(); + /** + * the uri contains the host and path. + */ virtual std::string uri(); + /** + * the url maybe the path. + */ virtual std::string url(); virtual std::string host(); virtual std::string path(); public: - virtual std::string body(); - virtual char* body_raw(); - virtual int64_t body_size(); + /** + * read body to string. + * @remark for small http body. + */ + virtual int body_read_all(std::string& body); + /** + * get the body reader, to read one by one. + * @remark when body is very large, or chunked, use this. + */ + virtual ISrsHttpResponseReader* body_reader(); + /** + * the content length, -1 for chunked or not set. + */ virtual int64_t content_length(); - virtual void set_url(std::string url); - virtual void set_state(SrsHttpParseState state); - virtual void set_header(http_parser* header); - virtual void append_body(const char* body, int length); /** * get the param in query string, * for instance, query is "start=100&end=200", * then query_get("start") is "100", and query_get("end") is "200" */ virtual std::string query_get(std::string key); + /** + * get the headers. + */ virtual int request_header_count(); virtual std::string request_header_key_at(int index); virtual std::string request_header_value_at(int index); - virtual void set_request_header(std::string key, std::string value); virtual std::string get_request_header(std::string name); }; @@ -462,8 +540,18 @@ class SrsHttpParser private: http_parser_settings settings; http_parser parser; - SrsHttpMessage* msg; + // the global parse buffer. + SrsFastBuffer* buffer; +private: + // http parse data, reset before parse message. + bool expect_filed_name; std::string filed_name; + std::string field_value; + SrsHttpParseState state; + http_parser header; + std::string url; + std::vector headers; + int body_parsed; public: SrsHttpParser(); virtual ~SrsHttpParser(); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index f8236567b..5d92c7895 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -48,7 +48,7 @@ SrsGoApiRoot::~SrsGoApiRoot() { } -int SrsGoApiRoot::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiRoot::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -70,7 +70,7 @@ SrsGoApiApi::~SrsGoApiApi() { } -int SrsGoApiApi::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiApi::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -92,7 +92,7 @@ SrsGoApiV1::~SrsGoApiV1() { } -int SrsGoApiV1::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -108,8 +108,7 @@ int SrsGoApiV1::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) << __SRS_JFIELD_STR("authors", "the primary authors and contributors") << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("requests", "the request itself, for http debug") << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("vhosts", "dumps vhost to json") << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("streams", "dumps streams to json") << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("dvrs", "query or control the dvr plan") + << __SRS_JFIELD_STR("streams", "dumps streams to json") << __SRS_JOBJECT_END << __SRS_JOBJECT_END; @@ -124,7 +123,7 @@ SrsGoApiVersion::~SrsGoApiVersion() { } -int SrsGoApiVersion::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiVersion::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -149,7 +148,7 @@ SrsGoApiSummaries::~SrsGoApiSummaries() { } -int SrsGoApiSummaries::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; srs_api_dump_summaries(ss); @@ -164,7 +163,7 @@ SrsGoApiRusages::~SrsGoApiRusages() { } -int SrsGoApiRusages::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* req) +int SrsGoApiRusages::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* req) { std::stringstream ss; @@ -205,7 +204,7 @@ SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats() { } -int SrsGoApiSelfProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -275,7 +274,7 @@ SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats() { } -int SrsGoApiSystemProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -310,7 +309,7 @@ SrsGoApiMemInfos::~SrsGoApiMemInfos() { } -int SrsGoApiMemInfos::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -346,7 +345,7 @@ SrsGoApiAuthors::~SrsGoApiAuthors() { } -int SrsGoApiAuthors::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream ss; @@ -371,7 +370,7 @@ SrsGoApiRequests::~SrsGoApiRequests() { } -int SrsGoApiRequests::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { SrsHttpMessage* req = r; @@ -432,7 +431,7 @@ SrsGoApiVhosts::~SrsGoApiVhosts() { } -int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream data; SrsStatistic* stat = SrsStatistic::instance(); @@ -457,7 +456,7 @@ SrsGoApiStreams::~SrsGoApiStreams() { } -int SrsGoApiStreams::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { std::stringstream data; SrsStatistic* stat = SrsStatistic::instance(); @@ -474,77 +473,7 @@ int SrsGoApiStreams::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) return srs_go_http_response_json(w, ss.str()); } -SrsGoApiDvrs::SrsGoApiDvrs() -{ -} - -SrsGoApiDvrs::~SrsGoApiDvrs() -{ -} - -int SrsGoApiDvrs::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) -{ - std::stringstream ss; - -#ifndef SRS_AUTO_DVR - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ERROR_HTTP_DVR_DISABLED) - << __SRS_JOBJECT_END; -#else - SrsApiDvrPool* pool = SrsApiDvrPool::instance(); - if (r->is_http_get()) { - std::stringstream data; - int ret = pool->dumps(r->query_get("vhost"), data); - - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT - << __SRS_JFIELD_ORG("dvrs", data.str()) - << __SRS_JOBJECT_END; - } else if (r->is_http_post()) { - std::string body = r->body(); - SrsJsonAny* json = SrsJsonAny::loads((char*)body.c_str()); - int ret = ERROR_SUCCESS; - if (!json) { - ret = ERROR_HTTP_JSON_REQUIRED; - } else { - SrsAutoFree(SrsJsonAny, json); - ret = pool->create(json); - } - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ret) - << __SRS_JOBJECT_END; - } else if (r->is_http_delete()) { - int ret = pool->stop(r->query_get("vhost")); - - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ret) - << __SRS_JOBJECT_END; - } else if (r->is_http_put()) { - int ret = ERROR_SUCCESS; - - std::string body = r->body(); - SrsJsonAny* json = SrsJsonAny::loads((char*)body.c_str()); - if (!json) { - ret = ERROR_HTTP_JSON_REQUIRED; - } else { - SrsAutoFree(SrsJsonAny, json); - ret = pool->rpc(json); - } - - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ret) - << __SRS_JOBJECT_END; - } else { - ss << __SRS_JOBJECT_START - << __SRS_JFIELD_ERROR(ERROR_HTTP_DVR_REQUEST) - << __SRS_JOBJECT_END; - } -#endif - - return srs_go_http_response_json(w, ss.str()); -} - -SrsHttpApi::SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m) +SrsHttpApi::SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsHttpServeMux* m) : SrsConnection(svr, fd) { mux = m; @@ -557,7 +486,7 @@ SrsHttpApi::~SrsHttpApi() srs_freep(parser); } -void SrsHttpApi::kbps_resample() +void SrsHttpApi::resample() { // TODO: FIXME: implements it } @@ -574,6 +503,11 @@ int64_t SrsHttpApi::get_recv_bytes_delta() return 0; } +void SrsHttpApi::cleanup() +{ + // TODO: FIXME: implements it +} + int SrsHttpApi::do_cycle() { int ret = ERROR_SUCCESS; @@ -598,15 +532,22 @@ int SrsHttpApi::do_cycle() return ret; } - // if SUCCESS, always NOT-NULL and completed message. + // if SUCCESS, always NOT-NULL. srs_assert(req); - srs_assert(req->is_complete()); // always free it in this scope. SrsAutoFree(SrsHttpMessage, req); + // TODO: FIXME: use the post body. + std::string res; + + // get response body. + if ((ret = req->body_read_all(res)) != ERROR_SUCCESS) { + return ret; + } + // ok, handle http request. - SrsGoHttpResponseWriter writer(&skt); + SrsHttpResponseWriter writer(&skt); if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { return ret; } @@ -615,7 +556,7 @@ int SrsHttpApi::do_cycle() return ret; } -int SrsHttpApi::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 067047cda..f3f2d0a36 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -42,151 +42,142 @@ class SrsHttpHandler; #include // for http root. -class SrsGoApiRoot : public ISrsGoHttpHandler +class SrsGoApiRoot : public ISrsHttpHandler { public: SrsGoApiRoot(); virtual ~SrsGoApiRoot(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiApi : public ISrsGoHttpHandler +class SrsGoApiApi : public ISrsHttpHandler { public: SrsGoApiApi(); virtual ~SrsGoApiApi(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiV1 : public ISrsGoHttpHandler +class SrsGoApiV1 : public ISrsHttpHandler { public: SrsGoApiV1(); virtual ~SrsGoApiV1(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiVersion : public ISrsGoHttpHandler +class SrsGoApiVersion : public ISrsHttpHandler { public: SrsGoApiVersion(); virtual ~SrsGoApiVersion(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiSummaries : public ISrsGoHttpHandler +class SrsGoApiSummaries : public ISrsHttpHandler { public: SrsGoApiSummaries(); virtual ~SrsGoApiSummaries(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiRusages : public ISrsGoHttpHandler +class SrsGoApiRusages : public ISrsHttpHandler { public: SrsGoApiRusages(); virtual ~SrsGoApiRusages(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiSelfProcStats : public ISrsGoHttpHandler +class SrsGoApiSelfProcStats : public ISrsHttpHandler { public: SrsGoApiSelfProcStats(); virtual ~SrsGoApiSelfProcStats(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiSystemProcStats : public ISrsGoHttpHandler +class SrsGoApiSystemProcStats : public ISrsHttpHandler { public: SrsGoApiSystemProcStats(); virtual ~SrsGoApiSystemProcStats(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiMemInfos : public ISrsGoHttpHandler +class SrsGoApiMemInfos : public ISrsHttpHandler { public: SrsGoApiMemInfos(); virtual ~SrsGoApiMemInfos(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiAuthors : public ISrsGoHttpHandler +class SrsGoApiAuthors : public ISrsHttpHandler { public: SrsGoApiAuthors(); virtual ~SrsGoApiAuthors(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiRequests : public ISrsGoHttpHandler +class SrsGoApiRequests : public ISrsHttpHandler { public: SrsGoApiRequests(); virtual ~SrsGoApiRequests(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiVhosts : public ISrsGoHttpHandler +class SrsGoApiVhosts : public ISrsHttpHandler { public: SrsGoApiVhosts(); virtual ~SrsGoApiVhosts(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; -class SrsGoApiStreams : public ISrsGoHttpHandler +class SrsGoApiStreams : public ISrsHttpHandler { public: SrsGoApiStreams(); virtual ~SrsGoApiStreams(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); -}; - -class SrsGoApiDvrs : public ISrsGoHttpHandler -{ -public: - SrsGoApiDvrs(); - virtual ~SrsGoApiDvrs(); -public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; class SrsHttpApi : public SrsConnection { private: SrsHttpParser* parser; - SrsGoHttpServeMux* mux; + SrsHttpServeMux* mux; bool crossdomain_required; public: - SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m); + SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsHttpServeMux* m); virtual ~SrsHttpApi(); -public: - virtual void kbps_resample(); // interface IKbpsDelta public: + virtual void resample(); virtual int64_t get_send_bytes_delta(); virtual int64_t get_recv_bytes_delta(); + virtual void cleanup(); protected: virtual int do_cycle(); private: - virtual int process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; #endif diff --git a/trunk/src/app/srs_app_http_client.cpp b/trunk/src/app/srs_app_http_client.cpp index aeaebdc1c..a701d2ba8 100644 --- a/trunk/src/app/srs_app_http_client.cpp +++ b/trunk/src/app/srs_app_http_client.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include // when error, http client sleep for a while and retry. #define SRS_HTTP_CLIENT_SLEEP_US (int64_t)(3*1000*1000LL) @@ -43,6 +44,7 @@ SrsHttpClient::SrsHttpClient() { connected = false; stfd = NULL; + skt = NULL; parser = NULL; } @@ -52,22 +54,31 @@ SrsHttpClient::~SrsHttpClient() srs_freep(parser); } -int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& res) +int SrsHttpClient::initialize(string h, int p) { - res = ""; + int ret = ERROR_SUCCESS; + + srs_freep(parser); + parser = new SrsHttpParser(); + + if ((ret = parser->initialize(HTTP_RESPONSE)) != ERROR_SUCCESS) { + srs_error("initialize parser failed. ret=%d", ret); + return ret; + } + + host = h; + port = p; + + return ret; +} + +int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) +{ + *ppmsg = NULL; int ret = ERROR_SUCCESS; - if (!parser) { - parser = new SrsHttpParser(); - - if ((ret = parser->initialize(HTTP_RESPONSE)) != ERROR_SUCCESS) { - srs_error("initialize parser failed. ret=%d", ret); - return ret; - } - } - - if ((ret = connect(uri)) != ERROR_SUCCESS) { + if ((ret = connect()) != ERROR_SUCCESS) { srs_warn("http connect server failed. ret=%d", ret); return ret; } @@ -75,9 +86,9 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r // send POST request to uri // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s std::stringstream ss; - ss << "POST " << uri->get_path() << " " + ss << "POST " << path << " " << "HTTP/1.1" << __SRS_HTTP_CRLF - << "Host: " << uri->get_host() << __SRS_HTTP_CRLF + << "Host: " << host << __SRS_HTTP_CRLF << "Connection: Keep-Alive" << __SRS_HTTP_CRLF << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF @@ -85,10 +96,8 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r << __SRS_HTTP_CRLF << req; - SrsStSocket skt(stfd); - std::string data = ss.str(); - if ((ret = skt.write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { // disconnect when error. disconnect(); @@ -97,24 +106,61 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r } SrsHttpMessage* msg = NULL; - if ((ret = parser->parse_message(&skt, &msg)) != ERROR_SUCCESS) { + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) { srs_error("parse http post response failed. ret=%d", ret); return ret; } srs_assert(msg); - srs_assert(msg->is_complete()); - - status_code = (int)msg->status_code(); - - // get response body. - if (msg->body_size() > 0) { - res = msg->body(); - } + *ppmsg = msg; srs_info("parse http post response success."); - srs_freep(msg); - + return ret; +} + +int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) +{ + *ppmsg = NULL; + + int ret = ERROR_SUCCESS; + + if ((ret = connect()) != ERROR_SUCCESS) { + srs_warn("http connect server failed. ret=%d", ret); + return ret; + } + + // send POST request to uri + // GET %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s + std::stringstream ss; + ss << "GET " << path << " " + << "HTTP/1.1" << __SRS_HTTP_CRLF + << "Host: " << host << __SRS_HTTP_CRLF + << "Connection: Keep-Alive" << __SRS_HTTP_CRLF + << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF + << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF + << "Content-Type: application/json" << __SRS_HTTP_CRLF + << __SRS_HTTP_CRLF + << req; + + std::string data = ss.str(); + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { + // disconnect when error. + disconnect(); + + srs_error("write http get failed. ret=%d", ret); + return ret; + } + + SrsHttpMessage* msg = NULL; + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) { + srs_error("parse http post response failed. ret=%d", ret); + return ret; + } + srs_assert(msg); + + *ppmsg = msg; + srs_info("parse http get response success."); + return ret; } @@ -123,9 +169,10 @@ void SrsHttpClient::disconnect() connected = false; srs_close_stfd(stfd); + srs_freep(skt); } -int SrsHttpClient::connect(SrsHttpUri* uri) +int SrsHttpClient::connect() { int ret = ERROR_SUCCESS; @@ -135,19 +182,17 @@ int SrsHttpClient::connect(SrsHttpUri* uri) disconnect(); - std::string server = uri->get_host(); - int port = uri->get_port(); - // open socket. int64_t timeout = SRS_HTTP_CLIENT_SLEEP_US; - if ((ret = srs_socket_connect(server, port, timeout, &stfd)) != ERROR_SUCCESS) { + if ((ret = srs_socket_connect(host, port, timeout, &stfd)) != ERROR_SUCCESS) { srs_warn("http client failed, server=%s, port=%d, timeout=%"PRId64", ret=%d", - server.c_str(), port, timeout, ret); + host.c_str(), port, timeout, ret); return ret; } - srs_info("connect to server success. http url=%s, server=%s, port=%d", - uri->get_url(), uri->get_host(), uri->get_port()); + srs_info("connect to server success. server=%s, port=%d", host, port); + srs_assert(!skt); + skt = new SrsStSocket(stfd); connected = true; return ret; diff --git a/trunk/src/app/srs_app_http_client.hpp b/trunk/src/app/srs_app_http_client.hpp index 1ffef3bc9..451f336bf 100644 --- a/trunk/src/app/srs_app_http_client.hpp +++ b/trunk/src/app/srs_app_http_client.hpp @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsHttpUri; class SrsHttpParser; +class SrsHttpMessage; +class SrsStSocket; /** * http client to GET/POST/PUT/DELETE uri @@ -46,21 +48,38 @@ class SrsHttpClient private: bool connected; st_netfd_t stfd; + SrsStSocket* skt; SrsHttpParser* parser; +private: + // host name or ip. + std::string host; + int port; public: SrsHttpClient(); virtual ~SrsHttpClient(); public: /** - * to post data to the uri. - * @param req the data post to uri. - * @param status_code the output status code response by server. - * @param res output the response data from server. + * initialize the client, connect to host and port. */ - virtual int post(SrsHttpUri* uri, std::string req, int& status_code, std::string& res); + virtual int initialize(std::string h, int p); +public: + /** + * to post data to the uri. + * @param the path to request on. + * @param req the data post to uri. empty string to ignore. + * @param ppmsg output the http message to read the response. + */ + virtual int post(std::string path, std::string req, SrsHttpMessage** ppmsg); + /** + * to get data from the uri. + * @param the path to request on. + * @param req the data post to uri. empty string to ignore. + * @param ppmsg output the http message to read the response. + */ + virtual int get(std::string path, std::string req, SrsHttpMessage** ppmsg); private: virtual void disconnect(); - virtual int connect(SrsHttpUri* uri); + virtual int connect(); }; #endif diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index aa5892abb..eee1708df 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -50,7 +50,7 @@ using namespace std; #include SrsVodStream::SrsVodStream(string root_dir) - : SrsGoHttpFileServer(root_dir) + : SrsHttpFileServer(root_dir) { } @@ -58,7 +58,7 @@ SrsVodStream::~SrsVodStream() { } -int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) +int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) { int ret = ERROR_SUCCESS; @@ -142,7 +142,7 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return ret; } -int SrsVodStream::serve_mp4_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) +int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) { int ret = ERROR_SUCCESS; @@ -394,7 +394,7 @@ int SrsFlvStreamEncoder::write_video(int64_t timestamp, char* data, int size) int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size) { - return enc->write_metadata(timestamp, data, size); + return enc->write_metadata(SrsCodecFlvTagScript, data, size); } bool SrsFlvStreamEncoder::has_cache() @@ -517,7 +517,7 @@ int SrsMp3StreamEncoder::dump_cache(SrsConsumer* consumer) return cache->dump_cache(consumer); } -SrsStreamWriter::SrsStreamWriter(ISrsGoHttpResponseWriter* w) +SrsStreamWriter::SrsStreamWriter(ISrsHttpResponseWriter* w) { writer = w; } @@ -565,7 +565,7 @@ SrsLiveStream::~SrsLiveStream() srs_freep(req); } -int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; @@ -708,7 +708,7 @@ void SrsHlsM3u8Stream::set_m3u8(std::string v) m3u8 = v; } -int SrsHlsM3u8Stream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; @@ -740,7 +740,7 @@ void SrsHlsTsStream::set_ts(std::string v) ts = v; } -int SrsHlsTsStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; @@ -771,19 +771,35 @@ SrsHttpServer::~SrsHttpServer() { if (true) { std::map::iterator it; - for (it = flvs.begin(); it != flvs.end(); ++it) { + for (it = tflvs.begin(); it != tflvs.end(); ++it) { SrsLiveEntry* entry = it->second; srs_freep(entry); } - flvs.clear(); + tflvs.clear(); + } + if (true) { + std::map::iterator it; + for (it = sflvs.begin(); it != sflvs.end(); ++it) { + SrsLiveEntry* entry = it->second; + srs_freep(entry); + } + sflvs.clear(); } if (true) { std::map::iterator it; - for (it = hls.begin(); it != hls.end(); ++it) { + for (it = thls.begin(); it != thls.end(); ++it) { SrsHlsEntry* entry = it->second; srs_freep(entry); } - hls.clear(); + thls.clear(); + } + if (true) { + std::map::iterator it; + for (it = shls.begin(); it != shls.end(); ++it) { + SrsHlsEntry* entry = it->second; + srs_freep(entry); + } + shls.clear(); } } @@ -814,56 +830,72 @@ int SrsHttpServer::mount(SrsSource* s, SrsRequest* r) { int ret = ERROR_SUCCESS; - if (flvs.find(r->vhost) == flvs.end()) { - srs_info("ignore mount flv stream for disabled"); - return ret; - } + // the id to identify stream. + std::string sid = r->get_stream_url(); + SrsLiveEntry* entry = NULL; - SrsLiveEntry* entry = flvs[r->vhost]; + // create stream from template when not found. + if (sflvs.find(sid) == sflvs.end()) { + if (tflvs.find(r->vhost) == tflvs.end()) { + srs_info("ignore mount flv stream for disabled"); + return ret; + } + + SrsLiveEntry* tmpl = tflvs[r->vhost]; + + std::string mount = tmpl->mount; + + // replace the vhost variable + mount = srs_string_replace(mount, "[vhost]", r->vhost); + mount = srs_string_replace(mount, "[app]", r->app); + mount = srs_string_replace(mount, "[stream]", r->stream); + + // remove the default vhost mount + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); + + entry = new SrsLiveEntry(); + entry->mount = mount; + + entry->cache = new SrsStreamCache(s, r); + entry->stream = new SrsLiveStream(s, r, entry->cache); + + sflvs[sid] = entry; + + // start http stream cache thread + if ((ret = entry->cache->start()) != ERROR_SUCCESS) { + srs_error("http: start stream cache failed. ret=%d", ret); + return ret; + } + + // mount the http flv stream. + if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) { + srs_error("http: mount flv stream for vhost=%s failed. ret=%d", sid.c_str(), ret); + return ret; + } + srs_trace("http: mount flv stream for vhost=%s, mount=%s", sid.c_str(), mount.c_str()); + } else { + entry = sflvs[sid]; + } // TODO: FIXME: supports reload. if (entry->stream) { entry->stream->entry->enabled = true; return ret; } - - std::string mount = entry->mount; - - // replace the vhost variable - mount = srs_string_replace(mount, "[vhost]", r->vhost); - mount = srs_string_replace(mount, "[app]", r->app); - mount = srs_string_replace(mount, "[stream]", r->stream); - - // remove the default vhost mount - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - - entry->cache = new SrsStreamCache(s, r); - entry->stream = new SrsLiveStream(s, r, entry->cache); - - // start http stream cache thread - if ((ret = entry->cache->start()) != ERROR_SUCCESS) { - srs_error("http: start stream cache failed. ret=%d", ret); - return ret; - } - - // mount the http flv stream. - if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) { - srs_error("http: mount flv stream for vhost=%s failed. ret=%d", r->vhost.c_str(), ret); - return ret; - } - srs_trace("http: mount flv stream for vhost=%s, mount=%s", r->vhost.c_str(), mount.c_str()); return ret; } void SrsHttpServer::unmount(SrsSource* s, SrsRequest* r) { - if (flvs.find(r->vhost) == flvs.end()) { + std::string sid = r->get_stream_url(); + + if (sflvs.find(sid) == sflvs.end()) { srs_info("ignore unmount flv stream for disabled"); return; } - SrsLiveEntry* entry = flvs[r->vhost]; + SrsLiveEntry* entry = sflvs[sid]; entry->stream->entry->enabled = false; } @@ -871,17 +903,19 @@ int SrsHttpServer::mount_hls(SrsRequest* r) { int ret = ERROR_SUCCESS; - if (hls.find(r->vhost) == hls.end()) { + std::string sid = r->get_stream_url(); + + if (shls.find(sid) == shls.end()) { srs_info("ignore mount hls stream for disabled"); return ret; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; // TODO: FIXME: supports reload. - std::map::iterator it; + std::map::iterator it; for (it = entry->streams.begin(); it != entry->streams.end(); ++it) { - ISrsGoHttpHandler* stream = it->second; + ISrsHttpHandler* stream = it->second; stream->entry->enabled = true; } @@ -891,33 +925,37 @@ int SrsHttpServer::mount_hls(SrsRequest* r) int SrsHttpServer::hls_update_m3u8(SrsRequest* r, string m3u8) { int ret = ERROR_SUCCESS; + + std::string mount = m3u8; - // when no hls mounted, ignore. - if (hls.find(r->vhost) == hls.end()) { - return ret; - } + std::string sid = r->get_stream_url(); + SrsHlsEntry* entry = NULL; - SrsHlsEntry* entry = hls[r->vhost]; - srs_assert(entry); - - std::string mount = entry->mount; - - // replace the vhost variable - mount = srs_string_replace(mount, "[vhost]", r->vhost); - mount = srs_string_replace(mount, "[app]", r->app); - mount = srs_string_replace(mount, "[stream]", r->stream); - - // remove the default vhost mount - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - - if (entry->streams.find(mount) == entry->streams.end()) { - ISrsGoHttpHandler* he = new SrsHlsM3u8Stream(); - entry->streams[mount] = he; - - if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { - srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret); + // create stream from template when not found. + if (shls.find(sid) == shls.end()) { + if (thls.find(r->vhost) == thls.end()) { + srs_info("ignore mount hls stream for disabled"); return ret; } + + SrsHlsEntry* tmpl = thls[r->vhost]; + + entry = new SrsHlsEntry(); + entry->mount = tmpl->mount; + + shls[sid] = entry; + + if (entry->streams.find(mount) == entry->streams.end()) { + ISrsHttpHandler* he = new SrsHlsM3u8Stream(); + entry->streams[mount] = he; + + if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { + srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret); + return ret; + } + } + } else { + entry = shls[sid]; } // update the m3u8 stream. @@ -934,12 +972,14 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) { int ret = ERROR_SUCCESS; + std::string sid = r->get_stream_url(); + // when no hls mounted, ignore. - if (hls.find(r->vhost) == hls.end()) { + if (shls.find(sid) == shls.end()) { return ret; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; srs_assert(entry); std::string mount = entry->mount; @@ -962,7 +1002,7 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) mount += uri; if (entry->streams.find(mount) == entry->streams.end()) { - ISrsGoHttpHandler* he = new SrsHlsTsStream(); + ISrsHttpHandler* he = new SrsHlsTsStream(); entry->streams[mount] = he; if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { @@ -983,16 +1023,18 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) void SrsHttpServer::unmount_hls(SrsRequest* r) { - if (hls.find(r->vhost) == hls.end()) { + std::string sid = r->get_stream_url(); + + if (shls.find(sid) == shls.end()) { srs_info("ignore unmount hls stream for disabled"); return; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; - std::map::iterator it; + std::map::iterator it; for (it = entry->streams.begin(); it != entry->streams.end(); ++it) { - ISrsGoHttpHandler* stream = it->second; + ISrsHttpHandler* stream = it->second; stream->entry->enabled = false; } } @@ -1097,9 +1139,8 @@ int SrsHttpServer::initialize_flv_streaming() } SrsLiveEntry* entry = new SrsLiveEntry(); - entry->vhost = vhost; entry->mount = _srs_config->get_vhost_http_remux_mount(vhost); - flvs[vhost] = entry; + tflvs[vhost] = entry; srs_trace("http flv live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount.c_str()); } @@ -1131,9 +1172,8 @@ int SrsHttpServer::initialize_hls_streaming() } SrsHlsEntry* entry = new SrsHlsEntry(); - entry->vhost = vhost; entry->mount = _srs_config->get_hls_mount(vhost); - hls[vhost] = entry; + thls[vhost] = entry; srs_trace("http hls live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount.c_str()); } @@ -1153,7 +1193,7 @@ SrsHttpConn::~SrsHttpConn() srs_freep(parser); } -void SrsHttpConn::kbps_resample() +void SrsHttpConn::resample() { // TODO: FIXME: implements it } @@ -1170,6 +1210,11 @@ int64_t SrsHttpConn::get_recv_bytes_delta() return 0; } +void SrsHttpConn::cleanup() +{ + // TODO: FIXME: implements it +} + int SrsHttpConn::do_cycle() { int ret = ERROR_SUCCESS; @@ -1194,15 +1239,22 @@ int SrsHttpConn::do_cycle() return ret; } - // if SUCCESS, always NOT-NULL and completed message. + // if SUCCESS, always NOT-NULL. srs_assert(req); - srs_assert(req->is_complete()); // always free it in this scope. SrsAutoFree(SrsHttpMessage, req); + // TODO: FIXME: use the post body. + std::string res; + + // get response body. + if ((ret = req->body_read_all(res)) != ERROR_SUCCESS) { + return ret; + } + // ok, handle http request. - SrsGoHttpResponseWriter writer(&skt); + SrsHttpResponseWriter writer(&skt); if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { return ret; } @@ -1211,7 +1263,7 @@ int SrsHttpConn::do_cycle() return ret; } -int SrsHttpConn::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 5a63418d1..56f4f7806 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -59,14 +59,14 @@ class SrsSharedPtrMessage; * server will write flv header and sequence header, * then seek(10240) and response flv tag data. */ -class SrsVodStream : public SrsGoHttpFileServer +class SrsVodStream : public SrsHttpFileServer { public: SrsVodStream(std::string root_dir); virtual ~SrsVodStream(); protected: - virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); - virtual int serve_mp4_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); }; /** @@ -214,9 +214,9 @@ public: class SrsStreamWriter : public SrsFileWriter { private: - ISrsGoHttpResponseWriter* writer; + ISrsHttpResponseWriter* writer; public: - SrsStreamWriter(ISrsGoHttpResponseWriter* w); + SrsStreamWriter(ISrsHttpResponseWriter* w); virtual ~SrsStreamWriter(); public: virtual int open(std::string file); @@ -232,7 +232,7 @@ public: * the flv live stream supports access rtmp in flv over http. * srs will remux rtmp to flv streaming. */ -class SrsLiveStream : public ISrsGoHttpHandler +class SrsLiveStream : public ISrsHttpHandler { private: SrsRequest* req; @@ -242,7 +242,7 @@ public: SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c); virtual ~SrsLiveStream(); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); private: virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs); }; @@ -252,8 +252,10 @@ private: */ struct SrsLiveEntry { - std::string vhost; + // for template, the mount contains variables. + // for concrete stream, the mount is url to access. std::string mount; + SrsLiveStream* stream; SrsStreamCache* cache; @@ -263,7 +265,7 @@ struct SrsLiveEntry /** * the m3u8 stream handler. */ -class SrsHlsM3u8Stream : public ISrsGoHttpHandler +class SrsHlsM3u8Stream : public ISrsHttpHandler { private: std::string m3u8; @@ -273,13 +275,13 @@ public: public: virtual void set_m3u8(std::string v); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; /** * the ts stream handler. */ -class SrsHlsTsStream : public ISrsGoHttpHandler +class SrsHlsTsStream : public ISrsHttpHandler { private: std::string ts; @@ -289,7 +291,7 @@ public: public: virtual void set_ts(std::string v); public: - virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; /** @@ -297,12 +299,13 @@ public: */ struct SrsHlsEntry { - std::string vhost; + // for template, the mount contains variables. + // for concrete stream, the mount is url to access. std::string mount; // key: the m3u8/ts file path. // value: the http handler. - std::map streams; + std::map streams; SrsHlsEntry(); }; @@ -314,11 +317,15 @@ struct SrsHlsEntry class SrsHttpServer : public ISrsReloadHandler { public: - SrsGoHttpServeMux mux; - // the flv live streaming template. - std::map flvs; - // the hls live streaming template. - std::map hls; + SrsHttpServeMux mux; + // the flv live streaming template, to create streams. + std::map tflvs; + // the flv live streaming streams, crote by template. + std::map sflvs; + // the hls live streaming template, to create streams. + std::map thls; + // the hls live streaming streams, crote by template. + std::map shls; public: SrsHttpServer(); virtual ~SrsHttpServer(); @@ -353,16 +360,16 @@ private: public: SrsHttpConn(SrsServer* svr, st_netfd_t fd, SrsHttpServer* m); virtual ~SrsHttpConn(); -public: - virtual void kbps_resample(); // interface IKbpsDelta public: + virtual void resample(); virtual int64_t get_send_bytes_delta(); virtual int64_t get_recv_bytes_delta(); + virtual void cleanup(); protected: virtual int do_cycle(); private: - virtual int process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); }; #endif diff --git a/trunk/src/app/srs_app_http_hooks.cpp b/trunk/src/app/srs_app_http_hooks.cpp index 4a02232cc..6d1de2155 100644 --- a/trunk/src/app/srs_app_http_hooks.cpp +++ b/trunk/src/app/srs_app_http_hooks.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include #define SRS_HTTP_RESPONSE_OK __SRS_XSTR(ERROR_SUCCESS) @@ -53,13 +54,6 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_connect url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_connect") << __SRS_JFIELD_CONT @@ -70,31 +64,14 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r << __SRS_JFIELD_STR("tcUrl", req->tcUrl) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("pageUrl", req->pageUrl) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_error("http post on_connect uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_connect status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_connect validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return ret; } @@ -109,13 +86,6 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_close url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_close") << __SRS_JFIELD_CONT @@ -124,31 +94,14 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re << __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("app", req->app) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_warn("http post on_close uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_close status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_close validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return; } @@ -163,13 +116,6 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_publish url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_publish") << __SRS_JFIELD_CONT @@ -179,31 +125,14 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r << __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("stream", req->stream) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_error("http post on_publish uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_publish status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_publish validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return ret; } @@ -218,13 +147,6 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_unpublish url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_unpublish") << __SRS_JFIELD_CONT @@ -234,31 +156,14 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest << __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("stream", req->stream) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_warn("http post on_unpublish uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_unpublish status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_unpublish validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return; } @@ -273,13 +178,6 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req) { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_play url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_play") << __SRS_JFIELD_CONT @@ -289,31 +187,14 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req) << __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("stream", req->stream) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_error("http post on_play uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_play status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_play validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return ret; } @@ -328,13 +209,6 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_stop url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_stop") << __SRS_JFIELD_CONT @@ -344,31 +218,14 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req << __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("stream", req->stream) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_warn("http post on_stop uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_stop status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_stop validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return; } @@ -383,13 +240,6 @@ int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_dvr url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_dvr") << __SRS_JFIELD_CONT @@ -401,31 +251,14 @@ int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, << __SRS_JFIELD_STR("cwd", cwd) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("file", file) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_error("http post on_dvr uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_dvr status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_dvr validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return ret; } @@ -440,13 +273,6 @@ int SrsHttpHooks::on_dvr_reap_segment(string url, int client_id, SrsRequest* req { int ret = ERROR_SUCCESS; - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_dvr_reap_segment url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - std::stringstream ss; ss << __SRS_JOBJECT_START << __SRS_JFIELD_STR("action", "on_dvr_reap_segment") << __SRS_JFIELD_CONT @@ -457,31 +283,14 @@ int SrsHttpHooks::on_dvr_reap_segment(string url, int client_id, SrsRequest* req << __SRS_JFIELD_STR("cwd", cwd) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("file", file) << __SRS_JOBJECT_END; + std::string data = ss.str(); std::string res; int status_code; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) { + if ((ret = do_post(url, data, status_code, res)) != ERROR_SUCCESS) { srs_error("http post on_dvr_reap_segment uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - // ensure the http status is ok. - // https://github.com/winlinvip/simple-rtmp-server/issues/158 - if (status_code != SRS_CONSTS_HTTP_OK) { - ret = ERROR_HTTP_STATUS_INVLIAD; - srs_error("http hook on_dvr_reap_segment status failed. " - "client_id=%d, code=%d, ret=%d", client_id, status_code, ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_dvr_reap_segment validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + "client_id=%d, url=%s, request=%s, response=%s, code=%d, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); return ret; } @@ -492,4 +301,44 @@ int SrsHttpHooks::on_dvr_reap_segment(string url, int client_id, SrsRequest* req return ret; } +int SrsHttpHooks::do_post(std::string url, std::string req, int& code, string& res) +{ + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_error("http: post failed. url=%s, ret=%d", url.c_str(), ret); + return ret; + } + + SrsHttpClient http; + if ((ret = http.initialize(uri.get_host(), uri.get_port())) != ERROR_SUCCESS) { + return ret; + } + + SrsHttpMessage* msg = NULL; + if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { + return ret; + } + SrsAutoFree(SrsHttpMessage, msg); + + code = msg->status_code(); + if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { + return ret; + } + + // ensure the http status is ok. + // https://github.com/winlinvip/simple-rtmp-server/issues/158 + if (code != SRS_CONSTS_HTTP_OK) { + return ERROR_HTTP_STATUS_INVLIAD; + } + + // TODO: FIXME: parse json. + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + return ERROR_HTTP_DATA_INVLIAD; + } + + return ret; +} + #endif diff --git a/trunk/src/app/srs_app_http_hooks.hpp b/trunk/src/app/srs_app_http_hooks.hpp index ebc1452ba..49c387fb9 100644 --- a/trunk/src/app/srs_app_http_hooks.hpp +++ b/trunk/src/app/srs_app_http_hooks.hpp @@ -113,6 +113,8 @@ public: * @param file the file path, can be relative or absolute path. */ static int on_dvr_reap_segment(std::string url, int client_id, SrsRequest* req, std::string cwd, std::string file); +private: + static int do_post(std::string url, std::string req, int& code, std::string& res); }; #endif diff --git a/trunk/src/app/srs_app_json.hpp b/trunk/src/app/srs_app_json.hpp index 002492fdf..d8aeba818 100644 --- a/trunk/src/app/srs_app_json.hpp +++ b/trunk/src/app/srs_app_json.hpp @@ -217,6 +217,7 @@ that is: #define __SRS_JFIELD_STR(k, v) "\"" << k << "\":\"" << v << "\"" #define __SRS_JFIELD_ORG(k, v) "\"" << k << "\":" << std::dec << v #define __SRS_JFIELD_BOOL(k, v) __SRS_JFIELD_ORG(k, (v? "true":"false")) +#define __SRS_JFIELD_NULL(k) "\"" << k << "\":null" #define __SRS_JFIELD_ERROR(ret) "\"" << "code" << "\":" << ret #define __SRS_JFIELD_CONT "," #define __SRS_JOBJECT_END "}" diff --git a/trunk/src/app/srs_app_kbps.cpp b/trunk/src/app/srs_app_kbps.cpp index 9abbcc5bb..9df0e8457 100644 --- a/trunk/src/app/srs_app_kbps.cpp +++ b/trunk/src/app/srs_app_kbps.cpp @@ -203,20 +203,29 @@ int64_t SrsKbps::get_recv_bytes() return is.get_total_bytes(); } +void SrsKbps::resample() +{ + sample(); +} + int64_t SrsKbps::get_send_bytes_delta() { int64_t delta = os.get_total_bytes() - os.delta_bytes; - os.delta_bytes = os.get_total_bytes(); return delta; } int64_t SrsKbps::get_recv_bytes_delta() { int64_t delta = is.get_total_bytes() - is.delta_bytes; - is.delta_bytes = is.get_total_bytes(); return delta; } +void SrsKbps::cleanup() +{ + os.delta_bytes = os.get_total_bytes(); + is.delta_bytes = is.get_total_bytes(); +} + void SrsKbps::add_delta(IKbpsDelta* delta) { srs_assert(delta); diff --git a/trunk/src/app/srs_app_kbps.hpp b/trunk/src/app/srs_app_kbps.hpp index bb6faee91..4c56c890a 100644 --- a/trunk/src/app/srs_app_kbps.hpp +++ b/trunk/src/app/srs_app_kbps.hpp @@ -107,6 +107,11 @@ public: /** * the interface which provices delta of bytes. +* for a delta, for example, a live stream connection, we can got the delta by: +* IKbpsDelta* delta = ...; +* delta->resample(); +* kbps->add_delta(delta); +* delta->cleanup(); */ class IKbpsDelta { @@ -114,25 +119,41 @@ public: IKbpsDelta(); virtual ~IKbpsDelta(); public: + /** + * resample to generate the value of delta bytes. + */ + virtual void resample() = 0; + /** + * get the send or recv bytes delta. + */ virtual int64_t get_send_bytes_delta() = 0; virtual int64_t get_recv_bytes_delta() = 0; + /** + * cleanup the value of delta bytes. + */ + virtual void cleanup() = 0; }; /** * to statistic the kbps of io. * itself can be a statistic source, for example, used for SRS bytes stat. * there are two usage scenarios: -* 1. connections to calc kbps: -* set_io(in, out) -* sample() -* get_xxx_kbps(). +* 1. connections to calc kbps by sample(): +* SrsKbps* kbps = ...; +* kbps->set_io(in, out) +* kbps->sample() +* kbps->get_xxx_kbps(). * the connections know how many bytes already send/recv. -* 2. server to calc kbps: -* set_io(NULL, NULL) +* 2. server to calc kbps by add_delta(): +* SrsKbps* kbps = ...; +* kbps->set_io(NULL, NULL) * for each connection in connections: -* add_delta(connections) // where connection is a IKbpsDelta* -* sample() -* get_xxx_kbps(). +* IKbpsDelta* delta = connection; // where connection implements IKbpsDelta +* delta->resample() +* kbps->add_delta(delta) +* delta->cleanup() +* kbps->sample() +* kbps->get_xxx_kbps(). * the server never know how many bytes already send/recv, for the connection maybe closed. */ class SrsKbps : public virtual ISrsProtocolStatistic, public virtual IKbpsDelta @@ -174,18 +195,26 @@ public: */ virtual int64_t get_send_bytes(); virtual int64_t get_recv_bytes(); +public: + /** + * resample to get the delta. + */ + virtual void resample(); /** * get the delta of send/recv bytes. - * @remark, used for add_delta to calc the total system bytes/kbps. */ virtual int64_t get_send_bytes_delta(); virtual int64_t get_recv_bytes_delta(); + /** + * cleanup the delta. + */ + virtual void cleanup(); public: /** * add delta to kbps clac mechenism. * we donot know the total bytes, but know the delta, for instance, * for rtmp server to calc total bytes and kbps. - * @remark user must invoke sample() when invoke this method. + * @remark user must invoke sample() to calc result after invoke this method. * @param delta, assert should never be NULL. */ virtual void add_delta(IKbpsDelta* delta); diff --git a/trunk/src/app/srs_app_mpegts_udp.cpp b/trunk/src/app/srs_app_mpegts_udp.cpp index d40a8fd19..885c342cc 100644 --- a/trunk/src/app/srs_app_mpegts_udp.cpp +++ b/trunk/src/app/srs_app_mpegts_udp.cpp @@ -130,11 +130,13 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c) context = new SrsTsContext(); buffer = new SrsSimpleBuffer(); output = _srs_config->get_stream_caster_output(c); + req = NULL; io = NULL; client = NULL; stfd = NULL; stream_id = 0; + avc = new SrsRawH264Stream(); aac = new SrsRawAacStream(); h264_sps_changed = false; @@ -159,8 +161,6 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp() int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) { - int ret = ERROR_SUCCESS; - std::string peer_ip = inet_ntoa(from->sin_addr); int peer_port = ntohs(from->sin_port); @@ -169,6 +169,13 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) srs_info("udp: got %s:%d packet %d/%d bytes", peer_ip.c_str(), peer_port, nb_buf, buffer->length()); + + return on_udp_bytes(peer_ip, peer_port, buf, nb_buf); +} + +int SrsMpegtsOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf) +{ + int ret = ERROR_SUCCESS; // collect nMB data to parse in a time. // TODO: FIXME: comment the following for release. @@ -215,8 +222,7 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) // drop ts packet when size not modulus by 188 if (buffer->length() < SRS_TS_PACKET_SIZE) { - srs_warn("udp: wait %s:%d packet %d/%d bytes", - peer_ip.c_str(), peer_port, nb_buf, buffer->length()); + srs_warn("udp: wait %s:%d packet %d/%d bytes", host.c_str(), port, nb_buf, buffer->length()); return ret; } @@ -582,6 +588,7 @@ int SrsMpegtsOverUdp::connect() int ret = ERROR_SUCCESS; // when ok, ignore. + // TODO: FIXME: should reconnect when disconnected. if (io || client) { return ret; } diff --git a/trunk/src/app/srs_app_mpegts_udp.hpp b/trunk/src/app/srs_app_mpegts_udp.hpp index 7c8bdd6b0..39f2cb12b 100644 --- a/trunk/src/app/srs_app_mpegts_udp.hpp +++ b/trunk/src/app/srs_app_mpegts_udp.hpp @@ -109,6 +109,8 @@ public: // interface ISrsUdpHandler public: virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf); +private: + virtual int on_udp_bytes(std::string host, int port, char* buf, int nb_buf); // interface ISrsTsHandler public: virtual int on_ts_message(SrsTsMessage* msg); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 1008d31e5..8ddeeac6e 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include using namespace std; @@ -109,11 +110,6 @@ SrsRtmpConn::~SrsRtmpConn() srs_freep(kbps); } -void SrsRtmpConn::kbps_resample() -{ - kbps->sample(); -} - // TODO: return detail message when error for client. int SrsRtmpConn::do_cycle() { @@ -201,7 +197,7 @@ int SrsRtmpConn::do_cycle() ret = service_cycle(); http_hooks_on_close(); SrsStatistic* stat = SrsStatistic::instance(); - stat->on_close(_srs_context->get_id()); + stat->on_disconnect(_srs_context->get_id()); return ret; } @@ -254,6 +250,11 @@ int SrsRtmpConn::on_reload_vhost_realtime(string vhost) return ret; } +void SrsRtmpConn::resample() +{ + kbps->resample(); +} + int64_t SrsRtmpConn::get_send_bytes_delta() { return kbps->get_send_bytes_delta(); @@ -263,6 +264,11 @@ int64_t SrsRtmpConn::get_recv_bytes_delta() { return kbps->get_recv_bytes_delta(); } + +void SrsRtmpConn::cleanup() +{ + kbps->cleanup(); +} int SrsRtmpConn::service_cycle() { @@ -392,9 +398,11 @@ int SrsRtmpConn::stream_service_cycle() bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost); // find a source to serve. - SrsSource* source = NULL; - if ((ret = SrsSource::find(req, server, server, &source)) != ERROR_SUCCESS) { - return ret; + SrsSource* source = SrsSource::fetch(req); + if (!source) { + if ((ret = SrsSource::create(req, server, server, &source)) != ERROR_SUCCESS) { + return ret; + } } srs_assert(source != NULL); @@ -622,6 +630,9 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, SrsQueueRe mw_enabled = true; change_mw_sleep(_srs_config->get_mw_sleep_ms(req->vhost)); + // set the sock options. + play_set_sock_options(); + while (true) { // collect elapse for pithy print. pprint->elapse(); @@ -1087,7 +1098,7 @@ void SrsRtmpConn::change_mw_sleep(int sleep_ms) socklen_t sock_buf_size = sizeof(int); getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &onb_sbuf, &sock_buf_size); -#ifdef SRS_PERF_MW_SO_SNDBUF +#ifdef SRS_PERF_MW_SO_SNDBUF // the bytes: // 4KB=4096, 8KB=8192, 16KB=16384, 32KB=32768, 64KB=65536, // 128KB=131072, 256KB=262144, 512KB=524288 @@ -1104,6 +1115,11 @@ void SrsRtmpConn::change_mw_sleep(int sleep_ms) // socket send buffer, system will double it. int nb_sbuf = socket_buffer_size / 2; + // override the send buffer by macro. + #ifdef SRS_PERF_SO_SNDBUF_SIZE + nb_sbuf = SRS_PERF_SO_SNDBUF_SIZE / 2; + #endif + // set the socket send buffer when required larger buffer if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nb_sbuf, sock_buf_size) < 0) { srs_warn("set sock SO_SENDBUF=%d failed.", nb_sbuf); @@ -1121,6 +1137,29 @@ void SrsRtmpConn::change_mw_sleep(int sleep_ms) mw_sleep = sleep_ms; } +void SrsRtmpConn::play_set_sock_options() +{ +#ifdef SRS_PERF_TCP_NODELAY + if (true) { + int fd = st_netfd_fileno(stfd); + + socklen_t nb_v = sizeof(int); + + int ov = 0; + getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &ov, &nb_v); + + int v = 1; + // set the socket send buffer when required larger buffer + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, nb_v) < 0) { + srs_warn("set sock TCP_NODELAY=%d failed.", v); + } + getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, &nb_v); + + srs_trace("set TCP_NODELAY %d=>%d", ov, v); + } +#endif +} + int SrsRtmpConn::check_edge_token_traverse_auth() { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp index bca501ad4..33ebfcacb 100644 --- a/trunk/src/app/srs_app_rtmp_conn.hpp +++ b/trunk/src/app/srs_app_rtmp_conn.hpp @@ -83,8 +83,6 @@ private: public: SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd); virtual ~SrsRtmpConn(); -public: - virtual void kbps_resample(); protected: virtual int do_cycle(); // interface ISrsReloadHandler @@ -94,8 +92,10 @@ public: virtual int on_reload_vhost_realtime(std::string vhost); // interface IKbpsDelta public: + virtual void resample(); virtual int64_t get_send_bytes_delta(); virtual int64_t get_recv_bytes_delta(); + virtual void cleanup(); private: // when valid and connected to vhost/app, service the client. virtual int service_cycle(); @@ -111,6 +111,7 @@ private: virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool vhost_is_edge); virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); virtual void change_mw_sleep(int sleep_ms); + virtual void play_set_sock_options(); private: virtual int check_edge_token_traverse_auth(); virtual int connect_server(int origin_index, st_netfd_t* pstsock); diff --git a/trunk/src/app/srs_app_rtsp.cpp b/trunk/src/app/srs_app_rtsp.cpp index 0747160de..ad1c4f360 100644 --- a/trunk/src/app/srs_app_rtsp.cpp +++ b/trunk/src/app/srs_app_rtsp.cpp @@ -131,7 +131,7 @@ int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) SrsRtspAudioCache::SrsRtspAudioCache() { - dts = NULL; + dts = 0; audio_samples = NULL; payload = NULL; } diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 7d2481ea5..4e6742e2d 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -45,6 +45,7 @@ using namespace std; #include #include #include +#include // signal defines. #define SIGNAL_RELOAD SIGHUP @@ -392,13 +393,12 @@ SrsServer::SrsServer() pid_fd = -1; signal_manager = NULL; - kbps = NULL; // donot new object in constructor, // for some global instance is not ready now, // new these objects in initialize instead. #ifdef SRS_AUTO_HTTP_API - http_api_mux = new SrsGoHttpServeMux(); + http_api_mux = new SrsHttpServeMux(); #endif #ifdef SRS_AUTO_HTTP_SERVER http_stream_mux = new SrsHttpServer(); @@ -452,7 +452,6 @@ void SrsServer::destroy() } srs_freep(signal_manager); - srs_freep(kbps); // @remark never destroy the connections, // for it's still alive. @@ -478,61 +477,11 @@ int SrsServer::initialize() srs_assert(!signal_manager); signal_manager = new SrsSignalManager(this); - srs_assert(!kbps); - kbps = new SrsKbps(); - kbps->set_io(NULL, NULL); - #ifdef SRS_AUTO_HTTP_API if ((ret = http_api_mux->initialize()) != ERROR_SUCCESS) { return ret; } #endif - -#ifdef SRS_AUTO_HTTP_API - srs_assert(http_api_mux); - if ((ret = http_api_mux->handle("/", new SrsGoApiRoot())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api", new SrsGoApiApi())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1", new SrsGoApiV1())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/summaries", new SrsGoApiSummaries())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/rusages", new SrsGoApiRusages())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/self_proc_stats", new SrsGoApiSelfProcStats())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/system_proc_stats", new SrsGoApiSystemProcStats())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/meminfos", new SrsGoApiMemInfos())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/authors", new SrsGoApiAuthors())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/vhosts", new SrsGoApiVhosts())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/streams", new SrsGoApiStreams())) != ERROR_SUCCESS) { - return ret; - } - if ((ret = http_api_mux->handle("/api/v1/dvrs", new SrsGoApiDvrs())) != ERROR_SUCCESS) { - return ret; - } -#endif #ifdef SRS_AUTO_HTTP_SERVER srs_assert(http_stream_mux); @@ -692,6 +641,56 @@ int SrsServer::register_signal() return signal_manager->start(); } +int SrsServer::http_handle() +{ + int ret = ERROR_SUCCESS; + +#ifdef SRS_AUTO_HTTP_API + srs_assert(http_api_mux); + if ((ret = http_api_mux->handle("/", new SrsGoApiRoot())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api", new SrsGoApiApi())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1", new SrsGoApiV1())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/summaries", new SrsGoApiSummaries())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/rusages", new SrsGoApiRusages())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/self_proc_stats", new SrsGoApiSelfProcStats())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/system_proc_stats", new SrsGoApiSystemProcStats())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/meminfos", new SrsGoApiMemInfos())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/authors", new SrsGoApiAuthors())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/vhosts", new SrsGoApiVhosts())) != ERROR_SUCCESS) { + return ret; + } + if ((ret = http_api_mux->handle("/api/v1/streams", new SrsGoApiStreams())) != ERROR_SUCCESS) { + return ret; + } +#endif + + return ret; +} + int SrsServer::ingest() { int ret = ERROR_SUCCESS; @@ -741,8 +740,8 @@ void SrsServer::remove(SrsConnection* conn) srs_info("conn removed. conns=%d", (int)conns.size()); - // resample the resource of specified connection. - resample_kbps(conn); + SrsStatistic* stat = SrsStatistic::instance(); + stat->kbps_add_delta(conn); // all connections are created by server, // so we free it here. @@ -858,9 +857,8 @@ int SrsServer::do_cycle() srs_update_network_devices(); } if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) { - srs_info("update network rtmp server info."); - resample_kbps(NULL); - srs_update_rtmp_server((int)conns.size(), kbps); + srs_info("update network server kbps info."); + resample_kbps(); } #ifdef SRS_AUTO_HTTP_PARSER if (_srs_config->get_heartbeat_enabled()) { @@ -1009,31 +1007,25 @@ void SrsServer::close_listeners(SrsListenerType type) } } -void SrsServer::resample_kbps(SrsConnection* conn, bool do_resample) +void SrsServer::resample_kbps() { - // resample all when conn is NULL. - if (!conn) { - for (std::vector::iterator it = conns.begin(); it != conns.end(); ++it) { - SrsConnection* client = *it; - srs_assert(client); - - // only resample, do resample when all finished. - resample_kbps(client, false); - } + SrsStatistic* stat = SrsStatistic::instance(); + + // collect delta from all clients. + for (std::vector::iterator it = conns.begin(); it != conns.end(); ++it) { + SrsConnection* conn = *it; - kbps->sample(); - return; + // add delta of connection to server kbps., + // for next sample() of server kbps can get the stat. + stat->kbps_add_delta(conn); } - // resample for connection. - conn->kbps_resample(); + // TODO: FXME: support all other connections. + + // sample the kbps, get the stat. + SrsKbps* kbps = stat->kbps_sample(); - kbps->add_delta(conn); - - // resample for server. - if (do_resample) { - kbps->sample(); - } + srs_update_rtmp_server((int)conns.size(), kbps); } int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index 62af1e9fa..9a9314c61 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -41,7 +41,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsServer; class SrsConnection; -class SrsGoHttpServeMux; +class SrsHttpServeMux; class SrsHttpServer; class SrsIngester; class SrsHttpHeartbeat; @@ -178,7 +178,7 @@ class SrsServer : virtual public ISrsReloadHandler { private: #ifdef SRS_AUTO_HTTP_API - SrsGoHttpServeMux* http_api_mux; + SrsHttpServeMux* http_api_mux; #endif #ifdef SRS_AUTO_HTTP_SERVER SrsHttpServer* http_stream_mux; @@ -210,10 +210,6 @@ private: */ SrsSignalManager* signal_manager; /** - * server total kbps. - */ - SrsKbps* kbps; - /** * user send the signal, convert to variable. */ bool signal_reload; @@ -236,6 +232,7 @@ public: virtual int initialize_st(); virtual int listen(); virtual int register_signal(); + virtual int http_handle(); virtual int ingest(); virtual int cycle(); // server utility @@ -277,12 +274,9 @@ private: */ virtual void close_listeners(SrsListenerType type); /** - * resample the server kbps. - * if conn is NULL, resample all connections delta, then calc the total kbps. - * @param conn, the connection to do resample the kbps. NULL to resample all connections. - * @param do_resample, whether resample the server kbps. always false when sample a connection. + * resample the server kbs. */ - virtual void resample_kbps(SrsConnection* conn, bool do_resample = true); + virtual void resample_kbps(); // internal only public: /** @@ -316,3 +310,4 @@ public: }; #endif + diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index be129f151..2030ee00d 100644 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -43,6 +43,7 @@ using namespace std; #include #include #include +#include #define CONST_MAX_JITTER_MS 500 #define DEFAULT_FRAME_TIME_MS 40 @@ -714,35 +715,47 @@ ISrsSourceHandler::~ISrsSourceHandler() std::map SrsSource::pool; -int SrsSource::find(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh, SrsSource** pps) +int SrsSource::create(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh, SrsSource** pps) { int ret = ERROR_SUCCESS; string stream_url = r->get_stream_url(); string vhost = r->vhost; - if (pool.find(stream_url) == pool.end()) { - SrsSource* source = new SrsSource(hh); - if ((ret = source->initialize(r, h)) != ERROR_SUCCESS) { - srs_freep(source); - return ret; - } - - pool[stream_url] = source; - srs_info("create new source for url=%s, vhost=%s", - stream_url.c_str(), vhost.c_str()); + // should always not exists for create a source. + srs_assert (pool.find(stream_url) == pool.end()); + + SrsSource* source = new SrsSource(); + if ((ret = source->initialize(r, h, hh)) != ERROR_SUCCESS) { + srs_freep(source); + return ret; } + + pool[stream_url] = source; + srs_info("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); + *pps = source; + + return ret; +} + +SrsSource* SrsSource::fetch(SrsRequest* r) +{ + SrsSource* source = NULL; + + string stream_url = r->get_stream_url(); + if (pool.find(stream_url) == pool.end()) { + return NULL; + } + + source = pool[stream_url]; + // we always update the request of resource, // for origin auth is on, the token in request maybe invalid, // and we only need to update the token of request, it's simple. - if (true) { - SrsSource* source = pool[stream_url]; - source->_req->update_auth(r); - *pps = source; - } - - return ret; + source->_req->update_auth(r); + + return source; } void SrsSource::destroy() @@ -755,17 +768,16 @@ void SrsSource::destroy() pool.clear(); } -SrsSource::SrsSource(ISrsHlsHandler* hh) +SrsSource::SrsSource() { _req = NULL; jitter_algorithm = SrsRtmpJitterAlgorithmOFF; #ifdef SRS_AUTO_HLS - // TODO: FIXME: refine code, use subscriber pattern. - hls = new SrsHls(this, hh); + hls = new SrsHls(); #endif #ifdef SRS_AUTO_DVR - dvr = new SrsDvr(this); + dvr = new SrsDvr(); #endif #ifdef SRS_AUTO_TRANSCODE encoder = new SrsEncoder(); @@ -827,16 +839,26 @@ SrsSource::~SrsSource() srs_freep(_req); } -int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h) +int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh) { int ret = ERROR_SUCCESS; + srs_assert(h); + srs_assert(hh); + srs_assert(!_req); + handler = h; _req = r->copy(); atc = _srs_config->get_atc(_req->vhost); + +#ifdef SRS_AUTO_HLS + if ((ret = hls->initialize(this, hh)) != ERROR_SUCCESS) { + return ret; + } +#endif #ifdef SRS_AUTO_DVR - if ((ret = dvr->initialize(_req)) != ERROR_SUCCESS) { + if ((ret = dvr->initialize(this, _req)) != ERROR_SUCCESS) { return ret; } #endif @@ -1000,7 +1022,7 @@ int SrsSource::on_reload_vhost_dvr(string vhost) dvr->on_unpublish(); // reinitialize the dvr, update plan. - if ((ret = dvr->initialize(_req)) != ERROR_SUCCESS) { + if ((ret = dvr->initialize(this, _req)) != ERROR_SUCCESS) { return ret; } @@ -1364,6 +1386,7 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) // cache the sequence header of aac, or first packet of mp3. // for example, the mp3 is used for hls to write the "right" audio codec. + // TODO: FIXME: to refine the stream info system. bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg.payload, msg.size); if (is_aac_sequence_header || !cache_sh_audio) { srs_freep(cache_sh_audio); @@ -1383,11 +1406,18 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) static int flv_sample_sizes[] = {8, 16, 0}; static int flv_sound_types[] = {1, 2, 0}; + + // when got audio stream info. + SrsStatistic* stat = SrsStatistic::instance(); + if ((ret = stat->on_audio_info(_req, SrsCodecAudioAAC, sample.sound_rate, sample.sound_type, codec.aac_object)) != ERROR_SUCCESS) { + return ret; + } + srs_trace("%dB audio sh, " - "codec(%d, profile=%d, %dchannels, %dkbps, %dHZ), " + "codec(%d, profile=%s, %dchannels, %dkbps, %dHZ), " "flv(%dbits, %dchannels, %dHZ)", msg.size, codec.audio_codec_id, - codec.aac_profile, codec.aac_channels, + srs_codec_aac_object2str(codec.aac_object).c_str(), codec.aac_channels, codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate], flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type], flv_sample_rates[sample.sound_rate]); @@ -1515,10 +1545,17 @@ int SrsSource::on_video(SrsCommonMessage* __video) return ret; } + // when got video stream info. + SrsStatistic* stat = SrsStatistic::instance(); + if ((ret = stat->on_video_info(_req, SrsCodecVideoAVC, codec.avc_profile, codec.avc_level)) != ERROR_SUCCESS) { + return ret; + } + srs_trace("%dB video sh, " - "codec(%d, profile=%d, level=%d, %dx%d, %dkbps, %dfps, %ds)", + "codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %dfps, %ds)", msg.size, codec.video_codec_id, - codec.avc_profile, codec.avc_level, codec.width, codec.height, + srs_codec_avc_profile2str(codec.avc_profile).c_str(), + srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height, codec.video_data_rate / 1000, codec.frame_rate, codec.duration); return ret; } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 54511750f..86401b16b 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -381,7 +381,12 @@ public: * @param hh the event handler for hls. * @param pps the matched source, if success never be NULL. */ - static int find(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh, SrsSource** pps); + static int create(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh, SrsSource** pps); + /** + * get the exists source, NULL when not exists. + * update the request and return the exists source. + */ + static SrsSource* fetch(SrsRequest* r); /** * when system exit, destroy the sources, * for gmc to analysis mem leaks. @@ -451,15 +456,14 @@ private: // the cached audio sequence header. SrsSharedPtrMessage* cache_sh_audio; public: - /** - * @param _req the client request object, - * this object will deep copy it for reload. - */ - SrsSource(ISrsHlsHandler* hh); + SrsSource(); virtual ~SrsSource(); // initialize, get and setter. public: - virtual int initialize(SrsRequest* r, ISrsSourceHandler* h); + /** + * initialize the hls with handlers. + */ + virtual int initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh); // interface ISrsReloadHandler public: virtual int on_reload_vhost_atc(std::string vhost); diff --git a/trunk/src/app/srs_app_st.cpp b/trunk/src/app/srs_app_st.cpp index cac863200..4160f9464 100644 --- a/trunk/src/app/srs_app_st.cpp +++ b/trunk/src/app/srs_app_st.cpp @@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#ifndef SRS_OSX #include bool srs_st_epoll_is_supported(void) { @@ -38,11 +39,13 @@ bool srs_st_epoll_is_supported(void) return (errno != ENOSYS); } +#endif int srs_init_st() { int ret = ERROR_SUCCESS; +#ifndef SRS_OSX // check epoll, some old linux donot support epoll. // @see https://github.com/winlinvip/simple-rtmp-server/issues/162 if (!srs_st_epoll_is_supported()) { @@ -58,6 +61,7 @@ int srs_init_st() return ret; } srs_verbose("st_set_eventsys use linux epoll success"); +#endif if(st_init() != 0){ ret = ERROR_ST_INITIALIZE; diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index e58d547bb..fc7f59c35 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -29,6 +29,8 @@ using namespace std; #include #include +#include +#include int64_t __srs_gvid = getpid(); @@ -40,20 +42,45 @@ int64_t __srs_generate_id() SrsStatisticVhost::SrsStatisticVhost() { id = __srs_generate_id(); + + kbps = new SrsKbps(); + kbps->set_io(NULL, NULL); } SrsStatisticVhost::~SrsStatisticVhost() { + srs_freep(kbps); } SrsStatisticStream::SrsStatisticStream() { id = __srs_generate_id(); vhost = NULL; + + has_video = false; + vcodec = SrsCodecVideoReserved; + avc_profile = SrsAvcProfileReserved; + avc_level = SrsAvcLevelReserved; + + has_audio = false; + acodec = SrsCodecAudioReserved1; + asample_rate = SrsCodecAudioSampleRateReserved; + asound_type = SrsCodecAudioSoundTypeReserved; + aac_object = SrsAacObjectTypeReserved; + + kbps = new SrsKbps(); + kbps->set_io(NULL, NULL); } SrsStatisticStream::~SrsStatisticStream() { + srs_freep(kbps); +} + +void SrsStatisticStream::close() +{ + has_video = false; + has_audio = false; } SrsStatistic* SrsStatistic::_instance = new SrsStatistic(); @@ -61,10 +88,15 @@ SrsStatistic* SrsStatistic::_instance = new SrsStatistic(); SrsStatistic::SrsStatistic() { _server_id = __srs_generate_id(); + + kbps = new SrsKbps(); + kbps->set_io(NULL, NULL); } SrsStatistic::~SrsStatistic() { + srs_freep(kbps); + if (true) { std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { @@ -93,34 +125,54 @@ SrsStatistic* SrsStatistic::instance() return _instance; } +int SrsStatistic::on_video_info(SrsRequest* req, + SrsCodecVideo vcodec, SrsAvcProfile avc_profile, SrsAvcLevel avc_level +) { + int ret = ERROR_SUCCESS; + + SrsStatisticVhost* vhost = create_vhost(req); + SrsStatisticStream* stream = create_stream(vhost, req); + + stream->has_video = true; + stream->vcodec = vcodec; + stream->avc_profile = avc_profile; + stream->avc_level = avc_level; + + return ret; +} + +int SrsStatistic::on_audio_info(SrsRequest* req, + SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type, + SrsAacObjectType aac_object +) { + int ret = ERROR_SUCCESS; + + SrsStatisticVhost* vhost = create_vhost(req); + SrsStatisticStream* stream = create_stream(vhost, req); + + stream->has_audio = true; + stream->acodec = acodec; + stream->asample_rate = asample_rate; + stream->asound_type = asound_type; + stream->aac_object = aac_object; + + return ret; +} + +void SrsStatistic::on_stream_close(SrsRequest* req) +{ + SrsStatisticVhost* vhost = create_vhost(req); + SrsStatisticStream* stream = create_stream(vhost, req); + + stream->close(); +} + int SrsStatistic::on_client(int id, SrsRequest* req) { int ret = ERROR_SUCCESS; - // create vhost if not exists. - SrsStatisticVhost* vhost = NULL; - if (vhosts.find(req->vhost) == vhosts.end()) { - vhost = new SrsStatisticVhost(); - vhost->vhost = req->vhost; - vhosts[req->vhost] = vhost; - } else { - vhost = vhosts[req->vhost]; - } - - // the url to identify the stream. - std::string url = req->get_stream_url(); - - // create stream if not exists. - SrsStatisticStream* stream = NULL; - if (streams.find(url) == streams.end()) { - stream = new SrsStatisticStream(); - stream->vhost = vhost; - stream->stream = req->stream; - stream->url = url; - streams[url] = stream; - } else { - stream = streams[url]; - } + SrsStatisticVhost* vhost = create_vhost(req); + SrsStatisticStream* stream = create_stream(vhost, req); // create client if not exists SrsStatisticClient* client = NULL; @@ -135,7 +187,7 @@ int SrsStatistic::on_client(int id, SrsRequest* req) return ret; } -void SrsStatistic::on_close(int id) +void SrsStatistic::on_disconnect(int id) { std::map::iterator it; it = clients.find(id); @@ -146,6 +198,49 @@ void SrsStatistic::on_close(int id) } } +void SrsStatistic::kbps_add_delta(SrsConnection* conn) +{ + int id = conn->srs_id(); + if (clients.find(id) == clients.end()) { + return; + } + + SrsStatisticClient* client = clients[id]; + + // resample the kbps to collect the delta. + conn->resample(); + + // add delta of connection to kbps. + // for next sample() of server kbps can get the stat. + kbps->add_delta(conn); + client->stream->kbps->add_delta(conn); + client->stream->vhost->kbps->add_delta(conn); + + // cleanup the delta. + conn->cleanup(); +} + +SrsKbps* SrsStatistic::kbps_sample() +{ + kbps->sample(); + if (true) { + std::map::iterator it; + for (it = vhosts.begin(); it != vhosts.end(); it++) { + SrsStatisticVhost* vhost = it->second; + vhost->kbps->sample(); + } + } + if (true) { + std::map::iterator it; + for (it = streams.begin(); it != streams.end(); it++) { + SrsStatisticStream* stream = it->second; + stream->kbps->sample(); + } + } + + return kbps; +} + int64_t SrsStatistic::server_id() { return _server_id; @@ -165,7 +260,9 @@ int SrsStatistic::dumps_vhosts(stringstream& ss) ss << __SRS_JOBJECT_START << __SRS_JFIELD_ORG("id", vhost->id) << __SRS_JFIELD_CONT - << __SRS_JFIELD_STR("name", vhost->vhost) + << __SRS_JFIELD_STR("name", vhost->vhost) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("send_bytes", vhost->kbps->get_send_bytes()) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("recv_bytes", vhost->kbps->get_recv_bytes()) << __SRS_JOBJECT_END; } ss << __SRS_JARRAY_END; @@ -198,10 +295,76 @@ int SrsStatistic::dumps_streams(stringstream& ss) << __SRS_JFIELD_ORG("id", stream->id) << __SRS_JFIELD_CONT << __SRS_JFIELD_STR("name", stream->stream) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("vhost", stream->vhost->id) << __SRS_JFIELD_CONT - << __SRS_JFIELD_ORG("clients", client_num) - << __SRS_JOBJECT_END; + << __SRS_JFIELD_ORG("clients", client_num) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("send_bytes", stream->kbps->get_send_bytes()) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("recv_bytes", stream->kbps->get_recv_bytes()) << __SRS_JFIELD_CONT; + + if (!stream->has_video) { + ss << __SRS_JFIELD_NULL("video") << __SRS_JFIELD_CONT; + } else { + ss << __SRS_JFIELD_NAME("video") + << __SRS_JOBJECT_START + << __SRS_JFIELD_STR("codec", srs_codec_video2str(stream->vcodec)) << __SRS_JFIELD_CONT + << __SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(stream->avc_profile)) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("level", srs_codec_avc_level2str(stream->avc_level)) + << __SRS_JOBJECT_END + << __SRS_JFIELD_CONT; + } + + if (!stream->has_audio) { + ss << __SRS_JFIELD_NULL("audio"); + } else { + ss << __SRS_JFIELD_NAME("audio") + << __SRS_JOBJECT_START + << __SRS_JFIELD_STR("codec", srs_codec_audio2str(stream->acodec)) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[stream->asample_rate]) << __SRS_JFIELD_CONT + << __SRS_JFIELD_ORG("channel", (int)stream->asound_type + 1) << __SRS_JFIELD_CONT + << __SRS_JFIELD_STR("profile", srs_codec_aac_object2str(stream->aac_object)) + << __SRS_JOBJECT_END; + } + + ss << __SRS_JOBJECT_END; } ss << __SRS_JARRAY_END; return ret; } + +SrsStatisticVhost* SrsStatistic::create_vhost(SrsRequest* req) +{ + SrsStatisticVhost* vhost = NULL; + + // create vhost if not exists. + if (vhosts.find(req->vhost) == vhosts.end()) { + vhost = new SrsStatisticVhost(); + vhost->vhost = req->vhost; + vhosts[req->vhost] = vhost; + return vhost; + } + + vhost = vhosts[req->vhost]; + + return vhost; +} + +SrsStatisticStream* SrsStatistic::create_stream(SrsStatisticVhost* vhost, SrsRequest* req) +{ + std::string url = req->get_stream_url(); + + SrsStatisticStream* stream = NULL; + + // create stream if not exists. + if (streams.find(url) == streams.end()) { + stream = new SrsStatisticStream(); + stream->vhost = vhost; + stream->stream = req->stream; + stream->url = url; + streams[url] = stream; + return stream; + } + + stream = streams[url]; + + return stream; +} + diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 0e3c5aa89..1451e3252 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -33,13 +33,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include + +class SrsKbps; class SrsRequest; +class SrsConnection; struct SrsStatisticVhost { public: int64_t id; std::string vhost; +public: + /** + * vhost total kbps. + */ + SrsKbps* kbps; public: SrsStatisticVhost(); virtual ~SrsStatisticVhost(); @@ -53,9 +62,38 @@ public: std::string app; std::string stream; std::string url; +public: + /** + * stream total kbps. + */ + SrsKbps* kbps; +public: + bool has_video; + SrsCodecVideo vcodec; + // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + SrsAvcProfile avc_profile; + // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + SrsAvcLevel avc_level; +public: + bool has_audio; + SrsCodecAudio acodec; + SrsCodecAudioSampleRate asample_rate; + SrsCodecAudioSoundType asound_type; + /** + * audio specified + * audioObjectType, in 1.6.2.1 AudioSpecificConfig, page 33, + * 1.5.1.1 Audio object type definition, page 23, + * in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf. + */ + SrsAacObjectType aac_object; public: SrsStatisticStream(); virtual ~SrsStatisticStream(); +public: + /** + * close the stream. + */ + virtual void close(); }; struct SrsStatisticClient @@ -73,15 +111,35 @@ private: int64_t _server_id; // key: vhost name, value: vhost object. std::map vhosts; - // key: stream name, value: stream object. + // key: stream url, value: stream object. std::map streams; // key: client id, value: stream object. std::map clients; + // server total kbps. + SrsKbps* kbps; private: SrsStatistic(); virtual ~SrsStatistic(); public: static SrsStatistic* instance(); +public: + /** + * when got video info for stream. + */ + virtual int on_video_info(SrsRequest* req, + SrsCodecVideo vcodec, SrsAvcProfile avc_profile, SrsAvcLevel avc_level + ); + /** + * when got audio info for stream. + */ + virtual int on_audio_info(SrsRequest* req, + SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type, + SrsAacObjectType aac_object + ); + /** + * when close stream. + */ + virtual void on_stream_close(SrsRequest* req); public: /** * when got a client to publish/play stream, @@ -90,9 +148,19 @@ public: */ virtual int on_client(int id, SrsRequest* req); /** - * client close + * client disconnect */ - virtual void on_close(int id); + virtual void on_disconnect(int id); + /** + * sample the kbps, add delta bytes of conn. + * use kbps_sample() to get all result of kbps stat. + */ + virtual void kbps_add_delta(SrsConnection* conn); + /** + * calc the result for all kbps. + * @return the server kbps. + */ + virtual SrsKbps* kbps_sample(); public: /** * get the server id, used to identify the server. @@ -107,6 +175,9 @@ public: * dumps the streams to sstream in json. */ virtual int dumps_streams(std::stringstream& ss); +private: + virtual SrsStatisticVhost* create_vhost(SrsRequest* req); + virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req); }; #endif diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index 3af39035a..66c4525fa 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -1119,9 +1119,7 @@ void srs_api_dump_summaries(std::stringstream& ss) << __SRS_JFIELD_ORG("net_send_bytes", ns_bytes) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("srs_sample_time", nrs->sample_time) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("srs_recv_bytes", nrs->rbytes) << __SRS_JFIELD_CONT - << __SRS_JFIELD_ORG("srs_recv_kbps", nrs->rkbps) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("srs_send_bytes", nrs->sbytes) << __SRS_JFIELD_CONT - << __SRS_JFIELD_ORG("srs_send_kbps", nrs->skbps) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("conn_sys", nrs->nb_conn_sys) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("conn_sys_et", nrs->nb_conn_sys_et) << __SRS_JFIELD_CONT << __SRS_JFIELD_ORG("conn_sys_tw", nrs->nb_conn_sys_tw) << __SRS_JFIELD_CONT diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 8d14c1b11..1ee018e04 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 124 +#define VERSION_REVISION 137 // server info. #define RTMP_SIG_SRS_KEY "SRS" @@ -88,6 +88,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // generated by configure. #include +// important performance options. +#include // free the p and set to NULL. // p must be a T*. diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index edc82cd7c..4cd65e3d9 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -108,7 +108,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * whether set the socket send buffer size. * @see https://github.com/winlinvip/simple-rtmp-server/issues/251 */ -#undef SRS_PERF_MW_SO_SNDBUF +#define SRS_PERF_MW_SO_SNDBUF + /** * whether set the socket recv buffer size. * @see https://github.com/winlinvip/simple-rtmp-server/issues/251 @@ -154,5 +155,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // in seconds, the live queue length. #define SRS_PERF_PLAY_QUEUE 30 +/** +* whether always use complex send algorithm. +* for some network does not support the complex send, +* @see https://github.com/winlinvip/simple-rtmp-server/issues/320 +*/ +//#undef SRS_PERF_COMPLEX_SEND +#define SRS_PERF_COMPLEX_SEND +/** +* whether enable the TCP_NODELAY +* user maybe need send small tcp packet for some network. +* @see https://github.com/winlinvip/simple-rtmp-server/issues/320 +*/ +//#define SRS_PERF_TCP_NODELAY +#undef SRS_PERF_TCP_NODELAY +/** +* set the socket send buffer, +* to force the server to send smaller tcp packet. +* @see https://github.com/winlinvip/simple-rtmp-server/issues/320 +* @remark undef it to auto calc it by merged write sleep ms. +* @remark only apply it when SRS_PERF_MW_SO_RCVBUF is defined. +*/ +#ifdef SRS_PERF_MW_SO_SNDBUF + //#define SRS_PERF_SO_SNDBUF_SIZE 1024 + #undef SRS_PERF_SO_SNDBUF_SIZE +#endif + #endif diff --git a/trunk/src/kernel/srs_kernel_aac.cpp b/trunk/src/kernel/srs_kernel_aac.cpp index 80ec3d9d3..18193fbe1 100644 --- a/trunk/src/kernel/srs_kernel_aac.cpp +++ b/trunk/src/kernel/srs_kernel_aac.cpp @@ -43,6 +43,7 @@ SrsAacEncoder::SrsAacEncoder() _fs = NULL; got_sequence_header = false; tag_stream = new SrsStream(); + aac_object = SrsAacObjectTypeReserved; } SrsAacEncoder::~SrsAacEncoder() @@ -114,7 +115,7 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size) // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. // // only need to decode the first 2bytes: - // audioObjectType, aac_profile, 5bits. + // audioObjectType, 5bits. // samplingFrequencyIndex, aac_sample_rate, 4bits. // channelConfiguration, aac_channels, 4bits if (!stream->require(2)) { @@ -123,12 +124,14 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size) return ret; } - aac_profile = stream->read_1bytes(); + int8_t audioObjectType = stream->read_1bytes(); aac_sample_rate = stream->read_1bytes(); aac_channels = (aac_sample_rate >> 3) & 0x0f; - aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); - aac_profile = (aac_profile >> 3) & 0x1f; + aac_sample_rate = ((audioObjectType << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); + + audioObjectType = (audioObjectType >> 3) & 0x1f; + aac_object = (SrsAacObjectType)audioObjectType; got_sequence_header = true; @@ -177,16 +180,14 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size) // protection_absent 1 bslbf *pp++ = 0xf1; - // Profile_ObjectType 2 uimsbf + // profile 2 uimsbf // sampling_frequency_index 4 uimsbf // private_bit 1 bslbf // channel_configuration 3 uimsbf // original/copy 1 bslbf // home 1 bslbf - int8_t fh_Profile_ObjectType = aac_profile - 1; - *pp++ = ((fh_Profile_ObjectType << 6) & 0xc0) | ((aac_sample_rate << 2) & 0x3c) | ((aac_channels >> 2) & 0x01); - // @remark, Emphasis is removed, - // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736 + SrsAacProfile aac_profile = srs_codec_aac_rtmp2ts(aac_object); + *pp++ = ((aac_profile << 6) & 0xc0) | ((aac_sample_rate << 2) & 0x3c) | ((aac_channels >> 2) & 0x01); // 4bits left. // adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS // copyright_identification_bit 1 bslbf diff --git a/trunk/src/kernel/srs_kernel_aac.hpp b/trunk/src/kernel/srs_kernel_aac.hpp index f4fddf545..e29ce9f17 100644 --- a/trunk/src/kernel/srs_kernel_aac.hpp +++ b/trunk/src/kernel/srs_kernel_aac.hpp @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + class SrsStream; class SrsFileWriter; class SrsFileReader; @@ -43,7 +45,7 @@ class SrsAacEncoder private: SrsFileWriter* _fs; private: - int8_t aac_profile; + SrsAacObjectType aac_object; int8_t aac_sample_rate; int8_t aac_channels; bool got_sequence_header; diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 90512b06e..5d6d6dda5 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -32,6 +32,154 @@ using namespace std; #include #include +string srs_codec_video2str(SrsCodecVideo codec) +{ + switch (codec) { + case SrsCodecVideoAVC: + return "H264"; + case SrsCodecVideoOn2VP6: + case SrsCodecVideoOn2VP6WithAlphaChannel: + return "VP6"; + case SrsCodecVideoReserved: + case SrsCodecVideoReserved1: + case SrsCodecVideoReserved2: + case SrsCodecVideoDisabled: + case SrsCodecVideoSorensonH263: + case SrsCodecVideoScreenVideo: + case SrsCodecVideoScreenVideoVersion2: + default: + return "Other"; + } +} + +string srs_codec_audio2str(SrsCodecAudio codec) +{ + switch (codec) { + case SrsCodecAudioAAC: + return "AAC"; + case SrsCodecAudioMP3: + return "MP3"; + case SrsCodecAudioReserved1: + case SrsCodecAudioLinearPCMPlatformEndian: + case SrsCodecAudioADPCM: + case SrsCodecAudioLinearPCMLittleEndian: + case SrsCodecAudioNellymoser16kHzMono: + case SrsCodecAudioNellymoser8kHzMono: + case SrsCodecAudioNellymoser: + case SrsCodecAudioReservedG711AlawLogarithmicPCM: + case SrsCodecAudioReservedG711MuLawLogarithmicPCM: + case SrsCodecAudioReserved: + case SrsCodecAudioSpeex: + case SrsCodecAudioReservedMP3_8kHz: + case SrsCodecAudioReservedDeviceSpecificSound: + default: + return "Other"; + } +} + +string srs_codec_aac_profile2str(SrsAacProfile aac_profile) +{ + switch (aac_profile) { + case SrsAacProfileMain: return "Main"; + case SrsAacProfileLC: return "LC"; + case SrsAacProfileSSR: return "SSR"; + default: return "Other"; + } +} + +string srs_codec_aac_object2str(SrsAacObjectType aac_object) +{ + switch (aac_object) { + case SrsAacObjectTypeAacMain: return "Main"; + case SrsAacObjectTypeHE: return "HE"; + case SrsAacObjectTypeHEV2: return "HEv2"; + case SrsAacObjectTypeAacLC: return "LC"; + case SrsAacObjectTypeAacSSR: return "SSR"; + default: return "Other"; + } +} + +SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile) +{ + switch (profile) { + case SrsAacProfileMain: return SrsAacObjectTypeAacMain; + case SrsAacProfileLC: return SrsAacObjectTypeAacLC; + case SrsAacProfileSSR: return SrsAacObjectTypeAacSSR; + default: return SrsAacObjectTypeReserved; + } +} + +SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type) +{ + switch (object_type) { + case SrsAacObjectTypeAacMain: return SrsAacProfileMain; + case SrsAacObjectTypeHE: + case SrsAacObjectTypeHEV2: + case SrsAacObjectTypeAacLC: return SrsAacProfileLC; + case SrsAacObjectTypeAacSSR: return SrsAacProfileSSR; + default: return SrsAacProfileReserved; + } +} + +string srs_codec_avc_profile2str(SrsAvcProfile profile) +{ + switch (profile) { + case SrsAvcProfileBaseline: return "Baseline"; + case SrsAvcProfileConstrainedBaseline: return "Baseline(Constrained)"; + case SrsAvcProfileMain: return "Main"; + case SrsAvcProfileExtended: return "Extended"; + case SrsAvcProfileHigh: return "High"; + case SrsAvcProfileHigh10: return "High(10)"; + case SrsAvcProfileHigh10Intra: return "High(10+Intra)"; + case SrsAvcProfileHigh422: return "High(422)"; + case SrsAvcProfileHigh422Intra: return "High(422+Intra)"; + case SrsAvcProfileHigh444: return "High(444)"; + case SrsAvcProfileHigh444Predictive: return "High(444+Predictive)"; + case SrsAvcProfileHigh444Intra: return "High(444+Intra)"; + default: return "Other"; + } +} + +string srs_codec_avc_level2str(SrsAvcLevel level) +{ + switch (level) { + case SrsAvcLevel_1: return "1"; + case SrsAvcLevel_11: return "1.1"; + case SrsAvcLevel_12: return "1.2"; + case SrsAvcLevel_13: return "1.3"; + case SrsAvcLevel_2: return "2"; + case SrsAvcLevel_21: return "2.1"; + case SrsAvcLevel_22: return "2.2"; + case SrsAvcLevel_3: return "3"; + case SrsAvcLevel_31: return "3.1"; + case SrsAvcLevel_32: return "3.2"; + case SrsAvcLevel_4: return "4"; + case SrsAvcLevel_41: return "4.1"; + case SrsAvcLevel_5: return "5"; + case SrsAvcLevel_51: return "5.1"; + default: return "Other"; + } +} + +/** +* the public data, event HLS disable, others can use it. +*/ +// 0 = 5.5 kHz = 5512 Hz +// 1 = 11 kHz = 11025 Hz +// 2 = 22 kHz = 22050 Hz +// 3 = 44 kHz = 44100 Hz +int flv_sample_rates[] = {5512, 11025, 22050, 44100}; + +// the sample rates in the codec, +// in the sequence header. +int aac_sample_rates[] = +{ + 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 +}; + SrsFlvCodec::SrsFlvCodec() { } @@ -184,9 +332,9 @@ SrsAvcAacCodec::SrsAvcAacCodec() audio_data_rate = 0; audio_codec_id = 0; - avc_profile = 0; - avc_level = 0; - aac_profile = 0; + avc_profile = SrsAvcProfileReserved; + avc_level = SrsAvcLevelReserved; + aac_object = SrsAacObjectTypeReserved; aac_sample_rate = __SRS_AAC_SAMPLE_RATE_UNSET; // sample rate ignored aac_channels = 0; avc_extra_size = 0; @@ -384,20 +532,9 @@ int SrsAvcAacCodec::audio_aac_sequence_header_demux(char* data, int size) // set the aac sample rate. aac_sample_rate = samplingFrequencyIndex; - // the profile = object_id + 1 - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, - // Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types - aac_profile = profile_ObjectType + 1; - - // the valid aac profile: - // MPEG-2 profile - // Main profile (ID == 1) - // Low Complexity profile (LC) (ID == 2) - // Scalable Sampling Rate profile (SSR) (ID == 3) - // (reserved) (ID == 4) - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, - // Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types - if (aac_profile > 4) { + // convert the object type in sequence header to aac profile of ADTS. + aac_object = (SrsAacObjectType)profile_ObjectType; + if (aac_object == SrsAacObjectTypeReserved) { ret = ERROR_HLS_DECODE_ERROR; srs_error("audio codec decode aac sequence header failed, " "adts object=%d invalid. ret=%d", profile_ObjectType, ret); @@ -554,11 +691,11 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) //int8_t configurationVersion = stream->read_1bytes(); stream->read_1bytes(); //int8_t AVCProfileIndication = stream->read_1bytes(); - avc_profile = stream->read_1bytes(); + avc_profile = (SrsAvcProfile)stream->read_1bytes(); //int8_t profile_compatibility = stream->read_1bytes(); stream->read_1bytes(); //int8_t AVCLevelIndication = stream->read_1bytes(); - avc_level = stream->read_1bytes(); + avc_level = (SrsAvcLevel)stream->read_1bytes(); // parse the NALU size. int8_t lengthSizeMinusOne = stream->read_1bytes(); diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 34604a6a1..1739792d9 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -110,6 +110,7 @@ enum SrsCodecVideo SrsCodecVideoScreenVideoVersion2 = 6, SrsCodecVideoAVC = 7, }; +std::string srs_codec_video2str(SrsCodecVideo codec); // SoundFormat UB [4] // Format of SoundData. The following values are defined: @@ -150,6 +151,7 @@ enum SrsCodecAudio SrsCodecAudioReservedMP3_8kHz = 14, SrsCodecAudioReservedDeviceSpecificSound = 15, }; +std::string srs_codec_audio2str(SrsCodecAudio codec); /** * the FLV/RTMP supported audio sample rate. @@ -373,6 +375,98 @@ enum SrsAvcPayloadFormat SrsAvcPayloadFormatIbmf, }; +/** +* the aac profile, for ADTS(HLS/TS) +* @see https://github.com/winlinvip/simple-rtmp-server/issues/310 +*/ +enum SrsAacProfile +{ + SrsAacProfileReserved = 3, + + // @see 7.1 Profiles, aac-iso-13818-7.pdf, page 40 + SrsAacProfileMain = 0, + SrsAacProfileLC = 1, + SrsAacProfileSSR = 2, +}; +std::string srs_codec_aac_profile2str(SrsAacProfile aac_profile); + +/** +* the aac object type, for RTMP sequence header +* for AudioSpecificConfig, @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33 +* for audioObjectType, @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23 +*/ +enum SrsAacObjectType +{ + SrsAacObjectTypeReserved = 0, + + // Table 1.1 – Audio Object Type definition + // @see @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23 + SrsAacObjectTypeAacMain = 1, + SrsAacObjectTypeAacLC = 2, + SrsAacObjectTypeAacSSR = 3, + + // AAC HE = LC+SBR + SrsAacObjectTypeHE = 5, + // AAC HEv2 = LC+SBR+PS + SrsAacObjectTypeHEV2 = 29, +}; +std::string srs_codec_aac_object2str(SrsAacObjectType aac_object); +// ts/hls/adts audio header profile to RTMP sequence header object type. +SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile); +// RTMP sequence header object type to ts/hls/adts audio header profile. +SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type); + +/** +* the profile for avc/h.264. +* @see Annex A Profiles and levels, H.264-AVC-ISO_IEC_14496-10.pdf, page 205. +*/ +enum SrsAvcProfile +{ + SrsAvcProfileReserved = 0, + + // @see ffmpeg, libavcodec/avcodec.h:2713 + SrsAvcProfileBaseline = 66, + // FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag + // FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) + SrsAvcProfileConstrainedBaseline = 578, + SrsAvcProfileMain = 77, + SrsAvcProfileExtended = 88, + SrsAvcProfileHigh = 100, + SrsAvcProfileHigh10 = 110, + SrsAvcProfileHigh10Intra = 2158, + SrsAvcProfileHigh422 = 122, + SrsAvcProfileHigh422Intra = 2170, + SrsAvcProfileHigh444 = 144, + SrsAvcProfileHigh444Predictive = 244, + SrsAvcProfileHigh444Intra = 2192, +}; +std::string srs_codec_avc_profile2str(SrsAvcProfile profile); + +/** +* the level for avc/h.264. +* @see Annex A Profiles and levels, H.264-AVC-ISO_IEC_14496-10.pdf, page 207. +*/ +enum SrsAvcLevel +{ + SrsAvcLevelReserved = 0, + + SrsAvcLevel_1 = 10, + SrsAvcLevel_11 = 11, + SrsAvcLevel_12 = 12, + SrsAvcLevel_13 = 13, + SrsAvcLevel_2 = 20, + SrsAvcLevel_21 = 21, + SrsAvcLevel_22 = 22, + SrsAvcLevel_3 = 30, + SrsAvcLevel_31 = 31, + SrsAvcLevel_32 = 32, + SrsAvcLevel_4 = 40, + SrsAvcLevel_41 = 41, + SrsAvcLevel_5 = 50, + SrsAvcLevel_51 = 51, +}; +std::string srs_codec_avc_level2str(SrsAvcLevel level); + /** * the h264/avc and aac codec, for media stream. * @@ -410,9 +504,9 @@ public: * video specified */ // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_profile; + SrsAvcProfile avc_profile; // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_level; + SrsAvcLevel avc_level; // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 int8_t NAL_unit_length; u_int16_t sequenceParameterSetLength; @@ -429,7 +523,7 @@ public: * 1.5.1.1 Audio object type definition, page 23, * in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf. */ - u_int8_t aac_profile; + SrsAacObjectType aac_object; /** * samplingFrequencyIndex */ diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 7f0223cd6..8d87eae1f 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -213,13 +213,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_HTTP_DVR_REQUEST 3051 #define ERROR_HTTP_JSON_REQUIRED 3052 #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 +#define ERROR_HTTP_DVR_NO_TAEGET 3054 +#define ERROR_ADTS_ID_NOT_AAC 3055 + // HDS error code -#define ERROR_HDS_OPEN_F4M_FAILED 3054 -#define ERROR_HDS_WRITE_F4M_FAILED 3055 -#define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3056 -#define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3057 -#define ERROR_HDS_OPEN_FRAGMENT_FAILED 3058 -#define ERROR_HDS_WRITE_FRAGMENT_FAILED 3059 +#define ERROR_HDS_OPEN_F4M_FAILED 3056 +#define ERROR_HDS_WRITE_F4M_FAILED 3057 +#define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3058 +#define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3059 +#define ERROR_HDS_OPEN_FRAGMENT_FAILED 3060 +#define ERROR_HDS_WRITE_FRAGMENT_FAILED 3061 /////////////////////////////////////////////////////// // HTTP/StreamCaster protocol error. @@ -249,6 +252,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_STREAM_CASTER_AVC_SPS 4022 #define ERROR_STREAM_CASTER_AVC_PPS 4023 #define ERROR_STREAM_CASTER_FLV_TAG 4024 +#define ERROR_HTTP_RESPONSE_EOF 4025 +#define ERROR_HTTP_INVALID_CHUNK_HEADER 4026 + +/////////////////////////////////////////////////////// +// user-define error. +/////////////////////////////////////////////////////// +#define ERROR_USER_START 9000 +#define ERROR_USER_END 9999 /** * whether the error code is an system control error. diff --git a/trunk/src/kernel/srs_kernel_file.hpp b/trunk/src/kernel/srs_kernel_file.hpp index 53a9f0e62..da7a83b50 100644 --- a/trunk/src/kernel/srs_kernel_file.hpp +++ b/trunk/src/kernel/srs_kernel_file.hpp @@ -82,6 +82,7 @@ public: virtual int open(std::string file); virtual void close(); public: + // TODO: FIXME: extract interface. virtual bool is_open(); virtual int64_t tellg(); virtual void skip(int64_t size); diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 13e923ef5..4d1464ad9 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -36,6 +36,7 @@ using namespace std; #include #include #include +#include #define SRS_FLV_TAG_HEADER_SIZE 11 #define SRS_FLV_PREVIOUS_TAG_SIZE 4 @@ -149,7 +150,7 @@ int SrsFlvEncoder::write_audio(int64_t timestamp, char* data, int size) // 11bytes tag header static char tag_header[] = { - (char)8, // TagType UB [5], 8 = audio + (char)SrsCodecFlvTagAudio, // TagType UB [5], 8 = audio (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. (char)0x00, // TimestampExtended UI8 @@ -183,7 +184,7 @@ int SrsFlvEncoder::write_video(int64_t timestamp, char* data, int size) // 11bytes tag header static char tag_header[] = { - (char)9, // TagType UB [5], 9 = video + (char)SrsCodecFlvTagVideo, // TagType UB [5], 9 = video (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. (char)0x00, // TimestampExtended UI8 diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 52a30837f..957bfc63b 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -67,6 +67,7 @@ public: /** * write flv metadata. * @param type, the type of data, or other message type. + * @see SrsCodecFlvTag * @param data, the amf0 metadata which serialize from: * AMF0 string: onMetaData, * AMF0 object: the metadata object. diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index e5449df4b..414dd47ac 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -56,25 +56,6 @@ using namespace std; #define TS_AUDIO_AAC_PID 0x102 #define TS_AUDIO_MP3_PID 0x103 -/** -* the public data, event HLS disable, others can use it. -*/ -// 0 = 5.5 kHz = 5512 Hz -// 1 = 11 kHz = 11025 Hz -// 2 = 22 kHz = 22050 Hz -// 3 = 44 kHz = 44100 Hz -int flv_sample_rates[] = {5512, 11025, 22050, 44100}; - -// the sample rates in the codec, -// in the sequence header. -int aac_sample_rates[] = -{ - 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 -}; - string srs_ts_stream2string(SrsTsStream stream) { switch (stream) { @@ -1130,7 +1111,7 @@ int SrsTsAdaptationField::encode(SrsStream* stream) // @see https://github.com/winlinvip/simple-rtmp-server/issues/250#issuecomment-71349370 int64_t pcrv = program_clock_reference_extension & 0x1ff; pcrv |= (const1_value0 << 9) & 0x7E00; - pcrv |= (program_clock_reference_base << 15) & 0x1FFFFFFFF000000; + pcrv |= (program_clock_reference_base << 15) & 0x1FFFFFFFF000000LL; pp = (char*)&pcrv; *p++ = pp[5]; @@ -2783,20 +2764,6 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample) srs_error("invalid aac frame length=%d, ret=%d", size, ret); return ret; } - - // the profile = object_id + 1 - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, - // Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types - // the valid object type: - // AAC Main(ID == 0) - // AAC LC(ID == 1) - // AAC SSR(ID == 2) - // AAC LTP(ID == 3) - u_int8_t profile_ObjectType = codec->aac_profile - 1; - - // TODO: FIXME: only support Main or LC. - // @see https://github.com/winlinvip/simple-rtmp-server/issues/310 - profile_ObjectType = srs_min(1, profile_ObjectType); // the frame length is the AAC raw data plus the adts header size. int32_t frame_length = size + 7; @@ -2805,12 +2772,12 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample) // 6.2 Audio Data Transport Stream, ADTS // in aac-iso-13818-7.pdf, page 26. // fixed 7bytes header - static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc}; + static u_int8_t adts_header[7] = {0xff, 0xf9, 0x00, 0x00, 0x00, 0x0f, 0xfc}; /* // adts_fixed_header // 2B, 16bits int16_t syncword; //12bits, '1111 1111 1111' - int8_t ID; //1bit, '0' + int8_t ID; //1bit, '1' int8_t layer; //2bits, '00' int8_t protection_absent; //1bit, can be '1' // 12bits @@ -2830,7 +2797,8 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample) int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block() */ // profile, 2bits - adts_header[2] = (profile_ObjectType << 6) & 0xc0; + SrsAacProfile aac_profile = srs_codec_aac_rtmp2ts(codec->aac_object); + adts_header[2] = (aac_profile << 6) & 0xc0; // sampling_frequency_index 4bits adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c; // channel_configuration 3bits diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 3a2eeebda..e725c722f 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -437,7 +437,9 @@ u_int32_t srs_crc32(const void* buf, int size) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef UINT_MAX #define UINT_MAX 0xffffffff +#endif #ifndef AV_RB32 # define AV_RB32(x) \ diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index d0ead523c..bb6ded30d 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -148,6 +148,24 @@ void show_macro_features() srs_trace("MW(merged-write) default sleep %d", SRS_PERF_MW_SLEEP); srs_trace("read chunk stream cache cid [0, %d)", SRS_PERF_CHUNK_STREAM_CACHE); srs_trace("default gop cache %d, play queue %ds", SRS_PERF_GOP_CACHE, SRS_PERF_PLAY_QUEUE); + +#ifndef SRS_PERF_COMPLEX_SEND + srs_warn("complex send algorithm disabled."); +#else + srs_trace("complex send algorithm enabled."); +#endif + +#ifdef SRS_PERF_TCP_NODELAY + srs_warn("TCP_NODELAY enabled, hurts performance."); +#else + srs_trace("TCP_NODELAY disabled."); +#endif + +#ifdef SRS_PERF_SO_SNDBUF_SIZE + srs_warn("socket send buffer size %d", SRS_PERF_SO_SNDBUF_SIZE); +#else + srs_trace("auto guess socket send buffer by merged write"); +#endif int possible_mr_latency = 0; #ifdef SRS_PERF_MERGED_READ @@ -159,6 +177,23 @@ void show_macro_features() void check_macro_features() { + // important preset. +#ifdef SRS_OSX + srs_trace("SRS for OSX"); +#endif +#ifdef SRS_PI + srs_trace("SRS for pi"); +#endif +#ifdef SRS_CUBIE + srs_trace("SRS for cubieboard"); +#endif +#ifdef SRS_ARM_UBUNTU12 + srs_trace("SRS for arm(build on ubuntu)"); +#endif +#ifdef SRS_MIPS_UBUNTU12 + srs_trace("SRS for mips(build on ubuntu)"); +#endif + // for special features. #ifndef SRS_PERF_MERGED_READ srs_warn("MR(merged-read) is disabled, hurts read performance. @see %s", RTMP_SIG_SRS_ISSUES(241)); @@ -170,6 +205,15 @@ void check_macro_features() #warning "using develop SRS, please use release instead." srs_warn("SRS %s is develop branch, please use %s instead", RTMP_SIG_SRS_VERSION, RTMP_SIG_SRS_RELEASE); #endif + +#if defined(SRS_AUTO_STREAM_CASTER) + #warning "stream caster is experiment feature." + srs_warn("stream caster is experiment feature."); +#endif + +#if defined(SRS_PERF_SO_SNDBUF_SIZE) && !defined(SRS_PERF_MW_SO_SNDBUF) + #error "SRS_PERF_SO_SNDBUF_SIZE depends on SRS_PERF_MW_SO_SNDBUF" +#endif } /** @@ -230,8 +274,8 @@ int main(int argc, char** argv) srs_trace("conf: %s, limit: %d", _srs_config->config().c_str(), _srs_config->get_max_connections()); // features - show_macro_features(); check_macro_features(); + show_macro_features(); /** * we do nothing in the constructor of server, @@ -314,6 +358,10 @@ int run_master() return ret; } + if ((ret = _srs_server->http_handle()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = _srs_server->ingest()) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/protocol/srs_raw_avc.cpp b/trunk/src/protocol/srs_raw_avc.cpp index 143ea6fa3..e25b6c5c7 100644 --- a/trunk/src/protocol/srs_raw_avc.cpp +++ b/trunk/src/protocol/srs_raw_avc.cpp @@ -329,8 +329,8 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame int adts_header_start = stream->pos(); // decode the ADTS. - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, - // 1.A.2.2 Audio_Data_Transport_Stream frame, ADTS + // @see aac-iso-13818-7.pdf, page 26 + // 6.2 Audio Data Transport Stream, ADTS // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64145885 // byte_alignment() @@ -356,55 +356,63 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame return ERROR_AAC_REQUIRED_ADTS; } - // Syncword 12 bslbf + // syncword 12 bslbf stream->read_1bytes(); // 4bits left. // adts_fixed_header(), 1.A.2.2.1 Fixed Header of ADTS // ID 1 bslbf - // Layer 2 uimsbf + // layer 2 uimsbf // protection_absent 1 bslbf - int8_t fh0 = (stream->read_1bytes() & 0x0f); - /*int8_t fh_id = (fh0 >> 3) & 0x01;*/ - /*int8_t fh_layer = (fh0 >> 1) & 0x03;*/ - int8_t fh_protection_absent = fh0 & 0x01; + int8_t pav = (stream->read_1bytes() & 0x0f); + int8_t id = (pav >> 3) & 0x01; + /*int8_t layer = (pav >> 1) & 0x03;*/ + int8_t protection_absent = pav & 0x01; - int16_t fh1 = stream->read_2bytes(); - // Profile_ObjectType 2 uimsbf + /** + * ID: MPEG identifier, set to ‘1’ if the audio data in the ADTS stream are MPEG-2 AAC (See ISO/IEC 13818-7) + * and set to ‘0’ if the audio data are MPEG-4. See also ISO/IEC 11172-3, subclause 2.4.2.3. + */ + if (id != 0x01) { + ret = ERROR_ADTS_ID_NOT_AAC; + srs_warn("adts: id must be 1(aac), actual 0(mp4a). ret=%d", ret); + return ret; + } + + int16_t sfiv = stream->read_2bytes(); + // profile 2 uimsbf // sampling_frequency_index 4 uimsbf // private_bit 1 bslbf // channel_configuration 3 uimsbf // original/copy 1 bslbf // home 1 bslbf - int8_t audioObjectType = (fh1 >> 14) & 0x03; - int8_t samplingFrequencyIndex = (fh1 >> 10) & 0x0f; - /*int8_t fh_private_bit = (fh1 >> 9) & 0x01;*/ - int8_t channelConfiguration = (fh1 >> 6) & 0x07; - /*int8_t fh_original = (fh1 >> 5) & 0x01;*/ - /*int8_t fh_home = (fh1 >> 4) & 0x01;*/ - // @remark, Emphasis is removed, - // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736 - //int8_t fh_Emphasis = (fh1 >> 2) & 0x03; + int8_t profile = (sfiv >> 14) & 0x03; + int8_t sampling_frequency_index = (sfiv >> 10) & 0x0f; + /*int8_t private_bit = (sfiv >> 9) & 0x01;*/ + int8_t channel_configuration = (sfiv >> 6) & 0x07; + /*int8_t original = (sfiv >> 5) & 0x01;*/ + /*int8_t home = (sfiv >> 4) & 0x01;*/ + //int8_t Emphasis; @remark, Emphasis is removed, @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736 // 4bits left. // adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS // copyright_identification_bit 1 bslbf // copyright_identification_start 1 bslbf /*int8_t fh_copyright_identification_bit = (fh1 >> 3) & 0x01;*/ /*int8_t fh_copyright_identification_start = (fh1 >> 2) & 0x01;*/ - // aac_frame_length 13 bslbf: Length of the frame including headers and error_check in bytes. + // frame_length 13 bslbf: Length of the frame including headers and error_check in bytes. // use the left 2bits as the 13 and 12 bit, - // the aac_frame_length is 13bits, so we move 13-2=11. - int16_t fh_aac_frame_length = (fh1 << 11) & 0x1800; + // the frame_length is 13bits, so we move 13-2=11. + int16_t frame_length = (sfiv << 11) & 0x1800; - int32_t fh2 = stream->read_3bytes(); - // aac_frame_length 13 bslbf: consume the first 13-2=11bits + int32_t abfv = stream->read_3bytes(); + // frame_length 13 bslbf: consume the first 13-2=11bits // the fh2 is 24bits, so we move right 24-11=13. - fh_aac_frame_length |= (fh2 >> 13) & 0x07ff; + frame_length |= (abfv >> 13) & 0x07ff; // adts_buffer_fullness 11 bslbf - /*int16_t fh_adts_buffer_fullness = (fh2 >> 2) & 0x7ff;*/ - // no_raw_data_blocks_in_frame 2 uimsbf - /*int16_t fh_no_raw_data_blocks_in_frame = fh2 & 0x03;*/ + /*int16_t fh_adts_buffer_fullness = (abfv >> 2) & 0x7ff;*/ + // number_of_raw_data_blocks_in_frame 2 uimsbf + /*int16_t number_of_raw_data_blocks_in_frame = abfv & 0x03;*/ // adts_error_check(), 1.A.2.2.3 Error detection - if (!fh_protection_absent) { + if (!protection_absent) { if (!stream->require(2)) { return ERROR_AAC_ADTS_HEADER; } @@ -412,47 +420,38 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame /*int16_t crc_check = */stream->read_2bytes(); } - // TODO: check the samplingFrequencyIndex - // TODO: check the channelConfiguration + // TODO: check the sampling_frequency_index + // TODO: check the channel_configuration // raw_data_blocks int adts_header_size = stream->pos() - adts_header_start; - int raw_data_size = fh_aac_frame_length - adts_header_size; + int raw_data_size = frame_length - adts_header_size; if (!stream->require(raw_data_size)) { return ERROR_AAC_ADTS_HEADER; } - // the profile = object_id + 1 - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, - // Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types - char aac_profile = audioObjectType + 1; - // the codec info. - codec.protection_absent = fh_protection_absent; - codec.Profile_ObjectType = audioObjectType; - codec.sampling_frequency_index = samplingFrequencyIndex; - codec.channel_configuration = channelConfiguration; - codec.aac_frame_length = fh_aac_frame_length; - - codec.aac_profile = aac_profile; - codec.aac_samplerate = samplingFrequencyIndex; - codec.aac_channel = channelConfiguration; + codec.protection_absent = protection_absent; + codec.aac_object = srs_codec_aac_ts2rtmp((SrsAacProfile)profile); + codec.sampling_frequency_index = sampling_frequency_index; + codec.channel_configuration = channel_configuration; + codec.frame_length = frame_length; // @see srs_audio_write_raw_frame(). codec.sound_format = 10; // AAC - if (samplingFrequencyIndex <= 0x0c && samplingFrequencyIndex > 0x0a) { + if (sampling_frequency_index <= 0x0c && sampling_frequency_index > 0x0a) { codec.sound_rate = SrsCodecAudioSampleRate5512; - } else if (samplingFrequencyIndex <= 0x0a && samplingFrequencyIndex > 0x07) { + } else if (sampling_frequency_index <= 0x0a && sampling_frequency_index > 0x07) { codec.sound_rate = SrsCodecAudioSampleRate11025; - } else if (samplingFrequencyIndex <= 0x07 && samplingFrequencyIndex > 0x04) { + } else if (sampling_frequency_index <= 0x07 && sampling_frequency_index > 0x04) { codec.sound_rate = SrsCodecAudioSampleRate22050; - } else if (samplingFrequencyIndex <= 0x04) { + } else if (sampling_frequency_index <= 0x04) { codec.sound_rate = SrsCodecAudioSampleRate44100; } else { codec.sound_rate = SrsCodecAudioSampleRate44100; - srs_warn("adts invalid sample rate for flv, rate=%#x", samplingFrequencyIndex); + srs_warn("adts invalid sample rate for flv, rate=%#x", sampling_frequency_index); } - codec.sound_size = srs_max(0, srs_min(1, channelConfiguration - 1)); + codec.sound_size = srs_max(0, srs_min(1, channel_configuration - 1)); // TODO: FIXME: finger it out the sound size by adts. codec.sound_size = 1; // 0(8bits) or 1(16bits). @@ -472,16 +471,13 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh int ret = ERROR_SUCCESS; // only support aac profile 1-4. - if (codec->aac_profile < 1 || codec->aac_profile > 4) { + if (codec->aac_object == SrsAacObjectTypeReserved) { return ERROR_AAC_DATA_INVALID; } - // the profile = object_id + 1 - // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, - // Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types - char profile_ObjectType = codec->aac_profile - 1; - char channelConfiguration = codec->aac_channel; - char samplingFrequencyIndex = codec->aac_samplerate; + SrsAacObjectType audioObjectType = codec->aac_object; + char channelConfiguration = codec->channel_configuration; + char samplingFrequencyIndex = codec->sampling_frequency_index; // override the aac samplerate by user specified. // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64146899 @@ -503,7 +499,7 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh // AudioSpecificConfig (), page 33 // 1.6.2.1 AudioSpecificConfig // audioObjectType; 5 bslbf - ch = (profile_ObjectType << 3) & 0xf8; + ch = (audioObjectType << 3) & 0xf8; // 3bits left. // samplingFrequencyIndex; 4 bslbf diff --git a/trunk/src/protocol/srs_raw_avc.hpp b/trunk/src/protocol/srs_raw_avc.hpp index 5fcdf62a0..0dc05dc6f 100644 --- a/trunk/src/protocol/srs_raw_avc.hpp +++ b/trunk/src/protocol/srs_raw_avc.hpp @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + class SrsStream; /** @@ -92,15 +94,10 @@ public: struct SrsRawAacStreamCodec { int8_t protection_absent; - int8_t Profile_ObjectType; + SrsAacObjectType aac_object; int8_t sampling_frequency_index; int8_t channel_configuration; - int16_t aac_frame_length; - - // calc by Profile_ObjectType+1 - char aac_profile; - char aac_samplerate; - char aac_channel; + int16_t frame_length; char sound_format; char sound_rate; diff --git a/trunk/src/protocol/srs_rtmp_buffer.cpp b/trunk/src/protocol/srs_rtmp_buffer.cpp index d72a1d857..651ff2b64 100644 --- a/trunk/src/protocol/srs_rtmp_buffer.cpp +++ b/trunk/src/protocol/srs_rtmp_buffer.cpp @@ -62,6 +62,16 @@ SrsFastBuffer::SrsFastBuffer() p = end = buffer; } +int SrsFastBuffer::size() +{ + return end - p; +} + +char* SrsFastBuffer::bytes() +{ + return p; +} + void SrsFastBuffer::set_buffer(int buffer_size) { // the user-space buffer size limit to a max value. diff --git a/trunk/src/protocol/srs_rtmp_buffer.hpp b/trunk/src/protocol/srs_rtmp_buffer.hpp index 98f6ec792..912417d5b 100644 --- a/trunk/src/protocol/srs_rtmp_buffer.hpp +++ b/trunk/src/protocol/srs_rtmp_buffer.hpp @@ -85,6 +85,16 @@ public: SrsFastBuffer(); virtual ~SrsFastBuffer(); public: + /** + * get the size of current bytes in buffer. + */ + virtual int size(); + /** + * get the current bytes in buffer. + * @remark user should use read_slice() if possible, + * the bytes() is used to test bytes, for example, to detect the bytes schema. + */ + virtual char* bytes(); /** * create buffer with specifeid size. * @param buffer the size of buffer. @@ -110,6 +120,8 @@ public: * skip some bytes in buffer. * @param size the bytes to skip. positive to next; negative to previous. * @remark assert buffer already grow(size). + * @remark always use read_slice to consume bytes, which will reset for EOF. + * while skip never consume bytes. */ virtual void skip(int size); public: @@ -130,6 +142,7 @@ public: * @param v true to ename merged read. * @param handler the handler when merge read is enabled. * @see https://github.com/winlinvip/simple-rtmp-server/issues/241 + * @remark the merged read is optional, ignore if not specifies. */ virtual void set_merge_read(bool v, IMergeReadHandler* handler); #endif diff --git a/trunk/src/protocol/srs_rtmp_handshake.cpp b/trunk/src/protocol/srs_rtmp_handshake.cpp index e21f1336b..f379aadb5 100644 --- a/trunk/src/protocol/srs_rtmp_handshake.cpp +++ b/trunk/src/protocol/srs_rtmp_handshake.cpp @@ -116,7 +116,6 @@ namespace _srs_internal // @remark, if no key, use EVP_Digest to digest, // for instance, in python, hashlib.sha256(data).digest(). HMAC_CTX_init(&ctx); - if (HMAC_Init_ex(&ctx, __key, key_size, EVP_sha256(), NULL) < 0) { ret = ERROR_OpenSslSha256Init; return ret; diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 9a33b8a3c..863866359 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -762,8 +762,9 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) { int ret = ERROR_SUCCESS; +#ifdef SRS_PERF_COMPLEX_SEND int iov_index = 0; - iovec* iov = out_iovs + iov_index; + iovec* iovs = out_iovs + iov_index; int c0c3_cache_index = 0; char* c0c3_cache = out_c0c3_caches + c0c3_cache_index; @@ -796,13 +797,13 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) srs_assert(nbh > 0); // header iov - iov[0].iov_base = c0c3_cache; - iov[0].iov_len = nbh; + iovs[0].iov_base = c0c3_cache; + iovs[0].iov_len = nbh; // payload iov int payload_size = srs_min(out_chunk_size, pend - p); - iov[1].iov_base = p; - iov[1].iov_len = payload_size; + iovs[1].iov_base = p; + iovs[1].iov_len = payload_size; // consume sendout bytes. p += payload_size; @@ -822,7 +823,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) // to next pair of iovs iov_index += 2; - iov = out_iovs + iov_index; + iovs = out_iovs + iov_index; // to next c0c3 header cache c0c3_cache_index += nbh; @@ -849,7 +850,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) // reset caches, while these cache ensure // atleast we can sendout a chunk. iov_index = 0; - iov = out_iovs + iov_index; + iovs = out_iovs + iov_index; c0c3_cache_index = 0; c0c3_cache = out_c0c3_caches + c0c3_cache_index; @@ -866,6 +867,61 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); return do_iovs_send(out_iovs, iov_index); +#else + // try to send use the c0c3 header cache, + // if cache is consumed, try another loop. + for (int i = 0; i < nb_msgs; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + if (!msg) { + continue; + } + + // ignore empty message. + if (!msg->payload || msg->size <= 0) { + srs_info("ignore empty message."); + continue; + } + + // p set to current write position, + // it's ok when payload is NULL and size is 0. + char* p = msg->payload; + char* pend = msg->payload + msg->size; + + // always write the header event payload is empty. + while (p < pend) { + // for simple send, send each chunk one by one + iovec* iovs = out_iovs; + char* c0c3_cache = out_c0c3_caches; + int nb_cache = SRS_CONSTS_C0C3_HEADERS_MAX; + + // always has header + int nbh = msg->chunk_header(c0c3_cache, nb_cache, p == msg->payload); + srs_assert(nbh > 0); + + // header iov + iovs[0].iov_base = c0c3_cache; + iovs[0].iov_len = nbh; + + // payload iov + int payload_size = srs_min(out_chunk_size, pend - p); + iovs[1].iov_base = p; + iovs[1].iov_len = payload_size; + + // consume sendout bytes. + p += payload_size; + + if ((ret = skt->writev(iovs, 2, NULL)) != ERROR_SUCCESS) { + if (!srs_is_client_gracefully_close(ret)) { + srs_error("send packet with writev failed. ret=%d", ret); + } + return ret; + } + } + } + + return ret; +#endif } int SrsProtocol::do_iovs_send(iovec* iovs, int size) diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index ac9c4af9d..a26d389c1 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -80,976 +80,565 @@ int MockSrsConfig::parse(string buf) // full.conf std::string __full_conf = "" - "# all config for srs \n" - " \n" - "############################################################################################# \n" - "# RTMP sections \n" - "############################################################################################# \n" - "# the rtmp listen ports, split by space. \n" - "listen 1935; \n" - "# the pid file \n" - "# to ensure only one process can use a pid file \n" - "# and provides the current running process id, for script, \n" - "# for example, init.d script to manage the server. \n" - "# default: ./objs/srs.pid \n" - "pid ./objs/srs.pid; \n" - "# the default chunk size is 128, max is 65536, \n" - "# some client does not support chunk size change, \n" - "# however, most clients supports it and it can improve \n" - "# performance about 10%. \n" - "# default: 60000 \n" - "chunk_size 60000; \n" - "# the logs dir. \n" - "# if enabled ffmpeg, each stracoding stream will create a log file. \n" - "# /dev/null to disable the log. \n" - "# default: ./objs \n" - "ff_log_dir ./objs; \n" - "# the log tank, console or file. \n" - "# if console, print log to console. \n" - "# if file, write log to file. requires srs_log_file if log to file. \n" - "# default: file. \n" - "srs_log_tank file; \n" - "# the log level, for all log tanks. \n" - "# can be: verbose, info, trace, warn, error \n" - "# default: trace \n" - "srs_log_level trace; \n" - "# when srs_log_tank is file, specifies the log file. \n" - "# default: ./objs/srs.log \n" - "srs_log_file ./objs/srs.log; \n" - "# the max connections. \n" - "# if exceed the max connections, server will drop the new connection. \n" - "# default: 12345 \n" - "max_connections 1000; \n" - "# whether start as deamon \n" - "# @remark: donot support reload. \n" - "# default: on \n" - "daemon on; \n" - "# heartbeat to api server \n" - "heartbeat { \n" - " # whether heartbeat is enalbed. \n" - " # default: off \n" - " enabled on; \n" - " # the interval seconds for heartbeat, \n" - " # recommend 0.3,0.6,0.9,1.2,1.5,1.8,2.1,2.4,2.7,3,...,6,9,12,.... \n" - " # default: 9.9 \n" - " interval 9.3; \n" - " # when startup, srs will heartbeat to this api. \n" - " # @remark: must be a restful http api url, where SRS will POST with following data: \n" - " # { \n" - " # \"device_id\": \"my-srs-device\", \n" - " # \"ip\": \"192.168.1.100\" \n" - " # } \n" - " # default: http://127.0.0.1:8085/api/v1/servers \n" - " url http://127.0.0.1:8085/api/v1/servers; \n" - " # the id of devide. \n" - " device_id \"my-srs-device\"; \n" - " # whether report with summaries \n" - " # if true, put /api/v1/summaries to the request data: \n" - " # { \n" - " # \"summaries\": summaries object. \n" - " # } \n" - " # @remark: optional config. \n" - " # default: off \n" - " summaries off; \n" - "} \n" - " \n" - "############################################################################################# \n" - "# HTTP sections \n" - "############################################################################################# \n" - "# api of srs. \n" - "# the http api config, export for external program to manage srs. \n" - "# user can access http api of srs in browser directly, for instance, to access by: \n" - "# curl http://192.168.1.170:1985/api/v1/reload \n" - "# which will reload srs, like cmd killall -1 srs, but the js can also invoke the http api, \n" - "# where the cli can only be used in shell/terminate. \n" - "http_api { \n" - " # whether http api is enabled. \n" - " # default: off \n" - " enabled on; \n" - " # the http api port \n" - " # default: 1985 \n" - " listen 1985; \n" - "} \n" - "# embeded http server in srs. \n" - "# the http streaming config, for HLS/HDS/DASH/HTTPProgressive \n" - "# global config for http streaming, user must config the http section for each vhost. \n" - "# the embed http server used to substitute nginx in ./objs/nginx, \n" - "# for example, srs runing in arm, can provides RTMP and HTTP service, only with srs installed. \n" - "# user can access the http server pages, generally: \n" - "# curl http://192.168.1.170:80/srs.html \n" - "# which will show srs version and welcome to srs. \n" - "# @remark, the http embeded stream need to config the vhost, for instance, the __defaultVhost__ \n" - "# need to open the feature http of vhost. \n" - "http_stream { \n" - " # whether http streaming service is enabled. \n" - " # default: off \n" - " enabled on; \n" - " # the http streaming port \n" - " # @remark, if use lower port, for instance 80, user must start srs by root. \n" - " # default: 8080 \n" - " listen 8080; \n" - " # the default dir for http root. \n" - " # default: ./objs/nginx/html \n" - " dir ./objs/nginx/html; \n" - "} \n" - "# system statistics section. \n" - "# the main cycle will retrieve the system stat, \n" - "# for example, the cpu/mem/network/disk-io data, \n" - "# the http api, for instance, /api/v1/summaries will show these data. \n" - "# @remark the heartbeat depends on the network, \n" - "# for example, the eth0 maybe the device which index is 0. \n" - "stats { \n" - " # the index of device ip. \n" - " # we may retrieve more than one network device. \n" - " # default: 0 \n" - " network 0; \n" - " # the device name to stat the disk iops. \n" - " # ignore the device of /proc/diskstats if not configed. \n" - " disk sda sdb xvda xvdb; \n" - "} \n" - " \n" - "############################################################################################# \n" - "# RTMP/HTTP VHOST sections \n" - "############################################################################################# \n" - "# vhost list, the __defaultVhost__ is the default vhost \n" - "# for example, user use ip to access the stream: rtmp://192.168.1.2/live/livestream. \n" - "# for which cannot identify the required vhost. \n" - "vhost __defaultVhost__ { \n" - "} \n" - " \n" - "# vhost for edge, edge and origin is the same vhost \n" - "vhost same.edge.srs.com { \n" - " # the mode of vhost, local or remote. \n" - " # local: vhost is origin vhost, which provides stream source. \n" - " # remote: vhost is edge vhost, which pull/push to origin. \n" - " # default: local \n" - " mode remote; \n" - " # for edge(remote mode), user must specifies the origin server \n" - " # format as: [:port] \n" - " # @remark user can specifies multiple origin for error backup, by space, \n" - " # for example, 192.168.1.100:1935 192.168.1.101:1935 192.168.1.102:1935 \n" - " origin 127.0.0.1:1935 localhost:1935; \n" - " # for edge, whether open the token traverse mode, \n" - " # if token traverse on, all connections of edge will forward to origin to check(auth), \n" - " # it's very important for the edge to do the token auth. \n" - " # the better way is use http callback to do the token auth by the edge, \n" - " # but if user prefer origin check(auth), the token_traverse if better solution. \n" - " # default: off \n" - " token_traverse off; \n" - "} \n" - "# vhost for edge, change vhost. \n" - "vhost change.edge.srs.com { \n" - " mode remote; \n" - " # TODO: FIXME: support extra params. \n" - " origin 127.0.0.1:1935 localhost:1935 { \n" - " # specify the vhost to override the vhost in client request. \n" - " vhost edge2.srs.com; \n" - " # specify the refer(pageUrl) to override the refer in client request. \n" - " refer http://srs/index.html; \n" - " } \n" - "} \n" - " \n" - "# vhost for dvr \n" - "vhost dvr.srs.com { \n" - " # dvr RTMP stream to file, \n" - " # start to record to file when encoder publish, \n" - " # reap flv according by specified dvr_plan. \n" - " # http callbacks: \n" - " dvr { \n" - " # whether enabled dvr features \n" - " # default: off \n" - " enabled on; \n" - " # the dvr output path. \n" - " # the app dir is auto created under the dvr_path. \n" - " # for example, for rtmp stream: \n" - " # rtmp://127.0.0.1/live/livestream \n" - " # http://127.0.0.1/live/livestream.m3u8 \n" - " # where dvr_path is /dvr, srs will create the following files: \n" - " # /dvr/live the app dir for all streams. \n" - " # /dvr/live/livestream.{time}.flv the dvr flv file. \n" - " # @remark, the time use system timestamp in ms, user can use http callback to rename it. \n" - " # in a word, the dvr_path is for vhost. \n" - " # default: ./objs/nginx/html \n" - " dvr_path ./objs/nginx/html; \n" - " # the dvr plan. canbe: \n" - " # session reap flv when session end(unpublish). \n" - " # segment reap flv when flv duration exceed the specified dvr_duration. \n" - " # default: session \n" - " dvr_plan session; \n" - " # the param for plan(segment), in seconds. \n" - " # default: 30 \n" - " dvr_duration 30; \n" - " dvr_wait_keyframe on; \n" - " # about the stream monotonically increasing: \n" - " # 1. video timestamp is monotonically increasing, \n" - " # 2. audio timestamp is monotonically increasing, \n" - " # 3. video and audio timestamp is interleaved monotonically increasing. \n" - " # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format \n" - " # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. \n" - " # the time jitter algorithm: \n" - " # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. \n" - " # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. \n" - " # 3. off, disable the time jitter algorithm, like atc. \n" - " # default: full \n" - " time_jitter full; \n" - " } \n" - "} \n" - " \n" - "# vhost for ingest \n" - "vhost ingest.srs.com { \n" - " # ingest file/stream/device then push to SRS over RTMP. \n" - " # the name/id used to identify the ingest, must be unique in global. \n" - " # ingest id is used in reload or http api management. \n" - " ingest livestream { \n" - " # whether enabled ingest features \n" - " # default: off \n" - " enabled on; \n" - " # input file/stream/device \n" - " # @remark only support one input. \n" - " input { \n" - " # the type of input. \n" - " # can be file/stream/device, that is, \n" - " # file: ingest file specifies by url. \n" - " # stream: ingest stream specifeis by url. \n" - " # device: not support yet. \n" - " # default: file \n" - " type file; \n" - " # the url of file/stream. \n" - " url ./doc/source.200kbps.768x320.flv; \n" - " } \n" - " # the ffmpeg \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " # the transcode engine, @see all.transcode.srs.com \n" - " # @remark, the output is specified following. \n" - " engine { \n" - " # @see enabled of transcode engine. \n" - " # if disabled or vcodec/acodec not specified, use copy. \n" - " # default: off. \n" - " enabled off; \n" - " # output stream. variables: \n" - " # [vhost] current vhost which start the ingest. \n" - " # [port] system RTMP stream port. \n" - " output rtmp://127.0.0.1:[port]/live?vhost=[vhost]/livestream; \n" - " } \n" - " } \n" - "} \n" - " \n" - "# vhost for http \n" - "vhost http.srs.com { \n" - " # http vhost specified config \n" - " http { \n" - " # whether enabled the http streaming service for vhost. \n" - " # default: off \n" - " enabled on; \n" - " # the virtual directory root for this vhost to mount at \n" - " # for example, if mount to /hls, user access by http://server/hls \n" - " # default: / \n" - " mount /hls; \n" - " # main dir of vhost, \n" - " # to delivery HTTP stream of this vhost. \n" - " # default: ./objs/nginx/html \n" - " dir ./objs/nginx/html/hls; \n" - " } \n" - "} \n" - " \n" - "# the vhost with hls specified. \n" - "vhost with-hls.srs.com { \n" - " hls { \n" - " # whether the hls is enabled. \n" - " # if off, donot write hls(ts and m3u8) when publish. \n" - " # default: off \n" - " enabled on; \n" - " # the hls output path. \n" - " # the app dir is auto created under the hls_path. \n" - " # for example, for rtmp stream: \n" - " # rtmp://127.0.0.1/live/livestream \n" - " # http://127.0.0.1/live/livestream.m3u8 \n" - " # where hls_path is /hls, srs will create the following files: \n" - " # /hls/live the app dir for all streams. \n" - " # /hls/live/livestream.m3u8 the HLS m3u8 file. \n" - " # /hls/live/livestream-1.ts the HLS media/ts file. \n" - " # in a word, the hls_path is for vhost. \n" - " # default: ./objs/nginx/html \n" - " hls_path ./objs/nginx/html; \n" - " # the hls fragment in seconds, the duration of a piece of ts. \n" - " # default: 10 \n" - " hls_fragment 10; \n" - " # the hls window in seconds, the number of ts in m3u8. \n" - " # default: 60 \n" - " hls_window 60; \n" - " } \n" - "} \n" - "# the vhost with hls disabled. \n" - "vhost no-hls.srs.com { \n" - " hls { \n" - " # whether the hls is enabled. \n" - " # if off, donot write hls(ts and m3u8) when publish. \n" - " # default: off \n" - " enabled off; \n" - " } \n" - "} \n" - " \n" - "# the http hook callback vhost, srs will invoke the hooks for specified events. \n" - "vhost hooks.callback.srs.com { \n" - " http_hooks { \n" - " # whether the http hooks enalbe. \n" - " # default off. \n" - " enabled on; \n" - " # when client connect to vhost/app, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_connect\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" - " # \"tcUrl\": \"rtmp://video.test.com/live?key=d2fa801d08e3f90ed1e1670e6e52651a\", \n" - " # \"pageUrl\": \"http://www.test.com/live.html\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_connect http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_connect http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n" - " # when client close/disconnect to vhost/app/stream, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_close\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_close http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_close http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n" - " # when client(encoder) publish to vhost/app/stream, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_publish\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" - " # \"stream\": \"livestream\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n" - " # when client(encoder) stop publish to vhost/app/stream, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_unpublish\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" - " # \"stream\": \"livestream\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n" - " # when client start to play vhost/app/stream, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_play\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" - " # \"stream\": \"livestream\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n" - " # when client stop to play vhost/app/stream, call the hook, \n" - " # the request in the POST data string is a object encode by json: \n" - " # { \n" - " # \"action\": \"on_stop\", \n" - " # \"client_id\": 1985, \n" - " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" - " # \"stream\": \"livestream\" \n" - " # } \n" - " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" - " # an int value specifies the error code(0 corresponding to success): \n" - " # 0 \n" - " # support multiple api hooks, format: \n" - " # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" - " on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n" - " } \n" - "} \n" - " \n" - "# the vhost for min delay, donot cache any stream. \n" - "vhost min.delay.com { \n" - " # whether cache the last gop. \n" - " # if on, cache the last gop and dispatch to client, \n" - " # to enabled fast startup for client, client play immediately. \n" - " # if off, send the latest media data to client, \n" - " # client need to wait for the next Iframe to decode and show the video. \n" - " # set to off if requires min delay; \n" - " # set to on if requires client fast startup. \n" - " # default: on \n" - " gop_cache off; \n" - " # the max live queue length in seconds. \n" - " # if the messages in the queue exceed the max length, \n" - " # drop the old whole gop. \n" - " # default: 30 \n" - " queue_length 10; \n" - "} \n" - " \n" - "# the vhost for srs debug info, whether send args in connect(tcUrl). \n" - "vhost debug.srs.com { \n" - " # when upnode(forward to, edge push to, edge pull from) is srs, \n" - " # it's strongly recommend to open the debug_srs_upnode, \n" - " # when connect to upnode, it will take the debug info, \n" - " # for example, the id, source id, pid. \n" - " # please see: https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_SrsLog \n" - " # default: on \n" - " debug_srs_upnode on; \n" - "} \n" - " \n" - "# the vhost for antisuck. \n" - "vhost refer.anti_suck.com { \n" - " # the common refer for play and publish. \n" - " # if the page url of client not in the refer, access denied. \n" - " # if not specified this field, allow all. \n" - " # default: not specified. \n" - " refer github.com github.io; \n" - " # refer for publish clients specified. \n" - " # the common refer is not overrided by this. \n" - " # if not specified this field, allow all. \n" - " # default: not specified. \n" - " refer_publish github.com github.io; \n" - " # refer for play clients specified. \n" - " # the common refer is not overrided by this. \n" - " # if not specified this field, allow all. \n" - " # default: not specified. \n" - " refer_play github.com github.io; \n" - "} \n" - " \n" - "# the vhost which forward publish streams. \n" - "vhost same.vhost.forward.srs.com { \n" - " # forward all publish stream to the specified server. \n" - " # this used to split/forward the current stream for cluster active-standby, \n" - " # active-active for cdn to build high available fault tolerance system. \n" - " # format: {ip}:{port} {ip_N}:{port_N} \n" - " # or specify the vhost by params, @see: change.vhost.forward.srs.com \n" - " # if vhost not specified, use the request vhost instead. \n" - " forward 127.0.0.1:1936 127.0.0.1:1937; \n" - "} \n" - "# TODO: FIXME: support extra params. \n" - "# [plan] the vhost which forward publish streams to other vhosts. \n" - "vhost change.vhost.forward.srs.com { \n" - " forward 127.0.0.1:1936 127.0.0.1:1937 { \n" - " # specify the vhost to override the vhost in client request. \n" - " vhost forward2.srs.com; \n" - " # specify the refer(pageUrl) to override the refer in client request. \n" - " refer http://srs/index.html; \n" - " } \n" - " forward 127.0.0.1:1938 { \n" - " vhost forward3.srs.com; \n" - " } \n" - "} \n" - " \n" - "# the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction \n" - "vhost mirror.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine mirror { \n" - " enabled on; \n" - " vfilter { \n" - " vf 'split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2'; \n" - " } \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# \n" - "# the drawtext filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#drawtext-1 \n" - "# remark: we remove the libfreetype which always cause build failed, you must add it manual if needed. \n" - "# \n" - "####################################################################################################### \n" - "# the crop filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#crop \n" - "vhost crop.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine crop { \n" - " enabled on; \n" - " vfilter { \n" - " vf 'crop=in_w-20:in_h-160:10:80'; \n" - " } \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# the logo filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#overlay \n" - "vhost logo.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine logo { \n" - " enabled on; \n" - " vfilter { \n" - " i ./doc/ffmpeg-logo.png; \n" - " filter_complex 'overlay=10:10'; \n" - " } \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# audio transcode only. \n" - "# for example, FMLE publish audio codec in mp3, and donot support HLS output, \n" - "# we can transcode the audio to aac and copy video to the new stream with HLS. \n" - "vhost audio.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine acodec { \n" - " enabled on; \n" - " vcodec copy; \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# disable video, transcode/copy audio. \n" - "# for example, publish pure audio stream. \n" - "vhost vn.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine vn { \n" - " enabled on; \n" - " vcodec vn; \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# ffmpeg-copy(forward implements by ffmpeg). \n" - "# copy the video and audio to a new stream. \n" - "vhost copy.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine copy { \n" - " enabled on; \n" - " vcodec copy; \n" - " acodec copy; \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# transcode all app and stream of vhost \n" - "vhost all.transcode.srs.com { \n" - " # the streaming transcode configs. \n" - " transcode { \n" - " # whether the transcode enabled. \n" - " # if off, donot transcode. \n" - " # default: off. \n" - " enabled on; \n" - " # the ffmpeg \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " # the transcode engine for matched stream. \n" - " # all matched stream will transcoded to the following stream. \n" - " # the transcode set name(ie. hd) is optional and not used. \n" - " engine ffsuper { \n" - " # whether the engine is enabled \n" - " # default: off. \n" - " enabled on; \n" - " # input format, can be: \n" - " # off, do not specifies the format, ffmpeg will guess it. \n" - " # flv, for flv or RTMP stream. \n" - " # other format, for example, mp4/aac whatever. \n" - " # default: flv \n" - " iformat flv; \n" - " # ffmpeg filters, follows the main input. \n" - " vfilter { \n" - " # the logo input file. \n" - " i ./doc/ffmpeg-logo.png; \n" - " # the ffmpeg complex filter. \n" - " # for filters, @see: http://ffmpeg.org/ffmpeg-filters.html \n" - " filter_complex 'overlay=10:10'; \n" - " } \n" - " # video encoder name. can be: \n" - " # libx264: use h.264(libx264) video encoder. \n" - " # copy: donot encoder the video stream, copy it. \n" - " # vn: disable video output. \n" - " vcodec libx264; \n" - " # video bitrate, in kbps \n" - " vbitrate 1500; \n" - " # video framerate. \n" - " vfps 25; \n" - " # video width, must be even numbers. \n" - " vwidth 768; \n" - " # video height, must be even numbers. \n" - " vheight 320; \n" - " # the max threads for ffmpeg to used. \n" - " vthreads 12; \n" - " # x264 profile, @see x264 -help, can be: \n" - " # high,main,baseline \n" - " vprofile main; \n" - " # x264 preset, @see x264 -help, can be: \n" - " # ultrafast,superfast,veryfast,faster,fast \n" - " # medium,slow,slower,veryslow,placebo \n" - " vpreset medium; \n" - " # other x264 or ffmpeg video params \n" - " vparams { \n" - " # ffmpeg options, @see: http://ffmpeg.org/ffmpeg.html \n" - " t 100; \n" - " # 264 params, @see: http://ffmpeg.org/ffmpeg-codecs.html#libx264 \n" - " coder 1; \n" - " b_strategy 2; \n" - " bf 3; \n" - " refs 10; \n" - " } \n" - " # audio encoder name. can be: \n" - " # libaacplus: use aac(libaacplus) audio encoder. \n" - " # copy: donot encoder the audio stream, copy it. \n" - " # an: disable audio output. \n" - " acodec libaacplus; \n" - " # audio bitrate, in kbps. [16, 72] for libaacplus. \n" - " abitrate 70; \n" - " # audio sample rate. for flv/rtmp, it must be: \n" - " # 44100,22050,11025,5512 \n" - " asample_rate 44100; \n" - " # audio channel, 1 for mono, 2 for stereo. \n" - " achannels 2; \n" - " # other ffmpeg audio params \n" - " aparams { \n" - " # audio params, @see: http://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders \n" - " profile:a aac_low; \n" - " } \n" - " # output format, can be: \n" - " # off, do not specifies the format, ffmpeg will guess it. \n" - " # flv, for flv or RTMP stream. \n" - " # other format, for example, mp4/aac whatever. \n" - " # default: flv \n" - " oformat flv; \n" - " # output stream. variables: \n" - " # [vhost] the input stream vhost. \n" - " # [port] the intput stream port. \n" - " # [app] the input stream app. \n" - " # [stream] the input stream name. \n" - " # [engine] the tanscode engine name. \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine ffhd { \n" - " enabled on; \n" - " vcodec libx264; \n" - " vbitrate 1200; \n" - " vfps 25; \n" - " vwidth 1382; \n" - " vheight 576; \n" - " vthreads 6; \n" - " vprofile main; \n" - " vpreset medium; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 70; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine ffsd { \n" - " enabled on; \n" - " vcodec libx264; \n" - " vbitrate 800; \n" - " vfps 25; \n" - " vwidth 1152; \n" - " vheight 480; \n" - " vthreads 4; \n" - " vprofile main; \n" - " vpreset fast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 60; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine fffast { \n" - " enabled on; \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine vcopy { \n" - " enabled on; \n" - " vcodec copy; \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine acopy { \n" - " enabled on; \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec copy; \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " engine copy { \n" - " enabled on; \n" - " vcodec copy; \n" - " acodec copy; \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# transcode all stream using the empty ffmpeg demo, donothing. \n" - "vhost ffempty.transcode.srs.com { \n" - " transcode { \n" - " enabled on; \n" - " ffmpeg ./objs/research/ffempty; \n" - " engine empty { \n" - " enabled on; \n" - " vcodec libx264; \n" - " vbitrate 300; \n" - " vfps 20; \n" - " vwidth 768; \n" - " vheight 320; \n" - " vthreads 2; \n" - " vprofile baseline; \n" - " vpreset superfast; \n" - " vparams { \n" - " } \n" - " acodec libaacplus; \n" - " abitrate 45; \n" - " asample_rate 44100; \n" - " achannels 2; \n" - " aparams { \n" - " } \n" - " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" - " } \n" - " } \n" - "} \n" - "# transcode all app and stream of app \n" - "vhost app.transcode.srs.com { \n" - " # the streaming transcode configs. \n" - " # if app specified, transcode all streams of app. \n" - " transcode live { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine { \n" - " enabled off; \n" - " } \n" - " } \n" - "} \n" - "# transcode specified stream. \n" - "vhost stream.transcode.srs.com { \n" - " # the streaming transcode configs. \n" - " # if stream specified, transcode the matched stream. \n" - " transcode live/livestream { \n" - " enabled on; \n" - " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" - " engine { \n" - " enabled off; \n" - " } \n" - " } \n" - "} \n" - " \n" - "# vhost for bandwidth check \n" - "# generally, the bandcheck vhost must be: bandcheck.srs.com, \n" - "# or need to modify the vhost of client. \n" - "vhost bandcheck.srs.com { \n" - " enabled on; \n" - " chunk_size 65000; \n" - " # bandwidth check config. \n" - " bandcheck { \n" - " # whether support bandwidth check, \n" - " # default: off. \n" - " enabled on; \n" - " # the key for server to valid, \n" - " # if invalid key, server disconnect and abort the bandwidth check. \n" - " key \"35c9b402c12a7246868752e2878f7e0e\"; \n" - " # the interval in seconds for bandwidth check, \n" - " # server donot allow new test request. \n" - " # default: 30 \n" - " interval 30; \n" - " # the max available check bandwidth in kbps. \n" - " # to avoid attack of bandwidth check. \n" - " # default: 1000 \n" - " limit_kbps 4000; \n" - " } \n" - "} \n" - " \n" - "# set the chunk size of vhost. \n" - "vhost chunksize.srs.com { \n" - " # the default chunk size is 128, max is 65536, \n" - " # some client does not support chunk size change, \n" - " # vhost chunk size will override the global value. \n" - " # default: global chunk size. \n" - " chunk_size 128; \n" - "} \n" - " \n" - "# vhost for time jitter \n" - "vhost jitter.srs.com { \n" - " # about the stream monotonically increasing: \n" - " # 1. video timestamp is monotonically increasing, \n" - " # 2. audio timestamp is monotonically increasing, \n" - " # 3. video and audio timestamp is interleaved monotonically increasing. \n" - " # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format \n" - " # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. \n" - " # the time jitter algorithm: \n" - " # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. \n" - " # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. \n" - " # 3. off, disable the time jitter algorithm, like atc. \n" - " # default: full \n" - " time_jitter full; \n" - "} \n" - " \n" - "# vhost for atc. \n" - "vhost atc.srs.com { \n" - " # vhost for atc for hls/hds/rtmp backup. \n" - " # generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0. \n" - " # when atc is on, server delivery rtmp stream by absolute time. \n" - " # atc is used, for instance, encoder will copy stream to master and slave server, \n" - " # server use atc to delivery stream to edge/client, where stream time from master/slave server \n" - " # is always the same, client/tools can slice RTMP stream to HLS according to the same time, \n" - " # if the time not the same, the HLS stream cannot slice to support system backup. \n" - " # \n" - " # @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html \n" - " # @see http://www.baidu.com/#wd=hds%20hls%20atc \n" - " # \n" - " # default: off \n" - " atc on; \n" - " # whether enable the auto atc, \n" - " # if enabled, detect the bravo_atc=\"true\" in onMetaData packet, \n" - " # set atc to on if matched. \n" - " # always ignore the onMetaData if atc_auto is off. \n" - " # default: on \n" - " atc_auto on; \n" - "} \n" - " \n" - "# the vhost disabled. \n" - "vhost removed.srs.com { \n" - " # whether the vhost is enabled. \n" - " # if off, all request access denied. \n" - " # default: on \n" - " enabled off; \n" - "} \n" - " \n" - "# config for the pithy print, \n" - "# which always print constant message specified by interval, \n" - "# whatever the clients in concurrency. \n" - "pithy_print { \n" - " # shared print interval for all publish clients, in milliseconds. \n" - " # default: 10000 \n" - " publish 10000; \n" - " # shared print interval for all play clients, in milliseconds. \n" - " # default: 10000 \n" - " play 10000; \n" - " # shared print interval for all forwarders, in milliseconds. \n" - " # default: 10000 \n" - " forwarder 10000; \n" - " # shared print interval for all encoders, in milliseconds. \n" - " # default: 10000 \n" - " encoder 10000; \n" - " # shared print interval for all ingesters, in milliseconds. \n" - " # default: 10000 \n" - " ingester 10000; \n" - " # shared print interval for all hls, in milliseconds. \n" - " # default: 10000 \n" - " hls 10000; \n" - " # shared print interval for all edge, in milliseconds. \n" - " # default: 10000 \n" - " edge 10000; \n" - "} \n" +"listen 1935; \n " +"pid ./objs/srs.pid; \n " +"chunk_size 60000; \n " +"ff_log_dir ./objs; \n " +"srs_log_tank file; \n " +"srs_log_level trace; \n " +"srs_log_file ./objs/srs.log; \n " +"max_connections 1000; \n " +"daemon on; \n " +" \n " +"heartbeat { \n " +" enabled off; \n " +" interval 9.3; \n " +" url http://127.0.0.1:8085/api/v1/servers; \n " +" device_id \"my-srs-device\"; \n " +" summaries off; \n " +"} \n " +" \n " +"stats { \n " +" network 0; \n " +" disk sda sdb xvda xvdb; \n " +"} \n " +" \n " +"http_api { \n " +" enabled on; \n " +" listen 1985; \n " +" crossdomain on; \n " +"} \n " +"http_server { \n " +" enabled on; \n " +" listen 8080; \n " +" dir ./objs/nginx/html; \n " +"} \n " +" \n " +"stream_caster { \n " +" enabled off; \n " +" caster mpegts_over_udp; \n " +" output rtmp://127.0.0.1/live/livestream; \n " +" listen 8935; \n " +" rtp_port_min 57200; \n " +" rtp_port_max 57300; \n " +"} \n " +"stream_caster { \n " +" enabled off; \n " +" caster mpegts_over_udp; \n " +" output rtmp://127.0.0.1/live/livestream; \n " +" listen 8935; \n " +"} \n " +"stream_caster { \n " +" enabled off; \n " +" caster rtsp; \n " +" output rtmp://127.0.0.1/[app]/[stream]; \n " +" listen 554; \n " +" rtp_port_min 57200; \n " +" rtp_port_max 57300; \n " +"} \n " +" \n " +"vhost __defaultVhost__ { \n " +"} \n " +" \n " +"vhost security.srs.com { \n " +" security { \n " +" enabled on; \n " +" allow play all; \n " +" allow publish all; \n " +" } \n " +"} \n " +" \n " +"vhost mrw.srs.com { \n " +" min_latency off; \n " +" mr { \n " +" enabled on; \n " +" latency 350; \n " +" } \n " +" mw_latency 350; \n " +"} \n " +" \n " +"vhost same.edge.srs.com { \n " +" mode remote; \n " +" origin 127.0.0.1:1935 localhost:1935; \n " +" token_traverse off; \n " +"} \n " +" \n " +"vhost dvr.srs.com { \n " +" dvr { \n " +" enabled on; \n " +" dvr_plan session; \n " +" dvr_path ./objs/nginx/html; \n " +" dvr_duration 30; \n " +" dvr_wait_keyframe on; \n " +" time_jitter full; \n " +" \n " +" } \n " +"} \n " +" \n " +"vhost ingest.srs.com { \n " +" ingest livestream { \n " +" enabled on; \n " +" input { \n " +" type file; \n " +" url ./doc/source.200kbps.768x320.flv; \n " +" } \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine { \n " +" enabled off; \n " +" output rtmp://127.0.0.1:[port]/live?vhost=[vhost]/livestream; \n " +" } \n " +" } \n " +"} \n " +" \n " +"vhost http.static.srs.com { \n " +" http { \n " +" enabled on; \n " +" mount [vhost]/hls; \n " +" dir ./objs/nginx/html/hls; \n " +" } \n " +"} \n " +" \n " +"vhost http.remux.srs.com { \n " +" http_remux { \n " +" enabled on; \n " +" fast_cache 30; \n " +" mount [vhost]/[app]/[stream].flv; \n " +" } \n " +"} \n " +" \n " +"vhost with-hls.srs.com { \n " +" hls { \n " +" enabled on; \n " +" hls_fragment 10; \n " +" hls_td_ratio 1.5; \n " +" hls_window 60; \n " +" hls_on_error ignore; \n " +" hls_storage disk; \n " +" hls_path ./objs/nginx/html; \n " +" hls_mount [vhost]/[app]/[stream].m3u8; \n " +" hls_acodec aac; \n " +" hls_vcodec h264; \n " +" } \n " +"} \n " +"vhost no-hls.srs.com { \n " +" hls { \n " +" enabled off; \n " +" } \n " +"} \n " +" \n " +"vhost hooks.callback.srs.com { \n " +" http_hooks { \n " +" enabled on; \n " +" on_connect http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n " +" on_close http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n " +" on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n " +" on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n " +" on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n " +" on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n " +" on_dvr http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs; \n " +" } \n " +"} \n " +" \n " +"vhost debug.srs.com { \n " +" debug_srs_upnode on; \n " +"} \n " +" \n " +"vhost min.delay.com { \n " +" min_latency on; \n " +" mr { \n " +" enabled off; \n " +" } \n " +" mw_latency 100; \n " +" gop_cache off; \n " +" queue_length 10; \n " +"} \n " +" \n " +"vhost refer.anti_suck.com { \n " +" refer github.com github.io; \n " +" refer_publish github.com github.io; \n " +" refer_play github.com github.io; \n " +"} \n " +" \n " +"vhost same.vhost.forward.srs.com { \n " +" forward 127.0.0.1:1936 127.0.0.1:1937; \n " +"} \n " +" \n " +"vhost example.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine example { \n " +" enabled on; \n " +" iformat flv; \n " +" vfilter { \n " +" i ./doc/ffmpeg-logo.png; \n " +" filter_complex 'overlay=10:10'; \n " +" } \n " +" vcodec libx264; \n " +" vbitrate 1500; \n " +" vfps 25; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 12; \n " +" vprofile main; \n " +" vpreset medium; \n " +" vparams { \n " +" t 100; \n " +" coder 1; \n " +" b_strategy 2; \n " +" bf 3; \n " +" refs 10; \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 70; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" profile:a aac_low; \n " +" } \n " +" oformat flv; \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost mirror.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine mirror { \n " +" enabled on; \n " +" vfilter { \n " +" vf 'split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2'; \n " +" } \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost crop.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine crop { \n " +" enabled on; \n " +" vfilter { \n " +" vf 'crop=in_w-20:in_h-160:10:80'; \n " +" } \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost logo.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine logo { \n " +" enabled on; \n " +" vfilter { \n " +" i ./doc/ffmpeg-logo.png; \n " +" filter_complex 'overlay=10:10'; \n " +" } \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost audio.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine acodec { \n " +" enabled on; \n " +" vcodec copy; \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost vn.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine vn { \n " +" enabled on; \n " +" vcodec vn; \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost copy.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine copy { \n " +" enabled on; \n " +" vcodec copy; \n " +" acodec copy; \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost all.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine ffsuper { \n " +" enabled on; \n " +" iformat flv; \n " +" vfilter { \n " +" i ./doc/ffmpeg-logo.png; \n " +" filter_complex 'overlay=10:10'; \n " +" } \n " +" vcodec libx264; \n " +" vbitrate 1500; \n " +" vfps 25; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 12; \n " +" vprofile main; \n " +" vpreset medium; \n " +" vparams { \n " +" t 100; \n " +" coder 1; \n " +" b_strategy 2; \n " +" bf 3; \n " +" refs 10; \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 70; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" profile:a aac_low; \n " +" } \n " +" oformat flv; \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine ffhd { \n " +" enabled on; \n " +" vcodec libx264; \n " +" vbitrate 1200; \n " +" vfps 25; \n " +" vwidth 1382; \n " +" vheight 576; \n " +" vthreads 6; \n " +" vprofile main; \n " +" vpreset medium; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 70; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine ffsd { \n " +" enabled on; \n " +" vcodec libx264; \n " +" vbitrate 800; \n " +" vfps 25; \n " +" vwidth 1152; \n " +" vheight 480; \n " +" vthreads 4; \n " +" vprofile main; \n " +" vpreset fast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 60; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine fffast { \n " +" enabled on; \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine vcopy { \n " +" enabled on; \n " +" vcodec copy; \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine acopy { \n " +" enabled on; \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec copy; \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" engine copy { \n " +" enabled on; \n " +" vcodec copy; \n " +" acodec copy; \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost ffempty.transcode.srs.com { \n " +" transcode { \n " +" enabled on; \n " +" ffmpeg ./objs/research/ffempty; \n " +" engine empty { \n " +" enabled on; \n " +" vcodec libx264; \n " +" vbitrate 300; \n " +" vfps 20; \n " +" vwidth 768; \n " +" vheight 320; \n " +" vthreads 2; \n " +" vprofile baseline; \n " +" vpreset superfast; \n " +" vparams { \n " +" } \n " +" acodec libaacplus; \n " +" abitrate 45; \n " +" asample_rate 44100; \n " +" achannels 2; \n " +" aparams { \n " +" } \n " +" output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n " +" } \n " +" } \n " +"} \n " +"vhost app.transcode.srs.com { \n " +" transcode live { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine { \n " +" enabled off; \n " +" } \n " +" } \n " +"} \n " +"vhost stream.transcode.srs.com { \n " +" transcode live/livestream { \n " +" enabled on; \n " +" ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n " +" engine { \n " +" enabled off; \n " +" } \n " +" } \n " +"} \n " +" \n " +"vhost bandcheck.srs.com { \n " +" enabled on; \n " +" chunk_size 65000; \n " +" bandcheck { \n " +" enabled on; \n " +" key \"35c9b402c12a7246868752e2878f7e0e\"; \n " +" interval 30; \n " +" limit_kbps 4000; \n " +" } \n " +"} \n " +" \n " +"vhost chunksize.srs.com { \n " +" chunk_size 128; \n " +"} \n " +" \n " +"vhost jitter.srs.com { \n " +" time_jitter full; \n " +"} \n " +" \n " +"vhost atc.srs.com { \n " +" atc on; \n " +" atc_auto on; \n " +"} \n " +" \n " +"vhost removed.srs.com { \n " +" enabled off; \n " +"} \n " +" \n " +"pithy_print_ms 10000; \n " ; VOID TEST(ConfigTest, CheckMacros) @@ -1132,25 +721,7 @@ VOID TEST(ConfigTest, CheckMacros) #ifndef SRS_CONF_DEFAULT_STATS_NETWORK_DEVICE_INDEX EXPECT_TRUE(false); #endif -#ifndef SRS_CONF_DEFAULT_STAGE_PLAY_USER_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_PUBLISH_USER_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_FORWARDER_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_ENCODER_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_INGESTER_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_HLS_INTERVAL_MS - EXPECT_TRUE(false); -#endif -#ifndef SRS_CONF_DEFAULT_STAGE_EDGE_INTERVAL_MS +#ifndef SRS_CONF_DEFAULT_PITHY_PRINT_MS EXPECT_TRUE(false); #endif #ifndef SRS_CONF_DEFAULT_INGEST_TYPE_FILE @@ -1821,7 +1392,7 @@ VOID TEST(ConfigMainTest, ParseFullConf) EXPECT_EQ(1000, conf.get_max_connections()); EXPECT_TRUE(conf.get_deamon()); - EXPECT_TRUE(conf.get_heartbeat_enabled()); + EXPECT_FALSE(conf.get_heartbeat_enabled()); EXPECT_EQ(9300, conf.get_heartbeat_interval()); EXPECT_STREQ("http://127.0.0.1:8085/api/v1/servers", conf.get_heartbeat_url().c_str()); EXPECT_STREQ("my-srs-device", conf.get_heartbeat_device_id().c_str()); @@ -1838,13 +1409,7 @@ VOID TEST(ConfigMainTest, ParseFullConf) EXPECT_EQ(8080, conf.get_http_stream_listen()); EXPECT_STREQ("./objs/nginx/html", conf.get_http_stream_dir().c_str()); - EXPECT_EQ(10000, conf.get_pithy_print_publish()); - EXPECT_EQ(10000, conf.get_pithy_print_play()); - EXPECT_EQ(10000, conf.get_pithy_print_forwarder()); - EXPECT_EQ(10000, conf.get_pithy_print_encoder()); - EXPECT_EQ(10000, conf.get_pithy_print_ingester()); - EXPECT_EQ(10000, conf.get_pithy_print_hls()); - EXPECT_EQ(10000, conf.get_pithy_print_edge()); + EXPECT_EQ(10000, conf.get_pithy_print_ms()); EXPECT_TRUE(NULL != conf.get_vhost("__defaultVhost__")); EXPECT_TRUE(NULL != conf.get_vhost("same.edge.srs.com")); @@ -1949,7 +1514,7 @@ VOID TEST(ConfigMainTest, ParseFullConf) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// @@ -2356,9 +1921,9 @@ VOID TEST(ConfigMainTest, ParseFullConf_http) EXPECT_EQ(30, conf.get_dvr_duration(vhost)); EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); - EXPECT_TRUE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/hls", conf.get_vhost_http_mount(vhost).c_str()); - EXPECT_STREQ("./objs/nginx/html/hls", conf.get_vhost_http_dir(vhost).c_str()); + EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } VOID TEST(ConfigMainTest, ParseFullConf_hls_enabled) @@ -2435,7 +2000,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_hls_enabled) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2513,7 +2078,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_hls_disabled) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2622,7 +2187,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_http_hooks) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2701,7 +2266,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_min_delay) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2795,7 +2360,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_refer_anti_suck) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2879,7 +2444,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_forward_same_vhost) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -2959,7 +2524,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_forward_change_vhost) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str());*/ } @@ -3049,7 +2614,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_mirror) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3139,7 +2704,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_crop) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3229,7 +2794,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_logo) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3313,7 +2878,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_audio) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3397,7 +2962,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_vn) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3477,7 +3042,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_copy) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3695,7 +3260,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_all) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3785,7 +3350,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_ffempty) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3875,7 +3440,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_app) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -3965,7 +3530,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_transcode_stream) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -4044,7 +3609,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_bandcheck) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -4123,7 +3688,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_chunksize) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -4202,7 +3767,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_jitter) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -4281,7 +3846,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_atc) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -4360,7 +3925,7 @@ VOID TEST(ConfigMainTest, ParseFullConf_removed) EXPECT_TRUE(conf.get_dvr_wait_keyframe(vhost)); EXPECT_TRUE(SrsRtmpJitterAlgorithmFULL == conf.get_dvr_time_jitter(vhost)); EXPECT_FALSE(conf.get_vhost_http_enabled(vhost)); - EXPECT_STREQ("/", conf.get_vhost_http_mount(vhost).c_str()); + EXPECT_STREQ("[vhost]/", conf.get_vhost_http_mount(vhost).c_str()); EXPECT_STREQ("./objs/nginx/html", conf.get_vhost_http_dir(vhost).c_str()); } @@ -5472,82 +5037,12 @@ VOID TEST(ConfigMainTest, CheckConf_pithy_print) { if (true) { MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{}")); + EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print_ms 1000;")); } if (true) { MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_prints{}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{publish 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{publishs 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{play 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{plays 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{forwarder 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{forwarders 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{encoder 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{encoders 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{ingester 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{ingesters 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{hls 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{hlss 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print{edge 10000;}")); - } - - if (true) { - MockSrsConfig conf; - EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print{edges 10000;}")); + EXPECT_TRUE(ERROR_SUCCESS != conf.parse(_MIN_OK_CONF"pithy_print_mss 1000;")); } } diff --git a/trunk/src/utest/srs_utest_reload.cpp b/trunk/src/utest/srs_utest_reload.cpp index 94b51813d..166a0247c 100644 --- a/trunk/src/utest/srs_utest_reload.cpp +++ b/trunk/src/utest/srs_utest_reload.cpp @@ -460,17 +460,17 @@ VOID TEST(ConfigReloadTest, ReloadPithyPrint) MockSrsReloadConfig conf; conf.subscribe(&handler); - EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print {publish 1000;}")); - EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print {publish 1000;}")); + EXPECT_TRUE(ERROR_SUCCESS == conf.parse(_MIN_OK_CONF"pithy_print_ms 1000;")); + EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print_ms 1000;")); EXPECT_TRUE(handler.all_false()); handler.reset(); - EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print {publish 2000;}")); + EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print_ms 2000;")); EXPECT_TRUE(handler.pithy_print_reloaded); EXPECT_EQ(1, handler.count_true()); handler.reset(); - EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print {publish 1000;}")); + EXPECT_TRUE(ERROR_SUCCESS == conf.reload(_MIN_OK_CONF"pithy_print_ms 1000;")); EXPECT_EQ(1, handler.count_true()); handler.reset(); }