正在显示
10 个修改的文件
包含
1156 行增加
和
884 行删除
| @@ -184,6 +184,7 @@ Please select your language: | @@ -184,6 +184,7 @@ Please select your language: | ||
| 184 | 184 | ||
| 185 | ### V3 changes | 185 | ### V3 changes |
| 186 | 186 | ||
| 187 | +* v3.0, 2017-01-19, for [#742][bug #742] refine source, meta and origin hub. 3.0.16 | ||
| 187 | * v3.0, 2017-01-17, for [#742][bug #742] refine source, timeout, live cycle. 3.0.15 | 188 | * v3.0, 2017-01-17, for [#742][bug #742] refine source, timeout, live cycle. 3.0.15 |
| 188 | * v3.0, 2017-01-11, fix [#735][bug #735] config transform refer_publish invalid. 3.0.14 | 189 | * v3.0, 2017-01-11, fix [#735][bug #735] config transform refer_publish invalid. 3.0.14 |
| 189 | * v3.0, 2017-01-06, for [#730][bug #730] support config in/out ack size. 3.0.13 | 190 | * v3.0, 2017-01-06, for [#730][bug #730] support config in/out ack size. 3.0.13 |
| @@ -872,13 +873,13 @@ Remark: | @@ -872,13 +873,13 @@ Remark: | ||
| 872 | | Input | SRS(Simple RTMP Server) | Output | | 873 | | Input | SRS(Simple RTMP Server) | Output | |
| 873 | +----------------------+-------------------------+----------------+ | 874 | +----------------------+-------------------------+----------------+ |
| 874 | | Encoder(1) | +-> RTMP/HDS --------+-> Flash player | | 875 | | Encoder(1) | +-> RTMP/HDS --------+-> Flash player | |
| 875 | -| (FMLE,FFMPEG, -rtmp-+->-+-> HLS/HTTP ---------+-> M3u8 player | | 876 | +| (FMLE,FFMPEG, -rtmp-+->-+-> HLS/HTTP ---------+-> M3U8 player | |
| 876 | | Flash,XSPLIT, | +-> FLV/MP3/Aac/Ts ---+-> HTTP player | | 877 | | Flash,XSPLIT, | +-> FLV/MP3/Aac/Ts ---+-> HTTP player | |
| 877 | | ......) | +-> Fowarder ---------+-> RTMP server | | 878 | | ......) | +-> Fowarder ---------+-> RTMP server | |
| 878 | | | +-> Transcoder -------+-> RTMP server | | 879 | | | +-> Transcoder -------+-> RTMP server | |
| 879 | | | +-> EXEC(5) ----------+-> External app | | 880 | | | +-> EXEC(5) ----------+-> External app | |
| 880 | -| | +-> DVR --------------+-> Flv file | | ||
| 881 | -| | +-> BandwidthTest ----+-> flash | | 881 | +| | +-> DVR --------------+-> FLV file | |
| 882 | +| | +-> BandwidthTest ----+-> Flash | | ||
| 882 | +----------------------+ | | | 883 | +----------------------+ | | |
| 883 | | MediaSource(2) | | | | 884 | | MediaSource(2) | | | |
| 884 | | (RTSP,FILE, | | | | 885 | | (RTSP,FILE, | | | |
| @@ -970,7 +970,7 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg) | @@ -970,7 +970,7 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg) | ||
| 970 | 970 | ||
| 971 | SrsDvr::SrsDvr() | 971 | SrsDvr::SrsDvr() |
| 972 | { | 972 | { |
| 973 | - source = NULL; | 973 | + hub = NULL; |
| 974 | plan = NULL; | 974 | plan = NULL; |
| 975 | req = NULL; | 975 | req = NULL; |
| 976 | actived = false; | 976 | actived = false; |
| @@ -985,12 +985,12 @@ SrsDvr::~SrsDvr() | @@ -985,12 +985,12 @@ SrsDvr::~SrsDvr() | ||
| 985 | srs_freep(plan); | 985 | srs_freep(plan); |
| 986 | } | 986 | } |
| 987 | 987 | ||
| 988 | -int SrsDvr::initialize(SrsSource* s, SrsRequest* r) | 988 | +int SrsDvr::initialize(SrsOriginHub* h, SrsRequest* r) |
| 989 | { | 989 | { |
| 990 | int ret = ERROR_SUCCESS; | 990 | int ret = ERROR_SUCCESS; |
| 991 | 991 | ||
| 992 | req = r; | 992 | req = r; |
| 993 | - source = s; | 993 | + hub = h; |
| 994 | 994 | ||
| 995 | SrsConfDirective* conf = _srs_config->get_dvr_apply(r->vhost); | 995 | SrsConfDirective* conf = _srs_config->get_dvr_apply(r->vhost); |
| 996 | actived = srs_config_apply_filter(conf, r); | 996 | actived = srs_config_apply_filter(conf, r); |
| @@ -1018,7 +1018,7 @@ int SrsDvr::on_publish(bool fetch_sequence_header) | @@ -1018,7 +1018,7 @@ int SrsDvr::on_publish(bool fetch_sequence_header) | ||
| 1018 | return ret; | 1018 | return ret; |
| 1019 | } | 1019 | } |
| 1020 | 1020 | ||
| 1021 | - if (fetch_sequence_header && (ret = source->on_dvr_request_sh()) != ERROR_SUCCESS) { | 1021 | + if (fetch_sequence_header && (ret = hub->on_dvr_request_sh()) != ERROR_SUCCESS) { |
| 1022 | return ret; | 1022 | return ret; |
| 1023 | } | 1023 | } |
| 1024 | 1024 |
| @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 35 | #ifdef SRS_AUTO_DVR | 35 | #ifdef SRS_AUTO_DVR |
| 36 | 36 | ||
| 37 | class SrsSource; | 37 | class SrsSource; |
| 38 | +class SrsOriginHub; | ||
| 38 | class SrsRequest; | 39 | class SrsRequest; |
| 39 | class SrsBuffer; | 40 | class SrsBuffer; |
| 40 | class SrsRtmpJitter; | 41 | class SrsRtmpJitter; |
| @@ -300,7 +301,7 @@ private: | @@ -300,7 +301,7 @@ private: | ||
| 300 | class SrsDvr : public ISrsReloadHandler | 301 | class SrsDvr : public ISrsReloadHandler |
| 301 | { | 302 | { |
| 302 | private: | 303 | private: |
| 303 | - SrsSource* source; | 304 | + SrsOriginHub* hub; |
| 304 | SrsDvrPlan* plan; | 305 | SrsDvrPlan* plan; |
| 305 | SrsRequest* req; | 306 | SrsRequest* req; |
| 306 | private: | 307 | private: |
| @@ -317,7 +318,7 @@ public: | @@ -317,7 +318,7 @@ public: | ||
| 317 | * when system initialize(encoder publish at first time, or reload), | 318 | * when system initialize(encoder publish at first time, or reload), |
| 318 | * initialize the dvr will reinitialize the plan, the whole dvr framework. | 319 | * initialize the dvr will reinitialize the plan, the whole dvr framework. |
| 319 | */ | 320 | */ |
| 320 | - virtual int initialize(SrsSource* s, SrsRequest* r); | 321 | + virtual int initialize(SrsOriginHub* h, SrsRequest* r); |
| 321 | /** | 322 | /** |
| 322 | * publish stream event, | 323 | * publish stream event, |
| 323 | * when encoder start to publish RTMP stream. | 324 | * when encoder start to publish RTMP stream. |
| @@ -50,9 +50,9 @@ using namespace std; | @@ -50,9 +50,9 @@ using namespace std; | ||
| 50 | // when error, forwarder sleep for a while and retry. | 50 | // when error, forwarder sleep for a while and retry. |
| 51 | #define SRS_FORWARDER_CIMS (3000) | 51 | #define SRS_FORWARDER_CIMS (3000) |
| 52 | 52 | ||
| 53 | -SrsForwarder::SrsForwarder(SrsSource* s) | 53 | +SrsForwarder::SrsForwarder(SrsOriginHub* h) |
| 54 | { | 54 | { |
| 55 | - source = s; | 55 | + hub = h; |
| 56 | 56 | ||
| 57 | req = NULL; | 57 | req = NULL; |
| 58 | sh_video = sh_audio = NULL; | 58 | sh_video = sh_audio = NULL; |
| @@ -250,7 +250,7 @@ int SrsForwarder::cycle() | @@ -250,7 +250,7 @@ int SrsForwarder::cycle() | ||
| 250 | return ret; | 250 | return ret; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | - if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) { | 253 | + if ((ret = hub->on_forwarder_start(this)) != ERROR_SUCCESS) { |
| 254 | srs_error("callback the source to feed the sequence header failed. ret=%d", ret); | 254 | srs_error("callback the source to feed the sequence header failed. ret=%d", ret); |
| 255 | return ret; | 255 | return ret; |
| 256 | } | 256 | } |
| @@ -42,6 +42,7 @@ class SrsRtmpJitter; | @@ -42,6 +42,7 @@ class SrsRtmpJitter; | ||
| 42 | class SrsRtmpClient; | 42 | class SrsRtmpClient; |
| 43 | class SrsRequest; | 43 | class SrsRequest; |
| 44 | class SrsSource; | 44 | class SrsSource; |
| 45 | +class SrsOriginHub; | ||
| 45 | class SrsKbps; | 46 | class SrsKbps; |
| 46 | class SrsSimpleRtmpClient; | 47 | class SrsSimpleRtmpClient; |
| 47 | 48 | ||
| @@ -58,7 +59,7 @@ private: | @@ -58,7 +59,7 @@ private: | ||
| 58 | private: | 59 | private: |
| 59 | SrsReusableThread2* pthread; | 60 | SrsReusableThread2* pthread; |
| 60 | private: | 61 | private: |
| 61 | - SrsSource* source; | 62 | + SrsOriginHub* hub; |
| 62 | SrsSimpleRtmpClient* sdk; | 63 | SrsSimpleRtmpClient* sdk; |
| 63 | SrsRtmpJitter* jitter; | 64 | SrsRtmpJitter* jitter; |
| 64 | SrsMessageQueue* queue; | 65 | SrsMessageQueue* queue; |
| @@ -69,7 +70,7 @@ private: | @@ -69,7 +70,7 @@ private: | ||
| 69 | SrsSharedPtrMessage* sh_audio; | 70 | SrsSharedPtrMessage* sh_audio; |
| 70 | SrsSharedPtrMessage* sh_video; | 71 | SrsSharedPtrMessage* sh_video; |
| 71 | public: | 72 | public: |
| 72 | - SrsForwarder(SrsSource* _source); | 73 | + SrsForwarder(SrsOriginHub* h); |
| 73 | virtual ~SrsForwarder(); | 74 | virtual ~SrsForwarder(); |
| 74 | public: | 75 | public: |
| 75 | virtual int initialize(SrsRequest* r, std::string ep); | 76 | virtual int initialize(SrsRequest* r, std::string ep); |
| @@ -1125,7 +1125,7 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme | @@ -1125,7 +1125,7 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme | ||
| 1125 | SrsHls::SrsHls() | 1125 | SrsHls::SrsHls() |
| 1126 | { | 1126 | { |
| 1127 | req = NULL; | 1127 | req = NULL; |
| 1128 | - source = NULL; | 1128 | + hub = NULL; |
| 1129 | 1129 | ||
| 1130 | hls_enabled = false; | 1130 | hls_enabled = false; |
| 1131 | hls_can_dispose = false; | 1131 | hls_can_dispose = false; |
| @@ -1197,11 +1197,11 @@ int SrsHls::cycle() | @@ -1197,11 +1197,11 @@ int SrsHls::cycle() | ||
| 1197 | return ret; | 1197 | return ret; |
| 1198 | } | 1198 | } |
| 1199 | 1199 | ||
| 1200 | -int SrsHls::initialize(SrsSource* s, SrsRequest* r) | 1200 | +int SrsHls::initialize(SrsOriginHub* h, SrsRequest* r) |
| 1201 | { | 1201 | { |
| 1202 | int ret = ERROR_SUCCESS; | 1202 | int ret = ERROR_SUCCESS; |
| 1203 | 1203 | ||
| 1204 | - source = s; | 1204 | + hub = h; |
| 1205 | req = r; | 1205 | req = r; |
| 1206 | 1206 | ||
| 1207 | if ((ret = muxer->initialize()) != ERROR_SUCCESS) { | 1207 | if ((ret = muxer->initialize()) != ERROR_SUCCESS) { |
| @@ -1244,7 +1244,7 @@ int SrsHls::on_publish(bool fetch_sequence_header) | @@ -1244,7 +1244,7 @@ int SrsHls::on_publish(bool fetch_sequence_header) | ||
| 1244 | // notice the source to get the cached sequence header. | 1244 | // notice the source to get the cached sequence header. |
| 1245 | // when reload to start hls, hls will never get the sequence header in stream, | 1245 | // when reload to start hls, hls will never get the sequence header in stream, |
| 1246 | // use the SrsSource.on_hls_start to push the sequence header to HLS. | 1246 | // use the SrsSource.on_hls_start to push the sequence header to HLS. |
| 1247 | - if ((ret = source->on_hls_start()) != ERROR_SUCCESS) { | 1247 | + if ((ret = hub->on_hls_start()) != ERROR_SUCCESS) { |
| 1248 | srs_error("callback source hls start failed. ret=%d", ret); | 1248 | srs_error("callback source hls start failed. ret=%d", ret); |
| 1249 | return ret; | 1249 | return ret; |
| 1250 | } | 1250 | } |
| @@ -45,6 +45,7 @@ class SrsAvcAacCodec; | @@ -45,6 +45,7 @@ class SrsAvcAacCodec; | ||
| 45 | class SrsRequest; | 45 | class SrsRequest; |
| 46 | class SrsPithyPrint; | 46 | class SrsPithyPrint; |
| 47 | class SrsSource; | 47 | class SrsSource; |
| 48 | +class SrsOriginHub; | ||
| 48 | class SrsFileWriter; | 49 | class SrsFileWriter; |
| 49 | class SrsSimpleStream; | 50 | class SrsSimpleStream; |
| 50 | class SrsTsAacJitter; | 51 | class SrsTsAacJitter; |
| @@ -362,7 +363,7 @@ private: | @@ -362,7 +363,7 @@ private: | ||
| 362 | bool hls_can_dispose; | 363 | bool hls_can_dispose; |
| 363 | int64_t last_update_time; | 364 | int64_t last_update_time; |
| 364 | private: | 365 | private: |
| 365 | - SrsSource* source; | 366 | + SrsOriginHub* hub; |
| 366 | SrsAvcAacCodec* codec; | 367 | SrsAvcAacCodec* codec; |
| 367 | SrsCodecSample* sample; | 368 | SrsCodecSample* sample; |
| 368 | SrsRtmpJitter* jitter; | 369 | SrsRtmpJitter* jitter; |
| @@ -391,7 +392,7 @@ public: | @@ -391,7 +392,7 @@ public: | ||
| 391 | /** | 392 | /** |
| 392 | * initialize the hls by handler and source. | 393 | * initialize the hls by handler and source. |
| 393 | */ | 394 | */ |
| 394 | - virtual int initialize(SrsSource* s, SrsRequest* r); | 395 | + virtual int initialize(SrsOriginHub* h, SrsRequest* r); |
| 395 | /** | 396 | /** |
| 396 | * publish stream event, continue to write the m3u8, | 397 | * publish stream event, continue to write the m3u8, |
| 397 | * for the muxer object not destroyed. | 398 | * for the muxer object not destroyed. |
| @@ -745,207 +745,29 @@ ISrsSourceHandler::~ISrsSourceHandler() | @@ -745,207 +745,29 @@ ISrsSourceHandler::~ISrsSourceHandler() | ||
| 745 | { | 745 | { |
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | -std::map<std::string, SrsSource*> SrsSource::pool; | ||
| 749 | - | ||
| 750 | -int SrsSource::fetch_or_create(SrsRequest* r, ISrsSourceHandler* h, SrsSource** pps) | ||
| 751 | -{ | ||
| 752 | - int ret = ERROR_SUCCESS; | ||
| 753 | - | ||
| 754 | - SrsSource* source = NULL; | ||
| 755 | - if ((source = fetch(r)) != NULL) { | ||
| 756 | - *pps = source; | ||
| 757 | - return ret; | ||
| 758 | - } | ||
| 759 | - | ||
| 760 | - string stream_url = r->get_stream_url(); | ||
| 761 | - string vhost = r->vhost; | ||
| 762 | - | ||
| 763 | - // should always not exists for create a source. | ||
| 764 | - srs_assert (pool.find(stream_url) == pool.end()); | ||
| 765 | - | ||
| 766 | - source = new SrsSource(); | ||
| 767 | - if ((ret = source->initialize(r, h)) != ERROR_SUCCESS) { | ||
| 768 | - srs_freep(source); | ||
| 769 | - return ret; | ||
| 770 | - } | ||
| 771 | - | ||
| 772 | - pool[stream_url] = source; | ||
| 773 | - srs_info("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); | ||
| 774 | - | ||
| 775 | - *pps = source; | ||
| 776 | - | ||
| 777 | - return ret; | ||
| 778 | -} | ||
| 779 | - | ||
| 780 | -SrsSource* SrsSource::fetch(SrsRequest* r) | ||
| 781 | -{ | ||
| 782 | - SrsSource* source = NULL; | ||
| 783 | - | ||
| 784 | - string stream_url = r->get_stream_url(); | ||
| 785 | - if (pool.find(stream_url) == pool.end()) { | ||
| 786 | - return NULL; | ||
| 787 | - } | ||
| 788 | - | ||
| 789 | - source = pool[stream_url]; | ||
| 790 | - | ||
| 791 | - // we always update the request of resource, | ||
| 792 | - // for origin auth is on, the token in request maybe invalid, | ||
| 793 | - // and we only need to update the token of request, it's simple. | ||
| 794 | - source->req->update_auth(r); | ||
| 795 | - | ||
| 796 | - return source; | ||
| 797 | -} | ||
| 798 | - | ||
| 799 | -void SrsSource::dispose_all() | ||
| 800 | -{ | ||
| 801 | - std::map<std::string, SrsSource*>::iterator it; | ||
| 802 | - for (it = pool.begin(); it != pool.end(); ++it) { | ||
| 803 | - SrsSource* source = it->second; | ||
| 804 | - source->dispose(); | ||
| 805 | - } | ||
| 806 | - return; | ||
| 807 | -} | ||
| 808 | - | ||
| 809 | -int SrsSource::cycle_all() | ||
| 810 | -{ | ||
| 811 | - int ret = ERROR_SUCCESS; | ||
| 812 | - | ||
| 813 | - int cid = _srs_context->get_id(); | ||
| 814 | - ret = do_cycle_all(); | ||
| 815 | - _srs_context->set_id(cid); | ||
| 816 | - | ||
| 817 | - return ret; | ||
| 818 | -} | ||
| 819 | - | ||
| 820 | -int SrsSource::do_cycle_all() | ||
| 821 | -{ | ||
| 822 | - int ret = ERROR_SUCCESS; | ||
| 823 | - | ||
| 824 | - std::map<std::string, SrsSource*>::iterator it; | ||
| 825 | - for (it = pool.begin(); it != pool.end();) { | ||
| 826 | - SrsSource* source = it->second; | ||
| 827 | - | ||
| 828 | - // Do cycle source to cleanup components, such as hls dispose. | ||
| 829 | - if ((ret = source->cycle()) != ERROR_SUCCESS) { | ||
| 830 | - return ret; | ||
| 831 | - } | ||
| 832 | - | ||
| 833 | - // TODO: FIXME: support source cleanup. | ||
| 834 | - // @see https://github.com/ossrs/srs/issues/713 | ||
| 835 | - // @see https://github.com/ossrs/srs/issues/714 | ||
| 836 | -#if 0 | ||
| 837 | - // When source expired, remove it. | ||
| 838 | - if (source->expired()) { | ||
| 839 | - int cid = source->source_id(); | ||
| 840 | - if (cid == -1 && source->pre_source_id() > 0) { | ||
| 841 | - cid = source->pre_source_id(); | ||
| 842 | - } | ||
| 843 | - if (cid > 0) { | ||
| 844 | - _srs_context->set_id(cid); | ||
| 845 | - } | ||
| 846 | - srs_trace("cleanup die source, total=%d", (int)pool.size()); | ||
| 847 | - | ||
| 848 | - srs_freep(source); | ||
| 849 | - pool.erase(it++); | ||
| 850 | - } else { | ||
| 851 | - ++it; | ||
| 852 | - } | ||
| 853 | -#else | ||
| 854 | - ++it; | ||
| 855 | -#endif | ||
| 856 | - } | ||
| 857 | - | ||
| 858 | - return ret; | ||
| 859 | -} | ||
| 860 | - | ||
| 861 | -void SrsSource::destroy() | ||
| 862 | -{ | ||
| 863 | - std::map<std::string, SrsSource*>::iterator it; | ||
| 864 | - for (it = pool.begin(); it != pool.end(); ++it) { | ||
| 865 | - SrsSource* source = it->second; | ||
| 866 | - srs_freep(source); | ||
| 867 | - } | ||
| 868 | - pool.clear(); | ||
| 869 | -} | ||
| 870 | - | ||
| 871 | -SrsMixQueue::SrsMixQueue() | ||
| 872 | -{ | ||
| 873 | - nb_videos = 0; | ||
| 874 | - nb_audios = 0; | ||
| 875 | -} | ||
| 876 | - | ||
| 877 | -SrsMixQueue::~SrsMixQueue() | ||
| 878 | -{ | ||
| 879 | - clear(); | ||
| 880 | -} | ||
| 881 | - | ||
| 882 | -void SrsMixQueue::clear() | ||
| 883 | -{ | ||
| 884 | - std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it; | ||
| 885 | - for (it = msgs.begin(); it != msgs.end(); ++it) { | ||
| 886 | - SrsSharedPtrMessage* msg = it->second; | ||
| 887 | - srs_freep(msg); | ||
| 888 | - } | ||
| 889 | - msgs.clear(); | ||
| 890 | - | ||
| 891 | - nb_videos = 0; | ||
| 892 | - nb_audios = 0; | ||
| 893 | -} | ||
| 894 | - | ||
| 895 | -void SrsMixQueue::push(SrsSharedPtrMessage* msg) | ||
| 896 | -{ | ||
| 897 | - msgs.insert(std::make_pair(msg->timestamp, msg)); | ||
| 898 | - | ||
| 899 | - if (msg->is_video()) { | ||
| 900 | - nb_videos++; | ||
| 901 | - } else { | ||
| 902 | - nb_audios++; | ||
| 903 | - } | ||
| 904 | -} | ||
| 905 | - | ||
| 906 | -SrsSharedPtrMessage* SrsMixQueue::pop() | 748 | +// TODO: FIXME: Remove it? |
| 749 | +bool srs_hls_can_continue(int ret, SrsSharedPtrMessage* sh, SrsSharedPtrMessage* msg) | ||
| 907 | { | 750 | { |
| 908 | - bool mix_ok = false; | ||
| 909 | - | ||
| 910 | - // pure video | ||
| 911 | - if (nb_videos >= SRS_MIX_CORRECT_PURE_AV && nb_audios == 0) { | ||
| 912 | - mix_ok = true; | ||
| 913 | - } | ||
| 914 | - | ||
| 915 | - // pure audio | ||
| 916 | - if (nb_audios >= SRS_MIX_CORRECT_PURE_AV && nb_videos == 0) { | ||
| 917 | - mix_ok = true; | ||
| 918 | - } | ||
| 919 | - | ||
| 920 | - // got 1 video and 1 audio, mix ok. | ||
| 921 | - if (nb_videos >= 1 && nb_audios >= 1) { | ||
| 922 | - mix_ok = true; | ||
| 923 | - } | ||
| 924 | - | ||
| 925 | - if (!mix_ok) { | ||
| 926 | - return NULL; | 751 | + // only continue for decode error. |
| 752 | + if (ret != ERROR_HLS_DECODE_ERROR) { | ||
| 753 | + return false; | ||
| 927 | } | 754 | } |
| 928 | 755 | ||
| 929 | - // pop the first msg. | ||
| 930 | - std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it = msgs.begin(); | ||
| 931 | - SrsSharedPtrMessage* msg = it->second; | ||
| 932 | - msgs.erase(it); | ||
| 933 | - | ||
| 934 | - if (msg->is_video()) { | ||
| 935 | - nb_videos--; | ||
| 936 | - } else { | ||
| 937 | - nb_audios--; | 756 | + // when video size equals to sequence header, |
| 757 | + // the video actually maybe a sequence header, | ||
| 758 | + // continue to make ffmpeg happy. | ||
| 759 | + if (sh && sh->size == msg->size) { | ||
| 760 | + srs_warn("the msg is actually a sequence header, ignore this packet."); | ||
| 761 | + return true; | ||
| 938 | } | 762 | } |
| 939 | 763 | ||
| 940 | - return msg; | 764 | + return false; |
| 941 | } | 765 | } |
| 942 | 766 | ||
| 943 | -SrsSource::SrsSource() | 767 | +SrsOriginHub::SrsOriginHub(SrsSource* s) |
| 944 | { | 768 | { |
| 769 | + source = s; | ||
| 945 | req = NULL; | 770 | req = NULL; |
| 946 | - jitter_algorithm = SrsRtmpJitterAlgorithmOFF; | ||
| 947 | - mix_correct = false; | ||
| 948 | - mix_queue = new SrsMixQueue(); | ||
| 949 | 771 | ||
| 950 | #ifdef SRS_AUTO_HLS | 772 | #ifdef SRS_AUTO_HLS |
| 951 | hls = new SrsHls(); | 773 | hls = new SrsHls(); |
| @@ -957,36 +779,17 @@ SrsSource::SrsSource() | @@ -957,36 +779,17 @@ SrsSource::SrsSource() | ||
| 957 | encoder = new SrsEncoder(); | 779 | encoder = new SrsEncoder(); |
| 958 | #endif | 780 | #endif |
| 959 | #ifdef SRS_AUTO_HDS | 781 | #ifdef SRS_AUTO_HDS |
| 960 | - hds = new SrsHds(this); | 782 | + hds = new SrsHds(s); |
| 961 | #endif | 783 | #endif |
| 962 | - | ||
| 963 | - cache_metadata = cache_sh_video = cache_sh_audio = NULL; | ||
| 964 | - | ||
| 965 | - _can_publish = true; | ||
| 966 | - _pre_source_id = _source_id = -1; | ||
| 967 | - die_at = -1; | ||
| 968 | - | ||
| 969 | - play_edge = new SrsPlayEdge(); | ||
| 970 | - publish_edge = new SrsPublishEdge(); | ||
| 971 | - gop_cache = new SrsGopCache(); | ||
| 972 | - aggregate_stream = new SrsBuffer(); | ||
| 973 | ng_exec = new SrsNgExec(); | 784 | ng_exec = new SrsNgExec(); |
| 974 | 785 | ||
| 975 | - is_monotonically_increase = false; | ||
| 976 | - last_packet_time = 0; | ||
| 977 | - | ||
| 978 | _srs_config->subscribe(this); | 786 | _srs_config->subscribe(this); |
| 979 | - atc = false; | ||
| 980 | } | 787 | } |
| 981 | 788 | ||
| 982 | -SrsSource::~SrsSource() | 789 | +SrsOriginHub::~SrsOriginHub() |
| 983 | { | 790 | { |
| 984 | _srs_config->unsubscribe(this); | 791 | _srs_config->unsubscribe(this); |
| 985 | 792 | ||
| 986 | - // never free the consumers, | ||
| 987 | - // for all consumers are auto free. | ||
| 988 | - consumers.clear(); | ||
| 989 | - | ||
| 990 | if (true) { | 793 | if (true) { |
| 991 | std::vector<SrsForwarder*>::iterator it; | 794 | std::vector<SrsForwarder*>::iterator it; |
| 992 | for (it = forwarders.begin(); it != forwarders.end(); ++it) { | 795 | for (it = forwarders.begin(); it != forwarders.end(); ++it) { |
| @@ -995,16 +798,6 @@ SrsSource::~SrsSource() | @@ -995,16 +798,6 @@ SrsSource::~SrsSource() | ||
| 995 | } | 798 | } |
| 996 | forwarders.clear(); | 799 | forwarders.clear(); |
| 997 | } | 800 | } |
| 998 | - | ||
| 999 | - srs_freep(mix_queue); | ||
| 1000 | - srs_freep(cache_metadata); | ||
| 1001 | - srs_freep(cache_sh_video); | ||
| 1002 | - srs_freep(cache_sh_audio); | ||
| 1003 | - | ||
| 1004 | - srs_freep(play_edge); | ||
| 1005 | - srs_freep(publish_edge); | ||
| 1006 | - srs_freep(gop_cache); | ||
| 1007 | - srs_freep(aggregate_stream); | ||
| 1008 | srs_freep(ng_exec); | 801 | srs_freep(ng_exec); |
| 1009 | 802 | ||
| 1010 | #ifdef SRS_AUTO_HLS | 803 | #ifdef SRS_AUTO_HLS |
| @@ -1019,208 +812,429 @@ SrsSource::~SrsSource() | @@ -1019,208 +812,429 @@ SrsSource::~SrsSource() | ||
| 1019 | #ifdef SRS_AUTO_HDS | 812 | #ifdef SRS_AUTO_HDS |
| 1020 | srs_freep(hds); | 813 | srs_freep(hds); |
| 1021 | #endif | 814 | #endif |
| 1022 | - | ||
| 1023 | - srs_freep(req); | ||
| 1024 | -} | ||
| 1025 | - | ||
| 1026 | -void SrsSource::dispose() | ||
| 1027 | -{ | ||
| 1028 | -#ifdef SRS_AUTO_HLS | ||
| 1029 | - hls->dispose(); | ||
| 1030 | -#endif | ||
| 1031 | - | ||
| 1032 | - // cleaup the cached packets. | ||
| 1033 | - srs_freep(cache_metadata); | ||
| 1034 | - srs_freep(cache_sh_video); | ||
| 1035 | - srs_freep(cache_sh_audio); | ||
| 1036 | - | ||
| 1037 | - // cleanup the gop cache. | ||
| 1038 | - gop_cache->dispose(); | ||
| 1039 | } | 815 | } |
| 1040 | 816 | ||
| 1041 | -int SrsSource::cycle() | 817 | +int SrsOriginHub::initialize(SrsRequest* r) |
| 1042 | { | 818 | { |
| 1043 | int ret = ERROR_SUCCESS; | 819 | int ret = ERROR_SUCCESS; |
| 1044 | 820 | ||
| 821 | + req = r; | ||
| 822 | + | ||
| 1045 | #ifdef SRS_AUTO_HLS | 823 | #ifdef SRS_AUTO_HLS |
| 1046 | - if ((ret = hls->cycle()) != ERROR_SUCCESS) { | 824 | + if ((ret = hls->initialize(this, req)) != ERROR_SUCCESS) { |
| 1047 | return ret; | 825 | return ret; |
| 1048 | } | 826 | } |
| 1049 | #endif | 827 | #endif |
| 1050 | 828 | ||
| 1051 | - return ret; | ||
| 1052 | -} | ||
| 1053 | - | ||
| 1054 | -bool SrsSource::expired() | ||
| 1055 | -{ | ||
| 1056 | - // unknown state? | ||
| 1057 | - if (die_at == -1) { | ||
| 1058 | - return false; | ||
| 1059 | - } | ||
| 1060 | - | ||
| 1061 | - // still publishing? | ||
| 1062 | - if (!_can_publish || !publish_edge->can_publish()) { | ||
| 1063 | - return false; | 829 | +#ifdef SRS_AUTO_DVR |
| 830 | + if ((ret = dvr->initialize(this, req)) != ERROR_SUCCESS) { | ||
| 831 | + return ret; | ||
| 1064 | } | 832 | } |
| 833 | +#endif | ||
| 1065 | 834 | ||
| 1066 | - // has any consumers? | ||
| 1067 | - if (!consumers.empty()) { | ||
| 1068 | - return false; | ||
| 1069 | - } | 835 | + return ret; |
| 836 | +} | ||
| 837 | + | ||
| 838 | +void SrsOriginHub::dispose() | ||
| 839 | +{ | ||
| 840 | +#ifdef SRS_AUTO_HLS | ||
| 841 | + hls->dispose(); | ||
| 842 | +#endif | ||
| 843 | +} | ||
| 844 | + | ||
| 845 | +int SrsOriginHub::cycle() | ||
| 846 | +{ | ||
| 847 | + int ret = ERROR_SUCCESS; | ||
| 1070 | 848 | ||
| 1071 | - int64_t now = srs_get_system_time_ms(); | ||
| 1072 | - if (now > die_at + SRS_SOURCE_CLEANUP) { | ||
| 1073 | - return true; | 849 | +#ifdef SRS_AUTO_HLS |
| 850 | + if ((ret = hls->cycle()) != ERROR_SUCCESS) { | ||
| 851 | + return ret; | ||
| 1074 | } | 852 | } |
| 853 | +#endif | ||
| 1075 | 854 | ||
| 1076 | - return false; | 855 | + return ret; |
| 1077 | } | 856 | } |
| 1078 | 857 | ||
| 1079 | -int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h) | 858 | +int SrsOriginHub::on_original_metadata(SrsOnMetaDataPacket* metadata) |
| 1080 | { | 859 | { |
| 1081 | int ret = ERROR_SUCCESS; | 860 | int ret = ERROR_SUCCESS; |
| 1082 | 861 | ||
| 1083 | - srs_assert(h); | ||
| 1084 | - srs_assert(!req); | ||
| 1085 | - | ||
| 1086 | - handler = h; | ||
| 1087 | - req = r->copy(); | ||
| 1088 | - atc = _srs_config->get_atc(req->vhost); | ||
| 1089 | - | ||
| 1090 | #ifdef SRS_AUTO_HLS | 862 | #ifdef SRS_AUTO_HLS |
| 1091 | - if ((ret = hls->initialize(this, req)) != ERROR_SUCCESS) { | 863 | + if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { |
| 864 | + srs_error("hls process onMetaData message failed. ret=%d", ret); | ||
| 1092 | return ret; | 865 | return ret; |
| 1093 | } | 866 | } |
| 1094 | #endif | 867 | #endif |
| 1095 | 868 | ||
| 1096 | #ifdef SRS_AUTO_DVR | 869 | #ifdef SRS_AUTO_DVR |
| 1097 | - if ((ret = dvr->initialize(this, req)) != ERROR_SUCCESS) { | 870 | + if (metadata && (ret = dvr->on_meta_data(metadata)) != ERROR_SUCCESS) { |
| 871 | + srs_error("dvr process onMetaData message failed. ret=%d", ret); | ||
| 1098 | return ret; | 872 | return ret; |
| 1099 | } | 873 | } |
| 1100 | #endif | 874 | #endif |
| 1101 | - | ||
| 1102 | - if ((ret = play_edge->initialize(this, req)) != ERROR_SUCCESS) { | ||
| 1103 | - return ret; | ||
| 1104 | - } | ||
| 1105 | - if ((ret = publish_edge->initialize(this, req)) != ERROR_SUCCESS) { | ||
| 1106 | - return ret; | ||
| 1107 | - } | ||
| 1108 | - | ||
| 1109 | - double queue_size = _srs_config->get_queue_length(req->vhost); | ||
| 1110 | - publish_edge->set_queue_size(queue_size); | ||
| 1111 | - | ||
| 1112 | - jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost); | ||
| 1113 | - mix_correct = _srs_config->get_mix_correct(req->vhost); | ||
| 1114 | 875 | ||
| 1115 | return ret; | 876 | return ret; |
| 1116 | } | 877 | } |
| 1117 | 878 | ||
| 1118 | -int SrsSource::on_reload_vhost_play(string vhost) | 879 | +int SrsOriginHub::on_meta_data(SrsSharedPtrMessage* shared_metadata) |
| 1119 | { | 880 | { |
| 1120 | int ret = ERROR_SUCCESS; | 881 | int ret = ERROR_SUCCESS; |
| 1121 | 882 | ||
| 1122 | - if (req->vhost != vhost) { | ||
| 1123 | - return ret; | 883 | + // copy to all forwarders |
| 884 | + if (true) { | ||
| 885 | + std::vector<SrsForwarder*>::iterator it; | ||
| 886 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 887 | + SrsForwarder* forwarder = *it; | ||
| 888 | + if ((ret = forwarder->on_meta_data(shared_metadata)) != ERROR_SUCCESS) { | ||
| 889 | + srs_error("forwarder process onMetaData message failed. ret=%d", ret); | ||
| 890 | + return ret; | ||
| 891 | + } | ||
| 892 | + } | ||
| 1124 | } | 893 | } |
| 1125 | 894 | ||
| 1126 | - // time_jitter | ||
| 1127 | - jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost); | 895 | + return ret; |
| 896 | +} | ||
| 897 | + | ||
| 898 | +int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio) | ||
| 899 | +{ | ||
| 900 | + int ret = ERROR_SUCCESS; | ||
| 1128 | 901 | ||
| 1129 | - // mix_correct | ||
| 1130 | - if (true) { | ||
| 1131 | - bool v = _srs_config->get_mix_correct(req->vhost); | ||
| 1132 | - | ||
| 1133 | - // when changed, clear the mix queue. | ||
| 1134 | - if (v != mix_correct) { | ||
| 1135 | - mix_queue->clear(); | 902 | + SrsSharedPtrMessage* msg = shared_audio; |
| 903 | + | ||
| 904 | +#ifdef SRS_AUTO_HLS | ||
| 905 | + if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 906 | + // apply the error strategy for hls. | ||
| 907 | + // @see https://github.com/ossrs/srs/issues/264 | ||
| 908 | + std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); | ||
| 909 | + if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) { | ||
| 910 | + srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); | ||
| 911 | + | ||
| 912 | + // unpublish, ignore ret. | ||
| 913 | + hls->on_unpublish(); | ||
| 914 | + | ||
| 915 | + // ignore. | ||
| 916 | + ret = ERROR_SUCCESS; | ||
| 917 | + } else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) { | ||
| 918 | + if (srs_hls_can_continue(ret, source->meta->ash(), msg)) { | ||
| 919 | + ret = ERROR_SUCCESS; | ||
| 920 | + } else { | ||
| 921 | + srs_warn("hls continue audio failed. ret=%d", ret); | ||
| 922 | + return ret; | ||
| 923 | + } | ||
| 924 | + } else { | ||
| 925 | + srs_warn("hls disconnect publisher for audio error. ret=%d", ret); | ||
| 926 | + return ret; | ||
| 1136 | } | 927 | } |
| 1137 | - mix_correct = v; | ||
| 1138 | } | 928 | } |
| 929 | +#endif | ||
| 1139 | 930 | ||
| 1140 | - // atc changed. | ||
| 1141 | - if (true) { | ||
| 1142 | - bool v = _srs_config->get_atc(vhost); | 931 | +#ifdef SRS_AUTO_DVR |
| 932 | + if ((ret = dvr->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 933 | + srs_warn("dvr process audio message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1143 | 934 | ||
| 1144 | - if (v != atc) { | ||
| 1145 | - srs_warn("vhost %s atc changed to %d, connected client may corrupt.", vhost.c_str(), v); | ||
| 1146 | - gop_cache->clear(); | ||
| 1147 | - } | ||
| 1148 | - atc = v; | 935 | + // unpublish, ignore ret. |
| 936 | + dvr->on_unpublish(); | ||
| 937 | + | ||
| 938 | + // ignore. | ||
| 939 | + ret = ERROR_SUCCESS; | ||
| 1149 | } | 940 | } |
| 941 | +#endif | ||
| 1150 | 942 | ||
| 1151 | - // gop cache changed. | ||
| 1152 | - if (true) { | ||
| 1153 | - bool v = _srs_config->get_gop_cache(vhost); | 943 | +#ifdef SRS_AUTO_HDS |
| 944 | + if ((ret = hds->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 945 | + srs_warn("hds process audio message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1154 | 946 | ||
| 1155 | - if (v != gop_cache->enabled()) { | ||
| 1156 | - string url = req->get_stream_url(); | ||
| 1157 | - srs_trace("vhost %s gop_cache changed to %d, source url=%s", vhost.c_str(), v, url.c_str()); | ||
| 1158 | - gop_cache->set(v); | ||
| 1159 | - } | 947 | + // unpublish, ignore ret. |
| 948 | + hds->on_unpublish(); | ||
| 949 | + // ignore. | ||
| 950 | + ret = ERROR_SUCCESS; | ||
| 1160 | } | 951 | } |
| 952 | +#endif | ||
| 1161 | 953 | ||
| 1162 | - // queue length | 954 | + // copy to all forwarders. |
| 1163 | if (true) { | 955 | if (true) { |
| 1164 | - double v = _srs_config->get_queue_length(req->vhost); | ||
| 1165 | - | ||
| 1166 | - if (true) { | ||
| 1167 | - std::vector<SrsConsumer*>::iterator it; | ||
| 1168 | - | ||
| 1169 | - for (it = consumers.begin(); it != consumers.end(); ++it) { | ||
| 1170 | - SrsConsumer* consumer = *it; | ||
| 1171 | - consumer->set_queue_size(v); | ||
| 1172 | - } | ||
| 1173 | - | ||
| 1174 | - srs_trace("consumers reload queue size success."); | ||
| 1175 | - } | ||
| 1176 | - | ||
| 1177 | - if (true) { | ||
| 1178 | - std::vector<SrsForwarder*>::iterator it; | ||
| 1179 | - | ||
| 1180 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1181 | - SrsForwarder* forwarder = *it; | ||
| 1182 | - forwarder->set_queue_size(v); | 956 | + std::vector<SrsForwarder*>::iterator it; |
| 957 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 958 | + SrsForwarder* forwarder = *it; | ||
| 959 | + if ((ret = forwarder->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 960 | + srs_error("forwarder process audio message failed. ret=%d", ret); | ||
| 961 | + return ret; | ||
| 1183 | } | 962 | } |
| 1184 | - | ||
| 1185 | - srs_trace("forwarders reload queue size success."); | ||
| 1186 | - } | ||
| 1187 | - | ||
| 1188 | - if (true) { | ||
| 1189 | - publish_edge->set_queue_size(v); | ||
| 1190 | - srs_trace("publish_edge reload queue size success."); | ||
| 1191 | } | 963 | } |
| 1192 | } | 964 | } |
| 1193 | 965 | ||
| 1194 | return ret; | 966 | return ret; |
| 1195 | } | 967 | } |
| 1196 | 968 | ||
| 1197 | -int SrsSource::on_reload_vhost_forward(string vhost) | 969 | +int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header) |
| 1198 | { | 970 | { |
| 1199 | int ret = ERROR_SUCCESS; | 971 | int ret = ERROR_SUCCESS; |
| 1200 | 972 | ||
| 1201 | - if (req->vhost != vhost) { | ||
| 1202 | - return ret; | 973 | + SrsSharedPtrMessage* msg = shared_video; |
| 974 | + | ||
| 975 | +#ifdef SRS_AUTO_HLS | ||
| 976 | + if ((ret = hls->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { | ||
| 977 | + // apply the error strategy for hls. | ||
| 978 | + // @see https://github.com/ossrs/srs/issues/264 | ||
| 979 | + std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); | ||
| 980 | + if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) { | ||
| 981 | + srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); | ||
| 982 | + | ||
| 983 | + // unpublish, ignore ret. | ||
| 984 | + hls->on_unpublish(); | ||
| 985 | + | ||
| 986 | + // ignore. | ||
| 987 | + ret = ERROR_SUCCESS; | ||
| 988 | + } else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) { | ||
| 989 | + if (srs_hls_can_continue(ret, source->meta->vsh(), msg)) { | ||
| 990 | + ret = ERROR_SUCCESS; | ||
| 991 | + } else { | ||
| 992 | + srs_warn("hls continue video failed. ret=%d", ret); | ||
| 993 | + return ret; | ||
| 994 | + } | ||
| 995 | + } else { | ||
| 996 | + srs_warn("hls disconnect publisher for video error. ret=%d", ret); | ||
| 997 | + return ret; | ||
| 998 | + } | ||
| 1203 | } | 999 | } |
| 1000 | +#endif | ||
| 1204 | 1001 | ||
| 1205 | - // TODO: FIXME: maybe should ignore when publish already stopped? | ||
| 1206 | - | ||
| 1207 | - // forwarders | ||
| 1208 | - destroy_forwarders(); | ||
| 1209 | - if ((ret = create_forwarders()) != ERROR_SUCCESS) { | ||
| 1210 | - srs_error("create forwarders failed. ret=%d", ret); | ||
| 1211 | - return ret; | 1002 | +#ifdef SRS_AUTO_DVR |
| 1003 | + if ((ret = dvr->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1004 | + srs_warn("dvr process video message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1005 | + | ||
| 1006 | + // unpublish, ignore ret. | ||
| 1007 | + dvr->on_unpublish(); | ||
| 1008 | + | ||
| 1009 | + // ignore. | ||
| 1010 | + ret = ERROR_SUCCESS; | ||
| 1011 | + } | ||
| 1012 | +#endif | ||
| 1013 | + | ||
| 1014 | +#ifdef SRS_AUTO_HDS | ||
| 1015 | + if ((ret = hds->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1016 | + srs_warn("hds process video message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1017 | + | ||
| 1018 | + // unpublish, ignore ret. | ||
| 1019 | + hds->on_unpublish(); | ||
| 1020 | + // ignore. | ||
| 1021 | + ret = ERROR_SUCCESS; | ||
| 1022 | + } | ||
| 1023 | +#endif | ||
| 1024 | + | ||
| 1025 | + // copy to all forwarders. | ||
| 1026 | + if (!forwarders.empty()) { | ||
| 1027 | + std::vector<SrsForwarder*>::iterator it; | ||
| 1028 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1029 | + SrsForwarder* forwarder = *it; | ||
| 1030 | + if ((ret = forwarder->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1031 | + srs_error("forwarder process video message failed. ret=%d", ret); | ||
| 1032 | + return ret; | ||
| 1033 | + } | ||
| 1034 | + } | ||
| 1212 | } | 1035 | } |
| 1213 | - | ||
| 1214 | - srs_trace("vhost %s forwarders reload success", vhost.c_str()); | ||
| 1215 | 1036 | ||
| 1216 | return ret; | 1037 | return ret; |
| 1217 | } | 1038 | } |
| 1218 | 1039 | ||
| 1219 | -int SrsSource::on_reload_vhost_hls(string vhost) | 1040 | +int SrsOriginHub::on_publish() |
| 1220 | { | 1041 | { |
| 1221 | int ret = ERROR_SUCCESS; | 1042 | int ret = ERROR_SUCCESS; |
| 1222 | 1043 | ||
| 1223 | - if (req->vhost != vhost) { | 1044 | + // create forwarders |
| 1045 | + if ((ret = create_forwarders()) != ERROR_SUCCESS) { | ||
| 1046 | + srs_error("create forwarders failed. ret=%d", ret); | ||
| 1047 | + return ret; | ||
| 1048 | + } | ||
| 1049 | + | ||
| 1050 | + // TODO: FIXME: use initialize to set req. | ||
| 1051 | +#ifdef SRS_AUTO_TRANSCODE | ||
| 1052 | + if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1053 | + srs_error("start encoder failed. ret=%d", ret); | ||
| 1054 | + return ret; | ||
| 1055 | + } | ||
| 1056 | +#endif | ||
| 1057 | + | ||
| 1058 | +#ifdef SRS_AUTO_HLS | ||
| 1059 | + if ((ret = hls->on_publish(false)) != ERROR_SUCCESS) { | ||
| 1060 | + srs_error("start hls failed. ret=%d", ret); | ||
| 1061 | + return ret; | ||
| 1062 | + } | ||
| 1063 | +#endif | ||
| 1064 | + | ||
| 1065 | +#ifdef SRS_AUTO_DVR | ||
| 1066 | + if ((ret = dvr->on_publish(false)) != ERROR_SUCCESS) { | ||
| 1067 | + srs_error("start dvr failed. ret=%d", ret); | ||
| 1068 | + return ret; | ||
| 1069 | + } | ||
| 1070 | +#endif | ||
| 1071 | + | ||
| 1072 | + // TODO: FIXME: use initialize to set req. | ||
| 1073 | +#ifdef SRS_AUTO_HDS | ||
| 1074 | + if ((ret = hds->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1075 | + srs_error("start hds failed. ret=%d", ret); | ||
| 1076 | + return ret; | ||
| 1077 | + } | ||
| 1078 | +#endif | ||
| 1079 | + | ||
| 1080 | + // TODO: FIXME: use initialize to set req. | ||
| 1081 | + if ((ret = ng_exec->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1082 | + srs_error("start exec failed. ret=%d", ret); | ||
| 1083 | + return ret; | ||
| 1084 | + } | ||
| 1085 | + | ||
| 1086 | + return ret; | ||
| 1087 | +} | ||
| 1088 | + | ||
| 1089 | +void SrsOriginHub::on_unpublish() | ||
| 1090 | +{ | ||
| 1091 | + // destroy all forwarders | ||
| 1092 | + destroy_forwarders(); | ||
| 1093 | + | ||
| 1094 | +#ifdef SRS_AUTO_TRANSCODE | ||
| 1095 | + encoder->on_unpublish(); | ||
| 1096 | +#endif | ||
| 1097 | + | ||
| 1098 | +#ifdef SRS_AUTO_HLS | ||
| 1099 | + hls->on_unpublish(); | ||
| 1100 | +#endif | ||
| 1101 | + | ||
| 1102 | +#ifdef SRS_AUTO_DVR | ||
| 1103 | + dvr->on_unpublish(); | ||
| 1104 | +#endif | ||
| 1105 | + | ||
| 1106 | +#ifdef SRS_AUTO_HDS | ||
| 1107 | + hds->on_unpublish(); | ||
| 1108 | +#endif | ||
| 1109 | + | ||
| 1110 | + ng_exec->on_unpublish(); | ||
| 1111 | +} | ||
| 1112 | + | ||
| 1113 | +int SrsOriginHub::on_forwarder_start(SrsForwarder* forwarder) | ||
| 1114 | +{ | ||
| 1115 | + int ret = ERROR_SUCCESS; | ||
| 1116 | + | ||
| 1117 | + SrsSharedPtrMessage* cache_metadata = source->meta->data(); | ||
| 1118 | + SrsSharedPtrMessage* cache_sh_video = source->meta->vsh(); | ||
| 1119 | + SrsSharedPtrMessage* cache_sh_audio = source->meta->ash(); | ||
| 1120 | + | ||
| 1121 | + // feed the forwarder the metadata/sequence header, | ||
| 1122 | + // when reload to enable the forwarder. | ||
| 1123 | + if (cache_metadata && (ret = forwarder->on_meta_data(cache_metadata)) != ERROR_SUCCESS) { | ||
| 1124 | + srs_error("forwarder process onMetaData message failed. ret=%d", ret); | ||
| 1125 | + return ret; | ||
| 1126 | + } | ||
| 1127 | + if (cache_sh_video && (ret = forwarder->on_video(cache_sh_video)) != ERROR_SUCCESS) { | ||
| 1128 | + srs_error("forwarder process video sequence header message failed. ret=%d", ret); | ||
| 1129 | + return ret; | ||
| 1130 | + } | ||
| 1131 | + if (cache_sh_audio && (ret = forwarder->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1132 | + srs_error("forwarder process audio sequence header message failed. ret=%d", ret); | ||
| 1133 | + return ret; | ||
| 1134 | + } | ||
| 1135 | + | ||
| 1136 | + return ret; | ||
| 1137 | +} | ||
| 1138 | + | ||
| 1139 | +int SrsOriginHub::on_hls_start() | ||
| 1140 | +{ | ||
| 1141 | + int ret = ERROR_SUCCESS; | ||
| 1142 | + | ||
| 1143 | + SrsSharedPtrMessage* cache_sh_video = source->meta->vsh(); | ||
| 1144 | + SrsSharedPtrMessage* cache_sh_audio = source->meta->ash(); | ||
| 1145 | + | ||
| 1146 | +#ifdef SRS_AUTO_HLS | ||
| 1147 | + // feed the hls the metadata/sequence header, | ||
| 1148 | + // when reload to start hls, hls will never get the sequence header in stream, | ||
| 1149 | + // use the SrsSource.on_hls_start to push the sequence header to HLS. | ||
| 1150 | + // TODO: maybe need to decode the metadata? | ||
| 1151 | + if (cache_sh_video && (ret = hls->on_video(cache_sh_video, true)) != ERROR_SUCCESS) { | ||
| 1152 | + srs_error("hls process video sequence header message failed. ret=%d", ret); | ||
| 1153 | + return ret; | ||
| 1154 | + } | ||
| 1155 | + if (cache_sh_audio && (ret = hls->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1156 | + srs_error("hls process audio sequence header message failed. ret=%d", ret); | ||
| 1157 | + return ret; | ||
| 1158 | + } | ||
| 1159 | +#endif | ||
| 1160 | + | ||
| 1161 | + return ret; | ||
| 1162 | +} | ||
| 1163 | + | ||
| 1164 | +int SrsOriginHub::on_dvr_request_sh() | ||
| 1165 | +{ | ||
| 1166 | + int ret = ERROR_SUCCESS; | ||
| 1167 | + | ||
| 1168 | + SrsSharedPtrMessage* cache_metadata = source->meta->data(); | ||
| 1169 | + SrsSharedPtrMessage* cache_sh_video = source->meta->vsh(); | ||
| 1170 | + SrsSharedPtrMessage* cache_sh_audio = source->meta->ash(); | ||
| 1171 | + | ||
| 1172 | +#ifdef SRS_AUTO_DVR | ||
| 1173 | + // feed the dvr the metadata/sequence header, | ||
| 1174 | + // when reload to start dvr, dvr will never get the sequence header in stream, | ||
| 1175 | + // use the SrsSource.on_dvr_request_sh to push the sequence header to DVR. | ||
| 1176 | + if (cache_metadata) { | ||
| 1177 | + char* payload = cache_metadata->payload; | ||
| 1178 | + int size = cache_metadata->size; | ||
| 1179 | + | ||
| 1180 | + SrsBuffer stream; | ||
| 1181 | + if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { | ||
| 1182 | + srs_error("dvr decode metadata stream failed. ret=%d", ret); | ||
| 1183 | + return ret; | ||
| 1184 | + } | ||
| 1185 | + | ||
| 1186 | + SrsOnMetaDataPacket pkt; | ||
| 1187 | + if ((ret = pkt.decode(&stream)) != ERROR_SUCCESS) { | ||
| 1188 | + srs_error("dvr decode metadata packet failed."); | ||
| 1189 | + return ret; | ||
| 1190 | + } | ||
| 1191 | + | ||
| 1192 | + if ((ret = dvr->on_meta_data(&pkt)) != ERROR_SUCCESS) { | ||
| 1193 | + srs_error("dvr process onMetaData message failed. ret=%d", ret); | ||
| 1194 | + return ret; | ||
| 1195 | + } | ||
| 1196 | + } | ||
| 1197 | + | ||
| 1198 | + if (cache_sh_video && (ret = dvr->on_video(cache_sh_video)) != ERROR_SUCCESS) { | ||
| 1199 | + srs_error("dvr process video sequence header message failed. ret=%d", ret); | ||
| 1200 | + return ret; | ||
| 1201 | + } | ||
| 1202 | + if (cache_sh_audio && (ret = dvr->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1203 | + srs_error("dvr process audio sequence header message failed. ret=%d", ret); | ||
| 1204 | + return ret; | ||
| 1205 | + } | ||
| 1206 | +#endif | ||
| 1207 | + | ||
| 1208 | + return ret; | ||
| 1209 | +} | ||
| 1210 | + | ||
| 1211 | +int SrsOriginHub::on_reload_vhost_forward(string vhost) | ||
| 1212 | +{ | ||
| 1213 | + int ret = ERROR_SUCCESS; | ||
| 1214 | + | ||
| 1215 | + if (req->vhost != vhost) { | ||
| 1216 | + return ret; | ||
| 1217 | + } | ||
| 1218 | + | ||
| 1219 | + // TODO: FIXME: maybe should ignore when publish already stopped? | ||
| 1220 | + | ||
| 1221 | + // forwarders | ||
| 1222 | + destroy_forwarders(); | ||
| 1223 | + if ((ret = create_forwarders()) != ERROR_SUCCESS) { | ||
| 1224 | + srs_error("create forwarders failed. ret=%d", ret); | ||
| 1225 | + return ret; | ||
| 1226 | + } | ||
| 1227 | + | ||
| 1228 | + srs_trace("vhost %s forwarders reload success", vhost.c_str()); | ||
| 1229 | + | ||
| 1230 | + return ret; | ||
| 1231 | +} | ||
| 1232 | + | ||
| 1233 | +int SrsOriginHub::on_reload_vhost_hls(string vhost) | ||
| 1234 | +{ | ||
| 1235 | + int ret = ERROR_SUCCESS; | ||
| 1236 | + | ||
| 1237 | + if (req->vhost != vhost) { | ||
| 1224 | return ret; | 1238 | return ret; |
| 1225 | } | 1239 | } |
| 1226 | 1240 | ||
| @@ -1238,16 +1252,16 @@ int SrsSource::on_reload_vhost_hls(string vhost) | @@ -1238,16 +1252,16 @@ int SrsSource::on_reload_vhost_hls(string vhost) | ||
| 1238 | return ret; | 1252 | return ret; |
| 1239 | } | 1253 | } |
| 1240 | 1254 | ||
| 1241 | -int SrsSource::on_reload_vhost_hds(string vhost) | 1255 | +int SrsOriginHub::on_reload_vhost_hds(string vhost) |
| 1242 | { | 1256 | { |
| 1243 | int ret = ERROR_SUCCESS; | 1257 | int ret = ERROR_SUCCESS; |
| 1244 | - | 1258 | + |
| 1245 | if (req->vhost != vhost) { | 1259 | if (req->vhost != vhost) { |
| 1246 | return ret; | 1260 | return ret; |
| 1247 | } | 1261 | } |
| 1248 | 1262 | ||
| 1249 | // TODO: FIXME: maybe should ignore when publish already stopped? | 1263 | // TODO: FIXME: maybe should ignore when publish already stopped? |
| 1250 | - | 1264 | + |
| 1251 | #ifdef SRS_AUTO_HDS | 1265 | #ifdef SRS_AUTO_HDS |
| 1252 | hds->on_unpublish(); | 1266 | hds->on_unpublish(); |
| 1253 | if ((ret = hds->on_publish(req)) != ERROR_SUCCESS) { | 1267 | if ((ret = hds->on_publish(req)) != ERROR_SUCCESS) { |
| @@ -1256,11 +1270,11 @@ int SrsSource::on_reload_vhost_hds(string vhost) | @@ -1256,11 +1270,11 @@ int SrsSource::on_reload_vhost_hds(string vhost) | ||
| 1256 | } | 1270 | } |
| 1257 | srs_trace("vhost %s hds reload success", vhost.c_str()); | 1271 | srs_trace("vhost %s hds reload success", vhost.c_str()); |
| 1258 | #endif | 1272 | #endif |
| 1259 | - | 1273 | + |
| 1260 | return ret; | 1274 | return ret; |
| 1261 | } | 1275 | } |
| 1262 | 1276 | ||
| 1263 | -int SrsSource::on_reload_vhost_dvr(string vhost) | 1277 | +int SrsOriginHub::on_reload_vhost_dvr(string vhost) |
| 1264 | { | 1278 | { |
| 1265 | int ret = ERROR_SUCCESS; | 1279 | int ret = ERROR_SUCCESS; |
| 1266 | 1280 | ||
| @@ -1273,12 +1287,12 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | @@ -1273,12 +1287,12 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | ||
| 1273 | #ifdef SRS_AUTO_DVR | 1287 | #ifdef SRS_AUTO_DVR |
| 1274 | // cleanup dvr | 1288 | // cleanup dvr |
| 1275 | dvr->on_unpublish(); | 1289 | dvr->on_unpublish(); |
| 1276 | - | 1290 | + |
| 1277 | // reinitialize the dvr, update plan. | 1291 | // reinitialize the dvr, update plan. |
| 1278 | if ((ret = dvr->initialize(this, req)) != ERROR_SUCCESS) { | 1292 | if ((ret = dvr->initialize(this, req)) != ERROR_SUCCESS) { |
| 1279 | return ret; | 1293 | return ret; |
| 1280 | } | 1294 | } |
| 1281 | - | 1295 | + |
| 1282 | // start to publish by new plan. | 1296 | // start to publish by new plan. |
| 1283 | if ((ret = dvr->on_publish(true)) != ERROR_SUCCESS) { | 1297 | if ((ret = dvr->on_publish(true)) != ERROR_SUCCESS) { |
| 1284 | srs_error("dvr publish failed. ret=%d", ret); | 1298 | srs_error("dvr publish failed. ret=%d", ret); |
| @@ -1291,131 +1305,624 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | @@ -1291,131 +1305,624 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | ||
| 1291 | return ret; | 1305 | return ret; |
| 1292 | } | 1306 | } |
| 1293 | 1307 | ||
| 1294 | -int SrsSource::on_reload_vhost_transcode(string vhost) | 1308 | +int SrsOriginHub::on_reload_vhost_transcode(string vhost) |
| 1309 | +{ | ||
| 1310 | + int ret = ERROR_SUCCESS; | ||
| 1311 | + | ||
| 1312 | + if (req->vhost != vhost) { | ||
| 1313 | + return ret; | ||
| 1314 | + } | ||
| 1315 | + | ||
| 1316 | + // TODO: FIXME: maybe should ignore when publish already stopped? | ||
| 1317 | + | ||
| 1318 | +#ifdef SRS_AUTO_TRANSCODE | ||
| 1319 | + encoder->on_unpublish(); | ||
| 1320 | + if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1321 | + srs_error("start encoder failed. ret=%d", ret); | ||
| 1322 | + return ret; | ||
| 1323 | + } | ||
| 1324 | + srs_trace("vhost %s transcode reload success", vhost.c_str()); | ||
| 1325 | +#endif | ||
| 1326 | + | ||
| 1327 | + return ret; | ||
| 1328 | +} | ||
| 1329 | + | ||
| 1330 | +int SrsOriginHub::on_reload_vhost_exec(string vhost) | ||
| 1331 | +{ | ||
| 1332 | + int ret = ERROR_SUCCESS; | ||
| 1333 | + | ||
| 1334 | + if (req->vhost != vhost) { | ||
| 1335 | + return ret; | ||
| 1336 | + } | ||
| 1337 | + | ||
| 1338 | + // TODO: FIXME: maybe should ignore when publish already stopped? | ||
| 1339 | + | ||
| 1340 | + ng_exec->on_unpublish(); | ||
| 1341 | + if ((ret = ng_exec->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1342 | + srs_error("start exec failed. ret=%d", ret); | ||
| 1343 | + return ret; | ||
| 1344 | + } | ||
| 1345 | + srs_trace("vhost %s exec reload success", vhost.c_str()); | ||
| 1346 | + | ||
| 1347 | + return ret; | ||
| 1348 | +} | ||
| 1349 | + | ||
| 1350 | +int SrsOriginHub::create_forwarders() | ||
| 1351 | +{ | ||
| 1352 | + int ret = ERROR_SUCCESS; | ||
| 1353 | + | ||
| 1354 | + if (!_srs_config->get_forward_enabled(req->vhost)) { | ||
| 1355 | + return ret; | ||
| 1356 | + } | ||
| 1357 | + | ||
| 1358 | + SrsConfDirective* conf = _srs_config->get_forwards(req->vhost); | ||
| 1359 | + for (int i = 0; conf && i < (int)conf->args.size(); i++) { | ||
| 1360 | + std::string forward_server = conf->args.at(i); | ||
| 1361 | + | ||
| 1362 | + SrsForwarder* forwarder = new SrsForwarder(this); | ||
| 1363 | + forwarders.push_back(forwarder); | ||
| 1364 | + | ||
| 1365 | + // initialize the forwarder with request. | ||
| 1366 | + if ((ret = forwarder->initialize(req, forward_server)) != ERROR_SUCCESS) { | ||
| 1367 | + return ret; | ||
| 1368 | + } | ||
| 1369 | + | ||
| 1370 | + // TODO: FIXME: support queue size. | ||
| 1371 | + //double queue_size = _srs_config->get_queue_length(req->vhost); | ||
| 1372 | + //forwarder->set_queue_size(queue_size); | ||
| 1373 | + | ||
| 1374 | + if ((ret = forwarder->on_publish()) != ERROR_SUCCESS) { | ||
| 1375 | + srs_error("start forwarder failed. " | ||
| 1376 | + "vhost=%s, app=%s, stream=%s, forward-to=%s", | ||
| 1377 | + req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), | ||
| 1378 | + forward_server.c_str()); | ||
| 1379 | + return ret; | ||
| 1380 | + } | ||
| 1381 | + } | ||
| 1382 | + | ||
| 1383 | + return ret; | ||
| 1384 | +} | ||
| 1385 | + | ||
| 1386 | +void SrsOriginHub::destroy_forwarders() | ||
| 1387 | +{ | ||
| 1388 | + std::vector<SrsForwarder*>::iterator it; | ||
| 1389 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1390 | + SrsForwarder* forwarder = *it; | ||
| 1391 | + forwarder->on_unpublish(); | ||
| 1392 | + srs_freep(forwarder); | ||
| 1393 | + } | ||
| 1394 | + forwarders.clear(); | ||
| 1395 | +} | ||
| 1396 | + | ||
| 1397 | +SrsMetaCache::SrsMetaCache() | ||
| 1398 | +{ | ||
| 1399 | + cache_metadata = cache_sh_video = cache_sh_audio = NULL; | ||
| 1400 | +} | ||
| 1401 | + | ||
| 1402 | +SrsMetaCache::~SrsMetaCache() | ||
| 1403 | +{ | ||
| 1404 | + dispose(); | ||
| 1405 | +} | ||
| 1406 | + | ||
| 1407 | +void SrsMetaCache::dispose() | ||
| 1408 | +{ | ||
| 1409 | + srs_freep(cache_metadata); | ||
| 1410 | + srs_freep(cache_sh_video); | ||
| 1411 | + srs_freep(cache_sh_audio); | ||
| 1412 | +} | ||
| 1413 | + | ||
| 1414 | +SrsSharedPtrMessage* SrsMetaCache::data() | ||
| 1415 | +{ | ||
| 1416 | + return cache_metadata; | ||
| 1417 | +} | ||
| 1418 | + | ||
| 1419 | +SrsSharedPtrMessage* SrsMetaCache::vsh() | ||
| 1420 | +{ | ||
| 1421 | + return cache_sh_video; | ||
| 1422 | +} | ||
| 1423 | + | ||
| 1424 | +SrsSharedPtrMessage* SrsMetaCache::ash() | ||
| 1425 | +{ | ||
| 1426 | + return cache_sh_audio; | ||
| 1427 | +} | ||
| 1428 | + | ||
| 1429 | +int SrsMetaCache::dumps(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds) | ||
| 1430 | +{ | ||
| 1431 | + int ret = ERROR_SUCCESS; | ||
| 1432 | + | ||
| 1433 | + // copy metadata. | ||
| 1434 | + if (dm && cache_metadata && (ret = consumer->enqueue(cache_metadata, atc, ag)) != ERROR_SUCCESS) { | ||
| 1435 | + srs_error("dispatch metadata failed. ret=%d", ret); | ||
| 1436 | + return ret; | ||
| 1437 | + } | ||
| 1438 | + srs_info("dispatch metadata success"); | ||
| 1439 | + | ||
| 1440 | + // copy sequence header | ||
| 1441 | + // copy audio sequence first, for hls to fast parse the "right" audio codec. | ||
| 1442 | + // @see https://github.com/ossrs/srs/issues/301 | ||
| 1443 | + if (ds && cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, ag)) != ERROR_SUCCESS) { | ||
| 1444 | + srs_error("dispatch audio sequence header failed. ret=%d", ret); | ||
| 1445 | + return ret; | ||
| 1446 | + } | ||
| 1447 | + srs_info("dispatch audio sequence header success"); | ||
| 1448 | + | ||
| 1449 | + if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, ag)) != ERROR_SUCCESS) { | ||
| 1450 | + srs_error("dispatch video sequence header failed. ret=%d", ret); | ||
| 1451 | + return ret; | ||
| 1452 | + } | ||
| 1453 | + srs_info("dispatch video sequence header success"); | ||
| 1454 | + | ||
| 1455 | + return ret; | ||
| 1456 | +} | ||
| 1457 | + | ||
| 1458 | +int SrsMetaCache::update_data(SrsMessageHeader* header, SrsOnMetaDataPacket* metadata, bool& updated) | ||
| 1459 | +{ | ||
| 1460 | + updated = false; | ||
| 1461 | + | ||
| 1462 | + int ret = ERROR_SUCCESS; | ||
| 1463 | + | ||
| 1464 | + SrsAmf0Any* prop = NULL; | ||
| 1465 | + | ||
| 1466 | + // when exists the duration, remove it to make ExoPlayer happy. | ||
| 1467 | + if (metadata->metadata->get_property("duration") != NULL) { | ||
| 1468 | + metadata->metadata->remove("duration"); | ||
| 1469 | + } | ||
| 1470 | + | ||
| 1471 | + // generate metadata info to print | ||
| 1472 | + std::stringstream ss; | ||
| 1473 | + if ((prop = metadata->metadata->ensure_property_number("width")) != NULL) { | ||
| 1474 | + ss << ", width=" << (int)prop->to_number(); | ||
| 1475 | + } | ||
| 1476 | + if ((prop = metadata->metadata->ensure_property_number("height")) != NULL) { | ||
| 1477 | + ss << ", height=" << (int)prop->to_number(); | ||
| 1478 | + } | ||
| 1479 | + if ((prop = metadata->metadata->ensure_property_number("videocodecid")) != NULL) { | ||
| 1480 | + ss << ", vcodec=" << (int)prop->to_number(); | ||
| 1481 | + } | ||
| 1482 | + if ((prop = metadata->metadata->ensure_property_number("audiocodecid")) != NULL) { | ||
| 1483 | + ss << ", acodec=" << (int)prop->to_number(); | ||
| 1484 | + } | ||
| 1485 | + srs_trace("got metadata%s", ss.str().c_str()); | ||
| 1486 | + | ||
| 1487 | + // add server info to metadata | ||
| 1488 | + metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_SERVER)); | ||
| 1489 | + metadata->metadata->set("srs_primary", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY)); | ||
| 1490 | + metadata->metadata->set("srs_authors", SrsAmf0Any::str(RTMP_SIG_SRS_AUTHROS)); | ||
| 1491 | + | ||
| 1492 | + // version, for example, 1.0.0 | ||
| 1493 | + // add version to metadata, please donot remove it, for debug. | ||
| 1494 | + metadata->metadata->set("server_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); | ||
| 1495 | + | ||
| 1496 | + // encode the metadata to payload | ||
| 1497 | + int size = 0; | ||
| 1498 | + char* payload = NULL; | ||
| 1499 | + if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { | ||
| 1500 | + srs_error("encode metadata error. ret=%d", ret); | ||
| 1501 | + srs_freep(payload); | ||
| 1502 | + return ret; | ||
| 1503 | + } | ||
| 1504 | + srs_verbose("encode metadata success."); | ||
| 1505 | + | ||
| 1506 | + if (size <= 0) { | ||
| 1507 | + srs_warn("ignore the invalid metadata. size=%d", size); | ||
| 1508 | + return ret; | ||
| 1509 | + } | ||
| 1510 | + | ||
| 1511 | + // create a shared ptr message. | ||
| 1512 | + srs_freep(cache_metadata); | ||
| 1513 | + cache_metadata = new SrsSharedPtrMessage(); | ||
| 1514 | + updated = true; | ||
| 1515 | + | ||
| 1516 | + // dump message to shared ptr message. | ||
| 1517 | + // the payload/size managed by cache_metadata, user should not free it. | ||
| 1518 | + if ((ret = cache_metadata->create(header, payload, size)) != ERROR_SUCCESS) { | ||
| 1519 | + srs_error("initialize the cache metadata failed. ret=%d", ret); | ||
| 1520 | + return ret; | ||
| 1521 | + } | ||
| 1522 | + srs_verbose("initialize shared ptr metadata success."); | ||
| 1523 | + | ||
| 1524 | + return ret; | ||
| 1525 | +} | ||
| 1526 | + | ||
| 1527 | +void SrsMetaCache::update_ash(SrsSharedPtrMessage* msg) | ||
| 1528 | +{ | ||
| 1529 | + srs_freep(cache_sh_audio); | ||
| 1530 | + cache_sh_audio = msg->copy(); | ||
| 1531 | +} | ||
| 1532 | + | ||
| 1533 | +void SrsMetaCache::update_vsh(SrsSharedPtrMessage* msg) | ||
| 1534 | +{ | ||
| 1535 | + srs_freep(cache_sh_video); | ||
| 1536 | + cache_sh_video = msg->copy(); | ||
| 1537 | +} | ||
| 1538 | + | ||
| 1539 | +std::map<std::string, SrsSource*> SrsSource::pool; | ||
| 1540 | + | ||
| 1541 | +int SrsSource::fetch_or_create(SrsRequest* r, ISrsSourceHandler* h, SrsSource** pps) | ||
| 1542 | +{ | ||
| 1543 | + int ret = ERROR_SUCCESS; | ||
| 1544 | + | ||
| 1545 | + SrsSource* source = NULL; | ||
| 1546 | + if ((source = fetch(r)) != NULL) { | ||
| 1547 | + *pps = source; | ||
| 1548 | + return ret; | ||
| 1549 | + } | ||
| 1550 | + | ||
| 1551 | + string stream_url = r->get_stream_url(); | ||
| 1552 | + string vhost = r->vhost; | ||
| 1553 | + | ||
| 1554 | + // should always not exists for create a source. | ||
| 1555 | + srs_assert (pool.find(stream_url) == pool.end()); | ||
| 1556 | + | ||
| 1557 | + source = new SrsSource(); | ||
| 1558 | + if ((ret = source->initialize(r, h)) != ERROR_SUCCESS) { | ||
| 1559 | + srs_freep(source); | ||
| 1560 | + return ret; | ||
| 1561 | + } | ||
| 1562 | + | ||
| 1563 | + pool[stream_url] = source; | ||
| 1564 | + srs_info("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); | ||
| 1565 | + | ||
| 1566 | + *pps = source; | ||
| 1567 | + | ||
| 1568 | + return ret; | ||
| 1569 | +} | ||
| 1570 | + | ||
| 1571 | +SrsSource* SrsSource::fetch(SrsRequest* r) | ||
| 1572 | +{ | ||
| 1573 | + SrsSource* source = NULL; | ||
| 1574 | + | ||
| 1575 | + string stream_url = r->get_stream_url(); | ||
| 1576 | + if (pool.find(stream_url) == pool.end()) { | ||
| 1577 | + return NULL; | ||
| 1578 | + } | ||
| 1579 | + | ||
| 1580 | + source = pool[stream_url]; | ||
| 1581 | + | ||
| 1582 | + // we always update the request of resource, | ||
| 1583 | + // for origin auth is on, the token in request maybe invalid, | ||
| 1584 | + // and we only need to update the token of request, it's simple. | ||
| 1585 | + source->req->update_auth(r); | ||
| 1586 | + | ||
| 1587 | + return source; | ||
| 1588 | +} | ||
| 1589 | + | ||
| 1590 | +void SrsSource::dispose_all() | ||
| 1591 | +{ | ||
| 1592 | + std::map<std::string, SrsSource*>::iterator it; | ||
| 1593 | + for (it = pool.begin(); it != pool.end(); ++it) { | ||
| 1594 | + SrsSource* source = it->second; | ||
| 1595 | + source->dispose(); | ||
| 1596 | + } | ||
| 1597 | + return; | ||
| 1598 | +} | ||
| 1599 | + | ||
| 1600 | +int SrsSource::cycle_all() | ||
| 1601 | +{ | ||
| 1602 | + int ret = ERROR_SUCCESS; | ||
| 1603 | + | ||
| 1604 | + int cid = _srs_context->get_id(); | ||
| 1605 | + ret = do_cycle_all(); | ||
| 1606 | + _srs_context->set_id(cid); | ||
| 1607 | + | ||
| 1608 | + return ret; | ||
| 1609 | +} | ||
| 1610 | + | ||
| 1611 | +int SrsSource::do_cycle_all() | ||
| 1612 | +{ | ||
| 1613 | + int ret = ERROR_SUCCESS; | ||
| 1614 | + | ||
| 1615 | + std::map<std::string, SrsSource*>::iterator it; | ||
| 1616 | + for (it = pool.begin(); it != pool.end();) { | ||
| 1617 | + SrsSource* source = it->second; | ||
| 1618 | + | ||
| 1619 | + // Do cycle source to cleanup components, such as hls dispose. | ||
| 1620 | + if ((ret = source->cycle()) != ERROR_SUCCESS) { | ||
| 1621 | + return ret; | ||
| 1622 | + } | ||
| 1623 | + | ||
| 1624 | + // TODO: FIXME: support source cleanup. | ||
| 1625 | + // @see https://github.com/ossrs/srs/issues/713 | ||
| 1626 | + // @see https://github.com/ossrs/srs/issues/714 | ||
| 1627 | +#if 0 | ||
| 1628 | + // When source expired, remove it. | ||
| 1629 | + if (source->expired()) { | ||
| 1630 | + int cid = source->source_id(); | ||
| 1631 | + if (cid == -1 && source->pre_source_id() > 0) { | ||
| 1632 | + cid = source->pre_source_id(); | ||
| 1633 | + } | ||
| 1634 | + if (cid > 0) { | ||
| 1635 | + _srs_context->set_id(cid); | ||
| 1636 | + } | ||
| 1637 | + srs_trace("cleanup die source, total=%d", (int)pool.size()); | ||
| 1638 | + | ||
| 1639 | + srs_freep(source); | ||
| 1640 | + pool.erase(it++); | ||
| 1641 | + } else { | ||
| 1642 | + ++it; | ||
| 1643 | + } | ||
| 1644 | +#else | ||
| 1645 | + ++it; | ||
| 1646 | +#endif | ||
| 1647 | + } | ||
| 1648 | + | ||
| 1649 | + return ret; | ||
| 1650 | +} | ||
| 1651 | + | ||
| 1652 | +void SrsSource::destroy() | ||
| 1653 | +{ | ||
| 1654 | + std::map<std::string, SrsSource*>::iterator it; | ||
| 1655 | + for (it = pool.begin(); it != pool.end(); ++it) { | ||
| 1656 | + SrsSource* source = it->second; | ||
| 1657 | + srs_freep(source); | ||
| 1658 | + } | ||
| 1659 | + pool.clear(); | ||
| 1660 | +} | ||
| 1661 | + | ||
| 1662 | +SrsMixQueue::SrsMixQueue() | ||
| 1663 | +{ | ||
| 1664 | + nb_videos = 0; | ||
| 1665 | + nb_audios = 0; | ||
| 1666 | +} | ||
| 1667 | + | ||
| 1668 | +SrsMixQueue::~SrsMixQueue() | ||
| 1669 | +{ | ||
| 1670 | + clear(); | ||
| 1671 | +} | ||
| 1672 | + | ||
| 1673 | +void SrsMixQueue::clear() | ||
| 1674 | +{ | ||
| 1675 | + std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it; | ||
| 1676 | + for (it = msgs.begin(); it != msgs.end(); ++it) { | ||
| 1677 | + SrsSharedPtrMessage* msg = it->second; | ||
| 1678 | + srs_freep(msg); | ||
| 1679 | + } | ||
| 1680 | + msgs.clear(); | ||
| 1681 | + | ||
| 1682 | + nb_videos = 0; | ||
| 1683 | + nb_audios = 0; | ||
| 1684 | +} | ||
| 1685 | + | ||
| 1686 | +void SrsMixQueue::push(SrsSharedPtrMessage* msg) | ||
| 1687 | +{ | ||
| 1688 | + msgs.insert(std::make_pair(msg->timestamp, msg)); | ||
| 1689 | + | ||
| 1690 | + if (msg->is_video()) { | ||
| 1691 | + nb_videos++; | ||
| 1692 | + } else { | ||
| 1693 | + nb_audios++; | ||
| 1694 | + } | ||
| 1695 | +} | ||
| 1696 | + | ||
| 1697 | +SrsSharedPtrMessage* SrsMixQueue::pop() | ||
| 1698 | +{ | ||
| 1699 | + bool mix_ok = false; | ||
| 1700 | + | ||
| 1701 | + // pure video | ||
| 1702 | + if (nb_videos >= SRS_MIX_CORRECT_PURE_AV && nb_audios == 0) { | ||
| 1703 | + mix_ok = true; | ||
| 1704 | + } | ||
| 1705 | + | ||
| 1706 | + // pure audio | ||
| 1707 | + if (nb_audios >= SRS_MIX_CORRECT_PURE_AV && nb_videos == 0) { | ||
| 1708 | + mix_ok = true; | ||
| 1709 | + } | ||
| 1710 | + | ||
| 1711 | + // got 1 video and 1 audio, mix ok. | ||
| 1712 | + if (nb_videos >= 1 && nb_audios >= 1) { | ||
| 1713 | + mix_ok = true; | ||
| 1714 | + } | ||
| 1715 | + | ||
| 1716 | + if (!mix_ok) { | ||
| 1717 | + return NULL; | ||
| 1718 | + } | ||
| 1719 | + | ||
| 1720 | + // pop the first msg. | ||
| 1721 | + std::multimap<int64_t, SrsSharedPtrMessage*>::iterator it = msgs.begin(); | ||
| 1722 | + SrsSharedPtrMessage* msg = it->second; | ||
| 1723 | + msgs.erase(it); | ||
| 1724 | + | ||
| 1725 | + if (msg->is_video()) { | ||
| 1726 | + nb_videos--; | ||
| 1727 | + } else { | ||
| 1728 | + nb_audios--; | ||
| 1729 | + } | ||
| 1730 | + | ||
| 1731 | + return msg; | ||
| 1732 | +} | ||
| 1733 | + | ||
| 1734 | +SrsSource::SrsSource() | ||
| 1735 | +{ | ||
| 1736 | + req = NULL; | ||
| 1737 | + jitter_algorithm = SrsRtmpJitterAlgorithmOFF; | ||
| 1738 | + mix_correct = false; | ||
| 1739 | + mix_queue = new SrsMixQueue(); | ||
| 1740 | + | ||
| 1741 | + _can_publish = true; | ||
| 1742 | + _pre_source_id = _source_id = -1; | ||
| 1743 | + die_at = -1; | ||
| 1744 | + | ||
| 1745 | + play_edge = new SrsPlayEdge(); | ||
| 1746 | + publish_edge = new SrsPublishEdge(); | ||
| 1747 | + gop_cache = new SrsGopCache(); | ||
| 1748 | + aggregate_stream = new SrsBuffer(); | ||
| 1749 | + hub = new SrsOriginHub(this); | ||
| 1750 | + meta = new SrsMetaCache(); | ||
| 1751 | + | ||
| 1752 | + is_monotonically_increase = false; | ||
| 1753 | + last_packet_time = 0; | ||
| 1754 | + | ||
| 1755 | + _srs_config->subscribe(this); | ||
| 1756 | + atc = false; | ||
| 1757 | +} | ||
| 1758 | + | ||
| 1759 | +SrsSource::~SrsSource() | ||
| 1760 | +{ | ||
| 1761 | + _srs_config->unsubscribe(this); | ||
| 1762 | + | ||
| 1763 | + // never free the consumers, | ||
| 1764 | + // for all consumers are auto free. | ||
| 1765 | + consumers.clear(); | ||
| 1766 | + | ||
| 1767 | + srs_freep(hub); | ||
| 1768 | + srs_freep(meta); | ||
| 1769 | + srs_freep(mix_queue); | ||
| 1770 | + | ||
| 1771 | + srs_freep(play_edge); | ||
| 1772 | + srs_freep(publish_edge); | ||
| 1773 | + srs_freep(gop_cache); | ||
| 1774 | + srs_freep(aggregate_stream); | ||
| 1775 | + | ||
| 1776 | + srs_freep(req); | ||
| 1777 | +} | ||
| 1778 | + | ||
| 1779 | +void SrsSource::dispose() | ||
| 1780 | +{ | ||
| 1781 | + hub->dispose(); | ||
| 1782 | + meta->dispose(); | ||
| 1783 | + gop_cache->dispose(); | ||
| 1784 | +} | ||
| 1785 | + | ||
| 1786 | +int SrsSource::cycle() | ||
| 1295 | { | 1787 | { |
| 1296 | - int ret = ERROR_SUCCESS; | ||
| 1297 | - | ||
| 1298 | - if (req->vhost != vhost) { | ||
| 1299 | - return ret; | ||
| 1300 | - } | ||
| 1301 | - | ||
| 1302 | - // TODO: FIXME: maybe should ignore when publish already stopped? | ||
| 1303 | - | ||
| 1304 | -#ifdef SRS_AUTO_TRANSCODE | ||
| 1305 | - encoder->on_unpublish(); | ||
| 1306 | - if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1307 | - srs_error("start encoder failed. ret=%d", ret); | ||
| 1308 | - return ret; | ||
| 1309 | - } | ||
| 1310 | - srs_trace("vhost %s transcode reload success", vhost.c_str()); | ||
| 1311 | -#endif | ||
| 1312 | - | ||
| 1313 | - return ret; | 1788 | + return hub->cycle(); |
| 1314 | } | 1789 | } |
| 1315 | 1790 | ||
| 1316 | -int SrsSource::on_reload_vhost_exec(string vhost) | 1791 | +bool SrsSource::expired() |
| 1317 | { | 1792 | { |
| 1318 | - int ret = ERROR_SUCCESS; | 1793 | + // unknown state? |
| 1794 | + if (die_at == -1) { | ||
| 1795 | + return false; | ||
| 1796 | + } | ||
| 1319 | 1797 | ||
| 1320 | - if (req->vhost != vhost) { | ||
| 1321 | - return ret; | 1798 | + // still publishing? |
| 1799 | + if (!_can_publish || !publish_edge->can_publish()) { | ||
| 1800 | + return false; | ||
| 1322 | } | 1801 | } |
| 1323 | 1802 | ||
| 1324 | - // TODO: FIXME: maybe should ignore when publish already stopped? | 1803 | + // has any consumers? |
| 1804 | + if (!consumers.empty()) { | ||
| 1805 | + return false; | ||
| 1806 | + } | ||
| 1325 | 1807 | ||
| 1326 | - ng_exec->on_unpublish(); | ||
| 1327 | - if ((ret = ng_exec->on_publish(req)) != ERROR_SUCCESS) { | ||
| 1328 | - srs_error("start exec failed. ret=%d", ret); | ||
| 1329 | - return ret; | 1808 | + int64_t now = srs_get_system_time_ms(); |
| 1809 | + if (now > die_at + SRS_SOURCE_CLEANUP) { | ||
| 1810 | + return true; | ||
| 1330 | } | 1811 | } |
| 1331 | - srs_trace("vhost %s exec reload success", vhost.c_str()); | ||
| 1332 | 1812 | ||
| 1333 | - return ret; | 1813 | + return false; |
| 1334 | } | 1814 | } |
| 1335 | 1815 | ||
| 1336 | -int SrsSource::on_forwarder_start(SrsForwarder* forwarder) | 1816 | +int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h) |
| 1337 | { | 1817 | { |
| 1338 | int ret = ERROR_SUCCESS; | 1818 | int ret = ERROR_SUCCESS; |
| 1339 | - | ||
| 1340 | - // feed the forwarder the metadata/sequence header, | ||
| 1341 | - // when reload to enable the forwarder. | ||
| 1342 | - if (cache_metadata && (ret = forwarder->on_meta_data(cache_metadata)) != ERROR_SUCCESS) { | ||
| 1343 | - srs_error("forwarder process onMetaData message failed. ret=%d", ret); | 1819 | + |
| 1820 | + srs_assert(h); | ||
| 1821 | + srs_assert(!req); | ||
| 1822 | + | ||
| 1823 | + handler = h; | ||
| 1824 | + req = r->copy(); | ||
| 1825 | + atc = _srs_config->get_atc(req->vhost); | ||
| 1826 | + | ||
| 1827 | + if ((ret = hub->initialize(req)) != ERROR_SUCCESS) { | ||
| 1344 | return ret; | 1828 | return ret; |
| 1345 | } | 1829 | } |
| 1346 | - if (cache_sh_video && (ret = forwarder->on_video(cache_sh_video)) != ERROR_SUCCESS) { | ||
| 1347 | - srs_error("forwarder process video sequence header message failed. ret=%d", ret); | 1830 | + |
| 1831 | + if ((ret = play_edge->initialize(this, req)) != ERROR_SUCCESS) { | ||
| 1348 | return ret; | 1832 | return ret; |
| 1349 | } | 1833 | } |
| 1350 | - if (cache_sh_audio && (ret = forwarder->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1351 | - srs_error("forwarder process audio sequence header message failed. ret=%d", ret); | 1834 | + if ((ret = publish_edge->initialize(this, req)) != ERROR_SUCCESS) { |
| 1352 | return ret; | 1835 | return ret; |
| 1353 | } | 1836 | } |
| 1354 | 1837 | ||
| 1838 | + double queue_size = _srs_config->get_queue_length(req->vhost); | ||
| 1839 | + publish_edge->set_queue_size(queue_size); | ||
| 1840 | + | ||
| 1841 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost); | ||
| 1842 | + mix_correct = _srs_config->get_mix_correct(req->vhost); | ||
| 1843 | + | ||
| 1355 | return ret; | 1844 | return ret; |
| 1356 | } | 1845 | } |
| 1357 | 1846 | ||
| 1358 | -int SrsSource::on_hls_start() | 1847 | +int SrsSource::on_reload_vhost_play(string vhost) |
| 1359 | { | 1848 | { |
| 1360 | int ret = ERROR_SUCCESS; | 1849 | int ret = ERROR_SUCCESS; |
| 1361 | 1850 | ||
| 1362 | -#ifdef SRS_AUTO_HLS | ||
| 1363 | - // feed the hls the metadata/sequence header, | ||
| 1364 | - // when reload to start hls, hls will never get the sequence header in stream, | ||
| 1365 | - // use the SrsSource.on_hls_start to push the sequence header to HLS. | ||
| 1366 | - // TODO: maybe need to decode the metadata? | ||
| 1367 | - if (cache_sh_video && (ret = hls->on_video(cache_sh_video, true)) != ERROR_SUCCESS) { | ||
| 1368 | - srs_error("hls process video sequence header message failed. ret=%d", ret); | ||
| 1369 | - return ret; | ||
| 1370 | - } | ||
| 1371 | - if (cache_sh_audio && (ret = hls->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1372 | - srs_error("hls process audio sequence header message failed. ret=%d", ret); | 1851 | + if (req->vhost != vhost) { |
| 1373 | return ret; | 1852 | return ret; |
| 1374 | } | 1853 | } |
| 1375 | -#endif | ||
| 1376 | 1854 | ||
| 1377 | - return ret; | ||
| 1378 | -} | ||
| 1379 | - | ||
| 1380 | -int SrsSource::on_dvr_request_sh() | ||
| 1381 | -{ | ||
| 1382 | - int ret = ERROR_SUCCESS; | 1855 | + // time_jitter |
| 1856 | + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost); | ||
| 1383 | 1857 | ||
| 1384 | -#ifdef SRS_AUTO_DVR | ||
| 1385 | - // feed the dvr the metadata/sequence header, | ||
| 1386 | - // when reload to start dvr, dvr will never get the sequence header in stream, | ||
| 1387 | - // use the SrsSource.on_dvr_request_sh to push the sequence header to DVR. | ||
| 1388 | - if (cache_metadata) { | ||
| 1389 | - char* payload = cache_metadata->payload; | ||
| 1390 | - int size = cache_metadata->size; | 1858 | + // mix_correct |
| 1859 | + if (true) { | ||
| 1860 | + bool v = _srs_config->get_mix_correct(req->vhost); | ||
| 1391 | 1861 | ||
| 1392 | - SrsBuffer stream; | ||
| 1393 | - if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { | ||
| 1394 | - srs_error("dvr decode metadata stream failed. ret=%d", ret); | ||
| 1395 | - return ret; | 1862 | + // when changed, clear the mix queue. |
| 1863 | + if (v != mix_correct) { | ||
| 1864 | + mix_queue->clear(); | ||
| 1396 | } | 1865 | } |
| 1866 | + mix_correct = v; | ||
| 1867 | + } | ||
| 1868 | + | ||
| 1869 | + // atc changed. | ||
| 1870 | + if (true) { | ||
| 1871 | + bool v = _srs_config->get_atc(vhost); | ||
| 1397 | 1872 | ||
| 1398 | - SrsOnMetaDataPacket pkt; | ||
| 1399 | - if ((ret = pkt.decode(&stream)) != ERROR_SUCCESS) { | ||
| 1400 | - srs_error("dvr decode metadata packet failed."); | ||
| 1401 | - return ret; | 1873 | + if (v != atc) { |
| 1874 | + srs_warn("vhost %s atc changed to %d, connected client may corrupt.", vhost.c_str(), v); | ||
| 1875 | + gop_cache->clear(); | ||
| 1402 | } | 1876 | } |
| 1877 | + atc = v; | ||
| 1878 | + } | ||
| 1879 | + | ||
| 1880 | + // gop cache changed. | ||
| 1881 | + if (true) { | ||
| 1882 | + bool v = _srs_config->get_gop_cache(vhost); | ||
| 1403 | 1883 | ||
| 1404 | - if ((ret = dvr->on_meta_data(&pkt)) != ERROR_SUCCESS) { | ||
| 1405 | - srs_error("dvr process onMetaData message failed. ret=%d", ret); | ||
| 1406 | - return ret; | 1884 | + if (v != gop_cache->enabled()) { |
| 1885 | + string url = req->get_stream_url(); | ||
| 1886 | + srs_trace("vhost %s gop_cache changed to %d, source url=%s", vhost.c_str(), v, url.c_str()); | ||
| 1887 | + gop_cache->set(v); | ||
| 1407 | } | 1888 | } |
| 1408 | } | 1889 | } |
| 1409 | 1890 | ||
| 1410 | - if (cache_sh_video && (ret = dvr->on_video(cache_sh_video)) != ERROR_SUCCESS) { | ||
| 1411 | - srs_error("dvr process video sequence header message failed. ret=%d", ret); | ||
| 1412 | - return ret; | ||
| 1413 | - } | ||
| 1414 | - if (cache_sh_audio && (ret = dvr->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { | ||
| 1415 | - srs_error("dvr process audio sequence header message failed. ret=%d", ret); | ||
| 1416 | - return ret; | ||
| 1417 | - } | 1891 | + // queue length |
| 1892 | + if (true) { | ||
| 1893 | + double v = _srs_config->get_queue_length(req->vhost); | ||
| 1894 | + | ||
| 1895 | + if (true) { | ||
| 1896 | + std::vector<SrsConsumer*>::iterator it; | ||
| 1897 | + | ||
| 1898 | + for (it = consumers.begin(); it != consumers.end(); ++it) { | ||
| 1899 | + SrsConsumer* consumer = *it; | ||
| 1900 | + consumer->set_queue_size(v); | ||
| 1901 | + } | ||
| 1902 | + | ||
| 1903 | + srs_trace("consumers reload queue size success."); | ||
| 1904 | + } | ||
| 1905 | + | ||
| 1906 | + // TODO: FIXME: https://github.com/ossrs/srs/issues/742#issuecomment-273656897 | ||
| 1907 | + // TODO: FIXME: support queue size. | ||
| 1908 | +#if 0 | ||
| 1909 | + if (true) { | ||
| 1910 | + std::vector<SrsForwarder*>::iterator it; | ||
| 1911 | + | ||
| 1912 | + for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1913 | + SrsForwarder* forwarder = *it; | ||
| 1914 | + forwarder->set_queue_size(v); | ||
| 1915 | + } | ||
| 1916 | + | ||
| 1917 | + srs_trace("forwarders reload queue size success."); | ||
| 1918 | + } | ||
| 1919 | + | ||
| 1920 | + if (true) { | ||
| 1921 | + publish_edge->set_queue_size(v); | ||
| 1922 | + srs_trace("publish_edge reload queue size success."); | ||
| 1923 | + } | ||
| 1418 | #endif | 1924 | #endif |
| 1925 | + } | ||
| 1419 | 1926 | ||
| 1420 | return ret; | 1927 | return ret; |
| 1421 | } | 1928 | } |
| @@ -1469,53 +1976,13 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | @@ -1469,53 +1976,13 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | ||
| 1469 | { | 1976 | { |
| 1470 | int ret = ERROR_SUCCESS; | 1977 | int ret = ERROR_SUCCESS; |
| 1471 | 1978 | ||
| 1472 | -#ifdef SRS_AUTO_HLS | ||
| 1473 | - if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { | ||
| 1474 | - srs_error("hls process onMetaData message failed. ret=%d", ret); | ||
| 1475 | - return ret; | ||
| 1476 | - } | ||
| 1477 | -#endif | ||
| 1478 | - | ||
| 1479 | -#ifdef SRS_AUTO_DVR | ||
| 1480 | - if (metadata && (ret = dvr->on_meta_data(metadata)) != ERROR_SUCCESS) { | ||
| 1481 | - srs_error("dvr process onMetaData message failed. ret=%d", ret); | 1979 | + // Notify hub about the original metadata. |
| 1980 | + if ((ret = hub->on_original_metadata(metadata)) != ERROR_SUCCESS) { | ||
| 1482 | return ret; | 1981 | return ret; |
| 1483 | } | 1982 | } |
| 1484 | -#endif | ||
| 1485 | - | ||
| 1486 | - SrsAmf0Any* prop = NULL; | ||
| 1487 | - | ||
| 1488 | - // when exists the duration, remove it to make ExoPlayer happy. | ||
| 1489 | - if (metadata->metadata->get_property("duration") != NULL) { | ||
| 1490 | - metadata->metadata->remove("duration"); | ||
| 1491 | - } | ||
| 1492 | - | ||
| 1493 | - // generate metadata info to print | ||
| 1494 | - std::stringstream ss; | ||
| 1495 | - if ((prop = metadata->metadata->ensure_property_number("width")) != NULL) { | ||
| 1496 | - ss << ", width=" << (int)prop->to_number(); | ||
| 1497 | - } | ||
| 1498 | - if ((prop = metadata->metadata->ensure_property_number("height")) != NULL) { | ||
| 1499 | - ss << ", height=" << (int)prop->to_number(); | ||
| 1500 | - } | ||
| 1501 | - if ((prop = metadata->metadata->ensure_property_number("videocodecid")) != NULL) { | ||
| 1502 | - ss << ", vcodec=" << (int)prop->to_number(); | ||
| 1503 | - } | ||
| 1504 | - if ((prop = metadata->metadata->ensure_property_number("audiocodecid")) != NULL) { | ||
| 1505 | - ss << ", acodec=" << (int)prop->to_number(); | ||
| 1506 | - } | ||
| 1507 | - srs_trace("got metadata%s", ss.str().c_str()); | ||
| 1508 | - | ||
| 1509 | - // add server info to metadata | ||
| 1510 | - metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_SERVER)); | ||
| 1511 | - metadata->metadata->set("srs_primary", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY)); | ||
| 1512 | - metadata->metadata->set("srs_authors", SrsAmf0Any::str(RTMP_SIG_SRS_AUTHROS)); | ||
| 1513 | - | ||
| 1514 | - // version, for example, 1.0.0 | ||
| 1515 | - // add version to metadata, please donot remove it, for debug. | ||
| 1516 | - metadata->metadata->set("server_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); | ||
| 1517 | 1983 | ||
| 1518 | // if allow atc_auto and bravo-atc detected, open atc for vhost. | 1984 | // if allow atc_auto and bravo-atc detected, open atc for vhost. |
| 1985 | + SrsAmf0Any* prop = NULL; | ||
| 1519 | atc = _srs_config->get_atc(req->vhost); | 1986 | atc = _srs_config->get_atc(req->vhost); |
| 1520 | if (_srs_config->get_atc_auto(req->vhost)) { | 1987 | if (_srs_config->get_atc_auto(req->vhost)) { |
| 1521 | if ((prop = metadata->metadata->get_property("bravo_atc")) != NULL) { | 1988 | if ((prop = metadata->metadata->get_property("bravo_atc")) != NULL) { |
| @@ -1525,65 +1992,36 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | @@ -1525,65 +1992,36 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | ||
| 1525 | } | 1992 | } |
| 1526 | } | 1993 | } |
| 1527 | 1994 | ||
| 1528 | - // encode the metadata to payload | ||
| 1529 | - int size = 0; | ||
| 1530 | - char* payload = NULL; | ||
| 1531 | - if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { | ||
| 1532 | - srs_error("encode metadata error. ret=%d", ret); | ||
| 1533 | - srs_freep(payload); | 1995 | + // Update the meta cache. |
| 1996 | + bool updated = false; | ||
| 1997 | + if ((ret = meta->update_data(&msg->header, metadata, updated)) != ERROR_SUCCESS) { | ||
| 1534 | return ret; | 1998 | return ret; |
| 1535 | } | 1999 | } |
| 1536 | - srs_verbose("encode metadata success."); | ||
| 1537 | - | ||
| 1538 | - if (size <= 0) { | ||
| 1539 | - srs_warn("ignore the invalid metadata. size=%d", size); | 2000 | + if (!updated) { |
| 1540 | return ret; | 2001 | return ret; |
| 1541 | } | 2002 | } |
| 1542 | 2003 | ||
| 1543 | // when already got metadata, drop when reduce sequence header. | 2004 | // when already got metadata, drop when reduce sequence header. |
| 1544 | bool drop_for_reduce = false; | 2005 | bool drop_for_reduce = false; |
| 1545 | - if (cache_metadata && _srs_config->get_reduce_sequence_header(req->vhost)) { | 2006 | + if (meta->data() && _srs_config->get_reduce_sequence_header(req->vhost)) { |
| 1546 | drop_for_reduce = true; | 2007 | drop_for_reduce = true; |
| 1547 | srs_warn("drop for reduce sh metadata, size=%d", msg->size); | 2008 | srs_warn("drop for reduce sh metadata, size=%d", msg->size); |
| 1548 | } | 2009 | } |
| 1549 | 2010 | ||
| 1550 | - // create a shared ptr message. | ||
| 1551 | - srs_freep(cache_metadata); | ||
| 1552 | - cache_metadata = new SrsSharedPtrMessage(); | ||
| 1553 | - | ||
| 1554 | - // dump message to shared ptr message. | ||
| 1555 | - // the payload/size managed by cache_metadata, user should not free it. | ||
| 1556 | - if ((ret = cache_metadata->create(&msg->header, payload, size)) != ERROR_SUCCESS) { | ||
| 1557 | - srs_error("initialize the cache metadata failed. ret=%d", ret); | ||
| 1558 | - return ret; | ||
| 1559 | - } | ||
| 1560 | - srs_verbose("initialize shared ptr metadata success."); | ||
| 1561 | - | ||
| 1562 | // copy to all consumer | 2011 | // copy to all consumer |
| 1563 | if (!drop_for_reduce) { | 2012 | if (!drop_for_reduce) { |
| 1564 | std::vector<SrsConsumer*>::iterator it; | 2013 | std::vector<SrsConsumer*>::iterator it; |
| 1565 | - for (it = consumers.begin(); it != consumers.end(); ++it) { | ||
| 1566 | - SrsConsumer* consumer = *it; | ||
| 1567 | - if ((ret = consumer->enqueue(cache_metadata, atc, jitter_algorithm)) != ERROR_SUCCESS) { | ||
| 1568 | - srs_error("dispatch the metadata failed. ret=%d", ret); | ||
| 1569 | - return ret; | ||
| 1570 | - } | ||
| 1571 | - } | ||
| 1572 | - } | ||
| 1573 | - | ||
| 1574 | - // copy to all forwarders | ||
| 1575 | - if (true) { | ||
| 1576 | - std::vector<SrsForwarder*>::iterator it; | ||
| 1577 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1578 | - SrsForwarder* forwarder = *it; | ||
| 1579 | - if ((ret = forwarder->on_meta_data(cache_metadata)) != ERROR_SUCCESS) { | ||
| 1580 | - srs_error("forwarder process onMetaData message failed. ret=%d", ret); | 2014 | + for (it = consumers.begin(); it != consumers.end(); ++it) { |
| 2015 | + SrsConsumer* consumer = *it; | ||
| 2016 | + if ((ret = consumer->enqueue(meta->data(), atc, jitter_algorithm)) != ERROR_SUCCESS) { | ||
| 2017 | + srs_error("dispatch the metadata failed. ret=%d", ret); | ||
| 1581 | return ret; | 2018 | return ret; |
| 1582 | } | 2019 | } |
| 1583 | } | 2020 | } |
| 1584 | } | 2021 | } |
| 1585 | 2022 | ||
| 1586 | - return ret; | 2023 | + // Copy to hub to all utilities. |
| 2024 | + return hub->on_meta_data(meta->data()); | ||
| 1587 | } | 2025 | } |
| 1588 | 2026 | ||
| 1589 | int SrsSource::on_audio(SrsCommonMessage* shared_audio) | 2027 | int SrsSource::on_audio(SrsCommonMessage* shared_audio) |
| @@ -1633,24 +2071,6 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) | @@ -1633,24 +2071,6 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) | ||
| 1633 | return ret; | 2071 | return ret; |
| 1634 | } | 2072 | } |
| 1635 | 2073 | ||
| 1636 | -bool srs_hls_can_continue(int ret, SrsSharedPtrMessage* sh, SrsSharedPtrMessage* msg) | ||
| 1637 | -{ | ||
| 1638 | - // only continue for decode error. | ||
| 1639 | - if (ret != ERROR_HLS_DECODE_ERROR) { | ||
| 1640 | - return false; | ||
| 1641 | - } | ||
| 1642 | - | ||
| 1643 | - // when video size equals to sequence header, | ||
| 1644 | - // the video actually maybe a sequence header, | ||
| 1645 | - // continue to make ffmpeg happy. | ||
| 1646 | - if (sh && sh->size == msg->size) { | ||
| 1647 | - srs_warn("the msg is actually a sequence header, ignore this packet."); | ||
| 1648 | - return true; | ||
| 1649 | - } | ||
| 1650 | - | ||
| 1651 | - return false; | ||
| 1652 | -} | ||
| 1653 | - | ||
| 1654 | int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | 2074 | int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) |
| 1655 | { | 2075 | { |
| 1656 | int ret = ERROR_SUCCESS; | 2076 | int ret = ERROR_SUCCESS; |
| @@ -1661,9 +2081,9 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | @@ -1661,9 +2081,9 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | ||
| 1661 | 2081 | ||
| 1662 | // whether consumer should drop for the duplicated sequence header. | 2082 | // whether consumer should drop for the duplicated sequence header. |
| 1663 | bool drop_for_reduce = false; | 2083 | bool drop_for_reduce = false; |
| 1664 | - if (is_sequence_header && cache_sh_audio && _srs_config->get_reduce_sequence_header(req->vhost)) { | ||
| 1665 | - if (cache_sh_audio->size == msg->size) { | ||
| 1666 | - drop_for_reduce = srs_bytes_equals(cache_sh_audio->payload, msg->payload, msg->size); | 2084 | + if (is_sequence_header && meta->ash() && _srs_config->get_reduce_sequence_header(req->vhost)) { |
| 2085 | + if (meta->ash()->size == msg->size) { | ||
| 2086 | + drop_for_reduce = srs_bytes_equals(meta->ash()->payload, msg->payload, msg->size); | ||
| 1667 | srs_warn("drop for reduce sh audio, size=%d", msg->size); | 2087 | srs_warn("drop for reduce sh audio, size=%d", msg->size); |
| 1668 | } | 2088 | } |
| 1669 | } | 2089 | } |
| @@ -1697,56 +2117,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | @@ -1697,56 +2117,6 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | ||
| 1697 | flv_sample_rates[sample.sound_rate]); | 2117 | flv_sample_rates[sample.sound_rate]); |
| 1698 | } | 2118 | } |
| 1699 | 2119 | ||
| 1700 | -#ifdef SRS_AUTO_HLS | ||
| 1701 | - if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 1702 | - // apply the error strategy for hls. | ||
| 1703 | - // @see https://github.com/ossrs/srs/issues/264 | ||
| 1704 | - std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); | ||
| 1705 | - if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) { | ||
| 1706 | - srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); | ||
| 1707 | - | ||
| 1708 | - // unpublish, ignore ret. | ||
| 1709 | - hls->on_unpublish(); | ||
| 1710 | - | ||
| 1711 | - // ignore. | ||
| 1712 | - ret = ERROR_SUCCESS; | ||
| 1713 | - } else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) { | ||
| 1714 | - if (srs_hls_can_continue(ret, cache_sh_audio, msg)) { | ||
| 1715 | - ret = ERROR_SUCCESS; | ||
| 1716 | - } else { | ||
| 1717 | - srs_warn("hls continue audio failed. ret=%d", ret); | ||
| 1718 | - return ret; | ||
| 1719 | - } | ||
| 1720 | - } else { | ||
| 1721 | - srs_warn("hls disconnect publisher for audio error. ret=%d", ret); | ||
| 1722 | - return ret; | ||
| 1723 | - } | ||
| 1724 | - } | ||
| 1725 | -#endif | ||
| 1726 | - | ||
| 1727 | -#ifdef SRS_AUTO_DVR | ||
| 1728 | - if ((ret = dvr->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 1729 | - srs_warn("dvr process audio message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1730 | - | ||
| 1731 | - // unpublish, ignore ret. | ||
| 1732 | - dvr->on_unpublish(); | ||
| 1733 | - | ||
| 1734 | - // ignore. | ||
| 1735 | - ret = ERROR_SUCCESS; | ||
| 1736 | - } | ||
| 1737 | -#endif | ||
| 1738 | - | ||
| 1739 | -#ifdef SRS_AUTO_HDS | ||
| 1740 | - if ((ret = hds->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 1741 | - srs_warn("hds process audio message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1742 | - | ||
| 1743 | - // unpublish, ignore ret. | ||
| 1744 | - hds->on_unpublish(); | ||
| 1745 | - // ignore. | ||
| 1746 | - ret = ERROR_SUCCESS; | ||
| 1747 | - } | ||
| 1748 | -#endif | ||
| 1749 | - | ||
| 1750 | // copy to all consumer | 2120 | // copy to all consumer |
| 1751 | if (!drop_for_reduce) { | 2121 | if (!drop_for_reduce) { |
| 1752 | for (int i = 0; i < (int)consumers.size(); i++) { | 2122 | for (int i = 0; i < (int)consumers.size(); i++) { |
| @@ -1759,24 +2129,16 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | @@ -1759,24 +2129,16 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | ||
| 1759 | srs_info("dispatch audio success."); | 2129 | srs_info("dispatch audio success."); |
| 1760 | } | 2130 | } |
| 1761 | 2131 | ||
| 1762 | - // copy to all forwarders. | ||
| 1763 | - if (true) { | ||
| 1764 | - std::vector<SrsForwarder*>::iterator it; | ||
| 1765 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1766 | - SrsForwarder* forwarder = *it; | ||
| 1767 | - if ((ret = forwarder->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 1768 | - srs_error("forwarder process audio message failed. ret=%d", ret); | ||
| 1769 | - return ret; | ||
| 1770 | - } | ||
| 1771 | - } | 2132 | + // Copy to hub to all utilities. |
| 2133 | + if ((ret = hub->on_audio(msg)) != ERROR_SUCCESS) { | ||
| 2134 | + return ret; | ||
| 1772 | } | 2135 | } |
| 1773 | 2136 | ||
| 1774 | // cache the sequence header of aac, or first packet of mp3. | 2137 | // cache the sequence header of aac, or first packet of mp3. |
| 1775 | // for example, the mp3 is used for hls to write the "right" audio codec. | 2138 | // for example, the mp3 is used for hls to write the "right" audio codec. |
| 1776 | // TODO: FIXME: to refine the stream info system. | 2139 | // TODO: FIXME: to refine the stream info system. |
| 1777 | - if (is_aac_sequence_header || !cache_sh_audio) { | ||
| 1778 | - srs_freep(cache_sh_audio); | ||
| 1779 | - cache_sh_audio = msg->copy(); | 2140 | + if (is_aac_sequence_header || !meta->ash()) { |
| 2141 | + meta->update_ash(msg); | ||
| 1780 | } | 2142 | } |
| 1781 | 2143 | ||
| 1782 | // when sequence header, donot push to gop cache and adjust the timestamp. | 2144 | // when sequence header, donot push to gop cache and adjust the timestamp. |
| @@ -1793,11 +2155,11 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | @@ -1793,11 +2155,11 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) | ||
| 1793 | 2155 | ||
| 1794 | // if atc, update the sequence header to abs time. | 2156 | // if atc, update the sequence header to abs time. |
| 1795 | if (atc) { | 2157 | if (atc) { |
| 1796 | - if (cache_sh_audio) { | ||
| 1797 | - cache_sh_audio->timestamp = msg->timestamp; | 2158 | + if (meta->ash()) { |
| 2159 | + meta->ash()->timestamp = msg->timestamp; | ||
| 1798 | } | 2160 | } |
| 1799 | - if (cache_metadata) { | ||
| 1800 | - cache_metadata->timestamp = msg->timestamp; | 2161 | + if (meta->data()) { |
| 2162 | + meta->data()->timestamp = msg->timestamp; | ||
| 1801 | } | 2163 | } |
| 1802 | } | 2164 | } |
| 1803 | 2165 | ||
| @@ -1874,9 +2236,9 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | @@ -1874,9 +2236,9 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | ||
| 1874 | 2236 | ||
| 1875 | // whether consumer should drop for the duplicated sequence header. | 2237 | // whether consumer should drop for the duplicated sequence header. |
| 1876 | bool drop_for_reduce = false; | 2238 | bool drop_for_reduce = false; |
| 1877 | - if (is_sequence_header && cache_sh_video && _srs_config->get_reduce_sequence_header(req->vhost)) { | ||
| 1878 | - if (cache_sh_video->size == msg->size) { | ||
| 1879 | - drop_for_reduce = srs_bytes_equals(cache_sh_video->payload, msg->payload, msg->size); | 2239 | + if (is_sequence_header && meta->vsh() && _srs_config->get_reduce_sequence_header(req->vhost)) { |
| 2240 | + if (meta->vsh()->size == msg->size) { | ||
| 2241 | + drop_for_reduce = srs_bytes_equals(meta->vsh()->payload, msg->payload, msg->size); | ||
| 1880 | srs_warn("drop for reduce sh video, size=%d", msg->size); | 2242 | srs_warn("drop for reduce sh video, size=%d", msg->size); |
| 1881 | } | 2243 | } |
| 1882 | } | 2244 | } |
| @@ -1884,8 +2246,7 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | @@ -1884,8 +2246,7 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | ||
| 1884 | // cache the sequence header if h264 | 2246 | // cache the sequence header if h264 |
| 1885 | // donot cache the sequence header to gop_cache, return here. | 2247 | // donot cache the sequence header to gop_cache, return here. |
| 1886 | if (is_sequence_header) { | 2248 | if (is_sequence_header) { |
| 1887 | - srs_freep(cache_sh_video); | ||
| 1888 | - cache_sh_video = msg->copy(); | 2249 | + meta->update_vsh(msg); |
| 1889 | 2250 | ||
| 1890 | // parse detail audio codec | 2251 | // parse detail audio codec |
| 1891 | SrsAvcAacCodec codec; | 2252 | SrsAvcAacCodec codec; |
| @@ -1913,55 +2274,10 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | @@ -1913,55 +2274,10 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | ||
| 1913 | codec.video_data_rate / 1000, codec.frame_rate, codec.duration); | 2274 | codec.video_data_rate / 1000, codec.frame_rate, codec.duration); |
| 1914 | } | 2275 | } |
| 1915 | 2276 | ||
| 1916 | -#ifdef SRS_AUTO_HLS | ||
| 1917 | - if ((ret = hls->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { | ||
| 1918 | - // apply the error strategy for hls. | ||
| 1919 | - // @see https://github.com/ossrs/srs/issues/264 | ||
| 1920 | - std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); | ||
| 1921 | - if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) { | ||
| 1922 | - srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); | ||
| 1923 | - | ||
| 1924 | - // unpublish, ignore ret. | ||
| 1925 | - hls->on_unpublish(); | ||
| 1926 | - | ||
| 1927 | - // ignore. | ||
| 1928 | - ret = ERROR_SUCCESS; | ||
| 1929 | - } else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) { | ||
| 1930 | - if (srs_hls_can_continue(ret, cache_sh_video, msg)) { | ||
| 1931 | - ret = ERROR_SUCCESS; | ||
| 1932 | - } else { | ||
| 1933 | - srs_warn("hls continue video failed. ret=%d", ret); | ||
| 1934 | - return ret; | ||
| 1935 | - } | ||
| 1936 | - } else { | ||
| 1937 | - srs_warn("hls disconnect publisher for video error. ret=%d", ret); | ||
| 1938 | - return ret; | ||
| 1939 | - } | ||
| 1940 | - } | ||
| 1941 | -#endif | ||
| 1942 | - | ||
| 1943 | -#ifdef SRS_AUTO_DVR | ||
| 1944 | - if ((ret = dvr->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1945 | - srs_warn("dvr process video message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1946 | - | ||
| 1947 | - // unpublish, ignore ret. | ||
| 1948 | - dvr->on_unpublish(); | ||
| 1949 | - | ||
| 1950 | - // ignore. | ||
| 1951 | - ret = ERROR_SUCCESS; | ||
| 1952 | - } | ||
| 1953 | -#endif | ||
| 1954 | - | ||
| 1955 | -#ifdef SRS_AUTO_HDS | ||
| 1956 | - if ((ret = hds->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1957 | - srs_warn("hds process video message failed, ignore and disable dvr. ret=%d", ret); | ||
| 1958 | - | ||
| 1959 | - // unpublish, ignore ret. | ||
| 1960 | - hds->on_unpublish(); | ||
| 1961 | - // ignore. | ||
| 1962 | - ret = ERROR_SUCCESS; | 2277 | + // Copy to hub to all utilities. |
| 2278 | + if ((ret = hub->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { | ||
| 2279 | + return ret; | ||
| 1963 | } | 2280 | } |
| 1964 | -#endif | ||
| 1965 | 2281 | ||
| 1966 | // copy to all consumer | 2282 | // copy to all consumer |
| 1967 | if (!drop_for_reduce) { | 2283 | if (!drop_for_reduce) { |
| @@ -1974,18 +2290,6 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | @@ -1974,18 +2290,6 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | ||
| 1974 | } | 2290 | } |
| 1975 | srs_info("dispatch video success."); | 2291 | srs_info("dispatch video success."); |
| 1976 | } | 2292 | } |
| 1977 | - | ||
| 1978 | - // copy to all forwarders. | ||
| 1979 | - if (!forwarders.empty()) { | ||
| 1980 | - std::vector<SrsForwarder*>::iterator it; | ||
| 1981 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 1982 | - SrsForwarder* forwarder = *it; | ||
| 1983 | - if ((ret = forwarder->on_video(msg)) != ERROR_SUCCESS) { | ||
| 1984 | - srs_error("forwarder process video message failed. ret=%d", ret); | ||
| 1985 | - return ret; | ||
| 1986 | - } | ||
| 1987 | - } | ||
| 1988 | - } | ||
| 1989 | 2293 | ||
| 1990 | // when sequence header, donot push to gop cache and adjust the timestamp. | 2294 | // when sequence header, donot push to gop cache and adjust the timestamp. |
| 1991 | if (is_sequence_header) { | 2295 | if (is_sequence_header) { |
| @@ -2001,11 +2305,11 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | @@ -2001,11 +2305,11 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) | ||
| 2001 | 2305 | ||
| 2002 | // if atc, update the sequence header to abs time. | 2306 | // if atc, update the sequence header to abs time. |
| 2003 | if (atc) { | 2307 | if (atc) { |
| 2004 | - if (cache_sh_video) { | ||
| 2005 | - cache_sh_video->timestamp = msg->timestamp; | 2308 | + if (meta->vsh()) { |
| 2309 | + meta->vsh()->timestamp = msg->timestamp; | ||
| 2006 | } | 2310 | } |
| 2007 | - if (cache_metadata) { | ||
| 2008 | - cache_metadata->timestamp = msg->timestamp; | 2311 | + if (meta->data()) { |
| 2312 | + meta->data()->timestamp = msg->timestamp; | ||
| 2009 | } | 2313 | } |
| 2010 | } | 2314 | } |
| 2011 | 2315 | ||
| @@ -2142,45 +2446,8 @@ int SrsSource::on_publish() | @@ -2142,45 +2446,8 @@ int SrsSource::on_publish() | ||
| 2142 | is_monotonically_increase = true; | 2446 | is_monotonically_increase = true; |
| 2143 | last_packet_time = 0; | 2447 | last_packet_time = 0; |
| 2144 | 2448 | ||
| 2145 | - // create forwarders | ||
| 2146 | - if ((ret = create_forwarders()) != ERROR_SUCCESS) { | ||
| 2147 | - srs_error("create forwarders failed. ret=%d", ret); | ||
| 2148 | - return ret; | ||
| 2149 | - } | ||
| 2150 | - | ||
| 2151 | - // TODO: FIXME: use initialize to set req. | ||
| 2152 | -#ifdef SRS_AUTO_TRANSCODE | ||
| 2153 | - if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { | ||
| 2154 | - srs_error("start encoder failed. ret=%d", ret); | ||
| 2155 | - return ret; | ||
| 2156 | - } | ||
| 2157 | -#endif | ||
| 2158 | - | ||
| 2159 | -#ifdef SRS_AUTO_HLS | ||
| 2160 | - if ((ret = hls->on_publish(false)) != ERROR_SUCCESS) { | ||
| 2161 | - srs_error("start hls failed. ret=%d", ret); | ||
| 2162 | - return ret; | ||
| 2163 | - } | ||
| 2164 | -#endif | ||
| 2165 | - | ||
| 2166 | -#ifdef SRS_AUTO_DVR | ||
| 2167 | - if ((ret = dvr->on_publish(false)) != ERROR_SUCCESS) { | ||
| 2168 | - srs_error("start dvr failed. ret=%d", ret); | ||
| 2169 | - return ret; | ||
| 2170 | - } | ||
| 2171 | -#endif | ||
| 2172 | - | ||
| 2173 | - // TODO: FIXME: use initialize to set req. | ||
| 2174 | -#ifdef SRS_AUTO_HDS | ||
| 2175 | - if ((ret = hds->on_publish(req)) != ERROR_SUCCESS) { | ||
| 2176 | - srs_error("start hds failed. ret=%d", ret); | ||
| 2177 | - return ret; | ||
| 2178 | - } | ||
| 2179 | -#endif | ||
| 2180 | - | ||
| 2181 | - // TODO: FIXME: use initialize to set req. | ||
| 2182 | - if ((ret = ng_exec->on_publish(req)) != ERROR_SUCCESS) { | ||
| 2183 | - srs_error("start exec failed. ret=%d", ret); | 2449 | + // Notify the hub about the publish event. |
| 2450 | + if ((ret = hub->on_publish()) != ERROR_SUCCESS) { | ||
| 2184 | return ret; | 2451 | return ret; |
| 2185 | } | 2452 | } |
| 2186 | 2453 | ||
| @@ -2203,26 +2470,8 @@ void SrsSource::on_unpublish() | @@ -2203,26 +2470,8 @@ void SrsSource::on_unpublish() | ||
| 2203 | return; | 2470 | return; |
| 2204 | } | 2471 | } |
| 2205 | 2472 | ||
| 2206 | - // destroy all forwarders | ||
| 2207 | - destroy_forwarders(); | ||
| 2208 | - | ||
| 2209 | -#ifdef SRS_AUTO_TRANSCODE | ||
| 2210 | - encoder->on_unpublish(); | ||
| 2211 | -#endif | ||
| 2212 | - | ||
| 2213 | -#ifdef SRS_AUTO_HLS | ||
| 2214 | - hls->on_unpublish(); | ||
| 2215 | -#endif | ||
| 2216 | - | ||
| 2217 | -#ifdef SRS_AUTO_DVR | ||
| 2218 | - dvr->on_unpublish(); | ||
| 2219 | -#endif | ||
| 2220 | - | ||
| 2221 | -#ifdef SRS_AUTO_HDS | ||
| 2222 | - hds->on_unpublish(); | ||
| 2223 | -#endif | ||
| 2224 | - | ||
| 2225 | - ng_exec->on_unpublish(); | 2473 | + // Notify the hub about the unpublish event. |
| 2474 | + hub->on_unpublish(); | ||
| 2226 | 2475 | ||
| 2227 | // only clear the gop cache, | 2476 | // only clear the gop cache, |
| 2228 | // donot clear the sequence header, for it maybe not changed, | 2477 | // donot clear the sequence header, for it maybe not changed, |
| @@ -2259,38 +2508,21 @@ int SrsSource::create_consumer(SrsConnection* conn, SrsConsumer*& consumer, bool | @@ -2259,38 +2508,21 @@ int SrsSource::create_consumer(SrsConnection* conn, SrsConsumer*& consumer, bool | ||
| 2259 | 2508 | ||
| 2260 | // if atc, update the sequence header to gop cache time. | 2509 | // if atc, update the sequence header to gop cache time. |
| 2261 | if (atc && !gop_cache->empty()) { | 2510 | if (atc && !gop_cache->empty()) { |
| 2262 | - if (cache_metadata) { | ||
| 2263 | - cache_metadata->timestamp = gop_cache->start_time(); | 2511 | + if (meta->data()) { |
| 2512 | + meta->data()->timestamp = gop_cache->start_time(); | ||
| 2264 | } | 2513 | } |
| 2265 | - if (cache_sh_video) { | ||
| 2266 | - cache_sh_video->timestamp = gop_cache->start_time(); | 2514 | + if (meta->vsh()) { |
| 2515 | + meta->vsh()->timestamp = gop_cache->start_time(); | ||
| 2267 | } | 2516 | } |
| 2268 | - if (cache_sh_audio) { | ||
| 2269 | - cache_sh_audio->timestamp = gop_cache->start_time(); | 2517 | + if (meta->ash()) { |
| 2518 | + meta->ash()->timestamp = gop_cache->start_time(); | ||
| 2270 | } | 2519 | } |
| 2271 | } | 2520 | } |
| 2272 | 2521 | ||
| 2273 | - // copy metadata. | ||
| 2274 | - if (dm && cache_metadata && (ret = consumer->enqueue(cache_metadata, atc, jitter_algorithm)) != ERROR_SUCCESS) { | ||
| 2275 | - srs_error("dispatch metadata failed. ret=%d", ret); | ||
| 2276 | - return ret; | ||
| 2277 | - } | ||
| 2278 | - srs_info("dispatch metadata success"); | ||
| 2279 | - | ||
| 2280 | - // copy sequence header | ||
| 2281 | - // copy audio sequence first, for hls to fast parse the "right" audio codec. | ||
| 2282 | - // @see https://github.com/ossrs/srs/issues/301 | ||
| 2283 | - if (ds && cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, jitter_algorithm)) != ERROR_SUCCESS) { | ||
| 2284 | - srs_error("dispatch audio sequence header failed. ret=%d", ret); | ||
| 2285 | - return ret; | ||
| 2286 | - } | ||
| 2287 | - srs_info("dispatch audio sequence header success"); | ||
| 2288 | - | ||
| 2289 | - if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, jitter_algorithm)) != ERROR_SUCCESS) { | ||
| 2290 | - srs_error("dispatch video sequence header failed. ret=%d", ret); | 2522 | + // Copy metadata and sequence header to consumer. |
| 2523 | + if ((ret = meta->dumps(consumer, atc, jitter_algorithm, dm, ds)) != ERROR_SUCCESS) { | ||
| 2291 | return ret; | 2524 | return ret; |
| 2292 | } | 2525 | } |
| 2293 | - srs_info("dispatch video sequence header success"); | ||
| 2294 | 2526 | ||
| 2295 | // copy gop cache to client. | 2527 | // copy gop cache to client. |
| 2296 | if (dg && (ret = gop_cache->dump(consumer, atc, jitter_algorithm)) != ERROR_SUCCESS) { | 2528 | if (dg && (ret = gop_cache->dump(consumer, atc, jitter_algorithm)) != ERROR_SUCCESS) { |
| @@ -2356,52 +2588,6 @@ void SrsSource::on_edge_proxy_unpublish() | @@ -2356,52 +2588,6 @@ void SrsSource::on_edge_proxy_unpublish() | ||
| 2356 | publish_edge->on_proxy_unpublish(); | 2588 | publish_edge->on_proxy_unpublish(); |
| 2357 | } | 2589 | } |
| 2358 | 2590 | ||
| 2359 | -int SrsSource::create_forwarders() | ||
| 2360 | -{ | ||
| 2361 | - int ret = ERROR_SUCCESS; | ||
| 2362 | - | ||
| 2363 | - if (!_srs_config->get_forward_enabled(req->vhost)) { | ||
| 2364 | - return ret; | ||
| 2365 | - } | ||
| 2366 | - | ||
| 2367 | - SrsConfDirective* conf = _srs_config->get_forwards(req->vhost); | ||
| 2368 | - for (int i = 0; conf && i < (int)conf->args.size(); i++) { | ||
| 2369 | - std::string forward_server = conf->args.at(i); | ||
| 2370 | - | ||
| 2371 | - SrsForwarder* forwarder = new SrsForwarder(this); | ||
| 2372 | - forwarders.push_back(forwarder); | ||
| 2373 | - | ||
| 2374 | - // initialize the forwarder with request. | ||
| 2375 | - if ((ret = forwarder->initialize(req, forward_server)) != ERROR_SUCCESS) { | ||
| 2376 | - return ret; | ||
| 2377 | - } | ||
| 2378 | - | ||
| 2379 | - double queue_size = _srs_config->get_queue_length(req->vhost); | ||
| 2380 | - forwarder->set_queue_size(queue_size); | ||
| 2381 | - | ||
| 2382 | - if ((ret = forwarder->on_publish()) != ERROR_SUCCESS) { | ||
| 2383 | - srs_error("start forwarder failed. " | ||
| 2384 | - "vhost=%s, app=%s, stream=%s, forward-to=%s", | ||
| 2385 | - req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), | ||
| 2386 | - forward_server.c_str()); | ||
| 2387 | - return ret; | ||
| 2388 | - } | ||
| 2389 | - } | ||
| 2390 | - | ||
| 2391 | - return ret; | ||
| 2392 | -} | ||
| 2393 | - | ||
| 2394 | -void SrsSource::destroy_forwarders() | ||
| 2395 | -{ | ||
| 2396 | - std::vector<SrsForwarder*>::iterator it; | ||
| 2397 | - for (it = forwarders.begin(); it != forwarders.end(); ++it) { | ||
| 2398 | - SrsForwarder* forwarder = *it; | ||
| 2399 | - forwarder->on_unpublish(); | ||
| 2400 | - srs_freep(forwarder); | ||
| 2401 | - } | ||
| 2402 | - forwarders.clear(); | ||
| 2403 | -} | ||
| 2404 | - | ||
| 2405 | string SrsSource::get_curr_origin() | 2591 | string SrsSource::get_curr_origin() |
| 2406 | { | 2592 | { |
| 2407 | return play_edge->get_curr_origin(); | 2593 | return play_edge->get_curr_origin(); |
| @@ -53,6 +53,7 @@ class SrsEdgeProxyContext; | @@ -53,6 +53,7 @@ class SrsEdgeProxyContext; | ||
| 53 | class SrsMessageArray; | 53 | class SrsMessageArray; |
| 54 | class SrsNgExec; | 54 | class SrsNgExec; |
| 55 | class SrsConnection; | 55 | class SrsConnection; |
| 56 | +class SrsMessageHeader; | ||
| 56 | #ifdef SRS_AUTO_HLS | 57 | #ifdef SRS_AUTO_HLS |
| 57 | class SrsHls; | 58 | class SrsHls; |
| 58 | #endif | 59 | #endif |
| @@ -411,10 +412,128 @@ public: | @@ -411,10 +412,128 @@ public: | ||
| 411 | }; | 412 | }; |
| 412 | 413 | ||
| 413 | /** | 414 | /** |
| 415 | + * The hub for origin is a collection of utilities for origin only, | ||
| 416 | + * for example, DVR, HLS, Forward and Transcode are only available for origin, | ||
| 417 | + * they are meanless for edge server. | ||
| 418 | + */ | ||
| 419 | +class SrsOriginHub : public ISrsReloadHandler | ||
| 420 | +{ | ||
| 421 | +private: | ||
| 422 | + SrsSource* source; | ||
| 423 | + SrsRequest* req; | ||
| 424 | +private: | ||
| 425 | + // hls handler. | ||
| 426 | +#ifdef SRS_AUTO_HLS | ||
| 427 | + SrsHls* hls; | ||
| 428 | +#endif | ||
| 429 | + // dvr handler. | ||
| 430 | +#ifdef SRS_AUTO_DVR | ||
| 431 | + SrsDvr* dvr; | ||
| 432 | +#endif | ||
| 433 | + // transcoding handler. | ||
| 434 | +#ifdef SRS_AUTO_TRANSCODE | ||
| 435 | + SrsEncoder* encoder; | ||
| 436 | +#endif | ||
| 437 | +#ifdef SRS_AUTO_HDS | ||
| 438 | + // adobe hds(http dynamic streaming). | ||
| 439 | + SrsHds *hds; | ||
| 440 | +#endif | ||
| 441 | + // nginx-rtmp exec feature. | ||
| 442 | + SrsNgExec* ng_exec; | ||
| 443 | + // to forward stream to other servers | ||
| 444 | + std::vector<SrsForwarder*> forwarders; | ||
| 445 | +public: | ||
| 446 | + SrsOriginHub(SrsSource* s); | ||
| 447 | + virtual ~SrsOriginHub(); | ||
| 448 | +public: | ||
| 449 | + // Initialize the hub with source and request. | ||
| 450 | + // @param r The request object, managed by source. | ||
| 451 | + virtual int initialize(SrsRequest* r); | ||
| 452 | + // Dispose the hub, release utilities resource, | ||
| 453 | + // for example, delete all HLS pieces. | ||
| 454 | + virtual void dispose(); | ||
| 455 | + // Cycle the hub, process some regular events, | ||
| 456 | + // for example, dispose hls in cycle. | ||
| 457 | + virtual int cycle(); | ||
| 458 | +public: | ||
| 459 | + // When got a original metadata. | ||
| 460 | + virtual int on_original_metadata(SrsOnMetaDataPacket* metadata); | ||
| 461 | + // When got a parsed metadata. | ||
| 462 | + virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata); | ||
| 463 | + // When got a parsed audio packet. | ||
| 464 | + virtual int on_audio(SrsSharedPtrMessage* shared_audio); | ||
| 465 | + // When got a parsed video packet. | ||
| 466 | + virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header); | ||
| 467 | +public: | ||
| 468 | + // When start publish stream. | ||
| 469 | + virtual int on_publish(); | ||
| 470 | + // When stop publish stream. | ||
| 471 | + virtual void on_unpublish(); | ||
| 472 | +// for the tools callback | ||
| 473 | +public: | ||
| 474 | + // for the SrsForwarder to callback to request the sequence headers. | ||
| 475 | + virtual int on_forwarder_start(SrsForwarder* forwarder); | ||
| 476 | + // for the SrsHls to callback to request the sequence headers. | ||
| 477 | + virtual int on_hls_start(); | ||
| 478 | + // for the SrsDvr to callback to request the sequence headers. | ||
| 479 | + virtual int on_dvr_request_sh(); | ||
| 480 | +// interface ISrsReloadHandler | ||
| 481 | +public: | ||
| 482 | + virtual int on_reload_vhost_forward(std::string vhost); | ||
| 483 | + virtual int on_reload_vhost_hls(std::string vhost); | ||
| 484 | + virtual int on_reload_vhost_hds(std::string vhost); | ||
| 485 | + virtual int on_reload_vhost_dvr(std::string vhost); | ||
| 486 | + virtual int on_reload_vhost_transcode(std::string vhost); | ||
| 487 | + virtual int on_reload_vhost_exec(std::string vhost); | ||
| 488 | +private: | ||
| 489 | + virtual int create_forwarders(); | ||
| 490 | + virtual void destroy_forwarders(); | ||
| 491 | +}; | ||
| 492 | + | ||
| 493 | +/** | ||
| 494 | + * Each stream have optional meta(sps/pps in sequence header and metadata). | ||
| 495 | + * This class cache and update the meta. | ||
| 496 | + */ | ||
| 497 | +class SrsMetaCache | ||
| 498 | +{ | ||
| 499 | +private: | ||
| 500 | + SrsSharedPtrMessage* cache_metadata; | ||
| 501 | + // the cached video sequence header. | ||
| 502 | + SrsSharedPtrMessage* cache_sh_video; | ||
| 503 | + // the cached audio sequence header. | ||
| 504 | + SrsSharedPtrMessage* cache_sh_audio; | ||
| 505 | +public: | ||
| 506 | + SrsMetaCache(); | ||
| 507 | + virtual ~SrsMetaCache(); | ||
| 508 | +public: | ||
| 509 | + // Dispose the metadata cache. | ||
| 510 | + virtual void dispose(); | ||
| 511 | +public: | ||
| 512 | + // Get the cached metadata. | ||
| 513 | + virtual SrsSharedPtrMessage* data(); | ||
| 514 | + // Get the cached vsh(video sequence header). | ||
| 515 | + virtual SrsSharedPtrMessage* vsh(); | ||
| 516 | + // Get the cached ash(audio sequence header). | ||
| 517 | + virtual SrsSharedPtrMessage* ash(); | ||
| 518 | + // Dumps cached metadata to consumer. | ||
| 519 | + // @param dm Whether dumps the metadata. | ||
| 520 | + // @param ds Whether dumps the sequence header. | ||
| 521 | + virtual int dumps(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds); | ||
| 522 | +public: | ||
| 523 | + // Update the cached metadata by packet. | ||
| 524 | + virtual int update_data(SrsMessageHeader* header, SrsOnMetaDataPacket* metadata, bool& updated); | ||
| 525 | + // Update the cached audio sequence header. | ||
| 526 | + virtual void update_ash(SrsSharedPtrMessage* msg); | ||
| 527 | + // Update the cached video sequence header. | ||
| 528 | + virtual void update_vsh(SrsSharedPtrMessage* msg); | ||
| 529 | +}; | ||
| 530 | + | ||
| 531 | +/** | ||
| 414 | * live streaming source. | 532 | * live streaming source. |
| 415 | */ | 533 | */ |
| 416 | class SrsSource : public ISrsReloadHandler | 534 | class SrsSource : public ISrsReloadHandler |
| 417 | { | 535 | { |
| 536 | + friend class SrsOriginHub; | ||
| 418 | private: | 537 | private: |
| 419 | static std::map<std::string, SrsSource*> pool; | 538 | static std::map<std::string, SrsSource*> pool; |
| 420 | public: | 539 | public: |
| @@ -475,35 +594,19 @@ private: | @@ -475,35 +594,19 @@ private: | ||
| 475 | bool is_monotonically_increase; | 594 | bool is_monotonically_increase; |
| 476 | // the time of the packet we just got. | 595 | // the time of the packet we just got. |
| 477 | int64_t last_packet_time; | 596 | int64_t last_packet_time; |
| 478 | - // hls handler. | ||
| 479 | -#ifdef SRS_AUTO_HLS | ||
| 480 | - SrsHls* hls; | ||
| 481 | -#endif | ||
| 482 | - // dvr handler. | ||
| 483 | -#ifdef SRS_AUTO_DVR | ||
| 484 | - SrsDvr* dvr; | ||
| 485 | -#endif | ||
| 486 | - // transcoding handler. | ||
| 487 | -#ifdef SRS_AUTO_TRANSCODE | ||
| 488 | - SrsEncoder* encoder; | ||
| 489 | -#endif | ||
| 490 | -#ifdef SRS_AUTO_HDS | ||
| 491 | - // adobe hds(http dynamic streaming). | ||
| 492 | - SrsHds *hds; | ||
| 493 | -#endif | ||
| 494 | - // nginx-rtmp exec feature. | ||
| 495 | - SrsNgExec* ng_exec; | 597 | + // for aggregate message |
| 598 | + SrsBuffer* aggregate_stream; | ||
| 599 | + // the event handler. | ||
| 600 | + ISrsSourceHandler* handler; | ||
| 496 | // edge control service | 601 | // edge control service |
| 497 | SrsPlayEdge* play_edge; | 602 | SrsPlayEdge* play_edge; |
| 498 | SrsPublishEdge* publish_edge; | 603 | SrsPublishEdge* publish_edge; |
| 499 | // gop cache for client fast startup. | 604 | // gop cache for client fast startup. |
| 500 | SrsGopCache* gop_cache; | 605 | SrsGopCache* gop_cache; |
| 501 | - // to forward stream to other servers | ||
| 502 | - std::vector<SrsForwarder*> forwarders; | ||
| 503 | - // for aggregate message | ||
| 504 | - SrsBuffer* aggregate_stream; | ||
| 505 | - // the event handler. | ||
| 506 | - ISrsSourceHandler* handler; | 606 | + // The hub for origin server. |
| 607 | + SrsOriginHub* hub; | ||
| 608 | + // The metadata cache. | ||
| 609 | + SrsMetaCache* meta; | ||
| 507 | private: | 610 | private: |
| 508 | /** | 611 | /** |
| 509 | * can publish, true when is not streaming | 612 | * can publish, true when is not streaming |
| @@ -512,12 +615,6 @@ private: | @@ -512,12 +615,6 @@ private: | ||
| 512 | // last die time, when all consumers quit and no publisher, | 615 | // last die time, when all consumers quit and no publisher, |
| 513 | // we will remove the source when source die. | 616 | // we will remove the source when source die. |
| 514 | int64_t die_at; | 617 | int64_t die_at; |
| 515 | -private: | ||
| 516 | - SrsSharedPtrMessage* cache_metadata; | ||
| 517 | - // the cached video sequence header. | ||
| 518 | - SrsSharedPtrMessage* cache_sh_video; | ||
| 519 | - // the cached audio sequence header. | ||
| 520 | - SrsSharedPtrMessage* cache_sh_audio; | ||
| 521 | public: | 618 | public: |
| 522 | SrsSource(); | 619 | SrsSource(); |
| 523 | virtual ~SrsSource(); | 620 | virtual ~SrsSource(); |
| @@ -535,20 +632,8 @@ public: | @@ -535,20 +632,8 @@ public: | ||
| 535 | // interface ISrsReloadHandler | 632 | // interface ISrsReloadHandler |
| 536 | public: | 633 | public: |
| 537 | virtual int on_reload_vhost_play(std::string vhost); | 634 | virtual int on_reload_vhost_play(std::string vhost); |
| 538 | - virtual int on_reload_vhost_forward(std::string vhost); | ||
| 539 | - virtual int on_reload_vhost_hls(std::string vhost); | ||
| 540 | - virtual int on_reload_vhost_hds(std::string vhost); | ||
| 541 | - virtual int on_reload_vhost_dvr(std::string vhost); | ||
| 542 | - virtual int on_reload_vhost_transcode(std::string vhost); | ||
| 543 | - virtual int on_reload_vhost_exec(std::string vhost); | ||
| 544 | // for the tools callback | 635 | // for the tools callback |
| 545 | public: | 636 | public: |
| 546 | - // for the SrsForwarder to callback to request the sequence headers. | ||
| 547 | - virtual int on_forwarder_start(SrsForwarder* forwarder); | ||
| 548 | - // for the SrsHls to callback to request the sequence headers. | ||
| 549 | - virtual int on_hls_start(); | ||
| 550 | - // for the SrsDvr to callback to request the sequence headers. | ||
| 551 | - virtual int on_dvr_request_sh(); | ||
| 552 | // source id changed. | 637 | // source id changed. |
| 553 | virtual int on_source_id_changed(int id); | 638 | virtual int on_source_id_changed(int id); |
| 554 | // get current source id. | 639 | // get current source id. |
| @@ -599,9 +684,6 @@ public: | @@ -599,9 +684,6 @@ public: | ||
| 599 | virtual int on_edge_proxy_publish(SrsCommonMessage* msg); | 684 | virtual int on_edge_proxy_publish(SrsCommonMessage* msg); |
| 600 | // for edge, proxy stop publish | 685 | // for edge, proxy stop publish |
| 601 | virtual void on_edge_proxy_unpublish(); | 686 | virtual void on_edge_proxy_unpublish(); |
| 602 | -private: | ||
| 603 | - virtual int create_forwarders(); | ||
| 604 | - virtual void destroy_forwarders(); | ||
| 605 | public: | 687 | public: |
| 606 | virtual std::string get_curr_origin(); | 688 | virtual std::string get_curr_origin(); |
| 607 | }; | 689 | }; |
| @@ -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 3 | 32 | #define VERSION_MAJOR 3 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 15 | 34 | +#define VERSION_REVISION 16 |
| 35 | 35 | ||
| 36 | // generated by configure, only macros. | 36 | // generated by configure, only macros. |
| 37 | #include <srs_auto_headers.hpp> | 37 | #include <srs_auto_headers.hpp> |
-
请 注册 或 登录 后发表评论