diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 5613c9f45..2dae96242 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1587,27 +1587,38 @@ SrsConfDirective* SrsConfig::get_refer_publish(string vhost) int SrsConfig::get_chunk_size(string vhost) { + if (vhost.empty()) { + return get_global_chunk_size(); + } + SrsConfDirective* conf = get_vhost(vhost); if (!conf) { - return SRS_CONSTS_RTMP_SRS_CHUNK_SIZE; + // vhost does not specify the chunk size, + // use the global instead. + return get_global_chunk_size(); } conf = conf->get("chunk_size"); if (!conf) { // vhost does not specify the chunk size, // use the global instead. - conf = root->get("chunk_size"); - if (!conf) { - return SRS_CONSTS_RTMP_SRS_CHUNK_SIZE; - } - - return ::atoi(conf->arg0().c_str()); + return get_global_chunk_size(); } return ::atoi(conf->arg0().c_str()); } +int SrsConfig::get_global_chunk_size() +{ + SrsConfDirective* conf = root->get("chunk_size"); + if (!conf) { + return SRS_CONSTS_RTMP_SRS_CHUNK_SIZE; + } + + return ::atoi(conf->arg0().c_str()); +} + SrsConfDirective* SrsConfig::get_forward(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 0f85e7de2..6d2b5a5c2 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -490,12 +490,19 @@ public: virtual SrsConfDirective* get_refer_publish(std::string vhost); /** * get the chunk size of vhost. + * @param vhost, the vhost to get the chunk size. use global if not specified. + * empty string to get the global. */ virtual int get_chunk_size(std::string vhost); +private: + /** + * get the global chunk size. + */ + virtual int get_global_chunk_size(); // forward section public: /** - * + * get the forward directive of vhost. */ virtual SrsConfDirective* get_forward(std::string vhost); // http_hooks section diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index 431c9ba42..7995367cf 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -817,5 +817,1052 @@ VOID TEST(ConfigMainTest, ParseInvalidDirective) VOID TEST(ConfigMainTest, ParseInvalidDirective2) { MockSrsConfig conf; + // check error for user not specified the listen directive. EXPECT_TRUE(ERROR_SUCCESS != conf.parse("chunk_size 4096;")); } + +VOID TEST(ConfigMainTest, ParseFullConf) +{ + MockSrsConfig conf; + EXPECT_TRUE(ERROR_SUCCESS == conf.parse( + // full.conf + "# all config for srs \n" + " \n" + "############################################################################################# \n" + "# RTMP sections \n" + "############################################################################################# \n" + "# the rtmp listen ports, split by space. \n" + "listen 1935; \n" + "# the pid file \n" + "# to ensure only one process can use a pid file \n" + "# and provides the current running process id, for script, \n" + "# for example, init.d script to manage the server. \n" + "# default: ./objs/srs.pid \n" + "pid ./objs/srs.pid; \n" + "# the default chunk size is 128, max is 65536, \n" + "# some client does not support chunk size change, \n" + "# however, most clients supports it and it can improve \n" + "# performance about 10%. \n" + "# default: 60000 \n" + "chunk_size 60000; \n" + "# the logs dir. \n" + "# if enabled ffmpeg, each stracoding stream will create a log file. \n" + "# /dev/null to disable the log. \n" + "# default: ./objs \n" + "ff_log_dir ./objs; \n" + "# the log tank, console or file. \n" + "# if console, print log to console. \n" + "# if file, write log to file. requires srs_log_file if log to file. \n" + "# default: file. \n" + "srs_log_tank file; \n" + "# the log level, for all log tanks. \n" + "# can be: verbose, info, trace, warn, error \n" + "# default: trace \n" + "srs_log_level trace; \n" + "# when srs_log_tank is file, specifies the log file. \n" + "# default: ./objs/srs.log \n" + "srs_log_file ./objs/srs.log; \n" + "# the max connections. \n" + "# if exceed the max connections, server will drop the new connection. \n" + "# default: 12345 \n" + "max_connections 1000; \n" + "# whether start as deamon \n" + "# @remark: donot support reload. \n" + "# default: on \n" + "daemon on; \n" + "# heartbeat to api server \n" + "heartbeat { \n" + " # whether heartbeat is enalbed. \n" + " # default: off \n" + " enabled on; \n" + " # the interval seconds for heartbeat, \n" + " # recommend 0.3,0.6,0.9,1.2,1.5,1.8,2.1,2.4,2.7,3,...,6,9,12,.... \n" + " # default: 9.9 \n" + " interval 9.3; \n" + " # when startup, srs will heartbeat to this api. \n" + " # @remark: must be a restful http api url, where SRS will POST with following data: \n" + " # { \n" + " # \"device_id\": \"my-srs-device\", \n" + " # \"ip\": \"192.168.1.100\" \n" + " # } \n" + " # default: http://127.0.0.1:8085/api/v1/servers \n" + " url http://127.0.0.1:8085/api/v1/servers; \n" + " # the id of devide. \n" + " device_id \"my-srs-device\"; \n" + " # the index of device ip. \n" + " # we may retrieve more than one network device. \n" + " # default: 0 \n" + " device_index 0; \n" + " # whether report with summaries \n" + " # if true, put /api/v1/summaries to the request data: \n" + " # { \n" + " # \"summaries\": summaries object. \n" + " # } \n" + " # @remark: optional config. \n" + " # default: off \n" + " summaries off; \n" + "} \n" + " \n" + "############################################################################################# \n" + "# HTTP sections \n" + "############################################################################################# \n" + "# api of srs. \n" + "# the http api config, export for external program to manage srs. \n" + "# user can access http api of srs in browser directly, for instance, to access by: \n" + "# curl http://192.168.1.170:1985/api/v1/reload \n" + "# which will reload srs, like cmd killall -1 srs, but the js can also invoke the http api, \n" + "# where the cli can only be used in shell/terminate. \n" + "http_api { \n" + " # whether http api is enabled. \n" + " # default: off \n" + " enabled on; \n" + " # the http api port \n" + " # default: 1985 \n" + " listen 1985; \n" + "} \n" + "# embeded http server in srs. \n" + "# the http streaming config, for HLS/HDS/DASH/HTTPProgressive \n" + "# global config for http streaming, user must config the http section for each vhost. \n" + "# the embed http server used to substitute nginx in ./objs/nginx, \n" + "# for example, srs runing in arm, can provides RTMP and HTTP service, only with srs installed. \n" + "# user can access the http server pages, generally: \n" + "# curl http://192.168.1.170:80/srs.html \n" + "# which will show srs version and welcome to srs. \n" + "# @remark, the http embeded stream need to config the vhost, for instance, the __defaultVhost__ \n" + "# need to open the feature http of vhost. \n" + "http_stream { \n" + " # whether http streaming service is enabled. \n" + " # default: off \n" + " enabled on; \n" + " # the http streaming port \n" + " # @remark, if use lower port, for instance 80, user must start srs by root. \n" + " # default: 8080 \n" + " listen 8080; \n" + " # the default dir for http root. \n" + " # default: ./objs/nginx/html \n" + " dir ./objs/nginx/html; \n" + "} \n" + " \n" + "############################################################################################# \n" + "# RTMP/HTTP VHOST sections \n" + "############################################################################################# \n" + "# vhost list, the __defaultVhost__ is the default vhost \n" + "# for example, user use ip to access the stream: rtmp://192.168.1.2/live/livestream. \n" + "# for which cannot identify the required vhost. \n" + "vhost __defaultVhost__ { \n" + "} \n" + " \n" + "# vhost for edge, edge and origin is the same vhost \n" + "vhost same.edge.srs.com { \n" + " # the mode of vhost, local or remote. \n" + " # local: vhost is origin vhost, which provides stream source. \n" + " # remote: vhost is edge vhost, which pull/push to origin. \n" + " # default: local \n" + " mode remote; \n" + " # for edge(remote mode), user must specifies the origin server \n" + " # format as: [:port] \n" + " # @remark user can specifies multiple origin for error backup, by space, \n" + " # for example, 192.168.1.100:1935 192.168.1.101:1935 192.168.1.102:1935 \n" + " origin 127.0.0.1:1935 localhost:1935; \n" + " # for edge, whether open the token traverse mode, \n" + " # if token traverse on, all connections of edge will forward to origin to check(auth), \n" + " # it's very important for the edge to do the token auth. \n" + " # the better way is use http callback to do the token auth by the edge, \n" + " # but if user prefer origin check(auth), the token_traverse if better solution. \n" + " # default: off \n" + " token_traverse off; \n" + "} \n" + "# vhost for edge, change vhost. \n" + "vhost change.edge.srs.com { \n" + " mode remote; \n" + " # TODO: FIXME: support extra params. \n" + " origin 127.0.0.1:1935 localhost:1935 { \n" + " # specify the vhost to override the vhost in client request. \n" + " vhost edge2.srs.com; \n" + " # specify the refer(pageUrl) to override the refer in client request. \n" + " refer http://srs/index.html; \n" + " } \n" + "} \n" + " \n" + "# vhost for dvr \n" + "vhost dvr.srs.com { \n" + " # dvr RTMP stream to file, \n" + " # start to record to file when encoder publish, \n" + " # reap flv according by specified dvr_plan. \n" + " # http callbacks: \n" + " # @see http callback on_dvr_hss_reap_flv on http_hooks section. \n" + " dvr { \n" + " # whether enabled dvr features \n" + " # default: off \n" + " enabled on; \n" + " # the dvr output path. \n" + " # the app dir is auto created under the dvr_path. \n" + " # for example, for rtmp stream: \n" + " # rtmp://127.0.0.1/live/livestream \n" + " # http://127.0.0.1/live/livestream.m3u8 \n" + " # where dvr_path is /dvr, srs will create the following files: \n" + " # /dvr/live the app dir for all streams. \n" + " # /dvr/live/livestream.{time}.flv the dvr flv file. \n" + " # @remark, the time use system timestamp in ms, user can use http callback to rename it. \n" + " # in a word, the dvr_path is for vhost. \n" + " # default: ./objs/nginx/html \n" + " dvr_path ./objs/nginx/html; \n" + " # the dvr plan. canbe: \n" + " # session reap flv when session end(unpublish). \n" + " # segment reap flv when flv duration exceed the specified dvr_duration. \n" + " # hss reap flv required by bravo(chnvideo.com) p2p system. \n" + " # default: session \n" + " dvr_plan session; \n" + " # the param for plan(segment), in seconds. \n" + " # default: 30 \n" + " dvr_duration 30; \n" + " # about the stream monotonically increasing: \n" + " # 1. video timestamp is monotonically increasing, \n" + " # 2. audio timestamp is monotonically increasing, \n" + " # 3. video and audio timestamp is interleaved monotonically increasing. \n" + " # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format \n" + " # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. \n" + " # the time jitter algorithm: \n" + " # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. \n" + " # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. \n" + " # 3. off, disable the time jitter algorithm, like atc. \n" + " # default: full \n" + " time_jitter full; \n" + " } \n" + "} \n" + " \n" + "# vhost for ingest \n" + "vhost ingest.srs.com { \n" + " # ingest file/stream/device then push to SRS over RTMP. \n" + " # the name/id used to identify the ingest, must be unique in global. \n" + " # ingest id is used in reload or http api management. \n" + " ingest livestream { \n" + " # whether enabled ingest features \n" + " # default: off \n" + " enabled on; \n" + " # input file/stream/device \n" + " # @remark only support one input. \n" + " input { \n" + " # the type of input. \n" + " # can be file/stream/device, that is, \n" + " # file: ingest file specifies by url. \n" + " # stream: ingest stream specifeis by url. \n" + " # device: not support yet. \n" + " # default: file \n" + " type file; \n" + " # the url of file/stream. \n" + " url ./doc/source.200kbps.768x320.flv; \n" + " } \n" + " # the ffmpeg \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " # the transcode engine, @see all.transcode.srs.com \n" + " # @remark, the output is specified following. \n" + " engine { \n" + " # @see enabled of transcode engine. \n" + " # if disabled or vcodec/acodec not specified, use copy. \n" + " # default: off. \n" + " enabled off; \n" + " # output stream. variables: \n" + " # [vhost] current vhost which start the ingest. \n" + " # [port] system RTMP stream port. \n" + " output rtmp://127.0.0.1:[port]/live?vhost=[vhost]/livestream; \n" + " } \n" + " } \n" + "} \n" + " \n" + "# vhost for http \n" + "vhost http.srs.com { \n" + " # http vhost specified config \n" + " http { \n" + " # whether enabled the http streaming service for vhost. \n" + " # default: off \n" + " enabled on; \n" + " # the virtual directory root for this vhost to mount at \n" + " # for example, if mount to /hls, user access by http://server/hls \n" + " # default: / \n" + " mount /hls; \n" + " # main dir of vhost, \n" + " # to delivery HTTP stream of this vhost. \n" + " # default: ./objs/nginx/html \n" + " dir ./objs/nginx/html/hls; \n" + " } \n" + "} \n" + " \n" + "# the vhost with hls specified. \n" + "vhost with-hls.srs.com { \n" + " hls { \n" + " # whether the hls is enabled. \n" + " # if off, donot write hls(ts and m3u8) when publish. \n" + " # default: off \n" + " enabled on; \n" + " # the hls output path. \n" + " # the app dir is auto created under the hls_path. \n" + " # for example, for rtmp stream: \n" + " # rtmp://127.0.0.1/live/livestream \n" + " # http://127.0.0.1/live/livestream.m3u8 \n" + " # where hls_path is /hls, srs will create the following files: \n" + " # /hls/live the app dir for all streams. \n" + " # /hls/live/livestream.m3u8 the HLS m3u8 file. \n" + " # /hls/live/livestream-1.ts the HLS media/ts file. \n" + " # in a word, the hls_path is for vhost. \n" + " # default: ./objs/nginx/html \n" + " hls_path ./objs/nginx/html; \n" + " # the hls fragment in seconds, the duration of a piece of ts. \n" + " # default: 10 \n" + " hls_fragment 10; \n" + " # the hls window in seconds, the number of ts in m3u8. \n" + " # default: 60 \n" + " hls_window 60; \n" + " } \n" + "} \n" + "# the vhost with hls disabled. \n" + "vhost no-hls.srs.com { \n" + " hls { \n" + " # whether the hls is enabled. \n" + " # if off, donot write hls(ts and m3u8) when publish. \n" + " # default: off \n" + " enabled off; \n" + " } \n" + "} \n" + " \n" + "# the http hook callback vhost, srs will invoke the hooks for specified events. \n" + "vhost hooks.callback.srs.com { \n" + " http_hooks { \n" + " # whether the http hooks enalbe. \n" + " # default off. \n" + " enabled on; \n" + " # when client connect to vhost/app, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_connect\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"tcUrl\": \"rtmp://video.test.com/live?key=d2fa801d08e3f90ed1e1670e6e52651a\", \n" + " # \"pageUrl\": \"http://www.test.com/live.html\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_connect http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_connect http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n" + " # when client close/disconnect to vhost/app/stream, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_close\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_close http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_close http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; \n" + " # when client(encoder) publish to vhost/app/stream, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_publish\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n" + " # when client(encoder) stop publish to vhost/app/stream, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_unpublish\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; \n" + " # when client start to play vhost/app/stream, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_play\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n" + " # when client stop to play vhost/app/stream, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_stop\", \n" + " # \"client_id\": 1985, \n" + " # \"ip\": \"192.168.1.10\", \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\" \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; \n" + " # \n" + " # for dvr(dvr_plan is hss). \n" + " # when dvr got flv header, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_dvr_hss_reap_flv_header\", \n" + " # \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\", \n" + " # \"segment\": { \n" + " # \"cwd\": \"/usr/local/srs\", \n" + " # \"path\": \"./objs/nginx/html/live/livestream.header.flv\" \n" + " # } \n" + " # } \n" + " # when dvr reap flv file, call the hook, \n" + " # the request in the POST data string is a object encode by json: \n" + " # { \n" + " # \"action\": \"on_dvr_hss_reap_flv\", \n" + " # \"vhost\": \"video.test.com\", \"app\": \"live\", \n" + " # \"stream\": \"livestream\", \n" + " # \"segment\": { \n" + " # \"cwd\": \"/usr/local/srs\", \n" + " # \"path\": \"./objs/nginx/html/live/livestream.1398315892865.flv\", \n" + " # \"duration\": 1001, \"offset\":0, \n" + " # \"has_keyframe\": true, \"pts\":1398315895958 \n" + " # } \n" + " # } \n" + " # if valid, the hook must return HTTP code 200(Stauts OK) and response \n" + " # an int value specifies the error code(0 corresponding to success): \n" + " # 0 \n" + " # support multiple api hooks, format: \n" + " # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN \n" + " on_dvr_hss_reap_flv http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs; \n" + " } \n" + "} \n" + " \n" + "# the vhost for min delay, donot cache any stream. \n" + "vhost min.delay.com { \n" + " # whether cache the last gop. \n" + " # if on, cache the last gop and dispatch to client, \n" + " # to enabled fast startup for client, client play immediately. \n" + " # if off, send the latest media data to client, \n" + " # client need to wait for the next Iframe to decode and show the video. \n" + " # set to off if requires min delay; \n" + " # set to on if requires client fast startup. \n" + " # default: on \n" + " gop_cache off; \n" + " # the max live queue length in seconds. \n" + " # if the messages in the queue exceed the max length, \n" + " # drop the old whole gop. \n" + " # default: 30 \n" + " queue_length 10; \n" + "} \n" + " \n" + "# the vhost for antisuck. \n" + "vhost refer.anti_suck.com { \n" + " # the common refer for play and publish. \n" + " # if the page url of client not in the refer, access denied. \n" + " # if not specified this field, allow all. \n" + " # default: not specified. \n" + " refer github.com github.io; \n" + " # refer for publish clients specified. \n" + " # the common refer is not overrided by this. \n" + " # if not specified this field, allow all. \n" + " # default: not specified. \n" + " refer_publish github.com github.io; \n" + " # refer for play clients specified. \n" + " # the common refer is not overrided by this. \n" + " # if not specified this field, allow all. \n" + " # default: not specified. \n" + " refer_play github.com github.io; \n" + "} \n" + " \n" + "# the vhost which forward publish streams. \n" + "vhost same.vhost.forward.srs.com { \n" + " # forward all publish stream to the specified server. \n" + " # this used to split/forward the current stream for cluster active-standby, \n" + " # active-active for cdn to build high available fault tolerance system. \n" + " # format: {ip}:{port} {ip_N}:{port_N} \n" + " # or specify the vhost by params, @see: change.vhost.forward.srs.com \n" + " # if vhost not specified, use the request vhost instead. \n" + " forward 127.0.0.1:1936 127.0.0.1:1937; \n" + "} \n" + "# TODO: FIXME: support extra params. \n" + "# [plan] the vhost which forward publish streams to other vhosts. \n" + "vhost change.vhost.forward.srs.com { \n" + " forward 127.0.0.1:1936 127.0.0.1:1937 { \n" + " # specify the vhost to override the vhost in client request. \n" + " vhost forward2.srs.com; \n" + " # specify the refer(pageUrl) to override the refer in client request. \n" + " refer http://srs/index.html; \n" + " } \n" + " forward 127.0.0.1:1938 { \n" + " vhost forward3.srs.com; \n" + " } \n" + "} \n" + " \n" + "# the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction \n" + "vhost mirror.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine mirror { \n" + " enabled on; \n" + " vfilter { \n" + " vf 'split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2'; \n" + " } \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# \n" + "# the drawtext filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#drawtext-1 \n" + "# remark: we remove the libfreetype which always cause build failed, you must add it manual if needed. \n" + "# \n" + "####################################################################################################### \n" + "# the crop filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#crop \n" + "vhost crop.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine crop { \n" + " enabled on; \n" + " vfilter { \n" + " vf 'crop=in_w-20:in_h-160:10:80'; \n" + " } \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# the logo filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#overlay \n" + "vhost logo.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine logo { \n" + " enabled on; \n" + " vfilter { \n" + " i ./doc/ffmpeg-logo.png; \n" + " filter_complex 'overlay=10:10'; \n" + " } \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# audio transcode only. \n" + "# for example, FMLE publish audio codec in mp3, and donot support HLS output, \n" + "# we can transcode the audio to aac and copy video to the new stream with HLS. \n" + "vhost audio.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine acodec { \n" + " enabled on; \n" + " vcodec copy; \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# disable video, transcode/copy audio. \n" + "# for example, publish pure audio stream. \n" + "vhost vn.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine vn { \n" + " enabled on; \n" + " vcodec vn; \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# ffmpeg-copy(forward implements by ffmpeg). \n" + "# copy the video and audio to a new stream. \n" + "vhost copy.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine copy { \n" + " enabled on; \n" + " vcodec copy; \n" + " acodec copy; \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# transcode all app and stream of vhost \n" + "vhost all.transcode.srs.com { \n" + " # the streaming transcode configs. \n" + " transcode { \n" + " # whether the transcode enabled. \n" + " # if off, donot transcode. \n" + " # default: off. \n" + " enabled on; \n" + " # the ffmpeg \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " # the transcode engine for matched stream. \n" + " # all matched stream will transcoded to the following stream. \n" + " # the transcode set name(ie. hd) is optional and not used. \n" + " engine ffsuper { \n" + " # whether the engine is enabled \n" + " # default: off. \n" + " enabled on; \n" + " # input format, can be: \n" + " # off, do not specifies the format, ffmpeg will guess it. \n" + " # flv, for flv or RTMP stream. \n" + " # other format, for example, mp4/aac whatever. \n" + " # default: flv \n" + " iformat flv; \n" + " # ffmpeg filters, follows the main input. \n" + " vfilter { \n" + " # the logo input file. \n" + " i ./doc/ffmpeg-logo.png; \n" + " # the ffmpeg complex filter. \n" + " # for filters, @see: http://ffmpeg.org/ffmpeg-filters.html \n" + " filter_complex 'overlay=10:10'; \n" + " } \n" + " # video encoder name. can be: \n" + " # libx264: use h.264(libx264) video encoder. \n" + " # copy: donot encoder the video stream, copy it. \n" + " # vn: disable video output. \n" + " vcodec libx264; \n" + " # video bitrate, in kbps \n" + " vbitrate 1500; \n" + " # video framerate. \n" + " vfps 25; \n" + " # video width, must be even numbers. \n" + " vwidth 768; \n" + " # video height, must be even numbers. \n" + " vheight 320; \n" + " # the max threads for ffmpeg to used. \n" + " vthreads 12; \n" + " # x264 profile, @see x264 -help, can be: \n" + " # high,main,baseline \n" + " vprofile main; \n" + " # x264 preset, @see x264 -help, can be: \n" + " # ultrafast,superfast,veryfast,faster,fast \n" + " # medium,slow,slower,veryslow,placebo \n" + " vpreset medium; \n" + " # other x264 or ffmpeg video params \n" + " vparams { \n" + " # ffmpeg options, @see: http://ffmpeg.org/ffmpeg.html \n" + " t 100; \n" + " # 264 params, @see: http://ffmpeg.org/ffmpeg-codecs.html#libx264 \n" + " coder 1; \n" + " b_strategy 2; \n" + " bf 3; \n" + " refs 10; \n" + " } \n" + " # audio encoder name. can be: \n" + " # libaacplus: use aac(libaacplus) audio encoder. \n" + " # copy: donot encoder the audio stream, copy it. \n" + " # an: disable audio output. \n" + " acodec libaacplus; \n" + " # audio bitrate, in kbps. [16, 72] for libaacplus. \n" + " abitrate 70; \n" + " # audio sample rate. for flv/rtmp, it must be: \n" + " # 44100,22050,11025,5512 \n" + " asample_rate 44100; \n" + " # audio channel, 1 for mono, 2 for stereo. \n" + " achannels 2; \n" + " # other ffmpeg audio params \n" + " aparams { \n" + " # audio params, @see: http://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders \n" + " profile:a aac_low; \n" + " } \n" + " # output format, can be: \n" + " # off, do not specifies the format, ffmpeg will guess it. \n" + " # flv, for flv or RTMP stream. \n" + " # other format, for example, mp4/aac whatever. \n" + " # default: flv \n" + " oformat flv; \n" + " # output stream. variables: \n" + " # [vhost] the input stream vhost. \n" + " # [port] the intput stream port. \n" + " # [app] the input stream app. \n" + " # [stream] the input stream name. \n" + " # [engine] the tanscode engine name. \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine ffhd { \n" + " enabled on; \n" + " vcodec libx264; \n" + " vbitrate 1200; \n" + " vfps 25; \n" + " vwidth 1382; \n" + " vheight 576; \n" + " vthreads 6; \n" + " vprofile main; \n" + " vpreset medium; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 70; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine ffsd { \n" + " enabled on; \n" + " vcodec libx264; \n" + " vbitrate 800; \n" + " vfps 25; \n" + " vwidth 1152; \n" + " vheight 480; \n" + " vthreads 4; \n" + " vprofile main; \n" + " vpreset fast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 60; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine fffast { \n" + " enabled on; \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine vcopy { \n" + " enabled on; \n" + " vcodec copy; \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine acopy { \n" + " enabled on; \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec copy; \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " engine copy { \n" + " enabled on; \n" + " vcodec copy; \n" + " acodec copy; \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# transcode all stream using the empty ffmpeg demo, donothing. \n" + "vhost ffempty.transcode.srs.com { \n" + " transcode { \n" + " enabled on; \n" + " ffmpeg ./objs/research/ffempty; \n" + " engine empty { \n" + " enabled on; \n" + " vcodec libx264; \n" + " vbitrate 300; \n" + " vfps 20; \n" + " vwidth 768; \n" + " vheight 320; \n" + " vthreads 2; \n" + " vprofile baseline; \n" + " vpreset superfast; \n" + " vparams { \n" + " } \n" + " acodec libaacplus; \n" + " abitrate 45; \n" + " asample_rate 44100; \n" + " achannels 2; \n" + " aparams { \n" + " } \n" + " output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; \n" + " } \n" + " } \n" + "} \n" + "# transcode all app and stream of app \n" + "vhost app.transcode.srs.com { \n" + " # the streaming transcode configs. \n" + " # if app specified, transcode all streams of app. \n" + " transcode live { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine { \n" + " enabled off; \n" + " } \n" + " } \n" + "} \n" + "# transcode specified stream. \n" + "vhost stream.transcode.srs.com { \n" + " # the streaming transcode configs. \n" + " # if stream specified, transcode the matched stream. \n" + " transcode live/livestream { \n" + " enabled on; \n" + " ffmpeg ./objs/ffmpeg/bin/ffmpeg; \n" + " engine { \n" + " enabled off; \n" + " } \n" + " } \n" + "} \n" + " \n" + "# vhost for bandwidth check \n" + "# generally, the bandcheck vhost must be: bandcheck.srs.com, \n" + "# or need to modify the vhost of client. \n" + "vhost bandcheck.srs.com { \n" + " enabled on; \n" + " chunk_size 65000; \n" + " # bandwidth check config. \n" + " bandcheck { \n" + " # whether support bandwidth check, \n" + " # default: off. \n" + " enabled on; \n" + " # the key for server to valid, \n" + " # if invalid key, server disconnect and abort the bandwidth check. \n" + " key \"35c9b402c12a7246868752e2878f7e0e\"; \n" + " # the interval in seconds for bandwidth check, \n" + " # server donot allow new test request. \n" + " # default: 30 \n" + " interval 30; \n" + " # the max available check bandwidth in kbps. \n" + " # to avoid attack of bandwidth check. \n" + " # default: 1000 \n" + " limit_kbps 4000; \n" + " } \n" + "} \n" + " \n" + "# set the chunk size of vhost. \n" + "vhost chunksize.srs.com { \n" + " # the default chunk size is 128, max is 65536, \n" + " # some client does not support chunk size change, \n" + " # vhost chunk size will override the global value. \n" + " # default: global chunk size. \n" + " chunk_size 128; \n" + "} \n" + " \n" + "# vhost for time jitter \n" + "vhost jitter.srs.com { \n" + " # about the stream monotonically increasing: \n" + " # 1. video timestamp is monotonically increasing, \n" + " # 2. audio timestamp is monotonically increasing, \n" + " # 3. video and audio timestamp is interleaved monotonically increasing. \n" + " # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format \n" + " # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. \n" + " # the time jitter algorithm: \n" + " # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. \n" + " # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. \n" + " # 3. off, disable the time jitter algorithm, like atc. \n" + " # default: full \n" + " time_jitter full; \n" + "} \n" + " \n" + "# vhost for atc. \n" + "vhost atc.srs.com { \n" + " # vhost for atc for hls/hds/rtmp backup. \n" + " # generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0. \n" + " # when atc is on, server delivery rtmp stream by absolute time. \n" + " # atc is used, for instance, encoder will copy stream to master and slave server, \n" + " # server use atc to delivery stream to edge/client, where stream time from master/slave server \n" + " # is always the same, client/tools can slice RTMP stream to HLS according to the same time, \n" + " # if the time not the same, the HLS stream cannot slice to support system backup. \n" + " # \n" + " # @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html \n" + " # @see http://www.baidu.com/#wd=hds%20hls%20atc \n" + " # \n" + " # default: off \n" + " atc on; \n" + " # whether enable the auto atc, \n" + " # if enabled, detect the bravo_atc=\"true\" in onMetaData packet, \n" + " # set atc to on if matched. \n" + " # always ignore the onMetaData if atc_auto is off. \n" + " # default: on \n" + " atc_auto on; \n" + "} \n" + " \n" + "# the vhost disabled. \n" + "vhost removed.srs.com { \n" + " # whether the vhost is enabled. \n" + " # if off, all request access denied. \n" + " # default: on \n" + " enabled off; \n" + "} \n" + " \n" + "# config for the pithy print, \n" + "# which always print constant message specified by interval, \n" + "# whatever the clients in concurrency. \n" + "pithy_print { \n" + " # shared print interval for all publish clients, in milliseconds. \n" + " # default: 10000 \n" + " publish 10000; \n" + " # shared print interval for all play clients, in milliseconds. \n" + " # default: 10000 \n" + " play 10000; \n" + " # shared print interval for all forwarders, in milliseconds. \n" + " # default: 10000 \n" + " forwarder 10000; \n" + " # shared print interval for all encoders, in milliseconds. \n" + " # default: 10000 \n" + " encoder 10000; \n" + " # shared print interval for all ingesters, in milliseconds. \n" + " # default: 10000 \n" + " ingester 10000; \n" + " # shared print interval for all hls, in milliseconds. \n" + " # default: 10000 \n" + " hls 10000; \n" + " # shared print interval for all edge, in milliseconds. \n" + " # default: 10000 \n" + " edge 10000; \n" + "} \n" + // full.conf + )); + + vector listens = conf.get_listen(); + EXPECT_EQ(1, (int)listens.size()); + EXPECT_STREQ("1935", listens.at(0).c_str()); + + EXPECT_STREQ("./objs/srs.pid", conf.get_pid_file().c_str()); + EXPECT_EQ(60000, conf.get_chunk_size("")); + EXPECT_STREQ("./objs", conf.get_ffmpeg_log_dir().c_str()); + EXPECT_TRUE(conf.get_log_tank_file()); + EXPECT_STREQ("trace", conf.get_log_level().c_str()); + EXPECT_STREQ("./objs/srs.log", conf.get_log_file().c_str()); + EXPECT_EQ(1000, conf.get_max_connections()); + EXPECT_TRUE(conf.get_deamon()); + + EXPECT_TRUE(conf.get_heartbeat_enabled()); + EXPECT_EQ(9300, conf.get_heartbeat_interval()); + EXPECT_STREQ("http://127.0.0.1:8085/api/v1/servers", conf.get_heartbeat_url().c_str()); + EXPECT_STREQ("my-srs-device", conf.get_heartbeat_device_id().c_str()); + EXPECT_EQ(0, conf.get_heartbeat_device_index()); + EXPECT_FALSE(conf.get_heartbeat_summaries()); + + EXPECT_TRUE(conf.get_http_api_enabled()); + EXPECT_EQ(1985, conf.get_http_api_listen()); + + EXPECT_TRUE(conf.get_http_stream_enabled()); + EXPECT_EQ(8080, conf.get_http_stream_listen()); + EXPECT_STREQ("./objs/nginx/html", conf.get_http_stream_dir().c_str()); + + EXPECT_TRUE(NULL != conf.get_vhost("__defaultVhost__")); + EXPECT_TRUE(NULL != conf.get_vhost("same.edge.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("change.edge.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("dvr.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("ingest.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("http.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("with-hls.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("no-hls.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("hooks.callback.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("min.delay.com")); + EXPECT_TRUE(NULL != conf.get_vhost("refer.anti_suck.com")); + EXPECT_TRUE(NULL != conf.get_vhost("same.vhost.forward.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("change.vhost.forward.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("mirror.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("crop.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("logo.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("audio.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("vn.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("copy.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("all.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("ffempty.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("app.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("stream.transcode.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("bandcheck.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("chunksize.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("jitter.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("atc.srs.com")); + EXPECT_TRUE(NULL != conf.get_vhost("removed.srs.com")); +}