diff --git a/README.md b/README.md index b00951bfe8..1860b9ba6b 100755 --- a/README.md +++ b/README.md @@ -343,6 +343,7 @@ Remark: ## History +* v2.0, 2015-09-14, fix [#474][bug #474] config to donot parse width/height from sps. 2.0.189 * v2.0, 2015-09-14, for [#474][bug #474] always release publish for source. * v2.0, 2015-09-14, for [#458][bug #458] http hooks use source thread cid. 2.0.188 * v2.0, 2015-09-14, for [#475][bug #475] fix http hooks crash for st context switch. 2.0.187 diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 340ae4626c..623a4d298a 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -858,6 +858,17 @@ vhost min.delay.com { tcp_nodelay on; } +# whether disable the sps parse, for the resolution of video. +vhost no.parse.sps.com { + publish { + # whether parse the sps when publish stream. + # we can got the resolution of video for stat api. + # but we may failed to cause publish failed. + # default: on + parse_sps on; + } +} + # the vhost to control the stream delivery feature vhost stream.control.com { # @see vhost mrw.srs.com for detail. diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 8a945cc253..92e3640438 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -618,6 +618,9 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) srs_error("reload never supports mode changed. ret=%d", ret); return ret; } + + // the auto reload configs: + // publish.parse_sps // ENABLED => ENABLED (modified) if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { @@ -1806,7 +1809,7 @@ int SrsConfig::check_config() && n != "time_jitter" && n != "mix_correct" && n != "atc" && n != "atc_auto" && n != "debug_srs_upnode" - && n != "mr" && n != "mw_latency" && n != "min_latency" + && n != "mr" && n != "mw_latency" && n != "min_latency" && n != "publish" && n != "tcp_nodelay" && n != "send_min_interval" && n != "reduce_sequence_header" && n != "publish_1stpkt_timeout" && n != "publish_normal_timeout" && n != "security" && n != "http_remux" @@ -1839,6 +1842,16 @@ int SrsConfig::check_config() return ret; } } + } else if (n == "publish") { + for (int j = 0; j < (int)conf->directives.size(); j++) { + string m = conf->at(j)->name.c_str(); + if (m != "parse_sps" + ) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("unsupported vhost publish directive %s, ret=%d", m.c_str(), ret); + return ret; + } + } } else if (n == "ingest") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); @@ -2473,6 +2486,29 @@ int SrsConfig::get_chunk_size(string vhost) return ::atoi(conf->arg0().c_str()); } +bool SrsConfig::get_parse_sps(string vhost) +{ + static bool DEFAULT = true; + + SrsConfDirective* conf = get_vhost(vhost); + + if (!conf) { + return DEFAULT; + } + + conf = conf->get("publish"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("parse_sps"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + bool SrsConfig::get_mr_enabled(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 4dd83c0444..f15a5ab890 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -499,6 +499,10 @@ class SrsConfig * @remark, default 60000. */ virtual int get_chunk_size(std::string vhost); + /** + * whether parse the sps when publish stream to SRS. + */ + virtual bool get_parse_sps(std::string vhost); /** * whether mr is enabled for vhost. * @param vhost, the vhost to get the mr. diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index fe73551eef..8b36ab7f94 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1395,7 +1395,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) return ret; } -int SrsHls::on_video(SrsSharedPtrMessage* shared_video) +int SrsHls::on_video(SrsSharedPtrMessage* shared_video, bool is_sps_pps) { int ret = ERROR_SUCCESS; @@ -1409,6 +1409,12 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) SrsSharedPtrMessage* video = shared_video->copy(); SrsAutoFree(SrsSharedPtrMessage, video); + // user can disable the sps parse to workaround when parse sps failed. + // @see https://github.com/simple-rtmp-server/srs/issues/474 + if (is_sps_pps) { + codec->avc_parse_sps = _srs_config->get_parse_sps(_req->vhost); + } + sample->clear(); if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { srs_error("hls codec demux video failed. ret=%d", ret); diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 0ffdf5b74b..62abd660f9 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -444,10 +444,11 @@ class SrsHls */ virtual int on_audio(SrsSharedPtrMessage* shared_audio); /** - * mux the video packets to ts. - * @param shared_video, directly ptr, copy it if need to save it. - */ - virtual int on_video(SrsSharedPtrMessage* shared_video); + * mux the video packets to ts. + * @param shared_video, directly ptr, copy it if need to save it. + * @param is_sps_pps whether the video is h.264 sps/pps. + */ + virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sps_pps); private: virtual void hls_show_mux_log(); }; diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index fa35960348..158acd16b5 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1290,7 +1290,7 @@ int SrsSource::on_hls_start() // when reload to start hls, hls will never get the sequence header in stream, // use the SrsSource.on_hls_start to push the sequence header to HLS. // TODO: maybe need to decode the metadata? - if (cache_sh_video && (ret = hls->on_video(cache_sh_video)) != ERROR_SUCCESS) { + if (cache_sh_video && (ret = hls->on_video(cache_sh_video, true)) != ERROR_SUCCESS) { srs_error("hls process video sequence header message failed. ret=%d", ret); return ret; } @@ -1587,7 +1587,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate], flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type], flv_sample_rates[sample.sound_rate]); - return ret; } #ifdef SRS_AUTO_HLS @@ -1674,6 +1673,11 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) cache_sh_audio = msg->copy(); } + // when sequence header, donot push to gop cache and adjust the timestamp. + if (is_sequence_header) { + return ret; + } + // cache the last gop packets if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { srs_error("shrink gop cache failed. ret=%d", ret); @@ -1779,6 +1783,11 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) // parse detail audio codec SrsAvcAacCodec codec; + + // user can disable the sps parse to workaround when parse sps failed. + // @see https://github.com/simple-rtmp-server/srs/issues/474 + codec.avc_parse_sps = _srs_config->get_parse_sps(_req->vhost); + SrsCodecSample sample; if ((ret = codec.video_avc_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) { srs_error("source codec demux video failed. ret=%d", ret); @@ -1796,11 +1805,10 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) srs_codec_avc_profile2str(codec.avc_profile).c_str(), srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height, codec.video_data_rate / 1000, codec.frame_rate, codec.duration); - return ret; } #ifdef SRS_AUTO_HLS - if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) { + if ((ret = hls->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { // apply the error strategy for hls. // @see https://github.com/simple-rtmp-server/srs/issues/264 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost); @@ -1874,6 +1882,11 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) } } } + + // when sequence header, donot push to gop cache and adjust the timestamp. + if (is_sequence_header) { + return ret; + } // cache the last gop packets if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 940b7e81d6..ebe87801dc 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 188 +#define VERSION_REVISION 189 // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index a0d0843f59..fddd112df7 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -382,6 +382,8 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) SrsAvcAacCodec::SrsAvcAacCodec() { + avc_parse_sps = true; + width = 0; height = 0; duration = 0; @@ -939,6 +941,12 @@ int SrsAvcAacCodec::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp) { int ret = ERROR_SUCCESS; + // we donot parse the detail of sps. + // @see https://github.com/simple-rtmp-server/srs/issues/474 + if (!avc_parse_sps) { + return ret; + } + // reparse the rbsp. SrsStream stream; if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) { diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 204673882c..3b1c7845bf 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -605,6 +605,9 @@ class SrsAvcAacCodec */ int aac_extra_size; char* aac_extra_data; +public: + // for sequence header, whether parse the h.264 sps. + bool avc_parse_sps; public: SrsAvcAacCodec(); virtual ~SrsAvcAacCodec();