winlin

merge from 2.0

@@ -1045,6 +1045,7 @@ Winlin @@ -1045,6 +1045,7 @@ Winlin
1045 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367 1045 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367
1046 [bug #471]: https://github.com/simple-rtmp-server/srs/issues/471 1046 [bug #471]: https://github.com/simple-rtmp-server/srs/issues/471
1047 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380 1047 [bug #380]: https://github.com/simple-rtmp-server/srs/issues/380
  1048 +[bug #474]: https://github.com/simple-rtmp-server/srs/issues/474
1048 [bug #475]: https://github.com/simple-rtmp-server/srs/issues/475 1049 [bug #475]: https://github.com/simple-rtmp-server/srs/issues/475
1049 [bug #458]: https://github.com/simple-rtmp-server/srs/issues/458 1050 [bug #458]: https://github.com/simple-rtmp-server/srs/issues/458
1050 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454 1051 [bug #454]: https://github.com/simple-rtmp-server/srs/issues/454
@@ -498,6 +498,14 @@ vhost min.delay.com { @@ -498,6 +498,14 @@ vhost min.delay.com {
498 } 498 }
499 } 499 }
500 500
  501 +# whether disable the sps parse, for the resolution of video.
  502 +vhost no.parse.sps.com {
  503 + # @see publish.srs.com
  504 + publish {
  505 + parse_sps on;
  506 + }
  507 +}
  508 +
501 # the vhost to control the stream delivery feature 509 # the vhost to control the stream delivery feature
502 vhost stream.control.com { 510 vhost stream.control.com {
503 # @see scope.vhost.srs.com 511 # @see scope.vhost.srs.com
@@ -546,6 +554,11 @@ vhost publish.srs.com { @@ -546,6 +554,11 @@ vhost publish.srs.com {
546 # the normal packet timeout in ms for encoder. 554 # the normal packet timeout in ms for encoder.
547 # default: 5000 555 # default: 5000
548 normal_timeout 7000; 556 normal_timeout 7000;
  557 + # whether parse the sps when publish stream.
  558 + # we can got the resolution of video for stat api.
  559 + # but we may failed to cause publish failed.
  560 + # default: on
  561 + parse_sps on;
549 } 562 }
550 } 563 }
551 564
@@ -738,6 +738,9 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) @@ -738,6 +738,9 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
738 srs_error("reload never supports mode changed. ret=%d", ret); 738 srs_error("reload never supports mode changed. ret=%d", ret);
739 return ret; 739 return ret;
740 } 740 }
  741 +
  742 + // the auto reload configs:
  743 + // publish.parse_sps
741 744
742 // ENABLED => ENABLED (modified) 745 // ENABLED => ENABLED (modified)
743 if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { 746 if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) {
@@ -3096,7 +3099,7 @@ int SrsConfig::check_config() @@ -3096,7 +3099,7 @@ int SrsConfig::check_config()
3096 } else if (n == "publish") { 3099 } else if (n == "publish") {
3097 for (int j = 0; j < (int)conf->directives.size(); j++) { 3100 for (int j = 0; j < (int)conf->directives.size(); j++) {
3098 string m = conf->at(j)->name.c_str(); 3101 string m = conf->at(j)->name.c_str();
3099 - if (m != "mr" && m != "mr_latency" && m != "firstpkt_timeout" && m != "normal_timeout") { 3102 + if (m != "mr" && m != "mr_latency" && m != "firstpkt_timeout" && m != "normal_timeout" && m != "parse_sps") {
3100 ret = ERROR_SYSTEM_CONFIG_INVALID; 3103 ret = ERROR_SYSTEM_CONFIG_INVALID;
3101 srs_error("unsupported vhost publish directive %s, ret=%d", m.c_str(), ret); 3104 srs_error("unsupported vhost publish directive %s, ret=%d", m.c_str(), ret);
3102 return ret; 3105 return ret;
@@ -3841,6 +3844,29 @@ int SrsConfig::get_chunk_size(string vhost) @@ -3841,6 +3844,29 @@ int SrsConfig::get_chunk_size(string vhost)
3841 return ::atoi(conf->arg0().c_str()); 3844 return ::atoi(conf->arg0().c_str());
3842 } 3845 }
3843 3846
  3847 +bool SrsConfig::get_parse_sps(string vhost)
  3848 +{
  3849 + static bool DEFAULT = true;
  3850 +
  3851 + SrsConfDirective* conf = get_vhost(vhost);
  3852 +
  3853 + if (!conf) {
  3854 + return DEFAULT;
  3855 + }
  3856 +
  3857 + conf = conf->get("publish");
  3858 + if (!conf) {
  3859 + return DEFAULT;
  3860 + }
  3861 +
  3862 + conf = conf->get("parse_sps");
  3863 + if (!conf || conf->arg0().empty()) {
  3864 + return DEFAULT;
  3865 + }
  3866 +
  3867 + return SRS_CONF_PERFER_TRUE(conf->arg0());
  3868 +}
  3869 +
3844 bool SrsConfig::get_mr_enabled(string vhost) 3870 bool SrsConfig::get_mr_enabled(string vhost)
3845 { 3871 {
3846 SrsConfDirective* conf = get_vhost(vhost); 3872 SrsConfDirective* conf = get_vhost(vhost);
@@ -604,6 +604,10 @@ public: @@ -604,6 +604,10 @@ public:
604 */ 604 */
605 virtual int get_chunk_size(std::string vhost); 605 virtual int get_chunk_size(std::string vhost);
606 /** 606 /**
  607 + * whether parse the sps when publish stream to SRS.
  608 + */
  609 + virtual bool get_parse_sps(std::string vhost);
  610 + /**
607 * whether mr is enabled for vhost. 611 * whether mr is enabled for vhost.
608 * @param vhost, the vhost to get the mr. 612 * @param vhost, the vhost to get the mr.
609 */ 613 */
@@ -476,6 +476,8 @@ void SrsEdgeForwarder::stop() @@ -476,6 +476,8 @@ void SrsEdgeForwarder::stop()
476 476
477 close_underlayer_socket(); 477 close_underlayer_socket();
478 478
  479 + queue->clear();
  480 +
479 srs_freep(client); 481 srs_freep(client);
480 srs_freep(io); 482 srs_freep(io);
481 kbps->set_io(NULL, NULL); 483 kbps->set_io(NULL, NULL);
@@ -1252,7 +1252,7 @@ int SrsHls::initialize(SrsSource* s, ISrsHlsHandler* h) @@ -1252,7 +1252,7 @@ int SrsHls::initialize(SrsSource* s, ISrsHlsHandler* h)
1252 return ret; 1252 return ret;
1253 } 1253 }
1254 1254
1255 -int SrsHls::on_publish(SrsRequest* req) 1255 +int SrsHls::on_publish(SrsRequest* req, bool fetch_sequence_header)
1256 { 1256 {
1257 int ret = ERROR_SUCCESS; 1257 int ret = ERROR_SUCCESS;
1258 1258
@@ -1282,12 +1282,16 @@ int SrsHls::on_publish(SrsRequest* req) @@ -1282,12 +1282,16 @@ int SrsHls::on_publish(SrsRequest* req)
1282 // ok, the hls can be dispose, or need to be dispose. 1282 // ok, the hls can be dispose, or need to be dispose.
1283 hls_can_dispose = true; 1283 hls_can_dispose = true;
1284 1284
1285 - // notice the source to get the cached sequence header.  
1286 - // when reload to start hls, hls will never get the sequence header in stream,  
1287 - // use the SrsSource.on_hls_start to push the sequence header to HLS.  
1288 - if ((ret = source->on_hls_start()) != ERROR_SUCCESS) {  
1289 - srs_error("callback source hls start failed. ret=%d", ret);  
1290 - return ret; 1285 + // when publish, don't need to fetch sequence header, which is old and maybe corrupt.
  1286 + // when reload, we must fetch the sequence header from source cache.
  1287 + if (fetch_sequence_header) {
  1288 + // notice the source to get the cached sequence header.
  1289 + // when reload to start hls, hls will never get the sequence header in stream,
  1290 + // use the SrsSource.on_hls_start to push the sequence header to HLS.
  1291 + if ((ret = source->on_hls_start()) != ERROR_SUCCESS) {
  1292 + srs_error("callback source hls start failed. ret=%d", ret);
  1293 + return ret;
  1294 + }
1291 } 1295 }
1292 1296
1293 return ret; 1297 return ret;
@@ -1391,7 +1395,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) @@ -1391,7 +1395,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio)
1391 return ret; 1395 return ret;
1392 } 1396 }
1393 1397
1394 -int SrsHls::on_video(SrsSharedPtrMessage* shared_video) 1398 +int SrsHls::on_video(SrsSharedPtrMessage* shared_video, bool is_sps_pps)
1395 { 1399 {
1396 int ret = ERROR_SUCCESS; 1400 int ret = ERROR_SUCCESS;
1397 1401
@@ -1405,6 +1409,12 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) @@ -1405,6 +1409,12 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video)
1405 SrsSharedPtrMessage* video = shared_video->copy(); 1409 SrsSharedPtrMessage* video = shared_video->copy();
1406 SrsAutoFree(SrsSharedPtrMessage, video); 1410 SrsAutoFree(SrsSharedPtrMessage, video);
1407 1411
  1412 + // user can disable the sps parse to workaround when parse sps failed.
  1413 + // @see https://github.com/simple-rtmp-server/srs/issues/474
  1414 + if (is_sps_pps) {
  1415 + codec->avc_parse_sps = _srs_config->get_parse_sps(_req->vhost);
  1416 + }
  1417 +
1408 sample->clear(); 1418 sample->clear();
1409 if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { 1419 if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) {
1410 srs_error("hls codec demux video failed. ret=%d", ret); 1420 srs_error("hls codec demux video failed. ret=%d", ret);
@@ -424,10 +424,11 @@ public: @@ -424,10 +424,11 @@ public:
424 */ 424 */
425 virtual int initialize(SrsSource* s, ISrsHlsHandler* h); 425 virtual int initialize(SrsSource* s, ISrsHlsHandler* h);
426 /** 426 /**
427 - * publish stream event, continue to write the m3u8,  
428 - * for the muxer object not destroyed.  
429 - */  
430 - virtual int on_publish(SrsRequest* req); 427 + * publish stream event, continue to write the m3u8,
  428 + * for the muxer object not destroyed.
  429 + * @param fetch_sequence_header whether fetch sequence from source.
  430 + */
  431 + virtual int on_publish(SrsRequest* req, bool fetch_sequence_header);
431 /** 432 /**
432 * the unpublish event, only close the muxer, donot destroy the 433 * the unpublish event, only close the muxer, donot destroy the
433 * muxer, for when we continue to publish, the m3u8 will continue. 434 * muxer, for when we continue to publish, the m3u8 will continue.
@@ -443,10 +444,11 @@ public: @@ -443,10 +444,11 @@ public:
443 */ 444 */
444 virtual int on_audio(SrsSharedPtrMessage* shared_audio); 445 virtual int on_audio(SrsSharedPtrMessage* shared_audio);
445 /** 446 /**
446 - * mux the video packets to ts.  
447 - * @param shared_video, directly ptr, copy it if need to save it.  
448 - */  
449 - virtual int on_video(SrsSharedPtrMessage* shared_video); 447 + * mux the video packets to ts.
  448 + * @param shared_video, directly ptr, copy it if need to save it.
  449 + * @param is_sps_pps whether the video is h.264 sps/pps.
  450 + */
  451 + virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sps_pps);
450 private: 452 private:
451 virtual void hls_show_mux_log(); 453 virtual void hls_show_mux_log();
452 }; 454 };
@@ -816,7 +816,14 @@ int SrsRtmpConn::publishing(SrsSource* source) @@ -816,7 +816,14 @@ int SrsRtmpConn::publishing(SrsSource* source)
816 816
817 // stop isolate recv thread 817 // stop isolate recv thread
818 trd.stop(); 818 trd.stop();
819 - 819 + }
  820 +
  821 + // whatever the acquire publish, always release publish.
  822 + // when the acquire error in the midlle-way, the publish state changed,
  823 + // but failed, so we must cleanup it.
  824 + // @see https://github.com/simple-rtmp-server/srs/issues/474
  825 + // @remark when stream is busy, should never release it.
  826 + if (ret != ERROR_SYSTEM_STREAM_BUSY) {
820 release_publish(source, vhost_is_edge); 827 release_publish(source, vhost_is_edge);
821 } 828 }
822 829
@@ -926,10 +933,12 @@ int SrsRtmpConn::acquire_publish(SrsSource* source, bool is_edge) @@ -926,10 +933,12 @@ int SrsRtmpConn::acquire_publish(SrsSource* source, bool is_edge)
926 if (is_edge) { 933 if (is_edge) {
927 if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) { 934 if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) {
928 srs_error("notice edge start publish stream failed. ret=%d", ret); 935 srs_error("notice edge start publish stream failed. ret=%d", ret);
  936 + return ret;
929 } 937 }
930 } else { 938 } else {
931 if ((ret = source->on_publish()) != ERROR_SUCCESS) { 939 if ((ret = source->on_publish()) != ERROR_SUCCESS) {
932 srs_error("notify publish failed. ret=%d", ret); 940 srs_error("notify publish failed. ret=%d", ret);
  941 + return ret;
933 } 942 }
934 } 943 }
935 944
@@ -1161,7 +1161,7 @@ int SrsSource::on_reload_vhost_hls(string vhost) @@ -1161,7 +1161,7 @@ int SrsSource::on_reload_vhost_hls(string vhost)
1161 1161
1162 #ifdef SRS_AUTO_HLS 1162 #ifdef SRS_AUTO_HLS
1163 hls->on_unpublish(); 1163 hls->on_unpublish();
1164 - if ((ret = hls->on_publish(_req)) != ERROR_SUCCESS) { 1164 + if ((ret = hls->on_publish(_req, true)) != ERROR_SUCCESS) {
1165 srs_error("hls publish failed. ret=%d", ret); 1165 srs_error("hls publish failed. ret=%d", ret);
1166 return ret; 1166 return ret;
1167 } 1167 }
@@ -1297,7 +1297,7 @@ int SrsSource::on_hls_start() @@ -1297,7 +1297,7 @@ int SrsSource::on_hls_start()
1297 // when reload to start hls, hls will never get the sequence header in stream, 1297 // when reload to start hls, hls will never get the sequence header in stream,
1298 // use the SrsSource.on_hls_start to push the sequence header to HLS. 1298 // use the SrsSource.on_hls_start to push the sequence header to HLS.
1299 // TODO: maybe need to decode the metadata? 1299 // TODO: maybe need to decode the metadata?
1300 - if (cache_sh_video && (ret = hls->on_video(cache_sh_video)) != ERROR_SUCCESS) { 1300 + if (cache_sh_video && (ret = hls->on_video(cache_sh_video, true)) != ERROR_SUCCESS) {
1301 srs_error("hls process video sequence header message failed. ret=%d", ret); 1301 srs_error("hls process video sequence header message failed. ret=%d", ret);
1302 return ret; 1302 return ret;
1303 } 1303 }
@@ -1558,6 +1558,44 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1558,6 +1558,44 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1558 bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size); 1558 bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size);
1559 bool is_sequence_header = is_aac_sequence_header; 1559 bool is_sequence_header = is_aac_sequence_header;
1560 1560
  1561 + // whether consumer should drop for the duplicated sequence header.
  1562 + bool drop_for_reduce = false;
  1563 + if (is_sequence_header && cache_sh_audio && _srs_config->get_reduce_sequence_header(_req->vhost)) {
  1564 + if (cache_sh_audio->size == msg->size) {
  1565 + drop_for_reduce = srs_bytes_equals(cache_sh_audio->payload, msg->payload, msg->size);
  1566 + srs_warn("drop for reduce sh audio, size=%d", msg->size);
  1567 + }
  1568 + }
  1569 +
  1570 + // cache the sequence header if aac
  1571 + // donot cache the sequence header to gop_cache, return here.
  1572 + if (is_aac_sequence_header) {
  1573 + // parse detail audio codec
  1574 + SrsAvcAacCodec codec;
  1575 + SrsCodecSample sample;
  1576 + if ((ret = codec.audio_aac_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {
  1577 + srs_error("source codec demux audio failed. ret=%d", ret);
  1578 + return ret;
  1579 + }
  1580 +
  1581 + static int flv_sample_sizes[] = {8, 16, 0};
  1582 + static int flv_sound_types[] = {1, 2, 0};
  1583 +
  1584 + // when got audio stream info.
  1585 + SrsStatistic* stat = SrsStatistic::instance();
  1586 + if ((ret = stat->on_audio_info(_req, SrsCodecAudioAAC, sample.sound_rate, sample.sound_type, codec.aac_object)) != ERROR_SUCCESS) {
  1587 + return ret;
  1588 + }
  1589 +
  1590 + srs_trace("%dB audio sh, codec(%d, profile=%s, %dchannels, %dkbps, %dHZ), "
  1591 + "flv(%dbits, %dchannels, %dHZ)",
  1592 + msg->size, codec.audio_codec_id,
  1593 + srs_codec_aac_object2str(codec.aac_object).c_str(), codec.aac_channels,
  1594 + codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate],
  1595 + flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type],
  1596 + flv_sample_rates[sample.sound_rate]);
  1597 + }
  1598 +
1561 #ifdef SRS_AUTO_HLS 1599 #ifdef SRS_AUTO_HLS
1562 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { 1600 if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) {
1563 // apply the error strategy for hls. 1601 // apply the error strategy for hls.
@@ -1611,13 +1649,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1611,13 +1649,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1611 #endif 1649 #endif
1612 1650
1613 // copy to all consumer 1651 // copy to all consumer
1614 - bool drop_for_reduce = false;  
1615 - if (is_sequence_header && cache_sh_audio && _srs_config->get_reduce_sequence_header(_req->vhost)) {  
1616 - if (cache_sh_audio->size == msg->size) {  
1617 - drop_for_reduce = srs_bytes_equals(cache_sh_audio->payload, msg->payload, msg->size);  
1618 - srs_warn("drop for reduce sh audio, size=%d", msg->size);  
1619 - }  
1620 - }  
1621 if (!drop_for_reduce) { 1652 if (!drop_for_reduce) {
1622 for (int i = 0; i < (int)consumers.size(); i++) { 1653 for (int i = 0; i < (int)consumers.size(); i++) {
1623 SrsConsumer* consumer = consumers.at(i); 1654 SrsConsumer* consumer = consumers.at(i);
@@ -1648,35 +1679,9 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) @@ -1648,35 +1679,9 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
1648 srs_freep(cache_sh_audio); 1679 srs_freep(cache_sh_audio);
1649 cache_sh_audio = msg->copy(); 1680 cache_sh_audio = msg->copy();
1650 } 1681 }
1651 -  
1652 - // cache the sequence header if aac  
1653 - // donot cache the sequence header to gop_cache, return here.  
1654 - if (is_aac_sequence_header) {  
1655 - // parse detail audio codec  
1656 - SrsAvcAacCodec codec;  
1657 - SrsCodecSample sample;  
1658 - if ((ret = codec.audio_aac_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {  
1659 - srs_error("source codec demux audio failed. ret=%d", ret);  
1660 - return ret;  
1661 - }  
1662 -  
1663 - static int flv_sample_sizes[] = {8, 16, 0};  
1664 - static int flv_sound_types[] = {1, 2, 0};  
1665 -  
1666 - // when got audio stream info.  
1667 - SrsStatistic* stat = SrsStatistic::instance();  
1668 - if ((ret = stat->on_audio_info(_req, SrsCodecAudioAAC, sample.sound_rate, sample.sound_type, codec.aac_object)) != ERROR_SUCCESS) {  
1669 - return ret;  
1670 - }  
1671 -  
1672 - srs_trace("%dB audio sh, "  
1673 - "codec(%d, profile=%s, %dchannels, %dkbps, %dHZ), "  
1674 - "flv(%dbits, %dchannels, %dHZ)",  
1675 - msg->size, codec.audio_codec_id,  
1676 - srs_codec_aac_object2str(codec.aac_object).c_str(), codec.aac_channels,  
1677 - codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate],  
1678 - flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type],  
1679 - flv_sample_rates[sample.sound_rate]); 1682 +
  1683 + // when sequence header, donot push to gop cache and adjust the timestamp.
  1684 + if (is_sequence_header) {
1680 return ret; 1685 return ret;
1681 } 1686 }
1682 1687
@@ -1768,8 +1773,49 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1768,8 +1773,49 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1768 1773
1769 bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size); 1774 bool is_sequence_header = SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size);
1770 1775
  1776 + // whether consumer should drop for the duplicated sequence header.
  1777 + bool drop_for_reduce = false;
  1778 + if (is_sequence_header && cache_sh_video && _srs_config->get_reduce_sequence_header(_req->vhost)) {
  1779 + if (cache_sh_video->size == msg->size) {
  1780 + drop_for_reduce = srs_bytes_equals(cache_sh_video->payload, msg->payload, msg->size);
  1781 + srs_warn("drop for reduce sh video, size=%d", msg->size);
  1782 + }
  1783 + }
  1784 +
  1785 + // cache the sequence header if h264
  1786 + // donot cache the sequence header to gop_cache, return here.
  1787 + if (is_sequence_header) {
  1788 + srs_freep(cache_sh_video);
  1789 + cache_sh_video = msg->copy();
  1790 +
  1791 + // parse detail audio codec
  1792 + SrsAvcAacCodec codec;
  1793 +
  1794 + // user can disable the sps parse to workaround when parse sps failed.
  1795 + // @see https://github.com/simple-rtmp-server/srs/issues/474
  1796 + codec.avc_parse_sps = _srs_config->get_parse_sps(_req->vhost);
  1797 +
  1798 + SrsCodecSample sample;
  1799 + if ((ret = codec.video_avc_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {
  1800 + srs_error("source codec demux video failed. ret=%d", ret);
  1801 + return ret;
  1802 + }
  1803 +
  1804 + // when got video stream info.
  1805 + SrsStatistic* stat = SrsStatistic::instance();
  1806 + if ((ret = stat->on_video_info(_req, SrsCodecVideoAVC, codec.avc_profile, codec.avc_level, codec.width, codec.height)) != ERROR_SUCCESS) {
  1807 + return ret;
  1808 + }
  1809 +
  1810 + srs_trace("%dB video sh, codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %dfps, %ds)",
  1811 + msg->size, codec.video_codec_id,
  1812 + srs_codec_avc_profile2str(codec.avc_profile).c_str(),
  1813 + srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height,
  1814 + codec.video_data_rate / 1000, codec.frame_rate, codec.duration);
  1815 + }
  1816 +
1771 #ifdef SRS_AUTO_HLS 1817 #ifdef SRS_AUTO_HLS
1772 - if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) { 1818 + if ((ret = hls->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) {
1773 // apply the error strategy for hls. 1819 // apply the error strategy for hls.
1774 // @see https://github.com/simple-rtmp-server/srs/issues/264 1820 // @see https://github.com/simple-rtmp-server/srs/issues/264
1775 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost); 1821 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost);
@@ -1821,13 +1867,6 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1821,13 +1867,6 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1821 #endif 1867 #endif
1822 1868
1823 // copy to all consumer 1869 // copy to all consumer
1824 - bool drop_for_reduce = false;  
1825 - if (is_sequence_header && cache_sh_video && _srs_config->get_reduce_sequence_header(_req->vhost)) {  
1826 - if (cache_sh_video->size == msg->size) {  
1827 - drop_for_reduce = srs_bytes_equals(cache_sh_video->payload, msg->payload, msg->size);  
1828 - srs_warn("drop for reduce sh video, size=%d", msg->size);  
1829 - }  
1830 - }  
1831 if (!drop_for_reduce) { 1870 if (!drop_for_reduce) {
1832 for (int i = 0; i < (int)consumers.size(); i++) { 1871 for (int i = 0; i < (int)consumers.size(); i++) {
1833 SrsConsumer* consumer = consumers.at(i); 1872 SrsConsumer* consumer = consumers.at(i);
@@ -1850,33 +1889,9 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) @@ -1850,33 +1889,9 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
1850 } 1889 }
1851 } 1890 }
1852 } 1891 }
1853 -  
1854 - // cache the sequence header if h264  
1855 - // donot cache the sequence header to gop_cache, return here. 1892 +
  1893 + // when sequence header, donot push to gop cache and adjust the timestamp.
1856 if (is_sequence_header) { 1894 if (is_sequence_header) {
1857 - srs_freep(cache_sh_video);  
1858 - cache_sh_video = msg->copy();  
1859 -  
1860 - // parse detail audio codec  
1861 - SrsAvcAacCodec codec;  
1862 - SrsCodecSample sample;  
1863 - if ((ret = codec.video_avc_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {  
1864 - srs_error("source codec demux video failed. ret=%d", ret);  
1865 - return ret;  
1866 - }  
1867 -  
1868 - // when got video stream info.  
1869 - SrsStatistic* stat = SrsStatistic::instance();  
1870 - if ((ret = stat->on_video_info(_req, SrsCodecVideoAVC, codec.avc_profile, codec.avc_level, codec.width, codec.height)) != ERROR_SUCCESS) {  
1871 - return ret;  
1872 - }  
1873 -  
1874 - srs_trace("%dB video sh, "  
1875 - "codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %dfps, %ds)",  
1876 - msg->size, codec.video_codec_id,  
1877 - srs_codec_avc_profile2str(codec.avc_profile).c_str(),  
1878 - srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height,  
1879 - codec.video_data_rate / 1000, codec.frame_rate, codec.duration);  
1880 return ret; 1895 return ret;
1881 } 1896 }
1882 1897
@@ -2044,7 +2059,7 @@ int SrsSource::on_publish() @@ -2044,7 +2059,7 @@ int SrsSource::on_publish()
2044 2059
2045 // TODO: FIXME: use initialize to set req. 2060 // TODO: FIXME: use initialize to set req.
2046 #ifdef SRS_AUTO_HLS 2061 #ifdef SRS_AUTO_HLS
2047 - if ((ret = hls->on_publish(_req)) != ERROR_SUCCESS) { 2062 + if ((ret = hls->on_publish(_req, false)) != ERROR_SUCCESS) {
2048 srs_error("start hls failed. ret=%d", ret); 2063 srs_error("start hls failed. ret=%d", ret);
2049 return ret; 2064 return ret;
2050 } 2065 }
@@ -2079,6 +2094,7 @@ int SrsSource::on_publish() @@ -2079,6 +2094,7 @@ int SrsSource::on_publish()
2079 } 2094 }
2080 SrsStatistic* stat = SrsStatistic::instance(); 2095 SrsStatistic* stat = SrsStatistic::instance();
2081 stat->on_stream_publish(_req, _source_id); 2096 stat->on_stream_publish(_req, _source_id);
  2097 +
2082 return ret; 2098 return ret;
2083 } 2099 }
2084 2100
@@ -191,6 +191,10 @@ private: @@ -191,6 +191,10 @@ private:
191 * if no iframe found, clear it. 191 * if no iframe found, clear it.
192 */ 192 */
193 virtual void shrink(); 193 virtual void shrink();
  194 +public:
  195 + /**
  196 + * clear all messages in queue.
  197 + */
194 virtual void clear(); 198 virtual void clear();
195 }; 199 };
196 200
@@ -66,6 +66,7 @@ namespace internal { @@ -66,6 +66,7 @@ namespace internal {
66 really_terminated = true; 66 really_terminated = true;
67 _cid = -1; 67 _cid = -1;
68 _joinable = joinable; 68 _joinable = joinable;
  69 + disposed = false;
69 70
70 // in start(), the thread cycle method maybe stop and remove the thread itself, 71 // in start(), the thread cycle method maybe stop and remove the thread itself,
71 // and the thread start() is waiting for the _cid, and segment fault then. 72 // and the thread start() is waiting for the _cid, and segment fault then.
@@ -115,38 +116,15 @@ namespace internal { @@ -115,38 +116,15 @@ namespace internal {
115 116
116 void SrsThread::stop() 117 void SrsThread::stop()
117 { 118 {
118 - if (tid) {  
119 - loop = false;  
120 -  
121 - // the interrupt will cause the socket to read/write error,  
122 - // which will terminate the cycle thread.  
123 - st_thread_interrupt(tid);  
124 -  
125 - // when joinable, wait util quit.  
126 - if (_joinable) {  
127 - // wait the thread to exit.  
128 - int ret = st_thread_join(tid, NULL);  
129 - if (ret) {  
130 - srs_warn("core: ignore join thread failed.");  
131 - }  
132 - }  
133 -  
134 - // wait the thread actually terminated.  
135 - // sometimes the thread join return -1, for example,  
136 - // when thread use st_recvfrom, the thread join return -1.  
137 - // so here, we use a variable to ensure the thread stopped.  
138 - // @remark even the thread not joinable, we must ensure the thread stopped when stop.  
139 - while (!really_terminated) {  
140 - st_usleep(10 * 1000);  
141 -  
142 - if (really_terminated) {  
143 - break;  
144 - }  
145 - srs_warn("core: wait thread to actually terminated");  
146 - }  
147 -  
148 - tid = NULL; 119 + if (!tid) {
  120 + return;
149 } 121 }
  122 +
  123 + loop = false;
  124 +
  125 + dispose();
  126 +
  127 + tid = NULL;
150 } 128 }
151 129
152 bool SrsThread::can_loop() 130 bool SrsThread::can_loop()
@@ -159,6 +137,42 @@ namespace internal { @@ -159,6 +137,42 @@ namespace internal {
159 loop = false; 137 loop = false;
160 } 138 }
161 139
  140 + void SrsThread::dispose()
  141 + {
  142 + if (disposed) {
  143 + return;
  144 + }
  145 +
  146 + // the interrupt will cause the socket to read/write error,
  147 + // which will terminate the cycle thread.
  148 + st_thread_interrupt(tid);
  149 +
  150 + // when joinable, wait util quit.
  151 + if (_joinable) {
  152 + // wait the thread to exit.
  153 + int ret = st_thread_join(tid, NULL);
  154 + if (ret) {
  155 + srs_warn("core: ignore join thread failed.");
  156 + }
  157 + }
  158 +
  159 + // wait the thread actually terminated.
  160 + // sometimes the thread join return -1, for example,
  161 + // when thread use st_recvfrom, the thread join return -1.
  162 + // so here, we use a variable to ensure the thread stopped.
  163 + // @remark even the thread not joinable, we must ensure the thread stopped when stop.
  164 + while (!really_terminated) {
  165 + st_usleep(10 * 1000);
  166 +
  167 + if (really_terminated) {
  168 + break;
  169 + }
  170 + srs_warn("core: wait thread to actually terminated");
  171 + }
  172 +
  173 + disposed = true;
  174 + }
  175 +
162 void SrsThread::thread_cycle() 176 void SrsThread::thread_cycle()
163 { 177 {
164 int ret = ERROR_SUCCESS; 178 int ret = ERROR_SUCCESS;
@@ -217,6 +231,9 @@ namespace internal { @@ -217,6 +231,9 @@ namespace internal {
217 231
218 handler->on_thread_stop(); 232 handler->on_thread_stop();
219 srs_info("thread %s cycle finished", _name); 233 srs_info("thread %s cycle finished", _name);
  234 +
  235 + // when thread terminated normally, also disposed.
  236 + disposed = true;
220 } 237 }
221 238
222 void* SrsThread::thread_fun(void* arg) 239 void* SrsThread::thread_fun(void* arg)
@@ -100,6 +100,7 @@ namespace internal { @@ -100,6 +100,7 @@ namespace internal {
100 bool really_terminated; 100 bool really_terminated;
101 bool _joinable; 101 bool _joinable;
102 const char* _name; 102 const char* _name;
  103 + bool disposed;
103 private: 104 private:
104 ISrsThreadHandler* handler; 105 ISrsThreadHandler* handler;
105 int64_t cycle_interval_us; 106 int64_t cycle_interval_us;
@@ -154,6 +155,7 @@ namespace internal { @@ -154,6 +155,7 @@ namespace internal {
154 */ 155 */
155 virtual void stop_loop(); 156 virtual void stop_loop();
156 private: 157 private:
  158 + virtual void dispose();
157 virtual void thread_cycle(); 159 virtual void thread_cycle();
158 static void* thread_fun(void* arg); 160 static void* thread_fun(void* arg);
159 }; 161 };
@@ -382,6 +382,8 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) @@ -382,6 +382,8 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size)
382 382
383 SrsAvcAacCodec::SrsAvcAacCodec() 383 SrsAvcAacCodec::SrsAvcAacCodec()
384 { 384 {
  385 + avc_parse_sps = true;
  386 +
385 width = 0; 387 width = 0;
386 height = 0; 388 height = 0;
387 duration = 0; 389 duration = 0;
@@ -939,6 +941,12 @@ int SrsAvcAacCodec::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp) @@ -939,6 +941,12 @@ int SrsAvcAacCodec::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp)
939 { 941 {
940 int ret = ERROR_SUCCESS; 942 int ret = ERROR_SUCCESS;
941 943
  944 + // we donot parse the detail of sps.
  945 + // @see https://github.com/simple-rtmp-server/srs/issues/474
  946 + if (!avc_parse_sps) {
  947 + return ret;
  948 + }
  949 +
942 // reparse the rbsp. 950 // reparse the rbsp.
943 SrsStream stream; 951 SrsStream stream;
944 if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) { 952 if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) {
@@ -606,6 +606,9 @@ public: @@ -606,6 +606,9 @@ public:
606 int aac_extra_size; 606 int aac_extra_size;
607 char* aac_extra_data; 607 char* aac_extra_data;
608 public: 608 public:
  609 + // for sequence header, whether parse the h.264 sps.
  610 + bool avc_parse_sps;
  611 +public:
609 SrsAvcAacCodec(); 612 SrsAvcAacCodec();
610 virtual ~SrsAvcAacCodec(); 613 virtual ~SrsAvcAacCodec();
611 public: 614 public:
@@ -905,7 +905,7 @@ namespace _srs_internal @@ -905,7 +905,7 @@ namespace _srs_internal
905 } 905 }
906 906
907 // client c1 time and version 907 // client c1 time and version
908 - time = ::time(NULL); 908 + time = (int32_t)::time(NULL);
909 version = 0x80000702; // client c1 version 909 version = 0x80000702; // client c1 version
910 910
911 // generate signature by schema 911 // generate signature by schema