mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #351, support config the m3u8/ts path for hls. 2.0.149.
This commit is contained in:
parent
85afb6ea6f
commit
692b751da8
13 changed files with 235 additions and 110 deletions
|
@ -562,6 +562,7 @@ Supported operating systems and hardware:
|
|||
|
||||
### SRS 2.0 history
|
||||
|
||||
* v2.0, 2015-03-30, for [#351](https://github.com/winlinvip/simple-rtmp-server/issues/351), support config the m3u8/ts path for hls. 2.0.149.
|
||||
* v2.0, 2015-03-17, for [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), osx(darwin) support demo with nginx and ffmpeg. 2.0.143.
|
||||
* v2.0, 2015-03-15, start [2.0release branch](https://github.com/winlinvip/simple-rtmp-server/tree/2.0release), 80773 lines.
|
||||
* v2.0, 2015-03-14, fix [#324](https://github.com/winlinvip/simple-rtmp-server/issues/324), support hstrs(http stream trigger rtmp source) edge mode. 2.0.140.
|
||||
|
|
|
@ -528,17 +528,38 @@ vhost with-hls.srs.com {
|
|||
# default: disk
|
||||
hls_storage disk;
|
||||
# the hls output path.
|
||||
# the app dir is auto created under the hls_path.
|
||||
# for example, for rtmp stream:
|
||||
# rtmp://127.0.0.1/live/livestream
|
||||
# http://127.0.0.1/live/livestream.m3u8
|
||||
# where hls_path is /hls, srs will create the following files:
|
||||
# /hls/live the app dir for all streams.
|
||||
# /hls/live/livestream.m3u8 the HLS m3u8 file.
|
||||
# /hls/live/livestream-1.ts the HLS media/ts file.
|
||||
# in a word, the hls_path is for vhost.
|
||||
# the m3u8 file is configed by hls_path/hls_m3u8_file, the default is:
|
||||
# ./objs/nginx/html/[app]/[stream].m3u8
|
||||
# the ts file is configed by hls_path/hls_ts_file, the default is:
|
||||
# ./objs/nginx/html/[app]/[stream]-[seq].ts
|
||||
# @remark the hls_path is compatible with srs v1 config.
|
||||
# default: ./objs/nginx/html
|
||||
hls_path ./objs/nginx/html;
|
||||
# the hls m3u8 file name.
|
||||
# we supports some variables to generate the filename.
|
||||
# [vhost], the vhost of stream.
|
||||
# [app], the app of stream.
|
||||
# [stream], the stream name of stream.
|
||||
# default: [app]/[stream].m3u8
|
||||
hls_m3u8_file [app]/[stream].m3u8;
|
||||
# the hls ts file name.
|
||||
# we supports some variables to generate the filename.
|
||||
# [vhost], the vhost of stream.
|
||||
# [app], the app of stream.
|
||||
# [stream], the stream name of stream.
|
||||
# [2006], replace this const to current year.
|
||||
# [01], replace this const to current month.
|
||||
# [02], replace this const to current date.
|
||||
# [15], replace this const to current hour.
|
||||
# [04], repleace this const to current minute.
|
||||
# [05], repleace this const to current second.
|
||||
# [999], repleace this const to current millisecond.
|
||||
# [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
# [seq], the sequence number of ts.
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DeliveryHLS#hls-config
|
||||
# default: [app]/[stream]-[seq].ts
|
||||
hls_ts_file [app]/[stream]-[seq].ts;
|
||||
# the hls entry prefix, which is base url of ts url.
|
||||
# if specified, the ts path in m3u8 will be like:
|
||||
# http://your-server/live/livestream-0.ts
|
||||
|
|
|
@ -10,5 +10,7 @@ vhost __defaultVhost__ {
|
|||
hls_fragment 10;
|
||||
hls_window 60;
|
||||
hls_path ./objs/nginx/html;
|
||||
hls_m3u8_file [app]/[stream].m3u8;
|
||||
hls_ts_file [app]/[stream]-[seq].ts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@ http_server {
|
|||
vhost __defaultVhost__ {
|
||||
hls {
|
||||
enabled on;
|
||||
hls_path ./objs/nginx/html;
|
||||
hls_fragment 10;
|
||||
hls_window 60;
|
||||
hls_path ./objs/nginx/html;
|
||||
hls_m3u8_file [app]/[stream].m3u8;
|
||||
hls_ts_file [app]/[stream]-[seq].ts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ max_connections 1000;
|
|||
vhost __defaultVhost__ {
|
||||
hls {
|
||||
enabled on;
|
||||
hls_path ./objs/nginx/html;
|
||||
hls_fragment 10;
|
||||
hls_window 60;
|
||||
hls_path ./objs/nginx/html;
|
||||
hls_m3u8_file [app]/[stream].m3u8;
|
||||
hls_ts_file [app]/[stream]-[seq].ts;
|
||||
}
|
||||
transcode {
|
||||
enabled on;
|
||||
|
|
|
@ -1482,6 +1482,7 @@ int SrsConfig::check_config()
|
|||
string m = conf->at(j)->name.c_str();
|
||||
if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error"
|
||||
&& m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec"
|
||||
&& m != "hls_m3u8_file" && m != "hls_ts_file"
|
||||
) {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret);
|
||||
|
@ -3172,6 +3173,40 @@ string SrsConfig::get_hls_path(string vhost)
|
|||
return conf->arg0();
|
||||
}
|
||||
|
||||
string SrsConfig::get_hls_m3u8_file(string vhost)
|
||||
{
|
||||
SrsConfDirective* hls = get_hls(vhost);
|
||||
|
||||
if (!hls) {
|
||||
return SRS_CONF_DEFAULT_HLS_M3U8_FILE;
|
||||
}
|
||||
|
||||
SrsConfDirective* conf = hls->get("hls_m3u8_file");
|
||||
|
||||
if (!conf) {
|
||||
return SRS_CONF_DEFAULT_HLS_M3U8_FILE;
|
||||
}
|
||||
|
||||
return conf->arg0();
|
||||
}
|
||||
|
||||
string SrsConfig::get_hls_ts_file(string vhost)
|
||||
{
|
||||
SrsConfDirective* hls = get_hls(vhost);
|
||||
|
||||
if (!hls) {
|
||||
return SRS_CONF_DEFAULT_HLS_TS_FILE;
|
||||
}
|
||||
|
||||
SrsConfDirective* conf = hls->get("hls_ts_file");
|
||||
|
||||
if (!conf) {
|
||||
return SRS_CONF_DEFAULT_HLS_TS_FILE;
|
||||
}
|
||||
|
||||
return conf->arg0();
|
||||
}
|
||||
|
||||
double SrsConfig::get_hls_fragment(string vhost)
|
||||
{
|
||||
SrsConfDirective* hls = get_hls(vhost);
|
||||
|
|
|
@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000
|
||||
#define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
|
||||
#define SRS_CONF_DEFAULT_HLS_M3U8_FILE "[app]/[stream].m3u8"
|
||||
#define SRS_CONF_DEFAULT_HLS_TS_FILE "[app]/[stream]-[seq].ts"
|
||||
#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
|
||||
#define SRS_CONF_DEFAULT_HLS_TD_RATIO 1.5
|
||||
#define SRS_CONF_DEFAULT_HLS_AOF_RATIO 2.0
|
||||
|
@ -871,9 +873,17 @@ public:
|
|||
*/
|
||||
virtual std::string get_hls_entry_prefix(std::string vhost);
|
||||
/**
|
||||
* get the HLS ts/m3u8 file store path.
|
||||
*/
|
||||
* get the HLS ts/m3u8 file store path.
|
||||
*/
|
||||
virtual std::string get_hls_path(std::string vhost);
|
||||
/**
|
||||
* get the HLS m3u8 file path template.
|
||||
*/
|
||||
virtual std::string get_hls_m3u8_file(std::string vhost);
|
||||
/**
|
||||
* get the HLS ts file path template.
|
||||
*/
|
||||
virtual std::string get_hls_ts_file(std::string vhost);
|
||||
/**
|
||||
* get the hls fragment time, in seconds.
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <fcntl.h>
|
||||
#include <sstream>
|
||||
#include <sys/time.h>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
|
@ -42,6 +41,7 @@ using namespace std;
|
|||
#include <srs_rtmp_amf0.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
||||
// update the flv duration and filesize every this interval in ms.
|
||||
#define SRS_DVR_UPDATE_DURATION_INTERVAL 60000
|
||||
|
@ -422,76 +422,8 @@ string SrsFlvSegment::generate_path()
|
|||
|
||||
// the flv file path
|
||||
std::string flv_path = path_config;
|
||||
|
||||
// variable [vhost]
|
||||
flv_path = srs_string_replace(flv_path, "[vhost]", req->vhost);
|
||||
// variable [app]
|
||||
flv_path = srs_string_replace(flv_path, "[app]", req->app);
|
||||
// variable [stream]
|
||||
flv_path = srs_string_replace(flv_path, "[stream]", req->stream);
|
||||
|
||||
// date and time substitude
|
||||
// clock time
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
return flv_path;
|
||||
}
|
||||
|
||||
// to calendar time
|
||||
struct tm* tm;
|
||||
if ((tm = localtime(&tv.tv_sec)) == NULL) {
|
||||
return flv_path;
|
||||
}
|
||||
|
||||
// the buffer to format the date and time.
|
||||
char buf[64];
|
||||
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
flv_path = srs_string_replace(flv_path, "[2006]", buf);
|
||||
}
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
flv_path = srs_string_replace(flv_path, "[2006]", buf);
|
||||
}
|
||||
// [01], replace this const to current month.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon);
|
||||
flv_path = srs_string_replace(flv_path, "[01]", buf);
|
||||
}
|
||||
// [02], replace this const to current date.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_mday);
|
||||
flv_path = srs_string_replace(flv_path, "[02]", buf);
|
||||
}
|
||||
// [15], replace this const to current hour.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_hour);
|
||||
flv_path = srs_string_replace(flv_path, "[15]", buf);
|
||||
}
|
||||
// [04], repleace this const to current minute.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_min);
|
||||
flv_path = srs_string_replace(flv_path, "[04]", buf);
|
||||
}
|
||||
// [05], repleace this const to current second.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_sec);
|
||||
flv_path = srs_string_replace(flv_path, "[05]", buf);
|
||||
}
|
||||
// [999], repleace this const to current millisecond.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%03d", (int)(tv.tv_usec / 1000));
|
||||
flv_path = srs_string_replace(flv_path, "[999]", buf);
|
||||
}
|
||||
// [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
if (true) {
|
||||
int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec;
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, now_us / 1000);
|
||||
flv_path = srs_string_replace(flv_path, "[timestamp]", buf);
|
||||
}
|
||||
flv_path = srs_path_build_stream(flv_path, req->vhost, req->app, req->stream);
|
||||
flv_path = srs_path_build_timestamp(flv_path);
|
||||
|
||||
return flv_path;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ using namespace std;
|
|||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_rtmp_buffer.hpp>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
||||
// drop the segment when duration of ts too small.
|
||||
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
|
||||
|
@ -204,8 +205,9 @@ int SrsHlsMuxer::sequence_no()
|
|||
return _sequence_no;
|
||||
}
|
||||
|
||||
int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, int fragment, int window, double aof_ratio)
|
||||
{
|
||||
int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
|
||||
string path, string m3u8_file, string ts_file, int fragment, int window, double aof_ratio
|
||||
) {
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
srs_freep(req);
|
||||
|
@ -213,6 +215,8 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path,
|
|||
|
||||
hls_entry_prefix = entry_prefix;
|
||||
hls_path = path;
|
||||
hls_m3u8_file = m3u8_file;
|
||||
hls_ts_file = ts_file;
|
||||
hls_fragment = fragment;
|
||||
hls_aof_ratio = aof_ratio;
|
||||
hls_window = window;
|
||||
|
@ -249,7 +253,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
|||
|
||||
// TODO: create all parents dirs.
|
||||
// create dir for app.
|
||||
if (should_write_file && (ret = create_dir()) != ERROR_SUCCESS) {
|
||||
if (should_write_file && (ret = create_dir(current->full_path)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -292,22 +296,23 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
|||
current->segment_start_dts = segment_start_dts;
|
||||
|
||||
// generate filename.
|
||||
char filename[128];
|
||||
snprintf(filename, sizeof(filename),
|
||||
"%s-%d.ts", req->stream.c_str(), current->sequence_no);
|
||||
std::string ts_file = hls_ts_file;
|
||||
ts_file = srs_path_build_stream(ts_file, req->vhost, req->app, req->stream);
|
||||
ts_file = srs_path_build_timestamp(ts_file);
|
||||
if (true) {
|
||||
std::stringstream ss;
|
||||
ss << current->sequence_no;
|
||||
ts_file = srs_string_replace(ts_file, "[seq]", ss.str());
|
||||
}
|
||||
|
||||
// TODO: use temp file and rename it.
|
||||
current->full_path = hls_path;
|
||||
current->full_path += "/";
|
||||
current->full_path += req->app;
|
||||
current->full_path += "/";
|
||||
current->full_path += filename;
|
||||
// replace variables
|
||||
current->full_path = hls_path + "/" + ts_file;
|
||||
|
||||
current->uri += hls_entry_prefix;
|
||||
if (!hls_entry_prefix.empty() && !srs_string_ends_with(hls_entry_prefix, "/")) {
|
||||
current->uri += "/";
|
||||
}
|
||||
current->uri += filename;
|
||||
current->uri += ts_file;
|
||||
|
||||
std::string tmp_file = current->full_path + ".tmp";
|
||||
if ((ret = current->muxer->open(tmp_file.c_str())) != ERROR_SUCCESS) {
|
||||
|
@ -524,10 +529,8 @@ int SrsHlsMuxer::refresh_m3u8()
|
|||
|
||||
std::string m3u8_file = hls_path;
|
||||
m3u8_file += "/";
|
||||
m3u8_file += req->app;
|
||||
m3u8_file += "/";
|
||||
m3u8_file += req->stream;
|
||||
m3u8_file += ".m3u8";
|
||||
m3u8_file += hls_m3u8_file;
|
||||
m3u8_file = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream);
|
||||
|
||||
m3u8 = m3u8_file;
|
||||
m3u8_file += ".temp";
|
||||
|
@ -631,7 +634,7 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsHlsMuxer::create_dir()
|
||||
int SrsHlsMuxer::create_dir(string filepath)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
@ -639,9 +642,11 @@ int SrsHlsMuxer::create_dir()
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string app_dir = hls_path;
|
||||
app_dir += "/";
|
||||
app_dir += req->app;
|
||||
std::string app_dir = filepath;
|
||||
size_t pos = string::npos;
|
||||
if ((pos = app_dir.rfind("/")) != string::npos) {
|
||||
app_dir = app_dir.substr(0, pos);
|
||||
}
|
||||
|
||||
// TODO: cleanup the dir when startup.
|
||||
|
||||
|
@ -678,7 +683,9 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
|
|||
// get the hls m3u8 ts list entry prefix config
|
||||
std::string entry_prefix = _srs_config->get_hls_entry_prefix(vhost);
|
||||
// get the hls path config
|
||||
std::string hls_path = _srs_config->get_hls_path(vhost);
|
||||
std::string path = _srs_config->get_hls_path(vhost);
|
||||
std::string m3u8_file = _srs_config->get_hls_m3u8_file(vhost);
|
||||
std::string ts_file = _srs_config->get_hls_ts_file(vhost);
|
||||
// the audio overflow, for pure audio to reap segment.
|
||||
double hls_aof_ratio = _srs_config->get_hls_aof_ratio(vhost);
|
||||
|
||||
|
@ -686,7 +693,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
|
|||
// for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
|
||||
|
||||
// open muxer
|
||||
if ((ret = muxer->update_config(req, entry_prefix, hls_path, hls_fragment, hls_window, hls_aof_ratio)) != ERROR_SUCCESS) {
|
||||
if ((ret = muxer->update_config(req, entry_prefix, path, m3u8_file, ts_file, hls_fragment, hls_window, hls_aof_ratio)) != ERROR_SUCCESS) {
|
||||
srs_error("m3u8 muxer update config failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -169,6 +169,8 @@ private:
|
|||
private:
|
||||
std::string hls_entry_prefix;
|
||||
std::string hls_path;
|
||||
std::string hls_m3u8_file;
|
||||
std::string hls_ts_file;
|
||||
double hls_aof_ratio;
|
||||
int hls_fragment;
|
||||
int hls_window;
|
||||
|
@ -209,7 +211,9 @@ public:
|
|||
/**
|
||||
* when publish, update the config for muxer.
|
||||
*/
|
||||
virtual int update_config(SrsRequest* r, std::string entry_prefix, std::string path, int fragment, int window, double aof_ratio);
|
||||
virtual int update_config(SrsRequest* r, std::string entry_prefix,
|
||||
std::string path, std::string m3u8_file, std::string ts_file,
|
||||
int fragment, int window, double aof_ratio);
|
||||
/**
|
||||
* open a new segment(a new ts file),
|
||||
* @param segment_start_dts use to calc the segment duration,
|
||||
|
@ -240,7 +244,7 @@ public:
|
|||
private:
|
||||
virtual int refresh_m3u8();
|
||||
virtual int _refresh_m3u8(std::string m3u8_file);
|
||||
virtual int create_dir();
|
||||
virtual int create_dir(std::string filepath);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_kernel_log.hpp>
|
||||
|
@ -111,6 +112,91 @@ int srs_get_log_level(string level)
|
|||
}
|
||||
}
|
||||
|
||||
string srs_path_build_stream(string template_path, string vhost, string app, string stream)
|
||||
{
|
||||
std::string path = template_path;
|
||||
|
||||
// variable [vhost]
|
||||
path = srs_string_replace(path, "[vhost]", vhost);
|
||||
// variable [app]
|
||||
path = srs_string_replace(path, "[app]", app);
|
||||
// variable [stream]
|
||||
path = srs_string_replace(path, "[stream]", stream);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
string srs_path_build_timestamp(string template_path)
|
||||
{
|
||||
std::string path = template_path;
|
||||
|
||||
|
||||
// date and time substitude
|
||||
// clock time
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// to calendar time
|
||||
struct tm* tm;
|
||||
if ((tm = localtime(&tv.tv_sec)) == NULL) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// the buffer to format the date and time.
|
||||
char buf[64];
|
||||
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
path = srs_string_replace(path, "[2006]", buf);
|
||||
}
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
path = srs_string_replace(path, "[2006]", buf);
|
||||
}
|
||||
// [01], replace this const to current month.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon);
|
||||
path = srs_string_replace(path, "[01]", buf);
|
||||
}
|
||||
// [02], replace this const to current date.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_mday);
|
||||
path = srs_string_replace(path, "[02]", buf);
|
||||
}
|
||||
// [15], replace this const to current hour.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_hour);
|
||||
path = srs_string_replace(path, "[15]", buf);
|
||||
}
|
||||
// [04], repleace this const to current minute.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_min);
|
||||
path = srs_string_replace(path, "[04]", buf);
|
||||
}
|
||||
// [05], repleace this const to current second.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_sec);
|
||||
path = srs_string_replace(path, "[05]", buf);
|
||||
}
|
||||
// [999], repleace this const to current millisecond.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%03d", (int)(tv.tv_usec / 1000));
|
||||
path = srs_string_replace(path, "[999]", buf);
|
||||
}
|
||||
// [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
if (true) {
|
||||
int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec;
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, now_us / 1000);
|
||||
path = srs_string_replace(path, "[timestamp]", buf);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void srs_parse_endpoint(string ip_port, string& ip, string& port)
|
||||
{
|
||||
ip = "0.0.0.0";
|
||||
|
|
|
@ -50,6 +50,29 @@ extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_
|
|||
*/
|
||||
extern int srs_get_log_level(std::string level);
|
||||
|
||||
/**
|
||||
* build the path according to vhost/app/stream, where replace variables:
|
||||
* [vhost], the vhost of stream.
|
||||
* [app], the app of stream.
|
||||
* [stream], the stream name of stream.
|
||||
* @return the replaced path.
|
||||
*/
|
||||
extern std::string srs_path_build_stream(std::string template_path, std::string vhost, std::string app, std::string stream);
|
||||
|
||||
/**
|
||||
* build the path according to timestamp, where replace variables:
|
||||
* [2006], replace this const to current year.
|
||||
* [01], replace this const to current month.
|
||||
* [02], replace this const to current date.
|
||||
* [15], replace this const to current hour.
|
||||
* [04], repleace this const to current minute.
|
||||
* [05], repleace this const to current second.
|
||||
* [999], repleace this const to current millisecond.
|
||||
* [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
* @return the replaced path.
|
||||
*/
|
||||
extern std::string srs_path_build_timestamp(std::string template_path);
|
||||
|
||||
/**
|
||||
* parse the endpoint to ip and port.
|
||||
* @param ip_port the ip and port which formats in <[ip:]port>
|
||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
// current release version
|
||||
#define VERSION_MAJOR 2
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 148
|
||||
#define VERSION_REVISION 149
|
||||
|
||||
// server info.
|
||||
#define RTMP_SIG_SRS_KEY "SRS"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue