winlin

fix #383, support mix_correct algorithm. 2.0.161.

@@ -562,6 +562,7 @@ Supported operating systems and hardware: @@ -562,6 +562,7 @@ Supported operating systems and hardware:
562 562
563 ### SRS 2.0 history 563 ### SRS 2.0 history
564 564
  565 +* v2.0, 2015-04-15, for [#383](https://github.com/winlinvip/simple-rtmp-server/issues/383), support mix_correct algorithm. 2.0.161.
565 * v2.0, 2015-04-13, for [#381](https://github.com/winlinvip/simple-rtmp-server/issues/381), support reap hls/ts by gop or not. 2.0.160. 566 * v2.0, 2015-04-13, for [#381](https://github.com/winlinvip/simple-rtmp-server/issues/381), support reap hls/ts by gop or not. 2.0.160.
566 * v2.0, 2015-04-10, enhanced on_hls_notify, support HTTP GET when reap ts. 567 * v2.0, 2015-04-10, enhanced on_hls_notify, support HTTP GET when reap ts.
567 * v2.0, 2015-04-10, refine the hls deviation for floor algorithm. 568 * v2.0, 2015-04-10, refine the hls deviation for floor algorithm.
@@ -1329,7 +1329,7 @@ vhost jitter.srs.com { @@ -1329,7 +1329,7 @@ vhost jitter.srs.com {
1329 # about the stream monotonically increasing: 1329 # about the stream monotonically increasing:
1330 # 1. video timestamp is monotonically increasing, 1330 # 1. video timestamp is monotonically increasing,
1331 # 2. audio timestamp is monotonically increasing, 1331 # 2. audio timestamp is monotonically increasing,
1332 - # 3. video and audio timestamp is interleaved monotonically increasing. 1332 + # 3. video and audio timestamp is interleaved/mixed monotonically increasing.
1333 # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format 1333 # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format
1334 # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. 1334 # however, some encoder cannot provides this feature, please set this to off to ignore time jitter.
1335 # the time jitter algorithm: 1335 # the time jitter algorithm:
@@ -1338,8 +1338,8 @@ vhost jitter.srs.com { @@ -1338,8 +1338,8 @@ vhost jitter.srs.com {
1338 # 3. off, disable the time jitter algorithm, like atc. 1338 # 3. off, disable the time jitter algorithm, like atc.
1339 # default: full 1339 # default: full
1340 time_jitter full; 1340 time_jitter full;
1341 - # whether use the mix algorithm to correct the timestamp.  
1342 - # if on, always ensure the timestamp of audio+video is monotonically increase. 1341 + # whether use the interleaved/mixed algorithm to correct the timestamp.
  1342 + # if on, always ensure the timestamp of audio+video is interleaved/mixed monotonically increase.
1343 # if off, use time_jitter to correct the timestamp if required. 1343 # if off, use time_jitter to correct the timestamp if required.
1344 # default: off 1344 # default: off
1345 mix_correct off; 1345 mix_correct off;
@@ -807,6 +807,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) @@ -807,6 +807,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
807 } 807 }
808 srs_trace("vhost %s reload time_jitter success.", vhost.c_str()); 808 srs_trace("vhost %s reload time_jitter success.", vhost.c_str());
809 } 809 }
  810 + // mix_correct, only one per vhost
  811 + if (!srs_directive_equals(new_vhost->get("mix_correct"), old_vhost->get("mix_correct"))) {
  812 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  813 + ISrsReloadHandler* subscribe = *it;
  814 + if ((ret = subscribe->on_reload_vhost_mix_correct(vhost)) != ERROR_SUCCESS) {
  815 + srs_error("vhost %s notify subscribes mix_correct failed. ret=%d", vhost.c_str(), ret);
  816 + return ret;
  817 + }
  818 + }
  819 + srs_trace("vhost %s reload mix_correct success.", vhost.c_str());
  820 + }
810 // forward, only one per vhost 821 // forward, only one per vhost
811 if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { 822 if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) {
812 for (it = subscribes.begin(); it != subscribes.end(); ++it) { 823 for (it = subscribes.begin(); it != subscribes.end(); ++it) {
@@ -1419,7 +1430,7 @@ int SrsConfig::check_config() @@ -1419,7 +1430,7 @@ int SrsConfig::check_config()
1419 && n != "gop_cache" && n != "queue_length" 1430 && n != "gop_cache" && n != "queue_length"
1420 && n != "refer" && n != "refer_publish" && n != "refer_play" 1431 && n != "refer" && n != "refer_publish" && n != "refer_play"
1421 && n != "forward" && n != "transcode" && n != "bandcheck" 1432 && n != "forward" && n != "transcode" && n != "bandcheck"
1422 - && n != "time_jitter" 1433 + && n != "time_jitter" && n != "mix_correct"
1423 && n != "atc" && n != "atc_auto" 1434 && n != "atc" && n != "atc_auto"
1424 && n != "debug_srs_upnode" 1435 && n != "debug_srs_upnode"
1425 && n != "mr" && n != "mw_latency" && n != "min_latency" 1436 && n != "mr" && n != "mw_latency" && n != "min_latency"
@@ -2118,12 +2129,12 @@ bool SrsConfig::get_atc_auto(string vhost) @@ -2118,12 +2129,12 @@ bool SrsConfig::get_atc_auto(string vhost)
2118 SrsConfDirective* conf = get_vhost(vhost); 2129 SrsConfDirective* conf = get_vhost(vhost);
2119 2130
2120 if (!conf) { 2131 if (!conf) {
2121 - return true; 2132 + return SRS_CONF_DEFAULT_ATC_AUTO;
2122 } 2133 }
2123 2134
2124 conf = conf->get("atc_auto"); 2135 conf = conf->get("atc_auto");
2125 if (!conf || conf->arg0().empty()) { 2136 if (!conf || conf->arg0().empty()) {
2126 - return true; 2137 + return SRS_CONF_DEFAULT_ATC_AUTO;
2127 } 2138 }
2128 2139
2129 return SRS_CONF_PERFER_TRUE(conf->arg0()); 2140 return SRS_CONF_PERFER_TRUE(conf->arg0());
@@ -2131,14 +2142,14 @@ bool SrsConfig::get_atc_auto(string vhost) @@ -2131,14 +2142,14 @@ bool SrsConfig::get_atc_auto(string vhost)
2131 2142
2132 int SrsConfig::get_time_jitter(string vhost) 2143 int SrsConfig::get_time_jitter(string vhost)
2133 { 2144 {
2134 - SrsConfDirective* dvr = get_vhost(vhost); 2145 + SrsConfDirective* conf = get_vhost(vhost);
2135 2146
2136 std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER; 2147 std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER;
2137 2148
2138 - if (dvr) {  
2139 - SrsConfDirective* conf = dvr->get("time_jitter"); 2149 + if (conf) {
  2150 + conf = conf->get("time_jitter");
2140 2151
2141 - if (conf) { 2152 + if (conf && !conf->arg0().empty()) {
2142 time_jitter = conf->arg0(); 2153 time_jitter = conf->arg0();
2143 } 2154 }
2144 } 2155 }
@@ -2146,6 +2157,22 @@ int SrsConfig::get_time_jitter(string vhost) @@ -2146,6 +2157,22 @@ int SrsConfig::get_time_jitter(string vhost)
2146 return _srs_time_jitter_string2int(time_jitter); 2157 return _srs_time_jitter_string2int(time_jitter);
2147 } 2158 }
2148 2159
  2160 +bool SrsConfig::get_mix_correct(string vhost)
  2161 +{
  2162 + SrsConfDirective* conf = get_vhost(vhost);
  2163 +
  2164 + if (!conf) {
  2165 + return SRS_CONF_DEFAULT_MIX_CORRECT;
  2166 + }
  2167 +
  2168 + conf = conf->get("mix_correct");
  2169 + if (!conf || conf->arg0().empty()) {
  2170 + return SRS_CONF_DEFAULT_MIX_CORRECT;
  2171 + }
  2172 +
  2173 + return SRS_CONF_PERFER_FALSE(conf->arg0());
  2174 +}
  2175 +
2149 double SrsConfig::get_queue_length(string vhost) 2176 double SrsConfig::get_queue_length(string vhost)
2150 { 2177 {
2151 SrsConfDirective* conf = get_vhost(vhost); 2178 SrsConfDirective* conf = get_vhost(vhost);
@@ -72,6 +72,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -72,6 +72,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
72 #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION 72 #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION
73 #define SRS_CONF_DEFAULT_DVR_DURATION 30 73 #define SRS_CONF_DEFAULT_DVR_DURATION 30
74 #define SRS_CONF_DEFAULT_TIME_JITTER "full" 74 #define SRS_CONF_DEFAULT_TIME_JITTER "full"
  75 +#define SRS_CONF_DEFAULT_ATC_AUTO true
  76 +#define SRS_CONF_DEFAULT_MIX_CORRECT false
75 // in seconds, the paused queue length. 77 // in seconds, the paused queue length.
76 #define SRS_CONF_DEFAULT_PAUSED_LENGTH 10 78 #define SRS_CONF_DEFAULT_PAUSED_LENGTH 10
77 // the interval in seconds for bandwidth check 79 // the interval in seconds for bandwidth check
@@ -532,6 +534,11 @@ public: @@ -532,6 +534,11 @@ public:
532 */ 534 */
533 virtual int get_time_jitter(std::string vhost); 535 virtual int get_time_jitter(std::string vhost);
534 /** 536 /**
  537 + * whether use mix correct algorithm to ensure the timestamp
  538 + * monotonically increase.
  539 + */
  540 + virtual bool get_mix_correct(std::string vhost);
  541 + /**
535 * get the cache queue length, in seconds. 542 * get the cache queue length, in seconds.
536 * when exceed the queue length, drop packet util I frame. 543 * when exceed the queue length, drop packet util I frame.
537 * @remark, default 10. 544 * @remark, default 10.
@@ -130,6 +130,11 @@ int ISrsReloadHandler::on_reload_vhost_time_jitter(string /*vhost*/) @@ -130,6 +130,11 @@ int ISrsReloadHandler::on_reload_vhost_time_jitter(string /*vhost*/)
130 return ERROR_SUCCESS; 130 return ERROR_SUCCESS;
131 } 131 }
132 132
  133 +int ISrsReloadHandler::on_reload_vhost_mix_correct(string /*vhost*/)
  134 +{
  135 + return ERROR_SUCCESS;
  136 +}
  137 +
133 int ISrsReloadHandler::on_reload_vhost_forward(string /*vhost*/) 138 int ISrsReloadHandler::on_reload_vhost_forward(string /*vhost*/)
134 { 139 {
135 return ERROR_SUCCESS; 140 return ERROR_SUCCESS;
@@ -63,6 +63,7 @@ public: @@ -63,6 +63,7 @@ public:
63 virtual int on_reload_vhost_gop_cache(std::string vhost); 63 virtual int on_reload_vhost_gop_cache(std::string vhost);
64 virtual int on_reload_vhost_queue_length(std::string vhost); 64 virtual int on_reload_vhost_queue_length(std::string vhost);
65 virtual int on_reload_vhost_time_jitter(std::string vhost); 65 virtual int on_reload_vhost_time_jitter(std::string vhost);
  66 + virtual int on_reload_vhost_mix_correct(std::string vhost);
66 virtual int on_reload_vhost_forward(std::string vhost); 67 virtual int on_reload_vhost_forward(std::string vhost);
67 virtual int on_reload_vhost_hls(std::string vhost); 68 virtual int on_reload_vhost_hls(std::string vhost);
68 virtual int on_reload_vhost_hds(std::string vhost); 69 virtual int on_reload_vhost_hds(std::string vhost);
@@ -44,6 +44,7 @@ using namespace std; @@ -44,6 +44,7 @@ using namespace std;
44 #include <srs_rtmp_msg_array.hpp> 44 #include <srs_rtmp_msg_array.hpp>
45 #include <srs_app_hds.hpp> 45 #include <srs_app_hds.hpp>
46 #include <srs_app_statistic.hpp> 46 #include <srs_app_statistic.hpp>
  47 +#include <srs_core_autofree.hpp>
47 48
48 #define CONST_MAX_JITTER_MS 500 49 #define CONST_MAX_JITTER_MS 500
49 #define DEFAULT_FRAME_TIME_MS 40 50 #define DEFAULT_FRAME_TIME_MS 40
@@ -768,10 +769,62 @@ void SrsSource::destroy() @@ -768,10 +769,62 @@ void SrsSource::destroy()
768 pool.clear(); 769 pool.clear();
769 } 770 }
770 771
  772 +SrsMixQueue::SrsMixQueue()
  773 +{
  774 + nb_videos = 0;
  775 +}
  776 +
  777 +SrsMixQueue::~SrsMixQueue()
  778 +{
  779 + clear();
  780 +}
  781 +
  782 +void SrsMixQueue::clear()
  783 +{
  784 + std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it;
  785 + for (it = msgs.begin(); it != msgs.end(); ++it) {
  786 + SrsSharedPtrMessage* msg = it->second;
  787 + srs_freep(msg);
  788 + }
  789 + msgs.clear();
  790 +
  791 + nb_videos = 0;
  792 +}
  793 +
  794 +void SrsMixQueue::push(SrsSharedPtrMessage* msg)
  795 +{
  796 + msgs.insert(std::make_pair(msg->timestamp, msg));
  797 +
  798 + if (msg->is_video()) {
  799 + nb_videos++;
  800 + }
  801 +}
  802 +
  803 +SrsSharedPtrMessage* SrsMixQueue::pop()
  804 +{
  805 + // always keep 2+ videos
  806 + if (nb_videos < 2) {
  807 + return NULL;
  808 + }
  809 +
  810 + // pop the first msg.
  811 + std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it = msgs.begin();
  812 + SrsSharedPtrMessage* msg = it->second;
  813 + msgs.erase(it);
  814 +
  815 + if (msg->is_video()) {
  816 + nb_videos--;
  817 + }
  818 +
  819 + return msg;
  820 +}
  821 +
771 SrsSource::SrsSource() 822 SrsSource::SrsSource()
772 { 823 {
773 _req = NULL; 824 _req = NULL;
774 jitter_algorithm = SrsRtmpJitterAlgorithmOFF; 825 jitter_algorithm = SrsRtmpJitterAlgorithmOFF;
  826 + mix_correct = false;
  827 + mix_queue = new SrsMixQueue();
775 828
776 #ifdef SRS_AUTO_HLS 829 #ifdef SRS_AUTO_HLS
777 hls = new SrsHls(); 830 hls = new SrsHls();
@@ -818,6 +871,7 @@ SrsSource::~SrsSource() @@ -818,6 +871,7 @@ SrsSource::~SrsSource()
818 forwarders.clear(); 871 forwarders.clear();
819 } 872 }
820 873
  874 + srs_freep(mix_queue);
821 srs_freep(cache_metadata); 875 srs_freep(cache_metadata);
822 srs_freep(cache_sh_video); 876 srs_freep(cache_sh_video);
823 srs_freep(cache_sh_audio); 877 srs_freep(cache_sh_audio);
@@ -878,6 +932,7 @@ int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* h @@ -878,6 +932,7 @@ int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* h
878 publish_edge->set_queue_size(queue_size); 932 publish_edge->set_queue_size(queue_size);
879 933
880 jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); 934 jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost);
  935 + mix_correct = _srs_config->get_mix_correct(_req->vhost);
881 936
882 return ret; 937 return ret;
883 } 938 }
@@ -973,6 +1028,25 @@ int SrsSource::on_reload_vhost_time_jitter(string vhost) @@ -973,6 +1028,25 @@ int SrsSource::on_reload_vhost_time_jitter(string vhost)
973 return ret; 1028 return ret;
974 } 1029 }
975 1030
  1031 +int SrsSource::on_reload_vhost_mix_correct(string vhost)
  1032 +{
  1033 + int ret = ERROR_SUCCESS;
  1034 +
  1035 + if (_req->vhost != vhost) {
  1036 + return ret;
  1037 + }
  1038 +
  1039 + bool v = _srs_config->get_mix_correct(_req->vhost);
  1040 +
  1041 + // when changed, clear the mix queue.
  1042 + if (v != mix_correct) {
  1043 + mix_queue->clear();
  1044 + }
  1045 + mix_correct = v;
  1046 +
  1047 + return ret;
  1048 +}
  1049 +
976 int SrsSource::on_reload_vhost_forward(string vhost) 1050 int SrsSource::on_reload_vhost_forward(string vhost)
977 { 1051 {
978 int ret = ERROR_SUCCESS; 1052 int ret = ERROR_SUCCESS;
@@ -1330,17 +1404,21 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1330,17 +1404,21 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1330 srs_error("initialize the audio failed. ret=%d", ret); 1404 srs_error("initialize the audio failed. ret=%d", ret);
1331 return ret; 1405 return ret;
1332 } 1406 }
1333 - srs_verbose("initialize shared ptr audio success."); 1407 + srs_info("Audio dts=%"PRId64", size=%d", msg.timestamp, msg.size);
1334 1408
1335 - srs_warn("Audio dts=%"PRId64", size=%d", msg.timestamp, msg.size); 1409 + if (!mix_correct) {
  1410 + return on_audio_imp(&msg);
  1411 + }
1336 1412
1337 - return on_audio_imp(&msg); 1413 + return do_mix_correct(&msg);
1338 } 1414 }
1339 1415
1340 int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) 1416 int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1341 { 1417 {
1342 int ret = ERROR_SUCCESS; 1418 int ret = ERROR_SUCCESS;
1343 1419
  1420 + srs_info("Audio dts=%"PRId64", size=%d", msg->timestamp, msg->size);
  1421 +
1344 #ifdef SRS_AUTO_HLS 1422 #ifdef SRS_AUTO_HLS
1345 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { 1423 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) {
1346 // apply the error strategy for hls. 1424 // apply the error strategy for hls.
@@ -1490,17 +1568,21 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1490,17 +1568,21 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1490 srs_error("initialize the video failed. ret=%d", ret); 1568 srs_error("initialize the video failed. ret=%d", ret);
1491 return ret; 1569 return ret;
1492 } 1570 }
1493 - srs_verbose("initialize shared ptr video success."); 1571 + srs_info("Video dts=%"PRId64", size=%d", msg.timestamp, msg.size);
1494 1572
1495 - srs_warn("Video dts=%"PRId64", size=%d", msg.timestamp, msg.size); 1573 + if (!mix_correct) {
  1574 + return on_video_imp(&msg);
  1575 + }
1496 1576
1497 - return on_video_imp(&msg); 1577 + return do_mix_correct(&msg);
1498 } 1578 }
1499 1579
1500 int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) 1580 int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1501 { 1581 {
1502 int ret = ERROR_SUCCESS; 1582 int ret = ERROR_SUCCESS;
1503 1583
  1584 + srs_info("Video dts=%"PRId64", size=%d", msg->timestamp, msg->size);
  1585 +
1504 #ifdef SRS_AUTO_HLS 1586 #ifdef SRS_AUTO_HLS
1505 if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) { 1587 if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) {
1506 // apply the error strategy for hls. 1588 // apply the error strategy for hls.
@@ -1626,6 +1708,29 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1626,6 +1708,29 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1626 return ret; 1708 return ret;
1627 } 1709 }
1628 1710
  1711 +int SrsSource::do_mix_correct(SrsSharedPtrMessage* msg)
  1712 +{
  1713 + int ret = ERROR_SUCCESS;
  1714 +
  1715 + // insert msg to the queue.
  1716 + mix_queue->push(msg->copy());
  1717 +
  1718 + // fetch someone from mix queue.
  1719 + SrsSharedPtrMessage* m = mix_queue->pop();
  1720 + if (!m) {
  1721 + return ret;
  1722 + }
  1723 + SrsAutoFree(SrsSharedPtrMessage, m);
  1724 +
  1725 + // consume the monotonically increase message.
  1726 + if (m->is_audio()) {
  1727 + return on_audio_imp(m);
  1728 + }
  1729 +
  1730 + srs_assert(m->is_video());
  1731 + return on_video_imp(m);
  1732 +}
  1733 +
1629 int SrsSource::on_aggregate(SrsCommonMessage* msg) 1734 int SrsSource::on_aggregate(SrsCommonMessage* msg)
1630 { 1735 {
1631 int ret = ERROR_SUCCESS; 1736 int ret = ERROR_SUCCESS;
@@ -1766,6 +1871,9 @@ int SrsSource::on_publish() @@ -1766,6 +1871,9 @@ int SrsSource::on_publish()
1766 // save its id to srouce id. 1871 // save its id to srouce id.
1767 on_source_id_changed(_srs_context->get_id()); 1872 on_source_id_changed(_srs_context->get_id());
1768 1873
  1874 + // reset the mix queue.
  1875 + mix_queue->clear();
  1876 +
1769 // create forwarders 1877 // create forwarders
1770 if ((ret = create_forwarders()) != ERROR_SUCCESS) { 1878 if ((ret = create_forwarders()) != ERROR_SUCCESS) {
1771 srs_error("create forwarders failed. ret=%d", ret); 1879 srs_error("create forwarders failed. ret=%d", ret);
@@ -369,6 +369,23 @@ public: @@ -369,6 +369,23 @@ public:
369 }; 369 };
370 370
371 /** 371 /**
  372 + * the mix queue to correct the timestamp for mix_correct algorithm.
  373 + */
  374 +class SrsMixQueue
  375 +{
  376 +private:
  377 + u_int32_t nb_videos;
  378 + std::multimap<int64_t, SrsSharedPtrMessage*> msgs;
  379 +public:
  380 + SrsMixQueue();
  381 + virtual ~SrsMixQueue();
  382 +public:
  383 + virtual void clear();
  384 + virtual void push(SrsSharedPtrMessage* msg);
  385 + virtual SrsSharedPtrMessage* pop();
  386 +};
  387 +
  388 +/**
372 * live streaming source. 389 * live streaming source.
373 */ 390 */
374 class SrsSource : public ISrsReloadHandler 391 class SrsSource : public ISrsReloadHandler
@@ -407,6 +424,9 @@ private: @@ -407,6 +424,9 @@ private:
407 std::vector<SrsConsumer*> consumers; 424 std::vector<SrsConsumer*> consumers;
408 // the time jitter algorithm for vhost. 425 // the time jitter algorithm for vhost.
409 SrsRtmpJitterAlgorithm jitter_algorithm; 426 SrsRtmpJitterAlgorithm jitter_algorithm;
  427 + // whether use interlaced/mixed algorithm to correct timestamp.
  428 + bool mix_correct;
  429 + SrsMixQueue* mix_queue;
410 // hls handler. 430 // hls handler.
411 #ifdef SRS_AUTO_HLS 431 #ifdef SRS_AUTO_HLS
412 SrsHls* hls; 432 SrsHls* hls;
@@ -474,6 +494,7 @@ public: @@ -474,6 +494,7 @@ public:
474 virtual int on_reload_vhost_gop_cache(std::string vhost); 494 virtual int on_reload_vhost_gop_cache(std::string vhost);
475 virtual int on_reload_vhost_queue_length(std::string vhost); 495 virtual int on_reload_vhost_queue_length(std::string vhost);
476 virtual int on_reload_vhost_time_jitter(std::string vhost); 496 virtual int on_reload_vhost_time_jitter(std::string vhost);
  497 + virtual int on_reload_vhost_mix_correct(std::string vhost);
477 virtual int on_reload_vhost_forward(std::string vhost); 498 virtual int on_reload_vhost_forward(std::string vhost);
478 virtual int on_reload_vhost_hls(std::string vhost); 499 virtual int on_reload_vhost_hls(std::string vhost);
479 virtual int on_reload_vhost_hds(std::string vhost); 500 virtual int on_reload_vhost_hds(std::string vhost);
@@ -503,6 +524,8 @@ public: @@ -503,6 +524,8 @@ public:
503 virtual int on_video(SrsCommonMessage* video); 524 virtual int on_video(SrsCommonMessage* video);
504 private: 525 private:
505 virtual int on_video_imp(SrsSharedPtrMessage* video); 526 virtual int on_video_imp(SrsSharedPtrMessage* video);
  527 +private:
  528 + virtual int do_mix_correct(SrsSharedPtrMessage* msg);
506 public: 529 public:
507 virtual int on_aggregate(SrsCommonMessage* msg); 530 virtual int on_aggregate(SrsCommonMessage* msg);
508 /** 531 /**
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 160 34 +#define VERSION_REVISION 161
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"