1
0
Fork 0
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:
winlin 2013-11-26 11:15:44 +08:00
parent 501b182dc9
commit 326713fbed
4 changed files with 100 additions and 63 deletions

View file

@ -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)

View file

@ -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();

View file

@ -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;

View file

@ -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();
}; };