mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 20:31:56 +00:00
refine hls code, reorder classes.
This commit is contained in:
parent
d6897205c7
commit
b4eb38c86b
4 changed files with 175 additions and 155 deletions
|
@ -349,28 +349,6 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
SrsM3u8Segment::SrsM3u8Segment()
|
||||
{
|
||||
duration = 0;
|
||||
sequence_no = 0;
|
||||
muxer = new SrsTSMuxer();
|
||||
segment_start_dts = 0;
|
||||
}
|
||||
|
||||
SrsM3u8Segment::~SrsM3u8Segment()
|
||||
{
|
||||
srs_freep(muxer);
|
||||
}
|
||||
|
||||
SrsHlsAacJitter::SrsHlsAacJitter()
|
||||
{
|
||||
base_pts = 0;
|
||||
nb_samples = 0;
|
||||
|
||||
// TODO: config it, 0 means no adjust
|
||||
sync_ms = SRS_CONF_DEFAULT_AAC_SYNC;
|
||||
}
|
||||
|
||||
SrsHlsAacJitter::~SrsHlsAacJitter()
|
||||
{
|
||||
}
|
||||
|
@ -421,6 +399,111 @@ void SrsHlsAacJitter::on_buffer_continue()
|
|||
nb_samples++;
|
||||
}
|
||||
|
||||
SrsM3u8Segment::SrsM3u8Segment()
|
||||
{
|
||||
duration = 0;
|
||||
sequence_no = 0;
|
||||
muxer = new SrsTSMuxer();
|
||||
segment_start_dts = 0;
|
||||
}
|
||||
|
||||
SrsM3u8Segment::~SrsM3u8Segment()
|
||||
{
|
||||
srs_freep(muxer);
|
||||
}
|
||||
|
||||
double SrsM3u8Segment::update_duration(int64_t video_stream_dts)
|
||||
{
|
||||
duration = (video_stream_dts - segment_start_dts) / 90000.0;
|
||||
srs_assert(duration > 0);
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
SrsHlsAacJitter::SrsHlsAacJitter()
|
||||
{
|
||||
base_pts = 0;
|
||||
nb_samples = 0;
|
||||
|
||||
// TODO: config it, 0 means no adjust
|
||||
sync_ms = SRS_CONF_DEFAULT_AAC_SYNC;
|
||||
}
|
||||
|
||||
SrsTSMuxer::SrsTSMuxer()
|
||||
{
|
||||
fd = -1;
|
||||
_fresh = false;
|
||||
}
|
||||
|
||||
SrsTSMuxer::~SrsTSMuxer()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
int SrsTSMuxer::open(std::string _path)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
path = _path;
|
||||
|
||||
close();
|
||||
|
||||
int flags = O_CREAT|O_WRONLY|O_TRUNC;
|
||||
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
|
||||
if ((fd = ::open(path.c_str(), flags, mode)) < 0) {
|
||||
ret = ERROR_HLS_OPEN_FAILED;
|
||||
srs_error("open ts file %s failed. ret=%d", path.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// write mpegts header
|
||||
if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_fresh = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_fresh = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsTSMuxer::close()
|
||||
{
|
||||
if (fd > 0) {
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
_fresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SrsTSMuxer::fresh()
|
||||
{
|
||||
return _fresh;
|
||||
}
|
||||
|
||||
SrsHls::SrsHls()
|
||||
{
|
||||
hls_enabled = false;
|
||||
|
@ -430,7 +513,7 @@ SrsHls::SrsHls()
|
|||
jitter = new SrsRtmpJitter();
|
||||
aac_jitter = new SrsHlsAacJitter();
|
||||
file_index = 0;
|
||||
audio_buffer_start_pts = m3u8_dts = stream_dts = 0;
|
||||
audio_buffer_start_pts = video_stream_dts = 0;
|
||||
hls_fragment = hls_window = 0;
|
||||
|
||||
// TODO: config it.
|
||||
|
@ -583,14 +666,15 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) {
|
||||
int64_t corrected_time = 0;
|
||||
if ((ret = jitter->correct(audio, 0, 0, &corrected_time)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_assert(current);
|
||||
|
||||
// the pts calc from rtmp/flv header.
|
||||
int64_t pts = audio->header.timestamp * 90;
|
||||
int64_t pts = corrected_time * 90;
|
||||
|
||||
// flush if audio delay exceed
|
||||
if (pts - audio_buffer_start_pts > audio_delay * 90) {
|
||||
|
@ -650,7 +734,8 @@ int SrsHls::on_video(SrsSharedPtrMessage* video)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) {
|
||||
int64_t corrected_time = 0;
|
||||
if ((ret = jitter->correct(video, 0, 0, &corrected_time)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -659,16 +744,16 @@ int SrsHls::on_video(SrsSharedPtrMessage* video)
|
|||
return ret;
|
||||
}
|
||||
|
||||
stream_dts = video_frame->dts = video->header.timestamp * 90;
|
||||
video_stream_dts = video_frame->dts = corrected_time * 90;
|
||||
video_frame->pts = video_frame->dts + sample->cts * 90;
|
||||
video_frame->pid = TS_VIDEO_PID;
|
||||
video_frame->sid = TS_VIDEO_AVC;
|
||||
video_frame->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||
|
||||
// reopen the muxer for a gop
|
||||
srs_assert(current);
|
||||
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
|
||||
int64_t diff = stream_dts - m3u8_dts;
|
||||
if (diff / 90000 >= hls_fragment) {
|
||||
if (current->duration >= hls_fragment) {
|
||||
if ((ret = reopen()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -676,6 +761,9 @@ int SrsHls::on_video(SrsSharedPtrMessage* video)
|
|||
}
|
||||
|
||||
srs_assert(current);
|
||||
// update the duration of segment.
|
||||
current->update_duration(video_stream_dts);
|
||||
|
||||
if ((ret = current->muxer->write_video(video_frame, video_buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -712,11 +800,8 @@ int SrsHls::reopen()
|
|||
return ret;
|
||||
}
|
||||
|
||||
// start new segment.
|
||||
// close current segment and update the m3u8 file.
|
||||
if (current) {
|
||||
current->duration = (stream_dts - current->segment_start_dts) / 90000.0;
|
||||
srs_assert(current->duration > 0);
|
||||
|
||||
// assert segment duplicate.
|
||||
std::vector<SrsM3u8Segment*>::iterator it;
|
||||
it = std::find(segments.begin(), segments.end(), current);
|
||||
|
@ -774,7 +859,7 @@ int SrsHls::reopen()
|
|||
// new segment.
|
||||
current = new SrsM3u8Segment();
|
||||
current->sequence_no = file_index++;
|
||||
m3u8_dts = current->segment_start_dts = stream_dts;
|
||||
current->segment_start_dts = video_stream_dts;
|
||||
|
||||
// generate filename.
|
||||
char filename[128];
|
||||
|
@ -1106,80 +1191,5 @@ int SrsHls::flush_audio()
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsTSMuxer::SrsTSMuxer()
|
||||
{
|
||||
fd = -1;
|
||||
_fresh = false;
|
||||
}
|
||||
|
||||
SrsTSMuxer::~SrsTSMuxer()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
int SrsTSMuxer::open(std::string _path)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
path = _path;
|
||||
|
||||
close();
|
||||
|
||||
int flags = O_CREAT|O_WRONLY|O_TRUNC;
|
||||
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
|
||||
if ((fd = ::open(path.c_str(), flags, mode)) < 0) {
|
||||
ret = ERROR_HLS_OPEN_FAILED;
|
||||
srs_error("open ts file %s failed. ret=%d", path.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// write mpegts header
|
||||
if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_fresh = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTSMuxer::write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(fd, audio_frame, audio_buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_fresh = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTSMuxer::write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(fd, video_frame, video_buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsTSMuxer::close()
|
||||
{
|
||||
if (fd > 0) {
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
_fresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SrsTSMuxer::fresh()
|
||||
{
|
||||
return _fresh;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -44,29 +44,6 @@ class SrsTSMuxer;
|
|||
class SrsCodec;
|
||||
class SrsRequest;
|
||||
|
||||
/**
|
||||
* 3.3.2. EXTINF
|
||||
* The EXTINF tag specifies the duration of a media segment.
|
||||
*/
|
||||
struct SrsM3u8Segment
|
||||
{
|
||||
// duration in seconds in m3u8.
|
||||
double duration;
|
||||
// sequence number in m3u8.
|
||||
int sequence_no;
|
||||
// ts uri in m3u8.
|
||||
std::string uri;
|
||||
// ts full file to write.
|
||||
std::string full_path;
|
||||
// the muxer to write ts.
|
||||
SrsTSMuxer* muxer;
|
||||
// current segment start dts for m3u8
|
||||
int64_t segment_start_dts;
|
||||
|
||||
SrsM3u8Segment();
|
||||
virtual ~SrsM3u8Segment();
|
||||
};
|
||||
|
||||
/**
|
||||
* jitter correct for audio,
|
||||
* the sample rate 44100/32000 will lost precise,
|
||||
|
@ -97,6 +74,52 @@ public:
|
|||
virtual void on_buffer_continue();
|
||||
};
|
||||
|
||||
/**
|
||||
* 3.3.2. EXTINF
|
||||
* The EXTINF tag specifies the duration of a media segment.
|
||||
*/
|
||||
struct SrsM3u8Segment
|
||||
{
|
||||
// duration in seconds in m3u8.
|
||||
double duration;
|
||||
// sequence number in m3u8.
|
||||
int sequence_no;
|
||||
// ts uri in m3u8.
|
||||
std::string uri;
|
||||
// ts full file to write.
|
||||
std::string full_path;
|
||||
// the muxer to write ts.
|
||||
SrsTSMuxer* muxer;
|
||||
// current segment start dts for m3u8
|
||||
int64_t segment_start_dts;
|
||||
|
||||
SrsM3u8Segment();
|
||||
virtual ~SrsM3u8Segment();
|
||||
|
||||
/**
|
||||
* update the segment duration.
|
||||
*/
|
||||
virtual double update_duration(int64_t video_stream_dts);
|
||||
};
|
||||
|
||||
//TODO: refine the ts muxer, do more jobs.
|
||||
class SrsTSMuxer
|
||||
{
|
||||
private:
|
||||
int fd;
|
||||
std::string path;
|
||||
bool _fresh;
|
||||
public:
|
||||
SrsTSMuxer();
|
||||
virtual ~SrsTSMuxer();
|
||||
public:
|
||||
virtual int open(std::string _path);
|
||||
virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer);
|
||||
virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer);
|
||||
virtual void close();
|
||||
virtual bool fresh();
|
||||
};
|
||||
|
||||
/**
|
||||
* write m3u8 hls.
|
||||
*/
|
||||
|
@ -127,10 +150,8 @@ private:
|
|||
SrsMpegtsFrame* video_frame;
|
||||
SrsCodecBuffer* video_buffer;
|
||||
// last known dts
|
||||
int64_t stream_dts;
|
||||
int64_t video_stream_dts;
|
||||
int64_t audio_buffer_start_pts;
|
||||
// last segment dts in m3u8
|
||||
int64_t m3u8_dts;
|
||||
// in ms, audio delay to flush the audios.
|
||||
int64_t audio_delay;
|
||||
private:
|
||||
|
@ -159,24 +180,6 @@ private:
|
|||
virtual int flush_audio();
|
||||
};
|
||||
|
||||
//TODO: refine the ts muxer, do more jobs.
|
||||
class SrsTSMuxer
|
||||
{
|
||||
private:
|
||||
int fd;
|
||||
std::string path;
|
||||
bool _fresh;
|
||||
public:
|
||||
SrsTSMuxer();
|
||||
virtual ~SrsTSMuxer();
|
||||
public:
|
||||
virtual int open(std::string _path);
|
||||
virtual int write_audio(SrsMpegtsFrame* audio_frame, SrsCodecBuffer* audio_buffer);
|
||||
virtual int write_video(SrsMpegtsFrame* video_frame, SrsCodecBuffer* video_buffer);
|
||||
virtual void close();
|
||||
virtual bool fresh();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -49,7 +49,7 @@ SrsRtmpJitter::~SrsRtmpJitter()
|
|||
{
|
||||
}
|
||||
|
||||
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv)
|
||||
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
@ -93,7 +93,12 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv)
|
|||
}
|
||||
|
||||
last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta);
|
||||
|
||||
if (corrected_time) {
|
||||
*corrected_time = last_pkt_correct_time;
|
||||
}
|
||||
msg->header.timestamp = last_pkt_correct_time;
|
||||
|
||||
last_pkt_time = time;
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -62,8 +62,10 @@ public:
|
|||
public:
|
||||
/**
|
||||
* detect the time jitter and correct it.
|
||||
* @param corrected_time output the 64bits time.
|
||||
* ignore if NULL.
|
||||
*/
|
||||
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv, int64_t* corrected_time = NULL);
|
||||
/**
|
||||
* get current client time, the last packet time.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue