正在显示
10 个修改的文件
包含
97 行增加
和
34 行删除
| 1 | #Simple-RTMP-Server | 1 | #Simple-RTMP-Server |
| 2 | 2 | ||
| 3 | -SRS/3.0,开发代号:[OuXuli](https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#release30) | 3 | +SRS/3.0, [OuXuli](https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#release30) |
| 4 | 4 | ||
| 5 | SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码。<br/> | 5 | SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码。<br/> |
| 6 | SRS is industrial-strength live streaming cluster, for the best conceptual integrity and the simplest implementation. | 6 | SRS is industrial-strength live streaming cluster, for the best conceptual integrity and the simplest implementation. |
| 7 | 7 | ||
| 8 | Download from github.io: [Centos6-x86_64][centos0], [more...][more0]<br/> | 8 | Download from github.io: [Centos6-x86_64][centos0], [more...][more0]<br/> |
| 9 | Download from ossrs.net: [Centos6-x86_64][centos1], [more...][more1]<br/> | 9 | Download from ossrs.net: [Centos6-x86_64][centos1], [more...][more1]<br/> |
| 10 | -Contact by QQ or Skype, read [Contact][contact] | 10 | +Website for SRS/2.0, read SRS 2.0 [Chinese][srs2_CN] or [English][srs2_EN]. |
| 11 | 11 | ||
| 12 | ## Why SRS? | 12 | ## Why SRS? |
| 13 | 13 | ||
| @@ -1025,5 +1025,6 @@ Winlin | @@ -1025,5 +1025,6 @@ Winlin | ||
| 1025 | [centos0]: http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip | 1025 | [centos0]: http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip |
| 1026 | [centos1]: http://www.ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip | 1026 | [centos1]: http://www.ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip |
| 1027 | 1027 | ||
| 1028 | - | 1028 | +[srs2_CN]: https://github.com/simple-rtmp-server/srs/wiki/v2_CN_Home |
| 1029 | +[srs2_EN]: https://github.com/simple-rtmp-server/srs/wiki/v2_EN_Home | ||
| 1029 | 1030 |
| @@ -38,6 +38,7 @@ int proxy(srs_flv_t flv, srs_rtmp_t ortmp); | @@ -38,6 +38,7 @@ int proxy(srs_flv_t flv, srs_rtmp_t ortmp); | ||
| 38 | int connect_oc(srs_rtmp_t ortmp); | 38 | int connect_oc(srs_rtmp_t ortmp); |
| 39 | 39 | ||
| 40 | #define RE_PULSE_MS 300 | 40 | #define RE_PULSE_MS 300 |
| 41 | +#define RE_PULSE_JITTER_MS 3000 | ||
| 41 | int64_t re_create(); | 42 | int64_t re_create(); |
| 42 | void re_update(int64_t re, int32_t starttime, u_int32_t time); | 43 | void re_update(int64_t re, int32_t starttime, u_int32_t time); |
| 43 | void re_cleanup(int64_t re, int32_t starttime, u_int32_t time); | 44 | void re_cleanup(int64_t re, int32_t starttime, u_int32_t time); |
| @@ -256,7 +257,7 @@ void re_update(int64_t re, int32_t starttime, u_int32_t time) | @@ -256,7 +257,7 @@ void re_update(int64_t re, int32_t starttime, u_int32_t time) | ||
| 256 | // send by pulse algorithm. | 257 | // send by pulse algorithm. |
| 257 | int64_t now = srs_utils_time_ms(); | 258 | int64_t now = srs_utils_time_ms(); |
| 258 | int64_t diff = time - starttime - (now -re); | 259 | int64_t diff = time - starttime - (now -re); |
| 259 | - if (diff > RE_PULSE_MS) { | 260 | + if (diff > RE_PULSE_MS && diff < RE_PULSE_JITTER_MS) { |
| 260 | usleep((useconds_t)(diff * 1000)); | 261 | usleep((useconds_t)(diff * 1000)); |
| 261 | } | 262 | } |
| 262 | } | 263 | } |
| @@ -853,6 +853,7 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | @@ -853,6 +853,7 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | ||
| 853 | } | 853 | } |
| 854 | } | 854 | } |
| 855 | 855 | ||
| 856 | + // TODO: reload new http_remux in on_vhost_add | ||
| 856 | // http_remux, only one per vhost. | 857 | // http_remux, only one per vhost. |
| 857 | if (get_vhost_http_remux_enabled(vhost)) { | 858 | if (get_vhost_http_remux_enabled(vhost)) { |
| 858 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 859 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
| @@ -4417,3 +4418,18 @@ bool srs_config_dvr_is_plan_append(string plan) | @@ -4417,3 +4418,18 @@ bool srs_config_dvr_is_plan_append(string plan) | ||
| 4417 | { | 4418 | { |
| 4418 | return plan == SRS_CONF_DEFAULT_DVR_PLAN_APPEND; | 4419 | return plan == SRS_CONF_DEFAULT_DVR_PLAN_APPEND; |
| 4419 | } | 4420 | } |
| 4421 | + | ||
| 4422 | +bool srs_stream_caster_is_udp(string caster) | ||
| 4423 | +{ | ||
| 4424 | + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP; | ||
| 4425 | +} | ||
| 4426 | + | ||
| 4427 | +bool srs_stream_caster_is_rtsp(string caster) | ||
| 4428 | +{ | ||
| 4429 | + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP; | ||
| 4430 | +} | ||
| 4431 | + | ||
| 4432 | +bool srs_stream_caster_is_flv(string caster) | ||
| 4433 | +{ | ||
| 4434 | + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_FLV; | ||
| 4435 | +} |
| @@ -1143,6 +1143,9 @@ extern bool srs_config_ingest_is_stream(std::string type); | @@ -1143,6 +1143,9 @@ extern bool srs_config_ingest_is_stream(std::string type); | ||
| 1143 | extern bool srs_config_dvr_is_plan_segment(std::string plan); | 1143 | extern bool srs_config_dvr_is_plan_segment(std::string plan); |
| 1144 | extern bool srs_config_dvr_is_plan_session(std::string plan); | 1144 | extern bool srs_config_dvr_is_plan_session(std::string plan); |
| 1145 | extern bool srs_config_dvr_is_plan_append(std::string plan); | 1145 | extern bool srs_config_dvr_is_plan_append(std::string plan); |
| 1146 | +extern bool srs_stream_caster_is_udp(std::string caster); | ||
| 1147 | +extern bool srs_stream_caster_is_rtsp(std::string caster); | ||
| 1148 | +extern bool srs_stream_caster_is_flv(std::string caster); | ||
| 1146 | 1149 | ||
| 1147 | // global config | 1150 | // global config |
| 1148 | extern SrsConfig* _srs_config; | 1151 | extern SrsConfig* _srs_config; |
| @@ -164,7 +164,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata) | @@ -164,7 +164,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata) | ||
| 164 | SrsSharedPtrMessage* metadata = shared_metadata->copy(); | 164 | SrsSharedPtrMessage* metadata = shared_metadata->copy(); |
| 165 | 165 | ||
| 166 | // TODO: FIXME: config the jitter of Forwarder. | 166 | // TODO: FIXME: config the jitter of Forwarder. |
| 167 | - if ((ret = jitter->correct(metadata, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { | 167 | + if ((ret = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { |
| 168 | srs_freep(metadata); | 168 | srs_freep(metadata); |
| 169 | return ret; | 169 | return ret; |
| 170 | } | 170 | } |
| @@ -183,7 +183,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio) | @@ -183,7 +183,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio) | ||
| 183 | SrsSharedPtrMessage* msg = shared_audio->copy(); | 183 | SrsSharedPtrMessage* msg = shared_audio->copy(); |
| 184 | 184 | ||
| 185 | // TODO: FIXME: config the jitter of Forwarder. | 185 | // TODO: FIXME: config the jitter of Forwarder. |
| 186 | - if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { | 186 | + if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { |
| 187 | srs_freep(msg); | 187 | srs_freep(msg); |
| 188 | return ret; | 188 | return ret; |
| 189 | } | 189 | } |
| @@ -207,7 +207,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video) | @@ -207,7 +207,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video) | ||
| 207 | SrsSharedPtrMessage* msg = shared_video->copy(); | 207 | SrsSharedPtrMessage* msg = shared_video->copy(); |
| 208 | 208 | ||
| 209 | // TODO: FIXME: config the jitter of Forwarder. | 209 | // TODO: FIXME: config the jitter of Forwarder. |
| 210 | - if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { | 210 | + if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { |
| 211 | srs_freep(msg); | 211 | srs_freep(msg); |
| 212 | return ret; | 212 | return ret; |
| 213 | } | 213 | } |
| @@ -53,6 +53,8 @@ using namespace std; | @@ -53,6 +53,8 @@ using namespace std; | ||
| 53 | 53 | ||
| 54 | // drop the segment when duration of ts too small. | 54 | // drop the segment when duration of ts too small. |
| 55 | #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 | 55 | #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 |
| 56 | +// when hls timestamp jump, reset it. | ||
| 57 | +#define SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS 300 | ||
| 56 | 58 | ||
| 57 | // fragment plus the deviation percent. | 59 | // fragment plus the deviation percent. |
| 58 | #define SRS_HLS_FLOOR_REAP_PERCENT 0.3 | 60 | #define SRS_HLS_FLOOR_REAP_PERCENT 0.3 |
| @@ -161,6 +163,11 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) | @@ -161,6 +163,11 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) | ||
| 161 | // update the segment duration, which is nagetive, | 163 | // update the segment duration, which is nagetive, |
| 162 | // just ignore it. | 164 | // just ignore it. |
| 163 | if (current_frame_dts < segment_start_dts) { | 165 | if (current_frame_dts < segment_start_dts) { |
| 166 | + // for atc and timestamp jump, reset the start dts. | ||
| 167 | + if (current_frame_dts < segment_start_dts - SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS * 90) { | ||
| 168 | + srs_warn("hls timestamp jump %"PRId64"=>%"PRId64, segment_start_dts, current_frame_dts); | ||
| 169 | + segment_start_dts = current_frame_dts; | ||
| 170 | + } | ||
| 164 | return; | 171 | return; |
| 165 | } | 172 | } |
| 166 | 173 | ||
| @@ -280,7 +287,7 @@ SrsHlsMuxer::SrsHlsMuxer() | @@ -280,7 +287,7 @@ SrsHlsMuxer::SrsHlsMuxer() | ||
| 280 | previous_floor_ts = 0; | 287 | previous_floor_ts = 0; |
| 281 | accept_floor_ts = 0; | 288 | accept_floor_ts = 0; |
| 282 | hls_ts_floor = false; | 289 | hls_ts_floor = false; |
| 283 | - target_duration = 0; | 290 | + max_td = 0; |
| 284 | _sequence_no = 0; | 291 | _sequence_no = 0; |
| 285 | current = NULL; | 292 | current = NULL; |
| 286 | acodec = SrsCodecAudioReserved1; | 293 | acodec = SrsCodecAudioReserved1; |
| @@ -400,10 +407,8 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | @@ -400,10 +407,8 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | ||
| 400 | m3u8_url = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream); | 407 | m3u8_url = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream); |
| 401 | m3u8 = path + "/" + m3u8_url; | 408 | m3u8 = path + "/" + m3u8_url; |
| 402 | 409 | ||
| 403 | - // we always keep the target duration increasing. | ||
| 404 | - int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); | ||
| 405 | - srs_info("hls update target duration %d=>%d, aof=%.2f", target_duration, max_td, aof_ratio); | ||
| 406 | - target_duration = max_td; | 410 | + // when update config, reset the history target duration. |
| 411 | + max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)); | ||
| 407 | 412 | ||
| 408 | std::string storage = _srs_config->get_hls_storage(r->vhost); | 413 | std::string storage = _srs_config->get_hls_storage(r->vhost); |
| 409 | if (storage == "ram") { | 414 | if (storage == "ram") { |
| @@ -699,7 +704,9 @@ int SrsHlsMuxer::segment_close(string log_desc) | @@ -699,7 +704,9 @@ int SrsHlsMuxer::segment_close(string log_desc) | ||
| 699 | srs_assert(it == segments.end()); | 704 | srs_assert(it == segments.end()); |
| 700 | 705 | ||
| 701 | // valid, add to segments if segment duration is ok | 706 | // valid, add to segments if segment duration is ok |
| 702 | - if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) { | 707 | + // when too small, it maybe not enough data to play. |
| 708 | + // when too large, it maybe timestamp corrupt. | ||
| 709 | + if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)current->duration <= max_td) { | ||
| 703 | segments.push_back(current); | 710 | segments.push_back(current); |
| 704 | 711 | ||
| 705 | // use async to call the http hooks, for it will cause thread switch. | 712 | // use async to call the http hooks, for it will cause thread switch. |
| @@ -750,7 +757,6 @@ int SrsHlsMuxer::segment_close(string log_desc) | @@ -750,7 +757,6 @@ int SrsHlsMuxer::segment_close(string log_desc) | ||
| 750 | // rename from tmp to real path | 757 | // rename from tmp to real path |
| 751 | std::string tmp_file = current->full_path + ".tmp"; | 758 | std::string tmp_file = current->full_path + ".tmp"; |
| 752 | if (should_write_file) { | 759 | if (should_write_file) { |
| 753 | - unlink(tmp_file.c_str()); | ||
| 754 | if (unlink(tmp_file.c_str()) < 0) { | 760 | if (unlink(tmp_file.c_str()) < 0) { |
| 755 | srs_warn("ignore unlink path failed, file=%s.", tmp_file.c_str()); | 761 | srs_warn("ignore unlink path failed, file=%s.", tmp_file.c_str()); |
| 756 | } | 762 | } |
| @@ -817,6 +823,11 @@ int SrsHlsMuxer::refresh_m3u8() | @@ -817,6 +823,11 @@ int SrsHlsMuxer::refresh_m3u8() | ||
| 817 | { | 823 | { |
| 818 | int ret = ERROR_SUCCESS; | 824 | int ret = ERROR_SUCCESS; |
| 819 | 825 | ||
| 826 | + // no segments, also no m3u8, return. | ||
| 827 | + if (segments.size() == 0) { | ||
| 828 | + return ret; | ||
| 829 | + } | ||
| 830 | + | ||
| 820 | std::string temp_m3u8 = m3u8 + ".temp"; | 831 | std::string temp_m3u8 = m3u8 + ".temp"; |
| 821 | if ((ret = _refresh_m3u8(temp_m3u8)) == ERROR_SUCCESS) { | 832 | if ((ret = _refresh_m3u8(temp_m3u8)) == ERROR_SUCCESS) { |
| 822 | if (should_write_file && rename(temp_m3u8.c_str(), m3u8.c_str()) < 0) { | 833 | if (should_write_file && rename(temp_m3u8.c_str(), m3u8.c_str()) < 0) { |
| @@ -826,7 +837,11 @@ int SrsHlsMuxer::refresh_m3u8() | @@ -826,7 +837,11 @@ int SrsHlsMuxer::refresh_m3u8() | ||
| 826 | } | 837 | } |
| 827 | 838 | ||
| 828 | // remove the temp file. | 839 | // remove the temp file. |
| 829 | - unlink(temp_m3u8.c_str()); | 840 | + if (srs_path_exists(temp_m3u8)) { |
| 841 | + if (unlink(temp_m3u8.c_str()) < 0) { | ||
| 842 | + srs_warn("ignore remove m3u8 failed, %s", temp_m3u8.c_str()); | ||
| 843 | + } | ||
| 844 | + } | ||
| 830 | 845 | ||
| 831 | return ret; | 846 | return ret; |
| 832 | } | 847 | } |
| @@ -861,6 +876,9 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) | @@ -861,6 +876,9 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) | ||
| 861 | ss << "#EXT-X-MEDIA-SEQUENCE:" << first->sequence_no << SRS_CONSTS_LF; | 876 | ss << "#EXT-X-MEDIA-SEQUENCE:" << first->sequence_no << SRS_CONSTS_LF; |
| 862 | srs_verbose("write m3u8 sequence success."); | 877 | srs_verbose("write m3u8 sequence success."); |
| 863 | 878 | ||
| 879 | + // iterator shared for td generation and segemnts wrote. | ||
| 880 | + std::vector<SrsHlsSegment*>::iterator it; | ||
| 881 | + | ||
| 864 | // #EXT-X-TARGETDURATION:4294967295\n | 882 | // #EXT-X-TARGETDURATION:4294967295\n |
| 865 | /** | 883 | /** |
| 866 | * @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25 | 884 | * @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25 |
| @@ -871,11 +889,13 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) | @@ -871,11 +889,13 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) | ||
| 871 | * typical target duration is 10 seconds. | 889 | * typical target duration is 10 seconds. |
| 872 | */ | 890 | */ |
| 873 | // @see https://github.com/simple-rtmp-server/srs/issues/304#issuecomment-74000081 | 891 | // @see https://github.com/simple-rtmp-server/srs/issues/304#issuecomment-74000081 |
| 874 | - std::vector<SrsHlsSegment*>::iterator it; | 892 | + int target_duration = 0; |
| 875 | for (it = segments.begin(); it != segments.end(); ++it) { | 893 | for (it = segments.begin(); it != segments.end(); ++it) { |
| 876 | SrsHlsSegment* segment = *it; | 894 | SrsHlsSegment* segment = *it; |
| 877 | target_duration = srs_max(target_duration, (int)ceil(segment->duration)); | 895 | target_duration = srs_max(target_duration, (int)ceil(segment->duration)); |
| 878 | } | 896 | } |
| 897 | + target_duration = srs_max(target_duration, max_td); | ||
| 898 | + | ||
| 879 | ss << "#EXT-X-TARGETDURATION:" << target_duration << SRS_CONSTS_LF; | 899 | ss << "#EXT-X-TARGETDURATION:" << target_duration << SRS_CONSTS_LF; |
| 880 | srs_verbose("write m3u8 duration success."); | 900 | srs_verbose("write m3u8 duration success."); |
| 881 | 901 | ||
| @@ -1335,7 +1355,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) | @@ -1335,7 +1355,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) | ||
| 1335 | } | 1355 | } |
| 1336 | 1356 | ||
| 1337 | // TODO: FIXME: config the jitter of HLS. | 1357 | // TODO: FIXME: config the jitter of HLS. |
| 1338 | - if ((ret = jitter->correct(audio, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { | 1358 | + if ((ret = jitter->correct(audio, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { |
| 1339 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); | 1359 | srs_error("rtmp jitter correct audio failed. ret=%d", ret); |
| 1340 | return ret; | 1360 | return ret; |
| 1341 | } | 1361 | } |
| @@ -1393,7 +1413,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) | @@ -1393,7 +1413,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) | ||
| 1393 | } | 1413 | } |
| 1394 | 1414 | ||
| 1395 | // TODO: FIXME: config the jitter of HLS. | 1415 | // TODO: FIXME: config the jitter of HLS. |
| 1396 | - if ((ret = jitter->correct(video, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { | 1416 | + if ((ret = jitter->correct(video, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { |
| 1397 | srs_error("rtmp jitter correct video failed. ret=%d", ret); | 1417 | srs_error("rtmp jitter correct video failed. ret=%d", ret); |
| 1398 | return ret; | 1418 | return ret; |
| 1399 | } | 1419 | } |
| @@ -233,7 +233,7 @@ private: | @@ -233,7 +233,7 @@ private: | ||
| 233 | int64_t previous_floor_ts; | 233 | int64_t previous_floor_ts; |
| 234 | private: | 234 | private: |
| 235 | int _sequence_no; | 235 | int _sequence_no; |
| 236 | - int target_duration; | 236 | + int max_td; |
| 237 | std::string m3u8; | 237 | std::string m3u8; |
| 238 | std::string m3u8_url; | 238 | std::string m3u8_url; |
| 239 | private: | 239 | private: |
| @@ -805,7 +805,14 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r) | @@ -805,7 +805,14 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r) | ||
| 805 | entry->cache = new SrsStreamCache(s, r); | 805 | entry->cache = new SrsStreamCache(s, r); |
| 806 | entry->stream = new SrsLiveStream(s, r, entry->cache); | 806 | entry->stream = new SrsLiveStream(s, r, entry->cache); |
| 807 | 807 | ||
| 808 | - srs_assert(!tmpl->req); | 808 | + // TODO: FIXME: maybe refine the logic of http remux service. |
| 809 | + // if user push streams followed: | ||
| 810 | + // rtmp://test.com/live/stream1 | ||
| 811 | + // rtmp://test.com/live/stream2 | ||
| 812 | + // and they will using the same template, such as: [vhost]/[app]/[stream].flv | ||
| 813 | + // so, need to free last request object, otherwise, it will cause memory leak. | ||
| 814 | + srs_freep(tmpl->req); | ||
| 815 | + | ||
| 809 | tmpl->source = s; | 816 | tmpl->source = s; |
| 810 | tmpl->req = r->copy(); | 817 | tmpl->req = r->copy(); |
| 811 | 818 | ||
| @@ -1170,8 +1177,8 @@ int SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) | @@ -1170,8 +1177,8 @@ int SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) | ||
| 1170 | std::string sid = r->get_stream_url(); | 1177 | std::string sid = r->get_stream_url(); |
| 1171 | // check if the stream is enabled. | 1178 | // check if the stream is enabled. |
| 1172 | if (sflvs.find(sid) != sflvs.end()) { | 1179 | if (sflvs.find(sid) != sflvs.end()) { |
| 1173 | - SrsLiveEntry* entry = sflvs[sid]; | ||
| 1174 | - if (!entry->stream->entry->enabled) { | 1180 | + SrsLiveEntry* s_entry = sflvs[sid]; |
| 1181 | + if (!s_entry->stream->entry->enabled) { | ||
| 1175 | srs_error("stream is disabled, hijack failed. ret=%d", ret); | 1182 | srs_error("stream is disabled, hijack failed. ret=%d", ret); |
| 1176 | return ret; | 1183 | return ret; |
| 1177 | } | 1184 | } |
| @@ -1228,7 +1235,9 @@ int SrsHttpStreamServer::initialize_flv_streaming() | @@ -1228,7 +1235,9 @@ int SrsHttpStreamServer::initialize_flv_streaming() | ||
| 1228 | continue; | 1235 | continue; |
| 1229 | } | 1236 | } |
| 1230 | 1237 | ||
| 1231 | - initialize_flv_entry(conf->arg0()); | 1238 | + if ((ret = initialize_flv_entry(conf->arg0())) != ERROR_SUCCESS) { |
| 1239 | + return ret; | ||
| 1240 | + } | ||
| 1232 | } | 1241 | } |
| 1233 | return ret; | 1242 | return ret; |
| 1234 | } | 1243 | } |
| @@ -1120,11 +1120,11 @@ int SrsServer::listen_stream_caster() | @@ -1120,11 +1120,11 @@ int SrsServer::listen_stream_caster() | ||
| 1120 | SrsListener* listener = NULL; | 1120 | SrsListener* listener = NULL; |
| 1121 | 1121 | ||
| 1122 | std::string caster = _srs_config->get_stream_caster_engine(stream_caster); | 1122 | std::string caster = _srs_config->get_stream_caster_engine(stream_caster); |
| 1123 | - if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) { | 1123 | + if (srs_stream_caster_is_udp(caster)) { |
| 1124 | listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster); | 1124 | listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster); |
| 1125 | - } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP) { | 1125 | + } else if (srs_stream_caster_is_rtsp(caster)) { |
| 1126 | listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster); | 1126 | listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster); |
| 1127 | - } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_FLV) { | 1127 | + } else if (srs_stream_caster_is_flv(caster)) { |
| 1128 | listener = new SrsHttpFlvListener(this, SrsListenerFlv, stream_caster); | 1128 | listener = new SrsHttpFlvListener(this, SrsListenerFlv, stream_caster); |
| 1129 | } else { | 1129 | } else { |
| 1130 | ret = ERROR_STREAM_CASTER_ENGINE; | 1130 | ret = ERROR_STREAM_CASTER_ENGINE; |
| @@ -55,8 +55,8 @@ using namespace std; | @@ -55,8 +55,8 @@ using namespace std; | ||
| 55 | // 115 packets is 3s. | 55 | // 115 packets is 3s. |
| 56 | #define SRS_PURE_AUDIO_GUESS_COUNT 115 | 56 | #define SRS_PURE_AUDIO_GUESS_COUNT 115 |
| 57 | 57 | ||
| 58 | -// when got these videos or audios, mix ok. | ||
| 59 | -#define SRS_MIX_CORRECT_MIX_AV 10 | 58 | +// when got these videos or audios, pure audio or video, mix ok. |
| 59 | +#define SRS_MIX_CORRECT_PURE_AV 10 | ||
| 60 | 60 | ||
| 61 | int _srs_time_jitter_string2int(std::string time_jitter) | 61 | int _srs_time_jitter_string2int(std::string time_jitter) |
| 62 | { | 62 | { |
| @@ -849,12 +849,25 @@ void SrsMixQueue::push(SrsSharedPtrMessage* msg) | @@ -849,12 +849,25 @@ void SrsMixQueue::push(SrsSharedPtrMessage* msg) | ||
| 849 | 849 | ||
| 850 | SrsSharedPtrMessage* SrsMixQueue::pop() | 850 | SrsSharedPtrMessage* SrsMixQueue::pop() |
| 851 | { | 851 | { |
| 852 | - // when got 10+ videos or audios, mix ok. | ||
| 853 | - // when got 1 video and 1 audio, mix ok. | ||
| 854 | - if (nb_videos < SRS_MIX_CORRECT_MIX_AV && nb_audios < SRS_MIX_CORRECT_MIX_AV) { | ||
| 855 | - if (nb_videos < 1 || nb_audios < 1) { | ||
| 856 | - return NULL; | ||
| 857 | - } | 852 | + bool mix_ok = false; |
| 853 | + | ||
| 854 | + // pure video | ||
| 855 | + if (nb_videos >= SRS_MIX_CORRECT_PURE_AV && nb_audios == 0) { | ||
| 856 | + mix_ok = true; | ||
| 857 | + } | ||
| 858 | + | ||
| 859 | + // pure audio | ||
| 860 | + if (nb_audios >= SRS_MIX_CORRECT_PURE_AV && nb_videos == 0) { | ||
| 861 | + mix_ok = true; | ||
| 862 | + } | ||
| 863 | + | ||
| 864 | + // got 1 video and 1 audio, mix ok. | ||
| 865 | + if (nb_videos >= 1 && nb_audios >= 1) { | ||
| 866 | + mix_ok = true; | ||
| 867 | + } | ||
| 868 | + | ||
| 869 | + if (!mix_ok) { | ||
| 870 | + return NULL; | ||
| 858 | } | 871 | } |
| 859 | 872 | ||
| 860 | // pop the first msg. | 873 | // pop the first msg. |
-
请 注册 或 登录 后发表评论