winlin

use reduce_sequence_header for stream control.

@@ -342,6 +342,7 @@ Remark: @@ -342,6 +342,7 @@ Remark:
342 342
343 ## History 343 ## History
344 344
  345 +* v2.0, 2015-08-14, use reduce_sequence_header for stream control.
345 * v2.0, 2015-08-14, use send_min_interval for stream control. 2.0.183 346 * v2.0, 2015-08-14, use send_min_interval for stream control. 2.0.183
346 * v2.0, 2015-08-12, enable the SRS_PERF_TCP_NODELAY and add config tcp_nodelay. 2.0.182 347 * v2.0, 2015-08-12, enable the SRS_PERF_TCP_NODELAY and add config tcp_nodelay. 2.0.182
347 * v2.0, 2015-08-11, for [#442](https://github.com/simple-rtmp-server/srs/issues/442) support kickoff connected client. 2.0.181 348 * v2.0, 2015-08-11, for [#442](https://github.com/simple-rtmp-server/srs/issues/442) support kickoff connected client. 2.0.181
@@ -876,7 +876,12 @@ vhost stream.control.com { @@ -876,7 +876,12 @@ vhost stream.control.com {
876 # @remark 0 to disable the minimal interval. 876 # @remark 0 to disable the minimal interval.
877 # @remark >0 to make the srs to send message one by one. 877 # @remark >0 to make the srs to send message one by one.
878 # default: 0 878 # default: 0
879 - send_min_interval 10; 879 + send_min_interval 10;
  880 + # whether reduce the sequence header,
  881 + # for some client which cannot got duplicated sequence header,
  882 + # while the sequence header is not changed yet.
  883 + # default: off
  884 + reduce_sequence_header on;
880 } 885 }
881 886
882 # the vhost for antisuck. 887 # the vhost for antisuck.
@@ -1761,7 +1761,8 @@ int SrsConfig::check_config() @@ -1761,7 +1761,8 @@ int SrsConfig::check_config()
1761 && n != "time_jitter" && n != "mix_correct" 1761 && n != "time_jitter" && n != "mix_correct"
1762 && n != "atc" && n != "atc_auto" 1762 && n != "atc" && n != "atc_auto"
1763 && n != "debug_srs_upnode" 1763 && n != "debug_srs_upnode"
1764 - && n != "mr" && n != "mw_latency" && n != "min_latency" && n != "tcp_nodelay" && n != "send_min_interval" 1764 + && n != "mr" && n != "mw_latency" && n != "min_latency"
  1765 + && n != "tcp_nodelay" && n != "send_min_interval" && n != "reduce_sequence_header"
1765 && n != "security" && n != "http_remux" 1766 && n != "security" && n != "http_remux"
1766 && n != "http" && n != "http_static" 1767 && n != "http" && n != "http_static"
1767 && n != "hds" 1768 && n != "hds"
@@ -2534,6 +2535,23 @@ int SrsConfig::get_send_min_interval(string vhost) @@ -2534,6 +2535,23 @@ int SrsConfig::get_send_min_interval(string vhost)
2534 return ::atoi(conf->arg0().c_str()); 2535 return ::atoi(conf->arg0().c_str());
2535 } 2536 }
2536 2537
  2538 +bool SrsConfig::get_reduce_sequence_header(string vhost)
  2539 +{
  2540 + static bool DEFAULT = false;
  2541 +
  2542 + SrsConfDirective* conf = get_vhost(vhost);
  2543 + if (!conf) {
  2544 + return DEFAULT;
  2545 + }
  2546 +
  2547 + conf = conf->get("reduce_sequence_header");
  2548 + if (!conf || conf->arg0().empty()) {
  2549 + return DEFAULT;
  2550 + }
  2551 +
  2552 + return SRS_CONF_PERFER_FALSE(conf->arg0());
  2553 +}
  2554 +
2537 int SrsConfig::get_global_chunk_size() 2555 int SrsConfig::get_global_chunk_size()
2538 { 2556 {
2539 SrsConfDirective* conf = root->get("chunk_size"); 2557 SrsConfDirective* conf = root->get("chunk_size");
@@ -530,6 +530,10 @@ public: @@ -530,6 +530,10 @@ public:
530 * the minimal send interval in ms. 530 * the minimal send interval in ms.
531 */ 531 */
532 virtual int get_send_min_interval(std::string vhost); 532 virtual int get_send_min_interval(std::string vhost);
  533 + /**
  534 + * whether reduce the sequence header.
  535 + */
  536 + virtual bool get_reduce_sequence_header(std::string vhost);
533 private: 537 private:
534 /** 538 /**
535 * get the global chunk size. 539 * get the global chunk size.
@@ -1535,6 +1535,8 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1535,6 +1535,8 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1535 int ret = ERROR_SUCCESS; 1535 int ret = ERROR_SUCCESS;
1536 1536
1537 srs_info("Audio dts=%"PRId64", size=%d", msg->timestamp, msg->size); 1537 srs_info("Audio dts=%"PRId64", size=%d", msg->timestamp, msg->size);
  1538 + bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size);
  1539 + bool is_sequence_header = is_aac_sequence_header;
1538 1540
1539 #ifdef SRS_AUTO_HLS 1541 #ifdef SRS_AUTO_HLS
1540 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { 1542 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) {
@@ -1589,11 +1591,16 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1589,11 +1591,16 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1589 #endif 1591 #endif
1590 1592
1591 // copy to all consumer 1593 // copy to all consumer
1592 - int nb_consumers = (int)consumers.size();  
1593 - if (nb_consumers > 0) {  
1594 - SrsConsumer** pconsumer = consumers.data();  
1595 - for (int i = 0; i < nb_consumers; i++) {  
1596 - SrsConsumer* consumer = pconsumer[i]; 1594 + bool drop_for_reduce = false;
  1595 + if (is_sequence_header && cache_sh_audio && _srs_config->get_reduce_sequence_header(_req->vhost)) {
  1596 + if (cache_sh_audio->size == msg->size) {
  1597 + drop_for_reduce = srs_bytes_equals(cache_sh_audio->payload, msg->payload, msg->size);
  1598 + srs_warn("drop for reduce sh audio, size=%d", msg->size);
  1599 + }
  1600 + }
  1601 + if (!drop_for_reduce) {
  1602 + for (int i = 0; i < (int)consumers.size(); i++) {
  1603 + SrsConsumer* consumer = consumers.at(i);
1597 if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) { 1604 if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) {
1598 srs_error("dispatch the audio failed. ret=%d", ret); 1605 srs_error("dispatch the audio failed. ret=%d", ret);
1599 return ret; 1606 return ret;
@@ -1617,7 +1624,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1617,7 +1624,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1617 // cache the sequence header of aac, or first packet of mp3. 1624 // cache the sequence header of aac, or first packet of mp3.
1618 // for example, the mp3 is used for hls to write the "right" audio codec. 1625 // for example, the mp3 is used for hls to write the "right" audio codec.
1619 // TODO: FIXME: to refine the stream info system. 1626 // TODO: FIXME: to refine the stream info system.
1620 - bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size);  
1621 if (is_aac_sequence_header || !cache_sh_audio) { 1627 if (is_aac_sequence_header || !cache_sh_audio) {
1622 srs_freep(cache_sh_audio); 1628 srs_freep(cache_sh_audio);
1623 cache_sh_audio = msg->copy(); 1629 cache_sh_audio = msg->copy();
@@ -1740,6 +1746,8 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1740,6 +1746,8 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1740 1746
1741 srs_info("Video dts=%"PRId64", size=%d", msg->timestamp, msg->size); 1747 srs_info("Video dts=%"PRId64", size=%d", msg->timestamp, msg->size);
1742 1748
  1749 + bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size);
  1750 +
1743 #ifdef SRS_AUTO_HLS 1751 #ifdef SRS_AUTO_HLS
1744 if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) { 1752 if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) {
1745 // apply the error strategy for hls. 1753 // apply the error strategy for hls.
@@ -1793,7 +1801,14 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1793,7 +1801,14 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1793 #endif 1801 #endif
1794 1802
1795 // copy to all consumer 1803 // copy to all consumer
1796 - if (true) { 1804 + bool drop_for_reduce = false;
  1805 + if (is_sequence_header && cache_sh_video && _srs_config->get_reduce_sequence_header(_req->vhost)) {
  1806 + if (cache_sh_video->size == msg->size) {
  1807 + drop_for_reduce = srs_bytes_equals(cache_sh_video->payload, msg->payload, msg->size);
  1808 + srs_warn("drop for reduce sh video, size=%d", msg->size);
  1809 + }
  1810 + }
  1811 + if (!drop_for_reduce) {
1797 for (int i = 0; i < (int)consumers.size(); i++) { 1812 for (int i = 0; i < (int)consumers.size(); i++) {
1798 SrsConsumer* consumer = consumers.at(i); 1813 SrsConsumer* consumer = consumers.at(i);
1799 if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) { 1814 if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) {
@@ -1818,7 +1833,7 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1818,7 +1833,7 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1818 1833
1819 // cache the sequence header if h264 1834 // cache the sequence header if h264
1820 // donot cache the sequence header to gop_cache, return here. 1835 // donot cache the sequence header to gop_cache, return here.
1821 - if (SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size)) { 1836 + if (is_sequence_header) {
1822 srs_freep(cache_sh_video); 1837 srs_freep(cache_sh_video);
1823 cache_sh_video = msg->copy(); 1838 cache_sh_video = msg->copy();
1824 1839
@@ -2062,13 +2077,12 @@ void SrsSource::on_unpublish() @@ -2062,13 +2077,12 @@ void SrsSource::on_unpublish()
2062 hds->on_unpublish(); 2077 hds->on_unpublish();
2063 #endif 2078 #endif
2064 2079
  2080 + // only clear the gop cache metadata,
  2081 + // donot clear the sequence header, for it maybe not changed.
2065 gop_cache->clear(); 2082 gop_cache->clear();
2066 -  
2067 srs_freep(cache_metadata); 2083 srs_freep(cache_metadata);
2068 - srs_freep(cache_sh_video);  
2069 - srs_freep(cache_sh_audio);  
2070 2084
2071 - srs_info("clear cache/metadata/sequence-headers when unpublish."); 2085 + srs_info("clear cache/metadata when unpublish.");
2072 srs_trace("cleanup when unpublish"); 2086 srs_trace("cleanup when unpublish");
2073 2087
2074 _can_publish = true; 2088 _can_publish = true;