Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add crossdomain support in http_remux and hls for HTML5 playback #691

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 41 additions & 2 deletions trunk/src/app/srs_app_config.cpp
Expand Up @@ -70,6 +70,7 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER;
#define SRS_CONF_DEFAULT_UTC_TIME false

#define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000
#define SRS_CONF_DEFAULT_HLS_CROSSDOMAIN true
#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"
Expand Down Expand Up @@ -107,6 +108,7 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER;

#define SRS_CONF_DEFAULT_HTTP_MOUNT "[vhost]/"
#define SRS_CONF_DEFAULT_HTTP_REMUX_MOUNT "[vhost]/[app]/[stream].flv"
#define SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN true
#define SRS_CONF_DEFAULT_HTTP_DIR SRS_CONF_DEFAULT_HLS_PATH
#define SRS_CONF_DEFAULT_HTTP_AUDIO_FAST_CACHE 0

Expand Down Expand Up @@ -1888,7 +1890,7 @@ int SrsConfig::check_config()
} else if (n == "http_remux") {
for (int j = 0; j < (int)conf->directives.size(); j++) {
string m = conf->at(j)->name.c_str();
if (m != "enabled" && m != "mount" && m != "fast_cache" && m != "hstrs") {
if (m != "enabled" && m != "mount" && m != "crossdomain" && m != "fast_cache" && m != "hstrs") {
ret = ERROR_SYSTEM_CONFIG_INVALID;
srs_error("unsupported vhost http_remux directive %s, ret=%d", m.c_str(), ret);
return ret;
Expand All @@ -1897,7 +1899,7 @@ int SrsConfig::check_config()
} else if (n == "hls") {
for (int j = 0; j < (int)conf->directives.size(); j++) {
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"
if (m != "enabled" && m != "crossdomain" && 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" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify"
&& m != "hls_wait_keyframe" && m != "hls_dispose"
Expand Down Expand Up @@ -3623,6 +3625,23 @@ bool SrsConfig::get_hls_enabled(string vhost)
return SRS_CONF_PERFER_FALSE(conf->arg0());
}

bool SrsConfig::get_hls_crossdomain(string vhost)
{
SrsConfDirective* hls = get_hls(vhost);

if (!hls) {
return SRS_CONF_DEFAULT_HLS_CROSSDOMAIN;
}

SrsConfDirective* conf = hls->get("crossdomain");

if (!conf || conf->arg0().empty()) {
return SRS_CONF_DEFAULT_HLS_CROSSDOMAIN;
}

return SRS_CONF_PERFER_TRUE(conf->arg0());
}

string SrsConfig::get_hls_entry_prefix(string vhost)
{
SrsConfDirective* hls = get_hls(vhost);
Expand Down Expand Up @@ -4334,6 +4353,26 @@ bool SrsConfig::get_vhost_http_remux_enabled(string vhost)
return SRS_CONF_PERFER_FALSE(conf->arg0());
}

bool SrsConfig::get_vhost_http_remux_crossdomain(string vhost)
{
SrsConfDirective* conf = get_vhost(vhost);
if (!conf) {
return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN;
}

conf = conf->get("http_remux");
if (!conf) {
return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN;
}

conf = conf->get("crossdomain");
if (!conf || conf->arg0().empty()) {
return SRS_CONF_DEFAULT_HTTP_REMUX_CROSSDOMAIN;
}

return SRS_CONF_PERFER_TRUE(conf->arg0());
}

double SrsConfig::get_vhost_http_remux_fast_cache(string vhost)
{
SrsConfDirective* conf = get_vhost(vhost);
Expand Down
8 changes: 8 additions & 0 deletions trunk/src/app/srs_app_config.hpp
Expand Up @@ -870,6 +870,10 @@ class SrsConfig
*/
virtual bool get_hls_enabled(std::string vhost);
/**
* whether enable crossdomain for HLS.
*/
virtual bool get_hls_crossdomain(std::string vhost);
/**
* get the HLS m3u8 list ts segment entry prefix info.
*/
virtual std::string get_hls_entry_prefix(std::string vhost);
Expand Down Expand Up @@ -1071,6 +1075,10 @@ class SrsConfig
*/
virtual bool get_vhost_http_remux_enabled(std::string vhost);
/**
* whether enable crossdomain for http remux.
*/
virtual bool get_vhost_http_remux_crossdomain(std::string vhost);
/**
* get the fast cache duration for http audio live stream.
*/
virtual double get_vhost_http_remux_fast_cache(std::string vhost);
Expand Down
52 changes: 43 additions & 9 deletions trunk/src/app/srs_app_http_stream.cpp
Expand Up @@ -450,11 +450,12 @@ int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
return writer->writev(iov, iovcnt, pnwrite);
}

SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c, bool crossdomain)
{
source = s;
cache = c;
req = r->copy();
enable_crossdomain = crossdomain;
}

SrsLiveStream::~SrsLiveStream()
Expand All @@ -473,6 +474,11 @@ int SrsLiveStream::update(SrsSource* s, SrsRequest* r)
return ret;
}

void SrsLiveStream::reset_crossdomain(bool crossdomain)
{
enable_crossdomain = crossdomain;
}

int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
int ret = ERROR_SUCCESS;
Expand Down Expand Up @@ -503,6 +509,10 @@ int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
}
SrsAutoFree(ISrsStreamEncoder, enc);

if (enable_crossdomain) {
w->header()->set("Access-Control-Allow-Origin", "*");
}

// create consumer of souce, ignore gop cache, use the audio gop cache.
SrsConsumer* consumer = NULL;
if ((ret = source->create_consumer(NULL, consumer, true, true, !enc->has_cache())) != ERROR_SUCCESS) {
Expand Down Expand Up @@ -614,9 +624,10 @@ int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrM
return ret;
}

SrsLiveEntry::SrsLiveEntry(std::string m, bool h)
SrsLiveEntry::SrsLiveEntry(std::string m, bool c, bool h)
{
mount = m;
crossdomain = c;
hstrs = h;

stream = NULL;
Expand All @@ -641,6 +652,11 @@ void SrsLiveEntry::reset_hstrs(bool h)
hstrs = h;
}

void SrsLiveEntry::reset_crossdomain(bool c)
{
crossdomain = c;
}

bool SrsLiveEntry::is_flv()
{
return _is_flv;
Expand All @@ -661,8 +677,9 @@ bool SrsLiveEntry::is_mp3()
return _is_mp3;
}

SrsHlsM3u8Stream::SrsHlsM3u8Stream()
SrsHlsM3u8Stream::SrsHlsM3u8Stream(bool crossdomain)
{
enable_crossdomain = crossdomain;
}

SrsHlsM3u8Stream::~SrsHlsM3u8Stream()
Expand All @@ -683,6 +700,10 @@ int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
w->header()->set_content_length((int)data.length());
w->header()->set_content_type("application/x-mpegURL;charset=utf-8");

if (enable_crossdomain) {
w->header()->set("Access-Control-Allow-Origin", "*");
}

if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send m3u8 failed. ret=%d", ret);
Expand All @@ -693,8 +714,9 @@ int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
return ret;
}

SrsHlsTsStream::SrsHlsTsStream()
SrsHlsTsStream::SrsHlsTsStream(bool crossdomain)
{
enable_crossdomain = crossdomain;
}

SrsHlsTsStream::~SrsHlsTsStream()
Expand All @@ -715,6 +737,10 @@ int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
w->header()->set_content_length((int)data.length());
w->header()->set_content_type("video/MP2T");

if (enable_crossdomain) {
w->header()->set("Access-Control-Allow-Origin", "*");
}

if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send ts failed. ret=%d", ret);
Expand Down Expand Up @@ -823,10 +849,10 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r)
// remove the default vhost mount
mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");

entry = new SrsLiveEntry(mount, tmpl->hstrs);
entry = new SrsLiveEntry(mount, tmpl->crossdomain, tmpl->hstrs);

entry->cache = new SrsStreamCache(s, r);
entry->stream = new SrsLiveStream(s, r, entry->cache);
entry->stream = new SrsLiveStream(s, r, entry->cache, entry->crossdomain);

// TODO: FIXME: maybe refine the logic of http remux service.
// if user push streams followed:
Expand Down Expand Up @@ -924,8 +950,10 @@ int SrsHttpStreamServer::on_reload_vhost_http_remux_updated(string vhost)
string old_tmpl_mount = tmpl->mount;
string new_tmpl_mount = _srs_config->get_vhost_http_remux_mount(vhost);
bool hstrs = _srs_config->get_vhost_http_remux_hstrs(vhost);
bool crossdomain = _srs_config->get_vhost_http_remux_crossdomain(vhost);

tmpl->reset_hstrs(hstrs);
tmpl->reset_crossdomain(crossdomain);

/**
* TODO: not support to reload different mount url for the time being.
Expand All @@ -941,6 +969,8 @@ int SrsHttpStreamServer::on_reload_vhost_http_remux_updated(string vhost)
if (sflvs.find(sid) != sflvs.end()) {
SrsLiveEntry* stream = sflvs[sid];
stream->reset_hstrs(hstrs);
stream->reset_crossdomain(crossdomain);
stream->stream->reset_crossdomain(crossdomain);
}
// remount stream.
if ((ret = http_mount(source, req)) != ERROR_SUCCESS) {
Expand Down Expand Up @@ -1013,9 +1043,11 @@ int SrsHttpStreamServer::hls_update_m3u8(SrsRequest* r, string m3u8)
entry->tmpl = tmpl;
entry->mount = mount;
shls[sid] = entry;


bool enable_crossdomain = _srs_config->get_hls_crossdomain(r->vhost);

if (entry->streams.find(mount) == entry->streams.end()) {
ISrsHttpHandler* he = new SrsHlsM3u8Stream();
ISrsHttpHandler* he = new SrsHlsM3u8Stream(enable_crossdomain);
entry->streams[mount] = he;

if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {
Expand Down Expand Up @@ -1061,10 +1093,11 @@ int SrsHttpStreamServer::hls_update_ts(SrsRequest* r, string uri, string ts)
srs_assert(entry);
srs_assert(entry->tmpl);

bool enable_crossdomain = _srs_config->get_hls_crossdomain(r->vhost);
std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount);

if (entry->streams.find(mount) == entry->streams.end()) {
ISrsHttpHandler* he = new SrsHlsTsStream();
ISrsHttpHandler* he = new SrsHlsTsStream(enable_crossdomain);
entry->streams[mount] = he;

if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {
Expand Down Expand Up @@ -1287,6 +1320,7 @@ int SrsHttpStreamServer::initialize_flv_entry(std::string vhost)

SrsLiveEntry* entry = new SrsLiveEntry(
_srs_config->get_vhost_http_remux_mount(vhost),
_srs_config->get_vhost_http_remux_crossdomain(vhost),
_srs_config->get_vhost_http_remux_hstrs(vhost)
);

Expand Down
16 changes: 12 additions & 4 deletions trunk/src/app/srs_app_http_stream.hpp
Expand Up @@ -225,10 +225,13 @@ class SrsLiveStream : public ISrsHttpHandler
SrsRequest* req;
SrsSource* source;
SrsStreamCache* cache;
bool enable_crossdomain;
public:
SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c);
SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c, bool crossdomain);
virtual ~SrsLiveStream();
virtual int update(SrsSource* s, SrsRequest* r);
public:
void reset_crossdomain(bool crossdomain);
public:
virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
private:
Expand All @@ -252,14 +255,17 @@ struct SrsLiveEntry
// for template, the mount contains variables.
// for concrete stream, the mount is url to access.
std::string mount;
// whether crossdomain(Access-Control-Allow-Origin)
bool crossdomain;
// whether hstrs(http stream trigger rtmp source)
bool hstrs;

SrsLiveStream* stream;
SrsStreamCache* cache;

SrsLiveEntry(std::string m, bool h);
SrsLiveEntry(std::string m, bool c, bool h);
void reset_hstrs(bool h);
void reset_crossdomain(bool c);

bool is_flv();
bool is_ts();
Expand All @@ -274,8 +280,9 @@ class SrsHlsM3u8Stream : public ISrsHttpHandler
{
private:
std::string m3u8;
bool enable_crossdomain;
public:
SrsHlsM3u8Stream();
SrsHlsM3u8Stream(bool crossdomain);
virtual ~SrsHlsM3u8Stream();
public:
virtual void set_m3u8(std::string v);
Expand All @@ -290,8 +297,9 @@ class SrsHlsTsStream : public ISrsHttpHandler
{
private:
std::string ts;
bool enable_crossdomain;
public:
SrsHlsTsStream();
SrsHlsTsStream(bool crossdomain);
virtual ~SrsHlsTsStream();
public:
virtual void set_ts(std::string v);
Expand Down