mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
refine code, extract the rtmp jitter for hls
This commit is contained in:
parent
501b182dc9
commit
326713fbed
4 changed files with 100 additions and 63 deletions
|
@ -41,6 +41,7 @@ SrsHLS::SrsHLS()
|
||||||
codec = new SrsCodec();
|
codec = new SrsCodec();
|
||||||
sample = new SrsCodecSample();
|
sample = new SrsCodecSample();
|
||||||
muxer = NULL;
|
muxer = NULL;
|
||||||
|
jitter = new SrsRtmpJitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHLS::~SrsHLS()
|
SrsHLS::~SrsHLS()
|
||||||
|
@ -48,6 +49,7 @@ SrsHLS::~SrsHLS()
|
||||||
srs_freep(codec);
|
srs_freep(codec);
|
||||||
srs_freep(sample);
|
srs_freep(sample);
|
||||||
srs_freep(muxer);
|
srs_freep(muxer);
|
||||||
|
srs_freep(jitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHLS::on_publish(std::string _vhost)
|
int SrsHLS::on_publish(std::string _vhost)
|
||||||
|
|
|
@ -38,6 +38,7 @@ class SrsCodecBuffer;
|
||||||
class SrsMpegtsFrame;
|
class SrsMpegtsFrame;
|
||||||
class SrsTSMuxer;
|
class SrsTSMuxer;
|
||||||
class SrsCodec;
|
class SrsCodec;
|
||||||
|
class SrsRtmpJitter;
|
||||||
|
|
||||||
class SrsHLS
|
class SrsHLS
|
||||||
{
|
{
|
||||||
|
@ -47,6 +48,7 @@ private:
|
||||||
SrsCodec* codec;
|
SrsCodec* codec;
|
||||||
SrsCodecSample* sample;
|
SrsCodecSample* sample;
|
||||||
SrsTSMuxer* muxer;
|
SrsTSMuxer* muxer;
|
||||||
|
SrsRtmpJitter* jitter;
|
||||||
public:
|
public:
|
||||||
SrsHLS();
|
SrsHLS();
|
||||||
virtual ~SrsHLS();
|
virtual ~SrsHLS();
|
||||||
|
|
|
@ -36,23 +36,72 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define DEFAULT_FRAME_TIME_MS 10
|
#define DEFAULT_FRAME_TIME_MS 10
|
||||||
#define PAUSED_SHRINK_SIZE 250
|
#define PAUSED_SHRINK_SIZE 250
|
||||||
|
|
||||||
std::map<std::string, SrsSource*> SrsSource::pool;
|
SrsRtmpJitter::SrsRtmpJitter()
|
||||||
|
|
||||||
SrsSource* SrsSource::find(std::string stream_url)
|
|
||||||
{
|
{
|
||||||
if (pool.find(stream_url) == pool.end()) {
|
last_pkt_correct_time = last_pkt_time = 0;
|
||||||
pool[stream_url] = new SrsSource(stream_url);
|
}
|
||||||
srs_verbose("create new source for url=%s", stream_url.c_str());
|
|
||||||
|
SrsRtmpJitter::~SrsRtmpJitter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* we use a very simple time jitter detect/correct algorithm:
|
||||||
|
* 1. delta: ensure the delta is positive and valid,
|
||||||
|
* we set the delta to DEFAULT_FRAME_TIME_MS,
|
||||||
|
* if the delta of time is nagative or greater than CONST_MAX_JITTER_MS.
|
||||||
|
* 2. last_pkt_time: specifies the original packet time,
|
||||||
|
* is used to detect next jitter.
|
||||||
|
* 3. last_pkt_correct_time: simply add the positive delta,
|
||||||
|
* and enforce the time monotonically.
|
||||||
|
*/
|
||||||
|
u_int32_t time = msg->header.timestamp;
|
||||||
|
int32_t delta = time - last_pkt_time;
|
||||||
|
|
||||||
|
// if jitter detected, reset the delta.
|
||||||
|
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
||||||
|
// calc the right diff by audio sample rate
|
||||||
|
if (msg->header.is_audio() && audio_sample_rate > 0) {
|
||||||
|
delta = (int32_t)(delta * 1000.0 / audio_sample_rate);
|
||||||
|
} else if (msg->header.is_video() && video_frame_rate > 0) {
|
||||||
|
delta = (int32_t)(delta * 1.0 / video_frame_rate);
|
||||||
|
} else {
|
||||||
|
delta = DEFAULT_FRAME_TIME_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sometimes, the time is absolute time, so correct it again.
|
||||||
|
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
||||||
|
delta = DEFAULT_FRAME_TIME_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_info("jitter detected, last_pts=%d, pts=%d, diff=%d, last_time=%d, time=%d, diff=%d",
|
||||||
|
last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta);
|
||||||
|
} else {
|
||||||
|
srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d",
|
||||||
|
time, last_pkt_time, last_pkt_correct_time + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool[stream_url];
|
last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta);
|
||||||
|
msg->header.timestamp = last_pkt_correct_time;
|
||||||
|
last_pkt_time = time;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRtmpJitter::get_time()
|
||||||
|
{
|
||||||
|
return (int)last_pkt_correct_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConsumer::SrsConsumer(SrsSource* _source)
|
SrsConsumer::SrsConsumer(SrsSource* _source)
|
||||||
{
|
{
|
||||||
source = _source;
|
source = _source;
|
||||||
last_pkt_correct_time = last_pkt_time = 0;
|
|
||||||
paused = false;
|
paused = false;
|
||||||
|
jitter = new SrsRtmpJitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConsumer::~SrsConsumer()
|
SrsConsumer::~SrsConsumer()
|
||||||
|
@ -60,18 +109,19 @@ SrsConsumer::~SrsConsumer()
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
source->on_consumer_destroy(this);
|
source->on_consumer_destroy(this);
|
||||||
|
srs_freep(jitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConsumer::get_time()
|
int SrsConsumer::get_time()
|
||||||
{
|
{
|
||||||
return (int)last_pkt_correct_time;
|
return jitter->get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate)
|
int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = jitter_correct(msg, audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(msg, audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,53 +228,6 @@ void SrsConsumer::shrink()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate)
|
|
||||||
{
|
|
||||||
int ret = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* we use a very simple time jitter detect/correct algorithm:
|
|
||||||
* 1. delta: ensure the delta is positive and valid,
|
|
||||||
* we set the delta to DEFAULT_FRAME_TIME_MS,
|
|
||||||
* if the delta of time is nagative or greater than CONST_MAX_JITTER_MS.
|
|
||||||
* 2. last_pkt_time: specifies the original packet time,
|
|
||||||
* is used to detect next jitter.
|
|
||||||
* 3. last_pkt_correct_time: simply add the positive delta,
|
|
||||||
* and enforce the time monotonically.
|
|
||||||
*/
|
|
||||||
u_int32_t time = msg->header.timestamp;
|
|
||||||
int32_t delta = time - last_pkt_time;
|
|
||||||
|
|
||||||
// if jitter detected, reset the delta.
|
|
||||||
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
|
||||||
// calc the right diff by audio sample rate
|
|
||||||
if (msg->header.is_audio() && audio_sample_rate > 0) {
|
|
||||||
delta = (int32_t)(delta * 1000.0 / audio_sample_rate);
|
|
||||||
} else if (msg->header.is_video() && video_frame_rate > 0) {
|
|
||||||
delta = (int32_t)(delta * 1.0 / video_frame_rate);
|
|
||||||
} else {
|
|
||||||
delta = DEFAULT_FRAME_TIME_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sometimes, the time is absolute time, so correct it again.
|
|
||||||
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
|
||||||
delta = DEFAULT_FRAME_TIME_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
srs_info("jitter detected, last_pts=%d, pts=%d, diff=%d, last_time=%d, time=%d, diff=%d",
|
|
||||||
last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta);
|
|
||||||
} else {
|
|
||||||
srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d",
|
|
||||||
time, last_pkt_time, last_pkt_correct_time + delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta);
|
|
||||||
msg->header.timestamp = last_pkt_correct_time;
|
|
||||||
last_pkt_time = time;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsConsumer::clear()
|
void SrsConsumer::clear()
|
||||||
{
|
{
|
||||||
std::vector<SrsSharedPtrMessage*>::iterator it;
|
std::vector<SrsSharedPtrMessage*>::iterator it;
|
||||||
|
@ -235,6 +238,18 @@ void SrsConsumer::clear()
|
||||||
msgs.clear();
|
msgs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, SrsSource*> SrsSource::pool;
|
||||||
|
|
||||||
|
SrsSource* SrsSource::find(std::string stream_url)
|
||||||
|
{
|
||||||
|
if (pool.find(stream_url) == pool.end()) {
|
||||||
|
pool[stream_url] = new SrsSource(stream_url);
|
||||||
|
srs_verbose("create new source for url=%s", stream_url.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool[stream_url];
|
||||||
|
}
|
||||||
|
|
||||||
SrsSource::SrsSource(std::string _stream_url)
|
SrsSource::SrsSource(std::string _stream_url)
|
||||||
{
|
{
|
||||||
stream_url = _stream_url;
|
stream_url = _stream_url;
|
||||||
|
|
|
@ -40,14 +40,36 @@ class SrsOnMetaDataPacket;
|
||||||
class SrsSharedPtrMessage;
|
class SrsSharedPtrMessage;
|
||||||
class SrsHLS;
|
class SrsHLS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* time jitter detect and correct,
|
||||||
|
* to ensure the rtmp stream is monotonically.
|
||||||
|
*/
|
||||||
|
class SrsRtmpJitter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
u_int32_t last_pkt_time;
|
||||||
|
u_int32_t last_pkt_correct_time;
|
||||||
|
public:
|
||||||
|
SrsRtmpJitter();
|
||||||
|
virtual ~SrsRtmpJitter();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* detect the time jitter and correct it.
|
||||||
|
*/
|
||||||
|
virtual int correct(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate);
|
||||||
|
/**
|
||||||
|
* get current client time, the last packet time.
|
||||||
|
*/
|
||||||
|
virtual int get_time();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the consumer for SrsSource, that is a play client.
|
* the consumer for SrsSource, that is a play client.
|
||||||
*/
|
*/
|
||||||
class SrsConsumer
|
class SrsConsumer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
u_int32_t last_pkt_time;
|
SrsRtmpJitter* jitter;
|
||||||
u_int32_t last_pkt_correct_time;
|
|
||||||
SrsSource* source;
|
SrsSource* source;
|
||||||
std::vector<SrsSharedPtrMessage*> msgs;
|
std::vector<SrsSharedPtrMessage*> msgs;
|
||||||
bool paused;
|
bool paused;
|
||||||
|
@ -82,10 +104,6 @@ private:
|
||||||
* remove to cache only one gop.
|
* remove to cache only one gop.
|
||||||
*/
|
*/
|
||||||
virtual void shrink();
|
virtual void shrink();
|
||||||
/**
|
|
||||||
* detect the time jitter and correct it.
|
|
||||||
*/
|
|
||||||
virtual int jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate, int video_frame_rate);
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue