mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
support hls republish
This commit is contained in:
parent
f25c6558a5
commit
5758551508
3 changed files with 54 additions and 6 deletions
|
@ -475,6 +475,7 @@ SrsHlsSegment::SrsHlsSegment()
|
||||||
sequence_no = 0;
|
sequence_no = 0;
|
||||||
muxer = new SrsTSMuxer();
|
muxer = new SrsTSMuxer();
|
||||||
segment_start_dts = 0;
|
segment_start_dts = 0;
|
||||||
|
is_sequence_header = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHlsSegment::~SrsHlsSegment()
|
SrsHlsSegment::~SrsHlsSegment()
|
||||||
|
@ -589,6 +590,19 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsHlsMuxer::on_sequence_header()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
srs_assert(current);
|
||||||
|
|
||||||
|
// set the current segment to sequence header,
|
||||||
|
// when close the segement, it will write a discontinuity to m3u8 file.
|
||||||
|
current->is_sequence_header = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool SrsHlsMuxer::is_segment_overflow()
|
bool SrsHlsMuxer::is_segment_overflow()
|
||||||
{
|
{
|
||||||
srs_assert(current);
|
srs_assert(current);
|
||||||
|
@ -810,7 +824,7 @@ int SrsHlsMuxer::_refresh_m3u8(int& fd, string m3u8_file)
|
||||||
}
|
}
|
||||||
// TODO: maybe need to take an around value
|
// TODO: maybe need to take an around value
|
||||||
target_duration += 1;
|
target_duration += 1;
|
||||||
char duration[34];
|
char duration[34]; // 23+10+1
|
||||||
len = snprintf(duration, sizeof(duration), "#EXT-X-TARGETDURATION:%d\n", target_duration);
|
len = snprintf(duration, sizeof(duration), "#EXT-X-TARGETDURATION:%d\n", target_duration);
|
||||||
if (::write(fd, duration, len) != len) {
|
if (::write(fd, duration, len) != len) {
|
||||||
ret = ERROR_HLS_WRITE_FAILED;
|
ret = ERROR_HLS_WRITE_FAILED;
|
||||||
|
@ -823,15 +837,27 @@ int SrsHlsMuxer::_refresh_m3u8(int& fd, string m3u8_file)
|
||||||
for (it = segments.begin(); it != segments.end(); ++it) {
|
for (it = segments.begin(); it != segments.end(); ++it) {
|
||||||
SrsHlsSegment* segment = *it;
|
SrsHlsSegment* segment = *it;
|
||||||
|
|
||||||
|
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\n");
|
||||||
|
if (::write(fd, ext_discon, len) != len) {
|
||||||
|
ret = ERROR_HLS_WRITE_FAILED;
|
||||||
|
srs_error("write m3u8 segment discontinuity failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("write m3u8 segment discontinuity success.");
|
||||||
|
}
|
||||||
|
|
||||||
// "#EXTINF:4294967295.208,\n"
|
// "#EXTINF:4294967295.208,\n"
|
||||||
char ext_info[25];
|
char ext_info[25]; // 14+10+1
|
||||||
len = snprintf(ext_info, sizeof(ext_info), "#EXTINF:%.3f\n", segment->duration);
|
len = snprintf(ext_info, sizeof(ext_info), "#EXTINF:%.3f\n", segment->duration);
|
||||||
if (::write(fd, ext_info, len) != len) {
|
if (::write(fd, ext_info, len) != len) {
|
||||||
ret = ERROR_HLS_WRITE_FAILED;
|
ret = ERROR_HLS_WRITE_FAILED;
|
||||||
srs_error("write m3u8 segment failed. ret=%d", ret);
|
srs_error("write m3u8 segment info failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("write m3u8 segment success.");
|
srs_verbose("write m3u8 segment info success.");
|
||||||
|
|
||||||
// file name
|
// file name
|
||||||
std::string filename = segment->uri;
|
std::string filename = segment->uri;
|
||||||
|
@ -945,6 +971,17 @@ int SrsHlsCache::on_unpublish(SrsHlsMuxer* muxer)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsHlsCache::on_sequence_header(SrsHlsMuxer* muxer)
|
||||||
|
{
|
||||||
|
// TODO: support discontinuity for the same stream
|
||||||
|
// currently we reap and insert discontinity when encoder republish,
|
||||||
|
// but actually, event when stream is not republish, the
|
||||||
|
// sequence header may change, for example,
|
||||||
|
// ffmpeg ingest a external rtmp stream and push to srs,
|
||||||
|
// when the sequence header changed, the stream is not republish.
|
||||||
|
return muxer->on_sequence_header();
|
||||||
|
}
|
||||||
|
|
||||||
int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample)
|
int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
@ -1336,7 +1373,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio)
|
||||||
|
|
||||||
// ignore sequence header
|
// ignore sequence header
|
||||||
if (sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
if (sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
||||||
return ret;
|
return hls_cache->on_sequence_header(muxer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) {
|
||||||
|
@ -1381,7 +1418,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video)
|
||||||
// ignore sequence header
|
// ignore sequence header
|
||||||
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame
|
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame
|
||||||
&& sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
&& sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
||||||
return ret;
|
return hls_cache->on_sequence_header(muxer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) {
|
||||||
|
|
|
@ -116,6 +116,8 @@ public:
|
||||||
SrsTSMuxer* muxer;
|
SrsTSMuxer* muxer;
|
||||||
// current segment start dts for m3u8
|
// current segment start dts for m3u8
|
||||||
int64_t segment_start_dts;
|
int64_t segment_start_dts;
|
||||||
|
// whether current segement is sequence header.
|
||||||
|
bool is_sequence_header;
|
||||||
|
|
||||||
SrsHlsSegment();
|
SrsHlsSegment();
|
||||||
virtual ~SrsHlsSegment();
|
virtual ~SrsHlsSegment();
|
||||||
|
@ -167,6 +169,7 @@ public:
|
||||||
* use 0 for the first segment of HLS.
|
* use 0 for the first segment of HLS.
|
||||||
*/
|
*/
|
||||||
virtual int segment_open(int64_t segment_start_dts);
|
virtual int segment_open(int64_t segment_start_dts);
|
||||||
|
virtual int on_sequence_header();
|
||||||
/**
|
/**
|
||||||
* whether video overflow,
|
* whether video overflow,
|
||||||
* that is whether the current segment duration >= the segment in config
|
* that is whether the current segment duration >= the segment in config
|
||||||
|
@ -233,6 +236,13 @@ public:
|
||||||
virtual int on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment_start_dts);
|
virtual int on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment_start_dts);
|
||||||
virtual int on_unpublish(SrsHlsMuxer* muxer);
|
virtual int on_unpublish(SrsHlsMuxer* muxer);
|
||||||
/**
|
/**
|
||||||
|
* when get sequence header,
|
||||||
|
* must write a #EXT-X-DISCONTINUITY to m3u8.
|
||||||
|
* @see: hls-m3u8-draft-pantos-http-live-streaming-12.txt
|
||||||
|
* @see: 3.4.11. EXT-X-DISCONTINUITY
|
||||||
|
*/
|
||||||
|
virtual int on_sequence_header(SrsHlsMuxer* muxer);
|
||||||
|
/**
|
||||||
* write audio to cache, if need to flush, flush to muxer.
|
* write audio to cache, if need to flush, flush to muxer.
|
||||||
*/
|
*/
|
||||||
virtual int write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample);
|
virtual int write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample);
|
||||||
|
|
|
@ -41,6 +41,7 @@ void srs_update_system_time_ms()
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
|
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/35
|
||||||
// we must convert the tv_sec/tv_usec to int64_t.
|
// we must convert the tv_sec/tv_usec to int64_t.
|
||||||
_srs_system_time_us_cache = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec;
|
_srs_system_time_us_cache = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue