mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #304, use stringstream to generate m3u8, add hls_td_ratio. 2.0.116.
This commit is contained in:
parent
103ce78b35
commit
25af6c6847
7 changed files with 60 additions and 52 deletions
|
@ -525,6 +525,7 @@ Supported operating systems and hardware:
|
|||
|
||||
### SRS 2.0 history
|
||||
|
||||
* v2.0, 2015-02-12, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), use stringstream to generate m3u8, add hls_td_ratio. 2.0.116.
|
||||
* v2.0, 2015-02-11, dev code ZhouGuowen for 2.0.115.
|
||||
* v2.0, 2015-02-10, for [#311](https://github.com/winlinvip/simple-rtmp-server/issues/311), set pcr_base to dts. 2.0.114.
|
||||
* v2.0, 2015-02-10, fix [the bug](https://github.com/winlinvip/simple-rtmp-server/commit/87519aaae835199e5adb60c0ae2c1cd24939448c) of ibmf format which decoded in annexb.
|
||||
|
|
|
@ -451,6 +451,12 @@ vhost with-hls.srs.com {
|
|||
# the hls fragment in seconds, the duration of a piece of ts.
|
||||
# default: 10
|
||||
hls_fragment 10;
|
||||
# the hls m3u8 target duration ratio,
|
||||
# EXT-X-TARGETDURATION = hls_td_ratio * hls_fragment // init
|
||||
# EXT-X-TARGETDURATION = max(ts_duration, EXT-X-TARGETDURATION) // for each ts
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/issues/304#issuecomment-74000081
|
||||
# default: 1.5
|
||||
hls_td_ratio 1.5;
|
||||
# the hls window in seconds, the number of ts in m3u8.
|
||||
# default: 60
|
||||
hls_window 60;
|
||||
|
|
|
@ -1480,7 +1480,7 @@ int SrsConfig::check_config()
|
|||
for (int j = 0; j < (int)conf->directives.size(); j++) {
|
||||
string m = conf->at(j)->name.c_str();
|
||||
if (m != "enabled" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error"
|
||||
&& m != "hls_storage" && m != "hls_mount"
|
||||
&& m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio"
|
||||
) {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret);
|
||||
|
@ -3247,6 +3247,23 @@ double SrsConfig::get_hls_fragment(string vhost)
|
|||
return ::atof(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
double SrsConfig::get_hls_td_ratio(string vhost)
|
||||
{
|
||||
SrsConfDirective* hls = get_hls(vhost);
|
||||
|
||||
if (!hls) {
|
||||
return SRS_CONF_DEFAULT_HLS_TD_RATIO;
|
||||
}
|
||||
|
||||
SrsConfDirective* conf = hls->get("hls_td_ratio");
|
||||
|
||||
if (!conf) {
|
||||
return SRS_CONF_DEFAULT_HLS_TD_RATIO;
|
||||
}
|
||||
|
||||
return ::atof(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
double SrsConfig::get_hls_window(string vhost)
|
||||
{
|
||||
SrsConfDirective* hls = get_hls(vhost);
|
||||
|
|
|
@ -47,6 +47,7 @@ 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_FRAGMENT 10
|
||||
#define SRS_CONF_DEFAULT_HLS_TD_RATIO 1.5
|
||||
#define SRS_CONF_DEFAULT_HLS_WINDOW 60
|
||||
#define SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE "ignore"
|
||||
#define SRS_CONF_DEFAULT_HLS_ON_ERROR_DISCONNECT "disconnect"
|
||||
|
@ -896,6 +897,11 @@ public:
|
|||
*/
|
||||
virtual double get_hls_fragment(std::string vhost);
|
||||
/**
|
||||
* get the hls td(target duration) ratio.
|
||||
* a fragment is a ts file.
|
||||
*/
|
||||
virtual double get_hls_td_ratio(std::string vhost);
|
||||
/**
|
||||
* get the hls window time, in seconds.
|
||||
* a window is a set of ts, the ts collection in m3u8.
|
||||
* @remark SRS will delete the ts exceed the window.
|
||||
|
|
|
@ -33,8 +33,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_kernel_error.hpp>
|
||||
|
@ -166,6 +168,7 @@ SrsHlsMuxer::SrsHlsMuxer(ISrsHlsHandler* h)
|
|||
req = NULL;
|
||||
handler = h;
|
||||
hls_fragment = hls_window = 0;
|
||||
target_duration = 0;
|
||||
_sequence_no = 0;
|
||||
current = NULL;
|
||||
acodec = SrsCodecAudioReserved1;
|
||||
|
@ -201,6 +204,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string path, int fragment, int win
|
|||
hls_path = path;
|
||||
hls_fragment = fragment;
|
||||
hls_window = window;
|
||||
target_duration = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost));
|
||||
|
||||
std::string storage = _srs_config->get_hls_storage(r->vhost);
|
||||
if (storage == "ram") {
|
||||
|
@ -503,35 +507,21 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
|
|||
}
|
||||
srs_info("open m3u8 file %s success.", m3u8_file.c_str());
|
||||
|
||||
// #EXTM3U\n#EXT-X-VERSION:3\n
|
||||
char header[] = {
|
||||
// #EXTM3U\n
|
||||
0x23, 0x45, 0x58, 0x54, 0x4d, 0x33, 0x55, SRS_CONSTS_LF,
|
||||
// #EXT-X-VERSION:3\n
|
||||
0x23, 0x45, 0x58, 0x54, 0x2d, 0x58, 0x2d, 0x56, 0x45, 0x52,
|
||||
0x53, 0x49, 0x4f, 0x4e, 0x3a, 0x33, SRS_CONSTS_LF,
|
||||
// #EXT-X-ALLOW-CACHE:NO\n
|
||||
0x23, 0x45, 0x58, 0x54, 0x2d, 0x58, 0x2d, 0x41, 0x4c, 0x4c,
|
||||
0x4f, 0x57, 0x2d, 0x43, 0x41, 0x43, 0x48, 0x45, 0x3a, 0x4e, 0x4f, SRS_CONSTS_LF
|
||||
};
|
||||
if ((ret = writer.write(header, sizeof(header), NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "#EXTM3U" << SRS_CONSTS_LF
|
||||
<< "#EXT-X-VERSION:3" << SRS_CONSTS_LF
|
||||
<< "#EXT-X-ALLOW-CACHE:NO" << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 header success.");
|
||||
|
||||
// #EXT-X-MEDIA-SEQUENCE:4294967295\n
|
||||
SrsHlsSegment* first = *segments.begin();
|
||||
char sequence[34] = {};
|
||||
int len = snprintf(sequence, sizeof(sequence), "#EXT-X-MEDIA-SEQUENCE:%d%c", first->sequence_no, SRS_CONSTS_LF);
|
||||
if ((ret = writer.write(sequence, len, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 sequence failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
ss << "#EXT-X-MEDIA-SEQUENCE:" << first->sequence_no << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 sequence success.");
|
||||
|
||||
// #EXT-X-TARGETDURATION:4294967295\n
|
||||
int target_duration = 0;
|
||||
/**
|
||||
* @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25
|
||||
* The Media Playlist file MUST contain an EXT-X-TARGETDURATION tag.
|
||||
|
@ -540,20 +530,13 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
|
|||
* rounded to the nearest integer. Its value MUST NOT change. A
|
||||
* typical target duration is 10 seconds.
|
||||
*/
|
||||
// TODO: FIXME: finger it out whether it should not changed.
|
||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/304#issuecomment-74000081
|
||||
std::vector<SrsHlsSegment*>::iterator it;
|
||||
for (it = segments.begin(); it != segments.end(); ++it) {
|
||||
SrsHlsSegment* segment = *it;
|
||||
target_duration = srs_max(target_duration, (int)segment->duration);
|
||||
}
|
||||
// TODO: maybe need to take an around value
|
||||
target_duration += 1;
|
||||
char duration[34]; // 23+10+1
|
||||
len = snprintf(duration, sizeof(duration), "#EXT-X-TARGETDURATION:%d%c", target_duration, SRS_CONSTS_LF);
|
||||
if ((ret = writer.write(duration, len, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 duration failed. ret=%d", ret);
|
||||
return ret;
|
||||
target_duration = srs_max(target_duration, (int)ceil(segment->duration));
|
||||
}
|
||||
ss << "#EXT-X-TARGETDURATION:" << target_duration << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 duration success.");
|
||||
|
||||
// write all segments
|
||||
|
@ -562,33 +545,27 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
|
|||
|
||||
if (segment->is_sequence_header) {
|
||||
// #EXT-X-DISCONTINUITY\n
|
||||
char ext_discon[22]; // 21+1
|
||||
len = snprintf(ext_discon, sizeof(ext_discon), "#EXT-X-DISCONTINUITY%c", SRS_CONSTS_LF);
|
||||
if ((ret = writer.write(ext_discon, len, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 segment discontinuity failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
ss << "#EXT-X-DISCONTINUITY" << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 segment discontinuity success.");
|
||||
}
|
||||
|
||||
// "#EXTINF:4294967295.208,\n"
|
||||
char ext_info[25]; // 14+10+1
|
||||
len = snprintf(ext_info, sizeof(ext_info), "#EXTINF:%.3f,%c", segment->duration, SRS_CONSTS_LF);
|
||||
if ((ret = writer.write(ext_info, len, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 segment info failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
ss.precision(3);
|
||||
ss.setf(std::ios::fixed, std::ios::floatfield);
|
||||
ss << "#EXTINF:" << segment->duration << "," << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 segment info success.");
|
||||
|
||||
// {file name}\n
|
||||
std::string filename = segment->uri;
|
||||
filename += SRS_CONSTS_LF;
|
||||
if ((ret = writer.write((char*)filename.c_str(), (int)filename.length(), NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 segment uri failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
ss << segment->uri << SRS_CONSTS_LF;
|
||||
srs_verbose("write m3u8 segment uri success.");
|
||||
}
|
||||
|
||||
// write m3u8 to writer.
|
||||
std::string m3u8 = ss.str();
|
||||
if ((ret = writer.write((char*)m3u8.c_str(), (int)m3u8.length(), NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("write m3u8 failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("write m3u8 %s success.", m3u8_file.c_str());
|
||||
|
||||
// notify handler for update m3u8.
|
||||
|
|
|
@ -172,6 +172,7 @@ private:
|
|||
int hls_window;
|
||||
private:
|
||||
int _sequence_no;
|
||||
int target_duration;
|
||||
std::string m3u8;
|
||||
private:
|
||||
ISrsHlsHandler* handler;
|
||||
|
|
|
@ -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 115
|
||||
#define VERSION_REVISION 116
|
||||
|
||||
// server info.
|
||||
#define RTMP_SIG_SRS_KEY "SRS"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue