mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	Merge branch 'feature/rtc' into develop
This commit is contained in:
		
						commit
						1c72a89fca
					
				
					 97 changed files with 654 additions and 9368 deletions
				
			
		
							
								
								
									
										17
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								README.md
									
										
									
									
									
								
							|  | @ -159,7 +159,8 @@ For previous versions, please read: | |||
| 
 | ||||
| ## V4 changes | ||||
| 
 | ||||
| * v4.0, 2020-06-13, GB28181 with JitterBuffer support. 4.0.29 | ||||
| * v4.0, 2020-06-13, GB28181 with JitterBuffer support. 4.0.30 | ||||
| * v4.0, 2020-06-03, Support enable C++11. 4.0.29 | ||||
| * v4.0, 2020-05-31, Remove [srs-librtmp](https://github.com/ossrs/srs/issues/1535#issuecomment-633907655). 4.0.28 | ||||
| * v4.0, 2020-05-21, For [#307][bug #307], disable GSO and sendmmsg. 4.0.27 | ||||
| * v4.0, 2020-05-14, For [#307][bug #307], refine core structure, RTMP base on frame, RTC base on RTP. 4.0.26 | ||||
|  | @ -1091,14 +1092,12 @@ SRS always use the simplest architecture to solve complex domain problems. | |||
| ## Modularity Architecture | ||||
| 
 | ||||
| ``` | ||||
| +----------------+-------------------------------------+ | ||||
| | SRS/SRT server |    Programs in Main or Research     | | ||||
| +----------------+--+------------+---------------------+ | ||||
| |  App(For SRS)     | Modules(1) |  research/librtmp   | | ||||
| +-------------------+------------+---------------------+ | ||||
| |    Service(C/S apps over ST)   |     srs-librtmp     | | ||||
| +--------------------------------+---------------------+ | ||||
| |   Protocol Stack(RTMP/HTTP/RTSP/JSON/AMF/Format)     | | ||||
| +--------------------+---------------------------------+ | ||||
| |   SRS/SRT server   |       Programs in Main          | | ||||
| +--------------------+-------+-------------------------+ | ||||
| |  App(For SRS)              |      Modules(1)         | | ||||
| +----------------------------+-------------------------+ | ||||
| |   Protocol Stack(RTMP/HTTP/RTSP/JSON/AMF/Service)    | | ||||
| +------------------------------------------------------+ | ||||
| |      Kernel(File, Codec, Stream, LB services)        | | ||||
| +------------------------------------------------------+ | ||||
|  |  | |||
							
								
								
									
										4
									
								
								trunk/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								trunk/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -40,3 +40,7 @@ srs | |||
| *.ts | ||||
| *.h264 | ||||
| *.264 | ||||
| /webrtc | ||||
| /configure.sh | ||||
| /janus | ||||
| 
 | ||||
|  |  | |||
|  | @ -69,6 +69,18 @@ else | |||
|     srs_undefine_macro "SRS_SRT" $SRS_AUTO_HEADERS_H | ||||
| fi | ||||
| 
 | ||||
| if [ $SRS_CXX11 = YES ]; then | ||||
|     srs_define_macro "SRS_CXX11" $SRS_AUTO_HEADERS_H | ||||
| else | ||||
|     srs_undefine_macro "SRS_CXX11" $SRS_AUTO_HEADERS_H | ||||
| fi | ||||
| 
 | ||||
| if [ $SRS_CXX14 = YES ]; then | ||||
|     srs_define_macro "SRS_CXX14" $SRS_AUTO_HEADERS_H | ||||
| else | ||||
|     srs_undefine_macro "SRS_CXX14" $SRS_AUTO_HEADERS_H | ||||
| fi | ||||
| 
 | ||||
| if [ $SRS_RTC = YES ]; then | ||||
|     srs_define_macro "SRS_RTC" $SRS_AUTO_HEADERS_H | ||||
| else | ||||
|  |  | |||
|  | @ -1,112 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| ff_src_dir="../../3rdparty" | ||||
| 
 | ||||
| # the jobs to make ffmpeg | ||||
| if [[ "" == $SRS_JOBS ]]; then  | ||||
|     export SRS_JOBS="--jobs=1"  | ||||
| fi | ||||
| 
 | ||||
| ff_current_dir=$(pwd -P) | ||||
| ff_build_dir="${ff_current_dir}/_build" | ||||
| ff_release_dir="${ff_current_dir}/_release" | ||||
| echo "start to build the tools for transcode system:" | ||||
| echo "current_dir: ${ff_current_dir}" | ||||
| echo "build_dir: ${ff_build_dir}" | ||||
| echo "release_dir: ${ff_release_dir}" | ||||
| echo "SRS_JOBS: ${SRS_JOBS}" | ||||
| 
 | ||||
| mkdir -p ${ff_build_dir} | ||||
| mkdir -p ${ff_release_dir} | ||||
| 
 | ||||
| # yasm for libx264 | ||||
| ff_yasm_bin=${ff_release_dir}/bin/yasm | ||||
| if [[ -f ${ff_yasm_bin} ]]; then  | ||||
|     echo "yasm is ok" | ||||
| else | ||||
|     echo "build yasm-1.2.0" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf yasm-1.2.0 && unzip -q ${ff_src_dir}/yasm-1.2.0.zip && | ||||
|     cd yasm-1.2.0 && ./configure --prefix=${ff_release_dir} && | ||||
|     make && make install | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build yasm-1.2.0 failed"; exit 1; fi | ||||
| fi | ||||
| # add yasm to path, for x264 to use yasm directly. | ||||
| # ffmpeg can specifies the yasm path when configure it. | ||||
| export PATH=${PATH}:${ff_release_dir}/bin | ||||
| 
 | ||||
| # libfdk-aac | ||||
| if [[ -f ${ff_release_dir}/lib/libfdk-aac.a ]]; then | ||||
|     echo "libfdk_aac is ok" | ||||
| else | ||||
|     echo "build fdk-aac-0.1.3" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf fdk-aac-0.1.3 && unzip -q ${ff_src_dir}/fdk-aac-0.1.3.zip && | ||||
|     cd fdk-aac-0.1.3 && bash autogen.sh && ./configure --prefix=${ff_release_dir} --enable-static && make ${SRS_JOBS} && make install | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build fdk-aac-0.1.3 failed"; exit 1; fi | ||||
| fi | ||||
| 
 | ||||
| # lame-3.99 | ||||
| if [[ -f ${ff_release_dir}/lib/libmp3lame.a ]]; then | ||||
|     echo "libmp3lame is ok" | ||||
| else | ||||
|     echo "build lame-3.99.5" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf lame-3.99.5 && unzip -q ${ff_src_dir}/lame-3.99.5.zip && | ||||
|     cd lame-3.99.5 && ./configure --prefix=${ff_release_dir} --enable-static && make ${SRS_JOBS} && make install | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build lame-3.99.5 failed"; exit 1; fi | ||||
| fi | ||||
| 
 | ||||
| # speex-1.2rc1 | ||||
| if [[ -f ${ff_release_dir}/lib/libspeex.a ]]; then | ||||
|     echo "libspeex is ok" | ||||
| else | ||||
|     echo "build speex-1.2rc1" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf speex-1.2rc1 && unzip -q ${ff_src_dir}/speex-1.2rc1.zip && | ||||
|     cd speex-1.2rc1 && ./configure --prefix=${ff_release_dir} --enable-static && make ${SRS_JOBS} && make install | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build speex-1.2rc1 failed"; exit 1; fi | ||||
| fi | ||||
| 
 | ||||
| # x264 core.157 | ||||
| if [[ -f ${ff_release_dir}/lib/libx264.a ]]; then | ||||
|     echo "x264 is ok" | ||||
| else | ||||
|     echo "build x264" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf x264-snapshot-20181116-2245 && unzip -q ${ff_src_dir}/x264-snapshot-20181116-2245.zip && | ||||
|     cd x264-snapshot-20181116-2245 &&  | ||||
|     ./configure --prefix=${ff_release_dir} --disable-opencl --bit-depth=all \ | ||||
|         --enable-static --disable-avs  --disable-swscale  --disable-lavf \ | ||||
|         --disable-ffms  --disable-gpac --disable-cli &&  | ||||
|     make ${SRS_JOBS} && make install | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build x264 failed"; exit 1; fi | ||||
| fi | ||||
| 
 | ||||
| # ffmpeg-4.1 | ||||
| if [[ -f ${ff_release_dir}/bin/ffmpeg ]]; then | ||||
|     echo "ffmpeg-4.1 is ok" | ||||
| else | ||||
|     echo "build ffmpeg-4.1" | ||||
|     cd $ff_current_dir && | ||||
|     rm -rf ffmpeg-4.1 && unzip -q ${ff_src_dir}/ffmpeg-4.1.zip && | ||||
|     echo "remove all so to force the ffmpeg to build in static" && | ||||
|     rm -f ${ff_release_dir}/lib/*.so* && | ||||
|     echo "export the dir to enable the build command canbe use." && | ||||
|     export ffmpeg_exported_release_dir=${ff_release_dir} && | ||||
|     cd ffmpeg-4.1 &&  | ||||
|     ./configure \ | ||||
|         --enable-gpl --enable-nonfree \ | ||||
|         --yasmexe=${ff_yasm_bin} \ | ||||
|         --prefix=${ff_release_dir} --cc= \ | ||||
|         --enable-static --disable-shared --disable-debug \ | ||||
|         --extra-cflags='-I${ffmpeg_exported_release_dir}/include' \ | ||||
|         --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \ | ||||
|         --disable-ffplay --disable-ffprobe --disable-doc \ | ||||
|         --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ | ||||
|         --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 | ||||
|     ret=$?; if [[ 0 -ne ${ret} ]]; then echo "build ffmpeg failed"; exit 1; fi | ||||
| fi | ||||
|  | @ -1,8 +0,0 @@ | |||
| #!/bin/bash | ||||
| # genereate the library header file. | ||||
| 
 | ||||
| objs=$1 | ||||
| 
 | ||||
| rm -f $objs/include/srs_librtmp.h && | ||||
| cp $objs/../src/libs/srs_librtmp.hpp $objs/include/srs_librtmp.h | ||||
| echo "genereate srs-librtmp headers success" | ||||
|  | @ -29,8 +29,8 @@ echo "# INCS for ${MODULE_ID}, headers of module and its depends to compile" >> | |||
| echo "${MODULE_ID}_MODULE_INCS = -I${MODULE_DIR} " >> ${FILE} | ||||
| # | ||||
| # the private include files, for example: | ||||
| #       CORE_INCS = -Isrc/core -Iobjs/st -Iobjs -Iobjs/hp -Iobjs  | ||||
| #       MAIN_INCS = -Isrc/main $(CORE_MODULE_INCS) -Iobjs/st -Iobjs | ||||
| #       CORE_INCS = -Isrc/core -Iobjs | ||||
| #       CORE_LIBS_INCS = -Iobjs/st -Iobjs/ffmpeg/include | ||||
| # where the public will be used for other modules which depends on it. | ||||
| INCS_NAME="${MODULE_ID}_INCS" | ||||
| # | ||||
|  | @ -39,12 +39,14 @@ echo -n "${INCS_NAME} = -I${MODULE_DIR} " >> ${FILE} | |||
| # | ||||
| # depends module header files | ||||
| for item in ${MODULE_DEPENDS[*]}; do | ||||
|     DEP_INCS_NAME="${item}_INCS"do | ||||
|     DEP_INCS_NAME="${item}_MODULE_INCS" | ||||
|     echo -n "\$(${DEP_INCS_NAME})" >> ${FILE} | ||||
| done | ||||
| echo "" >> ${FILE} | ||||
| # | ||||
| # depends library header files | ||||
| INCS_LIBS_NAME="${MODULE_ID}_LIBS_INCS" | ||||
| echo -n "${INCS_LIBS_NAME} = " >> ${FILE} | ||||
| for item in ${ModuleLibIncs[*]}; do | ||||
|     echo -n "-I${item} " >> ${FILE} | ||||
| done | ||||
|  | @ -58,6 +60,7 @@ DEPS_NAME="${MODULE_ID}_DEPS" | |||
| echo -n "${DEPS_NAME} = " >> ${FILE} | ||||
| for item in ${MODULE_FILES[*]}; do | ||||
|     HEADER_FILE="${MODULE_DIR}/${item}.hpp" | ||||
|     if [[ ! -f ${HEADER_FILE} ]]; then HEADER_FILE="${MODULE_DIR}/${item}.h"; fi | ||||
|     if [ -f ${HEADER_FILE} ]; then | ||||
|         echo -n " ${HEADER_FILE}" >> ${FILE} | ||||
|     fi | ||||
|  | @ -75,13 +78,16 @@ echo "# OBJ for ${MODULE_ID}, each object file" >> ${FILE} | |||
| MODULE_OBJS=() | ||||
| for item in ${MODULE_FILES[*]}; do | ||||
|     CPP_FILE="${MODULE_DIR}/${item}.cpp" | ||||
|     if [[ ! -f ${CPP_FILE} ]]; then CPP_FILE="${MODULE_DIR}/${item}.cc"; fi | ||||
|     OBJ_FILE="${SRS_OBJS_DIR}/${MODULE_DIR}/${item}.o" | ||||
|     MODULE_OBJS="${MODULE_OBJS[@]} ${CPP_FILE}" | ||||
|     if [ -f ${CPP_FILE} ]; then | ||||
|         echo "${OBJ_FILE}: \$(${DEPS_NAME}) ${CPP_FILE} " >> ${FILE} | ||||
|         echo "	\$(CXX) -c \$(CXXFLAGS) ${DEFINES}\\" >> ${FILE} | ||||
|         echo "          \$(${INCS_NAME})\\" >> ${FILE} | ||||
|         echo "          -o ${OBJ_FILE} ${CPP_FILE}" >> ${FILE} | ||||
|         echo "    \$(${INCS_NAME})\\" >> ${FILE} | ||||
|         echo "    \$(${INCS_LIBS_NAME})\\" >> ${FILE} | ||||
|         echo "    -o ${OBJ_FILE} \\" >> ${FILE} | ||||
|         echo "    ${CPP_FILE}" >> ${FILE} | ||||
|     fi | ||||
| done | ||||
| echo "" >> ${FILE} | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ SRS_HDS=NO | |||
| SRS_SRT=NO | ||||
| SRS_RTC=YES | ||||
| SRS_GB28181=NO | ||||
| SRS_CXX11=NO | ||||
| SRS_CXX14=NO | ||||
| SRS_NGINX=NO | ||||
| SRS_FFMPEG_TOOL=NO | ||||
| SRS_LIBRTMP=NO | ||||
|  | @ -149,6 +151,8 @@ Features: | |||
|   --srt=on|off              Whether build the SRT support for SRS. | ||||
|   --rtc=on|off              Whether build the WebRTC support for SRS. | ||||
|   --gb28181=on|off          Whether build the GB28181 support for SRS. | ||||
|   --cxx11=on|off            Whether enable the C++11 support for SRS. | ||||
|   --cxx14=on|off            Whether enable the C++14 support for SRS. | ||||
| 
 | ||||
|   --prefix=<path>           The absolute installation path for srs. Default: $SRS_PREFIX | ||||
|   --gcov=on|off             Whether enable the GCOV compiler options. | ||||
|  | @ -321,6 +325,9 @@ function parse_user_option() { | |||
|         --without-gb28181)              SRS_GB28181=NO              ;; | ||||
|         --gb28181)                      if [[ $value == off ]]; then SRS_GB28181=NO; else SRS_GB28181=YES; fi    ;; | ||||
| 
 | ||||
|         --cxx11)                        if [[ $value == off ]]; then SRS_CXX11=NO; else SRS_CXX11=YES; fi    ;; | ||||
|         --cxx14)                        if [[ $value == off ]]; then SRS_CXX14=NO; else SRS_CXX14=YES; fi    ;; | ||||
| 
 | ||||
|         --with-clean)                   SRS_CLEAN=YES               ;; | ||||
|         --without-clean)                SRS_CLEAN=NO                ;; | ||||
|         --clean)                        if [[ $value == off ]]; then SRS_CLEAN=NO; else SRS_CLEAN=YES; fi    ;; | ||||
|  | @ -514,6 +521,11 @@ function apply_user_presets() { | |||
|         SRS_UTEST=NO | ||||
|         SRS_STATIC=NO | ||||
|     fi | ||||
| 
 | ||||
|     # Enable c++11 for SRT. | ||||
|     if [[ $SRS_SRT == YES ]]; then | ||||
|         SRS_CXX11=YES | ||||
|     fi | ||||
| } | ||||
| apply_user_presets | ||||
| 
 | ||||
|  | @ -613,6 +625,8 @@ function regenerate_options() { | |||
|     if [ $SRS_RTC = YES ]; then             SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --rtc=on"; else             SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --rtc=off"; fi | ||||
|     if [ $SRS_SIMULATOR = YES ]; then       SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --simulator=on"; else       SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --simulator=off"; fi | ||||
|     if [ $SRS_GB28181 = YES ]; then         SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --gb28181=on"; else         SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --gb28181=off"; fi | ||||
|     if [ $SRS_CXX11 = YES ]; then           SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cxx11=on"; else         SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cxx11=off"; fi | ||||
|     if [ $SRS_CXX14 = YES ]; then           SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cxx14=on"; else         SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cxx14=off"; fi | ||||
|     if [ $SRS_NASM = YES ]; then            SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --nasm=on"; else            SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --nasm=off"; fi | ||||
|     if [ $SRS_SRTP_ASM = YES ]; then        SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --srtp-nasm=on"; else       SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --srtp-nasm=off"; fi | ||||
|     if [ $SRS_SENDMMSG = YES ]; then        SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --sendmmsg=on"; else        SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --sendmmsg=off"; fi | ||||
|  |  | |||
|  | @ -491,6 +491,10 @@ vhost rtc.vhost.srs.com { | |||
|         # The strick check when process stun. | ||||
|         # default: off | ||||
|         stun_strict_check on; | ||||
|         # Whether keep original sequence number. | ||||
|         # If off, we will regenerate the sequence number for RTP packet. | ||||
|         # default: off | ||||
|         keep_sequence off; | ||||
|     } | ||||
|     # whether enable min delay mode for vhost. | ||||
|     # default: on, for RTC. | ||||
|  | @ -511,6 +515,12 @@ vhost rtc.vhost.srs.com { | |||
|         # default: on | ||||
|         enabled on; | ||||
|     } | ||||
|     # For TWCC. | ||||
|     twcc { | ||||
|         # Whether support TWCC. | ||||
|         # default: on | ||||
|         enabled on; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ############################################################################################# | ||||
|  | @ -2065,33 +2075,6 @@ vhost all.transcode.srs.com { | |||
|         } | ||||
|     } | ||||
| } | ||||
| # transcode all stream using the empty ffmpeg demo, do nothing. | ||||
| vhost ffempty.transcode.srs.com { | ||||
|     transcode { | ||||
|         enabled     on; | ||||
|         ffmpeg ./objs/research/ffempty; | ||||
|         engine empty { | ||||
|             enabled         on; | ||||
|             vcodec          libx264; | ||||
|             vbitrate        300; | ||||
|             vfps            20; | ||||
|             vwidth          768; | ||||
|             vheight         320; | ||||
|             vthreads        2; | ||||
|             vprofile        baseline; | ||||
|             vpreset         superfast; | ||||
|             vparams { | ||||
|             } | ||||
|             acodec          libfdk_aac; | ||||
|             abitrate        45; | ||||
|             asample_rate    44100; | ||||
|             achannels       2; | ||||
|             aparams { | ||||
|             } | ||||
|             output          rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| # transcode all app and stream of app | ||||
| vhost app.transcode.srs.com { | ||||
|     # the streaming transcode configs. | ||||
|  |  | |||
|  | @ -1,36 +0,0 @@ | |||
| # 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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										53
									
								
								trunk/configure
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								trunk/configure
									
										
									
									
										vendored
									
									
								
							|  | @ -87,9 +87,12 @@ GDBDebug=" -g -O0" | |||
| WarnLevel=" -Wall" | ||||
| # the compile standard. | ||||
| CppStd="-ansi" | ||||
| if [[ $SRS_SRT == YES ]]; then | ||||
| if [[ $SRS_CXX11 == YES ]]; then | ||||
|     CppStd="-std=c++11" | ||||
| fi | ||||
| if [[ $SRS_CXX14 == YES ]]; then | ||||
|     CppStd="-std=c++14" | ||||
| fi | ||||
| # performance of gprof | ||||
| SrsGprof=""; SrsGprofLink=""; if [ $SRS_GPROF = YES ]; then SrsGprof=" -pg -lc_p"; SrsGprofLink=" -pg"; fi | ||||
| # performance of gperf | ||||
|  | @ -211,13 +214,15 @@ KERNEL_OBJS="${MODULE_OBJS[@]}" | |||
| #RTMP/HTTP/Raw Protocol, depends on core/kernel, provides rtmp/htttp protocol features. | ||||
| MODULE_ID="PROTOCOL"  | ||||
| MODULE_DEPENDS=("CORE" "KERNEL")  | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibSSLRoot}) | ||||
| MODULE_FILES=("srs_protocol_amf0" "srs_protocol_io" "srs_rtmp_stack" | ||||
|         "srs_rtmp_handshake" "srs_protocol_utility" "srs_rtmp_msg_array" "srs_protocol_stream" | ||||
|         "srs_raw_avc" "srs_rtsp_stack" "srs_sip_stack" "srs_http_stack" "srs_protocol_kbps" "srs_protocol_json" | ||||
|         "srs_protocol_format") | ||||
|         "srs_protocol_format" "srs_service_log" "srs_service_st" "srs_service_http_client" "srs_service_http_conn" | ||||
|         "srs_service_rtmp_conn" "srs_service_utility" "srs_service_conn") | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     MODULE_FILES+=("srs_rtc_stun_stack") | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
| PROTOCOL_INCS="src/protocol"; MODULE_DIR=${PROTOCOL_INCS} . auto/modules.sh | ||||
| PROTOCOL_OBJS="${MODULE_OBJS[@]}" | ||||
|  | @ -225,33 +230,21 @@ PROTOCOL_OBJS="${MODULE_OBJS[@]}" | |||
| #srt protocol features. | ||||
| if [ $SRS_SRT = YES ]; then | ||||
|     MODULE_ID="SRT" | ||||
|     MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "SERVICE" "APP") | ||||
|     MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "APP") | ||||
|     ModuleLibIncs=(${SRS_OBJS_DIR}) | ||||
|     MODULE_FILES=("srt_server" "srt_handle" "srt_conn" "srt_to_rtmp" "ts_demux" "srt_data") | ||||
|     SRT_INCS=${LibSRTRoot}; MODULE_DIR=${LibSRTRoot} . auto/modules.sh | ||||
|     SRT_OBJS="${MODULE_OBJS[@]}" | ||||
| fi | ||||
| 
 | ||||
| # | ||||
| #Service Module, for both Server and Client Modules. | ||||
| # TODO: FIXME: Remove service module, https://github.com/ossrs/srs/issues/1535#issuecomment-633907655 | ||||
| MODULE_ID="SERVICE" | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL") | ||||
| ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibSSLRoot}) | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
| MODULE_FILES=("srs_service_log" "srs_service_st" "srs_service_http_client" | ||||
|     "srs_service_http_conn" "srs_service_rtmp_conn" "srs_service_utility" | ||||
|     "srs_service_conn") | ||||
| DEFINES="" | ||||
| SERVICE_INCS="src/service"; MODULE_DIR=${SERVICE_INCS} . auto/modules.sh | ||||
| SERVICE_OBJS="${MODULE_OBJS[@]}" | ||||
| # | ||||
| #App Module, for SRS server only. | ||||
| MODULE_ID="APP" | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "SERVICE") | ||||
| ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibSSLRoot} ${LibGperfRoot}) | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL") | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibSSLRoot}) | ||||
| if [ $SRS_GPERF = YES ]; then | ||||
|     ModuleLibIncs+=(${LibGperfRoot}) | ||||
| fi | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
|  | @ -285,11 +278,11 @@ APP_OBJS="${MODULE_OBJS[@]}" | |||
| # | ||||
| #Server Module, for SRS only. | ||||
| MODULE_ID="SERVER" | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "SERVICE" "APP") | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "APP") | ||||
| if [[ $SRS_SRT == YES ]]; then | ||||
|     MODULE_DEPENDS+=("SRT") | ||||
| fi | ||||
| ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
|  | @ -302,8 +295,8 @@ SERVER_OBJS="${MODULE_OBJS[@]}" | |||
| # | ||||
| #Main Module, for app from modules. | ||||
| MODULE_ID="MAIN" | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "SERVICE") | ||||
| ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL") | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
|  | @ -338,8 +331,8 @@ if [[ $SRS_SRT == YES ]]; then | |||
|     ModuleLibFiles+=("${LibSRTfile[*]}") | ||||
| fi | ||||
| # all depends objects | ||||
| MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${SERVICE_OBJS[@]} ${APP_OBJS[@]} ${SERVER_OBJS[@]}" | ||||
| ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${APP_OBJS[@]} ${SERVER_OBJS[@]}" | ||||
| ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSTRoot} ${LibGperfRoot} ${LibSSLRoot}) | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibIncs+=("${LibFfmpegRoot[*]}" ${LibSrtpRoot}) | ||||
| fi | ||||
|  | @ -352,7 +345,7 @@ LINK_OPTIONS="${SrsLinkOptions}${SrsGprofLink}${SrsGperfLink}" | |||
| BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" . auto/apps.sh | ||||
| # | ||||
| # For modules, without the app module. | ||||
| MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${SERVICE_OBJS[@]} ${MAIN_OBJS[@]}" | ||||
| MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${MAIN_OBJS[@]}" | ||||
| ModuleLibFiles=(${LibSTfile} ${LibSSLfile} ${LibGperfFile}) | ||||
| if [[ $SRS_RTC == YES ]]; then | ||||
|     ModuleLibFiles+=("${LibFfmpegFile[*]}" ${LibSrtpFile}) | ||||
|  | @ -389,11 +382,11 @@ if [ $SRS_UTEST = YES ]; then | |||
|     if [[ $SRS_SRT == YES ]]; then | ||||
|         ModuleLibFiles+=("${LibSRTfile[*]}") | ||||
|     fi | ||||
|     MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "SERVICE" "APP") | ||||
|     MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL" "APP") | ||||
|     if [[ $SRS_SRT == YES ]]; then | ||||
|         MODULE_DEPENDS+=("SRT") | ||||
|     fi | ||||
|     MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${SERVICE_OBJS[@]} ${APP_OBJS[@]} ${SRT_OBJS[@]}" | ||||
|     MODULE_OBJS="${CORE_OBJS[@]} ${KERNEL_OBJS[@]} ${PROTOCOL_OBJS[@]} ${APP_OBJS[@]} ${SRT_OBJS[@]}" | ||||
|     LINK_OPTIONS="-lpthread ${SrsLinkOptions}" MODULE_DIR="src/utest" APP_NAME="srs_utest" . auto/utest.sh | ||||
| fi | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,13 +4,6 @@ file | |||
|     ../../src/main/srs_main_ingest_hls.cpp, | ||||
|     auto readonly separator, | ||||
|     ../../objs/srs_auto_headers.hpp, | ||||
|     libs readonly separator, | ||||
|     ../../src/libs/srs_librtmp.hpp, | ||||
|     ../../src/libs/srs_librtmp.cpp, | ||||
|     ../../src/libs/srs_lib_bandwidth.hpp, | ||||
|     ../../src/libs/srs_lib_bandwidth.cpp, | ||||
|     ../../src/libs/srs_lib_simple_socket.hpp, | ||||
|     ../../src/libs/srs_lib_simple_socket.cpp, | ||||
|     core readonly separator, | ||||
|     ../../src/core/srs_core.hpp, | ||||
|     ../../src/core/srs_core.cpp, | ||||
|  | @ -167,21 +160,7 @@ file | |||
|     ../../src/utest/srs_utest_protocol.hpp, | ||||
|     ../../src/utest/srs_utest_protocol.cpp, | ||||
|     ../../src/utest/srs_utest_reload.hpp, | ||||
|     ../../src/utest/srs_utest_reload.cpp, | ||||
|     research readonly separator, | ||||
|     ../../research/librtmp/srs_aac_raw_publish.c, | ||||
|     ../../research/librtmp/srs_audio_raw_publish.c, | ||||
|     ../../research/librtmp/srs_bandwidth_check.c, | ||||
|     ../../research/librtmp/srs_detect_rtmp.c, | ||||
|     ../../research/librtmp/srs_flv_injecter.c, | ||||
|     ../../research/librtmp/srs_flv_parser.c, | ||||
|     ../../research/librtmp/srs_h264_raw_publish.c, | ||||
|     ../../research/librtmp/srs_ingest_flv.c, | ||||
|     ../../research/librtmp/srs_ingest_rtmp.c, | ||||
|     ../../research/librtmp/srs_play.c, | ||||
|     ../../research/librtmp/srs_publish.c, | ||||
|     ../../research/librtmp/srs_rtmp_dump.c, | ||||
|     ../../research/hls/ts_info.cc; | ||||
|     ../../src/utest/srs_utest_reload.cpp; | ||||
| 
 | ||||
| mainconfig | ||||
|     "" = "MAIN"; | ||||
|  |  | |||
|  | @ -116,9 +116,6 @@ | |||
|     <ClInclude Include="..\..\src\kernel\srs_kernel_buffer.hpp" /> | ||||
|     <ClInclude Include="..\..\src\kernel\srs_kernel_ts.hpp" /> | ||||
|     <ClInclude Include="..\..\src\kernel\srs_kernel_utility.hpp" /> | ||||
|     <ClInclude Include="..\..\src\libs\srs_librtmp.hpp" /> | ||||
|     <ClInclude Include="..\..\src\libs\srs_lib_bandwidth.hpp" /> | ||||
|     <ClInclude Include="..\..\src\libs\srs_lib_simple_socket.hpp" /> | ||||
|     <ClInclude Include="..\..\src\protocol\srs_http_stack.hpp" /> | ||||
|     <ClInclude Include="..\..\src\protocol\srs_raw_avc.hpp" /> | ||||
|     <ClInclude Include="..\..\src\protocol\srs_protocol_amf0.hpp" /> | ||||
|  | @ -132,19 +129,6 @@ | |||
|     <ClInclude Include="..\..\src\protocol\srs_protocol_kbps.hpp" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\..\research\hls\ts_info.cc" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_aac_raw_publish.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_audio_raw_publish.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_bandwidth_check.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_detect_rtmp.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_flv_injecter.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_flv_parser.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_h264_raw_publish.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_ingest_flv.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_ingest_rtmp.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_play.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_publish.c" /> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_rtmp_dump.c" /> | ||||
|     <ClCompile Include="..\..\src\app\srs_app_bandwidth.cpp" /> | ||||
|     <ClCompile Include="..\..\src\app\srs_app_config.cpp" /> | ||||
|     <ClCompile Include="..\..\src\app\srs_app_conn.cpp" /> | ||||
|  | @ -198,9 +182,6 @@ | |||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_buffer.cpp" /> | ||||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_ts.cpp" /> | ||||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_utility.cpp" /> | ||||
|     <ClCompile Include="..\..\src\libs\srs_librtmp.cpp" /> | ||||
|     <ClCompile Include="..\..\src\libs\srs_lib_bandwidth.cpp" /> | ||||
|     <ClCompile Include="..\..\src\libs\srs_lib_simple_socket.cpp" /> | ||||
|     <ClCompile Include="..\..\src\main\srs_main_server.cpp" /> | ||||
|     <ClCompile Include="..\..\src\protocol\srs_http_stack.cpp" /> | ||||
|     <ClCompile Include="..\..\src\protocol\srs_raw_avc.cpp" /> | ||||
|  |  | |||
|  | @ -1,21 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_detect_rtmp.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_flv_injecter.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_flv_parser.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_ingest_flv.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_ingest_rtmp.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\app\srs_app_http.cpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -127,9 +112,6 @@ | |||
|     <ClCompile Include="..\..\src\core\srs_core_performance.cpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_h264_raw_publish.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_aac.cpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -163,36 +145,6 @@ | |||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_utility.cpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_play.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_publish.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_rtmp_dump.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\hls\ts_info.cc"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_audio_raw_publish.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_bandwidth_check.c"> | ||||
|       <Filter>research</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\libs\srs_lib_bandwidth.cpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\libs\srs_lib_simple_socket.cpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\libs\srs_librtmp.cpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\research\librtmp\srs_aac_raw_publish.c"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\kernel\srs_kernel_ts.cpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -378,15 +330,6 @@ | |||
|     <ClInclude Include="..\..\src\kernel\srs_kernel_utility.hpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\src\libs\srs_librtmp.hpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\src\libs\srs_lib_bandwidth.hpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\src\libs\srs_lib_simple_socket.hpp"> | ||||
|       <Filter>librtmp</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\src\kernel\srs_kernel_ts.hpp"> | ||||
|       <Filter>srs</Filter> | ||||
|     </ClInclude> | ||||
|  | @ -434,14 +377,8 @@ | |||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="research"> | ||||
|       <UniqueIdentifier>{7e9069c1-f19c-4ab0-b47f-36d7903cfa8b}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="srs"> | ||||
|       <UniqueIdentifier>{0919b792-be75-49ed-b15a-2dc521e8394f}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="librtmp"> | ||||
|       <UniqueIdentifier>{d45a9ecb-fcbe-4400-abe3-792cddecb47e}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  |  | |||
|  | @ -77,9 +77,6 @@ | |||
| 		3C24ECCE1C3B824800460622 /* memory.error.tcmalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C24ECCC1C3B824800460622 /* memory.error.tcmalloc.cpp */; }; | ||||
| 		3C26E3C61BB146FF00D0F9DB /* srs_app_kafka.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C26E3C41BB146FF00D0F9DB /* srs_app_kafka.cpp */; }; | ||||
| 		3C28EDDF1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */; }; | ||||
| 		3C36DB5B1ABD1CB90066CCAF /* srs_lib_bandwidth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB551ABD1CB90066CCAF /* srs_lib_bandwidth.cpp */; }; | ||||
| 		3C36DB5C1ABD1CB90066CCAF /* srs_lib_simple_socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB571ABD1CB90066CCAF /* srs_lib_simple_socket.cpp */; }; | ||||
| 		3C36DB5D1ABD1CB90066CCAF /* srs_librtmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */; }; | ||||
| 		3C44AACF1E3AF50200D4ABC3 /* srs_kernel_mp4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C44AACD1E3AF50200D4ABC3 /* srs_kernel_mp4.cpp */; }; | ||||
| 		3C4AB9331B8C9148006627D3 /* srs_app_ng_exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C4AB9311B8C9148006627D3 /* srs_app_ng_exec.cpp */; }; | ||||
| 		3C4D184C1E73F133008806F7 /* srs_app_fragment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D184A1E73F133008806F7 /* srs_app_fragment.cpp */; }; | ||||
|  | @ -87,16 +84,6 @@ | |||
| 		3C5265B41B241BF0009CA186 /* srs_core_mem_watch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */; }; | ||||
| 		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 */; }; | ||||
| 		3C6F2D751E8653BF003D0805 /* srs_main_mp4_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6F2D741E8653BF003D0805 /* srs_main_mp4_parser.cpp */; }; | ||||
| 		3C82802C1BAFF8CC004A1794 /* srs_kafka_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C82802A1BAFF8CC004A1794 /* srs_kafka_stack.cpp */; }; | ||||
| 		3C8CE01E1C3F482100548CC6 /* srs_app_hourglass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C8CE01D1C3F482100548CC6 /* srs_app_hourglass.cpp */; }; | ||||
|  | @ -342,18 +329,10 @@ | |||
| 		3C1EE6D31AB1367D00576EE9 /* AUTHORS.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = AUTHORS.txt; path = ../../../AUTHORS.txt; sourceTree = "<group>"; }; | ||||
| 		3C1EE6D51AB1367D00576EE9 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../../../LICENSE; sourceTree = "<group>"; }; | ||||
| 		3C1EE6D61AB1367D00576EE9 /* README.md */ = {isa = PBXFileReference; explicitFileType = net.daringfireball.markdown; fileEncoding = 4; name = README.md; path = ../../../README.md; sourceTree = "<group>"; wrapsLines = 0; }; | ||||
| 		3C24ECCB1C3B824800460622 /* memory.error.notcmalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memory.error.notcmalloc.cpp; path = ../../../research/gperftools/memory.error.notcmalloc.cpp; sourceTree = "<group>"; }; | ||||
| 		3C24ECCC1C3B824800460622 /* memory.error.tcmalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memory.error.tcmalloc.cpp; path = ../../../research/gperftools/memory.error.tcmalloc.cpp; sourceTree = "<group>"; }; | ||||
| 		3C26E3C41BB146FF00D0F9DB /* srs_app_kafka.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_kafka.cpp; path = ../../../src/app/srs_app_kafka.cpp; sourceTree = "<group>"; }; | ||||
| 		3C26E3C51BB146FF00D0F9DB /* srs_app_kafka.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_kafka.hpp; path = ../../../src/app/srs_app_kafka.hpp; sourceTree = "<group>"; }; | ||||
| 		3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_caster_flv.cpp; path = ../../../src/app/srs_app_caster_flv.cpp; sourceTree = "<group>"; }; | ||||
| 		3C28EDDE1AF5C43F00A3AEAC /* srs_app_caster_flv.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_caster_flv.hpp; path = ../../../src/app/srs_app_caster_flv.hpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB551ABD1CB90066CCAF /* srs_lib_bandwidth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_lib_bandwidth.cpp; path = ../../../src/libs/srs_lib_bandwidth.cpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB561ABD1CB90066CCAF /* srs_lib_bandwidth.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_lib_bandwidth.hpp; path = ../../../src/libs/srs_lib_bandwidth.hpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB571ABD1CB90066CCAF /* srs_lib_simple_socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_lib_simple_socket.cpp; path = ../../../src/libs/srs_lib_simple_socket.cpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB581ABD1CB90066CCAF /* srs_lib_simple_socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_lib_simple_socket.hpp; path = ../../../src/libs/srs_lib_simple_socket.hpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_librtmp.cpp; path = ../../../src/libs/srs_librtmp.cpp; sourceTree = "<group>"; }; | ||||
| 		3C36DB5A1ABD1CB90066CCAF /* srs_librtmp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_librtmp.hpp; path = ../../../src/libs/srs_librtmp.hpp; sourceTree = "<group>"; }; | ||||
| 		3C4468E81BB0E31300589C9D /* sources_replace.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = sources_replace.sh; path = ../../../scripts/sources_replace.sh; sourceTree = "<group>"; }; | ||||
| 		3C44AACD1E3AF50200D4ABC3 /* srs_kernel_mp4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_mp4.cpp; path = ../../../src/kernel/srs_kernel_mp4.cpp; sourceTree = "<group>"; }; | ||||
| 		3C44AACE1E3AF50200D4ABC3 /* srs_kernel_mp4.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_mp4.hpp; path = ../../../src/kernel/srs_kernel_mp4.hpp; sourceTree = "<group>"; }; | ||||
|  | @ -365,19 +344,6 @@ | |||
| 		3C4F97101B8B466D00FF0E46 /* srs_app_process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_process.cpp; path = ../../../src/app/srs_app_process.cpp; sourceTree = "<group>"; }; | ||||
| 		3C4F97111B8B466D00FF0E46 /* srs_app_process.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_process.hpp; path = ../../../src/app/srs_app_process.hpp; sourceTree = "<group>"; }; | ||||
| 		3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core_mem_watch.cpp; path = ../../../src/core/srs_core_mem_watch.cpp; sourceTree = "<group>"; }; | ||||
| 		3C5265B31B241BF0009CA186 /* srs_core_mem_watch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core_mem_watch.hpp; path = ../../../src/core/srs_core_mem_watch.hpp; sourceTree = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		3C663F0B1AB0155100286D8B /* srs_play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_play.c; path = ../../../research/librtmp/srs_play.c; sourceTree = "<group>"; }; | ||||
| 		3C663F0C1AB0155100286D8B /* srs_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_publish.c; path = ../../../research/librtmp/srs_publish.c; sourceTree = "<group>"; }; | ||||
| 		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 = "<group>"; }; | ||||
| 		3C6673CF1DF7B93200A6DF57 /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = readme.txt; path = ../../../modules/readme.txt; sourceTree = "<group>"; }; | ||||
| 		3C6673D11DF7B95E00A6DF57 /* config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = config; path = "../../../modules/hls-ingester/config"; sourceTree = "<group>"; }; | ||||
| 		3C6F2D731E86536B003D0805 /* config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = config; path = "../../../modules/mp4-parser/config"; sourceTree = "<group>"; }; | ||||
|  | @ -397,10 +363,7 @@ | |||
| 		3C9F82241E4F5D2A00F5B2D2 /* srs_protocol_format.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_format.hpp; path = ../../../src/protocol/srs_protocol_format.hpp; sourceTree = "<group>"; }; | ||||
| 		3CA432A61E3F46DD001DA0C6 /* srs_kernel_io.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_io.cpp; path = ../../../src/kernel/srs_kernel_io.cpp; sourceTree = "<group>"; }; | ||||
| 		3CA432A71E3F46DD001DA0C6 /* srs_kernel_io.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_io.hpp; path = ../../../src/kernel/srs_kernel_io.hpp; sourceTree = "<group>"; }; | ||||
| 		3CA432A91E40AEBC001DA0C6 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = ../../../research/librtmp/Makefile; sourceTree = "<group>"; }; | ||||
| 		3CA432AA1E40AEBC001DA0C6 /* srs_ingest_mp4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_ingest_mp4.c; path = ../../../research/librtmp/srs_ingest_mp4.c; sourceTree = "<group>"; }; | ||||
| 		3CB25C281BB2596300C97A63 /* setup_variables.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = setup_variables.sh; path = ../../../auto/setup_variables.sh; sourceTree = "<group>"; }; | ||||
| 		3CB25C291BB269FD00C97A63 /* jmp_sp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jmp_sp.cpp; path = ../../../research/arm/jmp_sp.cpp; sourceTree = "<group>"; }; | ||||
| 		3CC52DCA1ACE4023006FEB01 /* srs_utest_amf0.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_utest_amf0.cpp; path = ../../src/utest/srs_utest_amf0.cpp; sourceTree = "<group>"; }; | ||||
| 		3CC52DCB1ACE4023006FEB01 /* srs_utest_amf0.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_utest_amf0.hpp; path = ../../src/utest/srs_utest_amf0.hpp; sourceTree = "<group>"; }; | ||||
| 		3CC52DCC1ACE4023006FEB01 /* srs_utest_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_utest_config.cpp; path = ../../src/utest/srs_utest_config.cpp; sourceTree = "<group>"; }; | ||||
|  | @ -473,7 +436,6 @@ | |||
| 				3C1232EE1AAEA71C00CE8F6C /* links */, | ||||
| 				3C1231E71AAE64A400CE8F6C /* srs_xcode */, | ||||
| 				3CC52DC91ACE4006006FEB01 /* utest */, | ||||
| 				3C663F001AB014B500286D8B /* research */, | ||||
| 			); | ||||
| 			sourceTree = "<group>"; | ||||
| 		}; | ||||
|  | @ -497,7 +459,6 @@ | |||
| 				3C12324B1AAE81CE00CE8F6C /* app */, | ||||
| 				3C96ADC41B00A71000885304 /* modules */, | ||||
| 				3C1232041AAE80CB00CE8F6C /* main */, | ||||
| 				3C36DB541ABD1CA70066CCAF /* libs */, | ||||
| 				3C1231F91AAE670E00CE8F6C /* objs */, | ||||
| 				3C1EE6AF1AB107EE00576EE9 /* conf */, | ||||
| 				3C1232EF1AAEAC5800CE8F6C /* etc */, | ||||
|  | @ -833,44 +794,6 @@ | |||
| 			name = doc; | ||||
| 			sourceTree = "<group>"; | ||||
| 		}; | ||||
| 		3C36DB541ABD1CA70066CCAF /* libs */ = { | ||||
| 			isa = PBXGroup; | ||||
| 			children = ( | ||||
| 				3C36DB551ABD1CB90066CCAF /* srs_lib_bandwidth.cpp */, | ||||
| 				3C36DB561ABD1CB90066CCAF /* srs_lib_bandwidth.hpp */, | ||||
| 				3C36DB571ABD1CB90066CCAF /* srs_lib_simple_socket.cpp */, | ||||
| 				3C36DB581ABD1CB90066CCAF /* srs_lib_simple_socket.hpp */, | ||||
| 				3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */, | ||||
| 				3C36DB5A1ABD1CB90066CCAF /* srs_librtmp.hpp */, | ||||
| 			); | ||||
| 			name = libs; | ||||
| 			sourceTree = "<group>"; | ||||
| 		}; | ||||
| 		3C663F001AB014B500286D8B /* research */ = { | ||||
| 			isa = PBXGroup; | ||||
| 			children = ( | ||||
| 				3CB25C291BB269FD00C97A63 /* jmp_sp.cpp */, | ||||
| 				3CA432A91E40AEBC001DA0C6 /* Makefile */, | ||||
| 				3C24ECCB1C3B824800460622 /* memory.error.notcmalloc.cpp */, | ||||
| 				3C24ECCC1C3B824800460622 /* memory.error.tcmalloc.cpp */, | ||||
| 				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 */, | ||||
| 				3CA432AA1E40AEBC001DA0C6 /* srs_ingest_mp4.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 = "<group>"; | ||||
| 		}; | ||||
| 		3C6673D01DF7B95000A6DF57 /* hls-ingester */ = { | ||||
| 			isa = PBXGroup; | ||||
| 			children = ( | ||||
|  | @ -1038,7 +961,6 @@ | |||
| 				3C12322B1AAE814D00CE8F6C /* srs_kernel_utility.cpp in Sources */, | ||||
| 				3C12324A1AAE81A400CE8F6C /* srs_rtsp_stack.cpp in Sources */, | ||||
| 				3CE893BF1E876A97000B742D /* srs_service_http_client.cpp in Sources */, | ||||
| 				3C36DB5D1ABD1CB90066CCAF /* srs_librtmp.cpp in Sources */, | ||||
| 				3C12329F1AAE81D900CE8F6C /* srs_app_http_api.cpp in Sources */, | ||||
| 				3CECAF991EDC100F00C50501 /* event.c in Sources */, | ||||
| 				3C1EE6AE1AB1055800576EE9 /* srs_app_hds.cpp in Sources */, | ||||
|  |  | |||
							
								
								
									
										3
									
								
								trunk/research/librtmp/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								trunk/research/librtmp/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +0,0 @@ | |||
| *.mp4 | ||||
| *.gcno | ||||
| *.gcda | ||||
|  | @ -1,125 +0,0 @@ | |||
| GCC = gcc | ||||
| 
 | ||||
| ifeq ($(HANDSHAKE),) | ||||
|     ST_ALL      = help | ||||
| else | ||||
|     ST_ALL      = objs/srs_flv_parser \
 | ||||
|                 objs/srs_flv_injecter objs/srs_publish objs/srs_play \
 | ||||
|                 objs/srs_ingest_flv objs/srs_ingest_rtmp objs/srs_detect_rtmp \
 | ||||
|                 objs/srs_bandwidth_check objs/srs_h264_raw_publish \
 | ||||
|                 objs/srs_audio_raw_publish objs/srs_aac_raw_publish \
 | ||||
|                 objs/srs_rtmp_dump objs/srs_ingest_mp4 | ||||
| endif | ||||
| 
 | ||||
| .PHONY: default clean help ssl nossl | ||||
| 
 | ||||
| default: $(ST_ALL) | ||||
| 
 | ||||
| help: | ||||
| 	@echo "Usage: make <help>|<clean>|<ssl>|<nossl>" | ||||
| 	@echo "     help                    display this help" | ||||
| 	@echo "     clean                   cleanup build" | ||||
| 	@echo "     ssl                     all tools link ssl" | ||||
| 	@echo "     nossl                   all tools never link ssl" | ||||
| 	@echo "ssl/nossl will build the following tools:" | ||||
| 	@echo "     srs_flv_parser          parse flv file, print detail info." | ||||
| 	@echo "     srs_flv_injecter        inject keyframes information to metadata." | ||||
| 	@echo "     srs_publish             publish program using srs-librtmp" | ||||
| 	@echo "     srs_h264_raw_publish    publish raw h.264 stream to SSR by srs-librtmp" | ||||
| 	@echo "     srs_audio_raw_publish   publish raw audio stream to SSR by srs-librtmp" | ||||
| 	@echo "     srs_aac_raw_publish     publish raw aac stream to SSR by srs-librtmp" | ||||
| 	@echo "     srs_play                play program using srs-librtmp" | ||||
| 	@echo "     srs_ingest_flv          ingest flv file and publish to RTMP server." | ||||
| 	@echo "     srs_ingest_mp4          ingest mp4 file and publish to RTMP server." | ||||
| 	@echo "     srs_ingest_rtmp         ingest RTMP and publish to RTMP server." | ||||
| 	@echo "     srs_detect_rtmp         detect RTMP stream info." | ||||
| 	@echo "     srs_bandwidth_check     bandwidth check/test tool." | ||||
| 	@echo "     srs_rtmp_dump           dump rtmp stream to flv file." | ||||
| 	@echo "Remark: about simple/complex handshake, see: http://blog.csdn.net/win_lin/article/details/13006803" | ||||
| 	@echo "Remark: srs Makefile will auto invoke this by --with/without-ssl, " | ||||
| 	@echo "     that is, if user specified ssl(by --with-ssl), srs will make this by 'make ssl'" | ||||
| 	@echo "     that is, if user not use ssl(by --without-ssl), use 'make nossl'" | ||||
| 	@echo "     see: https://github.com/ossrs/srs/wiki/v1_CN_v1_Build" | ||||
| 	@echo "Remark: before make this sample, user must make the srs, with/without ssl" | ||||
|      | ||||
| clean: | ||||
| 	@rm -rf objs | ||||
| 
 | ||||
| # srs library root
 | ||||
| SRS_OBJS = ../../objs | ||||
| # srs-librtmp for publish/play, built by srs.
 | ||||
| SRS_LIBRTMP_I = $(SRS_OBJS)/include/srs_librtmp.h | ||||
| SRS_LIBRTMP_L = $(SRS_OBJS)/lib/srs_librtmp.a | ||||
| # openssl for complex handshake, built by srs.
 | ||||
| SRS_LIBSSL_L = | ||||
| # public depends, the Makefile or public headers.
 | ||||
| SRS_RESEARCH_DEPS = Makefile | ||||
| 
 | ||||
| # for x86/x64 platform
 | ||||
| ifeq ($(GCC), gcc) | ||||
|     OTHER_FLAGS += -g -O0 -ldl -lstdc++ -lm | ||||
| endif | ||||
| # for arm.
 | ||||
| ifeq ($(GCC), arm-linux-gnueabi-gcc) | ||||
|     OTHER_FLAGS += -g -O0 -ldl -static -lstdc++ -lm | ||||
| endif | ||||
| # for mips, add -lgcc_eh, or stl compile failed.
 | ||||
| ifeq ($(GCC), mipsel-openwrt-linux-gcc) | ||||
|     OTHER_FLAGS += -g -O0 -ldl -lstdc++ -lm -lgcc_eh | ||||
| endif | ||||
| # for ssl or nossl
 | ||||
| ifeq ($(HANDSHAKE), SSL) | ||||
|     SRS_LIBSSL_L = $(SRS_OBJS)/openssl/lib/libssl.a $(SRS_OBJS)/openssl/lib/libcrypto.a | ||||
|     ifneq ($(shell test -f $(SRS_OBJS)/openssl/lib/libssl.a && echo yes), yes) | ||||
|         SRS_LIBSSL_L = -lssl -lcrypto | ||||
|     endif | ||||
| endif | ||||
| 
 | ||||
| ssl: | ||||
| 	@mkdir -p objs | ||||
| 	$(MAKE) HANDSHAKE="SSL" | ||||
| nossl: | ||||
| 	@mkdir -p objs | ||||
| 	$(MAKE) HANDSHAKE="NOSSL" | ||||
| 
 | ||||
| CXXFLAGS += $(OTHER_FLAGS) $(EXTRA_CXXFLAGS) | ||||
| 
 | ||||
| objs/srs_flv_parser: srs_flv_parser.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) | ||||
| 	$(GCC) srs_flv_parser.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_flv_parser | ||||
| 
 | ||||
| objs/srs_flv_injecter: srs_flv_injecter.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) | ||||
| 	$(GCC) srs_flv_injecter.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_flv_injecter | ||||
| 
 | ||||
| objs/srs_publish: srs_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_publish | ||||
| 
 | ||||
| objs/srs_h264_raw_publish: srs_h264_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_h264_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_h264_raw_publish | ||||
| 
 | ||||
| objs/srs_audio_raw_publish: srs_audio_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_audio_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_audio_raw_publish | ||||
| 
 | ||||
| objs/srs_aac_raw_publish: srs_aac_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_aac_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_aac_raw_publish | ||||
| 
 | ||||
| objs/srs_play: srs_play.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_play.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_play | ||||
| 
 | ||||
| objs/srs_ingest_flv: srs_ingest_flv.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_ingest_flv.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_ingest_flv | ||||
| 
 | ||||
| objs/srs_ingest_mp4: srs_ingest_mp4.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_ingest_mp4.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_ingest_mp4 | ||||
| 
 | ||||
| objs/srs_ingest_rtmp: srs_ingest_rtmp.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_ingest_rtmp.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_ingest_rtmp | ||||
| 
 | ||||
| objs/srs_detect_rtmp: srs_detect_rtmp.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_detect_rtmp.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_detect_rtmp | ||||
| 
 | ||||
| objs/srs_bandwidth_check: srs_bandwidth_check.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_bandwidth_check.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_bandwidth_check | ||||
| 
 | ||||
| objs/srs_rtmp_dump: srs_rtmp_dump.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) | ||||
| 	$(GCC) srs_rtmp_dump.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(CXXFLAGS) -o objs/srs_rtmp_dump | ||||
| 
 | ||||
|  | @ -1,187 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| // for open audio raw file.
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| // https://github.com/ossrs/srs/issues/212#issuecomment-64145910
 | ||||
| int read_audio_frame(char* data, int size, char** pp, char** frame, int* frame_size) | ||||
| { | ||||
|     char* p = *pp; | ||||
|      | ||||
|     // @remark, for this demo, to publish aac raw file to SRS,
 | ||||
|     // we search the adts frame from the buffer which cached the aac data.
 | ||||
|     // please get aac adts raw data from device, it always a encoded frame.
 | ||||
|     if (!srs_aac_is_adts(p, size - (p - data))) { | ||||
|         srs_human_trace("aac adts raw data invalid."); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     // @see srs_audio_write_raw_frame
 | ||||
|     // each frame prefixed aac adts header, '1111 1111 1111'B, that is 0xFFF.,
 | ||||
|     // for instance, frame = FF F1 5C 80 13 A0 FC 00 D0 33 83 E8 5B
 | ||||
|     *frame = p; | ||||
|     // skip some data.
 | ||||
|     // @remark, user donot need to do this.
 | ||||
|     p += srs_aac_adts_frame_size(p, size - (p - data)); | ||||
|      | ||||
|     *pp = p; | ||||
|     *frame_size = p - *frame; | ||||
|     if (*frame_size <= 0) { | ||||
|         srs_human_trace("aac adts raw data invalid."); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     printf("publish raw audio as rtmp stream to server like FMLE/FFMPEG/Encoder\n"); | ||||
|     printf("SRS(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("Usage: %s <audio_raw_file> <rtmp_publish_url>\n", argv[0]); | ||||
|         printf("     audio_raw_file: the audio raw steam file.\n"); | ||||
|         printf("     rtmp_publish_url: the rtmp publish url.\n"); | ||||
|         printf("For example:\n"); | ||||
|         printf("     %s ./audio.raw.aac rtmp://127.0.0.1:1935/live/livestream\n", argv[0]); | ||||
|         printf("Where the file: http://winlinvip.github.io/srs.release/3rdparty/audio.raw.aac\n"); | ||||
|         printf("See: https://github.com/ossrs/srs/issues/212\n"); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     const char* raw_file = argv[1]; | ||||
|     const char* rtmp_url = argv[2]; | ||||
|     srs_human_trace("raw_file=%s, rtmp_url=%s", raw_file, rtmp_url); | ||||
|      | ||||
|     // open file
 | ||||
|     int raw_fd = open(raw_file, O_RDONLY); | ||||
|     if (raw_fd < 0) { | ||||
|         srs_human_trace("open audio raw file %s failed.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     off_t file_size = lseek(raw_fd, 0, SEEK_END); | ||||
|     if (file_size <= 0) { | ||||
|         srs_human_trace("audio raw file %s empty.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("read entirely audio raw file, size=%dKB", (int)(file_size / 1024)); | ||||
|      | ||||
|     char* audio_raw = (char*)malloc(file_size); | ||||
|     if (!audio_raw) { | ||||
|         srs_human_trace("alloc raw buffer failed for file %s.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     lseek(raw_fd, 0, SEEK_SET); | ||||
|     ssize_t nb_read = 0; | ||||
|     if ((nb_read = read(raw_fd, audio_raw, file_size)) != file_size) { | ||||
|         srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.", | ||||
|             raw_file, (int)(file_size / 1024), (int)(nb_read / 1024)); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     // connect rtmp context
 | ||||
|     srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); | ||||
|      | ||||
|     if (srs_rtmp_handshake(rtmp) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if (srs_rtmp_connect_app(rtmp) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if (srs_rtmp_publish_stream(rtmp) != 0) { | ||||
|         srs_human_trace("publish stream failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("publish stream success"); | ||||
|      | ||||
|     uint32_t timestamp = 0; | ||||
|     uint32_t time_delta = 45; | ||||
|     // @remark, to decode the file.
 | ||||
|     char* p = audio_raw; | ||||
|     for (;p < audio_raw + file_size;) { | ||||
|         // @remark, read a frame from file buffer.
 | ||||
|         char* data = NULL; | ||||
|         int size = 0; | ||||
|         if (read_audio_frame(audio_raw, file_size, &p, &data, &size) < 0) { | ||||
|             srs_human_trace("read a frame from file buffer failed."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         // 0 = Linear PCM, platform endian
 | ||||
|         // 1 = ADPCM
 | ||||
|         // 2 = MP3
 | ||||
|         // 7 = G.711 A-law logarithmic PCM
 | ||||
|         // 8 = G.711 mu-law logarithmic PCM
 | ||||
|         // 10 = AAC
 | ||||
|         // 11 = Speex
 | ||||
|         char sound_format = 10; | ||||
|         // 2 = 22 kHz
 | ||||
|         char sound_rate = 2; | ||||
|         // 1 = 16-bit samples
 | ||||
|         char sound_size = 1; | ||||
|         // 1 = Stereo sound
 | ||||
|         char sound_type = 1; | ||||
|          | ||||
|         timestamp += time_delta; | ||||
|          | ||||
|         int ret = 0; | ||||
|         if ((ret = srs_audio_write_raw_frame(rtmp, sound_format, sound_rate, sound_size, sound_type, data, size, timestamp)) != 0) { | ||||
|             srs_human_trace("send audio raw data failed. ret=%d", ret); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         srs_human_trace("sent packet: type=%s, time=%d, size=%d, codec=%d, rate=%d, sample=%d, channel=%d", | ||||
|             srs_human_flv_tag_type2string(SRS_RTMP_TYPE_AUDIO), timestamp, size, sound_format, sound_rate, sound_size, | ||||
|             sound_type); | ||||
|          | ||||
|         // @remark, when use encode device, it not need to sleep.
 | ||||
|         usleep(1000 * time_delta); | ||||
|     } | ||||
|      | ||||
| rtmp_destroy: | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|     close(raw_fd); | ||||
|     free(audio_raw); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,183 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| // for open audio raw file.
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| // https://github.com/ossrs/srs/issues/212#issuecomment-63648892
 | ||||
| // allspace:
 | ||||
| //      Take this file as an example: https://github.com/allspace/files/blob/master/srs.pcm
 | ||||
| //      It's captured using SDK callback method. I have filtered out h264 video, so it's audio only now.
 | ||||
| //      For every frame, it's a 8 bytes vendor specific header, following 160 bytes audio frame.
 | ||||
| //      The header part can be ignored.
 | ||||
| int read_audio_frame(char* audio_raw, int file_size, char** pp, char** pdata, int* psize) | ||||
| { | ||||
|     char* p = *pp; | ||||
|      | ||||
|     if (file_size - (p - audio_raw) < 168) { | ||||
|         srs_human_trace("audio must be 160+8 bytes. left %d bytes.", (int)(file_size - (p - audio_raw))); | ||||
|         return - 1; | ||||
|     } | ||||
|      | ||||
|     // ignore 8bytes vendor specific header.
 | ||||
|     p += 8; | ||||
|      | ||||
|     // 160 bytes audio frame
 | ||||
|     *pdata = p; | ||||
|     *psize = 160; | ||||
|      | ||||
|     // next frame.
 | ||||
|     *pp = p + *psize; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     printf("publish raw audio as rtmp stream to server like FMLE/FFMPEG/Encoder\n"); | ||||
|     printf("SRS(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("Usage: %s <audio_raw_file> <rtmp_publish_url>\n", argv[0]); | ||||
|         printf("     audio_raw_file: the audio raw steam file.\n"); | ||||
|         printf("     rtmp_publish_url: the rtmp publish url.\n"); | ||||
|         printf("For example:\n"); | ||||
|         printf("     %s ./audio.raw.pcm rtmp://127.0.0.1:1935/live/livestream\n", argv[0]); | ||||
|         printf("Where the file: http://winlinvip.github.io/srs.release/3rdparty/audio.raw.pcm\n"); | ||||
|         printf("See: https://github.com/ossrs/srs/issues/212\n"); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     const char* raw_file = argv[1]; | ||||
|     const char* rtmp_url = argv[2]; | ||||
|     srs_human_trace("raw_file=%s, rtmp_url=%s", raw_file, rtmp_url); | ||||
|      | ||||
|     // open file
 | ||||
|     int raw_fd = open(raw_file, O_RDONLY); | ||||
|     if (raw_fd < 0) { | ||||
|         srs_human_trace("open audio raw file %s failed.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     off_t file_size = lseek(raw_fd, 0, SEEK_END); | ||||
|     if (file_size <= 0) { | ||||
|         srs_human_trace("audio raw file %s empty.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("read entirely audio raw file, size=%dKB", (int)(file_size / 1024)); | ||||
|      | ||||
|     char* audio_raw = (char*)malloc(file_size); | ||||
|     if (!audio_raw) { | ||||
|         srs_human_trace("alloc raw buffer failed for file %s.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     lseek(raw_fd, 0, SEEK_SET); | ||||
|     ssize_t nb_read = 0; | ||||
|     if ((nb_read = read(raw_fd, audio_raw, file_size)) != file_size) { | ||||
|         srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.", | ||||
|             raw_file, (int)(file_size / 1024), (int)(nb_read / 1024)); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     // connect rtmp context
 | ||||
|     srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); | ||||
|      | ||||
|     if (srs_rtmp_handshake(rtmp) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if (srs_rtmp_connect_app(rtmp) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if (srs_rtmp_publish_stream(rtmp) != 0) { | ||||
|         srs_human_trace("publish stream failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("publish stream success"); | ||||
|      | ||||
|     uint32_t timestamp = 0; | ||||
|     uint32_t time_delta = 17; | ||||
|     // @remark, to decode the file.
 | ||||
|     char* p = audio_raw; | ||||
|     for (;p < audio_raw + file_size;) { | ||||
|         // @remark, read a frame from file buffer.
 | ||||
|         char* data = NULL; | ||||
|         int size = 0; | ||||
|         if (read_audio_frame(audio_raw, file_size, &p, &data, &size) < 0) { | ||||
|             srs_human_trace("read a frame from file buffer failed."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         // 0 = Linear PCM, platform endian
 | ||||
|         // 1 = ADPCM
 | ||||
|         // 2 = MP3
 | ||||
|         // 7 = G.711 A-law logarithmic PCM
 | ||||
|         // 8 = G.711 mu-law logarithmic PCM
 | ||||
|         // 10 = AAC
 | ||||
|         // 11 = Speex
 | ||||
|         char sound_format = 1; | ||||
|         // 3 = 44 kHz
 | ||||
|         char sound_rate = 3; | ||||
|         // 1 = 16-bit samples
 | ||||
|         char sound_size = 1; | ||||
|         // 1 = Stereo sound
 | ||||
|         char sound_type = 1; | ||||
|          | ||||
|         timestamp += time_delta; | ||||
|          | ||||
|         if (srs_audio_write_raw_frame(rtmp, sound_format, sound_rate, sound_size, sound_type, data, size, timestamp) != 0) { | ||||
|             srs_human_trace("send audio raw data failed."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         srs_human_trace("sent packet: type=%s, time=%d, size=%d, codec=%d, rate=%d, sample=%d, channel=%d", | ||||
|             srs_human_flv_tag_type2string(SRS_RTMP_TYPE_AUDIO), timestamp, size, sound_format, sound_rate, sound_size, | ||||
|             sound_type); | ||||
|          | ||||
|         // @remark, when use encode device, it not need to sleep.
 | ||||
|         usleep(1000 * time_delta); | ||||
|     } | ||||
|      | ||||
| rtmp_destroy: | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|     close(raw_fd); | ||||
|     free(audio_raw); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,143 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| // srs debug info.
 | ||||
| char* ip = NULL; | ||||
| char* sig = NULL; | ||||
| int pid = 0, cid = 0; | ||||
| int major = 0, minor = 0, revision= 0, build = 0; | ||||
| // bandwidth test data.
 | ||||
| int64_t start_time = 0; | ||||
| int64_t end_time = 0; | ||||
| int play_kbps = 0; | ||||
| int publish_kbps = 0; | ||||
| int play_bytes = 0; | ||||
| int publish_bytes = 0; | ||||
| int play_duration = 0; | ||||
| int publish_duration = 0; | ||||
| 
 | ||||
| int do_check(srs_rtmp_t rtmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_handshake(rtmp)) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_app(rtmp)) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_get_server_sig(rtmp, &sig)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_id(rtmp, &ip, &pid, &cid)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_version(rtmp, &major, &minor, &revision, &build)) != 0) { | ||||
|         srs_human_trace("Retrieve server version failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_bandwidth_check(rtmp, | ||||
|         &start_time, &end_time, &play_kbps, &publish_kbps, &play_bytes, &publish_bytes, | ||||
|         &play_duration, &publish_duration)) != 0 | ||||
|     ) { | ||||
|         srs_human_trace("bandwidth check/test failed."); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("bandwidth check/test success"); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|     srs_rtmp_t rtmp; | ||||
|      | ||||
|     printf("RTMP bandwidth check/test with server.\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 1) { | ||||
|         printf("RTMP bandwidth check/test with server.\n" | ||||
|             "Usage: %s <rtmp_url>\n" | ||||
|             "   rtmp_url     RTMP bandwidth url to check. format: rtmp://server:port/app?key=xxx,vhost=xxx\n" | ||||
|             "For example:\n" | ||||
|             "   %s rtmp://127.0.0.1:1935/app?key=35c9b402c12a7246868752e2878f7e0e,vhost=bandcheck.srs.com\n" | ||||
|             "   %s rtmp://127.0.0.1:1935/app?key=35c9b402c12a7246868752e2878f7e0e,vhost=bandcheck.srs.com>/dev/null\n" | ||||
|             "@remark, output text to stdout, while json to stderr.\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     char url[512]; | ||||
|     snprintf(url, sizeof(url), "%s/%s", argv[1], "livestream"); | ||||
|     rtmp = srs_rtmp_create((const char*)url); | ||||
|     srs_human_trace("bandwidth check/test url: %s", argv[1]); | ||||
|      | ||||
|     if ((ret = do_check(rtmp)) != 0) { | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("\n%s, %s, %d.%d.%d.%d, srs_pid=%d, srs_id=%d\n" | ||||
|         "duration: %dms(%d+%d), play: %dkbps, publish: %dkbps", | ||||
|         (char*)sig, (char*)ip, major, minor, revision, build, pid, cid, | ||||
|         (int)(end_time - start_time), play_duration, publish_duration, play_kbps, publish_kbps); | ||||
|      | ||||
| rtmp_destroy: | ||||
|     fprintf(stderr, "{\"code\":%d," | ||||
|         "\"srs_server\":\"%s\", \"srs_primary\":\"\", \"srs_authors\":\"\", \"srs_server_ip\":\"%s\", " | ||||
|         "\"srs_version\":\"%d.%d.%d.%d\", " | ||||
|         "\"srs_pid\":%d, " | ||||
|         "\"srs_id\":%d, " | ||||
|         "\"duration\":%d, " | ||||
|         "\"play_duration\":%d, " | ||||
|         "\"publish_duration\":%d," | ||||
|         "\"play_kbps\":%d, " | ||||
|         "\"publish_kbps\":%d" | ||||
|         "}", | ||||
|         ret, | ||||
|         (char*)sig, (char*)ip, | ||||
|         major, minor, revision, build, pid, cid, | ||||
|         (int)(end_time - start_time), play_duration, publish_duration, | ||||
|         play_kbps, publish_kbps); | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|      | ||||
|     srs_human_trace(" "); | ||||
|     srs_human_trace("completed"); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | @ -1,239 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|     srs_rtmp_t rtmp; | ||||
|      | ||||
|     // time
 | ||||
|     int64_t time_startup = srs_utils_time_ms(); | ||||
|     int64_t time_dns_resolve = 0; | ||||
|     int64_t time_socket_connect = 0; | ||||
|     int64_t time_play_stream = 0; | ||||
|     int64_t time_first_packet = 0; | ||||
|     int64_t time_cleanup = 0; | ||||
|     // bytes
 | ||||
|     int64_t bytes_nsend = 0; | ||||
|     int time_duration = 0; | ||||
|     int64_t bytes_nrecv = 0; | ||||
|      | ||||
|     // packet data
 | ||||
|     int size; | ||||
|     char type; | ||||
|     char* data; | ||||
|     uint32_t timestamp; | ||||
|     uint32_t basetime = 0; | ||||
|      | ||||
|     // user options
 | ||||
|     const char* rtmp_url = NULL; | ||||
|     int duration = 0; | ||||
|     int timeout = 0; | ||||
|     enum srs_url_schema sus; | ||||
|      | ||||
|     printf("detect rtmp stream\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 3) { | ||||
|         printf("detect stream on RTMP server, print result to stderr.\n" | ||||
|                "Usage: %s <rtmp_url> <duration> <timeout> [url_schema]\n" | ||||
|                "   rtmp_url     RTMP stream url to play\n" | ||||
|                "   duration     how long to play, in seconds, stream time.\n" | ||||
|                "   timeout      how long to timeout, in seconds, system time.\n" | ||||
|                "   url_schema   the schema of url, default to vis, can be:\n" | ||||
|                "                    normal:    rtmp://vhost:port/app/stream\n" | ||||
|                "                    via   :    rtmp://ip:port/vhost/app/stream\n" | ||||
|                "                    vis   :    rtmp://ip:port/app/stream?vhost=xxx\n" | ||||
|                "                    vis2  :    rtmp://ip:port/app/stream?domain=xxx\n" | ||||
|                "For example:\n" | ||||
|                "   %s rtmp://127.0.0.1:1935/bravo.chnvideo.com/live/livestream 3 10\n", | ||||
|                argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     rtmp_url = argv[1]; | ||||
|     duration = atoi(argv[2]); | ||||
|     timeout = atoi(argv[3]); | ||||
|      | ||||
|     if (1) { | ||||
|         char *p = "vis"; | ||||
|         if (argc > 4) { | ||||
|             p = argv[4]; | ||||
|         } | ||||
|          | ||||
|         if (strcmp(p, "normal") == 0) { | ||||
|             sus = srs_url_schema_normal; | ||||
|         } else if (strcmp(p, "via") == 0) { | ||||
|             sus = srs_url_schema_via; | ||||
|         } else if (strcmp(p, "vis") == 0) { | ||||
|             sus = srs_url_schema_vis; | ||||
|         } else if (strcmp(p, "vis2") == 0){ | ||||
|             sus = srs_url_schema_vis2; | ||||
|         } else { | ||||
|             srs_human_trace("url_schema must be normal/via/vis/vis2"); | ||||
|             exit(-2); | ||||
|         } | ||||
|         srs_human_trace("url schema: %s", p); | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("rtmp url: %s", rtmp_url); | ||||
|     srs_human_trace("duration: %ds, timeout:%ds", duration, timeout); | ||||
|      | ||||
|     if (duration <= 0 || timeout <= 0) { | ||||
|         srs_human_trace("duration and timeout must be positive."); | ||||
|         exit(-3); | ||||
|     } | ||||
|      | ||||
|     if ((rtmp = srs_rtmp_create(rtmp_url)) == NULL) { | ||||
|         srs_human_trace("create rtmp failed"); | ||||
|         ret = -1; | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_set_timeout(rtmp, timeout * 1000, timeout * 1000)) != 0) { | ||||
|         srs_human_trace("set timeout for rtmp failed. errno=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_dns_resolve(rtmp)) != 0) { | ||||
|         srs_human_trace("dns resolve failed. ret=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("dns resolve success"); | ||||
|     time_dns_resolve = srs_utils_time_ms(); | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_server(rtmp)) != 0) { | ||||
|         srs_human_trace("socket connect failed. ret=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("socket connect success"); | ||||
|     time_socket_connect = srs_utils_time_ms(); | ||||
|      | ||||
|     if ((ret = srs_rtmp_do_simple_handshake(rtmp)) != 0) { | ||||
|         srs_human_trace("do simple handshake failed. ret=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("do simple handshake success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_set_schema(rtmp, sus)) != 0) { | ||||
|         srs_human_trace("set url schema=%d failed, ret=%d", sus, ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_app(rtmp)) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed. ret=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_play_stream(rtmp)) != 0) { | ||||
|         srs_human_trace("play stream failed. ret=%d", ret); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("play stream success"); | ||||
|     time_play_stream = srs_utils_time_ms(); | ||||
|      | ||||
|     for (;;) { | ||||
|         if ((ret = srs_rtmp_read_packet(rtmp, &type, ×tamp, &data, &size)) != 0) { | ||||
|             srs_human_trace("read packet failed. ret=%d", ret); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|         srs_human_trace("got packet: type=%s, time=%d, size=%d", srs_human_flv_tag_type2string(type), timestamp, size); | ||||
|          | ||||
|         if (SRS_RTMP_TYPE_VIDEO == type || SRS_RTMP_TYPE_AUDIO == type) { | ||||
|             if (time_first_packet <= 0) { | ||||
|                 time_first_packet = srs_utils_time_ms(); | ||||
|             } | ||||
|             if (basetime <= 0) { | ||||
|                 basetime = timestamp; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         free(data); | ||||
|          | ||||
|         if (srs_utils_time_ms() - time_startup > timeout * 1000) { | ||||
|             srs_human_trace("timeout, terminate."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         if (timestamp > basetime && (timestamp - basetime) > duration * 1000) { | ||||
|             srs_human_trace("duration exceed, terminate."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|     } | ||||
|      | ||||
| rtmp_destroy: | ||||
|     bytes_nsend = srs_utils_send_bytes(rtmp); | ||||
|     bytes_nrecv = srs_utils_recv_bytes(rtmp); | ||||
|      | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|     time_cleanup = srs_utils_time_ms(); | ||||
|     time_duration = (int)(time_cleanup - time_startup); | ||||
|      | ||||
|     // print result to stderr.
 | ||||
|     fprintf(stderr, "{" | ||||
|         "\"%s\":%d, " //#0
 | ||||
|         "\"%s\":%d, " //#1
 | ||||
|         "\"%s\":%d, " // #2
 | ||||
|         "\"%s\":%d, " // #3
 | ||||
|         "\"%s\":%d, " // #4
 | ||||
|         "\"%s\":%d, " // #5
 | ||||
|         "\"%s\":%d, " // #6
 | ||||
|         "\"%s\":%d, " // #7
 | ||||
|         "\"%s\":%d, " // #8
 | ||||
|         "\"%s\":%d, " // #9
 | ||||
|         "\"%s\":%d, " // #10
 | ||||
|         "%s,%s,%s,%s}", | ||||
|         "code", ret, //#0
 | ||||
|         // total = dns + tcp_connect + start_play + first_packet + last_packet
 | ||||
|         "total", time_duration, //#1
 | ||||
|         "dns", (int)(time_dns_resolve - time_startup), //#2
 | ||||
|         "tcp_connect", (int)(time_socket_connect - time_dns_resolve), //#3
 | ||||
|         "start_play", (int)(time_play_stream - time_socket_connect), //#4
 | ||||
|         "first_packet", (int)(time_first_packet - time_play_stream), //#5
 | ||||
|         "last_packet", (int)(time_cleanup - time_first_packet), //#6
 | ||||
|         "stream", (int)(timestamp - basetime), //#7
 | ||||
|         // expect = time_cleanup - time_first_packet
 | ||||
|         // actual = stream
 | ||||
|         // delay = actual - expect
 | ||||
|         "delay", (int)(timestamp - basetime - (time_cleanup - time_first_packet)), //#8
 | ||||
|         "publish_kbps", (int)((time_duration <= 0)? 0:(bytes_nsend * 8 / time_duration)), //#9
 | ||||
|         "play_kbps", (int)((time_duration <= 0)? 0:(bytes_nrecv * 8 / time_duration)), //#10
 | ||||
|         // unit in ms.
 | ||||
|         "\"unit\": \"ms\"", | ||||
|         "\"remark0\": \"total = dns + tcp_connect + start_play + first_packet + last_packet\"", | ||||
|         "\"remark1\": \"delay = stream - (time_cleanup - time_first_packet)\"", | ||||
|         "\"remark2\": \"if code is not 0, user must ignore all data\"" | ||||
|         ); | ||||
|      | ||||
|     srs_human_trace(" "); | ||||
|     srs_human_trace("completed"); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | @ -1,383 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| #define ERROR_INJECTED 10000 | ||||
| 
 | ||||
| int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc); | ||||
| int build_keyframes(srs_flv_t ic, srs_amf0_t *pname, srs_amf0_t* pdata, srs_amf0_t* pfilepositions, int64_t* pmetadata_end_offset); | ||||
| int do_inject_flv(srs_flv_t ic, srs_flv_t oc, srs_amf0_t amf0_name, srs_amf0_t amf0_data, srs_amf0_t filepositions, int64_t metadata_end_offset); | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // user options.
 | ||||
|     char* in_flv_file; | ||||
|     char* out_flv_file; | ||||
|     // flv handler
 | ||||
|     srs_flv_t ic = NULL; | ||||
|     srs_flv_t oc = NULL; | ||||
|      | ||||
|     // temp variables.
 | ||||
|     int tmp_file_size = 0; | ||||
|     char* tmp_file; | ||||
|      | ||||
|     printf("inject flv file keyframes to metadata.\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("inject flv file keyframes to metadata\n" | ||||
|             "Usage: %s in_flv_file out_flv_file\n" | ||||
|             "   in_flv_file         input flv file to inject.\n" | ||||
|             "   out_flv_file        the inject output file, can be in_flv_file.\n" | ||||
|             "For example:\n" | ||||
|             "   %s doc/source.200kbps.768x320.flv injected.flv\n" | ||||
|             "   %s ../../doc/source.200kbps.768x320.flv injected.flv\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     in_flv_file = argv[1]; | ||||
|     out_flv_file = argv[2]; | ||||
|      | ||||
|     tmp_file_size = strlen(out_flv_file) + strlen(".tmp") + 1; | ||||
|     tmp_file = (char*)malloc(tmp_file_size); | ||||
|     snprintf(tmp_file, tmp_file_size, "%s.tmp", out_flv_file); | ||||
|      | ||||
|     srs_human_trace("input:  %s", in_flv_file); | ||||
|     srs_human_trace("output:  %s", out_flv_file); | ||||
|     srs_human_trace("tmp_file:  %s", tmp_file); | ||||
|      | ||||
|     ret = process(in_flv_file, tmp_file, &ic, &oc); | ||||
|      | ||||
|     srs_flv_close(ic); | ||||
|     srs_flv_close(oc); | ||||
|      | ||||
|     if (ret != 0) { | ||||
|         unlink(tmp_file); | ||||
|         if (ret == ERROR_INJECTED) { | ||||
|             ret = 0; | ||||
|             srs_human_trace("file already injected."); | ||||
|         } else { | ||||
|             srs_human_trace("error, remove tmp file."); | ||||
|         } | ||||
|     } else { | ||||
|         rename(tmp_file, out_flv_file); | ||||
|         srs_human_trace("completed, rename to %s", out_flv_file); | ||||
|     } | ||||
|      | ||||
|     free(tmp_file); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     srs_flv_t ic; | ||||
|     srs_flv_t oc; | ||||
|      | ||||
|     // to adjust metadata.
 | ||||
|     // the ic metadata end offset, the next tag start offset.
 | ||||
|     // all oc metadata must adjust according to:
 | ||||
|     //      adjust = new_metadata_end_offset - metadata_end_offset
 | ||||
|     int64_t metadata_end_offset = 0; | ||||
|      | ||||
|     // metadata
 | ||||
|     srs_amf0_t amf0_name = NULL; | ||||
|     srs_amf0_t amf0_data = NULL; | ||||
|     srs_amf0_t filepositions = NULL; | ||||
|      | ||||
|     if ((ic = srs_flv_open_read(in_flv_file)) == NULL) { | ||||
|         ret = 2; | ||||
|         srs_human_trace("open input flv file failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     *pic = ic; | ||||
|      | ||||
|     if ((oc = srs_flv_open_write(out_flv_file)) == NULL) { | ||||
|         ret = 2; | ||||
|         srs_human_trace("open output flv file failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     *poc = oc; | ||||
|      | ||||
|     /**
 | ||||
|      * we use two roundtrip to avoid the paddings of metadata, | ||||
|      * to support large keyframes videos without padding fields. | ||||
|      */ | ||||
|     // build keyframes offset to metadata.
 | ||||
|     if ((ret = build_keyframes(ic, &amf0_name, &amf0_data, &filepositions, &metadata_end_offset)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     // inject the metadata to oc.
 | ||||
|     if ((ret = do_inject_flv(ic, oc, amf0_name, amf0_data, filepositions, metadata_end_offset)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     // TODO: FIXME: mem leak when error.
 | ||||
|     srs_amf0_free(amf0_name); | ||||
|     srs_amf0_free(amf0_data); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int parse_metadata(char* data, int size, srs_amf0_t* pname, srs_amf0_t* pdata) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     int nparsed = 0; | ||||
|     *pname = srs_amf0_parse(data, size, &nparsed); | ||||
|      | ||||
|     if (*pname == NULL || nparsed >= size) { | ||||
|         srs_human_trace("invalid amf0 name data."); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     *pdata = srs_amf0_parse(data + nparsed, size - nparsed, &nparsed); | ||||
|     if (*pdata == NULL || nparsed > size) { | ||||
|         srs_human_trace("invalid amf0 value data"); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int build_keyframes(srs_flv_t ic, srs_amf0_t *pname, srs_amf0_t* pdata, srs_amf0_t* pfilepositions, int64_t* pmetadata_end_offset) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // flv header
 | ||||
|     char header[13]; | ||||
|      | ||||
|     // packet data
 | ||||
|     char type; | ||||
|     uint32_t timestamp = 0; | ||||
|     char* data = NULL; | ||||
|     int32_t size; | ||||
|     int64_t offset = 0; | ||||
|      | ||||
|     // metadata
 | ||||
|     srs_amf0_t amf0_name = NULL; | ||||
|     srs_amf0_t amf0_data = NULL; | ||||
|      | ||||
|     srs_amf0_t keyframes = NULL; | ||||
|     srs_amf0_t filepositions = NULL; | ||||
|     srs_amf0_t times = NULL; | ||||
|      | ||||
|     // reset to generate metadata
 | ||||
|     srs_flv_lseek(ic, 0); | ||||
|      | ||||
|     if ((ret = srs_flv_read_header(ic, header)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("build keyframe infos from flv"); | ||||
|     for (;;) { | ||||
|         offset = srs_flv_tellg(ic); | ||||
|          | ||||
|         // tag header
 | ||||
|         if ((ret = srs_flv_read_tag_header(ic, &type, &size, ×tamp)) != 0) { | ||||
|             if (srs_flv_is_eof(ret)) { | ||||
|                 srs_human_trace("parse completed."); | ||||
|                 return 0; | ||||
|             } | ||||
|             srs_human_trace("flv get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (size <= 0) { | ||||
|             srs_human_trace("invalid size=%d", size); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         // TODO: FIXME: mem leak when error.
 | ||||
|         data = (char*)malloc(size); | ||||
|         if ((ret = srs_flv_read_tag_data(ic, data, size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         // data tag
 | ||||
|         if (type == SRS_RTMP_TYPE_VIDEO) { | ||||
|             if (!srs_flv_is_sequence_header(data, size) && srs_flv_is_keyframe(data, size)) { | ||||
|                 srs_amf0_strict_array_append(filepositions, srs_amf0_create_number(offset)); | ||||
|                 srs_amf0_strict_array_append(times, srs_amf0_create_number(((double)timestamp)/ 1000)); | ||||
|             } | ||||
|         } else if (type == SRS_RTMP_TYPE_SCRIPT) { | ||||
|             *pmetadata_end_offset = srs_flv_tellg(ic); | ||||
|             if ((ret = parse_metadata(data, size, &amf0_name, &amf0_data)) != 0) { | ||||
|                 return ret; | ||||
|             } | ||||
|              | ||||
|             *pname = amf0_name; | ||||
|             *pdata = amf0_data; | ||||
|              | ||||
|             if (srs_amf0_is_object(amf0_data)) { | ||||
|                 keyframes = srs_amf0_object_property(amf0_data, "keyframes"); | ||||
|                 if (keyframes == NULL) { | ||||
|                     keyframes = srs_amf0_create_object(); | ||||
|                     srs_amf0_object_property_set(amf0_data, "keyframes", keyframes); | ||||
|                 } | ||||
|                 // always clear the old keyframes.
 | ||||
|                 srs_amf0_object_clear(keyframes); | ||||
|                  | ||||
|                 *pfilepositions = filepositions = srs_amf0_create_strict_array(); | ||||
|                 srs_amf0_object_property_set(keyframes, "filepositions", filepositions); | ||||
|                  | ||||
|                 times = srs_amf0_create_strict_array(); | ||||
|                 srs_amf0_object_property_set(keyframes, "times", times); | ||||
|             } else if (srs_amf0_is_ecma_array(amf0_data)) { | ||||
|                 keyframes = srs_amf0_ecma_array_property(amf0_data, "keyframes"); | ||||
|                 if (keyframes == NULL) { | ||||
|                     keyframes = srs_amf0_create_object(); | ||||
|                     srs_amf0_ecma_array_property_set(amf0_data, "keyframes", keyframes); | ||||
|                 } | ||||
|                 // always clear the old keyframes.
 | ||||
|                 srs_amf0_object_clear(keyframes); | ||||
|                  | ||||
|                 *pfilepositions = filepositions = srs_amf0_create_strict_array(); | ||||
|                 srs_amf0_object_property_set(keyframes, "filepositions", filepositions); | ||||
|                  | ||||
|                 times = srs_amf0_create_strict_array(); | ||||
|                 srs_amf0_object_property_set(keyframes, "times", times); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         free(data); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int do_inject_flv(srs_flv_t ic, srs_flv_t oc, srs_amf0_t amf0_name, srs_amf0_t amf0_data, srs_amf0_t filepositions, int64_t metadata_end_offset) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // flv header
 | ||||
|     char header[13]; | ||||
|     // packet data
 | ||||
|     char type; | ||||
|     uint32_t timestamp = 0; | ||||
|     char* data = NULL; | ||||
|     int32_t size; | ||||
|      | ||||
|     // metadata
 | ||||
|     srs_amf0_t fileposition = NULL; | ||||
|     int amf0_name_size = 0; | ||||
|     int i; | ||||
|      | ||||
|     // the metadata end offset, the next tag start offset.
 | ||||
|     int64_t new_metadata_end_offset = 0; | ||||
|     int offset_adjust = 0; | ||||
|      | ||||
|     // reset to write injected file
 | ||||
|     srs_flv_lseek(ic, 0); | ||||
|      | ||||
|     if ((ret = srs_flv_read_header(ic, header)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_flv_write_header(oc, header)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     // write metadata
 | ||||
|     if (amf0_name != NULL && amf0_data != NULL) { | ||||
|         amf0_name_size = srs_amf0_size(amf0_name); | ||||
|         size = amf0_name_size + srs_amf0_size(amf0_data); | ||||
|          | ||||
|         // adjust all offset of keyframes.
 | ||||
|         new_metadata_end_offset = srs_flv_tellg(oc) + srs_flv_size_tag(size); | ||||
|         // the adjust is new offset sub the old offset of metadata end.
 | ||||
|         offset_adjust = new_metadata_end_offset - metadata_end_offset; | ||||
|         for (i = 0; i < srs_amf0_strict_array_property_count(filepositions); i++) { | ||||
|             fileposition = srs_amf0_strict_array_property_at(filepositions, i); | ||||
|             srs_amf0_set_number(fileposition, srs_amf0_to_number(fileposition) + offset_adjust); | ||||
|         } | ||||
|          | ||||
|         data = (char*)malloc(size); | ||||
|         memset(data, 0, size); | ||||
|         if ((ret = srs_amf0_serialize(amf0_name, data, amf0_name_size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|         if ((ret = srs_amf0_serialize(amf0_data, data + amf0_name_size, size - amf0_name_size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|         if ((ret = srs_flv_write_tag(oc, SRS_RTMP_TYPE_SCRIPT, 0, data, size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|         free(data); | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("build keyframe infos from flv"); | ||||
|     for (;;) { | ||||
|         // tag header
 | ||||
|         if ((ret = srs_flv_read_tag_header(ic, &type, &size, ×tamp)) != 0) { | ||||
|             if (srs_flv_is_eof(ret)) { | ||||
|                 srs_human_trace("parse completed."); | ||||
|                 return 0; | ||||
|             } | ||||
|             srs_human_trace("flv get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (size <= 0) { | ||||
|             srs_human_trace("invalid size=%d", size); | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         // TODO: FIXME: mem leak when error.
 | ||||
|         data = (char*)malloc(size); | ||||
|         if ((ret = srs_flv_read_tag_data(ic, data, size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         // data tag
 | ||||
|         if (type == SRS_RTMP_TYPE_SCRIPT) { | ||||
|             continue; | ||||
|         } | ||||
|          | ||||
|         // copy
 | ||||
|         if ((ret = srs_flv_write_tag(oc, type, timestamp, data, size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         free(data); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | @ -1,188 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int parse_flv(srs_flv_t flv); | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // user options.
 | ||||
|     char* in_flv_file; | ||||
|     // flv handler
 | ||||
|     srs_flv_t flv; | ||||
|      | ||||
|     printf("parse and show flv file detail.\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 1) { | ||||
|         printf("parse and show flv file detail\n" | ||||
|             "Usage: %s in_flv_file\n" | ||||
|             "   in_flv_file         flv file to parse and show.\n" | ||||
|             "For example:\n" | ||||
|             "   %s doc/source.200kbps.768x320.flv\n" | ||||
|             "   %s ../../doc/source.200kbps.768x320.flv\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     in_flv_file = argv[1]; | ||||
|     srs_human_trace("input:  %s", in_flv_file); | ||||
|      | ||||
|     if ((flv = srs_flv_open_read(in_flv_file)) == NULL) { | ||||
|         ret = 2; | ||||
|         srs_human_trace("open flv file failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     ret = parse_flv(flv); | ||||
|     srs_flv_close(flv); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void digit_to_char(char* src, int ssize, char* dst, int dsize) | ||||
| { | ||||
|     int i, j; | ||||
|     char v; | ||||
|      | ||||
|     for (i = 0, j = 0; i < ssize && j < dsize; i++) { | ||||
|         if (j >= dsize) { | ||||
|             break; | ||||
|         } | ||||
|         v = (src[i] >> 4) & 0x0F; | ||||
|         if (v < 10) { | ||||
|             dst[j++] = '0' + v; | ||||
|         } else { | ||||
|             dst[j++] = 'A' + (v - 10); | ||||
|         } | ||||
|          | ||||
|         if (j >= dsize) { | ||||
|             break; | ||||
|         } | ||||
|         v = src[i] & 0x0F; | ||||
|         if (v < 10) { | ||||
|             dst[j++] = '0' + v; | ||||
|         } else { | ||||
|             dst[j++] = 'A' + (v - 10); | ||||
|         } | ||||
|          | ||||
|         if (j >= dsize) { | ||||
|             break; | ||||
|         } | ||||
|         if (i < ssize - 1) { | ||||
|             dst[j++] = ' '; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int parse_bytes(char* data, int size, char* hbuf, int hsize, char* tbuf, int tsize, int print_size) | ||||
| { | ||||
|     memset(hbuf, 0, hsize); | ||||
|     memset(tbuf, 0, tsize); | ||||
|      | ||||
|     if (size > 0) { | ||||
|         digit_to_char(data, size, hbuf, hsize - 1); | ||||
|     } | ||||
|      | ||||
|     if (size > print_size * 2) { | ||||
|         digit_to_char(data + size - print_size, size, tbuf, tsize - 1); | ||||
|     } | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int parse_flv(srs_flv_t flv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // flv header
 | ||||
|     char header[13]; | ||||
|     // packet data
 | ||||
|     char type; | ||||
|     uint32_t timestamp = 0; | ||||
|     char* data = NULL; | ||||
|     int32_t size; | ||||
|     int64_t offset = 0; | ||||
|      | ||||
|     if ((ret = srs_flv_read_header(flv, header)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("start parse flv"); | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         offset = srs_flv_tellg(flv); | ||||
|          | ||||
|         // tag header
 | ||||
|         if ((ret = srs_flv_read_tag_header(flv, &type, &size, ×tamp)) != 0) { | ||||
|             if (srs_flv_is_eof(ret)) { | ||||
|                 srs_human_trace("parse completed."); | ||||
|                 return 0; | ||||
|             } | ||||
|             srs_human_trace("flv get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (size <= 0) { | ||||
|             srs_human_trace("invalid size=%d", size); | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         data = (char*)malloc(size); | ||||
|          | ||||
|         if ((ret = srs_flv_read_tag_data(flv, data, size)) == 0) { | ||||
|             if ((ret = srs_human_format_rtmp_packet(buffer, sizeof(buffer), type, timestamp, data, size)) == 0) { | ||||
|                 srs_human_trace("%s", buffer); | ||||
|                  | ||||
|                 char hbuf[48]; char tbuf[48]; | ||||
|                 parse_bytes(data, size, hbuf, sizeof(hbuf), tbuf, sizeof(tbuf), 16); | ||||
|                 srs_human_raw("offset=%d, first and last 16 bytes:\n[+00, +15] %s\n[-15, EOF] %s\n", (int)offset, hbuf, tbuf); | ||||
|             } else { | ||||
|                 srs_human_trace("print packet failed. ret=%d", ret); | ||||
|             } | ||||
|         } else { | ||||
|             srs_human_trace("read flv failed. ret=%d", ret); | ||||
|         } | ||||
|          | ||||
|         free(data); | ||||
|          | ||||
|         if (ret != 0) { | ||||
|             srs_human_trace("parse failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | @ -1,203 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| // for open h264 raw file.
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int read_h264_frame(char* data, int size, char** pp, int* pnb_start_code, int fps, | ||||
|                     char** frame, int* frame_size, int* dts, int* pts) | ||||
| { | ||||
|     char* p = *pp; | ||||
|      | ||||
|     // @remark, for this demo, to publish h264 raw file to SRS,
 | ||||
|     // we search the h264 frame from the buffer which cached the h264 data.
 | ||||
|     // please get h264 raw data from device, it always a encoded frame.
 | ||||
|     if (!srs_h264_startswith_annexb(p, size - (p - data), pnb_start_code)) { | ||||
|         srs_human_trace("h264 raw data invalid."); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     // @see srs_write_h264_raw_frames
 | ||||
|     // each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0,
 | ||||
|     // for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40)
 | ||||
|     *frame = p; | ||||
|     p += *pnb_start_code; | ||||
|      | ||||
|     for (;p < data + size; p++) { | ||||
|         if (srs_h264_startswith_annexb(p, size - (p - data), NULL)) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     *pp = p; | ||||
|     *frame_size = p - *frame; | ||||
|     if (*frame_size <= 0) { | ||||
|         srs_human_trace("h264 raw data invalid."); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     // @remark, please get the dts and pts from device,
 | ||||
|     // we assume there is no B frame, and the fps can guess the fps and dts,
 | ||||
|     // while the dts and pts must read from encode lib or device.
 | ||||
|     *dts += 1000 / fps; | ||||
|     *pts = *dts; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     printf("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder\n"); | ||||
|     printf("SRS(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 3) { | ||||
|         printf("Usage: %s <h264_raw_file> <rtmp_publish_url> <fps>\n", argv[0]); | ||||
|         printf("     h264_raw_file: the h264 raw steam file.\n"); | ||||
|         printf("     rtmp_publish_url: the rtmp publish url.\n"); | ||||
|         printf("     fps: the video average fps, for example, 25.\n"); | ||||
|         printf("For example:\n"); | ||||
|         printf("     %s ./720p.h264.raw rtmp://127.0.0.1:1935/live/livestream 25\n", argv[0]); | ||||
|         printf("Where the file: http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw\n"); | ||||
|         printf("     See: https://github.com/ossrs/srs/issues/66\n"); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     const char* raw_file = argv[1]; | ||||
|     const char* rtmp_url = argv[2]; | ||||
|     // @remark, the dts and pts if read from device, for instance, the encode lib,
 | ||||
|     // so we assume the fps is 25, and each h264 frame is 1000ms/25fps=40ms/f.
 | ||||
|     double fps = atof(argv[3]); | ||||
|     srs_human_trace("raw_file=%s, rtmp_url=%s, fps=%.2f", raw_file, rtmp_url, fps); | ||||
|      | ||||
|     // open file
 | ||||
|     int raw_fd = open(raw_file, O_RDONLY); | ||||
|     if (raw_fd < 0) { | ||||
|         srs_human_trace("open h264 raw file %s failed.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     off_t file_size = lseek(raw_fd, 0, SEEK_END); | ||||
|     if (file_size <= 0) { | ||||
|         srs_human_trace("h264 raw file %s empty.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("read entirely h264 raw file, size=%dKB", (int)(file_size / 1024)); | ||||
|      | ||||
|     char* h264_raw = (char*)malloc(file_size); | ||||
|     if (!h264_raw) { | ||||
|         srs_human_trace("alloc raw buffer failed for file %s.", raw_file); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     lseek(raw_fd, 0, SEEK_SET); | ||||
|     ssize_t nb_read = 0; | ||||
|     if ((nb_read = read(raw_fd, h264_raw, file_size)) != file_size) { | ||||
|         srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.", | ||||
|                         raw_file, (int)(file_size / 1024), (int)(nb_read / 1024)); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|      | ||||
|     // connect rtmp context
 | ||||
|     srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); | ||||
|      | ||||
|     if (srs_rtmp_handshake(rtmp) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if (srs_rtmp_connect_app(rtmp) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if (srs_rtmp_publish_stream(rtmp) != 0) { | ||||
|         srs_human_trace("publish stream failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("publish stream success"); | ||||
|      | ||||
|     int dts = 0; | ||||
|     int pts = 0; | ||||
|     // @remark, to decode the file.
 | ||||
|     char* p = h264_raw; | ||||
|     int count = 0; | ||||
|     for (; p < h264_raw + file_size;) { | ||||
|         // @remark, read a frame from file buffer.
 | ||||
|         char* data = NULL; | ||||
|         int size = 0; | ||||
|         int nb_start_code = 0; | ||||
|         if (read_h264_frame(h264_raw, (int)file_size, &p, &nb_start_code, fps, &data, &size, &dts, &pts) < 0) { | ||||
|             srs_human_trace("read a frame from file buffer failed."); | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         // send out the h264 packet over RTMP
 | ||||
|         int ret = srs_h264_write_raw_frames(rtmp, data, size, dts, pts); | ||||
|         if (ret != 0) { | ||||
|             if (srs_h264_is_dvbsp_error(ret)) { | ||||
|                 srs_human_trace("ignore drop video error, code=%d", ret); | ||||
|             } else if (srs_h264_is_duplicated_sps_error(ret)) { | ||||
|                 srs_human_trace("ignore duplicated sps, code=%d", ret); | ||||
|             } else if (srs_h264_is_duplicated_pps_error(ret)) { | ||||
|                 srs_human_trace("ignore duplicated pps, code=%d", ret); | ||||
|             } else { | ||||
|                 srs_human_trace("send h264 raw data failed. ret=%d", ret); | ||||
|                 goto rtmp_destroy; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // 5bits, 7.3.1 NAL unit syntax,
 | ||||
|         // ISO_IEC_14496-10-AVC-2003.pdf, page 44.
 | ||||
|         //  7: SPS, 8: PPS, 5: I Frame, 1: P Frame, 9: AUD, 6: SEI
 | ||||
|         uint8_t nut = (char)data[nb_start_code] & 0x1f; | ||||
|         srs_human_trace("sent packet: type=%s, time=%d, size=%d, fps=%.2f, b[%d]=%#x(%s)", | ||||
|             srs_human_flv_tag_type2string(SRS_RTMP_TYPE_VIDEO), dts, size, fps, nb_start_code, (char)data[nb_start_code], | ||||
|             (nut == 7? "SPS":(nut == 8? "PPS":(nut == 5? "I":(nut == 1? "P":(nut == 9? "AUD":(nut == 6? "SEI":"Unknown"))))))); | ||||
|          | ||||
|         // @remark, when use encode device, it not need to sleep.
 | ||||
|         if (count++ == 9) { | ||||
|             usleep(1000 * 1000 * count / fps); | ||||
|             count = 0; | ||||
|         } | ||||
|     } | ||||
|     srs_human_trace("h264 raw data completed"); | ||||
|      | ||||
| rtmp_destroy: | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|     close(raw_fd); | ||||
|     free(h264_raw); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,273 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int proxy(srs_flv_t flv, srs_rtmp_t ortmp); | ||||
| int connect_oc(srs_rtmp_t ortmp); | ||||
| 
 | ||||
| #define RE_PULSE_MS 300 | ||||
| #define RE_PULSE_JITTER_MS 3000 | ||||
| int64_t re_create(); | ||||
| void re_update(int64_t re, int32_t starttime, uint32_t time); | ||||
| void re_cleanup(int64_t re, int32_t starttime, uint32_t time); | ||||
| 
 | ||||
| int64_t tools_main_entrance_startup_time; | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // main function
 | ||||
|     tools_main_entrance_startup_time = srs_utils_time_ms(); | ||||
|      | ||||
|     // user option parse index.
 | ||||
|     int opt = 0; | ||||
|     // user options.
 | ||||
|     char* in_flv_file = NULL; | ||||
|     char* out_rtmp_url = NULL; | ||||
|     // rtmp handler
 | ||||
|     srs_rtmp_t ortmp; | ||||
|     // flv handler
 | ||||
|     srs_flv_t flv; | ||||
|      | ||||
|     printf("ingest flv file and publish to RTMP server like FFMPEG.\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("ingest flv file and publish to RTMP server\n" | ||||
|             "Usage: %s <-i in_flv_file> <-y out_rtmp_url>\n" | ||||
|             "   in_flv_file     input flv file, ingest from this file.\n" | ||||
|             "   out_rtmp_url    output rtmp url, publish to this url.\n" | ||||
|             "For example:\n" | ||||
|             "   %s -i doc/source.200kbps.768x320.flv -y rtmp://127.0.0.1/live/livestream\n" | ||||
|             "   %s -i ../../doc/source.200kbps.768x320.flv -y rtmp://127.0.0.1/live/livestream\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     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 <input>"); | ||||
|         return -1; | ||||
|     } | ||||
|     if (!out_rtmp_url) { | ||||
|         srs_human_trace("output invalid, use -y <output>"); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("input: %s", in_flv_file); | ||||
|     srs_human_trace("output: %s", out_rtmp_url); | ||||
|      | ||||
|     if ((flv = srs_flv_open_read(in_flv_file)) == NULL) { | ||||
|         ret = 2; | ||||
|         srs_human_trace("open flv file failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     ortmp = srs_rtmp_create(out_rtmp_url); | ||||
|      | ||||
|     ret = proxy(flv, ortmp); | ||||
|     srs_human_trace("ingest flv to RTMP completed"); | ||||
|      | ||||
|     srs_rtmp_destroy(ortmp); | ||||
|     srs_flv_close(flv); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int do_proxy(srs_flv_t flv, srs_rtmp_t ortmp, int64_t re, int32_t* pstarttime, uint32_t* ptimestamp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // packet data
 | ||||
|     char type; | ||||
|     int size; | ||||
|     char* data = NULL; | ||||
|      | ||||
|     srs_human_trace("start ingest flv to RTMP stream"); | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         // tag header
 | ||||
|         if ((ret = srs_flv_read_tag_header(flv, &type, &size, ptimestamp)) != 0) { | ||||
|             if (srs_flv_is_eof(ret)) { | ||||
|                 srs_human_trace("parse completed."); | ||||
|                 return 0; | ||||
|             } | ||||
|             srs_human_trace("flv get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (size <= 0) { | ||||
|             srs_human_trace("invalid size=%d", size); | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         // TODO: FIXME: mem leak when error.
 | ||||
|         data = (char*)malloc(size); | ||||
|         if ((ret = srs_flv_read_tag_data(flv, data, size)) != 0) { | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         uint32_t timestamp = *ptimestamp; | ||||
|          | ||||
|         if ((ret = srs_human_format_rtmp_packet(buffer, sizeof(buffer), type, timestamp, data, size)) != 0) { | ||||
|             srs_human_trace("print packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|         srs_human_trace("%s", buffer); | ||||
|          | ||||
|         if ((ret = srs_rtmp_write_packet(ortmp, type, *ptimestamp, data, size)) != 0) { | ||||
|             srs_human_trace("irtmp get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (*pstarttime < 0 && srs_utils_flv_tag_is_av(type)) { | ||||
|             *pstarttime = *ptimestamp; | ||||
|         } | ||||
|          | ||||
|         re_update(re, *pstarttime, *ptimestamp); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int proxy(srs_flv_t flv, srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|     uint32_t timestamp = 0; | ||||
|     int32_t starttime = -1; | ||||
|      | ||||
|     char header[13]; | ||||
|     if ((ret = srs_flv_read_header(flv, header)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = connect_oc(ortmp)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     int64_t re = re_create(); | ||||
|      | ||||
|     ret = do_proxy(flv, ortmp, re, &starttime, ×tamp); | ||||
|      | ||||
|     // for the last pulse, always sleep.
 | ||||
|     re_cleanup(re, starttime, timestamp); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int connect_oc(srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_handshake(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp simple handshake failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp simple handshake success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_app(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp connect vhost/app failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp connect vhost/app success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_publish_stream(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp publish stream failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp publish stream success"); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int64_t re_create() | ||||
| { | ||||
|     // if not very precise, we can directly use this as re.
 | ||||
|     int64_t re = srs_utils_time_ms(); | ||||
|      | ||||
|     // use the starttime to get the deviation
 | ||||
|     int64_t deviation = re - tools_main_entrance_startup_time; | ||||
|     srs_human_trace("deviation is %d ms, pulse is %d ms", (int)(deviation), (int)(RE_PULSE_MS)); | ||||
|      | ||||
|     // so, we adjust time to max(0, deviation)
 | ||||
|     // because the last pulse, we already sleeped
 | ||||
|     int adjust = (int)(deviation); | ||||
|     if (adjust > 0) { | ||||
|         srs_human_trace("adjust re time for %d ms", adjust); | ||||
|         re -= adjust; | ||||
|     } else { | ||||
|         srs_human_trace("no need to adjust re time"); | ||||
|     } | ||||
|      | ||||
|     return re; | ||||
| } | ||||
| void re_update(int64_t re, int32_t starttime, uint32_t time) | ||||
| { | ||||
|     // send by pulse algorithm.
 | ||||
|     int64_t now = srs_utils_time_ms(); | ||||
|     int64_t diff = time - starttime - (now -re); | ||||
|     if (diff > RE_PULSE_MS && diff < RE_PULSE_JITTER_MS) { | ||||
|         usleep((useconds_t)(diff * 1000)); | ||||
|     } | ||||
| } | ||||
| void re_cleanup(int64_t re, int32_t starttime, uint32_t time) | ||||
| { | ||||
|     // for the last pulse, always sleep.
 | ||||
|     // for the virtual live encoder long time publishing.
 | ||||
|     int64_t now = srs_utils_time_ms(); | ||||
|     int64_t diff = time - starttime - (now -re); | ||||
|     if (diff > 0) { | ||||
|         srs_human_trace("re_cleanup, diff=%d, start=%d, last=%d ms", (int)diff, starttime, time); | ||||
|         usleep((useconds_t)(diff * 1000)); | ||||
|     } | ||||
| } | ||||
|  | @ -1,261 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int64_t tools_main_entrance_startup_time; | ||||
| int proxy(srs_mp4_t mp4, srs_rtmp_t ortmp); | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     // main function
 | ||||
|     tools_main_entrance_startup_time = srs_utils_time_ms(); | ||||
|      | ||||
|     printf("Ingest mp4 file and publish to RTMP server like FFMPEG.\n"); | ||||
|     printf("SRS(OSSRS) client librtmp library.\n"); | ||||
|     printf("Version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("Ingest mp4 file and publish to RTMP server\n" | ||||
|             "Usage: %s <-i in_mp4_file> <-y out_rtmp_url>\n" | ||||
|             "   in_mp4_file     input mp4 file, ingest from this file.\n" | ||||
|             "   out_rtmp_url    output rtmp url, publish to this url.\n" | ||||
|             "@remark Only support non-seek mp4, see https://github.com/ossrs/srs/issues/738#issuecomment-276343669\n" | ||||
|             "For example:\n" | ||||
|             "   %s -i avatar.mp4 -y rtmp://127.0.0.1/live/livestream\n", | ||||
|             argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     int opt; | ||||
|     for (opt = 0; opt < argc; opt++) { | ||||
|         srs_human_trace("The argv[%d]=%s", opt, argv[opt]); | ||||
|     } | ||||
|      | ||||
|     // fill the options for mac
 | ||||
|     char* in_file = NULL; | ||||
|     char* out_rtmp_url = NULL; | ||||
|     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_file = argv[opt + 1]; break; | ||||
|             case 'y': out_rtmp_url = argv[opt + 1]; break; | ||||
|             default: break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     if (!in_file) { | ||||
|         srs_human_trace("Invalid input file, use -i <input>"); | ||||
|         return -1; | ||||
|     } | ||||
|     if (!out_rtmp_url) { | ||||
|         srs_human_trace("Invalid output url, use -y <output>"); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("Input file: %s", in_file); | ||||
|     srs_human_trace("Output url: %s", out_rtmp_url); | ||||
|      | ||||
|     int ret = 0; | ||||
|      | ||||
|     srs_mp4_t mp4 = NULL; | ||||
|     if ((mp4 = srs_mp4_open_read(in_file)) == NULL) { | ||||
|         ret = 2; | ||||
|         srs_human_trace("open mp4 file failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     srs_rtmp_t ortmp = srs_rtmp_create(out_rtmp_url); | ||||
|      | ||||
|     ret = proxy(mp4, ortmp); | ||||
|     srs_human_trace("Ingest mp4 to RTMP ok."); | ||||
|      | ||||
|     srs_rtmp_destroy(ortmp); | ||||
|     srs_mp4_close(mp4); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int connect_oc(srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_handshake(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp simple handshake failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp simple handshake success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_app(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp connect vhost/app failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp connect vhost/app success"); | ||||
|      | ||||
|     if ((ret = srs_rtmp_publish_stream(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp publish stream failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp publish stream success"); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| #define RE_PULSE_MS 300 | ||||
| #define RE_PULSE_JITTER_MS 3000 | ||||
| 
 | ||||
| int64_t re_create() | ||||
| { | ||||
|     // if not very precise, we can directly use this as re.
 | ||||
|     int64_t re = srs_utils_time_ms(); | ||||
|      | ||||
|     // use the starttime to get the deviation
 | ||||
|     int64_t deviation = re - tools_main_entrance_startup_time; | ||||
|     srs_human_trace("deviation is %d ms, pulse is %d ms", (int)(deviation), (int)(RE_PULSE_MS)); | ||||
|      | ||||
|     // so, we adjust time to max(0, deviation)
 | ||||
|     // because the last pulse, we already sleeped
 | ||||
|     int adjust = (int)(deviation); | ||||
|     if (adjust > 0) { | ||||
|         srs_human_trace("adjust re time for %d ms", adjust); | ||||
|         re -= adjust; | ||||
|     } else { | ||||
|         srs_human_trace("no need to adjust re time"); | ||||
|     } | ||||
|      | ||||
|     return re; | ||||
| } | ||||
| 
 | ||||
| void re_update(int64_t re, int32_t starttime, uint32_t time) | ||||
| { | ||||
|     // send by pulse algorithm.
 | ||||
|     int64_t now = srs_utils_time_ms(); | ||||
|     int64_t diff = time - starttime - (now -re); | ||||
|     if (diff > RE_PULSE_MS && diff < RE_PULSE_JITTER_MS) { | ||||
|         usleep((useconds_t)(diff * 1000)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void re_cleanup(int64_t re, int32_t starttime, uint32_t time) | ||||
| { | ||||
|     // for the last pulse, always sleep.
 | ||||
|     // for the virtual live encoder long time publishing.
 | ||||
|     int64_t now = srs_utils_time_ms(); | ||||
|     int64_t diff = time - starttime - (now -re); | ||||
|     if (diff > 0) { | ||||
|         srs_human_trace("re_cleanup, diff=%d, start=%d, last=%d ms", | ||||
|                         (int)diff, starttime, time); | ||||
|         usleep((useconds_t)(diff * 1000)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int do_proxy(srs_mp4_t mp4, srs_rtmp_t ortmp, int64_t re, int32_t* pstarttime, uint32_t* ptimestamp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     srs_human_trace("start ingest mp4 to RTMP stream"); | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         // packet data
 | ||||
|         char type; | ||||
|         int32_t size; | ||||
|         char* data = NULL; | ||||
|          | ||||
|         // Read a mp4 sample and convert to flv tag.
 | ||||
|         if (1) { | ||||
|             srs_mp4_sample_t sample; | ||||
|             if ((ret = srs_mp4_read_sample(mp4, &sample)) != 0) { | ||||
|                 if (srs_mp4_is_eof(ret)) { | ||||
|                     srs_human_trace("parse completed."); | ||||
|                     return 0; | ||||
|                 } | ||||
|                 srs_human_trace("mp4 get sample failed. ret=%d", ret); | ||||
|                 return ret; | ||||
|             } | ||||
|              | ||||
|             size = srs_mp4_sizeof(mp4, &sample); | ||||
|             data = (char*)malloc(size); | ||||
|              | ||||
|             if ((ret = srs_mp4_to_flv_tag(mp4, &sample, &type, ptimestamp, data, size)) != 0) { | ||||
|                 return ret; | ||||
|             } | ||||
|              | ||||
|             srs_mp4_free_sample(&sample); | ||||
|         } | ||||
|         uint32_t timestamp = *ptimestamp; | ||||
|          | ||||
|         if ((ret = srs_human_format_rtmp_packet(buffer, sizeof(buffer), type, timestamp, data, size)) != 0) { | ||||
|             srs_human_trace("print packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|         srs_human_trace("%s", buffer); | ||||
|          | ||||
|         if ((ret = srs_rtmp_write_packet(ortmp, type, *ptimestamp, data, size)) != 0) { | ||||
|             srs_human_trace("irtmp get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (*pstarttime < 0 && srs_utils_flv_tag_is_av(type)) { | ||||
|             *pstarttime = *ptimestamp; | ||||
|         } | ||||
|          | ||||
|         re_update(re, *pstarttime, *ptimestamp); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int proxy(srs_mp4_t mp4, srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     if ((ret = srs_mp4_init_demuxer(mp4)) != 0) { | ||||
|         srs_human_trace("init demuxer failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = connect_oc(ortmp)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     int64_t re = re_create(); | ||||
|      | ||||
|     uint32_t timestamp = 0; | ||||
|     int32_t starttime = -1; | ||||
|     ret = do_proxy(mp4, ortmp, re, &starttime, ×tamp); | ||||
|      | ||||
|     // for the last pulse, always sleep.
 | ||||
|     re_cleanup(re, starttime, timestamp); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,279 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int connect_ic(srs_rtmp_t irtmp); | ||||
| int connect_oc(srs_rtmp_t ortmp); | ||||
| int proxy(srs_rtmp_t irtmp, srs_rtmp_t ortmp); | ||||
| 
 | ||||
| // whether use verbose log.
 | ||||
| int verbose = 0; | ||||
| // 2000 is about 30s.
 | ||||
| #define PITHY_PRINT_EVERY_MSGS 2000 | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // user option parse index.
 | ||||
|     int opt = 0; | ||||
|     // user options.
 | ||||
|     char* in_rtmp_url = NULL; | ||||
|     char* out_rtmp_url = NULL; | ||||
|     // rtmp handler
 | ||||
|     srs_rtmp_t irtmp, ortmp; | ||||
|      | ||||
|     printf("Ingest RTMP to server like FFMPEG over srs-librtmp %d.%d.%d\n", | ||||
|            srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 2) { | ||||
|         printf("ingest RTMP and publish to RTMP server\n" | ||||
|             "Usage: %s <-i in_rtmp_url> <-y out_rtmp_url> [-v verbose]\n" | ||||
|             "   in_rtmp_url     input rtmp url, ingest from this url.\n" | ||||
|             "   out_rtmp_url    output rtmp url, publish to this url.\n" | ||||
|             "   verbose         output verbose log.\n" | ||||
|             "For example:\n" | ||||
|             "   %s -i rtmp://127.0.0.1/live/livestream -y rtmp://127.0.0.1/live/demo\n" | ||||
|             "   %s -i rtmp://127.0.0.1/live/livestream -y rtmp://127.0.0.1/live/demo -v verbose\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     // 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]; break; | ||||
|             case 'y': out_rtmp_url = argv[++opt]; break; | ||||
|             case 'v': verbose=1; opt++; break; | ||||
|             default: break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     if (!in_rtmp_url) { | ||||
|         srs_human_trace("input invalid, use -i <input>"); | ||||
|         return -1; | ||||
|     } | ||||
|     if (!out_rtmp_url) { | ||||
|         srs_human_trace("output invalid, use -y <output>"); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("ingest %s to %s, verbose=%d", in_rtmp_url, out_rtmp_url, verbose); | ||||
|      | ||||
|     irtmp = srs_rtmp_create(in_rtmp_url); | ||||
|     ortmp = srs_rtmp_create(out_rtmp_url); | ||||
|      | ||||
|     ret = proxy(irtmp, ortmp); | ||||
|     srs_human_trace("proxy completed"); | ||||
|      | ||||
|     srs_rtmp_destroy(irtmp); | ||||
|     srs_rtmp_destroy(ortmp); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int proxy(srs_rtmp_t irtmp, srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // packet data
 | ||||
|     int size; | ||||
|     char type; | ||||
|     char* data; | ||||
|     uint32_t timestamp; | ||||
|     uint64_t nb_msgs = 0; | ||||
|      | ||||
|     if ((ret = connect_ic(irtmp)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = connect_oc(ortmp)) != 0) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if (verbose) { | ||||
|         srs_human_trace("start proxy RTMP stream"); | ||||
|     } else { | ||||
|         srs_human_verbose("start proxy RTMP stream"); | ||||
|     } | ||||
|      | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         if ((ret = srs_rtmp_read_packet(irtmp, &type, ×tamp, &data, &size)) != 0) { | ||||
|             srs_human_trace("irtmp get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (!srs_utils_flv_tag_is_ok(type)) { | ||||
|             if (verbose) { | ||||
|                 srs_human_trace("ignore invalid flv tag=%d, dts=%d, %d bytes", type, timestamp, size); | ||||
|             } else { | ||||
|                 srs_human_verbose("ignore invalid flv tag=%d, dts=%d, %d bytes", type, timestamp, size); | ||||
|             } | ||||
|             free(data); | ||||
|             continue; | ||||
|         } | ||||
|          | ||||
|         if (verbose || ((nb_msgs++ % PITHY_PRINT_EVERY_MSGS) == 0 && nb_msgs > 10)) { | ||||
|             if ((ret = srs_human_format_rtmp_packet(buffer, sizeof(buffer), type, timestamp, data, size)) != 0) { | ||||
|                 srs_human_trace("print packet failed. ret=%d", ret); | ||||
|                 return ret; | ||||
|             } | ||||
|             srs_human_trace("%s", buffer); | ||||
|         } | ||||
|          | ||||
|         if ((ret = srs_rtmp_write_packet(ortmp, type, timestamp, data, size)) != 0) { | ||||
|             srs_human_trace("irtmp get packet failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (verbose) { | ||||
|             srs_human_trace("ortmp sent packet: type=%s, time=%d, size=%d", | ||||
|                             srs_human_flv_tag_type2string(type), timestamp, size); | ||||
|         } else { | ||||
|             srs_human_verbose("ortmp sent packet: type=%s, time=%d, size=%d", | ||||
|                               srs_human_flv_tag_type2string(type), timestamp, size); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int connect_ic(srs_rtmp_t irtmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // srs debug info.
 | ||||
|     char* ip = NULL; | ||||
|     char* sig = NULL; | ||||
|     int pid = 0, cid = 0; | ||||
|     int major = 0, minor = 0, revision= 0, build = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_handshake(irtmp)) != 0) { | ||||
|         srs_human_trace("irtmp simple handshake failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if (verbose) { | ||||
|         srs_human_trace("irtmp simple handshake success"); | ||||
|     } else { | ||||
|         srs_human_verbose("irtmp simple handshake success"); | ||||
|     } | ||||
|      | ||||
|     if (srs_rtmp_connect_app(irtmp) != 0) { | ||||
|         srs_human_trace("irtmp connect vhost/app failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_get_server_sig(irtmp, &sig)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_id(irtmp, &ip, &pid, &cid)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_version(irtmp, &major, &minor, &revision, &build)) != 0) { | ||||
|         srs_human_trace("Retrieve server version failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("irtmp connect ok, ip=%s, server=%s/%d.%d.%d.%d, pid=%d, cid=%d", | ||||
|                     ip, sig, major, minor, revision, build, pid, cid); | ||||
|      | ||||
|     if ((ret = srs_rtmp_play_stream(irtmp)) != 0) { | ||||
|         srs_human_trace("irtmp play stream failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if (verbose) { | ||||
|         srs_human_trace("irtmp play stream success"); | ||||
|     } else { | ||||
|         srs_human_verbose("irtmp play stream success"); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int connect_oc(srs_rtmp_t ortmp) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     // srs debug info.
 | ||||
|     char* ip = NULL; | ||||
|     char* sig = NULL; | ||||
|     int pid = 0, cid = 0; | ||||
|     int major = 0, minor = 0, revision= 0, build = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_handshake(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp simple handshake failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if (verbose) { | ||||
|         srs_human_trace("ortmp simple handshake success"); | ||||
|     } else { | ||||
|         srs_human_verbose("ortmp simple handshake success"); | ||||
|     } | ||||
|      | ||||
|     if (srs_rtmp_connect_app(ortmp) != 0) { | ||||
|         srs_human_trace("ortmp connect vhost/app failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_get_server_sig(ortmp, &sig)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_id(ortmp, &ip, &pid, &cid)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_version(ortmp, &major, &minor, &revision, &build)) != 0) { | ||||
|         srs_human_trace("Retrieve server version failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("ortmp connect ok, ip=%s, server=%s/%d.%d.%d.%d, pid=%d, cid=%d", | ||||
|                     ip, sig, major, minor, revision, build, pid, cid); | ||||
|      | ||||
|     if ((ret = srs_rtmp_publish_stream(ortmp)) != 0) { | ||||
|         srs_human_trace("ortmp publish stream failed. ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if (verbose) { | ||||
|         srs_human_trace("ortmp publish stream success"); | ||||
|     } else { | ||||
|         srs_human_verbose("ortmp publish stream success"); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | @ -1,88 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     printf("suck rtmp stream like rtmpdump\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 1) { | ||||
|         printf("Usage: %s <rtmp_url>\n" | ||||
|             "   rtmp_url     RTMP stream url to play\n" | ||||
|             "For example:\n" | ||||
|             "   %s rtmp://127.0.0.1:1935/live/livestream\n", | ||||
|             argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("rtmp url: %s", argv[1]); | ||||
|     srs_rtmp_t rtmp = srs_rtmp_create(argv[1]); | ||||
|      | ||||
|     if (srs_rtmp_handshake(rtmp) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if (srs_rtmp_connect_app(rtmp) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if (srs_rtmp_play_stream(rtmp) != 0) { | ||||
|         srs_human_trace("play stream failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("play stream success"); | ||||
|      | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         int size; | ||||
|         char type; | ||||
|         char* data; | ||||
|         uint32_t timestamp; | ||||
|          | ||||
|         if (srs_rtmp_read_packet(rtmp, &type, ×tamp, &data, &size) != 0) { | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|          | ||||
|         if (srs_human_format_rtmp_packet(buffer, sizeof(buffer), type, timestamp, data, size) != 0) { | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|         srs_human_trace("%s", buffer); | ||||
|          | ||||
|         free(data); | ||||
|     } | ||||
|      | ||||
| rtmp_destroy: | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
|  | @ -1,93 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     printf("publish rtmp stream to server like FMLE/FFMPEG/Encoder\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|      | ||||
|     if (argc <= 1) { | ||||
|         printf("Usage: %s <rtmp_url>\n" | ||||
|             "   rtmp_url     RTMP stream url to publish\n" | ||||
|             "For example:\n" | ||||
|             "   %s rtmp://127.0.0.1:1935/live/livestream\n", | ||||
|             argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     // warn it .
 | ||||
|     // @see: https://github.com/ossrs/srs/issues/126
 | ||||
|     srs_human_trace("\033[33m%s\033[0m", | ||||
|         "[warning] it's only a sample to use librtmp. " | ||||
|         "please never use it to publish and test forward/transcode/edge/HLS whatever. " | ||||
|         "you should refer to this tool to use the srs-librtmp to publish the real media stream." | ||||
|         "read about: https://github.com/ossrs/srs/issues/126"); | ||||
|     srs_human_trace("rtmp url: %s", argv[1]); | ||||
|     srs_rtmp_t rtmp = srs_rtmp_create(argv[1]); | ||||
|      | ||||
|     if (srs_rtmp_handshake(rtmp) != 0) { | ||||
|         srs_human_trace("simple handshake failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("simple handshake success"); | ||||
|      | ||||
|     if (srs_rtmp_connect_app(rtmp) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("connect vhost/app success"); | ||||
|      | ||||
|     if (srs_rtmp_publish_stream(rtmp) != 0) { | ||||
|         srs_human_trace("publish stream failed."); | ||||
|         goto rtmp_destroy; | ||||
|     } | ||||
|     srs_human_trace("publish stream success"); | ||||
|      | ||||
|     uint32_t timestamp = 0; | ||||
|     for (;;) { | ||||
|         char type = SRS_RTMP_TYPE_VIDEO; | ||||
|         int size = 4096; | ||||
|         char* data = (char*)malloc(4096); | ||||
|          | ||||
|         timestamp += 40; | ||||
|          | ||||
|         if (srs_rtmp_write_packet(rtmp, type, timestamp, data, size) != 0) { | ||||
|             goto rtmp_destroy; | ||||
|         } | ||||
|         srs_human_trace("sent packet: type=%s, time=%d, size=%d", srs_human_flv_tag_type2string(type), timestamp, size); | ||||
|          | ||||
|         usleep(40 * 1000); | ||||
|     } | ||||
|      | ||||
| rtmp_destroy: | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
|  | @ -1,350 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2018 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include "../../objs/include/srs_librtmp.h" | ||||
| 
 | ||||
| void parse_amf0_object(char* p, srs_amf0_t args) | ||||
| { | ||||
|     char opvt = 0; // object property value type.
 | ||||
|     const char* opnp = NULL; // object property name ptr.
 | ||||
|     const char* opvp = NULL; // object property value ptr.
 | ||||
|      | ||||
|     while (*p) { | ||||
|         switch (*p++) { | ||||
|             case 'O': | ||||
|                 while (*p && *p++ != ':') { | ||||
|                 } | ||||
|                 if (*p++ == '1') { | ||||
|                     printf("amf0 object start\n"); | ||||
|                 } else { | ||||
|                     printf("amf0 object end\n"); | ||||
|                 } | ||||
|                 break; | ||||
|             case 'N': | ||||
|                 opvt = *p++; | ||||
|                 if (*p++ != ':') { | ||||
|                     printf("object property must split by :.\n"); | ||||
|                     exit(-1); | ||||
|                 } | ||||
|                 opnp = p++; | ||||
|                 while (*p && *p++ != ':') { | ||||
|                 } | ||||
|                 p[-1] = 0; | ||||
|                 opvp = p; | ||||
|                 printf("amf0 %c property[%s]=%s\n", opvt, opnp, opvp); | ||||
|                 switch(opvt) { | ||||
|                     case 'S': | ||||
|                         srs_amf0_object_property_set(args, opnp, srs_amf0_create_string(opvp)); | ||||
|                         break; | ||||
|                     default: | ||||
|                         printf("unsupported object property.\n"); | ||||
|                         exit(-1); | ||||
|                 } | ||||
|                 *p=0; | ||||
|                 break; | ||||
|             default: | ||||
|                 printf("only supports an object arg.\n"); | ||||
|                 exit(-1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // srs debug info.
 | ||||
| char* ip = NULL; | ||||
| char* sig = NULL; | ||||
| int pid = 0, cid = 0; | ||||
| int major = 0, minor = 0, revision= 0, build = 0; | ||||
| // User options.
 | ||||
| int complex_handshake = 0; | ||||
| const char* rtmp_url = NULL; | ||||
| const char* output_flv = NULL; | ||||
| const char* swfUrl = NULL; | ||||
| const char* tcUrl = NULL; | ||||
| const char* pageUrl = NULL; | ||||
| srs_amf0_t args = NULL; | ||||
| 
 | ||||
| int do_proxy(srs_rtmp_t rtmp, srs_flv_t flv) | ||||
| { | ||||
|     int ret = 0; | ||||
|      | ||||
|     if ((ret = srs_rtmp_dns_resolve(rtmp)) != 0) { | ||||
|         srs_human_trace("dns resolve failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_server(rtmp)) != 0) { | ||||
|         srs_human_trace("connect to server failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if (complex_handshake) { | ||||
|         if ((ret = srs_rtmp_do_complex_handshake(rtmp)) != 0) { | ||||
|             srs_human_trace("complex handshake failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|         srs_human_trace("do complex handshake success"); | ||||
|     } else { | ||||
|         if ((ret = srs_rtmp_do_simple_handshake(rtmp)) != 0) { | ||||
|             srs_human_trace("simple handshake failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|         srs_human_trace("do simple handshake success"); | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_set_connect_args(rtmp, tcUrl, swfUrl, pageUrl, args)) != 0) { | ||||
|         srs_human_trace("set connect args failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_connect_app(rtmp)) != 0) { | ||||
|         srs_human_trace("connect vhost/app failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if ((ret = srs_rtmp_get_server_sig(rtmp, &sig)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_id(rtmp, &ip, &pid, &cid)) != 0) { | ||||
|         srs_human_trace("Retrieve server ID failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = srs_rtmp_get_server_version(rtmp, &major, &minor, &revision, &build)) != 0) { | ||||
|         srs_human_trace("Retrieve server version failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("connect ok, ip=%s, server=%s/%d.%d.%d.%d, pid=%d, cid=%d", | ||||
|                     ip, sig, major, minor, revision, build, pid, cid); | ||||
|      | ||||
|     if ((ret = srs_rtmp_play_stream(rtmp)) != 0) { | ||||
|         srs_human_trace("play stream failed, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     srs_human_trace("play stream success"); | ||||
|      | ||||
|     if (flv) { | ||||
|         // flv header
 | ||||
|         char header[9]; | ||||
|         // 3bytes, signature, "FLV",
 | ||||
|         header[0] = 'F'; | ||||
|         header[1] = 'L'; | ||||
|         header[2] = 'V'; | ||||
|         // 1bytes, version, 0x01,
 | ||||
|         header[3] = 0x01; | ||||
|         // 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present.
 | ||||
|         header[4] = 0x03; // audio + video.
 | ||||
|         // 4bytes, dataoffset
 | ||||
|         header[5] = 0x00; | ||||
|         header[6] = 0x00; | ||||
|         header[7] = 0x00; | ||||
|         header[8] = 0x09; | ||||
|         if ((ret = srs_flv_write_header(flv, header)) != 0) { | ||||
|             srs_human_trace("write flv header failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     int64_t nb_packets = 0; | ||||
|     uint32_t pre_timestamp = 0; | ||||
|     int64_t pre_now = -1; | ||||
|     int64_t start_time = -1; | ||||
|     char buffer[1024]; | ||||
|     for (;;) { | ||||
|         int size; | ||||
|         char type; | ||||
|         char* data; | ||||
|         uint32_t timestamp; | ||||
|          | ||||
|         if ((ret = srs_rtmp_read_packet(rtmp, &type, ×tamp, &data, &size)) != 0) { | ||||
|             srs_human_trace("read rtmp packet failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         if (pre_now == -1) { | ||||
|             pre_now = srs_utils_time_ms(); | ||||
|         } | ||||
|         if (start_time == -1) { | ||||
|             start_time = srs_utils_time_ms(); | ||||
|         } | ||||
|          | ||||
|         if ((ret = srs_human_format_rtmp_packet2(buffer, sizeof(buffer), type, timestamp, data, size, pre_timestamp, pre_now, start_time, nb_packets++)) != 0) { | ||||
|             srs_human_trace("print rtmp packet failed, ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|         srs_human_trace("%s", buffer); | ||||
|          | ||||
|         pre_timestamp = timestamp; | ||||
|         pre_now = srs_utils_time_ms(); | ||||
|          | ||||
|         // we only write some types of messages to flv file.
 | ||||
|         int is_flv_msg = type == SRS_RTMP_TYPE_AUDIO | ||||
|         || type == SRS_RTMP_TYPE_VIDEO || type == SRS_RTMP_TYPE_SCRIPT; | ||||
|          | ||||
|         // for script data, ignore except onMetaData
 | ||||
|         if (type == SRS_RTMP_TYPE_SCRIPT) { | ||||
|             if (!srs_rtmp_is_onMetaData(type, data, size)) { | ||||
|                 is_flv_msg = 0; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         if (flv) { | ||||
|             if (is_flv_msg) { | ||||
|                 if ((ret = srs_flv_write_tag(flv, type, timestamp, data, size)) != 0) { | ||||
|                     srs_human_trace("dump rtmp packet failed, ret=%d", ret); | ||||
|                     return ret; | ||||
|                 } | ||||
|             } else { | ||||
|                 srs_human_trace("drop message type=%#x, size=%dB", type, size); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         free(data); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     srs_flv_t flv = NULL; | ||||
|     srs_rtmp_t rtmp = NULL; | ||||
|      | ||||
|     printf("dump rtmp stream to flv file\n"); | ||||
|     printf("srs(ossrs) client librtmp library.\n"); | ||||
|     printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); | ||||
|     printf("@refer to http://rtmpdump.mplayerhq.hu/rtmpdump.1.html\n"); | ||||
|      | ||||
|     int show_help = 0; | ||||
|     const char* short_options = "hxr:o:s:t:p:C:"; | ||||
|     struct option long_options[] = { | ||||
|         {"rtmp", required_argument, 0, 'r'}, | ||||
|         {"flv", required_argument, 0, 'o'}, | ||||
|         {"swfUrl", required_argument, 0, 's'}, | ||||
|         {"tcUrl", required_argument, 0, 't'}, | ||||
|         {"pageUrl", required_argument, 0, 'p'}, | ||||
|         {"conn", required_argument, 0, 'C'}, | ||||
|         {"complex", no_argument, 0, 'x'}, | ||||
|         {"help", no_argument, 0, 'h'}, | ||||
|         {0, 0, 0, 0} | ||||
|     }; | ||||
|      | ||||
|     int opt = 0; | ||||
|     int option_index = 0; | ||||
|     while((opt = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1){ | ||||
|         switch(opt){ | ||||
|             case 'r': | ||||
|                 rtmp_url = optarg; | ||||
|                 break; | ||||
|             case 'o': | ||||
|                 output_flv = optarg; | ||||
|                 break; | ||||
|             case 's': | ||||
|                 swfUrl = optarg; | ||||
|                 break; | ||||
|             case 't': | ||||
|                 tcUrl = optarg; | ||||
|                 break; | ||||
|             case 'p': | ||||
|                 pageUrl = optarg; | ||||
|                 break; | ||||
|             case 'C': | ||||
|                 if (!args) { | ||||
|                     args = srs_amf0_create_object(); | ||||
|                 } | ||||
|                 char* p = (char*)optarg; | ||||
|                 parse_amf0_object(p, args); | ||||
|                 break; | ||||
|             case 'x': | ||||
|                 complex_handshake = 1; | ||||
|                 break; | ||||
|             case 'h': | ||||
|                 show_help = 1; | ||||
|                 break; | ||||
|             default: | ||||
|                 printf("unsupported opt.\n"); | ||||
|                 exit(-1); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     if (!rtmp_url || show_help) { | ||||
|         printf("Usage: %s -r url [-o output] [-s swfUrl] [-t tcUrl] [-p pageUrl] [-C conndata] [--complex] [-h]\n" | ||||
|             "Options:\n" | ||||
|             "   --rtmp -r url\n" | ||||
|             "       URL of the server and media content.\n" | ||||
|             "   --flv -o output\n" | ||||
|             "       Specify the output file name. If the name is − or is omitted, the stream is written to stdout.\n" | ||||
|             "   --complex\n" | ||||
|             "       Whether use complex handshake(srs-librtmp with ssl required).\n" | ||||
|             "   --swfUrl -s url\n" | ||||
|             "       URL of the SWF player for the media. By default no value will be sent.\n" | ||||
|             "   --tcUrl -t url\n" | ||||
|             "       URL of the target stream. Defaults to rtmp[e]://host[:port]/app/playpath.\n" | ||||
|             "   --pageUrl -p url\n" | ||||
|             "       URL of the web page in which the media was embedded. By default no value will be sent.\n" | ||||
|             "   −−conn −C type:data\n" | ||||
|             "       Append arbitrary AMF data to the Connect message. The type must be B for Boolean, N for number, S for string, O for object, or Z for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, respectively. Likewise for Objects the data must be 0 or 1 to end or begin an object, respectively. Data items in subobjects may be named, by prefixing the type with 'N' and specifying the name before the value, e.g. NB:myFlag:1. This option may be used multiple times to construct arbitrary AMF sequences. E.g.\n" | ||||
|             "       −C B:1 −C S:authMe −C O:1 −C NN:code:1.23 −C NS:flag:ok −C O:0\n" | ||||
|             "       -C O:1 -C NS:CONN:\" -C B:4Rg9vr0\" -C O:0\n" | ||||
|             "       @remark, support a object args only.\n" | ||||
|             "   --help -h\n" | ||||
|             "       Print a summary of command options.\n" | ||||
|             "For example:\n" | ||||
|             "   %s -r rtmp://127.0.0.1:1935/live/livestream -o output.flv\n" | ||||
|             "   %s -h\n", | ||||
|             argv[0], argv[0], argv[0]); | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     srs_human_trace("rtmp url: %s", rtmp_url); | ||||
|     srs_human_trace("handshake: %s", (complex_handshake? "complex" : "simple")); | ||||
|     srs_human_trace("swfUrl: %s", swfUrl); | ||||
|     srs_human_trace("pageUrl: %s", pageUrl); | ||||
|     srs_human_trace("tcUrl: %s", tcUrl); | ||||
|     if (output_flv) { | ||||
|         srs_human_trace("flv output path: %s", output_flv); | ||||
|     } else { | ||||
|         srs_human_trace("output to console"); | ||||
|     } | ||||
|      | ||||
|     rtmp = srs_rtmp_create(rtmp_url); | ||||
|     if (output_flv) { | ||||
|         flv = srs_flv_open_write(output_flv); | ||||
|     } | ||||
|      | ||||
|     int ret = 0; | ||||
|     if ((ret = do_proxy(rtmp, flv)) != 0) { | ||||
|         srs_human_trace("Dump RTMP failed, ret=%d", ret); | ||||
|     } | ||||
|      | ||||
|     srs_rtmp_destroy(rtmp); | ||||
|     srs_flv_close(flv); | ||||
|     srs_human_trace("completed"); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
|  | @ -1,269 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| params="$@" | ||||
| echo "params is: $params" | ||||
| 
 | ||||
| # discover the current work dir, the log and access. | ||||
| echo "argv[0]=$0" | ||||
| if [[ ! -f $0 ]]; then  | ||||
|     echo "directly execute the scripts on shell."; | ||||
|     work_dir=`pwd` | ||||
| else  | ||||
|     echo "execute scripts in file: $0"; | ||||
|     work_dir=`dirname $0`; work_dir=`(cd ${work_dir} && pwd)` | ||||
| fi | ||||
| work_dir=`(cd ${work_dir}/.. && pwd)` | ||||
| product_dir=$work_dir | ||||
| build_objs=${work_dir}/objs | ||||
| package_dir=${build_objs}/package | ||||
| 
 | ||||
| log="${build_objs}/test.`date +%s`.log" && . ${product_dir}/scripts/_log.sh && check_log | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then exit $ret; fi | ||||
| 
 | ||||
| item="./configure" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --x86-x64" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --pure-rtmp" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-ssl" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-hls" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-dvr" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-nginx" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-http-callback" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-http-server" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-http-api" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-ffmpeg" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-transcode" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-ingest" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-librtmp" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-research" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-stream-caster --with-http-api" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-utest" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-ssl --with-utest" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-gperf" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-gperf --with-gmc" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-gperf --with-gmp" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-gperf --with-gcp" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --with-gprof" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --log-verbose" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --log-info" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --log-trace" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast --log-info --log-verbose --log-trace" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| ####################################################################################################### | ||||
| ####################################################################################################### | ||||
| ####################################################################################################### | ||||
| item="./configure --dev" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --fast-dev" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --demo" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --full" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| ####################################################################################################### | ||||
| ####################################################################################################### | ||||
| ####################################################################################################### | ||||
| item="./configure --disable-all --with-ssl" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-hls --with-ssl --with-http-server --with-http-api" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-ssl --with-hls --with-nginx" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-ssl --with-hls --with-nginx --with-ffmpeg --with-transcode" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-ssl --with-ffmpeg --with-transcode" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-ssl --with-ffmpeg --with-ingest" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| item="./configure --disable-all --with-hls --with-ssl --with-http-server" | ||||
| ok_msg "test \" ${item} \"" | ||||
| ($item && make $params) >>$log 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi | ||||
| ok_msg "test \" ${item} \" success" | ||||
| 
 | ||||
| echo "success" | ||||
|  | @ -1468,9 +1468,6 @@ srs_error_t SrsConfig::reload_conf(SrsConfig* conf) | |||
|     root = conf->root; | ||||
|     conf->root = NULL; | ||||
|      | ||||
|     // merge config.
 | ||||
|     std::vector<ISrsReloadHandler*>::iterator it; | ||||
|      | ||||
|     // never support reload:
 | ||||
|     //      daemon
 | ||||
|     //
 | ||||
|  | @ -2246,7 +2243,7 @@ srs_error_t SrsConfig::global_to_json(SrsJsonObject* obj) | |||
|         sobjs->set(dir->arg0(), sobj); | ||||
|          | ||||
|         SrsStatisticVhost* svhost = stat->find_vhost(dir->arg0()); | ||||
|         sobj->set("id", SrsJsonAny::integer(svhost? (double)svhost->id : 0)); | ||||
|         sobj->set("id", SrsJsonAny::str(svhost? svhost->id.c_str() : "")); | ||||
|         sobj->set("name", dir->dumps_arg0_to_str()); | ||||
|         sobj->set("enabled", SrsJsonAny::boolean(get_vhost_enabled(dir->arg0()))); | ||||
|          | ||||
|  | @ -2371,7 +2368,7 @@ srs_error_t SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsJsonObject* obj | |||
|     SrsStatistic* stat = SrsStatistic::instance(); | ||||
|      | ||||
|     SrsStatisticVhost* svhost = stat->find_vhost(vhost->arg0()); | ||||
|     obj->set("id", SrsJsonAny::integer(svhost? (double)svhost->id : 0)); | ||||
|     obj->set("id", SrsJsonAny::str(svhost? svhost->id.c_str() : "")); | ||||
|      | ||||
|     obj->set("name", vhost->dumps_arg0_to_str()); | ||||
|     obj->set("enabled", SrsJsonAny::boolean(get_vhost_enabled(vhost))); | ||||
|  | @ -3937,7 +3934,8 @@ srs_error_t SrsConfig::check_normal_config() | |||
|             } else if (n == "rtc") { | ||||
|                 for (int j = 0; j < (int)conf->directives.size(); j++) { | ||||
|                     string m = conf->at(j)->name; | ||||
|                     if (m != "enabled" && m != "bframe" && m != "aac" && m != "stun_timeout" && m != "stun_strict_check") { | ||||
|                     if (m != "enabled" && m != "bframe" && m != "aac" && m != "stun_timeout" && m != "stun_strict_check" | ||||
|                         && m != "keep_sequence") { | ||||
|                         return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.rtc.%s of %s", m.c_str(), vhost->arg0().c_str()); | ||||
|                     } | ||||
|                 } | ||||
|  | @ -5020,6 +5018,24 @@ bool SrsConfig::get_rtc_stun_strict_check(string vhost) | |||
|     return SRS_CONF_PERFER_FALSE(conf->arg0()); | ||||
| } | ||||
| 
 | ||||
| bool SrsConfig::get_rtc_keep_sequence(string vhost) | ||||
| { | ||||
|     static bool DEFAULT = false; | ||||
| 
 | ||||
|     SrsConfDirective* conf = get_rtc(vhost); | ||||
| 
 | ||||
|     if (!conf) { | ||||
|         return DEFAULT; | ||||
|     } | ||||
| 
 | ||||
|     conf = conf->get("keep_sequence"); | ||||
|     if (!conf || conf->arg0().empty()) { | ||||
|         return DEFAULT; | ||||
|     } | ||||
| 
 | ||||
|     return SRS_CONF_PERFER_FALSE(conf->arg0()); | ||||
| } | ||||
| 
 | ||||
| bool SrsConfig::get_rtc_nack_enabled(string vhost) | ||||
| { | ||||
|     static bool DEFAULT = true; | ||||
|  |  | |||
|  | @ -544,6 +544,7 @@ public: | |||
|     bool get_rtc_aac_discard(std::string vhost); | ||||
|     srs_utime_t get_rtc_stun_timeout(std::string vhost); | ||||
|     bool get_rtc_stun_strict_check(std::string vhost); | ||||
|     bool get_rtc_keep_sequence(std::string vhost); | ||||
|     bool get_rtc_nack_enabled(std::string vhost); | ||||
|     bool get_rtc_twcc_enabled(std::string vhost); | ||||
| 
 | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ srs_error_t SrsConnection::cycle() | |||
|     return srs_success; | ||||
| } | ||||
| 
 | ||||
| int SrsConnection::srs_id() | ||||
| string SrsConnection::srs_id() | ||||
| { | ||||
|     return trd->cid(); | ||||
| } | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ public: | |||
|     virtual srs_error_t cycle(); | ||||
| public: | ||||
|     // Get the srs id which identify the client.
 | ||||
|     virtual int srs_id(); | ||||
|     virtual std::string srs_id(); | ||||
|     // Get the remote ip of peer.
 | ||||
|     virtual std::string remote_ip(); | ||||
|     // Set connection to expired.
 | ||||
|  |  | |||
|  | @ -533,7 +533,7 @@ srs_error_t SrsDvrMp4Segmenter::close_encoder() | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, string p) | ||||
| SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(std::string c, SrsRequest* r, string p) | ||||
| { | ||||
|     cid = c; | ||||
|     req = r->copy(); | ||||
|  | @ -673,7 +673,7 @@ srs_error_t SrsDvrPlan::on_reap_segment() | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int cid = _srs_context->get_id(); | ||||
|     std::string cid = _srs_context->get_id(); | ||||
|      | ||||
|     SrsFragment* fragment = segment->current(); | ||||
|     string fullpath = fragment->fullpath(); | ||||
|  |  | |||
|  | @ -159,11 +159,11 @@ protected: | |||
| class SrsDvrAsyncCallOnDvr : public ISrsAsyncCallTask | ||||
| { | ||||
| private: | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     std::string path; | ||||
|     SrsRequest* req; | ||||
| public: | ||||
|     SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, std::string p); | ||||
|     SrsDvrAsyncCallOnDvr(std::string c, SrsRequest* r, std::string p); | ||||
|     virtual ~SrsDvrAsyncCallOnDvr(); | ||||
| public: | ||||
|     virtual srs_error_t call(); | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ void SrsHlsSegment::config_cipher(unsigned char* key,unsigned char* iv) | |||
|     fw->config_cipher(key, iv); | ||||
| } | ||||
| 
 | ||||
| SrsDvrAsyncCallOnHls::SrsDvrAsyncCallOnHls(int c, SrsRequest* r, string p, string t, string m, string mu, int s, srs_utime_t d) | ||||
| SrsDvrAsyncCallOnHls::SrsDvrAsyncCallOnHls(string c, SrsRequest* r, string p, string t, string m, string mu, int s, srs_utime_t d) | ||||
| { | ||||
|     req = r->copy(); | ||||
|     cid = c; | ||||
|  | @ -137,7 +137,7 @@ string SrsDvrAsyncCallOnHls::to_string() | |||
|     return "on_hls: " + path; | ||||
| } | ||||
| 
 | ||||
| SrsDvrAsyncCallOnHlsNotify::SrsDvrAsyncCallOnHlsNotify(int c, SrsRequest* r, string u) | ||||
| SrsDvrAsyncCallOnHlsNotify::SrsDvrAsyncCallOnHlsNotify(string c, SrsRequest* r, string u) | ||||
| { | ||||
|     cid = c; | ||||
|     req = r->copy(); | ||||
|  | @ -759,9 +759,6 @@ srs_error_t SrsHlsMuxer::_refresh_m3u8(string m3u8_file) | |||
|     SrsHlsSegment* first = dynamic_cast<SrsHlsSegment*>(segments->first()); | ||||
|     ss << "#EXT-X-MEDIA-SEQUENCE:" << first->sequence_no << SRS_CONSTS_LF; | ||||
|      | ||||
|     // iterator shared for td generation and segemnts wrote.
 | ||||
|     std::vector<SrsHlsSegment*>::iterator it; | ||||
|      | ||||
|     // #EXT-X-TARGETDURATION:4294967295\n
 | ||||
|     /**
 | ||||
|      * @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25 | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ public: | |||
| class SrsDvrAsyncCallOnHls : public ISrsAsyncCallTask | ||||
| { | ||||
| private: | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     std::string path; | ||||
|     std::string ts_url; | ||||
|     std::string m3u8; | ||||
|  | @ -90,7 +90,7 @@ private: | |||
|     srs_utime_t duration; | ||||
| public: | ||||
|     // TODO: FIXME: Use TBN 1000.
 | ||||
|     SrsDvrAsyncCallOnHls(int c, SrsRequest* r, std::string p, std::string t, std::string m, std::string mu, int s, srs_utime_t d); | ||||
|     SrsDvrAsyncCallOnHls(std::string c, SrsRequest* r, std::string p, std::string t, std::string m, std::string mu, int s, srs_utime_t d); | ||||
|     virtual ~SrsDvrAsyncCallOnHls(); | ||||
| public: | ||||
|     virtual srs_error_t call(); | ||||
|  | @ -101,11 +101,11 @@ public: | |||
| class SrsDvrAsyncCallOnHlsNotify : public ISrsAsyncCallTask | ||||
| { | ||||
| private: | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     std::string ts_url; | ||||
|     SrsRequest* req; | ||||
| public: | ||||
|     SrsDvrAsyncCallOnHlsNotify(int c, SrsRequest* r, std::string u); | ||||
|     SrsDvrAsyncCallOnHlsNotify(std::string c, SrsRequest* r, std::string u); | ||||
|     virtual ~SrsDvrAsyncCallOnHlsNotify(); | ||||
| public: | ||||
|     virtual srs_error_t call(); | ||||
|  |  | |||
|  | @ -699,10 +699,10 @@ srs_error_t SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessag | |||
|      | ||||
|     // path: {pattern}{vhost_id}
 | ||||
|     // e.g. /api/v1/vhosts/100     pattern= /api/v1/vhosts/, vhost_id=100
 | ||||
|     int vid = r->parse_rest_id(entry->pattern); | ||||
|     std::string vid = r->parse_rest_id(entry->pattern); | ||||
|     SrsStatisticVhost* vhost = NULL; | ||||
|      | ||||
|     if (vid > 0 && (vhost = stat->find_vhost(vid)) == NULL) { | ||||
|     if (vid != "" && (vhost = stat->find_vhost(vid)) == NULL) { | ||||
|         return srs_api_response_code(w, r, ERROR_RTMP_VHOST_NOT_FOUND); | ||||
|     } | ||||
|      | ||||
|  | @ -755,10 +755,10 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa | |||
|      | ||||
|     // path: {pattern}{stream_id}
 | ||||
|     // e.g. /api/v1/streams/100     pattern= /api/v1/streams/, stream_id=100
 | ||||
|     int sid = r->parse_rest_id(entry->pattern); | ||||
|     std::string sid = r->parse_rest_id(entry->pattern); | ||||
|      | ||||
|     SrsStatisticStream* stream = NULL; | ||||
|     if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) { | ||||
|     if (sid != "" && (stream = stat->find_stream(sid)) == NULL) { | ||||
|         return srs_api_response_code(w, r, ERROR_RTMP_STREAM_NOT_FOUND); | ||||
|     } | ||||
|      | ||||
|  | @ -811,10 +811,10 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa | |||
|      | ||||
|     // path: {pattern}{client_id}
 | ||||
|     // e.g. /api/v1/clients/100     pattern= /api/v1/clients/, client_id=100
 | ||||
|     int cid = r->parse_rest_id(entry->pattern); | ||||
|     std::string cid = r->parse_rest_id(entry->pattern); | ||||
|      | ||||
|     SrsStatisticClient* client = NULL; | ||||
|     if (cid >= 0 && (client = stat->find_client(cid)) == NULL) { | ||||
|     if (cid != "" && (client = stat->find_client(cid)) == NULL) { | ||||
|         return srs_api_response_code(w, r, ERROR_RTMP_CLIENT_NOT_FOUND); | ||||
|     } | ||||
|      | ||||
|  | @ -854,7 +854,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa | |||
|         } | ||||
|          | ||||
|         client->conn->expire(); | ||||
|         srs_warn("kickoff client id=%d ok", cid); | ||||
|         srs_warn("kickoff client id=%s ok", cid.c_str()); | ||||
|     } else { | ||||
|         return srs_go_http_error(w, SRS_CONSTS_HTTP_MethodNotAllowed); | ||||
|     } | ||||
|  |  | |||
|  | @ -60,13 +60,15 @@ srs_error_t SrsHttpHooks::on_connect(string url, SrsRequest* req) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     // TODO: FIXME: check client_id must be int?
 | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_connect")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     // obj->set("client_id", SrsJsonAny::integer(client_id));
 | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -79,12 +81,12 @@ srs_error_t SrsHttpHooks::on_connect(string url, SrsRequest* req) | |||
|      | ||||
|     SrsHttpClient http; | ||||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         return srs_error_wrap(err, "http: on_connect failed, client_id=%d, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id, url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|         return srs_error_wrap(err, "http: on_connect failed, client_id=%s, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_connect ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|               client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_connect ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|               client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  | @ -93,13 +95,13 @@ void SrsHttpHooks::on_close(string url, SrsRequest* req, int64_t send_bytes, int | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_close")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -114,13 +116,13 @@ void SrsHttpHooks::on_close(string url, SrsRequest* req, int64_t send_bytes, int | |||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         int ret = srs_error_code(err); | ||||
|         srs_freep(err); | ||||
|         srs_warn("http: ignore on_close failed, 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); | ||||
|         srs_warn("http: ignore on_close failed, client_id=%s, url=%s, request=%s, response=%s, code=%d, ret=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code, ret); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_close ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_close ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return; | ||||
| } | ||||
|  | @ -129,13 +131,13 @@ srs_error_t SrsHttpHooks::on_publish(string url, SrsRequest* req) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_publish")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -149,12 +151,12 @@ srs_error_t SrsHttpHooks::on_publish(string url, SrsRequest* req) | |||
|      | ||||
|     SrsHttpClient http; | ||||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         return srs_error_wrap(err, "http: on_publish failed, client_id=%d, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id, url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|         return srs_error_wrap(err, "http: on_publish failed, client_id=%s, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_publish ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_publish ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  | @ -163,13 +165,13 @@ void SrsHttpHooks::on_unpublish(string url, SrsRequest* req) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_unpublish")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -184,13 +186,13 @@ void SrsHttpHooks::on_unpublish(string url, SrsRequest* req) | |||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         int ret = srs_error_code(err); | ||||
|         srs_freep(err); | ||||
|         srs_warn("http: ignore on_unpublish failed, client_id=%d, url=%s, request=%s, response=%s, status=%d, ret=%d", | ||||
|             client_id, url.c_str(), data.c_str(), res.c_str(), status_code, ret); | ||||
|         srs_warn("http: ignore on_unpublish failed, client_id=%s, url=%s, request=%s, response=%s, status=%d, ret=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code, ret); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_unpublish ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_unpublish ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return; | ||||
| } | ||||
|  | @ -199,13 +201,13 @@ srs_error_t SrsHttpHooks::on_play(string url, SrsRequest* req) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_play")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -219,12 +221,12 @@ srs_error_t SrsHttpHooks::on_play(string url, SrsRequest* req) | |||
|      | ||||
|     SrsHttpClient http; | ||||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         return srs_error_wrap(err, "http: on_play failed, client_id=%d, url=%s, request=%s, response=%s, status=%d", | ||||
|             client_id, url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|         return srs_error_wrap(err, "http: on_play failed, client_id=%s, url=%s, request=%s, response=%s, status=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_play ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_play ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  | @ -233,13 +235,13 @@ void SrsHttpHooks::on_stop(string url, SrsRequest* req) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = _srs_context->get_id(); | ||||
|     std::string client_id = _srs_context->get_id(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_stop")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -254,29 +256,29 @@ void SrsHttpHooks::on_stop(string url, SrsRequest* req) | |||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         int ret = srs_error_code(err); | ||||
|         srs_freep(err); | ||||
|         srs_warn("http: ignore on_stop failed, 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); | ||||
|         srs_warn("http: ignore on_stop failed, client_id=%s, url=%s, request=%s, response=%s, code=%d, ret=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code, ret); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_stop ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_stop ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsHttpHooks::on_dvr(int cid, string url, SrsRequest* req, string file) | ||||
| srs_error_t SrsHttpHooks::on_dvr(std::string cid, string url, SrsRequest* req, string file) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = cid; | ||||
|     std::string client_id = cid; | ||||
|     std::string cwd = _srs_config->cwd(); | ||||
|      | ||||
|     SrsJsonObject* obj = SrsJsonAny::object(); | ||||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_dvr")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -291,21 +293,21 @@ srs_error_t SrsHttpHooks::on_dvr(int cid, string url, SrsRequest* req, string fi | |||
|      | ||||
|     SrsHttpClient http; | ||||
|     if ((err = do_post(&http, url, data, status_code, res)) != srs_success) { | ||||
|         return srs_error_wrap(err, "http post on_dvr uri failed, client_id=%d, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id, url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|         return srs_error_wrap(err, "http post on_dvr uri failed, client_id=%s, url=%s, request=%s, response=%s, code=%d", | ||||
|             client_id.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code); | ||||
|     } | ||||
|      | ||||
|     srs_trace("http hook on_dvr success. client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http hook on_dvr success. client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsHttpHooks::on_hls(int cid, string url, SrsRequest* req, string file, string ts_url, string m3u8, string m3u8_url, int sn, srs_utime_t duration) | ||||
| srs_error_t SrsHttpHooks::on_hls(std::string cid, string url, SrsRequest* req, string file, string ts_url, string m3u8, string m3u8_url, int sn, srs_utime_t duration) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = cid; | ||||
|     std::string client_id = cid; | ||||
|     std::string cwd = _srs_config->cwd(); | ||||
|      | ||||
|     // the ts_url is under the same dir of m3u8_url.
 | ||||
|  | @ -318,7 +320,7 @@ srs_error_t SrsHttpHooks::on_hls(int cid, string url, SrsRequest* req, string fi | |||
|     SrsAutoFree(SrsJsonObject, obj); | ||||
|      | ||||
|     obj->set("action", SrsJsonAny::str("on_hls")); | ||||
|     obj->set("client_id", SrsJsonAny::integer(client_id)); | ||||
|     obj->set("client_id", SrsJsonAny::str(client_id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(req->vhost.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(req->app.c_str())); | ||||
|  | @ -341,17 +343,17 @@ srs_error_t SrsHttpHooks::on_hls(int cid, string url, SrsRequest* req, string fi | |||
|         return srs_error_wrap(err, "http: post %s with %s, status=%d, res=%s", url.c_str(), data.c_str(), status_code, res.c_str()); | ||||
|     } | ||||
|      | ||||
|     srs_trace("http: on_hls ok, client_id=%d, url=%s, request=%s, response=%s", | ||||
|         client_id, url.c_str(), data.c_str(), res.c_str()); | ||||
|     srs_trace("http: on_hls ok, client_id=%s, url=%s, request=%s, response=%s", | ||||
|         client_id.c_str(), url.c_str(), data.c_str(), res.c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsHttpHooks::on_hls_notify(int cid, std::string url, SrsRequest* req, std::string ts_url, int nb_notify) | ||||
| srs_error_t SrsHttpHooks::on_hls_notify(std::string cid, std::string url, SrsRequest* req, std::string ts_url, int nb_notify) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     int client_id = cid; | ||||
|     std::string client_id = cid; | ||||
|     std::string cwd = _srs_config->cwd(); | ||||
|      | ||||
|     if (srs_string_is_http(ts_url)) { | ||||
|  | @ -406,8 +408,8 @@ srs_error_t SrsHttpHooks::on_hls_notify(int cid, std::string url, SrsRequest* re | |||
|     } | ||||
|      | ||||
|     int spenttime = (int)(srsu2ms(srs_update_system_time()) - starttime); | ||||
|     srs_trace("http hook on_hls_notify success. client_id=%d, url=%s, code=%d, spent=%dms, read=%dB, err=%s", | ||||
|         client_id, url.c_str(), msg->status_code(), spenttime, nb_read, srs_error_desc(err).c_str()); | ||||
|     srs_trace("http hook on_hls_notify success. client_id=%s, url=%s, code=%d, spent=%dms, read=%dB, err=%s", | ||||
|         client_id.c_str(), url.c_str(), msg->status_code(), spenttime, nb_read, srs_error_desc(err).c_str()); | ||||
|      | ||||
|     // ignore any error for on_hls_notify.
 | ||||
|     srs_error_reset(err); | ||||
|  |  | |||
|  | @ -74,7 +74,7 @@ public: | |||
|     //         ignore if empty.
 | ||||
|     // @param file the file path, can be relative or absolute path.
 | ||||
|     // @param cid the source connection cid, for the on_dvr is async call.
 | ||||
|     static srs_error_t on_dvr(int cid, std::string url, SrsRequest* req, std::string file); | ||||
|     static srs_error_t on_dvr(std::string cid, std::string url, SrsRequest* req, std::string file); | ||||
|     // When hls reap segment, callback.
 | ||||
|     // @param url the api server url, to process the event.
 | ||||
|     //         ignore if empty.
 | ||||
|  | @ -85,7 +85,7 @@ public: | |||
|     // @param sn the seq_no, the sequence number of ts in hls/m3u8.
 | ||||
|     // @param duration the segment duration in srs_utime_t.
 | ||||
|     // @param cid the source connection cid, for the on_dvr is async call.
 | ||||
|     static srs_error_t on_hls(int cid, std::string url, SrsRequest* req, std::string file, std::string ts_url, | ||||
|     static srs_error_t on_hls(std::string cid, std::string url, SrsRequest* req, std::string file, std::string ts_url, | ||||
|         std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration); | ||||
|     // When hls reap segment, callback.
 | ||||
|     // @param url the api server url, to process the event.
 | ||||
|  | @ -93,7 +93,7 @@ public: | |||
|     // @param ts_url the ts uri, used to replace the variable [ts_url] in url.
 | ||||
|     // @param nb_notify the max bytes to read from notify server.
 | ||||
|     // @param cid the source connection cid, for the on_dvr is async call.
 | ||||
|     static srs_error_t on_hls_notify(int cid, std::string url, SrsRequest* req, std::string ts_url, int nb_notify); | ||||
|     static srs_error_t on_hls_notify(std::string cid, std::string url, SrsRequest* req, std::string ts_url, int nb_notify); | ||||
|     // Discover co-workers for origin cluster.
 | ||||
|     static srs_error_t discover_co_workers(std::string url, std::string& host, int& port); | ||||
| private: | ||||
|  |  | |||
|  | @ -1141,8 +1141,8 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandle | |||
|      | ||||
|     // trigger edge to fetch from origin.
 | ||||
|     bool vhost_is_edge = _srs_config->get_vhost_is_edge(r->vhost); | ||||
|     srs_trace("flv: source url=%s, is_edge=%d, source_id=[%d][%d]", | ||||
|         r->get_stream_url().c_str(), vhost_is_edge, ::getpid(), s->source_id()); | ||||
|     srs_trace("flv: source url=%s, is_edge=%d, source_id=[%d][%s]", | ||||
|         r->get_stream_url().c_str(), vhost_is_edge, ::getpid(), s->source_id().c_str()); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  |  | |||
|  | @ -171,7 +171,7 @@ srs_error_t SrsUdpListener::listen() | |||
|     handler->set_stfd(lfd); | ||||
|      | ||||
|     srs_freep(trd); | ||||
|     trd = new SrsSTCoroutine("udp", this); | ||||
|     trd = new SrsSTCoroutine("udp", this, _srs_context->get_id()); | ||||
|     if ((err = trd->start()) != srs_success) { | ||||
|         return srs_error_wrap(err, "start thread"); | ||||
|     } | ||||
|  |  | |||
|  | @ -94,7 +94,7 @@ void SrsFastLog::reopen() | |||
|     open_log_file(); | ||||
| } | ||||
| 
 | ||||
| void SrsFastLog::verbose(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsFastLog::verbose(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelVerbose) { | ||||
|         return; | ||||
|  | @ -114,7 +114,7 @@ void SrsFastLog::verbose(const char* tag, int context_id, const char* fmt, ...) | |||
|     write_log(fd, log_data, size, SrsLogLevelVerbose); | ||||
| } | ||||
| 
 | ||||
| void SrsFastLog::info(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsFastLog::info(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelInfo) { | ||||
|         return; | ||||
|  | @ -134,7 +134,7 @@ void SrsFastLog::info(const char* tag, int context_id, const char* fmt, ...) | |||
|     write_log(fd, log_data, size, SrsLogLevelInfo); | ||||
| } | ||||
| 
 | ||||
| void SrsFastLog::trace(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsFastLog::trace(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelTrace) { | ||||
|         return; | ||||
|  | @ -154,7 +154,7 @@ void SrsFastLog::trace(const char* tag, int context_id, const char* fmt, ...) | |||
|     write_log(fd, log_data, size, SrsLogLevelTrace); | ||||
| } | ||||
| 
 | ||||
| void SrsFastLog::warn(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsFastLog::warn(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelWarn) { | ||||
|         return; | ||||
|  | @ -174,7 +174,7 @@ void SrsFastLog::warn(const char* tag, int context_id, const char* fmt, ...) | |||
|     write_log(fd, log_data, size, SrsLogLevelWarn); | ||||
| } | ||||
| 
 | ||||
| void SrsFastLog::error(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsFastLog::error(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelError) { | ||||
|         return; | ||||
|  |  | |||
|  | @ -55,11 +55,11 @@ public: | |||
| public: | ||||
|     virtual srs_error_t initialize(); | ||||
|     virtual void reopen(); | ||||
|     virtual void verbose(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void info(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void trace(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void warn(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void error(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void verbose(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void info(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void trace(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void warn(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void error(const char* tag, const char* context_id, const char* fmt, ...); | ||||
| // Interface ISrsReloadHandler.
 | ||||
| public: | ||||
|     virtual srs_error_t on_reload_utc_time(); | ||||
|  |  | |||
|  | @ -180,7 +180,7 @@ srs_error_t SrsProcess::start() | |||
|     srs_info("fork process: %s", cli.c_str()); | ||||
|      | ||||
|     // for log
 | ||||
|     int cid = _srs_context->get_id(); | ||||
|     std::string cid = _srs_context->get_id(); | ||||
|     int ppid = getpid(); | ||||
|      | ||||
|     // TODO: fork or vfork?
 | ||||
|  | @ -221,8 +221,8 @@ srs_error_t SrsProcess::start() | |||
|         // log basic info to stderr.
 | ||||
|         if (true) { | ||||
|             fprintf(stdout, "\n"); | ||||
|             fprintf(stdout, "process ppid=%d, cid=%d, pid=%d, in=%d, out=%d, err=%d\n", | ||||
|                 ppid, cid, getpid(), STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO); | ||||
|             fprintf(stdout, "process ppid=%d, cid=%s, pid=%d, in=%d, out=%d, err=%d\n", | ||||
|                 ppid, cid.c_str(), getpid(), STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO); | ||||
|             fprintf(stdout, "process binary=%s, cli: %s\n", bin.c_str(), cli.c_str()); | ||||
|             fprintf(stdout, "process actual cli: %s\n", actual_cli.c_str()); | ||||
|         } | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ ISrsMessagePumper::~ISrsMessagePumper() | |||
| { | ||||
| } | ||||
| 
 | ||||
| SrsRecvThread::SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, srs_utime_t tm, int parent_cid) | ||||
| SrsRecvThread::SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, srs_utime_t tm, std::string parent_cid) | ||||
| { | ||||
|     rtmp = r; | ||||
|     pumper = p; | ||||
|  | @ -71,7 +71,7 @@ SrsRecvThread::~SrsRecvThread() | |||
|     srs_freep(trd); | ||||
| } | ||||
| 
 | ||||
| int SrsRecvThread::cid() | ||||
| std::string SrsRecvThread::cid() | ||||
| { | ||||
|     return trd->cid(); | ||||
| } | ||||
|  | @ -161,7 +161,7 @@ srs_error_t SrsRecvThread::do_cycle() | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| SrsQueueRecvThread::SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, srs_utime_t tm, int parent_cid) | ||||
| SrsQueueRecvThread::SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, srs_utime_t tm, std::string parent_cid) | ||||
| 	: trd(this, rtmp_sdk, tm, parent_cid) | ||||
| { | ||||
|     _consumer = consumer; | ||||
|  | @ -278,7 +278,7 @@ void SrsQueueRecvThread::on_stop() | |||
| } | ||||
| 
 | ||||
| SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest* _req, | ||||
| 	int mr_sock_fd, srs_utime_t tm, SrsRtmpConn* conn, SrsSource* source, int parent_cid) | ||||
| 	int mr_sock_fd, srs_utime_t tm, SrsRtmpConn* conn, SrsSource* source, std::string parent_cid) | ||||
|     : trd(this, rtmp_sdk, tm, parent_cid) | ||||
| { | ||||
|     rtmp = rtmp_sdk; | ||||
|  | @ -290,7 +290,7 @@ SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest* | |||
|     _nb_msgs = 0; | ||||
|     video_frames = 0; | ||||
|     error = srs_cond_new(); | ||||
|     ncid = cid = 0; | ||||
|     ncid = cid = ""; | ||||
|      | ||||
|     req = _req; | ||||
|     mr_fd = mr_sock_fd; | ||||
|  | @ -341,12 +341,12 @@ srs_error_t SrsPublishRecvThread::error_code() | |||
|     return srs_error_copy(recv_error); | ||||
| } | ||||
| 
 | ||||
| void SrsPublishRecvThread::set_cid(int v) | ||||
| void SrsPublishRecvThread::set_cid(std::string v) | ||||
| { | ||||
|     ncid = v; | ||||
| } | ||||
| 
 | ||||
| int SrsPublishRecvThread::get_cid() | ||||
| std::string SrsPublishRecvThread::get_cid() | ||||
| { | ||||
|     return ncid; | ||||
| } | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include <srs_core.hpp> | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <srs_app_thread.hpp> | ||||
| #include <srs_protocol_stream.hpp> | ||||
|  | @ -80,16 +81,16 @@ protected: | |||
|     SrsCoroutine* trd; | ||||
|     ISrsMessagePumper* pumper; | ||||
|     SrsRtmpServer* rtmp; | ||||
|     int _parent_cid; | ||||
|     std::string _parent_cid; | ||||
|     // The recv timeout in srs_utime_t.
 | ||||
|     srs_utime_t timeout; | ||||
| public: | ||||
|     // Constructor.
 | ||||
|     // @param tm The receive timeout in srs_utime_t.
 | ||||
|     SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, srs_utime_t tm, int parent_cid); | ||||
|     SrsRecvThread(ISrsMessagePumper* p, SrsRtmpServer* r, srs_utime_t tm, std::string parent_cid); | ||||
|     virtual ~SrsRecvThread(); | ||||
| public: | ||||
|     virtual int cid(); | ||||
|     virtual std::string cid(); | ||||
| public: | ||||
|     virtual srs_error_t start(); | ||||
|     virtual void stop(); | ||||
|  | @ -116,7 +117,7 @@ private: | |||
|     SrsConsumer* _consumer; | ||||
| public: | ||||
| 	// TODO: FIXME: Refine timeout in time unit.
 | ||||
|     SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, srs_utime_t tm, int parent_cid); | ||||
|     SrsQueueRecvThread(SrsConsumer* consumer, SrsRtmpServer* rtmp_sdk, srs_utime_t tm,  std::string parent_cid); | ||||
|     virtual ~SrsQueueRecvThread(); | ||||
| public: | ||||
|     virtual srs_error_t start(); | ||||
|  | @ -167,11 +168,11 @@ private: | |||
|     // @see https://github.com/ossrs/srs/issues/244
 | ||||
|     srs_cond_t error; | ||||
|     // The merged context id.
 | ||||
|     int cid; | ||||
|     int ncid; | ||||
|     std::string cid; | ||||
|     std::string ncid; | ||||
| public: | ||||
|     SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest* _req, | ||||
|         int mr_sock_fd, srs_utime_t tm, SrsRtmpConn* conn, SrsSource* source, int parent_cid); | ||||
|         int mr_sock_fd, srs_utime_t tm, SrsRtmpConn* conn, SrsSource* source, std::string parent_cid); | ||||
|     virtual ~SrsPublishRecvThread(); | ||||
| public: | ||||
|     // Wait for error for some timeout.
 | ||||
|  | @ -179,8 +180,8 @@ public: | |||
|     virtual int64_t nb_msgs(); | ||||
|     virtual uint64_t nb_video_frames(); | ||||
|     virtual srs_error_t error_code(); | ||||
|     virtual void set_cid(int v); | ||||
|     virtual int get_cid(); | ||||
|     virtual void set_cid(std::string v); | ||||
|     virtual std::string get_cid(); | ||||
| public: | ||||
|     virtual srs_error_t start(); | ||||
|     virtual void stop(); | ||||
|  |  | |||
|  | @ -136,10 +136,16 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe | |||
|     string eip = r->query_get("eip"); | ||||
|     // For client to specifies whether encrypt by SRTP.
 | ||||
|     string encrypt = r->query_get("encrypt"); | ||||
|     // If keep_sequence is off, for client to specifies the startup sequence.
 | ||||
|     string sequence_startup = r->query_get("sequence_startup"); | ||||
|     // If keep_sequence is on, for client to specifies the delta value for sequence.
 | ||||
|     string sequence_delta = r->query_get("sequence_delta"); | ||||
|     // Whether keep sequence, overwrite the config for debugging each session.
 | ||||
|     string sequence_keep = r->query_get("sequence_keep"); | ||||
| 
 | ||||
|     srs_trace("RTC play %s, api=%s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, encrypt=%s", | ||||
|         streamurl.c_str(), api.c_str(), clientip.c_str(), app.c_str(), stream_name.c_str(), remote_sdp_str.length(), | ||||
|         eip.c_str(), encrypt.c_str()); | ||||
|     srs_trace("RTC play %s, api=%s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, encrypt=%s, sequence(startup=%s,delta=%s,keep=%s)", | ||||
|         streamurl.c_str(), api.c_str(), clientip.c_str(), app.c_str(), stream_name.c_str(), remote_sdp_str.length(), eip.c_str(), encrypt.c_str(), | ||||
|         sequence_startup.c_str(), sequence_delta.c_str(), sequence_keep.c_str()); | ||||
| 
 | ||||
|     // TODO: FIXME: It seems remote_sdp doesn't represents the full SDP information.
 | ||||
|     SrsSdp remote_sdp; | ||||
|  | @ -189,6 +195,11 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe | |||
|         session->set_encrypt(encrypt != "false"); | ||||
|     } | ||||
| 
 | ||||
|     // Set the optional parameters from client.
 | ||||
|     session->sequence_startup = sequence_startup; | ||||
|     session->sequence_delta = sequence_delta; | ||||
|     session->sequence_keep = sequence_keep; | ||||
| 
 | ||||
|     ostringstream os; | ||||
|     if ((err = local_sdp.encode(os)) != srs_success) { | ||||
|         return srs_error_wrap(err, "encode sdp"); | ||||
|  |  | |||
|  | @ -487,18 +487,16 @@ SrsRtcOutgoingInfo::~SrsRtcOutgoingInfo() | |||
| { | ||||
| } | ||||
| 
 | ||||
| SrsRtcPlayer::SrsRtcPlayer(SrsRtcSession* s, int parent_cid) | ||||
| SrsRtcPlayer::SrsRtcPlayer(SrsRtcSession* s, string parent_cid) | ||||
| { | ||||
|     _parent_cid = parent_cid; | ||||
|     trd = new SrsDummyCoroutine(); | ||||
| 
 | ||||
|     session_ = s; | ||||
| 
 | ||||
|     audio_timestamp = 0; | ||||
|     audio_sequence = 0; | ||||
| 
 | ||||
|     video_sequence = 0; | ||||
| 
 | ||||
|     sequence_delta = 0; | ||||
|     mw_msgs = 0; | ||||
|     realtime = true; | ||||
| 
 | ||||
|  | @ -508,6 +506,7 @@ SrsRtcPlayer::SrsRtcPlayer(SrsRtcSession* s, int parent_cid) | |||
| 
 | ||||
|     nn_simulate_nack_drop = 0; | ||||
|     nack_enabled_ = false; | ||||
|     keep_sequence_ = false; | ||||
| 
 | ||||
|     _srs_config->subscribe(this); | ||||
| } | ||||
|  | @ -533,8 +532,18 @@ srs_error_t SrsRtcPlayer::initialize(const uint32_t& vssrc, const uint32_t& assr | |||
| 
 | ||||
|     // TODO: FIXME: Support reload.
 | ||||
|     nack_enabled_ = _srs_config->get_rtc_nack_enabled(session_->req->vhost); | ||||
|     srs_trace("RTC publisher video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), nack=%d", | ||||
|         video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, nack_enabled_); | ||||
|     keep_sequence_ = _srs_config->get_rtc_keep_sequence(session_->req->vhost); | ||||
|     if (!session_->sequence_startup.empty()) { | ||||
|         audio_sequence = video_sequence = uint16_t(::atoi(session_->sequence_startup.c_str())); | ||||
|     } | ||||
|     if (!session_->sequence_delta.empty()) { | ||||
|         sequence_delta = uint16_t(::atoi(session_->sequence_delta.c_str())); | ||||
|     } | ||||
|     if (!session_->sequence_keep.empty()) { | ||||
|         keep_sequence_ = (session_->sequence_keep == "true"); | ||||
|     } | ||||
|     srs_trace("RTC player video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), nack=%d, keep-seq=%d, sequence(audio=%u,video=%u,delta=%u)", | ||||
|         video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, nack_enabled_, keep_sequence_, audio_sequence, video_sequence, sequence_delta); | ||||
| 
 | ||||
|     if (_srs_rtc_hijacker) { | ||||
|         if ((err = _srs_rtc_hijacker->on_start_play(session_, this, session_->req)) != srs_success) { | ||||
|  | @ -566,7 +575,7 @@ srs_error_t SrsRtcPlayer::on_reload_vhost_realtime(string vhost) | |||
|     return on_reload_vhost_play(vhost); | ||||
| } | ||||
| 
 | ||||
| int SrsRtcPlayer::cid() | ||||
| std::string SrsRtcPlayer::cid() | ||||
| { | ||||
|     return trd->cid(); | ||||
| } | ||||
|  | @ -620,8 +629,8 @@ srs_error_t SrsRtcPlayer::cycle() | |||
|     realtime = _srs_config->get_realtime_enabled(req->vhost, true); | ||||
|     mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime, true); | ||||
| 
 | ||||
|     srs_trace("RTC source url=%s, source_id=[%d][%d], encrypt=%d, realtime=%d, mw_msgs=%d", req->get_stream_url().c_str(), | ||||
|         ::getpid(), source->source_id(), session_->encrypt, realtime, mw_msgs); | ||||
|     srs_trace("RTC source url=%s, source_id=[%d][%s], encrypt=%d, realtime=%d, mw_msgs=%d", req->get_stream_url().c_str(), | ||||
|         ::getpid(), source->source_id().c_str(), session_->encrypt, realtime, mw_msgs); | ||||
| 
 | ||||
|     SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); | ||||
|     SrsAutoFree(SrsPithyPrint, pprint); | ||||
|  | @ -707,29 +716,36 @@ srs_error_t SrsRtcPlayer::send_packets(SrsRtcSource* source, const vector<SrsRtp | |||
|         // Update stats.
 | ||||
|         info.nn_bytes += pkt->nb_bytes(); | ||||
| 
 | ||||
|         // For audio, we transcoded AAC to opus in extra payloads.
 | ||||
|         uint16_t oseq = pkt->header.get_sequence(); | ||||
|         if (pkt->is_audio()) { | ||||
|             info.nn_audios++; | ||||
| 
 | ||||
|             pkt->header.set_timestamp(audio_timestamp); | ||||
|             pkt->header.set_sequence(audio_sequence++); | ||||
|             if (!keep_sequence_) { | ||||
|                 // TODO: FIXME: Should keep the order by original sequence.
 | ||||
|                 pkt->header.set_sequence(sequence_delta + audio_sequence++); | ||||
|             } else { | ||||
|                 pkt->header.set_sequence(sequence_delta + oseq); | ||||
|             } | ||||
|             pkt->header.set_ssrc(audio_ssrc); | ||||
|             pkt->header.set_payload_type(audio_payload_type); | ||||
| 
 | ||||
|             // TODO: FIXME: Padding audio to the max payload in RTP packets.
 | ||||
|         } else { | ||||
|             info.nn_videos++; | ||||
| 
 | ||||
|             // TODO: FIXME: Why 960? Need Refactoring?
 | ||||
|             audio_timestamp += 960; | ||||
|             continue; | ||||
|             if (!keep_sequence_) { | ||||
|                 // TODO: FIXME: Should keep the order by original sequence.
 | ||||
|                 pkt->header.set_sequence(sequence_delta + video_sequence++); | ||||
|             } else { | ||||
|                 pkt->header.set_sequence(sequence_delta + oseq); | ||||
|             } | ||||
|             pkt->header.set_ssrc(video_ssrc); | ||||
|             pkt->header.set_payload_type(video_payload_type); | ||||
|         } | ||||
| 
 | ||||
|         // For video, we should process all NALUs in samples.
 | ||||
|         info.nn_videos++; | ||||
| 
 | ||||
|         // For video, we should set the RTP packet informations about this consumer.
 | ||||
|         pkt->header.set_sequence(video_sequence++); | ||||
|         pkt->header.set_ssrc(video_ssrc); | ||||
|         pkt->header.set_payload_type(video_payload_type); | ||||
|         // Detail log, should disable it in release version.
 | ||||
|         srs_info("RTC: Update PT=%u, SSRC=%#x, OSEQ=%u, SEQ=%u, Time=%u, %u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), | ||||
|             oseq, pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes()); | ||||
|     } | ||||
| 
 | ||||
|     // By default, we send packets by sendmmsg.
 | ||||
|  | @ -815,6 +831,10 @@ srs_error_t SrsRtcPlayer::do_send_packets(const std::vector<SrsRtpPacket2*>& pkt | |||
| 
 | ||||
|         // TODO: FIXME: Handle error.
 | ||||
|         session_->sendonly_skt->sendto(iov->iov_base, iov->iov_len, 0); | ||||
| 
 | ||||
|         // Detail log, should disable it in release version.
 | ||||
|         srs_info("RTC: SEND PT=%u, SSRC=%#x, SEQ=%u, Time=%u, %u/%u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), | ||||
|             pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes(), iov->iov_len); | ||||
|     } | ||||
| 
 | ||||
|     return err; | ||||
|  | @ -978,6 +998,12 @@ srs_error_t SrsRtcPlayer::on_rtcp_feedback(char* buf, int nb_buf) | |||
|     vector<SrsRtpPacket2*> resend_pkts; | ||||
|     nack_fetch(resend_pkts, ssrc_of_media_source, pid); | ||||
| 
 | ||||
|     // If NACK disabled, print a log.
 | ||||
|     if (!nack_enabled_) { | ||||
|         srs_trace("RTC NACK seq=%u, ignored", pid); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     uint16_t mask = 0x01; | ||||
|     for (int i = 1; i < 16 && blp; ++i, mask <<= 1) { | ||||
|         if (!(blp & mask)) { | ||||
|  | @ -1031,7 +1057,7 @@ srs_error_t SrsRtcPlayer::on_rtcp_ps_feedback(char* buf, int nb_buf) | |||
| 
 | ||||
|     switch (fmt) { | ||||
|         case kPLI: { | ||||
|             SrsRtcPublisher* publisher = session_->source_->rtc_publisher(); | ||||
|             ISrsRtcPublisher* publisher = session_->source_->rtc_publisher(); | ||||
|             if (publisher) { | ||||
|                 publisher->request_keyframe(); | ||||
|                 srs_trace("RTC request PLI"); | ||||
|  | @ -1088,10 +1114,9 @@ SrsRtcPublisher::SrsRtcPublisher(SrsRtcSession* session) | |||
| 
 | ||||
| SrsRtcPublisher::~SrsRtcPublisher() | ||||
| { | ||||
|     source->set_rtc_publisher(NULL); | ||||
| 
 | ||||
|     // TODO: FIXME: Do unpublish when session timeout.
 | ||||
|     if (source) { | ||||
|         source->set_rtc_publisher(NULL); | ||||
|         source->on_unpublish(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1420,11 +1445,12 @@ srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data) | |||
| 
 | ||||
|     if (true) { | ||||
|         pkt->set_decode_handler(this); | ||||
|         pkt->set_rtp_header_extensions(&extension_map_); | ||||
|         pkt->shared_msg = new SrsSharedPtrMessage(); | ||||
|         pkt->shared_msg->wrap(buf, nb_buf); | ||||
| 
 | ||||
|         SrsBuffer b(buf, nb_buf); | ||||
|         if ((err = pkt->decode(&b, &extension_map_)) != srs_success) { | ||||
|         if ((err = pkt->decode(&b)) != srs_success) { | ||||
|             return srs_error_wrap(err, "decode rtp packet"); | ||||
|         } | ||||
| 
 | ||||
|  | @ -1434,6 +1460,9 @@ srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data) | |||
|                 if((err = on_twcc(twcc_sn))) { | ||||
|                     return srs_error_wrap(err, "fail to process twcc packet"); | ||||
|                 } | ||||
|             } else { | ||||
|                 // TODO: FIXME: process no twcc seq number for audio ssrc
 | ||||
|                 srs_error_reset(err); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -1910,9 +1939,9 @@ block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| 
 | ||||
| void SrsRtcPublisher::request_keyframe() | ||||
| { | ||||
|     int scid = _srs_context->get_id(); | ||||
|     int pcid = session_->context_id(); | ||||
|     srs_trace("RTC play=[%d][%d] request keyframe from publish=[%d][%d]", ::getpid(), scid, ::getpid(), pcid); | ||||
|     std::string scid = _srs_context->get_id(); | ||||
|     std::string pcid = session_->context_id(); | ||||
|     srs_trace("RTC play=[%d][%s] request keyframe from publish=[%d][%s]", ::getpid(), scid.c_str(), ::getpid(), pcid.c_str()); | ||||
| 
 | ||||
|     request_keyframe_ = true; | ||||
| } | ||||
|  | @ -1946,7 +1975,7 @@ void SrsRtcPublisher::simulate_drop_packet(SrsRtpHeader* h, int nn_bytes) | |||
| SrsRtcSession::SrsRtcSession(SrsRtcServer* s) | ||||
| { | ||||
|     req = NULL; | ||||
|     cid = 0; | ||||
|     cid = ""; | ||||
|     is_publisher_ = false; | ||||
|     encrypt = true; | ||||
| 
 | ||||
|  | @ -2039,12 +2068,12 @@ void SrsRtcSession::switch_to_context() | |||
|     _srs_context->set_id(cid); | ||||
| } | ||||
| 
 | ||||
| int SrsRtcSession::context_id() | ||||
| std::string SrsRtcSession::context_id() | ||||
| { | ||||
|     return cid; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtcSession::initialize(SrsRtcSource* source, SrsRequest* r, bool is_publisher, string username, int context_id) | ||||
| srs_error_t SrsRtcSession::initialize(SrsRtcSource* source, SrsRequest* r, bool is_publisher, string username, std::string context_id) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ | |||
| #include <srs_kernel_rtc_rtp.hpp> | ||||
| #include <srs_kernel_rtc_rtcp.hpp> | ||||
| #include <srs_app_rtc_queue.hpp> | ||||
| #include <srs_app_rtc_source.hpp> | ||||
| 
 | ||||
| #include <string> | ||||
| #include <map> | ||||
|  | @ -188,13 +189,12 @@ public: | |||
| class SrsRtcPlayer : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler | ||||
| { | ||||
| protected: | ||||
|     int _parent_cid; | ||||
|     std::string _parent_cid; | ||||
|     SrsCoroutine* trd; | ||||
|     SrsRtcSession* session_; | ||||
| private: | ||||
|     // TODO: FIXME: How to handle timestamp overflow?
 | ||||
|     // Information for audio.
 | ||||
|     uint32_t audio_timestamp; | ||||
|     uint16_t audio_sequence; | ||||
|     uint32_t audio_ssrc; | ||||
|     uint16_t audio_payload_type; | ||||
|  | @ -206,6 +206,7 @@ private: | |||
|     SrsRtpRingBuffer* audio_queue_; | ||||
|     SrsRtpRingBuffer* video_queue_; | ||||
|     // Simulators.
 | ||||
|     uint16_t sequence_delta; | ||||
|     int nn_simulate_nack_drop; | ||||
| private: | ||||
|     // For merged-write messages.
 | ||||
|  | @ -213,8 +214,10 @@ private: | |||
|     bool realtime; | ||||
|     // Whether enabled nack.
 | ||||
|     bool nack_enabled_; | ||||
|     // Whether keep original sequence number.
 | ||||
|     bool keep_sequence_; | ||||
| public: | ||||
|     SrsRtcPlayer(SrsRtcSession* s, int parent_cid); | ||||
|     SrsRtcPlayer(SrsRtcSession* s, std::string parent_cid); | ||||
|     virtual ~SrsRtcPlayer(); | ||||
| public: | ||||
|     srs_error_t initialize(const uint32_t& vssrc, const uint32_t& assrc, const uint16_t& v_pt, const uint16_t& a_pt); | ||||
|  | @ -223,7 +226,7 @@ public: | |||
|     virtual srs_error_t on_reload_vhost_play(std::string vhost); | ||||
|     virtual srs_error_t on_reload_vhost_realtime(std::string vhost); | ||||
| public: | ||||
|     virtual int cid(); | ||||
|     virtual std::string cid(); | ||||
| public: | ||||
|     virtual srs_error_t start(); | ||||
|     virtual void stop(); | ||||
|  | @ -248,7 +251,7 @@ private: | |||
|     srs_error_t on_rtcp_rr(char* data, int nb_data); | ||||
| }; | ||||
| 
 | ||||
| class SrsRtcPublisher : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler | ||||
| class SrsRtcPublisher : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler, virtual public ISrsRtcPublisher | ||||
| { | ||||
| private: | ||||
|     SrsHourGlass* report_timer; | ||||
|  | @ -341,7 +344,7 @@ private: | |||
|     srs_utime_t last_stun_time; | ||||
| private: | ||||
|     // For each RTC session, we use a specified cid for debugging logs.
 | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     // For each RTC session, whether requires encrypt.
 | ||||
|     //      Read config value, rtc_server.encrypt, default to on.
 | ||||
|     //      Sepcifies by HTTP API, query encrypt, optional.
 | ||||
|  | @ -351,6 +354,11 @@ private: | |||
|     SrsRtcSource* source_; | ||||
|     SrsSdp remote_sdp; | ||||
|     SrsSdp local_sdp; | ||||
| public: | ||||
|     // User debugging parameters, overwrite config.
 | ||||
|     std::string sequence_startup; | ||||
|     std::string sequence_delta; | ||||
|     std::string sequence_keep; | ||||
| private: | ||||
|     bool blackhole; | ||||
|     sockaddr_in* blackhole_addr; | ||||
|  | @ -371,9 +379,9 @@ public: | |||
|     std::string username(); | ||||
|     void set_encrypt(bool v); | ||||
|     void switch_to_context(); | ||||
|     int context_id(); | ||||
|     std::string context_id(); | ||||
| public: | ||||
|     srs_error_t initialize(SrsRtcSource* source, SrsRequest* r, bool is_publisher, std::string username, int context_id); | ||||
|     srs_error_t initialize(SrsRtcSource* source, SrsRequest* r, bool is_publisher, std::string username, std::string context_id); | ||||
|     // The peer address may change, we can identify that by STUN messages.
 | ||||
|     srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r); | ||||
|     srs_error_t on_dtls(char* data, int nb_data); | ||||
|  |  | |||
|  | @ -320,7 +320,7 @@ srs_error_t SrsRtcServer::create_session( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     int cid = _srs_context->get_id(); | ||||
|     std::string cid = _srs_context->get_id(); | ||||
|     SrsRtcSession* session = new SrsRtcSession(this); | ||||
|     if ((err = session->initialize(source, req, publish, username, cid)) != srs_success) { | ||||
|         srs_freep(session); | ||||
|  | @ -396,7 +396,7 @@ srs_error_t SrsRtcServer::setup_session2(SrsRtcSession* session, SrsRequest* req | |||
|     // TODO: FIXME: Collision detect.
 | ||||
|     string username = session->get_local_sdp()->get_ice_ufrag() + ":" + remote_sdp.get_ice_ufrag(); | ||||
| 
 | ||||
|     int cid = _srs_context->get_id(); | ||||
|     std::string cid = _srs_context->get_id(); | ||||
|     if ((err = session->initialize(source, req, false, username, cid)) != srs_success) { | ||||
|         return srs_error_wrap(err, "init"); | ||||
|     } | ||||
|  |  | |||
|  | @ -137,7 +137,7 @@ srs_error_t SrsRtcConsumer::dump_packets(std::vector<SrsRtpPacket2*>& pkts) | |||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|     if (should_update_source_id) { | ||||
|         srs_trace("update source_id=%d[%d]", source->source_id(), source->source_id()); | ||||
|         srs_trace("update source_id=%d[%d]", source->source_id().c_str(), source->source_id().c_str()); | ||||
|         should_update_source_id = false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -232,9 +232,17 @@ SrsRtcSource* SrsRtcSourceManager::fetch(SrsRequest* r) | |||
| 
 | ||||
| SrsRtcSourceManager* _srs_rtc_sources = new SrsRtcSourceManager(); | ||||
| 
 | ||||
| ISrsRtcPublisher::ISrsRtcPublisher() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| ISrsRtcPublisher::~ISrsRtcPublisher() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| SrsRtcSource::SrsRtcSource() | ||||
| { | ||||
|     _source_id = _pre_source_id = -1; | ||||
|     _source_id = _pre_source_id = ""; | ||||
|     _can_publish = true; | ||||
|     rtc_publisher_ = NULL; | ||||
| 
 | ||||
|  | @ -270,7 +278,7 @@ void SrsRtcSource::update_auth(SrsRequest* r) | |||
|     req->update_auth(r); | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtcSource::on_source_id_changed(int id) | ||||
| srs_error_t SrsRtcSource::on_source_id_changed(std::string id) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|  | @ -278,7 +286,7 @@ srs_error_t SrsRtcSource::on_source_id_changed(int id) | |||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     if (_pre_source_id == -1) { | ||||
|     if (_pre_source_id == "") { | ||||
|         _pre_source_id = id; | ||||
|     } else if (_pre_source_id != _source_id) { | ||||
|         _pre_source_id = _source_id; | ||||
|  | @ -296,12 +304,12 @@ srs_error_t SrsRtcSource::on_source_id_changed(int id) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| int SrsRtcSource::source_id() | ||||
| std::string SrsRtcSource::source_id() | ||||
| { | ||||
|     return _source_id; | ||||
| } | ||||
| 
 | ||||
| int SrsRtcSource::pre_source_id() | ||||
| std::string SrsRtcSource::pre_source_id() | ||||
| { | ||||
|     return _pre_source_id; | ||||
| } | ||||
|  | @ -382,12 +390,12 @@ void SrsRtcSource::on_unpublish() | |||
|     // TODO: FIXME: Handle by statistic.
 | ||||
| } | ||||
| 
 | ||||
| SrsRtcPublisher* SrsRtcSource::rtc_publisher() | ||||
| ISrsRtcPublisher* SrsRtcSource::rtc_publisher() | ||||
| { | ||||
|     return rtc_publisher_; | ||||
| } | ||||
| 
 | ||||
| void SrsRtcSource::set_rtc_publisher(SrsRtcPublisher* v) | ||||
| void SrsRtcSource::set_rtc_publisher(ISrsRtcPublisher* v) | ||||
| { | ||||
|     rtc_publisher_ = v; | ||||
| } | ||||
|  | @ -416,6 +424,9 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcSource* source) | |||
|     discard_bframe = false; | ||||
|     merge_nalus = false; | ||||
|     meta = new SrsMetaCache(); | ||||
|     audio_timestamp = 0; | ||||
|     audio_sequence = 0; | ||||
|     video_sequence = 0; | ||||
| } | ||||
| 
 | ||||
| SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger() | ||||
|  | @ -584,6 +595,11 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack | |||
|     SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|     pkt->frame_type = SrsFrameTypeAudio; | ||||
|     pkt->header.set_marker(true); | ||||
|     pkt->header.set_sequence(audio_sequence++); | ||||
|     pkt->header.set_timestamp(audio_timestamp); | ||||
| 
 | ||||
|     // TODO: FIXME: Why 960? Need Refactoring?
 | ||||
|     audio_timestamp += 960; | ||||
| 
 | ||||
|     SrsRtpRawPayload* raw = new SrsRtpRawPayload(); | ||||
|     pkt->payload = raw; | ||||
|  | @ -641,25 +657,25 @@ srs_error_t SrsRtcFromRtmpBridger::on_video(SrsSharedPtrMessage* msg) | |||
|         if ((err = package_nalus(msg, samples, pkts)) != srs_success) { | ||||
|             return srs_error_wrap(err, "package nalus as one"); | ||||
|         } | ||||
|     } | ||||
|     } else { | ||||
|         // By default, we package each NALU(sample) to a RTP or FUA packet.
 | ||||
|         for (int i = 0; i < nn_samples; i++) { | ||||
|             SrsSample* sample = samples[i]; | ||||
| 
 | ||||
|     // By default, we package each NALU(sample) to a RTP or FUA packet.
 | ||||
|     for (int i = 0; i < nn_samples; i++) { | ||||
|         SrsSample* sample = samples[i]; | ||||
| 
 | ||||
|         // We always ignore bframe here, if config to discard bframe,
 | ||||
|         // the bframe flag will not be set.
 | ||||
|         if (sample->bframe) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (sample->size <= kRtpMaxPayloadSize) { | ||||
|             if ((err = package_single_nalu(msg, sample, pkts)) != srs_success) { | ||||
|                 return srs_error_wrap(err, "package single nalu"); | ||||
|             // We always ignore bframe here, if config to discard bframe,
 | ||||
|             // the bframe flag will not be set.
 | ||||
|             if (sample->bframe) { | ||||
|                 continue; | ||||
|             } | ||||
|         } else { | ||||
|             if ((err = package_fu_a(msg, sample, kRtpMaxPayloadSize, pkts)) != srs_success) { | ||||
|                 return srs_error_wrap(err, "package fu-a"); | ||||
| 
 | ||||
|             if (sample->size <= kRtpMaxPayloadSize) { | ||||
|                 if ((err = package_single_nalu(msg, sample, pkts)) != srs_success) { | ||||
|                     return srs_error_wrap(err, "package single nalu"); | ||||
|                 } | ||||
|             } else { | ||||
|                 if ((err = package_fu_a(msg, sample, kRtpMaxPayloadSize, pkts)) != srs_success) { | ||||
|                     return srs_error_wrap(err, "package fu-a"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -720,6 +736,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcSource* source, SrsShare | |||
|     SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|     pkt->frame_type = SrsFrameTypeVideo; | ||||
|     pkt->header.set_marker(false); | ||||
|     pkt->header.set_sequence(video_sequence++); | ||||
|     pkt->header.set_timestamp(msg->timestamp * 90); | ||||
| 
 | ||||
|     SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); | ||||
|  | @ -755,7 +772,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcSource* source, SrsShare | |||
|     } | ||||
| 
 | ||||
|     *ppkt = pkt; | ||||
|     srs_trace("RTC STAP-A seq=%u, sps %d, pps %d bytes", pkt->header.get_sequence(), sps.size(), pps.size()); | ||||
|     srs_info("RTC STAP-A seq=%u, sps %d, pps %d bytes", pkt->header.get_sequence(), sps.size(), pps.size()); | ||||
| 
 | ||||
|     return err; | ||||
| } | ||||
|  | @ -789,6 +806,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const | |||
|         // Package NALUs in a single RTP packet.
 | ||||
|         SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|         pkt->frame_type = SrsFrameTypeVideo; | ||||
|         pkt->header.set_sequence(video_sequence++); | ||||
|         pkt->header.set_timestamp(msg->timestamp * 90); | ||||
|         pkt->payload = raw; | ||||
|         pkt->shared_msg = msg->copy(); | ||||
|  | @ -818,6 +836,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const | |||
| 
 | ||||
|             SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|             pkt->frame_type = SrsFrameTypeVideo; | ||||
|             pkt->header.set_sequence(video_sequence++); | ||||
|             pkt->header.set_timestamp(msg->timestamp * 90); | ||||
| 
 | ||||
|             fua->nri = (SrsAvcNaluType)header; | ||||
|  | @ -843,6 +862,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, | |||
| 
 | ||||
|     SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|     pkt->frame_type = SrsFrameTypeVideo; | ||||
|     pkt->header.set_sequence(video_sequence++); | ||||
|     pkt->header.set_timestamp(msg->timestamp * 90); | ||||
| 
 | ||||
|     SrsRtpRawPayload* raw = new SrsRtpRawPayload(); | ||||
|  | @ -872,6 +892,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam | |||
| 
 | ||||
|         SrsRtpPacket2* pkt = new SrsRtpPacket2(); | ||||
|         pkt->frame_type = SrsFrameTypeVideo; | ||||
|         pkt->header.set_sequence(video_sequence++); | ||||
|         pkt->header.set_timestamp(msg->timestamp * 90); | ||||
| 
 | ||||
|         SrsRtpFUAPayload2* fua = new SrsRtpFUAPayload2(); | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ | |||
| class SrsRequest; | ||||
| class SrsConnection; | ||||
| class SrsMetaCache; | ||||
| class SrsRtcPublisher; | ||||
| class SrsSharedPtrMessage; | ||||
| class SrsCommonMessage; | ||||
| class SrsMessageArray; | ||||
|  | @ -94,6 +93,15 @@ private: | |||
| // Global singleton instance.
 | ||||
| extern SrsRtcSourceManager* _srs_rtc_sources; | ||||
| 
 | ||||
| class ISrsRtcPublisher | ||||
| { | ||||
| public: | ||||
|     ISrsRtcPublisher(); | ||||
|     virtual ~ISrsRtcPublisher(); | ||||
| public: | ||||
|     virtual void request_keyframe() = 0; | ||||
| }; | ||||
| 
 | ||||
| class SrsRtcSource | ||||
| { | ||||
| private: | ||||
|  | @ -101,11 +109,11 @@ private: | |||
|     // For edge, it's the edge ingest id.
 | ||||
|     // when source id changed, for example, the edge reconnect,
 | ||||
|     // invoke the on_source_id_changed() to let all clients know.
 | ||||
|     int _source_id; | ||||
|     std::string _source_id; | ||||
|     // previous source id.
 | ||||
|     int _pre_source_id; | ||||
|     std::string _pre_source_id; | ||||
|     SrsRequest* req; | ||||
|     SrsRtcPublisher* rtc_publisher_; | ||||
|     ISrsRtcPublisher* rtc_publisher_; | ||||
|     // Transmux RTMP to RTC.
 | ||||
|     SrsRtcFromRtmpBridger* bridger_; | ||||
| private: | ||||
|  | @ -121,10 +129,10 @@ public: | |||
|     // Update the authentication information in request.
 | ||||
|     virtual void update_auth(SrsRequest* r); | ||||
|     // The source id changed.
 | ||||
|     virtual srs_error_t on_source_id_changed(int id); | ||||
|     virtual srs_error_t on_source_id_changed(std::string id); | ||||
|     // Get current source id.
 | ||||
|     virtual int source_id(); | ||||
|     virtual int pre_source_id(); | ||||
|     virtual std::string source_id(); | ||||
|     virtual std::string pre_source_id(); | ||||
|     // Get the bridger.
 | ||||
|     ISrsSourceBridger* bridger(); | ||||
| public: | ||||
|  | @ -145,8 +153,8 @@ public: | |||
|     virtual void on_unpublish(); | ||||
| public: | ||||
|     // Get and set the publisher, passed to consumer to process requests such as PLI.
 | ||||
|     SrsRtcPublisher* rtc_publisher(); | ||||
|     void set_rtc_publisher(SrsRtcPublisher* v); | ||||
|     ISrsRtcPublisher* rtc_publisher(); | ||||
|     void set_rtc_publisher(ISrsRtcPublisher* v); | ||||
|     // Consume the shared RTP packet, user must free it.
 | ||||
|     srs_error_t on_rtp(SrsRtpPacket2* pkt); | ||||
| }; | ||||
|  | @ -165,6 +173,9 @@ private: | |||
|     SrsAudioRecode* codec; | ||||
|     bool discard_bframe; | ||||
|     bool merge_nalus; | ||||
|     uint32_t audio_timestamp; | ||||
|     uint16_t audio_sequence; | ||||
|     uint16_t video_sequence; | ||||
| public: | ||||
|     SrsRtcFromRtmpBridger(SrsRtcSource* source); | ||||
|     virtual ~SrsRtcFromRtmpBridger(); | ||||
|  |  | |||
|  | @ -515,8 +515,8 @@ srs_error_t SrsRtmpConn::stream_service_cycle() | |||
|     } | ||||
|      | ||||
|     bool enabled_cache = _srs_config->get_gop_cache(req->vhost); | ||||
|     srs_trace("source url=%s, ip=%s, cache=%d, is_edge=%d, source_id=[%d][%d]", | ||||
|         req->get_stream_url().c_str(), ip.c_str(), enabled_cache, info->edge, ::getpid(), source->source_id()); | ||||
|     srs_trace("source url=%s, ip=%s, cache=%d, is_edge=%d, source_id=[%d][%s]", | ||||
|         req->get_stream_url().c_str(), ip.c_str(), enabled_cache, info->edge, ::getpid(), source->source_id().c_str()); | ||||
|     source->set_cache(enabled_cache); | ||||
|      | ||||
|     switch (info->type) { | ||||
|  |  | |||
|  | @ -120,9 +120,11 @@ srs_error_t SrsRtpConn::on_udp_packet(const sockaddr* from, const int fromlen, c | |||
|      | ||||
|     // always free it.
 | ||||
|     SrsAutoFree(SrsRtpPacket, cache); | ||||
|      | ||||
|     if ((err = rtsp->on_rtp_packet(cache, stream_id)) != srs_success) { | ||||
|         return srs_error_wrap(err, "process rtp packet"); | ||||
| 
 | ||||
|     err = rtsp->on_rtp_packet(cache, stream_id); | ||||
|     if (err != srs_success) { | ||||
|         srs_warn("ignore RTP packet err %s", srs_error_desc(err).c_str()); | ||||
|         srs_freep(err); | ||||
|     } | ||||
|      | ||||
|     return err; | ||||
|  | @ -495,54 +497,62 @@ srs_error_t SrsRtspConn::write_sequence_header() | |||
|     } | ||||
|      | ||||
|     // generate audio sh by audio specific config.
 | ||||
|     if (true) { | ||||
|         std::string sh = aac_specific_config; | ||||
|          | ||||
|         SrsFormat* format = new SrsFormat(); | ||||
|         SrsAutoFree(SrsFormat, format); | ||||
|          | ||||
|         if ((err = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != srs_success) { | ||||
|             return srs_error_wrap(err, "on aac sequence header"); | ||||
|         } | ||||
|          | ||||
|         SrsAudioCodecConfig* dec = format->acodec; | ||||
|          | ||||
|         acodec->sound_format = SrsAudioCodecIdAAC; | ||||
|         acodec->sound_type = (dec->aac_channels == 2)? SrsAudioChannelsStereo : SrsAudioChannelsMono; | ||||
|         acodec->sound_size = SrsAudioSampleBits16bit; | ||||
|         acodec->aac_packet_type = 0; | ||||
|          | ||||
|         static int srs_aac_srates[] = { | ||||
|             96000, 88200, 64000, 48000, | ||||
|             44100, 32000, 24000, 22050, | ||||
|             16000, 12000, 11025,  8000, | ||||
|             7350,     0,     0,    0 | ||||
|         }; | ||||
|         switch (srs_aac_srates[dec->aac_sample_rate]) { | ||||
|             case 11025: | ||||
|                 acodec->sound_rate = SrsAudioSampleRate11025; | ||||
|                 break; | ||||
|             case 22050: | ||||
|                 acodec->sound_rate = SrsAudioSampleRate22050; | ||||
|                 break; | ||||
|             case 44100: | ||||
|                 acodec->sound_rate = SrsAudioSampleRate44100; | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         }; | ||||
|          | ||||
|         if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), acodec, (uint32_t)dts)) != srs_success) { | ||||
|             return srs_error_wrap(err, "write audio raw frame"); | ||||
|         } | ||||
|     if (aac_specific_config.empty()) { | ||||
|         srs_warn("no audio asc"); | ||||
|         return err; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     std::string sh = aac_specific_config; | ||||
| 
 | ||||
|     SrsFormat* format = new SrsFormat(); | ||||
|     SrsAutoFree(SrsFormat, format); | ||||
| 
 | ||||
|     if ((err = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != srs_success) { | ||||
|         return srs_error_wrap(err, "on aac sequence header"); | ||||
|     } | ||||
| 
 | ||||
|     SrsAudioCodecConfig* dec = format->acodec; | ||||
| 
 | ||||
|     acodec->sound_format = SrsAudioCodecIdAAC; | ||||
|     acodec->sound_type = (dec->aac_channels == 2)? SrsAudioChannelsStereo : SrsAudioChannelsMono; | ||||
|     acodec->sound_size = SrsAudioSampleBits16bit; | ||||
|     acodec->aac_packet_type = 0; | ||||
| 
 | ||||
|     static int srs_aac_srates[] = { | ||||
|         96000, 88200, 64000, 48000, | ||||
|         44100, 32000, 24000, 22050, | ||||
|         16000, 12000, 11025,  8000, | ||||
|         7350,     0,     0,    0 | ||||
|     }; | ||||
|     switch (srs_aac_srates[dec->aac_sample_rate]) { | ||||
|         case 11025: | ||||
|             acodec->sound_rate = SrsAudioSampleRate11025; | ||||
|             break; | ||||
|         case 22050: | ||||
|             acodec->sound_rate = SrsAudioSampleRate22050; | ||||
|             break; | ||||
|         case 44100: | ||||
|             acodec->sound_rate = SrsAudioSampleRate44100; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     }; | ||||
| 
 | ||||
|     if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), acodec, (uint32_t)dts)) != srs_success) { | ||||
|         return srs_error_wrap(err, "write audio raw frame"); | ||||
|     } | ||||
| 
 | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtspConn::write_h264_sps_pps(uint32_t dts, uint32_t pts) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|     if (h264_sps.empty() || h264_pps.empty()) { | ||||
|         srs_warn("no sps=%dB or pps=%dB", (int)h264_sps.size(), (int)h264_pps.size()); | ||||
|         return err; | ||||
|     } | ||||
|      | ||||
|     // h264 raw to h264 packet.
 | ||||
|     std::string sh; | ||||
|  | @ -687,6 +697,7 @@ void SrsRtspConn::close() | |||
| SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c) | ||||
| { | ||||
|     // TODO: FIXME: support reload.
 | ||||
|     engine = _srs_config->get_stream_caster_engine(c); | ||||
|     output = _srs_config->get_stream_caster_output(c); | ||||
|     local_port_min = _srs_config->get_stream_caster_rtp_port_min(c); | ||||
|     local_port_max = _srs_config->get_stream_caster_rtp_port_max(c); | ||||
|  | @ -728,7 +739,7 @@ srs_error_t SrsRtspCaster::alloc_port(int* pport) | |||
|             break; | ||||
|         } | ||||
|     } | ||||
|     srs_info("rtsp: alloc port=%d-%d", *pport, *pport + 1); | ||||
|     srs_trace("rtsp: %s alloc port=%d-%d", engine.c_str(), *pport, *pport + 1); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  | @ -738,7 +749,7 @@ void SrsRtspCaster::free_port(int lpmin, int lpmax) | |||
|     for (int i = lpmin; i < lpmax; i++) { | ||||
|         used_ports[i] = false; | ||||
|     } | ||||
|     srs_trace("rtsp: free rtp port=%d-%d", lpmin, lpmax); | ||||
|     srs_trace("rtsp: %s free rtp port=%d-%d", engine.c_str(), lpmin, lpmax); | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtspCaster::on_tcp_client(srs_netfd_t stfd) | ||||
|  |  | |||
|  | @ -173,6 +173,7 @@ private: | |||
| class SrsRtspCaster : public ISrsTcpHandler | ||||
| { | ||||
| private: | ||||
|     std::string engine; | ||||
|     std::string output; | ||||
|     int local_port_min; | ||||
|     int local_port_max; | ||||
|  |  | |||
|  | @ -825,8 +825,8 @@ srs_error_t SrsServer::initialize_st() | |||
|         return srs_error_new(ERROR_SYSTEM_ASSERT_FAILED, "ppid=%d illegal for asprocess", ppid); | ||||
|     } | ||||
|      | ||||
|     srs_trace("server main cid=%d, pid=%d, ppid=%d, asprocess=%d", | ||||
|         _srs_context->get_id(), ::getpid(), ppid, asprocess); | ||||
|     srs_trace("server main cid=%s, pid=%d, ppid=%d, asprocess=%d", | ||||
|         _srs_context->get_id().c_str(), ::getpid(), ppid, asprocess); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  |  | |||
|  | @ -520,7 +520,7 @@ srs_error_t SrsConsumer::dump_packets(SrsMessageArray* msgs, int& count) | |||
|     count = 0; | ||||
|      | ||||
|     if (should_update_source_id) { | ||||
|         srs_trace("update source_id=%d[%d]", source->source_id(), source->source_id()); | ||||
|         srs_trace("update source_id=%s[%s]", source->source_id().c_str(), source->source_id().c_str()); | ||||
|         should_update_source_id = false; | ||||
|     } | ||||
|      | ||||
|  | @ -1792,7 +1792,7 @@ void SrsSourceManager::dispose() | |||
| 
 | ||||
| srs_error_t SrsSourceManager::cycle() | ||||
| { | ||||
|     int cid = _srs_context->get_id(); | ||||
|     std::string cid = _srs_context->get_id(); | ||||
|     srs_error_t err = do_cycle(); | ||||
|     _srs_context->set_id(cid); | ||||
|      | ||||
|  | @ -1809,7 +1809,7 @@ srs_error_t SrsSourceManager::do_cycle() | |||
|          | ||||
|         // Do cycle source to cleanup components, such as hls dispose.
 | ||||
|         if ((err = source->cycle()) != srs_success) { | ||||
|             return srs_error_wrap(err, "source=%d/%d cycle", source->source_id(), source->pre_source_id()); | ||||
|             return srs_error_wrap(err, "source=%s/%s cycle", source->source_id().c_str(), source->pre_source_id().c_str()); | ||||
|         } | ||||
|          | ||||
|         // TODO: FIXME: support source cleanup.
 | ||||
|  | @ -1866,7 +1866,7 @@ SrsSource::SrsSource() | |||
|     mix_queue = new SrsMixQueue(); | ||||
|      | ||||
|     _can_publish = true; | ||||
|     _pre_source_id = _source_id = -1; | ||||
|     _pre_source_id = _source_id = ""; | ||||
|     die_at = 0; | ||||
| 
 | ||||
|     handler = NULL; | ||||
|  | @ -2065,7 +2065,7 @@ srs_error_t SrsSource::on_reload_vhost_play(string vhost) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsSource::on_source_id_changed(int id) | ||||
| srs_error_t SrsSource::on_source_id_changed(string id) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|  | @ -2073,7 +2073,7 @@ srs_error_t SrsSource::on_source_id_changed(int id) | |||
|         return err; | ||||
|     } | ||||
|      | ||||
|     if (_pre_source_id == -1) { | ||||
|     if (_pre_source_id == "") { | ||||
|         _pre_source_id = id; | ||||
|     } else if (_pre_source_id != _source_id) { | ||||
|         _pre_source_id = _source_id; | ||||
|  | @ -2091,12 +2091,12 @@ srs_error_t SrsSource::on_source_id_changed(int id) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| int SrsSource::source_id() | ||||
| string SrsSource::source_id() | ||||
| { | ||||
|     return _source_id; | ||||
| } | ||||
| 
 | ||||
| int SrsSource::pre_source_id() | ||||
| string SrsSource::pre_source_id() | ||||
| { | ||||
|     return _pre_source_id; | ||||
| } | ||||
|  |  | |||
|  | @ -508,9 +508,9 @@ private: | |||
|     // For edge, it's the edge ingest id.
 | ||||
|     // when source id changed, for example, the edge reconnect,
 | ||||
|     // invoke the on_source_id_changed() to let all clients know.
 | ||||
|     int _source_id; | ||||
|     std::string _source_id; | ||||
|     // previous source id.
 | ||||
|     int _pre_source_id; | ||||
|     std::string _pre_source_id; | ||||
|     // deep copy of client request.
 | ||||
|     SrsRequest* req; | ||||
|     // To delivery stream to clients.
 | ||||
|  | @ -567,10 +567,10 @@ public: | |||
|     virtual srs_error_t on_reload_vhost_play(std::string vhost); | ||||
| public: | ||||
|     // The source id changed.
 | ||||
|     virtual srs_error_t on_source_id_changed(int id); | ||||
|     virtual srs_error_t on_source_id_changed(std::string id); | ||||
|     // Get current source id.
 | ||||
|     virtual int source_id(); | ||||
|     virtual int pre_source_id(); | ||||
|     virtual std::string source_id(); | ||||
|     virtual std::string pre_source_id(); | ||||
|     // Whether source is inactive, which means there is no publishing stream source.
 | ||||
|     // @remark For edge, it's inactive util stream has been pulled from origin.
 | ||||
|     virtual bool inactive(); | ||||
|  |  | |||
|  | @ -74,14 +74,14 @@ srs_error_t SrsDummyCoroutine::pull() | |||
|     return srs_error_new(ERROR_THREAD_DUMMY, "dummy pull"); | ||||
| } | ||||
| 
 | ||||
| int SrsDummyCoroutine::cid() | ||||
| string SrsDummyCoroutine::cid() | ||||
| { | ||||
|     return 0; | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| _ST_THREAD_CREATE_PFN _pfn_st_thread_create = (_ST_THREAD_CREATE_PFN)st_thread_create; | ||||
| 
 | ||||
| SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, int cid) | ||||
| SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, std::string cid) | ||||
| { | ||||
|     name = n; | ||||
|     handler = h; | ||||
|  | @ -180,7 +180,7 @@ srs_error_t SrsSTCoroutine::pull() | |||
|     return srs_error_copy(trd_err); | ||||
| } | ||||
| 
 | ||||
| int SrsSTCoroutine::cid() | ||||
| string SrsSTCoroutine::cid() | ||||
| { | ||||
|     return context; | ||||
| } | ||||
|  | @ -188,7 +188,7 @@ int SrsSTCoroutine::cid() | |||
| srs_error_t SrsSTCoroutine::cycle() | ||||
| { | ||||
|     if (_srs_context) { | ||||
|         if (context) { | ||||
|         if (!context.empty()) { | ||||
|             _srs_context->set_id(context); | ||||
|         } else { | ||||
|             context = _srs_context->generate_id(); | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ public: | |||
|     // @return a copy of error, which should be freed by user.
 | ||||
|     //      NULL if not terminated and user should pull again.
 | ||||
|     virtual srs_error_t pull() = 0; | ||||
|     virtual int cid() = 0; | ||||
|     virtual std::string cid() = 0; | ||||
| }; | ||||
| 
 | ||||
| // An empty coroutine, user can default to this object before create any real coroutine.
 | ||||
|  | @ -95,7 +95,7 @@ public: | |||
|     virtual void stop(); | ||||
|     virtual void interrupt(); | ||||
|     virtual srs_error_t pull(); | ||||
|     virtual int cid(); | ||||
|     virtual std::string cid(); | ||||
| }; | ||||
| 
 | ||||
| // For utest to mock the thread create.
 | ||||
|  | @ -121,7 +121,7 @@ private: | |||
|     ISrsCoroutineHandler* handler; | ||||
| private: | ||||
|     srs_thread_t trd; | ||||
|     int context; | ||||
|     std::string context; | ||||
|     srs_error_t trd_err; | ||||
| private: | ||||
|     bool started; | ||||
|  | @ -132,7 +132,7 @@ private: | |||
| public: | ||||
|     // Create a thread with name n and handler h.
 | ||||
|     // @remark User can specify a cid for thread to use, or we will allocate a new one.
 | ||||
|     SrsSTCoroutine(std::string n, ISrsCoroutineHandler* h, int cid = 0); | ||||
|     SrsSTCoroutine(std::string n, ISrsCoroutineHandler* h, std::string cid = ""); | ||||
|     virtual ~SrsSTCoroutine(); | ||||
| public: | ||||
|     // Start the thread.
 | ||||
|  | @ -154,7 +154,7 @@ public: | |||
|     // @remark Return ERROR_THREAD_INTERRUPED when thread is interrupted.
 | ||||
|     virtual srs_error_t pull(); | ||||
|     // Get the context id of thread.
 | ||||
|     virtual int cid(); | ||||
|     virtual std::string cid(); | ||||
| private: | ||||
|     virtual srs_error_t cycle(); | ||||
|     static void* pfn(void* arg); | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ srs_error_t SrsStatisticVhost::dumps(SrsJsonObject* obj) | |||
|     bool hls_enabled = _srs_config->get_hls_enabled(vhost); | ||||
|     bool enabled = _srs_config->get_vhost_enabled(vhost); | ||||
|      | ||||
|     obj->set("id", SrsJsonAny::integer(id)); | ||||
|     obj->set("id", SrsJsonAny::str(id.c_str())); | ||||
|     obj->set("name", SrsJsonAny::str(vhost.c_str())); | ||||
|     obj->set("enabled", SrsJsonAny::boolean(enabled)); | ||||
|     obj->set("clients", SrsJsonAny::integer(nb_clients)); | ||||
|  | @ -134,9 +134,9 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     obj->set("id", SrsJsonAny::integer(id)); | ||||
|     obj->set("id", SrsJsonAny::str(id.c_str())); | ||||
|     obj->set("name", SrsJsonAny::str(stream.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::integer(vhost->id)); | ||||
|     obj->set("vhost", SrsJsonAny::str(vhost->id.c_str())); | ||||
|     obj->set("app", SrsJsonAny::str(app.c_str())); | ||||
|     obj->set("live_ms", SrsJsonAny::integer(srsu2ms(srs_get_system_time()))); | ||||
|     obj->set("clients", SrsJsonAny::integer(nb_clients)); | ||||
|  | @ -154,7 +154,7 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj) | |||
|     obj->set("publish", publish); | ||||
|      | ||||
|     publish->set("active", SrsJsonAny::boolean(active)); | ||||
|     publish->set("cid", SrsJsonAny::integer(connection_cid)); | ||||
|     publish->set("cid", SrsJsonAny::str(connection_cid.c_str())); | ||||
|      | ||||
|     if (!has_video) { | ||||
|         obj->set("video", SrsJsonAny::null()); | ||||
|  | @ -184,7 +184,7 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| void SrsStatisticStream::publish(int cid) | ||||
| void SrsStatisticStream::publish(string cid) | ||||
| { | ||||
|     connection_cid = cid; | ||||
|     active = true; | ||||
|  | @ -203,7 +203,7 @@ void SrsStatisticStream::close() | |||
| 
 | ||||
| SrsStatisticClient::SrsStatisticClient() | ||||
| { | ||||
|     id = 0; | ||||
|     id = ""; | ||||
|     stream = NULL; | ||||
|     conn = NULL; | ||||
|     req = NULL; | ||||
|  | @ -219,9 +219,9 @@ srs_error_t SrsStatisticClient::dumps(SrsJsonObject* obj) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     obj->set("id", SrsJsonAny::integer(id)); | ||||
|     obj->set("vhost", SrsJsonAny::integer(stream->vhost->id)); | ||||
|     obj->set("stream", SrsJsonAny::integer(stream->id)); | ||||
|     obj->set("id", SrsJsonAny::str(id.c_str())); | ||||
|     obj->set("vhost", SrsJsonAny::str(stream->vhost->id.c_str())); | ||||
|     obj->set("stream", SrsJsonAny::str(stream->id.c_str())); | ||||
|     obj->set("ip", SrsJsonAny::str(req->ip.c_str())); | ||||
|     obj->set("pageUrl", SrsJsonAny::str(req->pageUrl.c_str())); | ||||
|     obj->set("swfUrl", SrsJsonAny::str(req->swfUrl.c_str())); | ||||
|  | @ -278,21 +278,21 @@ SrsStatistic::~SrsStatistic() | |||
|     srs_freep(clk); | ||||
|      | ||||
|     if (true) { | ||||
|         std::map<int64_t, SrsStatisticVhost*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticVhost*>::iterator it; | ||||
|         for (it = vhosts.begin(); it != vhosts.end(); it++) { | ||||
|             SrsStatisticVhost* vhost = it->second; | ||||
|             srs_freep(vhost); | ||||
|         } | ||||
|     } | ||||
|     if (true) { | ||||
|         std::map<int64_t, SrsStatisticStream*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticStream*>::iterator it; | ||||
|         for (it = streams.begin(); it != streams.end(); it++) { | ||||
|             SrsStatisticStream* stream = it->second; | ||||
|             srs_freep(stream); | ||||
|         } | ||||
|     } | ||||
|     if (true) { | ||||
|         std::map<int, SrsStatisticClient*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticClient*>::iterator it; | ||||
|         for (it = clients.begin(); it != clients.end(); it++) { | ||||
|             SrsStatisticClient* client = it->second; | ||||
|             srs_freep(client); | ||||
|  | @ -319,40 +319,27 @@ SrsStatistic* SrsStatistic::instance() | |||
|     return _instance; | ||||
| } | ||||
| 
 | ||||
| SrsStatisticVhost* SrsStatistic::find_vhost(int vid) | ||||
| SrsStatisticVhost* SrsStatistic::find_vhost(string vid) | ||||
| { | ||||
|     std::map<int64_t, SrsStatisticVhost*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticVhost*>::iterator it; | ||||
|     if ((it = vhosts.find(vid)) != vhosts.end()) { | ||||
|         return it->second; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| SrsStatisticVhost* SrsStatistic::find_vhost(string name) | ||||
| SrsStatisticStream* SrsStatistic::find_stream(string sid) | ||||
| { | ||||
|     if (rvhosts.empty()) { | ||||
|         return NULL; | ||||
|     } | ||||
|      | ||||
|     std::map<string, SrsStatisticVhost*>::iterator it; | ||||
|     if ((it = rvhosts.find(name)) != rvhosts.end()) { | ||||
|         return it->second; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| SrsStatisticStream* SrsStatistic::find_stream(int sid) | ||||
| { | ||||
|     std::map<int64_t, SrsStatisticStream*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticStream*>::iterator it; | ||||
|     if ((it = streams.find(sid)) != streams.end()) { | ||||
|         return it->second; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| SrsStatisticClient* SrsStatistic::find_client(int cid) | ||||
| SrsStatisticClient* SrsStatistic::find_client(string cid) | ||||
| { | ||||
|     std::map<int, SrsStatisticClient*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticClient*>::iterator it; | ||||
|     if ((it = clients.find(cid)) != clients.end()) { | ||||
|         return it->second; | ||||
|     } | ||||
|  | @ -405,7 +392,7 @@ srs_error_t SrsStatistic::on_video_frames(SrsRequest* req, int nb_frames) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| void SrsStatistic::on_stream_publish(SrsRequest* req, int cid) | ||||
| void SrsStatistic::on_stream_publish(SrsRequest* req, string cid) | ||||
| { | ||||
|     SrsStatisticVhost* vhost = create_vhost(req); | ||||
|     SrsStatisticStream* stream = create_stream(vhost, req); | ||||
|  | @ -421,7 +408,7 @@ void SrsStatistic::on_stream_close(SrsRequest* req) | |||
|      | ||||
|     // TODO: FIXME: Should fix https://github.com/ossrs/srs/issues/803
 | ||||
|     if (true) { | ||||
|         std::map<int64_t, SrsStatisticStream*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticStream*>::iterator it; | ||||
|         if ((it=streams.find(stream->id)) != streams.end()) { | ||||
|             streams.erase(it); | ||||
|         } | ||||
|  | @ -436,7 +423,7 @@ void SrsStatistic::on_stream_close(SrsRequest* req) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsStatistic::on_client(int id, SrsRequest* req, SrsConnection* conn, SrsRtmpConnType type) | ||||
| srs_error_t SrsStatistic::on_client(std::string id, SrsRequest* req, SrsConnection* conn, SrsRtmpConnType type) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|  | @ -464,9 +451,9 @@ srs_error_t SrsStatistic::on_client(int id, SrsRequest* req, SrsConnection* conn | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| void SrsStatistic::on_disconnect(int id) | ||||
| void SrsStatistic::on_disconnect(std::string id) | ||||
| { | ||||
|     std::map<int, SrsStatisticClient*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticClient*>::iterator it; | ||||
|     if ((it = clients.find(id)) == clients.end()) { | ||||
|         return; | ||||
|     } | ||||
|  | @ -484,7 +471,7 @@ void SrsStatistic::on_disconnect(int id) | |||
| 
 | ||||
| void SrsStatistic::kbps_add_delta(SrsConnection* conn) | ||||
| { | ||||
|     int id = conn->srs_id(); | ||||
|     std::string id = conn->srs_id(); | ||||
|     if (clients.find(id) == clients.end()) { | ||||
|         return; | ||||
|     } | ||||
|  | @ -506,14 +493,14 @@ SrsKbps* SrsStatistic::kbps_sample() | |||
| { | ||||
|     kbps->sample(); | ||||
|     if (true) { | ||||
|         std::map<int64_t, SrsStatisticVhost*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticVhost*>::iterator it; | ||||
|         for (it = vhosts.begin(); it != vhosts.end(); it++) { | ||||
|             SrsStatisticVhost* vhost = it->second; | ||||
|             vhost->kbps->sample(); | ||||
|         } | ||||
|     } | ||||
|     if (true) { | ||||
|         std::map<int64_t, SrsStatisticStream*>::iterator it; | ||||
|         std::map<std::string, SrsStatisticStream*>::iterator it; | ||||
|         for (it = streams.begin(); it != streams.end(); it++) { | ||||
|             SrsStatisticStream* stream = it->second; | ||||
|             stream->kbps->sample(); | ||||
|  | @ -532,7 +519,7 @@ srs_error_t SrsStatistic::dumps_vhosts(SrsJsonArray* arr) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     std::map<int64_t, SrsStatisticVhost*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticVhost*>::iterator it; | ||||
|     for (it = vhosts.begin(); it != vhosts.end(); it++) { | ||||
|         SrsStatisticVhost* vhost = it->second; | ||||
|          | ||||
|  | @ -551,7 +538,7 @@ srs_error_t SrsStatistic::dumps_streams(SrsJsonArray* arr) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     std::map<int64_t, SrsStatisticStream*>::iterator it; | ||||
|     std::map<std::string, SrsStatisticStream*>::iterator it; | ||||
|     for (it = streams.begin(); it != streams.end(); it++) { | ||||
|         SrsStatisticStream* stream = it->second; | ||||
|          | ||||
|  | @ -570,7 +557,7 @@ srs_error_t SrsStatistic::dumps_clients(SrsJsonArray* arr, int start, int count) | |||
| { | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     std::map<int, SrsStatisticClient*>::iterator it = clients.begin(); | ||||
|     std::map<std::string, SrsStatisticClient*>::iterator it = clients.begin(); | ||||
|     for (int i = 0; i < start + count && it != clients.end(); it++, i++) { | ||||
|         if (i < start) { | ||||
|             continue; | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ class SrsJsonArray; | |||
| struct SrsStatisticVhost | ||||
| { | ||||
| public: | ||||
|     int64_t id; | ||||
|     std::string id; | ||||
|     std::string vhost; | ||||
|     int nb_streams; | ||||
|     int nb_clients; | ||||
|  | @ -61,13 +61,13 @@ public: | |||
| struct SrsStatisticStream | ||||
| { | ||||
| public: | ||||
|     int64_t id; | ||||
|     std::string id; | ||||
|     SrsStatisticVhost* vhost; | ||||
|     std::string app; | ||||
|     std::string stream; | ||||
|     std::string url; | ||||
|     bool active; | ||||
|     int connection_cid; | ||||
|     std::string connection_cid; | ||||
|     int nb_clients; | ||||
|     uint64_t nb_frames; | ||||
| public: | ||||
|  | @ -101,7 +101,7 @@ public: | |||
|     virtual srs_error_t dumps(SrsJsonObject* obj); | ||||
| public: | ||||
|     // Publish the stream.
 | ||||
|     virtual void publish(int cid); | ||||
|     virtual void publish(std::string cid); | ||||
|     // Close the stream.
 | ||||
|     virtual void close(); | ||||
| }; | ||||
|  | @ -113,7 +113,7 @@ public: | |||
|     SrsConnection* conn; | ||||
|     SrsRequest* req; | ||||
|     SrsRtmpConnType type; | ||||
|     int id; | ||||
|     std::string id; | ||||
|     srs_utime_t create; | ||||
| public: | ||||
|     SrsStatisticClient(); | ||||
|  | @ -151,19 +151,19 @@ private: | |||
|     int64_t _server_id; | ||||
| private: | ||||
|     // The key: vhost id, value: vhost object.
 | ||||
|     std::map<int64_t, SrsStatisticVhost*> vhosts; | ||||
|     std::map<std::string, SrsStatisticVhost*> vhosts; | ||||
|     // The key: vhost url, value: vhost Object.
 | ||||
|     // @remark a fast index for vhosts.
 | ||||
|     std::map<std::string, SrsStatisticVhost*> rvhosts; | ||||
| private: | ||||
|     // The key: stream id, value: stream Object.
 | ||||
|     std::map<int64_t, SrsStatisticStream*> streams; | ||||
|     std::map<std::string, SrsStatisticStream*> streams; | ||||
|     // The key: stream url, value: stream Object.
 | ||||
|     // @remark a fast index for streams.
 | ||||
|     std::map<std::string, SrsStatisticStream*> rstreams; | ||||
| private: | ||||
|     // The key: client id, value: stream object.
 | ||||
|     std::map<int, SrsStatisticClient*> clients; | ||||
|     std::map<std::string, SrsStatisticClient*> clients; | ||||
|     // The server total kbps.
 | ||||
|     SrsKbps* kbps; | ||||
|     SrsWallClock* clk; | ||||
|  | @ -179,10 +179,9 @@ private: | |||
| public: | ||||
|     static SrsStatistic* instance(); | ||||
| public: | ||||
|     virtual SrsStatisticVhost* find_vhost(int vid); | ||||
|     virtual SrsStatisticVhost* find_vhost(std::string name); | ||||
|     virtual SrsStatisticStream* find_stream(int sid); | ||||
|     virtual SrsStatisticClient* find_client(int cid); | ||||
|     virtual SrsStatisticVhost* find_vhost(std::string vid); | ||||
|     virtual SrsStatisticStream* find_stream(std::string sid); | ||||
|     virtual SrsStatisticClient* find_client(std::string cid); | ||||
| public: | ||||
|     // When got video info for stream.
 | ||||
|     virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile, | ||||
|  | @ -196,7 +195,7 @@ public: | |||
|     // When publish stream.
 | ||||
|     // @param req the request object of publish connection.
 | ||||
|     // @param cid the cid of publish connection.
 | ||||
|     virtual void on_stream_publish(SrsRequest* req, int cid); | ||||
|     virtual void on_stream_publish(SrsRequest* req, std::string cid); | ||||
|     // When close stream.
 | ||||
|     virtual void on_stream_close(SrsRequest* req); | ||||
| public: | ||||
|  | @ -205,12 +204,12 @@ public: | |||
|     // @param req, the client request object.
 | ||||
|     // @param conn, the physical absract connection object.
 | ||||
|     // @param type, the type of connection.
 | ||||
|     virtual srs_error_t on_client(int id, SrsRequest* req, SrsConnection* conn, SrsRtmpConnType type); | ||||
|     virtual srs_error_t on_client(std::string id, SrsRequest* req, SrsConnection* conn, SrsRtmpConnType type); | ||||
|     // Client disconnect
 | ||||
|     // @remark the on_disconnect always call, while the on_client is call when
 | ||||
|     //      only got the request object, so the client specified by id maybe not
 | ||||
|     //      exists in stat.
 | ||||
|     virtual void on_disconnect(int id); | ||||
|     virtual void on_disconnect(std::string id); | ||||
|     // Sample the kbps, add delta bytes of conn.
 | ||||
|     // Use kbps_sample() to get all result of kbps stat.
 | ||||
|     // TODO: FIXME: the add delta must use ISrsKbpsDelta interface instead.
 | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include <srs_kernel_log.hpp> | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <algorithm> | ||||
| using namespace std; | ||||
| 
 | ||||
| SrsCoroutineManager::SrsCoroutineManager() | ||||
|  | @ -72,7 +73,9 @@ srs_error_t SrsCoroutineManager::cycle() | |||
| 
 | ||||
| void SrsCoroutineManager::remove(ISrsConnection* c) | ||||
| { | ||||
|     conns.push_back(c); | ||||
|     if (::find(conns.begin(), conns.end(), c) == conns.end()) { | ||||
|         conns.push_back(c); | ||||
|     } | ||||
|     srs_cond_signal(cond); | ||||
| } | ||||
| 
 | ||||
|  | @ -80,8 +83,8 @@ void SrsCoroutineManager::clear() | |||
| { | ||||
|     // To prevent thread switch when delete connection,
 | ||||
|     // we copy all connections then free one by one.
 | ||||
|     vector<ISrsConnection*> copy = conns; | ||||
|     conns.clear(); | ||||
|     vector<ISrsConnection*> copy; | ||||
|     copy.swap(conns); | ||||
|      | ||||
|     vector<ISrsConnection*>::iterator it; | ||||
|     for (it = copy.begin(); it != copy.end(); ++it) { | ||||
|  |  | |||
|  | @ -24,6 +24,6 @@ | |||
| #ifndef SRS_CORE_VERSION4_HPP | ||||
| #define SRS_CORE_VERSION4_HPP | ||||
| 
 | ||||
| #define SRS_VERSION4_REVISION 29 | ||||
| #define SRS_VERSION4_REVISION 30 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -411,7 +411,7 @@ private: | |||
|     std::string file; | ||||
|     int line; | ||||
|      | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     int rerrno; | ||||
|      | ||||
|     std::string desc; | ||||
|  |  | |||
|  | @ -42,23 +42,23 @@ void ISrsLog::reopen() | |||
| { | ||||
| } | ||||
| 
 | ||||
| void ISrsLog::verbose(const char* /*tag*/, int /*context_id*/, const char* /*fmt*/, ...) | ||||
| void ISrsLog::verbose(const char* /*tag*/, const char* /*context_id*/, const char* /*fmt*/, ...) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ISrsLog::info(const char* /*tag*/, int /*context_id*/, const char* /*fmt*/, ...) | ||||
| void ISrsLog::info(const char* /*tag*/, const char* /*context_id*/, const char* /*fmt*/, ...) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ISrsLog::trace(const char* /*tag*/, int /*context_id*/, const char* /*fmt*/, ...) | ||||
| void ISrsLog::trace(const char* /*tag*/, const char* /*context_id*/, const char* /*fmt*/, ...) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ISrsLog::warn(const char* /*tag*/, int /*context_id*/, const char* /*fmt*/, ...) | ||||
| void ISrsLog::warn(const char* /*tag*/, const char* /*context_id*/, const char* /*fmt*/, ...) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ISrsLog::error(const char* /*tag*/, int /*context_id*/, const char* /*fmt*/, ...) | ||||
| void ISrsLog::error(const char* /*tag*/, const char* /*context_id*/, const char* /*fmt*/, ...) | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  | @ -70,19 +70,19 @@ ISrsThreadContext::~ISrsThreadContext() | |||
| { | ||||
| } | ||||
| 
 | ||||
| int ISrsThreadContext::generate_id() | ||||
| std::string ISrsThreadContext::generate_id() | ||||
| { | ||||
|     return 0; | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| int ISrsThreadContext::get_id() | ||||
| std::string ISrsThreadContext::get_id() | ||||
| { | ||||
|     return 0; | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| int ISrsThreadContext::set_id(int /*v*/) | ||||
| std::string ISrsThreadContext::set_id(std::string /*v*/) | ||||
| { | ||||
|     return 0; | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ | |||
| 
 | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <srs_kernel_consts.hpp> | ||||
| 
 | ||||
|  | @ -64,16 +65,16 @@ public: | |||
|     virtual void reopen(); | ||||
| public: | ||||
|     // The log for verbose, very verbose information.
 | ||||
|     virtual void verbose(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void verbose(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     // The log for debug, detail information.
 | ||||
|     virtual void info(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void info(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     // The log for trace, important information.
 | ||||
|     virtual void trace(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void trace(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     // The log for warn, warn is something should take attention, but not a error.
 | ||||
|     virtual void warn(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void warn(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     // The log for error, something error occur, do something about the error, ie. close the connection,
 | ||||
|     // but we will donot abort the program.
 | ||||
|     virtual void error(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void error(const char* tag, const char* context_id, const char* fmt, ...); | ||||
| }; | ||||
| 
 | ||||
| // The context id manager to identify context, for instance, the green-thread.
 | ||||
|  | @ -89,12 +90,12 @@ public: | |||
|     virtual ~ISrsThreadContext(); | ||||
| public: | ||||
|     // Generate the id for current context.
 | ||||
|     virtual int generate_id(); | ||||
|     virtual std::string generate_id(); | ||||
|     // Get the generated id of current context.
 | ||||
|     virtual int get_id(); | ||||
|     virtual std::string get_id(); | ||||
|     // Set the id of current context.
 | ||||
|     // @return the previous id value; 0 if no context.
 | ||||
|     virtual int set_id(int v); | ||||
|     virtual std::string set_id(std::string v); | ||||
| }; | ||||
| 
 | ||||
| // @global User must provides a log object
 | ||||
|  | @ -107,25 +108,25 @@ extern ISrsThreadContext* _srs_context; | |||
| // Use __FUNCTION__ to print c method
 | ||||
| // Use __PRETTY_FUNCTION__ to print c++ class:method
 | ||||
| #if 1 | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(NULL, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(NULL, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(NULL, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(NULL, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(NULL, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
| #endif | ||||
| #if 0 | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(__FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(__FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(__FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(__FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(__FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
| #endif | ||||
| #if 0 | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | ||||
|     #define srs_verbose(msg, ...) _srs_log->verbose(__PRETTY_FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_info(msg, ...)    _srs_log->info(__PRETTY_FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_trace(msg, ...)   _srs_log->trace(__PRETTY_FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_warn(msg, ...)    _srs_log->warn(__PRETTY_FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
|     #define srs_error(msg, ...)   _srs_log->error(__PRETTY_FUNCTION__, _srs_context->get_id().c_str(), msg, ##__VA_ARGS__) | ||||
| #endif | ||||
| 
 | ||||
| // TODO: FIXME: Add more verbose and info logs.
 | ||||
|  |  | |||
|  | @ -119,17 +119,11 @@ SrsRtpHeader::~SrsRtpHeader() | |||
| { | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf, const SrsRtpHeaderExtensionMap *extension_map) | ||||
| { | ||||
| srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf) { | ||||
|     srs_error_t err = srs_success; | ||||
|     uint16_t profile_id = buf->read_2bytes(); | ||||
|     extension_length = buf->read_2bytes(); | ||||
| 
 | ||||
|     if (!extension_map) { | ||||
|         buf->skip(extension_length * 4); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     // @see: https://tools.ietf.org/html/rfc5285#section-4.2
 | ||||
|     if (profile_id == 0xBEDE) { | ||||
|         uint32_t xlen = extension_length * 4; | ||||
|  | @ -151,7 +145,7 @@ srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf, const SrsRtpHeaderExte | |||
|             uint8_t id = (id_len & 0xF0) >> 4; | ||||
|             uint8_t len = (id_len & 0x0F); | ||||
|              | ||||
|             SrsRtpExtensionType xtype = extension_map->get_type(id); | ||||
|             SrsRtpExtensionType xtype = extension_map_.get_type(id); | ||||
|             if (xtype == kRtpExtensionTransportSequenceNumber) { | ||||
|                 //   0                   1                   2
 | ||||
|                 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
 | ||||
|  | @ -176,7 +170,7 @@ srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf, const SrsRtpHeaderExte | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtpHeader::decode(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* extmap) | ||||
| srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|  | @ -231,7 +225,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* | |||
|         |                        header extension                       | | ||||
|         |                             ....                              | | ||||
|         */ | ||||
|         if ((err = parse_extension(buf, extmap)) != srs_success) { | ||||
|         if ((err = parse_extension(buf)) != srs_success) { | ||||
|             return srs_error_wrap(err, "fail to parse extension"); | ||||
|         } | ||||
|     } | ||||
|  | @ -298,6 +292,12 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* buf) | |||
| 
 | ||||
|     return err; | ||||
| } | ||||
| void SrsRtpHeader::set_extensions(const SrsRtpHeaderExtensionMap* extmap) | ||||
| { | ||||
|     if (extmap) { | ||||
|         extension_map_ = *extmap; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtpHeader::get_twcc_sequence_number(uint16_t& twcc_sn) | ||||
| { | ||||
|  | @ -449,6 +449,11 @@ SrsRtpPacket2* SrsRtpPacket2::copy() | |||
|     return cp; | ||||
| } | ||||
| 
 | ||||
| void SrsRtpPacket2::set_rtp_header_extensions(const SrsRtpHeaderExtensionMap* extmap) | ||||
| { | ||||
|     return header.set_extensions(extmap); | ||||
| } | ||||
| 
 | ||||
| int SrsRtpPacket2::nb_bytes() | ||||
| { | ||||
|     if (!cached_payload_size) { | ||||
|  | @ -482,11 +487,11 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) | |||
|     return err; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* extmap) | ||||
| srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|     if ((err = header.decode(buf, extmap)) != srs_success) { | ||||
|     if ((err = header.decode(buf)) != srs_success) { | ||||
|         return srs_error_wrap(err, "rtp header"); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -140,14 +140,15 @@ private: | |||
|     uint32_t ssrc; | ||||
|     uint32_t csrc[15]; | ||||
|     uint16_t extension_length; | ||||
|     SrsRtpHeaderExtensionMap extension_map_; | ||||
|     SrsRtpHeaderExtension header_extension; | ||||
| public: | ||||
|     SrsRtpHeader(); | ||||
|     virtual ~SrsRtpHeader(); | ||||
| private: | ||||
|     srs_error_t parse_extension(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* extension_map); | ||||
|     srs_error_t parse_extension(SrsBuffer* buf); | ||||
| public: | ||||
|     virtual srs_error_t decode(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* extmap = NULL); | ||||
|     virtual srs_error_t decode(SrsBuffer* buf); | ||||
|     virtual srs_error_t encode(SrsBuffer* buf); | ||||
|     virtual int nb_bytes(); | ||||
| public: | ||||
|  | @ -163,6 +164,7 @@ public: | |||
|     uint32_t get_ssrc() const; | ||||
|     void set_padding(uint8_t v); | ||||
|     uint8_t get_padding() const; | ||||
|     void set_extensions(const SrsRtpHeaderExtensionMap* extmap); | ||||
|     srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); | ||||
| }; | ||||
| 
 | ||||
|  | @ -219,12 +221,13 @@ public: | |||
|     bool is_audio(); | ||||
|     // Copy the RTP packet.
 | ||||
|     SrsRtpPacket2* copy(); | ||||
|     // Set RTP header extensions for encoding or decoding header extension
 | ||||
|     void set_rtp_header_extensions(const SrsRtpHeaderExtensionMap* extmap); | ||||
| // interface ISrsEncoder
 | ||||
| public: | ||||
|     virtual int nb_bytes(); | ||||
|     virtual srs_error_t encode(SrsBuffer* buf); | ||||
|     // TODO: FIXME: Should follow interface ISrsEncoder.
 | ||||
|     virtual srs_error_t decode(SrsBuffer* buf, const SrsRtpHeaderExtensionMap* extmap = NULL); | ||||
|     virtual srs_error_t decode(SrsBuffer* buf); | ||||
| }; | ||||
| 
 | ||||
| // Single payload data.
 | ||||
|  |  | |||
|  | @ -1,416 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2020 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <srs_lib_bandwidth.hpp> | ||||
| 
 | ||||
| // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
 | ||||
| #ifndef _WIN32 | ||||
| #include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <sstream> | ||||
| using namespace std; | ||||
| 
 | ||||
| #include <srs_kernel_error.hpp> | ||||
| #include <srs_rtmp_stack.hpp> | ||||
| #include <srs_rtmp_stack.hpp> | ||||
| #include <srs_core_autofree.hpp> | ||||
| #include <srs_kernel_utility.hpp> | ||||
| #include <srs_protocol_amf0.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * recv bandwidth helper. | ||||
|  */ | ||||
| typedef bool (*_CheckPacketType)(SrsBandwidthPacket* pkt); | ||||
| bool _bandwidth_is_start_play(SrsBandwidthPacket* pkt) | ||||
| { | ||||
|     return pkt->is_start_play(); | ||||
| } | ||||
| bool _bandwidth_is_stop_play(SrsBandwidthPacket* pkt) | ||||
| { | ||||
|     return pkt->is_stop_play(); | ||||
| } | ||||
| bool _bandwidth_is_start_publish(SrsBandwidthPacket* pkt) | ||||
| { | ||||
|     return pkt->is_start_publish(); | ||||
| } | ||||
| bool _bandwidth_is_stop_publish(SrsBandwidthPacket* pkt) | ||||
| { | ||||
|     return pkt->is_stop_publish(); | ||||
| } | ||||
| bool _bandwidth_is_finish(SrsBandwidthPacket* pkt) | ||||
| { | ||||
|     return pkt->is_finish(); | ||||
| } | ||||
| int _srs_expect_bandwidth_packet(SrsRtmpClient* rtmp, _CheckPacketType pfn) | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     while (true) { | ||||
|         SrsCommonMessage* msg = NULL; | ||||
|         SrsBandwidthPacket* pkt = NULL; | ||||
|         if ((err = rtmp->expect_message<SrsBandwidthPacket>(&msg, &pkt)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             return ret; | ||||
|         } | ||||
|         SrsAutoFree(SrsCommonMessage, msg); | ||||
|         SrsAutoFree(SrsBandwidthPacket, pkt); | ||||
|         srs_info("get final message success."); | ||||
|          | ||||
|         if (pfn(pkt)) { | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| int _srs_expect_bandwidth_packet2(SrsRtmpClient* rtmp, _CheckPacketType pfn, SrsBandwidthPacket** ppkt) | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     while (true) { | ||||
|         SrsCommonMessage* msg = NULL; | ||||
|         SrsBandwidthPacket* pkt = NULL; | ||||
|         if ((err = rtmp->expect_message<SrsBandwidthPacket>(&msg, &pkt)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             return ret; | ||||
|         } | ||||
|         SrsAutoFree(SrsCommonMessage, msg); | ||||
|         srs_info("get final message success."); | ||||
|          | ||||
|         if (pfn(pkt)) { | ||||
|             *ppkt = pkt; | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         srs_freep(pkt); | ||||
|     } | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| SrsBandwidthClient::SrsBandwidthClient() | ||||
| { | ||||
|     _rtmp = NULL; | ||||
| } | ||||
| 
 | ||||
| SrsBandwidthClient::~SrsBandwidthClient() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::initialize(SrsRtmpClient* rtmp) | ||||
| { | ||||
|     _rtmp = rtmp; | ||||
|      | ||||
|     return ERROR_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::bandwidth_check( | ||||
|     int64_t* start_time, int64_t* end_time, | ||||
|     int* play_kbps, int* publish_kbps, | ||||
|     int* play_bytes, int* publish_bytes, | ||||
|     int* play_duration, int* publish_duration | ||||
| ) { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|      | ||||
|     *start_time = srsu2ms(srs_update_system_time()); | ||||
|      | ||||
|     // play
 | ||||
|     if ((ret = play_start()) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = play_checking()) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = play_stop()) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     // publish
 | ||||
|     int duration_ms = 0; | ||||
|     int actual_play_kbps = 0; | ||||
|     if ((ret = publish_start(duration_ms, actual_play_kbps)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = publish_checking(duration_ms, actual_play_kbps)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     if ((ret = publish_stop()) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     SrsBandwidthPacket* pkt = NULL; | ||||
|     if ((ret = do_final(&pkt)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     SrsAutoFree(SrsBandwidthPacket, pkt); | ||||
|      | ||||
|     // get data
 | ||||
|     if (true ) { | ||||
|         SrsAmf0Any* prop = NULL; | ||||
|         if ((prop = pkt->data->ensure_property_number("play_kbps")) != NULL) { | ||||
|             *play_kbps = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("publish_kbps")) != NULL) { | ||||
|             *publish_kbps = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("play_bytes")) != NULL) { | ||||
|             *play_bytes = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("publish_bytes")) != NULL) { | ||||
|             *publish_bytes = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("play_time")) != NULL) { | ||||
|             *play_duration = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("publish_time")) != NULL) { | ||||
|             *publish_duration = (int)prop->to_number(); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     *end_time = srsu2ms(srs_update_system_time()); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::play_start() | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_start_play)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     srs_info("BW check recv play begin request."); | ||||
|      | ||||
|     if (true) { | ||||
|         // send start play response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_starting_play(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check start play message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check play begin."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::play_checking() | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::play_stop() | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_stop_play)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     srs_info("BW check recv play stop request."); | ||||
|      | ||||
|     if (true) { | ||||
|         // send stop play response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stopped_play(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check stop play message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check play stop."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::publish_start(int& duration_ms, int& play_kbps) | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if (true) { | ||||
|         SrsBandwidthPacket* pkt = NULL; | ||||
|         if ((ret = _srs_expect_bandwidth_packet2(_rtmp, _bandwidth_is_start_publish, &pkt)) != ERROR_SUCCESS) { | ||||
|             return ret; | ||||
|         } | ||||
|         SrsAutoFree(SrsBandwidthPacket, pkt); | ||||
|          | ||||
|         SrsAmf0Any* prop = NULL; | ||||
|         if ((prop = pkt->data->ensure_property_number("duration_ms")) != NULL) { | ||||
|             duration_ms = (int)prop->to_number(); | ||||
|         } | ||||
|         if ((prop = pkt->data->ensure_property_number("limit_kbps")) != NULL) { | ||||
|             play_kbps = (int)prop->to_number(); | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check recv publish begin request."); | ||||
|      | ||||
|     if (true) { | ||||
|         // send start publish response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_starting_publish(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check start publish message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check publish begin."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::publish_checking(int duration_ms, int play_kbps) | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if (duration_ms <= 0) { | ||||
|         ret = ERROR_RTMP_BWTC_DATA; | ||||
|         srs_error("server must specifies the duration, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     if (play_kbps <= 0) { | ||||
|         ret = ERROR_RTMP_BWTC_DATA; | ||||
|         srs_error("server must specifies the play kbp, ret=%d", ret); | ||||
|         return ret; | ||||
|     } | ||||
|      | ||||
|     int data_count = 1; | ||||
|     int64_t starttime = srsu2ms(srs_update_system_time()); | ||||
|     while (int64_t(srsu2ms(srs_get_system_time()) - starttime) < duration_ms) { | ||||
|         // TODO: FIXME: use shared ptr message.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_publishing(); | ||||
|          | ||||
|         // TODO: FIXME: magic number
 | ||||
|         for (int i = 0; i < data_count; ++i) { | ||||
|             std::stringstream seq; | ||||
|             seq << i; | ||||
|             std::string play_data = "SRS band check data from server's publishing......"; | ||||
|             pkt->data->set(seq.str(), SrsAmf0Any::str(play_data.c_str())); | ||||
|         } | ||||
|         data_count += 2; | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check publish messages failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         // use the play kbps to control the publish
 | ||||
|         int elaps = (int)(srsu2ms(srs_update_system_time()) - starttime); | ||||
|         if (elaps > 0) { | ||||
|             int current_kbps = (int)(_rtmp->get_send_bytes() * 8 / elaps); | ||||
|             while (current_kbps > play_kbps) { | ||||
|                 srs_update_system_time(); | ||||
|                 elaps = (int)(srsu2ms(srs_get_system_time()) - starttime); | ||||
|                 current_kbps = (int)(_rtmp->get_send_bytes() * 8 / elaps); | ||||
|                 usleep(100 * 1000); // TODO: FIXME: magic number.
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check send publish bytes over."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::publish_stop() | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if (true) { | ||||
|         // send start publish response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check stop publish message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW client stop publish request."); | ||||
|      | ||||
|     if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_stop_publish)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     srs_info("BW check recv publish stop request."); | ||||
|      | ||||
|     if (true) { | ||||
|         // send start publish response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stopped_publish(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check stop publish message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check publish stop."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int SrsBandwidthClient::do_final(SrsBandwidthPacket** ppkt) | ||||
| { | ||||
|     int ret = ERROR_SUCCESS; | ||||
|     srs_error_t err = srs_success; | ||||
|      | ||||
|     if ((ret = _srs_expect_bandwidth_packet2(_rtmp, _bandwidth_is_finish, ppkt)) != ERROR_SUCCESS) { | ||||
|         return ret; | ||||
|     } | ||||
|     srs_info("BW check recv finish/report request."); | ||||
|      | ||||
|     if (true) { | ||||
|         // send final response to server.
 | ||||
|         SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_final(); | ||||
|          | ||||
|         if ((err = _rtmp->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|             ret = srs_error_code(err); | ||||
|             srs_freep(err); | ||||
|             srs_error("send bandwidth check final message failed. ret=%d", ret); | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|     srs_info("BW check final."); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,85 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2020 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef SRS_LIB_BANDWIDTH_HPP | ||||
| #define SRS_LIB_BANDWIDTH_HPP | ||||
| 
 | ||||
| #include <srs_core.hpp> | ||||
| 
 | ||||
| class SrsRtmpClient; | ||||
| class SrsBandwidthPacket; | ||||
| 
 | ||||
| /**
 | ||||
|  * bandwith client library for srs-librtmp. | ||||
|  */ | ||||
| class SrsBandwidthClient | ||||
| { | ||||
| private: | ||||
|     SrsRtmpClient* _rtmp; | ||||
| public: | ||||
|     SrsBandwidthClient(); | ||||
|     virtual ~SrsBandwidthClient(); | ||||
| public: | ||||
|     /**
 | ||||
|      * initialize the bandwidth check client. | ||||
|      */ | ||||
|     virtual int initialize(SrsRtmpClient* rtmp); | ||||
|     /**
 | ||||
|      * do bandwidth check. | ||||
|      * | ||||
|      * bandwidth info: | ||||
|      * @param start_time, output the start time, in ms. | ||||
|      * @param end_time, output the end time, in ms. | ||||
|      * @param play_kbps, output the play/download kbps. | ||||
|      * @param publish_kbps, output the publish/upload kbps. | ||||
|      * @param play_bytes, output the play/download bytes. | ||||
|      * @param publish_bytes, output the publish/upload bytes. | ||||
|      * @param play_duration, output the play/download test duration, in ms. | ||||
|      * @param publish_duration, output the publish/upload test duration, in ms. | ||||
|      */ | ||||
|     virtual int bandwidth_check( | ||||
|         int64_t* start_time, int64_t* end_time, | ||||
|         int* play_kbps, int* publish_kbps, | ||||
|         int* play_bytes, int* publish_bytes, | ||||
|         int* play_duration, int* publish_duration); | ||||
| private: | ||||
|     /**
 | ||||
|      * play check/test, downloading bandwidth kbps. | ||||
|      */ | ||||
|     virtual int play_start(); | ||||
|     virtual int play_checking(); | ||||
|     virtual int play_stop(); | ||||
|     /**
 | ||||
|      * publish check/test, publishing bandwidth kbps. | ||||
|      */ | ||||
|     virtual int publish_start(int& duration_ms, int& play_kbps); | ||||
|     virtual int publish_checking(int duration_ms, int play_kbps); | ||||
|     virtual int publish_stop(); | ||||
|     /**
 | ||||
|      * report and final packet | ||||
|      */ | ||||
|     virtual int do_final(SrsBandwidthPacket** ppkt); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | @ -1,486 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2020 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <srs_lib_simple_socket.hpp> | ||||
| 
 | ||||
| #include <netinet/tcp.h> | ||||
| 
 | ||||
| #include <srs_kernel_error.hpp> | ||||
| 
 | ||||
| // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
 | ||||
| #ifndef _WIN32 | ||||
| #define SOCKET_ETIME EWOULDBLOCK | ||||
| #define SOCKET_ECONNRESET ECONNRESET | ||||
| 
 | ||||
| #define SOCKET_ERRNO() errno | ||||
| #define SOCKET_RESET(fd) fd = -1; (void)0 | ||||
| #define SOCKET_CLOSE(fd) \ | ||||
|     if (fd > 0) {\ | ||||
|         ::close(fd); \ | ||||
|         fd = -1; \ | ||||
|     } \ | ||||
|     (void)0 | ||||
| #define SOCKET_VALID(x) (x > 0) | ||||
| #define SOCKET_SETUP() (void)0 | ||||
| #define SOCKET_CLEANUP() (void)0 | ||||
| #else | ||||
| #define SOCKET_ETIME WSAETIMEDOUT | ||||
| #define SOCKET_ECONNRESET WSAECONNRESET | ||||
| #define SOCKET_ERRNO() WSAGetLastError() | ||||
| #define SOCKET_RESET(x) x=INVALID_SOCKET | ||||
| #define SOCKET_CLOSE(x) if(x!=INVALID_SOCKET){::closesocket(x);x=INVALID_SOCKET;} | ||||
| #define SOCKET_VALID(x) (x!=INVALID_SOCKET) | ||||
| #define SOCKET_BUFF(x) ((char*)x) | ||||
| #define SOCKET_SETUP() socket_setup() | ||||
| #define SOCKET_CLEANUP() socket_cleanup() | ||||
| #endif | ||||
| 
 | ||||
| // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
 | ||||
| #ifndef _WIN32 | ||||
| #include <unistd.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <sys/uio.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <errno.h> | ||||
| #include <stdio.h> | ||||
| #include <netdb.h> | ||||
| 
 | ||||
| #include <srs_core_autofree.hpp> | ||||
| #include <srs_kernel_utility.hpp> | ||||
| #include <srs_kernel_consts.hpp> | ||||
| 
 | ||||
| // when io not hijacked, use simple socket, the block sync stream.
 | ||||
| #ifndef SRS_HIJACK_IO | ||||
| struct SrsBlockSyncSocket | ||||
| { | ||||
|     int family; | ||||
|     SOCKET fd; | ||||
|     SOCKET fdv4; | ||||
|     SOCKET fdv6; | ||||
|     // Bytes transmit.
 | ||||
|     int64_t rbytes; | ||||
|     int64_t sbytes; | ||||
|     // The send/recv timeout in ms.
 | ||||
|     int64_t rtm; | ||||
|     int64_t stm; | ||||
|      | ||||
|     SrsBlockSyncSocket() { | ||||
|         family = AF_UNSPEC; | ||||
|         stm = rtm = SRS_UTIME_NO_TIMEOUT; | ||||
|         rbytes = sbytes = 0; | ||||
|          | ||||
|         SOCKET_RESET(fd); | ||||
|         SOCKET_RESET(fdv4); | ||||
|         SOCKET_RESET(fdv6); | ||||
|         SOCKET_SETUP(); | ||||
|     } | ||||
| 
 | ||||
|     virtual ~SrsBlockSyncSocket() { | ||||
|         if (SOCKET_VALID(fd)) { | ||||
|             SOCKET_CLOSE(fd); | ||||
|         } | ||||
|         if (SOCKET_VALID(fdv4)) { | ||||
|             SOCKET_CLOSE(fdv4); | ||||
|         } | ||||
|         if (SOCKET_VALID(fdv6)) { | ||||
|             SOCKET_CLOSE(fdv6); | ||||
|         } | ||||
|         SOCKET_CLEANUP(); | ||||
|     } | ||||
| }; | ||||
| srs_hijack_io_t srs_hijack_io_create() | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = new SrsBlockSyncSocket(); | ||||
|     return skt; | ||||
| } | ||||
| void srs_hijack_io_destroy(srs_hijack_io_t ctx) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|     srs_freep(skt); | ||||
| } | ||||
| int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
| 
 | ||||
|     skt->family = AF_UNSPEC; | ||||
|     skt->fdv4 = ::socket(AF_INET, SOCK_STREAM, 0); | ||||
|     skt->fdv6 = ::socket(AF_INET6, SOCK_STREAM, 0); | ||||
|     if (!SOCKET_VALID(skt->fdv4) && !SOCKET_VALID(skt->fdv4)) { | ||||
|         return ERROR_SOCKET_CREATE; | ||||
|     } | ||||
| 
 | ||||
|     // No TCP cache.
 | ||||
|     int v = 1; | ||||
|     setsockopt(skt->fdv4, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); | ||||
|     setsockopt(skt->fdv6, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); | ||||
| 
 | ||||
|     return ERROR_SUCCESS; | ||||
| } | ||||
| int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
| 
 | ||||
|     char sport[8]; | ||||
|     snprintf(sport, sizeof(sport), "%d", port); | ||||
|      | ||||
|     addrinfo hints; | ||||
|     memset(&hints, 0, sizeof(hints)); | ||||
|     hints.ai_family   = AF_UNSPEC; | ||||
|     hints.ai_socktype = SOCK_STREAM; | ||||
|      | ||||
|     addrinfo* r  = NULL; | ||||
|     SrsAutoFree(addrinfo, r); | ||||
|     if(getaddrinfo(server_ip, sport, (const addrinfo*)&hints, &r)) { | ||||
|         return ERROR_SOCKET_CONNECT; | ||||
|     } | ||||
| 
 | ||||
|     skt->family = r->ai_family; | ||||
|     if (r->ai_family == AF_INET6) { | ||||
|         skt->fd = skt->fdv6; | ||||
|         SOCKET_RESET(skt->fdv6); | ||||
|     } else { | ||||
|         skt->fd = skt->fdv4; | ||||
|         SOCKET_RESET(skt->fdv4); | ||||
|     } | ||||
| 
 | ||||
|     if(::connect(skt->fd, r->ai_addr, r->ai_addrlen) < 0){ | ||||
|         return ERROR_SOCKET_CONNECT; | ||||
|     } | ||||
|      | ||||
|     return ERROR_SUCCESS; | ||||
| } | ||||
| int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|      | ||||
|     int ret = ERROR_SUCCESS; | ||||
|      | ||||
|     ssize_t nb_read = ::recv(skt->fd, (char*)buf, size, 0); | ||||
|      | ||||
|     if (nread) { | ||||
|         *nread = nb_read; | ||||
|     } | ||||
| 
 | ||||
|     // On success a non-negative integer indicating the number of bytes actually read is returned
 | ||||
|     // (a value of 0 means the network connection is closed or end of file is reached).
 | ||||
|     if (nb_read <= 0) { | ||||
|         if (nb_read < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||||
|             return ERROR_SOCKET_TIMEOUT; | ||||
|         } | ||||
|          | ||||
|         if (nb_read == 0) { | ||||
|             errno = SOCKET_ECONNRESET; | ||||
|         } | ||||
|          | ||||
|         return ERROR_SOCKET_READ; | ||||
|     } | ||||
|      | ||||
|     skt->rbytes += nb_read; | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| int srs_hijack_io_set_recv_timeout(srs_hijack_io_t ctx, int64_t tm) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     DWORD tv = (DWORD)(tm); | ||||
| 
 | ||||
|     // To convert tv to const char* to make VS2015 happy.
 | ||||
|     if (setsockopt(skt->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { | ||||
|         return SOCKET_ERRNO(); | ||||
|     } | ||||
| #else | ||||
|     // The default for this option is zero,
 | ||||
|     // which indicates that a receive operation shall not time out.
 | ||||
|     int32_t sec = 0; | ||||
|     int32_t usec = 0; | ||||
|      | ||||
|     if (tm != SRS_UTIME_NO_TIMEOUT) { | ||||
|         sec = (int32_t)(tm / 1000); | ||||
|         usec = (int32_t)((tm % 1000)*1000); | ||||
|     } | ||||
|      | ||||
|     struct timeval tv = { sec , usec }; | ||||
|     if (setsockopt(skt->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { | ||||
|         return SOCKET_ERRNO(); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     skt->rtm = tm; | ||||
| 
 | ||||
|     return ERROR_SUCCESS; | ||||
| } | ||||
| int64_t srs_hijack_io_get_recv_timeout(srs_hijack_io_t ctx) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|     return skt->rtm; | ||||
| } | ||||
| int64_t srs_hijack_io_get_recv_bytes(srs_hijack_io_t ctx) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|     return skt->rbytes; | ||||
| } | ||||
| int srs_hijack_io_set_send_timeout(srs_hijack_io_t ctx, int64_t tm) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     DWORD tv = (DWORD)(tm); | ||||
| 
 | ||||
|     // To convert tv to const char* to make VS2015 happy.
 | ||||
|     if (setsockopt(skt->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { | ||||
|         return SOCKET_ERRNO(); | ||||
|     } | ||||
| #else | ||||
|     // The default for this option is zero,
 | ||||
|     // which indicates that a receive operation shall not time out.
 | ||||
|     int32_t sec = 0; | ||||
|     int32_t usec = 0; | ||||
| 
 | ||||
|     if (tm != SRS_UTIME_NO_TIMEOUT) { | ||||
|         sec = (int32_t)(tm / 1000); | ||||
|         usec = (int32_t)((tm % 1000)*1000); | ||||
|     } | ||||
| 
 | ||||
|     struct timeval tv = { sec , usec }; | ||||
|     if (setsockopt(skt->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { | ||||
|         return SOCKET_ERRNO(); | ||||
|     } | ||||
| #endif | ||||
|      | ||||
|     skt->stm = tm; | ||||
|      | ||||
|     return ERROR_SUCCESS; | ||||
| } | ||||
| int64_t srs_hijack_io_get_send_timeout(srs_hijack_io_t ctx) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|     return skt->stm; | ||||
| } | ||||
| int64_t srs_hijack_io_get_send_bytes(srs_hijack_io_t ctx) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|     return skt->sbytes; | ||||
| } | ||||
| int srs_hijack_io_writev(srs_hijack_io_t ctx, const iovec *iov, int iov_size, ssize_t* nwrite) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|      | ||||
|     int ret = ERROR_SUCCESS; | ||||
|      | ||||
|     ssize_t nb_write = ::writev(skt->fd, iov, iov_size); | ||||
|      | ||||
|     if (nwrite) { | ||||
|         *nwrite = nb_write; | ||||
|     } | ||||
|      | ||||
|     // On  success,  the  readv()  function  returns the number of bytes read;
 | ||||
|     // the writev() function returns the number of bytes written.  On error, -1 is
 | ||||
|     // returned, and errno is set appropriately.
 | ||||
|     if (nb_write <= 0) { | ||||
|         // @see https://github.com/ossrs/srs/issues/200
 | ||||
|         if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||||
|             return ERROR_SOCKET_TIMEOUT; | ||||
|         } | ||||
|          | ||||
|         return ERROR_SOCKET_WRITE; | ||||
|     } | ||||
| 
 | ||||
|     skt->sbytes += nb_write; | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| int srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t tm) | ||||
| { | ||||
|     return tm == SRS_UTIME_NO_TIMEOUT; | ||||
| } | ||||
| int srs_hijack_io_read_fully(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|      | ||||
|     int ret = ERROR_SUCCESS; | ||||
|      | ||||
|     size_t left = size; | ||||
|     ssize_t nb_read = 0; | ||||
|      | ||||
|     while (left > 0) { | ||||
|         char* this_buf = (char*)buf + nb_read; | ||||
|         ssize_t this_nread; | ||||
|          | ||||
|         if ((ret = srs_hijack_io_read(ctx, this_buf, left, &this_nread)) != ERROR_SUCCESS) { | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|         nb_read += this_nread; | ||||
|         left -= (size_t)this_nread; | ||||
|     } | ||||
|      | ||||
|     if (nread) { | ||||
|         *nread = nb_read; | ||||
|     } | ||||
|     skt->rbytes += nb_read; | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| int srs_hijack_io_write(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nwrite) | ||||
| { | ||||
|     SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||||
|      | ||||
|     int ret = ERROR_SUCCESS; | ||||
|      | ||||
|     ssize_t nb_write = ::send(skt->fd, (char*)buf, size, 0); | ||||
|      | ||||
|     if (nwrite) { | ||||
|         *nwrite = nb_write; | ||||
|     } | ||||
|      | ||||
|     if (nb_write <= 0) { | ||||
|         // @see https://github.com/ossrs/srs/issues/200
 | ||||
|         if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||||
|             return ERROR_SOCKET_TIMEOUT; | ||||
|         } | ||||
|          | ||||
|         return ERROR_SOCKET_WRITE; | ||||
|     } | ||||
|      | ||||
|     skt->sbytes += nb_write; | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| SimpleSocketStream::SimpleSocketStream() | ||||
| { | ||||
|     io = srs_hijack_io_create(); | ||||
| } | ||||
| 
 | ||||
| SimpleSocketStream::~SimpleSocketStream() | ||||
| { | ||||
|     if (io) { | ||||
|         srs_hijack_io_destroy(io); | ||||
|         io = NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| srs_hijack_io_t SimpleSocketStream::hijack_io() | ||||
| { | ||||
|     return io; | ||||
| } | ||||
| 
 | ||||
| int SimpleSocketStream::create_socket(srs_rtmp_t owner) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_create_socket(io, owner); | ||||
| } | ||||
| 
 | ||||
| int SimpleSocketStream::connect(const char* server_ip, int port) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_connect(io, server_ip, port); | ||||
| } | ||||
| 
 | ||||
| // Interface ISrsReader
 | ||||
| srs_error_t SimpleSocketStream::read(void* buf, size_t size, ssize_t* nread) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     int ret = srs_hijack_io_read(io, buf, size, nread); | ||||
|     if (ret != ERROR_SUCCESS) { | ||||
|         return srs_error_new(ret, "read"); | ||||
|     } | ||||
|     return srs_success; | ||||
| } | ||||
| 
 | ||||
| // Interface ISrsProtocolReader
 | ||||
| void SimpleSocketStream::set_recv_timeout(srs_utime_t tm) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     srs_hijack_io_set_recv_timeout(io, srsu2ms(tm)); | ||||
| } | ||||
| 
 | ||||
| srs_utime_t SimpleSocketStream::get_recv_timeout() | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_get_recv_timeout(io) * SRS_UTIME_MILLISECONDS; | ||||
| } | ||||
| 
 | ||||
| int64_t SimpleSocketStream::get_recv_bytes() | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_get_recv_bytes(io); | ||||
| } | ||||
| 
 | ||||
| // Interface ISrsProtocolWriter
 | ||||
| void SimpleSocketStream::set_send_timeout(srs_utime_t tm) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     srs_hijack_io_set_send_timeout(io, srsu2ms(tm)); | ||||
| } | ||||
| 
 | ||||
| srs_utime_t SimpleSocketStream::get_send_timeout() | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_get_send_timeout(io) * SRS_UTIME_MILLISECONDS; | ||||
| } | ||||
| 
 | ||||
| int64_t SimpleSocketStream::get_send_bytes() | ||||
| { | ||||
|     srs_assert(io); | ||||
|     return srs_hijack_io_get_send_bytes(io); | ||||
| } | ||||
| 
 | ||||
| srs_error_t SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     int ret = srs_hijack_io_writev(io, iov, iov_size, nwrite); | ||||
|     if (ret != ERROR_SUCCESS) { | ||||
|         return srs_error_new(ret, "read"); | ||||
|     } | ||||
|     return srs_success; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SimpleSocketStream::read_fully(void* buf, size_t size, ssize_t* nread) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     int ret = srs_hijack_io_read_fully(io, buf, size, nread); | ||||
|     if (ret != ERROR_SUCCESS) { | ||||
|         return srs_error_new(ret, "read"); | ||||
|     } | ||||
|     return srs_success; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SimpleSocketStream::write(void* buf, size_t size, ssize_t* nwrite) | ||||
| { | ||||
|     srs_assert(io); | ||||
|     int ret = srs_hijack_io_write(io, buf, size, nwrite); | ||||
|     if (ret != ERROR_SUCCESS) { | ||||
|         return srs_error_new(ret, "read"); | ||||
|     } | ||||
|     return srs_success; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,73 +0,0 @@ | |||
| /**
 | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2013-2020 Winlin | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef SRS_LIB_SIMPLE_SOCKET_HPP | ||||
| #define SRS_LIB_SIMPLE_SOCKET_HPP | ||||
| 
 | ||||
| #include <srs_core.hpp> | ||||
| 
 | ||||
| #include <srs_protocol_io.hpp> | ||||
| #include <srs_librtmp.hpp> | ||||
| 
 | ||||
| // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
 | ||||
| #ifndef _WIN32 | ||||
| #define SOCKET int | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * simple socket stream, | ||||
|  * use tcp socket, sync block mode, for client like srs-librtmp. | ||||
|  */ | ||||
| class SimpleSocketStream : public ISrsProtocolReadWriter | ||||
| { | ||||
| private: | ||||
|     srs_hijack_io_t io; | ||||
| public: | ||||
|     SimpleSocketStream(); | ||||
|     virtual ~SimpleSocketStream(); | ||||
| public: | ||||
|     virtual srs_hijack_io_t hijack_io(); | ||||
|     virtual int create_socket(srs_rtmp_t owner); | ||||
|     virtual int connect(const char* server, int port); | ||||
| // Interface ISrsReader
 | ||||
| public: | ||||
|     virtual srs_error_t read(void* buf, size_t size, ssize_t* nread); | ||||
| // Interface ISrsProtocolReader
 | ||||
| public: | ||||
|     virtual void set_recv_timeout(srs_utime_t tm); | ||||
|     virtual srs_utime_t get_recv_timeout(); | ||||
|     virtual int64_t get_recv_bytes(); | ||||
| // Interface ISrsProtocolWriter
 | ||||
| public: | ||||
|     virtual void set_send_timeout(srs_utime_t tm); | ||||
|     virtual srs_utime_t get_send_timeout(); | ||||
|     virtual int64_t get_send_bytes(); | ||||
|     virtual srs_error_t writev(const iovec *iov, int iov_size, ssize_t* nwrite); | ||||
| // Interface ISrsProtocolReadWriter
 | ||||
| public: | ||||
|     virtual srs_error_t read_fully(void* buf, size_t size, ssize_t* nread); | ||||
|     virtual srs_error_t write(void* buf, size_t size, ssize_t* nwrite); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -490,7 +490,7 @@ public: | |||
|     // then the rest id is 100.
 | ||||
|     // @param pattern the handler pattern which will serve the request.
 | ||||
|     // @return the REST id; -1 if not matched.
 | ||||
|     virtual int parse_rest_id(std::string pattern) = 0; | ||||
|     virtual std::string parse_rest_id(std::string pattern) = 0; | ||||
| public: | ||||
|     // The left all data is chunked body, the infinite chunked mode,
 | ||||
|     // which is chunked encoding without chunked header.
 | ||||
|  |  | |||
|  | @ -2453,7 +2453,7 @@ srs_error_t SrsRtmpServer::response_connect_app(SrsRequest *req, const char* ser | |||
|     } | ||||
|     // for edge to directly get the id of client.
 | ||||
|     data->set("srs_pid", SrsAmf0Any::number(getpid())); | ||||
|     data->set("srs_id", SrsAmf0Any::number(_srs_context->get_id())); | ||||
|     data->set("srs_id", SrsAmf0Any::str(_srs_context->get_id().c_str())); | ||||
|      | ||||
|     if ((err = protocol->send_and_free_packet(pkt, 0)) != srs_success) { | ||||
|         return srs_error_wrap(err, "send connect app response"); | ||||
|  |  | |||
|  | @ -535,19 +535,19 @@ string SrsHttpMessage::ext() | |||
|     return _ext; | ||||
| } | ||||
| 
 | ||||
| int SrsHttpMessage::parse_rest_id(string pattern) | ||||
| std::string SrsHttpMessage::parse_rest_id(string pattern) | ||||
| { | ||||
|     string p = _uri->get_path(); | ||||
|     if (p.length() <= pattern.length()) { | ||||
|         return -1; | ||||
|         return ""; | ||||
|     } | ||||
|      | ||||
|     string id = p.substr((int)pattern.length()); | ||||
|     if (!id.empty()) { | ||||
|         return ::atoi(id.c_str()); | ||||
|         return id; | ||||
|     } | ||||
|      | ||||
|     return -1; | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| srs_error_t SrsHttpMessage::enter_infinite_chunked() | ||||
|  | @ -172,7 +172,7 @@ public: | |||
|     virtual std::string query(); | ||||
|     virtual std::string ext(); | ||||
|     // Get the RESTful matched id.
 | ||||
|     virtual int parse_rest_id(std::string pattern); | ||||
|     virtual std::string parse_rest_id(std::string pattern); | ||||
| public: | ||||
|     virtual srs_error_t enter_infinite_chunked(); | ||||
| public: | ||||
|  | @ -26,6 +26,7 @@ | |||
| #include <stdarg.h> | ||||
| #include <sys/time.h> | ||||
| #include <unistd.h> | ||||
| #include <sstream> | ||||
| using namespace std; | ||||
| 
 | ||||
| #include <srs_kernel_error.hpp> | ||||
|  | @ -41,29 +42,31 @@ SrsThreadContext::~SrsThreadContext() | |||
| { | ||||
| } | ||||
| 
 | ||||
| int SrsThreadContext::generate_id() | ||||
| string SrsThreadContext::generate_id() | ||||
| { | ||||
|     static int id = 0; | ||||
| 
 | ||||
|     if (id == 0) { | ||||
|         id = (100 + ((uint32_t)(int64_t)this)%1000); | ||||
|     } | ||||
|      | ||||
|     int gid = id++; | ||||
|     cache[srs_thread_self()] = gid; | ||||
|     return gid; | ||||
| 
 | ||||
|     stringstream ss; | ||||
|     ss << gid; | ||||
|     cache[srs_thread_self()] = ss.str(); | ||||
|     return ss.str(); | ||||
| } | ||||
| 
 | ||||
| int SrsThreadContext::get_id() | ||||
| string SrsThreadContext::get_id() | ||||
| { | ||||
|     return cache[srs_thread_self()]; | ||||
| } | ||||
| 
 | ||||
| int SrsThreadContext::set_id(int v) | ||||
| string SrsThreadContext::set_id(string v) | ||||
| { | ||||
|     srs_thread_t self = srs_thread_self(); | ||||
|      | ||||
|     int ov = 0; | ||||
|     string ov; | ||||
|     if (cache.find(self) != cache.end()) { | ||||
|         ov = cache[self]; | ||||
|     } | ||||
|  | @ -76,7 +79,7 @@ int SrsThreadContext::set_id(int v) | |||
| void SrsThreadContext::clear_cid() | ||||
| { | ||||
|     srs_thread_t self = srs_thread_self(); | ||||
|     std::map<srs_thread_t, int>::iterator it = cache.find(self); | ||||
|     std::map<srs_thread_t, string>::iterator it = cache.find(self); | ||||
|     if (it != cache.end()) { | ||||
|         cache.erase(it); | ||||
|     } | ||||
|  | @ -105,7 +108,7 @@ void SrsConsoleLog::reopen() | |||
| { | ||||
| } | ||||
| 
 | ||||
| void SrsConsoleLog::verbose(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsConsoleLog::verbose(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelVerbose) { | ||||
|         return; | ||||
|  | @ -125,7 +128,7 @@ void SrsConsoleLog::verbose(const char* tag, int context_id, const char* fmt, .. | |||
|     fprintf(stdout, "%s\n", buffer); | ||||
| } | ||||
| 
 | ||||
| void SrsConsoleLog::info(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsConsoleLog::info(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelInfo) { | ||||
|         return; | ||||
|  | @ -145,7 +148,7 @@ void SrsConsoleLog::info(const char* tag, int context_id, const char* fmt, ...) | |||
|     fprintf(stdout, "%s\n", buffer); | ||||
| } | ||||
| 
 | ||||
| void SrsConsoleLog::trace(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsConsoleLog::trace(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelTrace) { | ||||
|         return; | ||||
|  | @ -165,7 +168,7 @@ void SrsConsoleLog::trace(const char* tag, int context_id, const char* fmt, ...) | |||
|     fprintf(stdout, "%s\n", buffer); | ||||
| } | ||||
| 
 | ||||
| void SrsConsoleLog::warn(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsConsoleLog::warn(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelWarn) { | ||||
|         return; | ||||
|  | @ -185,7 +188,7 @@ void SrsConsoleLog::warn(const char* tag, int context_id, const char* fmt, ...) | |||
|     fprintf(stderr, "%s\n", buffer); | ||||
| } | ||||
| 
 | ||||
| void SrsConsoleLog::error(const char* tag, int context_id, const char* fmt, ...) | ||||
| void SrsConsoleLog::error(const char* tag, const char* context_id, const char* fmt, ...) | ||||
| { | ||||
|     if (level > SrsLogLevelError) { | ||||
|         return; | ||||
|  | @ -211,7 +214,7 @@ void SrsConsoleLog::error(const char* tag, int context_id, const char* fmt, ...) | |||
| } | ||||
| // LCOV_EXCL_STOP
 | ||||
| 
 | ||||
| bool srs_log_header(char* buffer, int size, bool utc, bool dangerous, const char* tag, int cid, const char* level, int* psize) | ||||
| bool srs_log_header(char* buffer, int size, bool utc, bool dangerous, const char* tag, const char* cid, const char* level, int* psize) | ||||
| { | ||||
|     // clock time
 | ||||
|     timeval tv; | ||||
|  | @ -235,24 +238,24 @@ bool srs_log_header(char* buffer, int size, bool utc, bool dangerous, const char | |||
|     if (dangerous) { | ||||
|         if (tag) { | ||||
|             written = snprintf(buffer, size, | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d][%d] ", | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%s][%d] ", | ||||
|                 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), | ||||
|                 level, tag, getpid(), cid, errno); | ||||
|         } else { | ||||
|             written = snprintf(buffer, size, | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d][%d] ", | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%s][%d] ", | ||||
|                 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), | ||||
|                 level, getpid(), cid, errno); | ||||
|         } | ||||
|     } else { | ||||
|         if (tag) { | ||||
|             written = snprintf(buffer, size, | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ", | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%s] ", | ||||
|                 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), | ||||
|                 level, tag, getpid(), cid); | ||||
|         } else { | ||||
|             written = snprintf(buffer, size, | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ", | ||||
|                 "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%s] ", | ||||
|                 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), | ||||
|                 level, getpid(), cid); | ||||
|         } | ||||
|  | @ -27,6 +27,7 @@ | |||
| #include <srs_core.hpp> | ||||
| 
 | ||||
| #include <map> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <srs_service_st.hpp> | ||||
| #include <srs_kernel_log.hpp> | ||||
|  | @ -36,14 +37,14 @@ | |||
| class SrsThreadContext : public ISrsThreadContext | ||||
| { | ||||
| private: | ||||
|     std::map<srs_thread_t, int> cache; | ||||
|     std::map<srs_thread_t, std::string> cache; | ||||
| public: | ||||
|     SrsThreadContext(); | ||||
|     virtual ~SrsThreadContext(); | ||||
| public: | ||||
|     virtual int generate_id(); | ||||
|     virtual int get_id(); | ||||
|     virtual int set_id(int v); | ||||
|     virtual std::string generate_id(); | ||||
|     virtual std::string get_id(); | ||||
|     virtual std::string set_id(std::string v); | ||||
| public: | ||||
|     virtual void clear_cid(); | ||||
| }; | ||||
|  | @ -63,11 +64,11 @@ public: | |||
| public: | ||||
|     virtual srs_error_t initialize(); | ||||
|     virtual void reopen(); | ||||
|     virtual void verbose(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void info(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void trace(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void warn(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void error(const char* tag, int context_id, const char* fmt, ...); | ||||
|     virtual void verbose(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void info(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void trace(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void warn(const char* tag, const char* context_id, const char* fmt, ...); | ||||
|     virtual void error(const char* tag, const char* context_id, const char* fmt, ...); | ||||
| }; | ||||
| 
 | ||||
| // Generate the log header.
 | ||||
|  | @ -75,6 +76,6 @@ public: | |||
| // @param utc Whether use UTC time format in the log header.
 | ||||
| // @param psize Output the actual header size.
 | ||||
| // @remark It's a internal API.
 | ||||
| bool srs_log_header(char* buffer, int size, bool utc, bool dangerous, const char* tag, int cid, const char* level, int* psize); | ||||
| bool srs_log_header(char* buffer, int size, bool utc, bool dangerous, const char* tag, const char* cid, const char* level, int* psize); | ||||
| 
 | ||||
| #endif | ||||
|  | @ -122,7 +122,7 @@ srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug) | |||
|     data->set("srs_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); | ||||
|     // for edge to directly get the id of client.
 | ||||
|     data->set("srs_pid", SrsAmf0Any::number(getpid())); | ||||
|     data->set("srs_id", SrsAmf0Any::number(_srs_context->get_id())); | ||||
|     data->set("srs_id", SrsAmf0Any::str(_srs_context->get_id().c_str())); | ||||
|      | ||||
|     // local ip of edge
 | ||||
|     data->set("srs_server_ip", SrsAmf0Any::str(local_ip.c_str())); | ||||
|  | @ -214,7 +214,7 @@ srs_error_t do_srs_tcp_listen(int fd, addrinfo* r, srs_netfd_t* pfd) | |||
|         return srs_error_wrap(err, "set reuseport"); | ||||
|     } | ||||
| 
 | ||||
|     if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { | ||||
|     if (::bind(fd, r->ai_addr, r->ai_addrlen) == -1) { | ||||
|         return srs_error_new(ERROR_SOCKET_BIND, "bind"); | ||||
|     } | ||||
| 
 | ||||
|  | @ -279,7 +279,7 @@ srs_error_t do_srs_udp_listen(int fd, addrinfo* r, srs_netfd_t* pfd) | |||
|         return srs_error_wrap(err, "set reuseport"); | ||||
|     } | ||||
| 
 | ||||
|     if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { | ||||
|     if (::bind(fd, r->ai_addr, r->ai_addrlen) == -1) { | ||||
|         return srs_error_new(ERROR_SOCKET_BIND, "bind"); | ||||
|     } | ||||
| 
 | ||||
|  | @ -129,3 +129,11 @@ VOID TEST(SampleTest, FastSampleMacrosTest) | |||
|     EXPECT_NEAR(10, 15, 5); | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StringEQTest) | ||||
| { | ||||
|     string str = "100"; | ||||
|     EXPECT_TRUE("100" == str); | ||||
|     EXPECT_EQ("100", str); | ||||
|     EXPECT_STREQ("100", str.c_str()); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ VOID TEST(AppCoroutineTest, Dummy) | |||
|     SrsDummyCoroutine dc; | ||||
| 
 | ||||
|     if (true) { | ||||
|         EXPECT_EQ(0, dc.cid()); | ||||
|         EXPECT_EQ("", dc.cid()); | ||||
| 
 | ||||
|         srs_error_t err = dc.pull(); | ||||
|         EXPECT_TRUE(err != srs_success); | ||||
|  | @ -52,7 +52,7 @@ VOID TEST(AppCoroutineTest, Dummy) | |||
|     if (true) { | ||||
|         dc.stop(); | ||||
| 
 | ||||
|         EXPECT_EQ(0, dc.cid()); | ||||
|         EXPECT_EQ("", dc.cid()); | ||||
| 
 | ||||
|         srs_error_t err = dc.pull(); | ||||
|         EXPECT_TRUE(err != srs_success); | ||||
|  | @ -68,7 +68,7 @@ VOID TEST(AppCoroutineTest, Dummy) | |||
|     if (true) { | ||||
|         dc.interrupt(); | ||||
| 
 | ||||
|         EXPECT_EQ(0, dc.cid()); | ||||
|         EXPECT_EQ("", dc.cid()); | ||||
| 
 | ||||
|         srs_error_t err = dc.pull(); | ||||
|         EXPECT_TRUE(err != srs_success); | ||||
|  | @ -88,11 +88,11 @@ public: | |||
|     srs_error_t err; | ||||
|     srs_cond_t running; | ||||
|     srs_cond_t exited; | ||||
|     int cid; | ||||
|     std::string cid; | ||||
|     // Quit without error.
 | ||||
|     bool quit; | ||||
| public: | ||||
|     MockCoroutineHandler() : trd(NULL), err(srs_success), cid(0), quit(false) { | ||||
|     MockCoroutineHandler() : trd(NULL), err(srs_success), cid("0"), quit(false) { | ||||
|         running = srs_cond_new(); | ||||
|         exited = srs_cond_new(); | ||||
|     } | ||||
|  | @ -128,12 +128,12 @@ VOID TEST(AppCoroutineTest, StartStop) | |||
|         MockCoroutineHandler ch; | ||||
|         SrsSTCoroutine sc("test", &ch); | ||||
|         ch.trd = ≻ | ||||
|         EXPECT_EQ(0, sc.cid()); | ||||
|         EXPECT_EQ("", sc.cid()); | ||||
| 
 | ||||
|         // Thread stop after created.
 | ||||
|         sc.stop(); | ||||
| 
 | ||||
|         EXPECT_EQ(0, sc.cid()); | ||||
|         EXPECT_EQ("", sc.cid()); | ||||
| 
 | ||||
|         srs_error_t err = sc.pull(); | ||||
|         EXPECT_TRUE(srs_success != err); | ||||
|  | @ -151,13 +151,13 @@ VOID TEST(AppCoroutineTest, StartStop) | |||
|         MockCoroutineHandler ch; | ||||
|         SrsSTCoroutine sc("test", &ch); | ||||
|         ch.trd = ≻ | ||||
|         EXPECT_EQ(0, sc.cid()); | ||||
|         EXPECT_EQ("", sc.cid()); | ||||
| 
 | ||||
|         EXPECT_TRUE(srs_success == sc.start()); | ||||
|         EXPECT_TRUE(srs_success == sc.pull()); | ||||
| 
 | ||||
|         srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS); | ||||
|         EXPECT_TRUE(sc.cid() > 0); | ||||
|         EXPECT_TRUE(!sc.cid().empty()); | ||||
| 
 | ||||
|         // Thread stop after started.
 | ||||
|         sc.stop(); | ||||
|  | @ -178,7 +178,7 @@ VOID TEST(AppCoroutineTest, StartStop) | |||
|         MockCoroutineHandler ch; | ||||
|         SrsSTCoroutine sc("test", &ch); | ||||
|         ch.trd = ≻ | ||||
|         EXPECT_EQ(0, sc.cid()); | ||||
|         EXPECT_EQ("", sc.cid()); | ||||
| 
 | ||||
|         EXPECT_TRUE(srs_success == sc.start()); | ||||
|         EXPECT_TRUE(srs_success == sc.pull()); | ||||
|  | @ -220,16 +220,16 @@ VOID TEST(AppCoroutineTest, Cycle) | |||
| 
 | ||||
|     if (true) { | ||||
|         MockCoroutineHandler ch; | ||||
|         SrsSTCoroutine sc("test", &ch, 250); | ||||
|         SrsSTCoroutine sc("test", &ch, "250"); | ||||
|         ch.trd = ≻ | ||||
|         EXPECT_EQ(250, sc.cid()); | ||||
|         EXPECT_TRUE("250" == sc.cid()); | ||||
| 
 | ||||
|         EXPECT_TRUE(srs_success == sc.start()); | ||||
|         EXPECT_TRUE(srs_success == sc.pull()); | ||||
| 
 | ||||
|         // After running, the cid in cycle should equal to the thread.
 | ||||
|         srs_cond_timedwait(ch.running, 100 * SRS_UTIME_MILLISECONDS); | ||||
|         EXPECT_EQ(250, ch.cid); | ||||
|         EXPECT_TRUE("250" == ch.cid); | ||||
|     } | ||||
| 
 | ||||
|     if (true) { | ||||
|  |  | |||
|  | @ -4099,16 +4099,16 @@ VOID TEST(KernelLogTest, CoverAll) | |||
|         HELPER_EXPECT_SUCCESS(l.initialize()); | ||||
|          | ||||
|         l.reopen(); | ||||
|         l.verbose("TAG", 0, "log"); | ||||
|         l.info("TAG", 0, "log"); | ||||
|         l.trace("TAG", 0, "log"); | ||||
|         l.warn("TAG", 0, "log"); | ||||
|         l.error("TAG", 0, "log"); | ||||
|         l.verbose("TAG", "0", "log"); | ||||
|         l.info("TAG", "0", "log"); | ||||
|         l.trace("TAG", "0", "log"); | ||||
|         l.warn("TAG", "0", "log"); | ||||
|         l.error("TAG", "0", "log"); | ||||
|          | ||||
|         ISrsThreadContext ctx; | ||||
|         ctx.set_id(10); | ||||
|         EXPECT_EQ(0, ctx.get_id()); | ||||
|         EXPECT_EQ(0, ctx.generate_id()); | ||||
|         ctx.set_id("10"); | ||||
|         EXPECT_EQ("", ctx.get_id()); | ||||
|         EXPECT_EQ("", ctx.generate_id()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -558,7 +558,7 @@ VOID TEST(TCPServerTest, MessageConnection) | |||
| 	if (true) { | ||||
| 	    SrsHttpMessage m; | ||||
| 	    HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/v1/streams/100", false)); | ||||
| 	    EXPECT_EQ(100, m.parse_rest_id("/v1/streams/")); EXPECT_FALSE(m.is_jsonp()); | ||||
| 	    EXPECT_EQ("100", m.parse_rest_id("/v1/streams/")); EXPECT_FALSE(m.is_jsonp()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -782,7 +782,7 @@ class MockOnCycleThread : public ISrsCoroutineHandler | |||
| public: | ||||
|     SrsSTCoroutine trd; | ||||
|     srs_cond_t cond; | ||||
|     MockOnCycleThread() : trd("mock", this, 0) { | ||||
|     MockOnCycleThread() : trd("mock", this, "0") { | ||||
|         cond = srs_cond_new(); | ||||
|     }; | ||||
|     virtual ~MockOnCycleThread() { | ||||
|  | @ -822,7 +822,7 @@ class MockOnCycleThread2 : public ISrsCoroutineHandler | |||
| public: | ||||
|     SrsSTCoroutine trd; | ||||
|     srs_mutex_t lock; | ||||
|     MockOnCycleThread2() : trd("mock", this, 0) { | ||||
|     MockOnCycleThread2() : trd("mock", this, "0") { | ||||
|         lock = srs_mutex_new(); | ||||
|     }; | ||||
|     virtual ~MockOnCycleThread2() { | ||||
|  | @ -863,7 +863,7 @@ class MockOnCycleThread3 : public ISrsCoroutineHandler | |||
| public: | ||||
|     SrsSTCoroutine trd; | ||||
|     srs_netfd_t fd; | ||||
|     MockOnCycleThread3() : trd("mock", this, 0) { | ||||
|     MockOnCycleThread3() : trd("mock", this, "0") { | ||||
|         fd = NULL; | ||||
|     }; | ||||
|     virtual ~MockOnCycleThread3() { | ||||
|  | @ -1116,7 +1116,7 @@ class MockOnCycleThread4 : public ISrsCoroutineHandler | |||
| public: | ||||
|     SrsSTCoroutine trd; | ||||
|     srs_netfd_t fd; | ||||
|     MockOnCycleThread4() : trd("mock", this, 0) { | ||||
|     MockOnCycleThread4() : trd("mock", this, "0") { | ||||
|         fd = NULL; | ||||
|     }; | ||||
|     virtual ~MockOnCycleThread4() { | ||||
|  | @ -1268,38 +1268,38 @@ VOID TEST(TCPServerTest, ContextUtility) | |||
|     if (true) { | ||||
|         SrsThreadContext ctx; | ||||
| 
 | ||||
|         EXPECT_EQ(0, ctx.set_id(100)); | ||||
|         EXPECT_EQ(100, ctx.set_id(1000)); | ||||
|         EXPECT_EQ(1000, ctx.get_id()); | ||||
|         EXPECT_TRUE("" == ctx.set_id("100")); | ||||
|         EXPECT_TRUE("100" == ctx.set_id("1000")); | ||||
|         EXPECT_TRUE("1000" == ctx.get_id()); | ||||
| 
 | ||||
|         ctx.clear_cid(); | ||||
|         EXPECT_EQ(0, ctx.set_id(100)); | ||||
|         EXPECT_TRUE("" == ctx.set_id("100")); | ||||
|     } | ||||
| 
 | ||||
|     int base_size = 0; | ||||
|     if (true) { | ||||
|         int size = 0; char buf[1024]; HELPER_ARRAY_INIT(buf, 1024, 0); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, true, true, "SRS", 100, "Trace", &size)); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, true, true, "SRS", "100", "Trace", &size)); | ||||
|         base_size = size; | ||||
|         EXPECT_TRUE(base_size > 0); | ||||
|     } | ||||
| 
 | ||||
|     if (true) { | ||||
|         int size = 0; char buf[1024]; HELPER_ARRAY_INIT(buf, 1024, 0); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, true, "SRS", 100, "Trace", &size)); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, true, "SRS", "100", "Trace", &size)); | ||||
|         EXPECT_EQ(base_size, size); | ||||
|     } | ||||
| 
 | ||||
|     if (true) { | ||||
|         errno = 0; | ||||
|         int size = 0; char buf[1024]; HELPER_ARRAY_INIT(buf, 1024, 0); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, true, NULL, 100, "Trace", &size)); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, true, NULL, "100", "Trace", &size)); | ||||
|         EXPECT_EQ(base_size - 5, size); | ||||
|     } | ||||
| 
 | ||||
|     if (true) { | ||||
|         int size = 0; char buf[1024]; HELPER_ARRAY_INIT(buf, 1024, 0); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, false, NULL, 100, "Trace", &size)); | ||||
|         ASSERT_TRUE(srs_log_header(buf, 1024, false, false, NULL, "100", "Trace", &size)); | ||||
|         EXPECT_EQ(base_size - 8, size); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue