1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

support HLS, refine the dir use app

This commit is contained in:
winlin 2013-11-26 17:21:49 +08:00
parent 57ea56970d
commit 04cfe20279
7 changed files with 74 additions and 20 deletions

View file

@ -13,6 +13,8 @@ vhost __defaultVhost__ {
gop_cache on; gop_cache on;
hls on; hls on;
hls_path ./objs/nginx/html; hls_path ./objs/nginx/html;
hls_fragment 10;
hls_window 60;
} }
# the vhost disabled. # the vhost disabled.
vhost removed.vhost.com { vhost removed.vhost.com {
@ -39,6 +41,12 @@ vhost no-hls.vhost.com {
# in a word, the hls_path is for vhost. # in a word, the hls_path is for vhost.
# default: ./objs/nginx/html # default: ./objs/nginx/html
hls_path /data/nginx/html; hls_path /data/nginx/html;
# the hls fragment in seconds, the duration of a piece of ts.
# default: 10
hls_fragment 10;
# the hls window in seconds, the number of ts in m3u8.
# default: 60
hls_window 60;
} }
# the vhost with hls disabled. # the vhost with hls disabled.
vhost no-hls.vhost.com { vhost no-hls.vhost.com {

View file

@ -332,7 +332,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle)
SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
// notify the hls to prepare when publish start. // notify the hls to prepare when publish start.
if ((ret = source->on_publish(req->vhost, req->stream)) != ERROR_SUCCESS) { if ((ret = source->on_publish(req->vhost, req->app, req->stream)) != ERROR_SUCCESS) {
srs_error("hls on_publish failed. ret=%d", ret); srs_error("hls on_publish failed. ret=%d", ret);
return ret; return ret;
} }

View file

@ -109,7 +109,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_HLS_METADATA 600 #define ERROR_HLS_METADATA 600
#define ERROR_HLS_DECODE_ERROR 601 #define ERROR_HLS_DECODE_ERROR 601
//#define ERROR_HLS_BUSY 602 #define ERROR_HLS_CREATE_DIR 602
#define ERROR_HLS_OPEN_FAILED 603 #define ERROR_HLS_OPEN_FAILED 603
#define ERROR_HLS_WRITE_FAILED 604 #define ERROR_HLS_WRITE_FAILED 604
#define ERROR_HLS_AAC_FRAME_LENGTH 605 #define ERROR_HLS_AAC_FRAME_LENGTH 605

View file

@ -403,12 +403,13 @@ SrsHLS::~SrsHLS()
srs_freep(video_frame); srs_freep(video_frame);
} }
int SrsHLS::on_publish(std::string _vhost, std::string _stream) int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
vhost = _vhost; vhost = _vhost;
stream = _stream; stream = _stream;
app = _app;
if ((ret = reopen()) != ERROR_SUCCESS) { if ((ret = reopen()) != ERROR_SUCCESS) {
return ret; return ret;
@ -555,6 +556,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video)
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
int64_t diff = stream_dts - m3u8_dts; int64_t diff = stream_dts - m3u8_dts;
// 10s. // 10s.
// TODO: config it.
if (diff / 90000 >= 10) { if (diff / 90000 >= 10) {
if ((ret = reopen()) != ERROR_SUCCESS) { if ((ret = reopen()) != ERROR_SUCCESS) {
return ret; return ret;
@ -590,6 +592,11 @@ int SrsHLS::reopen()
hls_path = conf->arg0(); hls_path = conf->arg0();
} }
// create dir for app.
if ((ret = create_dir()) != ERROR_SUCCESS) {
return ret;
}
// start new segment. // start new segment.
if (current) { if (current) {
current->duration = (stream_dts - current->segment_start_dts) / 90000.0; current->duration = (stream_dts - current->segment_start_dts) / 90000.0;
@ -610,6 +617,8 @@ int SrsHLS::reopen()
current->full_path = hls_path; current->full_path = hls_path;
current->full_path += "/"; current->full_path += "/";
current->full_path += app;
current->full_path += "/";
current->full_path += filename; current->full_path += filename;
// TODO: support base url, and so on. // TODO: support base url, and so on.
@ -619,7 +628,7 @@ int SrsHLS::reopen()
srs_error("open hls muxer failed. ret=%d", ret); srs_error("open hls muxer failed. ret=%d", ret);
return ret; return ret;
} }
srs_trace("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str());
return ret; return ret;
} }
@ -628,16 +637,33 @@ int SrsHLS::refresh_m3u8()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
std::string m3u8_file = hls_path;
m3u8_file += "/";
m3u8_file += app;
m3u8_file += "/";
m3u8_file += stream;
m3u8_file += ".m3u8";
m3u8 = m3u8_file;
m3u8_file += ".temp";
int fd = -1; int fd = -1;
ret = _refresh_m3u8(fd); ret = _refresh_m3u8(fd, m3u8_file);
if (fd >= 0) { if (fd >= 0) {
close(fd); close(fd);
if (rename(m3u8_file.c_str(), m3u8.c_str()) < 0) {
ret = ERROR_HLS_WRITE_FAILED;
srs_error("rename m3u8 file failed. ret=%d", ret);
}
} }
// remove the temp file.
unlink(m3u8_file.c_str());
return ret; return ret;
} }
int SrsHLS::_refresh_m3u8(int& fd) int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -646,19 +672,14 @@ int SrsHLS::_refresh_m3u8(int& fd)
return ret; return ret;
} }
m3u8 = hls_path;
m3u8 += "/";
m3u8 += stream;
m3u8 += ".m3u8";
int flags = O_CREAT|O_WRONLY|O_TRUNC; int flags = O_CREAT|O_WRONLY|O_TRUNC;
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
if ((fd = ::open(m3u8.c_str(), flags, mode)) < 0) { if ((fd = ::open(m3u8_file.c_str(), flags, mode)) < 0) {
ret = ERROR_HLS_OPEN_FAILED; ret = ERROR_HLS_OPEN_FAILED;
srs_error("open m3u8 file %s failed. ret=%d", m3u8.c_str(), ret); srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret);
return ret; return ret;
} }
srs_info("open m3u8 file %s success.", m3u8.c_str()); srs_info("open m3u8 file %s success.", m3u8_file.c_str());
// #EXTM3U\n#EXT-X-VERSION:3\n // #EXTM3U\n#EXT-X-VERSION:3\n
char header[] = { char header[] = {
@ -728,11 +749,34 @@ int SrsHLS::_refresh_m3u8(int& fd)
} }
srs_verbose("write m3u8 segment uri success."); srs_verbose("write m3u8 segment uri success.");
} }
srs_info("write m3u8 %s success.", m3u8.c_str()); srs_info("write m3u8 %s success.", m3u8_file.c_str());
return ret; return ret;
} }
int SrsHLS::create_dir()
{
int ret = ERROR_SUCCESS;
std::string app_dir = hls_path;
app_dir += "/";
app_dir += app;
// TODO: cleanup the dir when startup.
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
if (::mkdir(app_dir.c_str(), mode) < 0) {
if (errno != EEXIST) {
ret = ERROR_HLS_CREATE_DIR;
srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
return ret;
}
}
srs_info("create app dir %s success.", app_dir.c_str());
return ret;
}
SrsTSMuxer::SrsTSMuxer() SrsTSMuxer::SrsTSMuxer()
{ {
fd = -1; fd = -1;

View file

@ -72,6 +72,7 @@ class SrsHLS
private: private:
std::string vhost; std::string vhost;
std::string stream; std::string stream;
std::string app;
std::string hls_path; std::string hls_path;
private: private:
int file_index; int file_index;
@ -103,7 +104,7 @@ public:
SrsHLS(); SrsHLS();
virtual ~SrsHLS(); virtual ~SrsHLS();
public: public:
virtual int on_publish(std::string _vhost, std::string _stream); virtual int on_publish(std::string _vhost, std::string _app, std::string _stream);
virtual void on_unpublish(); virtual void on_unpublish();
virtual int on_meta_data(SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
virtual int on_audio(SrsSharedPtrMessage* audio); virtual int on_audio(SrsSharedPtrMessage* audio);
@ -111,7 +112,8 @@ public:
private: private:
virtual int reopen(); virtual int reopen();
virtual int refresh_m3u8(); virtual int refresh_m3u8();
virtual int _refresh_m3u8(int& fd); virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
virtual int create_dir();
}; };
class SrsTSMuxer class SrsTSMuxer

View file

@ -452,9 +452,9 @@ int SrsSource::on_video(SrsCommonMessage* video)
return ret; return ret;
} }
int SrsSource::on_publish(std::string vhost, std::string stream) int SrsSource::on_publish(std::string vhost, std::string app, std::string stream)
{ {
return hls->on_publish(vhost, stream); return hls->on_publish(vhost, app, stream);
} }
void SrsSource::on_unpublish() void SrsSource::on_unpublish()

View file

@ -166,7 +166,7 @@ public:
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
virtual int on_audio(SrsCommonMessage* audio); virtual int on_audio(SrsCommonMessage* audio);
virtual int on_video(SrsCommonMessage* video); virtual int on_video(SrsCommonMessage* video);
virtual int on_publish(std::string vhost, std::string stream); virtual int on_publish(std::string vhost, std::string app, std::string stream);
virtual void on_unpublish(); virtual void on_unpublish();
public: public:
virtual int create_consumer(SrsConsumer*& consumer); virtual int create_consumer(SrsConsumer*& consumer);