winlin

extract http static and http stream from http conn.

@@ -169,11 +169,11 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then @@ -169,11 +169,11 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
169 MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL") 169 MODULE_DEPENDS=("CORE" "KERNEL" "PROTOCOL")
170 ModuleLibIncs=(${LibSTRoot} ${LibHttpParserRoot} ${SRS_OBJS_DIR}) 170 ModuleLibIncs=(${LibSTRoot} ${LibHttpParserRoot} ${SRS_OBJS_DIR})
171 MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_source" 171 MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_source"
172 - "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" 172 + "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" "srs_app_http_stream"
173 "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" 173 "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config"
174 "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" 174 "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
175 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" 175 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
176 - "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" 176 + "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
177 "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds" 177 "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
178 "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call" 178 "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
179 "srs_app_caster_flv") 179 "srs_app_caster_flv")
@@ -103,6 +103,10 @@ file @@ -103,6 +103,10 @@ file
103 ../../src/app/srs_app_http_conn.cpp, 103 ../../src/app/srs_app_http_conn.cpp,
104 ../../src/app/srs_app_http_hooks.hpp, 104 ../../src/app/srs_app_http_hooks.hpp,
105 ../../src/app/srs_app_http_hooks.cpp, 105 ../../src/app/srs_app_http_hooks.cpp,
  106 + ../../src/app/srs_app_http_stream.hpp,
  107 + ../../src/app/srs_app_http_stream.cpp,
  108 + ../../src/app/srs_app_http_static.hpp,
  109 + ../../src/app/srs_app_http_static.cpp,
106 ../../src/app/srs_app_ingest.hpp, 110 ../../src/app/srs_app_ingest.hpp,
107 ../../src/app/srs_app_ingest.cpp, 111 ../../src/app/srs_app_ingest.cpp,
108 ../../src/app/srs_app_json.hpp, 112 ../../src/app/srs_app_json.hpp,
@@ -77,6 +77,8 @@ @@ -77,6 +77,8 @@
77 <ClInclude Include="..\..\src\app\srs_app_http_api.hpp" /> 77 <ClInclude Include="..\..\src\app\srs_app_http_api.hpp" />
78 <ClInclude Include="..\..\src\app\srs_app_http_client.hpp" /> 78 <ClInclude Include="..\..\src\app\srs_app_http_client.hpp" />
79 <ClInclude Include="..\..\src\app\srs_app_http_conn.hpp" /> 79 <ClInclude Include="..\..\src\app\srs_app_http_conn.hpp" />
  80 + <ClInclude Include="..\..\src\app\srs_app_http_static.hpp" />
  81 + <ClInclude Include="..\..\src\app\srs_app_http_stream.hpp" />
80 <ClInclude Include="..\..\src\app\srs_app_http_hooks.hpp" /> 82 <ClInclude Include="..\..\src\app\srs_app_http_hooks.hpp" />
81 <ClInclude Include="..\..\src\app\srs_app_ingest.hpp" /> 83 <ClInclude Include="..\..\src\app\srs_app_ingest.hpp" />
82 <ClInclude Include="..\..\src\app\srs_app_json.hpp" /> 84 <ClInclude Include="..\..\src\app\srs_app_json.hpp" />
@@ -157,6 +159,8 @@ @@ -157,6 +159,8 @@
157 <ClCompile Include="..\..\src\app\srs_app_http_api.cpp" /> 159 <ClCompile Include="..\..\src\app\srs_app_http_api.cpp" />
158 <ClCompile Include="..\..\src\app\srs_app_http_client.cpp" /> 160 <ClCompile Include="..\..\src\app\srs_app_http_client.cpp" />
159 <ClCompile Include="..\..\src\app\srs_app_http_conn.cpp" /> 161 <ClCompile Include="..\..\src\app\srs_app_http_conn.cpp" />
  162 + <ClCompile Include="..\..\src\app\srs_app_http_static.cpp" />
  163 + <ClCompile Include="..\..\src\app\srs_app_http_stream.cpp" />
160 <ClCompile Include="..\..\src\app\srs_app_http_hooks.cpp" /> 164 <ClCompile Include="..\..\src\app\srs_app_http_hooks.cpp" />
161 <ClCompile Include="..\..\src\app\srs_app_ingest.cpp" /> 165 <ClCompile Include="..\..\src\app\srs_app_ingest.cpp" />
162 <ClCompile Include="..\..\src\app\srs_app_json.cpp" /> 166 <ClCompile Include="..\..\src\app\srs_app_json.cpp" />
@@ -64,6 +64,12 @@ @@ -64,6 +64,12 @@
64 <ClCompile Include="..\..\src\app\srs_app_http_conn.cpp"> 64 <ClCompile Include="..\..\src\app\srs_app_http_conn.cpp">
65 <Filter>srs</Filter> 65 <Filter>srs</Filter>
66 </ClCompile> 66 </ClCompile>
  67 + <ClCompile Include="..\..\src\app\srs_app_http_static.cpp">
  68 + <Filter>srs</Filter>
  69 + </ClCompile>
  70 + <ClCompile Include="..\..\src\app\srs_app_http_stream.cpp">
  71 + <Filter>srs</Filter>
  72 + </ClCompile>
67 <ClCompile Include="..\..\src\app\srs_app_http_hooks.cpp"> 73 <ClCompile Include="..\..\src\app\srs_app_http_hooks.cpp">
68 <Filter>srs</Filter> 74 <Filter>srs</Filter>
69 </ClCompile> 75 </ClCompile>
@@ -7,6 +7,8 @@ @@ -7,6 +7,8 @@
7 objects = { 7 objects = {
8 8
9 /* Begin PBXBuildFile section */ 9 /* Begin PBXBuildFile section */
  10 + 3C036B551B2D0AC10078E2E0 /* srs_app_http_static.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C036B511B2D0AC10078E2E0 /* srs_app_http_static.cpp */; };
  11 + 3C036B561B2D0AC10078E2E0 /* srs_app_http_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C036B531B2D0AC10078E2E0 /* srs_app_http_stream.cpp */; };
10 3C068D6A1B10149F00AA722C /* srs_protocol_kbps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */; }; 12 3C068D6A1B10149F00AA722C /* srs_protocol_kbps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */; };
11 3C068D6D1B10175500AA722C /* srs_protocol_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */; }; 13 3C068D6D1B10175500AA722C /* srs_protocol_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */; };
12 3C0E1B8D1B0F5ADF003ADEF7 /* srs_http_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C0E1B8B1B0F5ADF003ADEF7 /* srs_http_stack.cpp */; }; 14 3C0E1B8D1B0F5ADF003ADEF7 /* srs_http_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C0E1B8B1B0F5ADF003ADEF7 /* srs_http_stack.cpp */; };
@@ -121,6 +123,10 @@ @@ -121,6 +123,10 @@
121 /* End PBXCopyFilesBuildPhase section */ 123 /* End PBXCopyFilesBuildPhase section */
122 124
123 /* Begin PBXFileReference section */ 125 /* Begin PBXFileReference section */
  126 + 3C036B511B2D0AC10078E2E0 /* srs_app_http_static.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_static.cpp; path = ../../../src/app/srs_app_http_static.cpp; sourceTree = "<group>"; };
  127 + 3C036B521B2D0AC10078E2E0 /* srs_app_http_static.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_static.hpp; path = ../../../src/app/srs_app_http_static.hpp; sourceTree = "<group>"; };
  128 + 3C036B531B2D0AC10078E2E0 /* srs_app_http_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_http_stream.cpp; path = ../../../src/app/srs_app_http_stream.cpp; sourceTree = "<group>"; };
  129 + 3C036B541B2D0AC10078E2E0 /* srs_app_http_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_stream.hpp; path = ../../../src/app/srs_app_http_stream.hpp; sourceTree = "<group>"; };
124 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_kbps.cpp; path = ../../../src/protocol/srs_protocol_kbps.cpp; sourceTree = "<group>"; }; 130 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_kbps.cpp; path = ../../../src/protocol/srs_protocol_kbps.cpp; sourceTree = "<group>"; };
125 3C068D691B10149F00AA722C /* srs_protocol_kbps.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_kbps.hpp; path = ../../../src/protocol/srs_protocol_kbps.hpp; sourceTree = "<group>"; }; 131 3C068D691B10149F00AA722C /* srs_protocol_kbps.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_kbps.hpp; path = ../../../src/protocol/srs_protocol_kbps.hpp; sourceTree = "<group>"; };
126 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_buffer.cpp; path = ../../../src/protocol/srs_protocol_buffer.cpp; sourceTree = "<group>"; }; 132 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_buffer.cpp; path = ../../../src/protocol/srs_protocol_buffer.cpp; sourceTree = "<group>"; };
@@ -551,6 +557,10 @@ @@ -551,6 +557,10 @@
551 3C1232671AAE81D900CE8F6C /* srs_app_http_conn.hpp */, 557 3C1232671AAE81D900CE8F6C /* srs_app_http_conn.hpp */,
552 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */, 558 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */,
553 3C1232691AAE81D900CE8F6C /* srs_app_http_hooks.hpp */, 559 3C1232691AAE81D900CE8F6C /* srs_app_http_hooks.hpp */,
  560 + 3C036B511B2D0AC10078E2E0 /* srs_app_http_static.cpp */,
  561 + 3C036B521B2D0AC10078E2E0 /* srs_app_http_static.hpp */,
  562 + 3C036B531B2D0AC10078E2E0 /* srs_app_http_stream.cpp */,
  563 + 3C036B541B2D0AC10078E2E0 /* srs_app_http_stream.hpp */,
554 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */, 564 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */,
555 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */, 565 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */,
556 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */, 566 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */,
@@ -907,10 +917,12 @@ @@ -907,10 +917,12 @@
907 3C1232461AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp in Sources */, 917 3C1232461AAE81A400CE8F6C /* srs_rtmp_msg_array.cpp in Sources */,
908 3C1232A71AAE81D900CE8F6C /* srs_app_listener.cpp in Sources */, 918 3C1232A71AAE81D900CE8F6C /* srs_app_listener.cpp in Sources */,
909 3C1232261AAE814D00CE8F6C /* srs_kernel_flv.cpp in Sources */, 919 3C1232261AAE814D00CE8F6C /* srs_kernel_flv.cpp in Sources */,
  920 + 3C036B551B2D0AC10078E2E0 /* srs_app_http_static.cpp in Sources */,
910 3C663F1A1AB0155100286D8B /* srs_rtmp_dump.c in Sources */, 921 3C663F1A1AB0155100286D8B /* srs_rtmp_dump.c in Sources */,
911 3CE6CD311AE4AFB800706E07 /* srs_main_ingest_hls.cpp in Sources */, 922 3CE6CD311AE4AFB800706E07 /* srs_main_ingest_hls.cpp in Sources */,
912 3C28EDDF1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp in Sources */, 923 3C28EDDF1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp in Sources */,
913 3C1232241AAE814D00CE8F6C /* srs_kernel_error.cpp in Sources */, 924 3C1232241AAE814D00CE8F6C /* srs_kernel_error.cpp in Sources */,
  925 + 3C036B561B2D0AC10078E2E0 /* srs_app_http_stream.cpp in Sources */,
914 3C068D6D1B10175500AA722C /* srs_protocol_buffer.cpp in Sources */, 926 3C068D6D1B10175500AA722C /* srs_protocol_buffer.cpp in Sources */,
915 3C1232441AAE81A400CE8F6C /* srs_rtmp_handshake.cpp in Sources */, 927 3C1232441AAE81A400CE8F6C /* srs_rtmp_handshake.cpp in Sources */,
916 3C1232291AAE814D00CE8F6C /* srs_kernel_stream.cpp in Sources */, 928 3C1232291AAE814D00CE8F6C /* srs_kernel_stream.cpp in Sources */,
@@ -23,7 +23,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,7 +23,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_app_http_conn.hpp> 24 #include <srs_app_http_conn.hpp>
25 25
26 -#if defined(SRS_AUTO_HTTP_CORE) || defined(SRS_AUTO_HTTP_SERVER) 26 +#if defined(SRS_AUTO_HTTP_CORE)
27 27
28 #include <sys/types.h> 28 #include <sys/types.h>
29 #include <sys/stat.h> 29 #include <sys/stat.h>
@@ -52,6 +52,9 @@ using namespace std; @@ -52,6 +52,9 @@ using namespace std;
52 #include <srs_app_pithy_print.hpp> 52 #include <srs_app_pithy_print.hpp>
53 #include <srs_app_source.hpp> 53 #include <srs_app_source.hpp>
54 #include <srs_app_server.hpp> 54 #include <srs_app_server.hpp>
  55 +#include <srs_app_http_static.hpp>
  56 +#include <srs_app_http_stream.hpp>
  57 +#include <srs_app_http_api.hpp>
55 58
56 #endif 59 #endif
57 60
@@ -1094,1392 +1097,7 @@ string SrsHttpUri::get_uri_field(string uri, http_parser_url* hp_u, http_parser_ @@ -1094,1392 +1097,7 @@ string SrsHttpUri::get_uri_field(string uri, http_parser_url* hp_u, http_parser_
1094 return uri.substr(offset, len); 1097 return uri.substr(offset, len);
1095 } 1098 }
1096 1099
1097 -#endif  
1098 -  
1099 -#ifdef SRS_AUTO_HTTP_SERVER  
1100 -  
1101 -SrsVodStream::SrsVodStream(string root_dir)  
1102 - : SrsHttpFileServer(root_dir)  
1103 -{  
1104 -}  
1105 -  
1106 -SrsVodStream::~SrsVodStream()  
1107 -{  
1108 -}  
1109 -  
1110 -int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset)  
1111 -{  
1112 - int ret = ERROR_SUCCESS;  
1113 -  
1114 - SrsFileReader fs;  
1115 -  
1116 - // open flv file  
1117 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
1118 - return ret;  
1119 - }  
1120 -  
1121 - if (offset > fs.filesize()) {  
1122 - ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;  
1123 - srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d",  
1124 - fullpath.c_str(), fs.filesize(), offset, ret);  
1125 - return ret;  
1126 - }  
1127 -  
1128 - SrsFlvVodStreamDecoder ffd;  
1129 -  
1130 - // open fast decoder  
1131 - if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {  
1132 - return ret;  
1133 - }  
1134 -  
1135 - // save header, send later.  
1136 - char flv_header[13];  
1137 -  
1138 - // send flv header  
1139 - if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {  
1140 - return ret;  
1141 - }  
1142 -  
1143 - // save sequence header, send later  
1144 - char* sh_data = NULL;  
1145 - int sh_size = 0;  
1146 -  
1147 - if (true) {  
1148 - // send sequence header  
1149 - int64_t start = 0;  
1150 - if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {  
1151 - return ret;  
1152 - }  
1153 - if (sh_size <= 0) {  
1154 - ret = ERROR_HTTP_REMUX_SEQUENCE_HEADER;  
1155 - srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret);  
1156 - return ret;  
1157 - }  
1158 - }  
1159 - sh_data = new char[sh_size];  
1160 - SrsAutoFree(char, sh_data);  
1161 - if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {  
1162 - return ret;  
1163 - }  
1164 -  
1165 - // seek to data offset  
1166 - int64_t left = fs.filesize() - offset;  
1167 -  
1168 - // write http header for ts.  
1169 - w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left));  
1170 - w->header()->set_content_type("video/x-flv");  
1171 -  
1172 - // write flv header and sequence header.  
1173 - if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) {  
1174 - return ret;  
1175 - }  
1176 - if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) {  
1177 - return ret;  
1178 - }  
1179 -  
1180 - // write body.  
1181 - if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {  
1182 - return ret;  
1183 - }  
1184 -  
1185 - // send data  
1186 - if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {  
1187 - srs_warn("read flv=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);  
1188 - return ret;  
1189 - }  
1190 -  
1191 - return ret;  
1192 -}  
1193 -  
1194 -int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end)  
1195 -{  
1196 - int ret = ERROR_SUCCESS;  
1197 -  
1198 - srs_assert(start >= 0);  
1199 - srs_assert(end == -1 || end >= 0);  
1200 -  
1201 - SrsFileReader fs;  
1202 -  
1203 - // open flv file  
1204 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
1205 - return ret;  
1206 - }  
1207 -  
1208 - // parse -1 to whole file.  
1209 - if (end == -1) {  
1210 - end = (int)fs.filesize();  
1211 - }  
1212 -  
1213 - if (end > fs.filesize() || start > end) {  
1214 - ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;  
1215 - srs_warn("http mp4 streaming %s overflow. size=%"PRId64", offset=%d, ret=%d",  
1216 - fullpath.c_str(), fs.filesize(), start, ret);  
1217 - return ret;  
1218 - }  
1219 -  
1220 - // seek to data offset, [start, end] for range.  
1221 - int64_t left = end - start + 1;  
1222 -  
1223 - // write http header for ts.  
1224 - w->header()->set_content_length(left);  
1225 - w->header()->set_content_type("video/mp4");  
1226 -  
1227 - // status code 206 to make dash.as happy.  
1228 - w->write_header(SRS_CONSTS_HTTP_PartialContent);  
1229 -  
1230 - // response the content range header.  
1231 - std::stringstream content_range;  
1232 - content_range << "bytes " << start << "-" << end << "/" << fs.filesize();  
1233 - w->header()->set("Content-Range", content_range.str());  
1234 -  
1235 - // write body.  
1236 - fs.lseek(start);  
1237 -  
1238 - // send data  
1239 - if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {  
1240 - srs_warn("read mp4=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);  
1241 - return ret;  
1242 - }  
1243 -  
1244 - return ret;  
1245 -}  
1246 -  
1247 -SrsStreamCache::SrsStreamCache(SrsSource* s, SrsRequest* r)  
1248 -{  
1249 - req = r->copy();  
1250 - source = s;  
1251 - queue = new SrsMessageQueue(true);  
1252 - pthread = new SrsEndlessThread("http-stream", this);  
1253 -}  
1254 -  
1255 -SrsStreamCache::~SrsStreamCache()  
1256 -{  
1257 - srs_freep(pthread);  
1258 -  
1259 - srs_freep(queue);  
1260 - srs_freep(req);  
1261 -}  
1262 -  
1263 -int SrsStreamCache::start()  
1264 -{  
1265 - return pthread->start();  
1266 -}  
1267 -  
1268 -int SrsStreamCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)  
1269 -{  
1270 - int ret = ERROR_SUCCESS;  
1271 -  
1272 - double fast_cache = _srs_config->get_vhost_http_remux_fast_cache(req->vhost);  
1273 -  
1274 - if (fast_cache <= 0) {  
1275 - srs_info("http: ignore dump fast cache.");  
1276 - return ret;  
1277 - }  
1278 -  
1279 - // the jitter is get from SrsSource, which means the time_jitter of vhost.  
1280 - if ((ret = queue->dump_packets(consumer, false, jitter)) != ERROR_SUCCESS) {  
1281 - return ret;  
1282 - }  
1283 -  
1284 - srs_trace("http: dump cache %d msgs, duration=%dms, cache=%.2fs",  
1285 - queue->size(), queue->duration(), fast_cache);  
1286 -  
1287 - return ret;  
1288 -}  
1289 -  
1290 -int SrsStreamCache::cycle()  
1291 -{  
1292 - int ret = ERROR_SUCCESS;  
1293 -  
1294 - SrsConsumer* consumer = NULL;  
1295 - if ((ret = source->create_consumer(consumer, false, false, true)) != ERROR_SUCCESS) {  
1296 - srs_error("http: create consumer failed. ret=%d", ret);  
1297 - return ret;  
1298 - }  
1299 - SrsAutoFree(SrsConsumer, consumer);  
1300 -  
1301 - SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream_cache();  
1302 - SrsAutoFree(SrsPithyPrint, pprint);  
1303 -  
1304 - SrsMessageArray msgs(SRS_PERF_MW_MSGS);  
1305 -  
1306 - // TODO: FIXME: support reload.  
1307 - double fast_cache = _srs_config->get_vhost_http_remux_fast_cache(req->vhost);  
1308 - if (fast_cache > 0) {  
1309 - queue->set_queue_size(fast_cache);  
1310 - }  
1311 -  
1312 - while (true) {  
1313 - pprint->elapse();  
1314 -  
1315 - // get messages from consumer.  
1316 - // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.  
1317 - int count = 0;  
1318 - if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) {  
1319 - srs_error("http: get messages from consumer failed. ret=%d", ret);  
1320 - return ret;  
1321 - }  
1322 -  
1323 - if (count <= 0) {  
1324 - srs_info("http: mw sleep %dms for no msg", mw_sleep);  
1325 - // directly use sleep, donot use consumer wait.  
1326 - st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);  
1327 -  
1328 - // ignore when nothing got.  
1329 - continue;  
1330 - }  
1331 -  
1332 - if (pprint->can_print()) {  
1333 - srs_trace("-> "SRS_CONSTS_LOG_HTTP_STREAM_CACHE" http: got %d msgs, age=%d, min=%d, mw=%d",  
1334 - count, pprint->age(), SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000);  
1335 - }  
1336 -  
1337 - // free the messages.  
1338 - for (int i = 0; i < count; i++) {  
1339 - SrsSharedPtrMessage* msg = msgs.msgs[i];  
1340 - if (fast_cache > 0) {  
1341 - queue->enqueue(msg);  
1342 - } else {  
1343 - srs_freep(msg);  
1344 - }  
1345 - }  
1346 - }  
1347 -  
1348 - return ret;  
1349 -}  
1350 -  
1351 -ISrsStreamEncoder::ISrsStreamEncoder()  
1352 -{  
1353 -}  
1354 -  
1355 -ISrsStreamEncoder::~ISrsStreamEncoder()  
1356 -{  
1357 -}  
1358 -  
1359 -SrsTsStreamEncoder::SrsTsStreamEncoder()  
1360 -{  
1361 - enc = new SrsTsEncoder();  
1362 -}  
1363 -  
1364 -SrsTsStreamEncoder::~SrsTsStreamEncoder()  
1365 -{  
1366 - srs_freep(enc);  
1367 -}  
1368 -  
1369 -int SrsTsStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* /*c*/)  
1370 -{  
1371 - int ret = ERROR_SUCCESS;  
1372 -  
1373 - if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {  
1374 - return ret;  
1375 - }  
1376 -  
1377 - return ret;  
1378 -}  
1379 -  
1380 -int SrsTsStreamEncoder::write_audio(int64_t timestamp, char* data, int size)  
1381 -{  
1382 - return enc->write_audio(timestamp, data, size);  
1383 -}  
1384 -  
1385 -int SrsTsStreamEncoder::write_video(int64_t timestamp, char* data, int size)  
1386 -{  
1387 - return enc->write_video(timestamp, data, size);  
1388 -}  
1389 -  
1390 -int SrsTsStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)  
1391 -{  
1392 - return ERROR_SUCCESS;  
1393 -}  
1394 -  
1395 -bool SrsTsStreamEncoder::has_cache()  
1396 -{  
1397 - // for ts stream, use gop cache of SrsSource is ok.  
1398 - return false;  
1399 -}  
1400 -  
1401 -int SrsTsStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)  
1402 -{  
1403 - // for ts stream, ignore cache.  
1404 - return ERROR_SUCCESS;  
1405 -}  
1406 -  
1407 -SrsFlvStreamEncoder::SrsFlvStreamEncoder()  
1408 -{  
1409 - enc = new SrsFlvEncoder();  
1410 -}  
1411 -  
1412 -SrsFlvStreamEncoder::~SrsFlvStreamEncoder()  
1413 -{  
1414 - srs_freep(enc);  
1415 -}  
1416 -  
1417 -int SrsFlvStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* /*c*/)  
1418 -{  
1419 - int ret = ERROR_SUCCESS;  
1420 -  
1421 - if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {  
1422 - return ret;  
1423 - }  
1424 -  
1425 - // write flv header.  
1426 - if ((ret = enc->write_header()) != ERROR_SUCCESS) {  
1427 - return ret;  
1428 - }  
1429 -  
1430 - return ret;  
1431 -}  
1432 -  
1433 -int SrsFlvStreamEncoder::write_audio(int64_t timestamp, char* data, int size)  
1434 -{  
1435 - return enc->write_audio(timestamp, data, size);  
1436 -}  
1437 -  
1438 -int SrsFlvStreamEncoder::write_video(int64_t timestamp, char* data, int size)  
1439 -{  
1440 - return enc->write_video(timestamp, data, size);  
1441 -}  
1442 -  
1443 -int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size)  
1444 -{  
1445 - return enc->write_metadata(SrsCodecFlvTagScript, data, size);  
1446 -}  
1447 -  
1448 -bool SrsFlvStreamEncoder::has_cache()  
1449 -{  
1450 - // for flv stream, use gop cache of SrsSource is ok.  
1451 - return false;  
1452 -}  
1453 -  
1454 -int SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)  
1455 -{  
1456 - // for flv stream, ignore cache.  
1457 - return ERROR_SUCCESS;  
1458 -}  
1459 -  
1460 -#ifdef SRS_PERF_FAST_FLV_ENCODER  
1461 -SrsFastFlvStreamEncoder::SrsFastFlvStreamEncoder()  
1462 -{  
1463 -}  
1464 -  
1465 -SrsFastFlvStreamEncoder::~SrsFastFlvStreamEncoder()  
1466 -{  
1467 -}  
1468 -  
1469 -int SrsFastFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count)  
1470 -{  
1471 - return enc->write_tags(msgs, count);  
1472 -}  
1473 -#endif  
1474 -  
1475 -SrsAacStreamEncoder::SrsAacStreamEncoder()  
1476 -{  
1477 - enc = new SrsAacEncoder();  
1478 - cache = NULL;  
1479 -}  
1480 -  
1481 -SrsAacStreamEncoder::~SrsAacStreamEncoder()  
1482 -{  
1483 - srs_freep(enc);  
1484 -}  
1485 -  
1486 -int SrsAacStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)  
1487 -{  
1488 - int ret = ERROR_SUCCESS;  
1489 -  
1490 - cache = c;  
1491 -  
1492 - if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {  
1493 - return ret;  
1494 - }  
1495 -  
1496 - return ret;  
1497 -}  
1498 -  
1499 -int SrsAacStreamEncoder::write_audio(int64_t timestamp, char* data, int size)  
1500 -{  
1501 - return enc->write_audio(timestamp, data, size);  
1502 -}  
1503 -  
1504 -int SrsAacStreamEncoder::write_video(int64_t /*timestamp*/, char* /*data*/, int /*size*/)  
1505 -{  
1506 - // aac ignore any flv video.  
1507 - return ERROR_SUCCESS;  
1508 -}  
1509 -  
1510 -int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)  
1511 -{  
1512 - // aac ignore any flv metadata.  
1513 - return ERROR_SUCCESS;  
1514 -}  
1515 -  
1516 -bool SrsAacStreamEncoder::has_cache()  
1517 -{  
1518 - return true;  
1519 -}  
1520 -  
1521 -int SrsAacStreamEncoder::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)  
1522 -{  
1523 - srs_assert(cache);  
1524 - return cache->dump_cache(consumer, jitter);  
1525 -}  
1526 -  
1527 -SrsMp3StreamEncoder::SrsMp3StreamEncoder()  
1528 -{  
1529 - enc = new SrsMp3Encoder();  
1530 - cache = NULL;  
1531 -}  
1532 -  
1533 -SrsMp3StreamEncoder::~SrsMp3StreamEncoder()  
1534 -{  
1535 - srs_freep(enc);  
1536 -}  
1537 -  
1538 -int SrsMp3StreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)  
1539 -{  
1540 - int ret = ERROR_SUCCESS;  
1541 -  
1542 - cache = c;  
1543 -  
1544 - if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {  
1545 - return ret;  
1546 - }  
1547 -  
1548 - if ((ret = enc->write_header()) != ERROR_SUCCESS) {  
1549 - return ret;  
1550 - }  
1551 -  
1552 - return ret;  
1553 -}  
1554 -  
1555 -int SrsMp3StreamEncoder::write_audio(int64_t timestamp, char* data, int size)  
1556 -{  
1557 - return enc->write_audio(timestamp, data, size);  
1558 -}  
1559 -  
1560 -int SrsMp3StreamEncoder::write_video(int64_t /*timestamp*/, char* /*data*/, int /*size*/)  
1561 -{  
1562 - // mp3 ignore any flv video.  
1563 - return ERROR_SUCCESS;  
1564 -}  
1565 -  
1566 -int SrsMp3StreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)  
1567 -{  
1568 - // mp3 ignore any flv metadata.  
1569 - return ERROR_SUCCESS;  
1570 -}  
1571 -  
1572 -bool SrsMp3StreamEncoder::has_cache()  
1573 -{  
1574 - return true;  
1575 -}  
1576 -  
1577 -int SrsMp3StreamEncoder::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)  
1578 -{  
1579 - srs_assert(cache);  
1580 - return cache->dump_cache(consumer, jitter);  
1581 -}  
1582 -  
1583 -SrsStreamWriter::SrsStreamWriter(ISrsHttpResponseWriter* w)  
1584 -{  
1585 - writer = w;  
1586 -}  
1587 -  
1588 -SrsStreamWriter::~SrsStreamWriter()  
1589 -{  
1590 -}  
1591 -  
1592 -int SrsStreamWriter::open(std::string /*file*/)  
1593 -{  
1594 - return ERROR_SUCCESS;  
1595 -}  
1596 -  
1597 -void SrsStreamWriter::close()  
1598 -{  
1599 -}  
1600 -  
1601 -bool SrsStreamWriter::is_open()  
1602 -{  
1603 - return true;  
1604 -}  
1605 -  
1606 -int64_t SrsStreamWriter::tellg()  
1607 -{  
1608 - return 0;  
1609 -}  
1610 -  
1611 -int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)  
1612 -{  
1613 - if (pnwrite) {  
1614 - *pnwrite = count;  
1615 - }  
1616 - return writer->write((char*)buf, (int)count);  
1617 -}  
1618 -  
1619 -int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)  
1620 -{  
1621 - return writer->writev(iov, iovcnt, pnwrite);  
1622 -}  
1623 -  
1624 -SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)  
1625 -{  
1626 - source = s;  
1627 - cache = c;  
1628 - req = r->copy();  
1629 -}  
1630 -  
1631 -SrsLiveStream::~SrsLiveStream()  
1632 -{  
1633 - srs_freep(req);  
1634 -}  
1635 -  
1636 -int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)  
1637 -{  
1638 - int ret = ERROR_SUCCESS;  
1639 -  
1640 - ISrsStreamEncoder* enc = NULL;  
1641 -  
1642 - srs_assert(entry);  
1643 - if (srs_string_ends_with(entry->pattern, ".flv")) {  
1644 - w->header()->set_content_type("video/x-flv");  
1645 -#ifdef SRS_PERF_FAST_FLV_ENCODER  
1646 - enc = new SrsFastFlvStreamEncoder();  
1647 -#else  
1648 - enc = new SrsFlvStreamEncoder();  
1649 -#endif  
1650 - } else if (srs_string_ends_with(entry->pattern, ".aac")) {  
1651 - w->header()->set_content_type("audio/x-aac");  
1652 - enc = new SrsAacStreamEncoder();  
1653 - } else if (srs_string_ends_with(entry->pattern, ".mp3")) {  
1654 - w->header()->set_content_type("audio/mpeg");  
1655 - enc = new SrsMp3StreamEncoder();  
1656 - } else if (srs_string_ends_with(entry->pattern, ".ts")) {  
1657 - w->header()->set_content_type("video/MP2T");  
1658 - enc = new SrsTsStreamEncoder();  
1659 - } else {  
1660 - ret = ERROR_HTTP_LIVE_STREAM_EXT;  
1661 - srs_error("http: unsupported pattern %s", entry->pattern.c_str());  
1662 - return ret;  
1663 - }  
1664 - SrsAutoFree(ISrsStreamEncoder, enc);  
1665 -  
1666 - // create consumer of souce, ignore gop cache, use the audio gop cache.  
1667 - SrsConsumer* consumer = NULL;  
1668 - if ((ret = source->create_consumer(consumer, true, true, !enc->has_cache())) != ERROR_SUCCESS) {  
1669 - srs_error("http: create consumer failed. ret=%d", ret);  
1670 - return ret;  
1671 - }  
1672 - SrsAutoFree(SrsConsumer, consumer);  
1673 - srs_verbose("http: consumer created success.");  
1674 -  
1675 - SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream();  
1676 - SrsAutoFree(SrsPithyPrint, pprint);  
1677 -  
1678 - SrsMessageArray msgs(SRS_PERF_MW_MSGS);  
1679 -  
1680 - // the memory writer.  
1681 - SrsStreamWriter writer(w);  
1682 - if ((ret = enc->initialize(&writer, cache)) != ERROR_SUCCESS) {  
1683 - srs_error("http: initialize stream encoder failed. ret=%d", ret);  
1684 - return ret;  
1685 - }  
1686 -  
1687 - // if gop cache enabled for encoder, dump to consumer.  
1688 - if (enc->has_cache()) {  
1689 - if ((ret = enc->dump_cache(consumer, source->jitter())) != ERROR_SUCCESS) {  
1690 - srs_error("http: dump cache to consumer failed. ret=%d", ret);  
1691 - return ret;  
1692 - }  
1693 - }  
1694 -  
1695 -#ifdef SRS_PERF_FAST_FLV_ENCODER  
1696 - SrsFastFlvStreamEncoder* ffe = dynamic_cast<SrsFastFlvStreamEncoder*>(enc);  
1697 -#endif  
1698 -  
1699 - while (true) {  
1700 - pprint->elapse();  
1701 -  
1702 - // get messages from consumer.  
1703 - // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.  
1704 - int count = 0;  
1705 - if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) {  
1706 - srs_error("http: get messages from consumer failed. ret=%d", ret);  
1707 - return ret;  
1708 - }  
1709 -  
1710 - if (count <= 0) {  
1711 - srs_info("http: mw sleep %dms for no msg", mw_sleep);  
1712 - // directly use sleep, donot use consumer wait.  
1713 - st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);  
1714 -  
1715 - // ignore when nothing got.  
1716 - continue;  
1717 - }  
1718 -  
1719 - if (pprint->can_print()) {  
1720 - srs_info("-> "SRS_CONSTS_LOG_HTTP_STREAM" http: got %d msgs, age=%d, min=%d, mw=%d",  
1721 - count, pprint->age(), SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000);  
1722 - }  
1723 -  
1724 - // sendout all messages.  
1725 -#ifdef SRS_PERF_FAST_FLV_ENCODER  
1726 - if (ffe) {  
1727 - ret = ffe->write_tags(msgs.msgs, count);  
1728 - } else {  
1729 - ret = streaming_send_messages(enc, msgs.msgs, count);  
1730 - }  
1731 -#else  
1732 - ret = streaming_send_messages(enc, msgs.msgs, count);  
1733 -#endif  
1734 -  
1735 - // free the messages.  
1736 - for (int i = 0; i < count; i++) {  
1737 - SrsSharedPtrMessage* msg = msgs.msgs[i];  
1738 - srs_freep(msg);  
1739 - }  
1740 -  
1741 - // check send error code.  
1742 - if (ret != ERROR_SUCCESS) {  
1743 - if (!srs_is_client_gracefully_close(ret)) {  
1744 - srs_error("http: send messages to client failed. ret=%d", ret);  
1745 - }  
1746 - return ret;  
1747 - }  
1748 - }  
1749 -  
1750 - return ret;  
1751 -}  
1752 -  
1753 -int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs)  
1754 -{  
1755 - int ret = ERROR_SUCCESS;  
1756 -  
1757 - for (int i = 0; i < nb_msgs; i++) {  
1758 - SrsSharedPtrMessage* msg = msgs[i];  
1759 -  
1760 - if (msg->is_audio()) {  
1761 - ret = enc->write_audio(msg->timestamp, msg->payload, msg->size);  
1762 - } else if (msg->is_video()) {  
1763 - ret = enc->write_video(msg->timestamp, msg->payload, msg->size);  
1764 - } else {  
1765 - ret = enc->write_metadata(msg->timestamp, msg->payload, msg->size);  
1766 - }  
1767 -  
1768 - if (ret != ERROR_SUCCESS) {  
1769 - return ret;  
1770 - }  
1771 - }  
1772 -  
1773 - return ret;  
1774 -}  
1775 -  
1776 -SrsLiveEntry::SrsLiveEntry(std::string m, bool h)  
1777 -{  
1778 - mount = m;  
1779 - hstrs = h;  
1780 -  
1781 - stream = NULL;  
1782 - cache = NULL;  
1783 -  
1784 - std::string ext;  
1785 - size_t pos = string::npos;  
1786 - if ((pos = m.rfind(".")) != string::npos) {  
1787 - ext = m.substr(pos);  
1788 - }  
1789 - _is_flv = (ext == ".flv");  
1790 - _is_ts = (ext == ".ts");  
1791 - _is_mp3 = (ext == ".mp3");  
1792 - _is_aac = (ext == ".aac");  
1793 -}  
1794 -  
1795 -bool SrsLiveEntry::is_flv()  
1796 -{  
1797 - return _is_flv;  
1798 -}  
1799 -  
1800 -bool SrsLiveEntry::is_ts()  
1801 -{  
1802 - return _is_ts;  
1803 -}  
1804 -  
1805 -bool SrsLiveEntry::is_aac()  
1806 -{  
1807 - return _is_aac;  
1808 -}  
1809 -  
1810 -bool SrsLiveEntry::is_mp3()  
1811 -{  
1812 - return _is_mp3;  
1813 -}  
1814 -  
1815 -SrsHlsM3u8Stream::SrsHlsM3u8Stream()  
1816 -{  
1817 -}  
1818 -  
1819 -SrsHlsM3u8Stream::~SrsHlsM3u8Stream()  
1820 -{  
1821 -}  
1822 -  
1823 -void SrsHlsM3u8Stream::set_m3u8(std::string v)  
1824 -{  
1825 - m3u8 = v;  
1826 -}  
1827 -  
1828 -int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)  
1829 -{  
1830 - int ret = ERROR_SUCCESS;  
1831 -  
1832 - std::string data = m3u8;  
1833 -  
1834 - w->header()->set_content_length((int)data.length());  
1835 - w->header()->set_content_type("application/x-mpegURL;charset=utf-8");  
1836 -  
1837 - if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {  
1838 - if (!srs_is_client_gracefully_close(ret)) {  
1839 - srs_error("send m3u8 failed. ret=%d", ret);  
1840 - }  
1841 - return ret;  
1842 - }  
1843 -  
1844 - return ret;  
1845 -}  
1846 -  
1847 -SrsHlsTsStream::SrsHlsTsStream()  
1848 -{  
1849 -}  
1850 -  
1851 -SrsHlsTsStream::~SrsHlsTsStream()  
1852 -{  
1853 -}  
1854 -  
1855 -void SrsHlsTsStream::set_ts(std::string v)  
1856 -{  
1857 - ts = v;  
1858 -}  
1859 -  
1860 -int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)  
1861 -{  
1862 - int ret = ERROR_SUCCESS;  
1863 -  
1864 - std::string data = ts;  
1865 -  
1866 - w->header()->set_content_length((int)data.length());  
1867 - w->header()->set_content_type("video/MP2T");  
1868 -  
1869 - if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {  
1870 - if (!srs_is_client_gracefully_close(ret)) {  
1871 - srs_error("send ts failed. ret=%d", ret);  
1872 - }  
1873 - return ret;  
1874 - }  
1875 -  
1876 - return ret;  
1877 -}  
1878 -  
1879 -SrsHlsEntry::SrsHlsEntry()  
1880 -{  
1881 - tmpl = NULL;  
1882 -}  
1883 -  
1884 -SrsHttpServer::SrsHttpServer(SrsServer* svr)  
1885 -{  
1886 - server = svr;  
1887 -  
1888 - mux.hijack(this);  
1889 -}  
1890 -  
1891 -SrsHttpServer::~SrsHttpServer()  
1892 -{  
1893 - mux.unhijack(this);  
1894 -  
1895 - if (true) {  
1896 - std::map<std::string, SrsLiveEntry*>::iterator it;  
1897 - for (it = tflvs.begin(); it != tflvs.end(); ++it) {  
1898 - SrsLiveEntry* entry = it->second;  
1899 - srs_freep(entry);  
1900 - }  
1901 - tflvs.clear();  
1902 - }  
1903 - if (true) {  
1904 - std::map<std::string, SrsLiveEntry*>::iterator it;  
1905 - for (it = sflvs.begin(); it != sflvs.end(); ++it) {  
1906 - SrsLiveEntry* entry = it->second;  
1907 - srs_freep(entry);  
1908 - }  
1909 - sflvs.clear();  
1910 - }  
1911 - if (true) {  
1912 - std::map<std::string, SrsHlsEntry*>::iterator it;  
1913 - for (it = thls.begin(); it != thls.end(); ++it) {  
1914 - SrsHlsEntry* entry = it->second;  
1915 - srs_freep(entry);  
1916 - }  
1917 - thls.clear();  
1918 - }  
1919 - if (true) {  
1920 - std::map<std::string, SrsHlsEntry*>::iterator it;  
1921 - for (it = shls.begin(); it != shls.end(); ++it) {  
1922 - SrsHlsEntry* entry = it->second;  
1923 - srs_freep(entry);  
1924 - }  
1925 - shls.clear();  
1926 - }  
1927 -}  
1928 -  
1929 -int SrsHttpServer::initialize()  
1930 -{  
1931 - int ret = ERROR_SUCCESS;  
1932 -  
1933 - // static file  
1934 - // flv vod streaming.  
1935 - if ((ret = initialize_static_file()) != ERROR_SUCCESS) {  
1936 - return ret;  
1937 - }  
1938 -  
1939 - // remux rtmp to flv live streaming  
1940 - if ((ret = initialize_flv_streaming()) != ERROR_SUCCESS) {  
1941 - return ret;  
1942 - }  
1943 -  
1944 - // remux rtmp to hls live streaming  
1945 - if ((ret = initialize_hls_streaming()) != ERROR_SUCCESS) {  
1946 - return ret;  
1947 - }  
1948 -  
1949 - return ret;  
1950 -}  
1951 -  
1952 -// TODO: FIXME: rename for HTTP FLV mount.  
1953 -int SrsHttpServer::http_mount(SrsSource* s, SrsRequest* r)  
1954 -{  
1955 - int ret = ERROR_SUCCESS;  
1956 -  
1957 - // the id to identify stream.  
1958 - std::string sid = r->get_stream_url();  
1959 - SrsLiveEntry* entry = NULL;  
1960 -  
1961 - // create stream from template when not found.  
1962 - if (sflvs.find(sid) == sflvs.end()) {  
1963 - if (tflvs.find(r->vhost) == tflvs.end()) {  
1964 - srs_info("ignore mount flv stream for disabled");  
1965 - return ret;  
1966 - }  
1967 -  
1968 - SrsLiveEntry* tmpl = tflvs[r->vhost];  
1969 -  
1970 - std::string mount = tmpl->mount;  
1971 -  
1972 - // replace the vhost variable  
1973 - mount = srs_string_replace(mount, "[vhost]", r->vhost);  
1974 - mount = srs_string_replace(mount, "[app]", r->app);  
1975 - mount = srs_string_replace(mount, "[stream]", r->stream);  
1976 -  
1977 - // remove the default vhost mount  
1978 - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");  
1979 -  
1980 - entry = new SrsLiveEntry(mount, tmpl->hstrs);  
1981 -  
1982 - entry->cache = new SrsStreamCache(s, r);  
1983 - entry->stream = new SrsLiveStream(s, r, entry->cache);  
1984 -  
1985 - sflvs[sid] = entry;  
1986 -  
1987 - // mount the http flv stream.  
1988 - // we must register the handler, then start the thread,  
1989 - // for the thread will cause thread switch context.  
1990 - // @see https://github.com/simple-rtmp-server/srs/issues/404  
1991 - if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) {  
1992 - srs_error("http: mount flv stream for vhost=%s failed. ret=%d", sid.c_str(), ret);  
1993 - return ret;  
1994 - }  
1995 -  
1996 - // start http stream cache thread  
1997 - if ((ret = entry->cache->start()) != ERROR_SUCCESS) {  
1998 - srs_error("http: start stream cache failed. ret=%d", ret);  
1999 - return ret;  
2000 - }  
2001 - srs_trace("http: mount flv stream for vhost=%s, mount=%s", sid.c_str(), mount.c_str());  
2002 - } else {  
2003 - entry = sflvs[sid];  
2004 - }  
2005 -  
2006 - // TODO: FIXME: supports reload.  
2007 - if (entry->stream) {  
2008 - entry->stream->entry->enabled = true;  
2009 - return ret;  
2010 - }  
2011 -  
2012 - return ret;  
2013 -}  
2014 -  
2015 -void SrsHttpServer::http_unmount(SrsSource* s, SrsRequest* r)  
2016 -{  
2017 - std::string sid = r->get_stream_url();  
2018 -  
2019 - if (sflvs.find(sid) == sflvs.end()) {  
2020 - srs_info("ignore unmount flv stream for disabled");  
2021 - return;  
2022 - }  
2023 -  
2024 - SrsLiveEntry* entry = sflvs[sid];  
2025 - entry->stream->entry->enabled = false;  
2026 -}  
2027 -  
2028 -int SrsHttpServer::mount_hls(SrsRequest* r)  
2029 -{  
2030 - int ret = ERROR_SUCCESS;  
2031 -  
2032 - std::string sid = r->get_stream_url();  
2033 -  
2034 - if (shls.find(sid) == shls.end()) {  
2035 - srs_info("ignore mount hls stream for disabled");  
2036 - return ret;  
2037 - }  
2038 -  
2039 - SrsHlsEntry* entry = shls[sid];  
2040 -  
2041 - // TODO: FIXME: supports reload.  
2042 - std::map<std::string, ISrsHttpHandler*>::iterator it;  
2043 - for (it = entry->streams.begin(); it != entry->streams.end(); ++it) {  
2044 - ISrsHttpHandler* stream = it->second;  
2045 - stream->entry->enabled = true;  
2046 - }  
2047 -  
2048 - return ret;  
2049 -}  
2050 -  
2051 -int SrsHttpServer::hls_update_m3u8(SrsRequest* r, string m3u8)  
2052 -{  
2053 - int ret = ERROR_SUCCESS;  
2054 -  
2055 - std::string mount;  
2056 -  
2057 - std::string sid = r->get_stream_url();  
2058 - SrsHlsEntry* entry = NULL;  
2059 -  
2060 - // create stream from template when not found.  
2061 - if (shls.find(sid) == shls.end()) {  
2062 - if (thls.find(r->vhost) == thls.end()) {  
2063 - srs_info("ignore mount hls stream for disabled");  
2064 - return ret;  
2065 - }  
2066 -  
2067 - SrsHlsEntry* tmpl = thls[r->vhost];  
2068 - srs_assert(tmpl);  
2069 -  
2070 - entry = new SrsHlsEntry();  
2071 - mount = tmpl->mount;  
2072 -  
2073 - // replace the vhost variable  
2074 - mount = srs_string_replace(mount, "[vhost]", r->vhost);  
2075 - mount = srs_string_replace(mount, "[app]", r->app);  
2076 - mount = srs_string_replace(mount, "[stream]", r->stream);  
2077 -  
2078 - // remove the default vhost mount  
2079 - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");  
2080 -  
2081 - entry->tmpl = tmpl;  
2082 - entry->mount = mount;  
2083 - shls[sid] = entry;  
2084 -  
2085 - if (entry->streams.find(mount) == entry->streams.end()) {  
2086 - ISrsHttpHandler* he = new SrsHlsM3u8Stream();  
2087 - entry->streams[mount] = he;  
2088 -  
2089 - if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {  
2090 - srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret);  
2091 - return ret;  
2092 - }  
2093 - }  
2094 - } else {  
2095 - entry = shls[sid];  
2096 - }  
2097 -  
2098 - mount = entry->mount;  
2099 -  
2100 - // update the m3u8 stream.  
2101 - SrsHlsM3u8Stream* hms = dynamic_cast<SrsHlsM3u8Stream*>(entry->streams[mount]);  
2102 - if (hms) {  
2103 - hms->set_m3u8(m3u8);  
2104 - }  
2105 - srs_trace("hls update m3u8 ok, mount=%s", mount.c_str());  
2106 -  
2107 - return ret;  
2108 -}  
2109 -  
2110 -int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts)  
2111 -{  
2112 - int ret = ERROR_SUCCESS;  
2113 -  
2114 - std::string sid = r->get_stream_url();  
2115 -  
2116 - // when no hls mounted, init with empty m3u8.  
2117 - if (shls.find(sid) == shls.end()) {  
2118 - if ((ret = hls_update_m3u8(r, "")) != ERROR_SUCCESS) {  
2119 - return ret;  
2120 - }  
2121 - }  
2122 -  
2123 - // find again, ignore if not exits.  
2124 - if (shls.find(sid) == shls.end()) {  
2125 - return ret;  
2126 - }  
2127 -  
2128 - SrsHlsEntry* entry = shls[sid];  
2129 - srs_assert(entry);  
2130 - srs_assert(entry->tmpl);  
2131 -  
2132 - std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount);  
2133 -  
2134 - if (entry->streams.find(mount) == entry->streams.end()) {  
2135 - ISrsHttpHandler* he = new SrsHlsTsStream();  
2136 - entry->streams[mount] = he;  
2137 -  
2138 - if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {  
2139 - srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret);  
2140 - return ret;  
2141 - }  
2142 - }  
2143 -  
2144 - // update the ts stream.  
2145 - SrsHlsTsStream* hts = dynamic_cast<SrsHlsTsStream*>(entry->streams[mount]);  
2146 - if (hts) {  
2147 - hts->set_ts(ts);  
2148 - }  
2149 - srs_trace("hls update ts ok, mount=%s", mount.c_str());  
2150 -  
2151 - return ret;  
2152 -}  
2153 -  
2154 -  
2155 -int SrsHttpServer::hls_remove_ts(SrsRequest* r, string uri)  
2156 -{  
2157 - int ret = ERROR_SUCCESS;  
2158 -  
2159 - std::string sid = r->get_stream_url();  
2160 -  
2161 - // when no hls mounted, ignore.  
2162 - if (shls.find(sid) == shls.end()) {  
2163 - return ret;  
2164 - }  
2165 -  
2166 - SrsHlsEntry* entry = shls[sid];  
2167 - srs_assert(entry);  
2168 - srs_assert(entry->tmpl);  
2169 -  
2170 - std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount);  
2171 -  
2172 - // ignore when no ts mounted.  
2173 - if (entry->streams.find(mount) == entry->streams.end()) {  
2174 - return ret;  
2175 - }  
2176 -  
2177 - // update the ts stream.  
2178 - SrsHlsTsStream* hts = dynamic_cast<SrsHlsTsStream*>(entry->streams[mount]);  
2179 - if (hts) {  
2180 - hts->set_ts("");  
2181 - // TODO: FIXME: unmount and remove the http handler.  
2182 - }  
2183 - srs_trace("hls remove ts ok, mount=%s", mount.c_str());  
2184 -  
2185 - return ret;  
2186 -}  
2187 -  
2188 -void SrsHttpServer::unmount_hls(SrsRequest* r)  
2189 -{  
2190 - std::string sid = r->get_stream_url();  
2191 -  
2192 - if (shls.find(sid) == shls.end()) {  
2193 - srs_info("ignore unmount hls stream for disabled");  
2194 - return;  
2195 - }  
2196 -  
2197 - SrsHlsEntry* entry = shls[sid];  
2198 -  
2199 - std::map<std::string, ISrsHttpHandler*>::iterator it;  
2200 - for (it = entry->streams.begin(); it != entry->streams.end(); ++it) {  
2201 - ISrsHttpHandler* stream = it->second;  
2202 - stream->entry->enabled = false;  
2203 - }  
2204 -}  
2205 -  
2206 -int SrsHttpServer::on_reload_vhost_http_updated()  
2207 -{  
2208 - int ret = ERROR_SUCCESS;  
2209 - // TODO: FIXME: implements it.  
2210 - return ret;  
2211 -}  
2212 -  
2213 -int SrsHttpServer::on_reload_vhost_http_remux_updated()  
2214 -{  
2215 - int ret = ERROR_SUCCESS;  
2216 - // TODO: FIXME: implements it.  
2217 - return ret;  
2218 -}  
2219 -  
2220 -int SrsHttpServer::on_reload_vhost_hls(string vhost)  
2221 -{  
2222 - int ret = ERROR_SUCCESS;  
2223 - // TODO: FIXME: implements it.  
2224 - return ret;  
2225 -}  
2226 -  
2227 -int SrsHttpServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph)  
2228 -{  
2229 - int ret = ERROR_SUCCESS;  
2230 -  
2231 - // when handler not the root, we think the handler is ok.  
2232 - ISrsHttpHandler* h = *ph? *ph : NULL;  
2233 - if (h && h->entry && h->entry->pattern != "/") {  
2234 - return ret;  
2235 - }  
2236 -  
2237 - // only hijack for http streaming, http-flv/ts/mp3/aac.  
2238 - std::string ext = request->ext();  
2239 - if (ext.empty()) {  
2240 - return ret;  
2241 - }  
2242 -  
2243 - // find the actually request vhost.  
2244 - SrsConfDirective* vhost = _srs_config->get_vhost(request->host());  
2245 - if (!vhost || !_srs_config->get_vhost_enabled(vhost)) {  
2246 - return ret;  
2247 - }  
2248 -  
2249 - // find the entry template for the stream.  
2250 - SrsLiveEntry* entry = NULL;  
2251 - if (true) {  
2252 - // no http streaming on vhost, ignore.  
2253 - std::map<std::string, SrsLiveEntry*>::iterator it = tflvs.find(vhost->arg0());  
2254 - if (it == tflvs.end()) {  
2255 - return ret;  
2256 - }  
2257 -  
2258 - // hstrs not enabled, ignore.  
2259 - entry = it->second;  
2260 - if (!entry->hstrs) {  
2261 - return ret;  
2262 - }  
2263 -  
2264 - // check entry and request extension.  
2265 - if (entry->is_flv()) {  
2266 - if (ext != ".flv") {  
2267 - return ret;  
2268 - }  
2269 - } else if (entry->is_ts()) {  
2270 - if (ext != ".ts") {  
2271 - return ret;  
2272 - }  
2273 - } else if (entry->is_mp3()) {  
2274 - if (ext != ".mp3") {  
2275 - return ret;  
2276 - }  
2277 - } else if (entry->is_aac()) {  
2278 - if (ext != ".aac") {  
2279 - return ret;  
2280 - }  
2281 - } else {  
2282 - return ret;  
2283 - }  
2284 - }  
2285 -  
2286 - // convert to concreate class.  
2287 - SrsHttpMessage* hreq = dynamic_cast<SrsHttpMessage*>(request);  
2288 - srs_assert(hreq);  
2289 -  
2290 - // hijack for entry.  
2291 - SrsRequest* r = hreq->to_request(vhost->arg0());  
2292 - SrsAutoFree(SrsRequest, r);  
2293 - SrsSource* s = SrsSource::fetch(r);  
2294 - if (!s) {  
2295 - if ((ret = SrsSource::create(r, server, server, &s)) != ERROR_SUCCESS) {  
2296 - return ret;  
2297 - }  
2298 - }  
2299 - srs_assert(s != NULL);  
2300 -  
2301 - // create http streaming handler.  
2302 - if ((ret = http_mount(s, r)) != ERROR_SUCCESS) {  
2303 - return ret;  
2304 - }  
2305 -  
2306 - // use the handler if exists.  
2307 - if (ph) {  
2308 - std::string sid = r->get_stream_url();  
2309 - if (sflvs.find(sid) != sflvs.end()) {  
2310 - entry = sflvs[sid];  
2311 - *ph = entry->stream;  
2312 - }  
2313 - }  
2314 -  
2315 - // trigger edge to fetch from origin.  
2316 - bool vhost_is_edge = _srs_config->get_vhost_is_edge(r->vhost);  
2317 - srs_trace("hstrs: source url=%s, is_edge=%d, source_id=%d[%d]",  
2318 - r->get_stream_url().c_str(), vhost_is_edge, s->source_id(), s->source_id());  
2319 -  
2320 - // TODO: FIXME: disconnect when all connection closed.  
2321 - if (vhost_is_edge) {  
2322 - // notice edge to start for the first client.  
2323 - if ((ret = s->on_edge_start_play()) != ERROR_SUCCESS) {  
2324 - srs_error("notice edge start play stream failed. ret=%d", ret);  
2325 - return ret;  
2326 - }  
2327 - }  
2328 -  
2329 - return ret;  
2330 -}  
2331 -  
2332 -int SrsHttpServer::initialize_static_file()  
2333 -{  
2334 - int ret = ERROR_SUCCESS;  
2335 -  
2336 - bool default_root_exists = false;  
2337 -  
2338 - // http static file and flv vod stream mount for each vhost.  
2339 - SrsConfDirective* root = _srs_config->get_root();  
2340 - for (int i = 0; i < (int)root->directives.size(); i++) {  
2341 - SrsConfDirective* conf = root->at(i);  
2342 -  
2343 - if (!conf->is_vhost()) {  
2344 - continue;  
2345 - }  
2346 -  
2347 - std::string vhost = conf->arg0();  
2348 - if (!_srs_config->get_vhost_http_enabled(vhost)) {  
2349 - continue;  
2350 - }  
2351 -  
2352 - std::string mount = _srs_config->get_vhost_http_mount(vhost);  
2353 - std::string dir = _srs_config->get_vhost_http_dir(vhost);  
2354 -  
2355 - // replace the vhost variable  
2356 - mount = srs_string_replace(mount, "[vhost]", vhost);  
2357 -  
2358 - // remove the default vhost mount  
2359 - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");  
2360 -  
2361 - // the dir mount must always ends with "/"  
2362 - if (mount != "/" && mount.rfind("/") != mount.length() - 1) {  
2363 - mount += "/";  
2364 - }  
2365 -  
2366 - // mount the http of vhost.  
2367 - if ((ret = mux.handle(mount, new SrsVodStream(dir))) != ERROR_SUCCESS) {  
2368 - srs_error("http: mount dir=%s for vhost=%s failed. ret=%d", dir.c_str(), vhost.c_str(), ret);  
2369 - return ret;  
2370 - }  
2371 -  
2372 - if (mount == "/") {  
2373 - default_root_exists = true;  
2374 - srs_warn("http: root mount to %s", dir.c_str());  
2375 - }  
2376 - srs_trace("http: vhost=%s mount to %s", vhost.c_str(), mount.c_str());  
2377 - }  
2378 -  
2379 - if (!default_root_exists) {  
2380 - // add root  
2381 - std::string dir = _srs_config->get_http_stream_dir();  
2382 - if ((ret = mux.handle("/", new SrsVodStream(dir))) != ERROR_SUCCESS) {  
2383 - srs_error("http: mount root dir=%s failed. ret=%d", dir.c_str(), ret);  
2384 - return ret;  
2385 - }  
2386 - srs_trace("http: root mount to %s", dir.c_str());  
2387 - }  
2388 -  
2389 - return ret;  
2390 -}  
2391 -  
2392 -int SrsHttpServer::initialize_flv_streaming()  
2393 -{  
2394 - int ret = ERROR_SUCCESS;  
2395 -  
2396 - // http flv live stream mount for each vhost.  
2397 - SrsConfDirective* root = _srs_config->get_root();  
2398 - for (int i = 0; i < (int)root->directives.size(); i++) {  
2399 - SrsConfDirective* conf = root->at(i);  
2400 -  
2401 - if (!conf->is_vhost()) {  
2402 - continue;  
2403 - }  
2404 -  
2405 - std::string vhost = conf->arg0();  
2406 - if (!_srs_config->get_vhost_http_remux_enabled(vhost)) {  
2407 - continue;  
2408 - }  
2409 -  
2410 - SrsLiveEntry* entry = new SrsLiveEntry(  
2411 - _srs_config->get_vhost_http_remux_mount(vhost),  
2412 - _srs_config->get_vhost_http_remux_hstrs(vhost)  
2413 - );  
2414 - tflvs[vhost] = entry;  
2415 - srs_trace("http flv live stream, vhost=%s, mount=%s",  
2416 - vhost.c_str(), entry->mount.c_str());  
2417 - }  
2418 -  
2419 - return ret;  
2420 -}  
2421 -  
2422 -int SrsHttpServer::initialize_hls_streaming()  
2423 -{  
2424 - int ret = ERROR_SUCCESS;  
2425 -  
2426 - // http hls live stream mount for each vhost.  
2427 - SrsConfDirective* root = _srs_config->get_root();  
2428 - for (int i = 0; i < (int)root->directives.size(); i++) {  
2429 - SrsConfDirective* conf = root->at(i);  
2430 -  
2431 - if (!conf->is_vhost()) {  
2432 - continue;  
2433 - }  
2434 -  
2435 - std::string vhost = conf->arg0();  
2436 - if (!_srs_config->get_hls_enabled(vhost)) {  
2437 - continue;  
2438 - }  
2439 -  
2440 - std::string storage = _srs_config->get_hls_storage(vhost);  
2441 - if (storage != "ram" && storage != "both") {  
2442 - continue;  
2443 - }  
2444 -  
2445 - SrsHlsEntry* entry = new SrsHlsEntry();  
2446 - entry->mount = _srs_config->get_hls_mount(vhost);  
2447 - thls[vhost] = entry;  
2448 - srs_trace("http hls live stream, vhost=%s, mount=%s",  
2449 - vhost.c_str(), entry->mount.c_str());  
2450 - }  
2451 -  
2452 - return ret;  
2453 -}  
2454 -  
2455 -string SrsHttpServer::hls_mount_generate(SrsRequest* r, string uri, string tmpl)  
2456 -{  
2457 - std::string mount = tmpl;  
2458 -  
2459 - // the ts is relative from the m3u8, the same start dir.  
2460 - size_t pos = string::npos;  
2461 - if ((pos = mount.rfind("/")) != string::npos) {  
2462 - mount = mount.substr(0, pos);  
2463 - }  
2464 -  
2465 - // replace the vhost variable  
2466 - mount = srs_string_replace(mount, "[vhost]", r->vhost);  
2467 - mount = srs_string_replace(mount, "[app]", r->app);  
2468 -  
2469 - // remove the default vhost mount  
2470 - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");  
2471 -  
2472 - // mount with ts.  
2473 - mount += "/";  
2474 - mount += uri;  
2475 -  
2476 - return mount;  
2477 -}  
2478 -  
2479 -#endif  
2480 -  
2481 -#ifdef SRS_AUTO_HTTP_CORE  
2482 -SrsHttpConn::SrsHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m) 1100 +SrsHttpConn::SrsHttpConn(IConnectionManager* cm, st_netfd_t fd, ISrsHttpServeMux* m)
2483 : SrsConnection(cm, fd) 1101 : SrsConnection(cm, fd)
2484 { 1102 {
2485 parser = new SrsHttpParser(); 1103 parser = new SrsHttpParser();
@@ -2586,7 +1204,7 @@ int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -2586,7 +1204,7 @@ int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
2586 return ret; 1204 return ret;
2587 } 1205 }
2588 1206
2589 -SrsStaticHttpConn::SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m) 1207 +SrsStaticHttpConn::SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, ISrsHttpServeMux* m)
2590 : SrsHttpConn(cm, fd, m) 1208 : SrsHttpConn(cm, fd, m)
2591 { 1209 {
2592 } 1210 }
@@ -2610,5 +1228,85 @@ int SrsStaticHttpConn::on_got_http_message(ISrsHttpMessage* msg) @@ -2610,5 +1228,85 @@ int SrsStaticHttpConn::on_got_http_message(ISrsHttpMessage* msg)
2610 return ret; 1228 return ret;
2611 } 1229 }
2612 1230
  1231 +SrsHttpServer::SrsHttpServer(SrsServer* svr)
  1232 +{
  1233 + server = svr;
  1234 + http_stream = new SrsHttpStreamServer(svr);
  1235 + http_static = new SrsHttpStaticServer(svr);
  1236 +}
  1237 +
  1238 +SrsHttpServer::~SrsHttpServer()
  1239 +{
  1240 + srs_freep(http_stream);
  1241 + srs_freep(http_static);
  1242 +}
  1243 +
  1244 +int SrsHttpServer::initialize()
  1245 +{
  1246 + int ret = ERROR_SUCCESS;
  1247 +
  1248 +#if defined(SRS_AUTO_HTTP_SERVER) && defined(SRS_AUTO_HTTP_API)
  1249 + // for SRS go-sharp to detect the status of HTTP server of SRS HTTP FLV Cluster.
  1250 + if ((ret = http_static->mux.handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) {
  1251 + return ret;
  1252 + }
  1253 +#endif
  1254 +
  1255 + if ((ret = http_stream->initialize()) != ERROR_SUCCESS) {
  1256 + return ret;
  1257 + }
  1258 +
  1259 + if ((ret = http_static->initialize()) != ERROR_SUCCESS) {
  1260 + return ret;
  1261 + }
  1262 +
  1263 + return ret;
  1264 +}
  1265 +
  1266 +int SrsHttpServer::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  1267 +{
  1268 + // try http stream first.
  1269 + if (http_stream->mux.can_serve(r)) {
  1270 + return http_stream->mux.serve_http(w, r);
  1271 + }
  1272 +
  1273 + return http_static->mux.serve_http(w, r);
  1274 +}
  1275 +
  1276 +int SrsHttpServer::http_mount(SrsSource* s, SrsRequest* r)
  1277 +{
  1278 + return http_stream->http_mount(s, r);
  1279 +}
  1280 +
  1281 +void SrsHttpServer::http_unmount(SrsSource* s, SrsRequest* r)
  1282 +{
  1283 + http_stream->http_unmount(s, r);
  1284 +}
  1285 +
  1286 +int SrsHttpServer::mount_hls(SrsRequest* r)
  1287 +{
  1288 + return http_stream->mount_hls(r);
  1289 +}
  1290 +
  1291 +int SrsHttpServer::hls_update_m3u8(SrsRequest* r, std::string m3u8)
  1292 +{
  1293 + return http_stream->hls_update_m3u8(r, m3u8);
  1294 +}
  1295 +
  1296 +int SrsHttpServer::hls_update_ts(SrsRequest* r, std::string uri, std::string ts)
  1297 +{
  1298 + return http_stream->hls_update_ts(r, uri, ts);
  1299 +}
  1300 +
  1301 +int SrsHttpServer::hls_remove_ts(SrsRequest* r, std::string uri)
  1302 +{
  1303 + return http_stream->hls_remove_ts(r, uri);
  1304 +}
  1305 +
  1306 +void SrsHttpServer::unmount_hls(SrsRequest* r)
  1307 +{
  1308 + http_stream->unmount_hls(r);
  1309 +}
  1310 +
2613 #endif 1311 #endif
2614 1312
@@ -67,10 +67,8 @@ class SrsFastBuffer; @@ -67,10 +67,8 @@ class SrsFastBuffer;
67 class SrsHttpUri; 67 class SrsHttpUri;
68 class SrsConnection; 68 class SrsConnection;
69 class SrsHttpMessage; 69 class SrsHttpMessage;
70 -  
71 -#endif  
72 -  
73 -#ifdef SRS_AUTO_HTTP_CORE 70 +class SrsHttpStreamServer;
  71 +class SrsHttpStaticServer;
74 72
75 // the http chunked header size, 73 // the http chunked header size,
76 // for writev, there always one chunk to send it. 74 // for writev, there always one chunk to send it.
@@ -371,327 +369,58 @@ private: @@ -371,327 +369,58 @@ private:
371 virtual std::string get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field); 369 virtual std::string get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field);
372 }; 370 };
373 371
374 -#endif  
375 -  
376 -#ifdef SRS_AUTO_HTTP_SERVER  
377 -  
378 -/**  
379 -* the flv vod stream supports flv?start=offset-bytes.  
380 -* for example, http://server/file.flv?start=10240  
381 -* server will write flv header and sequence header,  
382 -* then seek(10240) and response flv tag data.  
383 -*/  
384 -class SrsVodStream : public SrsHttpFileServer  
385 -{  
386 -public:  
387 - SrsVodStream(std::string root_dir);  
388 - virtual ~SrsVodStream();  
389 -protected:  
390 - virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset);  
391 - virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end);  
392 -};  
393 -  
394 -/**  
395 -* for the srs http stream cache,  
396 -* for example, the audio stream cache to make android(weixin) happy.  
397 -* we start a thread to shrink the queue.  
398 -*/  
399 -class SrsStreamCache : public ISrsEndlessThreadHandler 372 +class SrsHttpConn : public SrsConnection
400 { 373 {
401 private: 374 private:
402 - SrsMessageQueue* queue;  
403 - SrsSource* source;  
404 - SrsRequest* req;  
405 - SrsEndlessThread* pthread;  
406 -public:  
407 - SrsStreamCache(SrsSource* s, SrsRequest* r);  
408 - virtual ~SrsStreamCache();  
409 -public:  
410 - virtual int start();  
411 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);  
412 -// interface ISrsEndlessThreadHandler.  
413 -public:  
414 - virtual int cycle();  
415 -};  
416 -  
417 -/**  
418 -* the stream encoder in some codec, for example, flv or aac.  
419 -*/  
420 -class ISrsStreamEncoder  
421 -{  
422 -public:  
423 - ISrsStreamEncoder();  
424 - virtual ~ISrsStreamEncoder(); 375 + SrsHttpParser* parser;
  376 + ISrsHttpServeMux* http_mux;
425 public: 377 public:
426 - /**  
427 - * initialize the encoder with file writer(to http response) and stream cache.  
428 - * @param w the writer to write to http response.  
429 - * @param c the stream cache for audio stream fast startup.  
430 - */  
431 - virtual int initialize(SrsFileWriter* w, SrsStreamCache* c) = 0;  
432 - /**  
433 - * write rtmp video/audio/metadata.  
434 - */  
435 - virtual int write_audio(int64_t timestamp, char* data, int size) = 0;  
436 - virtual int write_video(int64_t timestamp, char* data, int size) = 0;  
437 - virtual int write_metadata(int64_t timestamp, char* data, int size) = 0; 378 + SrsHttpConn(IConnectionManager* cm, st_netfd_t fd, ISrsHttpServeMux* m);
  379 + virtual ~SrsHttpConn();
  380 +// interface IKbpsDelta
438 public: 381 public:
439 - /**  
440 - * for some stream, for example, mp3 and aac, the audio stream,  
441 - * we use large gop cache in encoder, for the gop cache of SrsSource is ignore audio.  
442 - * @return true to use gop cache of encoder; otherwise, use SrsSource.  
443 - */  
444 - virtual bool has_cache() = 0;  
445 - /**  
446 - * dumps the cache of encoder to consumer.  
447 - */  
448 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter) = 0;  
449 -};  
450 -  
451 -/**  
452 -* the flv stream encoder, remux rtmp stream to flv stream.  
453 -*/  
454 -class SrsFlvStreamEncoder : public ISrsStreamEncoder  
455 -{ 382 + virtual void resample();
  383 + virtual int64_t get_send_bytes_delta();
  384 + virtual int64_t get_recv_bytes_delta();
  385 + virtual void cleanup();
456 protected: 386 protected:
457 - SrsFlvEncoder* enc;  
458 -public:  
459 - SrsFlvStreamEncoder();  
460 - virtual ~SrsFlvStreamEncoder();  
461 -public:  
462 - virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);  
463 - virtual int write_audio(int64_t timestamp, char* data, int size);  
464 - virtual int write_video(int64_t timestamp, char* data, int size);  
465 - virtual int write_metadata(int64_t timestamp, char* data, int size);  
466 -public:  
467 - virtual bool has_cache();  
468 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);  
469 -};  
470 -  
471 -#ifdef SRS_PERF_FAST_FLV_ENCODER  
472 -/**  
473 - * the fast flv stream encoder.  
474 - * @see https://github.com/simple-rtmp-server/srs/issues/405  
475 - */  
476 -class SrsFastFlvStreamEncoder : public SrsFlvStreamEncoder  
477 -{  
478 -public:  
479 - SrsFastFlvStreamEncoder();  
480 - virtual ~SrsFastFlvStreamEncoder();  
481 -public:  
482 - /**  
483 - * write the tags in a time.  
484 - */  
485 - virtual int write_tags(SrsSharedPtrMessage** msgs, int count);  
486 -};  
487 -#endif  
488 -  
489 -/**  
490 -* the ts stream encoder, remux rtmp stream to ts stream.  
491 -*/  
492 -class SrsTsStreamEncoder : public ISrsStreamEncoder  
493 -{  
494 -private:  
495 - SrsTsEncoder* enc;  
496 -public:  
497 - SrsTsStreamEncoder();  
498 - virtual ~SrsTsStreamEncoder();  
499 -public:  
500 - virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);  
501 - virtual int write_audio(int64_t timestamp, char* data, int size);  
502 - virtual int write_video(int64_t timestamp, char* data, int size);  
503 - virtual int write_metadata(int64_t timestamp, char* data, int size);  
504 -public:  
505 - virtual bool has_cache();  
506 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);  
507 -};  
508 -  
509 -/**  
510 -* the aac stream encoder, remux rtmp stream to aac stream.  
511 -*/  
512 -class SrsAacStreamEncoder : public ISrsStreamEncoder  
513 -{  
514 -private:  
515 - SrsAacEncoder* enc;  
516 - SrsStreamCache* cache;  
517 -public:  
518 - SrsAacStreamEncoder();  
519 - virtual ~SrsAacStreamEncoder();  
520 -public:  
521 - virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);  
522 - virtual int write_audio(int64_t timestamp, char* data, int size);  
523 - virtual int write_video(int64_t timestamp, char* data, int size);  
524 - virtual int write_metadata(int64_t timestamp, char* data, int size);  
525 -public:  
526 - virtual bool has_cache();  
527 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);  
528 -};  
529 -  
530 -/**  
531 -* the mp3 stream encoder, remux rtmp stream to mp3 stream.  
532 -*/  
533 -class SrsMp3StreamEncoder : public ISrsStreamEncoder  
534 -{  
535 -private:  
536 - SrsMp3Encoder* enc;  
537 - SrsStreamCache* cache;  
538 -public:  
539 - SrsMp3StreamEncoder();  
540 - virtual ~SrsMp3StreamEncoder();  
541 -public:  
542 - virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);  
543 - virtual int write_audio(int64_t timestamp, char* data, int size);  
544 - virtual int write_video(int64_t timestamp, char* data, int size);  
545 - virtual int write_metadata(int64_t timestamp, char* data, int size);  
546 -public:  
547 - virtual bool has_cache();  
548 - virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);  
549 -};  
550 -  
551 -/**  
552 -* write stream to http response direclty.  
553 -*/  
554 -class SrsStreamWriter : public SrsFileWriter  
555 -{  
556 -private:  
557 - ISrsHttpResponseWriter* writer;  
558 -public:  
559 - SrsStreamWriter(ISrsHttpResponseWriter* w);  
560 - virtual ~SrsStreamWriter();  
561 -public:  
562 - virtual int open(std::string file);  
563 - virtual void close();  
564 -public:  
565 - virtual bool is_open();  
566 - virtual int64_t tellg();  
567 -public:  
568 - virtual int write(void* buf, size_t count, ssize_t* pnwrite);  
569 - virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);  
570 -};  
571 -  
572 -/**  
573 -* the flv live stream supports access rtmp in flv over http.  
574 -* srs will remux rtmp to flv streaming.  
575 -*/  
576 -class SrsLiveStream : public ISrsHttpHandler  
577 -{  
578 -private:  
579 - SrsRequest* req;  
580 - SrsSource* source;  
581 - SrsStreamCache* cache;  
582 -public:  
583 - SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c);  
584 - virtual ~SrsLiveStream();  
585 -public:  
586 - virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);  
587 -private:  
588 - virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs);  
589 -};  
590 -  
591 -/**  
592 -* the srs live entry  
593 -*/  
594 -struct SrsLiveEntry  
595 -{  
596 -private:  
597 - bool _is_flv;  
598 - bool _is_ts;  
599 - bool _is_aac;  
600 - bool _is_mp3;  
601 -public:  
602 - // for template, the mount contains variables.  
603 - // for concrete stream, the mount is url to access.  
604 - std::string mount;  
605 - // whether hstrs(http stream trigger rtmp source)  
606 - bool hstrs;  
607 -  
608 - SrsLiveStream* stream;  
609 - SrsStreamCache* cache;  
610 -  
611 - SrsLiveEntry(std::string m, bool h);  
612 -  
613 - bool is_flv();  
614 - bool is_ts();  
615 - bool is_mp3();  
616 - bool is_aac();  
617 -};  
618 -  
619 -/**  
620 -* the m3u8 stream handler.  
621 -*/  
622 -class SrsHlsM3u8Stream : public ISrsHttpHandler  
623 -{ 387 + virtual int do_cycle();
  388 +protected:
  389 + // when got http message,
  390 + // for the static service or api, discard any body.
  391 + // for the stream caster, for instance, http flv streaming, may discard the flv header or not.
  392 + virtual int on_got_http_message(ISrsHttpMessage* msg) = 0;
624 private: 393 private:
625 - std::string m3u8;  
626 -public:  
627 - SrsHlsM3u8Stream();  
628 - virtual ~SrsHlsM3u8Stream();  
629 -public:  
630 - virtual void set_m3u8(std::string v);  
631 -public:  
632 - virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); 394 + virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
633 }; 395 };
634 396
635 -/**  
636 -* the ts stream handler.  
637 -*/  
638 -class SrsHlsTsStream : public ISrsHttpHandler 397 +// TODO: FIXME: rename to SrsResponseOnlyHttpConn.
  398 +class SrsStaticHttpConn : public SrsHttpConn
639 { 399 {
640 -private:  
641 - std::string ts;  
642 -public:  
643 - SrsHlsTsStream();  
644 - virtual ~SrsHlsTsStream();  
645 public: 400 public:
646 - virtual void set_ts(std::string v); 401 + SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, ISrsHttpServeMux* m);
  402 + virtual ~SrsStaticHttpConn();
647 public: 403 public:
648 - virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);  
649 -};  
650 -  
651 -/**  
652 -* the srs hls entry.  
653 -*/  
654 -// TODO: FIXME: use hte hls template and entry.  
655 -struct SrsHlsEntry  
656 -{  
657 - // for template, the mount contains variables.  
658 - // for concrete stream, the mount is url to access.  
659 - std::string mount;  
660 -  
661 - // the template to create the entry  
662 - SrsHlsEntry* tmpl;  
663 -  
664 - // key: the m3u8/ts file path.  
665 - // value: the http handler.  
666 - std::map<std::string, ISrsHttpHandler*> streams;  
667 -  
668 - SrsHlsEntry(); 404 + virtual int on_got_http_message(ISrsHttpMessage* msg);
669 }; 405 };
670 406
671 /** 407 /**
672 -* the http server instance,  
673 -* serve http static file, flv vod stream and flv live stream.  
674 -*/  
675 -class SrsHttpServer : virtual public ISrsReloadHandler  
676 - , virtual public ISrsHttpMatchHijacker 408 + * the http server, use http stream or static server to serve requests.
  409 + */
  410 +class SrsHttpServer : public ISrsHttpServeMux
677 { 411 {
678 private: 412 private:
679 SrsServer* server; 413 SrsServer* server;
680 -public:  
681 - SrsHttpServeMux mux;  
682 - // the http live streaming template, to create streams.  
683 - std::map<std::string, SrsLiveEntry*> tflvs;  
684 - // the http live streaming streams, crote by template.  
685 - std::map<std::string, SrsLiveEntry*> sflvs;  
686 - // the hls live streaming template, to create streams.  
687 - std::map<std::string, SrsHlsEntry*> thls;  
688 - // the hls live streaming streams, crote by template.  
689 - std::map<std::string, SrsHlsEntry*> shls; 414 + SrsHttpStaticServer* http_static;
  415 + SrsHttpStreamServer* http_stream;
690 public: 416 public:
691 SrsHttpServer(SrsServer* svr); 417 SrsHttpServer(SrsServer* svr);
692 virtual ~SrsHttpServer(); 418 virtual ~SrsHttpServer();
693 public: 419 public:
694 virtual int initialize(); 420 virtual int initialize();
  421 +// ISrsHttpServeMux
  422 +public:
  423 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
695 // http flv/ts/mp3/aac stream 424 // http flv/ts/mp3/aac stream
696 public: 425 public:
697 virtual int http_mount(SrsSource* s, SrsRequest* r); 426 virtual int http_mount(SrsSource* s, SrsRequest* r);
@@ -703,56 +432,6 @@ public: @@ -703,56 +432,6 @@ public:
703 virtual int hls_update_ts(SrsRequest* r, std::string uri, std::string ts); 432 virtual int hls_update_ts(SrsRequest* r, std::string uri, std::string ts);
704 virtual int hls_remove_ts(SrsRequest* r, std::string uri); 433 virtual int hls_remove_ts(SrsRequest* r, std::string uri);
705 virtual void unmount_hls(SrsRequest* r); 434 virtual void unmount_hls(SrsRequest* r);
706 -// interface ISrsReloadHandler.  
707 -public:  
708 - virtual int on_reload_vhost_http_updated();  
709 - virtual int on_reload_vhost_http_remux_updated();  
710 - virtual int on_reload_vhost_hls(std::string vhost);  
711 -// interface ISrsHttpMatchHijacker  
712 -public:  
713 - virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph);  
714 -private:  
715 - virtual int initialize_static_file();  
716 - virtual int initialize_flv_streaming();  
717 - virtual int initialize_hls_streaming();  
718 - virtual std::string hls_mount_generate(SrsRequest* r, std::string uri, std::string tmpl);  
719 -};  
720 -  
721 -#endif  
722 -  
723 -#ifdef SRS_AUTO_HTTP_CORE  
724 -class SrsHttpConn : public SrsConnection  
725 -{  
726 -private:  
727 - SrsHttpParser* parser;  
728 - SrsHttpServeMux* http_mux;  
729 -public:  
730 - SrsHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m);  
731 - virtual ~SrsHttpConn();  
732 -// interface IKbpsDelta  
733 -public:  
734 - virtual void resample();  
735 - virtual int64_t get_send_bytes_delta();  
736 - virtual int64_t get_recv_bytes_delta();  
737 - virtual void cleanup();  
738 -protected:  
739 - virtual int do_cycle();  
740 -protected:  
741 - // when got http message,  
742 - // for the static service or api, discard any body.  
743 - // for the stream caster, for instance, http flv streaming, may discard the flv header or not.  
744 - virtual int on_got_http_message(ISrsHttpMessage* msg) = 0;  
745 -private:  
746 - virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);  
747 -};  
748 -  
749 -class SrsStaticHttpConn : public SrsHttpConn  
750 -{  
751 -public:  
752 - SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m);  
753 - virtual ~SrsStaticHttpConn();  
754 -public:  
755 - virtual int on_got_http_message(ISrsHttpMessage* msg);  
756 }; 435 };
757 436
758 #endif 437 #endif
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 SRS(simple-rtmp-server)
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_http_static.hpp>
  25 +
  26 +#if defined(SRS_AUTO_HTTP_CORE)
  27 +
  28 +#include <sys/types.h>
  29 +#include <sys/stat.h>
  30 +#include <fcntl.h>
  31 +#include <stdlib.h>
  32 +
  33 +#include <sstream>
  34 +using namespace std;
  35 +
  36 +#include <srs_protocol_buffer.hpp>
  37 +#include <srs_rtmp_utility.hpp>
  38 +#include <srs_kernel_log.hpp>
  39 +#include <srs_kernel_error.hpp>
  40 +#include <srs_app_st.hpp>
  41 +#include <srs_core_autofree.hpp>
  42 +#include <srs_app_config.hpp>
  43 +#include <srs_kernel_utility.hpp>
  44 +#include <srs_kernel_file.hpp>
  45 +#include <srs_kernel_flv.hpp>
  46 +#include <srs_rtmp_stack.hpp>
  47 +#include <srs_app_source.hpp>
  48 +#include <srs_rtmp_msg_array.hpp>
  49 +#include <srs_kernel_aac.hpp>
  50 +#include <srs_kernel_mp3.hpp>
  51 +#include <srs_kernel_ts.hpp>
  52 +#include <srs_app_pithy_print.hpp>
  53 +#include <srs_app_source.hpp>
  54 +#include <srs_app_server.hpp>
  55 +
  56 +#endif
  57 +
  58 +#ifdef SRS_AUTO_HTTP_SERVER
  59 +
  60 +SrsVodStream::SrsVodStream(string root_dir)
  61 + : SrsHttpFileServer(root_dir)
  62 +{
  63 +}
  64 +
  65 +SrsVodStream::~SrsVodStream()
  66 +{
  67 +}
  68 +
  69 +int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset)
  70 +{
  71 + int ret = ERROR_SUCCESS;
  72 +
  73 + SrsFileReader fs;
  74 +
  75 + // open flv file
  76 + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
  77 + return ret;
  78 + }
  79 +
  80 + if (offset > fs.filesize()) {
  81 + ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;
  82 + srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d",
  83 + fullpath.c_str(), fs.filesize(), offset, ret);
  84 + return ret;
  85 + }
  86 +
  87 + SrsFlvVodStreamDecoder ffd;
  88 +
  89 + // open fast decoder
  90 + if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {
  91 + return ret;
  92 + }
  93 +
  94 + // save header, send later.
  95 + char flv_header[13];
  96 +
  97 + // send flv header
  98 + if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {
  99 + return ret;
  100 + }
  101 +
  102 + // save sequence header, send later
  103 + char* sh_data = NULL;
  104 + int sh_size = 0;
  105 +
  106 + if (true) {
  107 + // send sequence header
  108 + int64_t start = 0;
  109 + if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {
  110 + return ret;
  111 + }
  112 + if (sh_size <= 0) {
  113 + ret = ERROR_HTTP_REMUX_SEQUENCE_HEADER;
  114 + srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret);
  115 + return ret;
  116 + }
  117 + }
  118 + sh_data = new char[sh_size];
  119 + SrsAutoFree(char, sh_data);
  120 + if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
  121 + return ret;
  122 + }
  123 +
  124 + // seek to data offset
  125 + int64_t left = fs.filesize() - offset;
  126 +
  127 + // write http header for ts.
  128 + w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left));
  129 + w->header()->set_content_type("video/x-flv");
  130 +
  131 + // write flv header and sequence header.
  132 + if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) {
  133 + return ret;
  134 + }
  135 + if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) {
  136 + return ret;
  137 + }
  138 +
  139 + // write body.
  140 + if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {
  141 + return ret;
  142 + }
  143 +
  144 + // send data
  145 + if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
  146 + srs_warn("read flv=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
  147 + return ret;
  148 + }
  149 +
  150 + return ret;
  151 +}
  152 +
  153 +int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end)
  154 +{
  155 + int ret = ERROR_SUCCESS;
  156 +
  157 + srs_assert(start >= 0);
  158 + srs_assert(end == -1 || end >= 0);
  159 +
  160 + SrsFileReader fs;
  161 +
  162 + // open flv file
  163 + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
  164 + return ret;
  165 + }
  166 +
  167 + // parse -1 to whole file.
  168 + if (end == -1) {
  169 + end = (int)fs.filesize();
  170 + }
  171 +
  172 + if (end > fs.filesize() || start > end) {
  173 + ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;
  174 + srs_warn("http mp4 streaming %s overflow. size=%"PRId64", offset=%d, ret=%d",
  175 + fullpath.c_str(), fs.filesize(), start, ret);
  176 + return ret;
  177 + }
  178 +
  179 + // seek to data offset, [start, end] for range.
  180 + int64_t left = end - start + 1;
  181 +
  182 + // write http header for ts.
  183 + w->header()->set_content_length(left);
  184 + w->header()->set_content_type("video/mp4");
  185 +
  186 + // status code 206 to make dash.as happy.
  187 + w->write_header(SRS_CONSTS_HTTP_PartialContent);
  188 +
  189 + // response the content range header.
  190 + std::stringstream content_range;
  191 + content_range << "bytes " << start << "-" << end << "/" << fs.filesize();
  192 + w->header()->set("Content-Range", content_range.str());
  193 +
  194 + // write body.
  195 + fs.lseek(start);
  196 +
  197 + // send data
  198 + if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
  199 + srs_warn("read mp4=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
  200 + return ret;
  201 + }
  202 +
  203 + return ret;
  204 +}
  205 +
  206 +SrsHttpStaticServer::SrsHttpStaticServer(SrsServer* svr)
  207 +{
  208 + server = svr;
  209 +}
  210 +
  211 +SrsHttpStaticServer::~SrsHttpStaticServer()
  212 +{
  213 +}
  214 +
  215 +int SrsHttpStaticServer::initialize()
  216 +{
  217 + int ret = ERROR_SUCCESS;
  218 +
  219 + bool default_root_exists = false;
  220 +
  221 + // http static file and flv vod stream mount for each vhost.
  222 + SrsConfDirective* root = _srs_config->get_root();
  223 + for (int i = 0; i < (int)root->directives.size(); i++) {
  224 + SrsConfDirective* conf = root->at(i);
  225 +
  226 + if (!conf->is_vhost()) {
  227 + continue;
  228 + }
  229 +
  230 + std::string vhost = conf->arg0();
  231 + if (!_srs_config->get_vhost_http_enabled(vhost)) {
  232 + continue;
  233 + }
  234 +
  235 + std::string mount = _srs_config->get_vhost_http_mount(vhost);
  236 + std::string dir = _srs_config->get_vhost_http_dir(vhost);
  237 +
  238 + // replace the vhost variable
  239 + mount = srs_string_replace(mount, "[vhost]", vhost);
  240 +
  241 + // remove the default vhost mount
  242 + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");
  243 +
  244 + // the dir mount must always ends with "/"
  245 + if (mount != "/" && mount.rfind("/") != mount.length() - 1) {
  246 + mount += "/";
  247 + }
  248 +
  249 + // mount the http of vhost.
  250 + if ((ret = mux.handle(mount, new SrsVodStream(dir))) != ERROR_SUCCESS) {
  251 + srs_error("http: mount dir=%s for vhost=%s failed. ret=%d", dir.c_str(), vhost.c_str(), ret);
  252 + return ret;
  253 + }
  254 +
  255 + if (mount == "/") {
  256 + default_root_exists = true;
  257 + srs_warn("http: root mount to %s", dir.c_str());
  258 + }
  259 + srs_trace("http: vhost=%s mount to %s", vhost.c_str(), mount.c_str());
  260 + }
  261 +
  262 + if (!default_root_exists) {
  263 + // add root
  264 + std::string dir = _srs_config->get_http_stream_dir();
  265 + if ((ret = mux.handle("/", new SrsVodStream(dir))) != ERROR_SUCCESS) {
  266 + srs_error("http: mount root dir=%s failed. ret=%d", dir.c_str(), ret);
  267 + return ret;
  268 + }
  269 + srs_trace("http: root mount to %s", dir.c_str());
  270 + }
  271 +
  272 + return ret;
  273 +}
  274 +
  275 +int SrsHttpStaticServer::on_reload_vhost_http_updated()
  276 +{
  277 + int ret = ERROR_SUCCESS;
  278 + // TODO: FIXME: implements it.
  279 + return ret;
  280 +}
  281 +
  282 +#endif
  283 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 SRS(simple-rtmp-server)
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_APP_HTTP_STATIC_HPP
  25 +#define SRS_APP_HTTP_STATIC_HPP
  26 +
  27 +/*
  28 +#include <srs_app_http_static.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <srs_app_http_conn.hpp>
  34 +
  35 +#ifdef SRS_AUTO_HTTP_SERVER
  36 +
  37 +/**
  38 + * the flv vod stream supports flv?start=offset-bytes.
  39 + * for example, http://server/file.flv?start=10240
  40 + * server will write flv header and sequence header,
  41 + * then seek(10240) and response flv tag data.
  42 + */
  43 +class SrsVodStream : public SrsHttpFileServer
  44 +{
  45 +public:
  46 + SrsVodStream(std::string root_dir);
  47 + virtual ~SrsVodStream();
  48 +protected:
  49 + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset);
  50 + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end);
  51 +};
  52 +
  53 +/**
  54 +* the http static server instance,
  55 +* serve http static file and flv/mp4 vod stream.
  56 +*/
  57 +class SrsHttpStaticServer : virtual public ISrsReloadHandler
  58 +{
  59 +private:
  60 + SrsServer* server;
  61 +public:
  62 + SrsHttpServeMux mux;
  63 +public:
  64 + SrsHttpStaticServer(SrsServer* svr);
  65 + virtual ~SrsHttpStaticServer();
  66 +public:
  67 + virtual int initialize();
  68 +// interface ISrsReloadHandler.
  69 +public:
  70 + virtual int on_reload_vhost_http_updated();
  71 +};
  72 +
  73 +#endif
  74 +
  75 +#endif
  76 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 SRS(simple-rtmp-server)
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_http_stream.hpp>
  25 +
  26 +#if defined(SRS_AUTO_HTTP_CORE)
  27 +
  28 +#include <sys/types.h>
  29 +#include <sys/stat.h>
  30 +#include <fcntl.h>
  31 +#include <stdlib.h>
  32 +
  33 +#include <sstream>
  34 +using namespace std;
  35 +
  36 +#include <srs_protocol_buffer.hpp>
  37 +#include <srs_rtmp_utility.hpp>
  38 +#include <srs_kernel_log.hpp>
  39 +#include <srs_kernel_error.hpp>
  40 +#include <srs_app_st.hpp>
  41 +#include <srs_core_autofree.hpp>
  42 +#include <srs_app_config.hpp>
  43 +#include <srs_kernel_utility.hpp>
  44 +#include <srs_kernel_file.hpp>
  45 +#include <srs_kernel_flv.hpp>
  46 +#include <srs_rtmp_stack.hpp>
  47 +#include <srs_app_source.hpp>
  48 +#include <srs_rtmp_msg_array.hpp>
  49 +#include <srs_kernel_aac.hpp>
  50 +#include <srs_kernel_mp3.hpp>
  51 +#include <srs_kernel_ts.hpp>
  52 +#include <srs_app_pithy_print.hpp>
  53 +#include <srs_app_source.hpp>
  54 +#include <srs_app_server.hpp>
  55 +
  56 +#endif
  57 +
  58 +#ifdef SRS_AUTO_HTTP_SERVER
  59 +
  60 +SrsStreamCache::SrsStreamCache(SrsSource* s, SrsRequest* r)
  61 +{
  62 + req = r->copy();
  63 + source = s;
  64 + queue = new SrsMessageQueue(true);
  65 + pthread = new SrsEndlessThread("http-stream", this);
  66 +}
  67 +
  68 +SrsStreamCache::~SrsStreamCache()
  69 +{
  70 + srs_freep(pthread);
  71 +
  72 + srs_freep(queue);
  73 + srs_freep(req);
  74 +}
  75 +
  76 +int SrsStreamCache::start()
  77 +{
  78 + return pthread->start();
  79 +}
  80 +
  81 +int SrsStreamCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)
  82 +{
  83 + int ret = ERROR_SUCCESS;
  84 +
  85 + double fast_cache = _srs_config->get_vhost_http_remux_fast_cache(req->vhost);
  86 +
  87 + if (fast_cache <= 0) {
  88 + srs_info("http: ignore dump fast cache.");
  89 + return ret;
  90 + }
  91 +
  92 + // the jitter is get from SrsSource, which means the time_jitter of vhost.
  93 + if ((ret = queue->dump_packets(consumer, false, jitter)) != ERROR_SUCCESS) {
  94 + return ret;
  95 + }
  96 +
  97 + srs_trace("http: dump cache %d msgs, duration=%dms, cache=%.2fs",
  98 + queue->size(), queue->duration(), fast_cache);
  99 +
  100 + return ret;
  101 +}
  102 +
  103 +int SrsStreamCache::cycle()
  104 +{
  105 + int ret = ERROR_SUCCESS;
  106 +
  107 + SrsConsumer* consumer = NULL;
  108 + if ((ret = source->create_consumer(consumer, false, false, true)) != ERROR_SUCCESS) {
  109 + srs_error("http: create consumer failed. ret=%d", ret);
  110 + return ret;
  111 + }
  112 + SrsAutoFree(SrsConsumer, consumer);
  113 +
  114 + SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream_cache();
  115 + SrsAutoFree(SrsPithyPrint, pprint);
  116 +
  117 + SrsMessageArray msgs(SRS_PERF_MW_MSGS);
  118 +
  119 + // TODO: FIXME: support reload.
  120 + double fast_cache = _srs_config->get_vhost_http_remux_fast_cache(req->vhost);
  121 + if (fast_cache > 0) {
  122 + queue->set_queue_size(fast_cache);
  123 + }
  124 +
  125 + while (true) {
  126 + pprint->elapse();
  127 +
  128 + // get messages from consumer.
  129 + // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
  130 + int count = 0;
  131 + if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) {
  132 + srs_error("http: get messages from consumer failed. ret=%d", ret);
  133 + return ret;
  134 + }
  135 +
  136 + if (count <= 0) {
  137 + srs_info("http: mw sleep %dms for no msg", mw_sleep);
  138 + // directly use sleep, donot use consumer wait.
  139 + st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
  140 +
  141 + // ignore when nothing got.
  142 + continue;
  143 + }
  144 +
  145 + if (pprint->can_print()) {
  146 + srs_trace("-> "SRS_CONSTS_LOG_HTTP_STREAM_CACHE" http: got %d msgs, age=%d, min=%d, mw=%d",
  147 + count, pprint->age(), SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000);
  148 + }
  149 +
  150 + // free the messages.
  151 + for (int i = 0; i < count; i++) {
  152 + SrsSharedPtrMessage* msg = msgs.msgs[i];
  153 + if (fast_cache > 0) {
  154 + queue->enqueue(msg);
  155 + } else {
  156 + srs_freep(msg);
  157 + }
  158 + }
  159 + }
  160 +
  161 + return ret;
  162 +}
  163 +
  164 +ISrsStreamEncoder::ISrsStreamEncoder()
  165 +{
  166 +}
  167 +
  168 +ISrsStreamEncoder::~ISrsStreamEncoder()
  169 +{
  170 +}
  171 +
  172 +SrsTsStreamEncoder::SrsTsStreamEncoder()
  173 +{
  174 + enc = new SrsTsEncoder();
  175 +}
  176 +
  177 +SrsTsStreamEncoder::~SrsTsStreamEncoder()
  178 +{
  179 + srs_freep(enc);
  180 +}
  181 +
  182 +int SrsTsStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* /*c*/)
  183 +{
  184 + int ret = ERROR_SUCCESS;
  185 +
  186 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  187 + return ret;
  188 + }
  189 +
  190 + return ret;
  191 +}
  192 +
  193 +int SrsTsStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  194 +{
  195 + return enc->write_audio(timestamp, data, size);
  196 +}
  197 +
  198 +int SrsTsStreamEncoder::write_video(int64_t timestamp, char* data, int size)
  199 +{
  200 + return enc->write_video(timestamp, data, size);
  201 +}
  202 +
  203 +int SrsTsStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
  204 +{
  205 + return ERROR_SUCCESS;
  206 +}
  207 +
  208 +bool SrsTsStreamEncoder::has_cache()
  209 +{
  210 + // for ts stream, use gop cache of SrsSource is ok.
  211 + return false;
  212 +}
  213 +
  214 +int SrsTsStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
  215 +{
  216 + // for ts stream, ignore cache.
  217 + return ERROR_SUCCESS;
  218 +}
  219 +
  220 +SrsFlvStreamEncoder::SrsFlvStreamEncoder()
  221 +{
  222 + enc = new SrsFlvEncoder();
  223 +}
  224 +
  225 +SrsFlvStreamEncoder::~SrsFlvStreamEncoder()
  226 +{
  227 + srs_freep(enc);
  228 +}
  229 +
  230 +int SrsFlvStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* /*c*/)
  231 +{
  232 + int ret = ERROR_SUCCESS;
  233 +
  234 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  235 + return ret;
  236 + }
  237 +
  238 + // write flv header.
  239 + if ((ret = enc->write_header()) != ERROR_SUCCESS) {
  240 + return ret;
  241 + }
  242 +
  243 + return ret;
  244 +}
  245 +
  246 +int SrsFlvStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  247 +{
  248 + return enc->write_audio(timestamp, data, size);
  249 +}
  250 +
  251 +int SrsFlvStreamEncoder::write_video(int64_t timestamp, char* data, int size)
  252 +{
  253 + return enc->write_video(timestamp, data, size);
  254 +}
  255 +
  256 +int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size)
  257 +{
  258 + return enc->write_metadata(SrsCodecFlvTagScript, data, size);
  259 +}
  260 +
  261 +bool SrsFlvStreamEncoder::has_cache()
  262 +{
  263 + // for flv stream, use gop cache of SrsSource is ok.
  264 + return false;
  265 +}
  266 +
  267 +int SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
  268 +{
  269 + // for flv stream, ignore cache.
  270 + return ERROR_SUCCESS;
  271 +}
  272 +
  273 +#ifdef SRS_PERF_FAST_FLV_ENCODER
  274 +SrsFastFlvStreamEncoder::SrsFastFlvStreamEncoder()
  275 +{
  276 +}
  277 +
  278 +SrsFastFlvStreamEncoder::~SrsFastFlvStreamEncoder()
  279 +{
  280 +}
  281 +
  282 +int SrsFastFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count)
  283 +{
  284 + return enc->write_tags(msgs, count);
  285 +}
  286 +#endif
  287 +
  288 +SrsAacStreamEncoder::SrsAacStreamEncoder()
  289 +{
  290 + enc = new SrsAacEncoder();
  291 + cache = NULL;
  292 +}
  293 +
  294 +SrsAacStreamEncoder::~SrsAacStreamEncoder()
  295 +{
  296 + srs_freep(enc);
  297 +}
  298 +
  299 +int SrsAacStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)
  300 +{
  301 + int ret = ERROR_SUCCESS;
  302 +
  303 + cache = c;
  304 +
  305 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  306 + return ret;
  307 + }
  308 +
  309 + return ret;
  310 +}
  311 +
  312 +int SrsAacStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  313 +{
  314 + return enc->write_audio(timestamp, data, size);
  315 +}
  316 +
  317 +int SrsAacStreamEncoder::write_video(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
  318 +{
  319 + // aac ignore any flv video.
  320 + return ERROR_SUCCESS;
  321 +}
  322 +
  323 +int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
  324 +{
  325 + // aac ignore any flv metadata.
  326 + return ERROR_SUCCESS;
  327 +}
  328 +
  329 +bool SrsAacStreamEncoder::has_cache()
  330 +{
  331 + return true;
  332 +}
  333 +
  334 +int SrsAacStreamEncoder::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)
  335 +{
  336 + srs_assert(cache);
  337 + return cache->dump_cache(consumer, jitter);
  338 +}
  339 +
  340 +SrsMp3StreamEncoder::SrsMp3StreamEncoder()
  341 +{
  342 + enc = new SrsMp3Encoder();
  343 + cache = NULL;
  344 +}
  345 +
  346 +SrsMp3StreamEncoder::~SrsMp3StreamEncoder()
  347 +{
  348 + srs_freep(enc);
  349 +}
  350 +
  351 +int SrsMp3StreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)
  352 +{
  353 + int ret = ERROR_SUCCESS;
  354 +
  355 + cache = c;
  356 +
  357 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  358 + return ret;
  359 + }
  360 +
  361 + if ((ret = enc->write_header()) != ERROR_SUCCESS) {
  362 + return ret;
  363 + }
  364 +
  365 + return ret;
  366 +}
  367 +
  368 +int SrsMp3StreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  369 +{
  370 + return enc->write_audio(timestamp, data, size);
  371 +}
  372 +
  373 +int SrsMp3StreamEncoder::write_video(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
  374 +{
  375 + // mp3 ignore any flv video.
  376 + return ERROR_SUCCESS;
  377 +}
  378 +
  379 +int SrsMp3StreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
  380 +{
  381 + // mp3 ignore any flv metadata.
  382 + return ERROR_SUCCESS;
  383 +}
  384 +
  385 +bool SrsMp3StreamEncoder::has_cache()
  386 +{
  387 + return true;
  388 +}
  389 +
  390 +int SrsMp3StreamEncoder::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)
  391 +{
  392 + srs_assert(cache);
  393 + return cache->dump_cache(consumer, jitter);
  394 +}
  395 +
  396 +SrsStreamWriter::SrsStreamWriter(ISrsHttpResponseWriter* w)
  397 +{
  398 + writer = w;
  399 +}
  400 +
  401 +SrsStreamWriter::~SrsStreamWriter()
  402 +{
  403 +}
  404 +
  405 +int SrsStreamWriter::open(std::string /*file*/)
  406 +{
  407 + return ERROR_SUCCESS;
  408 +}
  409 +
  410 +void SrsStreamWriter::close()
  411 +{
  412 +}
  413 +
  414 +bool SrsStreamWriter::is_open()
  415 +{
  416 + return true;
  417 +}
  418 +
  419 +int64_t SrsStreamWriter::tellg()
  420 +{
  421 + return 0;
  422 +}
  423 +
  424 +int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)
  425 +{
  426 + if (pnwrite) {
  427 + *pnwrite = count;
  428 + }
  429 + return writer->write((char*)buf, (int)count);
  430 +}
  431 +
  432 +int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
  433 +{
  434 + return writer->writev(iov, iovcnt, pnwrite);
  435 +}
  436 +
  437 +SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
  438 +{
  439 + source = s;
  440 + cache = c;
  441 + req = r->copy();
  442 +}
  443 +
  444 +SrsLiveStream::~SrsLiveStream()
  445 +{
  446 + srs_freep(req);
  447 +}
  448 +
  449 +int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  450 +{
  451 + int ret = ERROR_SUCCESS;
  452 +
  453 + ISrsStreamEncoder* enc = NULL;
  454 +
  455 + srs_assert(entry);
  456 + if (srs_string_ends_with(entry->pattern, ".flv")) {
  457 + w->header()->set_content_type("video/x-flv");
  458 +#ifdef SRS_PERF_FAST_FLV_ENCODER
  459 + enc = new SrsFastFlvStreamEncoder();
  460 +#else
  461 + enc = new SrsFlvStreamEncoder();
  462 +#endif
  463 + } else if (srs_string_ends_with(entry->pattern, ".aac")) {
  464 + w->header()->set_content_type("audio/x-aac");
  465 + enc = new SrsAacStreamEncoder();
  466 + } else if (srs_string_ends_with(entry->pattern, ".mp3")) {
  467 + w->header()->set_content_type("audio/mpeg");
  468 + enc = new SrsMp3StreamEncoder();
  469 + } else if (srs_string_ends_with(entry->pattern, ".ts")) {
  470 + w->header()->set_content_type("video/MP2T");
  471 + enc = new SrsTsStreamEncoder();
  472 + } else {
  473 + ret = ERROR_HTTP_LIVE_STREAM_EXT;
  474 + srs_error("http: unsupported pattern %s", entry->pattern.c_str());
  475 + return ret;
  476 + }
  477 + SrsAutoFree(ISrsStreamEncoder, enc);
  478 +
  479 + // create consumer of souce, ignore gop cache, use the audio gop cache.
  480 + SrsConsumer* consumer = NULL;
  481 + if ((ret = source->create_consumer(consumer, true, true, !enc->has_cache())) != ERROR_SUCCESS) {
  482 + srs_error("http: create consumer failed. ret=%d", ret);
  483 + return ret;
  484 + }
  485 + SrsAutoFree(SrsConsumer, consumer);
  486 + srs_verbose("http: consumer created success.");
  487 +
  488 + SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream();
  489 + SrsAutoFree(SrsPithyPrint, pprint);
  490 +
  491 + SrsMessageArray msgs(SRS_PERF_MW_MSGS);
  492 +
  493 + // the memory writer.
  494 + SrsStreamWriter writer(w);
  495 + if ((ret = enc->initialize(&writer, cache)) != ERROR_SUCCESS) {
  496 + srs_error("http: initialize stream encoder failed. ret=%d", ret);
  497 + return ret;
  498 + }
  499 +
  500 + // if gop cache enabled for encoder, dump to consumer.
  501 + if (enc->has_cache()) {
  502 + if ((ret = enc->dump_cache(consumer, source->jitter())) != ERROR_SUCCESS) {
  503 + srs_error("http: dump cache to consumer failed. ret=%d", ret);
  504 + return ret;
  505 + }
  506 + }
  507 +
  508 +#ifdef SRS_PERF_FAST_FLV_ENCODER
  509 + SrsFastFlvStreamEncoder* ffe = dynamic_cast<SrsFastFlvStreamEncoder*>(enc);
  510 +#endif
  511 +
  512 + while (true) {
  513 + pprint->elapse();
  514 +
  515 + // get messages from consumer.
  516 + // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
  517 + int count = 0;
  518 + if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) {
  519 + srs_error("http: get messages from consumer failed. ret=%d", ret);
  520 + return ret;
  521 + }
  522 +
  523 + if (count <= 0) {
  524 + srs_info("http: mw sleep %dms for no msg", mw_sleep);
  525 + // directly use sleep, donot use consumer wait.
  526 + st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
  527 +
  528 + // ignore when nothing got.
  529 + continue;
  530 + }
  531 +
  532 + if (pprint->can_print()) {
  533 + srs_info("-> "SRS_CONSTS_LOG_HTTP_STREAM" http: got %d msgs, age=%d, min=%d, mw=%d",
  534 + count, pprint->age(), SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000);
  535 + }
  536 +
  537 + // sendout all messages.
  538 +#ifdef SRS_PERF_FAST_FLV_ENCODER
  539 + if (ffe) {
  540 + ret = ffe->write_tags(msgs.msgs, count);
  541 + } else {
  542 + ret = streaming_send_messages(enc, msgs.msgs, count);
  543 + }
  544 +#else
  545 + ret = streaming_send_messages(enc, msgs.msgs, count);
  546 +#endif
  547 +
  548 + // free the messages.
  549 + for (int i = 0; i < count; i++) {
  550 + SrsSharedPtrMessage* msg = msgs.msgs[i];
  551 + srs_freep(msg);
  552 + }
  553 +
  554 + // check send error code.
  555 + if (ret != ERROR_SUCCESS) {
  556 + if (!srs_is_client_gracefully_close(ret)) {
  557 + srs_error("http: send messages to client failed. ret=%d", ret);
  558 + }
  559 + return ret;
  560 + }
  561 + }
  562 +
  563 + return ret;
  564 +}
  565 +
  566 +int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs)
  567 +{
  568 + int ret = ERROR_SUCCESS;
  569 +
  570 + for (int i = 0; i < nb_msgs; i++) {
  571 + SrsSharedPtrMessage* msg = msgs[i];
  572 +
  573 + if (msg->is_audio()) {
  574 + ret = enc->write_audio(msg->timestamp, msg->payload, msg->size);
  575 + } else if (msg->is_video()) {
  576 + ret = enc->write_video(msg->timestamp, msg->payload, msg->size);
  577 + } else {
  578 + ret = enc->write_metadata(msg->timestamp, msg->payload, msg->size);
  579 + }
  580 +
  581 + if (ret != ERROR_SUCCESS) {
  582 + return ret;
  583 + }
  584 + }
  585 +
  586 + return ret;
  587 +}
  588 +
  589 +SrsLiveEntry::SrsLiveEntry(std::string m, bool h)
  590 +{
  591 + mount = m;
  592 + hstrs = h;
  593 +
  594 + stream = NULL;
  595 + cache = NULL;
  596 +
  597 + std::string ext;
  598 + size_t pos = string::npos;
  599 + if ((pos = m.rfind(".")) != string::npos) {
  600 + ext = m.substr(pos);
  601 + }
  602 + _is_flv = (ext == ".flv");
  603 + _is_ts = (ext == ".ts");
  604 + _is_mp3 = (ext == ".mp3");
  605 + _is_aac = (ext == ".aac");
  606 +}
  607 +
  608 +bool SrsLiveEntry::is_flv()
  609 +{
  610 + return _is_flv;
  611 +}
  612 +
  613 +bool SrsLiveEntry::is_ts()
  614 +{
  615 + return _is_ts;
  616 +}
  617 +
  618 +bool SrsLiveEntry::is_aac()
  619 +{
  620 + return _is_aac;
  621 +}
  622 +
  623 +bool SrsLiveEntry::is_mp3()
  624 +{
  625 + return _is_mp3;
  626 +}
  627 +
  628 +SrsHlsM3u8Stream::SrsHlsM3u8Stream()
  629 +{
  630 +}
  631 +
  632 +SrsHlsM3u8Stream::~SrsHlsM3u8Stream()
  633 +{
  634 +}
  635 +
  636 +void SrsHlsM3u8Stream::set_m3u8(std::string v)
  637 +{
  638 + m3u8 = v;
  639 +}
  640 +
  641 +int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  642 +{
  643 + int ret = ERROR_SUCCESS;
  644 +
  645 + std::string data = m3u8;
  646 +
  647 + w->header()->set_content_length((int)data.length());
  648 + w->header()->set_content_type("application/x-mpegURL;charset=utf-8");
  649 +
  650 + if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
  651 + if (!srs_is_client_gracefully_close(ret)) {
  652 + srs_error("send m3u8 failed. ret=%d", ret);
  653 + }
  654 + return ret;
  655 + }
  656 +
  657 + return ret;
  658 +}
  659 +
  660 +SrsHlsTsStream::SrsHlsTsStream()
  661 +{
  662 +}
  663 +
  664 +SrsHlsTsStream::~SrsHlsTsStream()
  665 +{
  666 +}
  667 +
  668 +void SrsHlsTsStream::set_ts(std::string v)
  669 +{
  670 + ts = v;
  671 +}
  672 +
  673 +int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  674 +{
  675 + int ret = ERROR_SUCCESS;
  676 +
  677 + std::string data = ts;
  678 +
  679 + w->header()->set_content_length((int)data.length());
  680 + w->header()->set_content_type("video/MP2T");
  681 +
  682 + if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
  683 + if (!srs_is_client_gracefully_close(ret)) {
  684 + srs_error("send ts failed. ret=%d", ret);
  685 + }
  686 + return ret;
  687 + }
  688 +
  689 + return ret;
  690 +}
  691 +
  692 +SrsHlsEntry::SrsHlsEntry()
  693 +{
  694 + tmpl = NULL;
  695 +}
  696 +
  697 +SrsHttpStreamServer::SrsHttpStreamServer(SrsServer* svr)
  698 +{
  699 + server = svr;
  700 +
  701 + mux.hijack(this);
  702 +}
  703 +
  704 +SrsHttpStreamServer::~SrsHttpStreamServer()
  705 +{
  706 + mux.unhijack(this);
  707 +
  708 + if (true) {
  709 + std::map<std::string, SrsLiveEntry*>::iterator it;
  710 + for (it = tflvs.begin(); it != tflvs.end(); ++it) {
  711 + SrsLiveEntry* entry = it->second;
  712 + srs_freep(entry);
  713 + }
  714 + tflvs.clear();
  715 + }
  716 + if (true) {
  717 + std::map<std::string, SrsLiveEntry*>::iterator it;
  718 + for (it = sflvs.begin(); it != sflvs.end(); ++it) {
  719 + SrsLiveEntry* entry = it->second;
  720 + srs_freep(entry);
  721 + }
  722 + sflvs.clear();
  723 + }
  724 + if (true) {
  725 + std::map<std::string, SrsHlsEntry*>::iterator it;
  726 + for (it = thls.begin(); it != thls.end(); ++it) {
  727 + SrsHlsEntry* entry = it->second;
  728 + srs_freep(entry);
  729 + }
  730 + thls.clear();
  731 + }
  732 + if (true) {
  733 + std::map<std::string, SrsHlsEntry*>::iterator it;
  734 + for (it = shls.begin(); it != shls.end(); ++it) {
  735 + SrsHlsEntry* entry = it->second;
  736 + srs_freep(entry);
  737 + }
  738 + shls.clear();
  739 + }
  740 +}
  741 +
  742 +int SrsHttpStreamServer::initialize()
  743 +{
  744 + int ret = ERROR_SUCCESS;
  745 +
  746 + // remux rtmp to flv live streaming
  747 + if ((ret = initialize_flv_streaming()) != ERROR_SUCCESS) {
  748 + return ret;
  749 + }
  750 +
  751 + // remux rtmp to hls live streaming
  752 + if ((ret = initialize_hls_streaming()) != ERROR_SUCCESS) {
  753 + return ret;
  754 + }
  755 +
  756 + return ret;
  757 +}
  758 +
  759 +// TODO: FIXME: rename for HTTP FLV mount.
  760 +int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r)
  761 +{
  762 + int ret = ERROR_SUCCESS;
  763 +
  764 + // the id to identify stream.
  765 + std::string sid = r->get_stream_url();
  766 + SrsLiveEntry* entry = NULL;
  767 +
  768 + // create stream from template when not found.
  769 + if (sflvs.find(sid) == sflvs.end()) {
  770 + if (tflvs.find(r->vhost) == tflvs.end()) {
  771 + srs_info("ignore mount flv stream for disabled");
  772 + return ret;
  773 + }
  774 +
  775 + SrsLiveEntry* tmpl = tflvs[r->vhost];
  776 +
  777 + std::string mount = tmpl->mount;
  778 +
  779 + // replace the vhost variable
  780 + mount = srs_string_replace(mount, "[vhost]", r->vhost);
  781 + mount = srs_string_replace(mount, "[app]", r->app);
  782 + mount = srs_string_replace(mount, "[stream]", r->stream);
  783 +
  784 + // remove the default vhost mount
  785 + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");
  786 +
  787 + entry = new SrsLiveEntry(mount, tmpl->hstrs);
  788 +
  789 + entry->cache = new SrsStreamCache(s, r);
  790 + entry->stream = new SrsLiveStream(s, r, entry->cache);
  791 +
  792 + sflvs[sid] = entry;
  793 +
  794 + // mount the http flv stream.
  795 + // we must register the handler, then start the thread,
  796 + // for the thread will cause thread switch context.
  797 + // @see https://github.com/simple-rtmp-server/srs/issues/404
  798 + if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) {
  799 + srs_error("http: mount flv stream for vhost=%s failed. ret=%d", sid.c_str(), ret);
  800 + return ret;
  801 + }
  802 +
  803 + // start http stream cache thread
  804 + if ((ret = entry->cache->start()) != ERROR_SUCCESS) {
  805 + srs_error("http: start stream cache failed. ret=%d", ret);
  806 + return ret;
  807 + }
  808 + srs_trace("http: mount flv stream for vhost=%s, mount=%s", sid.c_str(), mount.c_str());
  809 + } else {
  810 + entry = sflvs[sid];
  811 + }
  812 +
  813 + // TODO: FIXME: supports reload.
  814 + if (entry->stream) {
  815 + entry->stream->entry->enabled = true;
  816 + return ret;
  817 + }
  818 +
  819 + return ret;
  820 +}
  821 +
  822 +void SrsHttpStreamServer::http_unmount(SrsSource* s, SrsRequest* r)
  823 +{
  824 + std::string sid = r->get_stream_url();
  825 +
  826 + if (sflvs.find(sid) == sflvs.end()) {
  827 + srs_info("ignore unmount flv stream for disabled");
  828 + return;
  829 + }
  830 +
  831 + SrsLiveEntry* entry = sflvs[sid];
  832 + entry->stream->entry->enabled = false;
  833 +}
  834 +
  835 +int SrsHttpStreamServer::mount_hls(SrsRequest* r)
  836 +{
  837 + int ret = ERROR_SUCCESS;
  838 +
  839 + std::string sid = r->get_stream_url();
  840 +
  841 + if (shls.find(sid) == shls.end()) {
  842 + srs_info("ignore mount hls stream for disabled");
  843 + return ret;
  844 + }
  845 +
  846 + SrsHlsEntry* entry = shls[sid];
  847 +
  848 + // TODO: FIXME: supports reload.
  849 + std::map<std::string, ISrsHttpHandler*>::iterator it;
  850 + for (it = entry->streams.begin(); it != entry->streams.end(); ++it) {
  851 + ISrsHttpHandler* stream = it->second;
  852 + stream->entry->enabled = true;
  853 + }
  854 +
  855 + return ret;
  856 +}
  857 +
  858 +int SrsHttpStreamServer::hls_update_m3u8(SrsRequest* r, string m3u8)
  859 +{
  860 + int ret = ERROR_SUCCESS;
  861 +
  862 + std::string mount;
  863 +
  864 + std::string sid = r->get_stream_url();
  865 + SrsHlsEntry* entry = NULL;
  866 +
  867 + // create stream from template when not found.
  868 + if (shls.find(sid) == shls.end()) {
  869 + if (thls.find(r->vhost) == thls.end()) {
  870 + srs_info("ignore mount hls stream for disabled");
  871 + return ret;
  872 + }
  873 +
  874 + SrsHlsEntry* tmpl = thls[r->vhost];
  875 + srs_assert(tmpl);
  876 +
  877 + entry = new SrsHlsEntry();
  878 + mount = tmpl->mount;
  879 +
  880 + // replace the vhost variable
  881 + mount = srs_string_replace(mount, "[vhost]", r->vhost);
  882 + mount = srs_string_replace(mount, "[app]", r->app);
  883 + mount = srs_string_replace(mount, "[stream]", r->stream);
  884 +
  885 + // remove the default vhost mount
  886 + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");
  887 +
  888 + entry->tmpl = tmpl;
  889 + entry->mount = mount;
  890 + shls[sid] = entry;
  891 +
  892 + if (entry->streams.find(mount) == entry->streams.end()) {
  893 + ISrsHttpHandler* he = new SrsHlsM3u8Stream();
  894 + entry->streams[mount] = he;
  895 +
  896 + if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {
  897 + srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret);
  898 + return ret;
  899 + }
  900 + }
  901 + } else {
  902 + entry = shls[sid];
  903 + }
  904 +
  905 + mount = entry->mount;
  906 +
  907 + // update the m3u8 stream.
  908 + SrsHlsM3u8Stream* hms = dynamic_cast<SrsHlsM3u8Stream*>(entry->streams[mount]);
  909 + if (hms) {
  910 + hms->set_m3u8(m3u8);
  911 + }
  912 + srs_trace("hls update m3u8 ok, mount=%s", mount.c_str());
  913 +
  914 + return ret;
  915 +}
  916 +
  917 +int SrsHttpStreamServer::hls_update_ts(SrsRequest* r, string uri, string ts)
  918 +{
  919 + int ret = ERROR_SUCCESS;
  920 +
  921 + std::string sid = r->get_stream_url();
  922 +
  923 + // when no hls mounted, init with empty m3u8.
  924 + if (shls.find(sid) == shls.end()) {
  925 + if ((ret = hls_update_m3u8(r, "")) != ERROR_SUCCESS) {
  926 + return ret;
  927 + }
  928 + }
  929 +
  930 + // find again, ignore if not exits.
  931 + if (shls.find(sid) == shls.end()) {
  932 + return ret;
  933 + }
  934 +
  935 + SrsHlsEntry* entry = shls[sid];
  936 + srs_assert(entry);
  937 + srs_assert(entry->tmpl);
  938 +
  939 + std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount);
  940 +
  941 + if (entry->streams.find(mount) == entry->streams.end()) {
  942 + ISrsHttpHandler* he = new SrsHlsTsStream();
  943 + entry->streams[mount] = he;
  944 +
  945 + if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) {
  946 + srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret);
  947 + return ret;
  948 + }
  949 + }
  950 +
  951 + // update the ts stream.
  952 + SrsHlsTsStream* hts = dynamic_cast<SrsHlsTsStream*>(entry->streams[mount]);
  953 + if (hts) {
  954 + hts->set_ts(ts);
  955 + }
  956 + srs_trace("hls update ts ok, mount=%s", mount.c_str());
  957 +
  958 + return ret;
  959 +}
  960 +
  961 +
  962 +int SrsHttpStreamServer::hls_remove_ts(SrsRequest* r, string uri)
  963 +{
  964 + int ret = ERROR_SUCCESS;
  965 +
  966 + std::string sid = r->get_stream_url();
  967 +
  968 + // when no hls mounted, ignore.
  969 + if (shls.find(sid) == shls.end()) {
  970 + return ret;
  971 + }
  972 +
  973 + SrsHlsEntry* entry = shls[sid];
  974 + srs_assert(entry);
  975 + srs_assert(entry->tmpl);
  976 +
  977 + std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount);
  978 +
  979 + // ignore when no ts mounted.
  980 + if (entry->streams.find(mount) == entry->streams.end()) {
  981 + return ret;
  982 + }
  983 +
  984 + // update the ts stream.
  985 + SrsHlsTsStream* hts = dynamic_cast<SrsHlsTsStream*>(entry->streams[mount]);
  986 + if (hts) {
  987 + hts->set_ts("");
  988 + // TODO: FIXME: unmount and remove the http handler.
  989 + }
  990 + srs_trace("hls remove ts ok, mount=%s", mount.c_str());
  991 +
  992 + return ret;
  993 +}
  994 +
  995 +void SrsHttpStreamServer::unmount_hls(SrsRequest* r)
  996 +{
  997 + std::string sid = r->get_stream_url();
  998 +
  999 + if (shls.find(sid) == shls.end()) {
  1000 + srs_info("ignore unmount hls stream for disabled");
  1001 + return;
  1002 + }
  1003 +
  1004 + SrsHlsEntry* entry = shls[sid];
  1005 +
  1006 + std::map<std::string, ISrsHttpHandler*>::iterator it;
  1007 + for (it = entry->streams.begin(); it != entry->streams.end(); ++it) {
  1008 + ISrsHttpHandler* stream = it->second;
  1009 + stream->entry->enabled = false;
  1010 + }
  1011 +}
  1012 +
  1013 +int SrsHttpStreamServer::on_reload_vhost_http_remux_updated()
  1014 +{
  1015 + int ret = ERROR_SUCCESS;
  1016 + // TODO: FIXME: implements it.
  1017 + return ret;
  1018 +}
  1019 +
  1020 +int SrsHttpStreamServer::on_reload_vhost_hls(string vhost)
  1021 +{
  1022 + int ret = ERROR_SUCCESS;
  1023 + // TODO: FIXME: implements it.
  1024 + return ret;
  1025 +}
  1026 +
  1027 +int SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph)
  1028 +{
  1029 + int ret = ERROR_SUCCESS;
  1030 +
  1031 + // when handler not the root, we think the handler is ok.
  1032 + ISrsHttpHandler* h = *ph? *ph : NULL;
  1033 + if (h && h->entry && h->entry->pattern != "/") {
  1034 + return ret;
  1035 + }
  1036 +
  1037 + // only hijack for http streaming, http-flv/ts/mp3/aac.
  1038 + std::string ext = request->ext();
  1039 + if (ext.empty()) {
  1040 + return ret;
  1041 + }
  1042 +
  1043 + // find the actually request vhost.
  1044 + SrsConfDirective* vhost = _srs_config->get_vhost(request->host());
  1045 + if (!vhost || !_srs_config->get_vhost_enabled(vhost)) {
  1046 + return ret;
  1047 + }
  1048 +
  1049 + // find the entry template for the stream.
  1050 + SrsLiveEntry* entry = NULL;
  1051 + if (true) {
  1052 + // no http streaming on vhost, ignore.
  1053 + std::map<std::string, SrsLiveEntry*>::iterator it = tflvs.find(vhost->arg0());
  1054 + if (it == tflvs.end()) {
  1055 + return ret;
  1056 + }
  1057 +
  1058 + // hstrs not enabled, ignore.
  1059 + entry = it->second;
  1060 + if (!entry->hstrs) {
  1061 + return ret;
  1062 + }
  1063 +
  1064 + // check entry and request extension.
  1065 + if (entry->is_flv()) {
  1066 + if (ext != ".flv") {
  1067 + return ret;
  1068 + }
  1069 + } else if (entry->is_ts()) {
  1070 + if (ext != ".ts") {
  1071 + return ret;
  1072 + }
  1073 + } else if (entry->is_mp3()) {
  1074 + if (ext != ".mp3") {
  1075 + return ret;
  1076 + }
  1077 + } else if (entry->is_aac()) {
  1078 + if (ext != ".aac") {
  1079 + return ret;
  1080 + }
  1081 + } else {
  1082 + return ret;
  1083 + }
  1084 + }
  1085 +
  1086 + // convert to concreate class.
  1087 + SrsHttpMessage* hreq = dynamic_cast<SrsHttpMessage*>(request);
  1088 + srs_assert(hreq);
  1089 +
  1090 + // hijack for entry.
  1091 + SrsRequest* r = hreq->to_request(vhost->arg0());
  1092 + SrsAutoFree(SrsRequest, r);
  1093 + SrsSource* s = SrsSource::fetch(r);
  1094 + if (!s) {
  1095 + if ((ret = SrsSource::create(r, server, server, &s)) != ERROR_SUCCESS) {
  1096 + return ret;
  1097 + }
  1098 + }
  1099 + srs_assert(s != NULL);
  1100 +
  1101 + // create http streaming handler.
  1102 + if ((ret = http_mount(s, r)) != ERROR_SUCCESS) {
  1103 + return ret;
  1104 + }
  1105 +
  1106 + // use the handler if exists.
  1107 + if (ph) {
  1108 + std::string sid = r->get_stream_url();
  1109 + if (sflvs.find(sid) != sflvs.end()) {
  1110 + entry = sflvs[sid];
  1111 + *ph = entry->stream;
  1112 + }
  1113 + }
  1114 +
  1115 + // trigger edge to fetch from origin.
  1116 + bool vhost_is_edge = _srs_config->get_vhost_is_edge(r->vhost);
  1117 + srs_trace("hstrs: source url=%s, is_edge=%d, source_id=%d[%d]",
  1118 + r->get_stream_url().c_str(), vhost_is_edge, s->source_id(), s->source_id());
  1119 +
  1120 + // TODO: FIXME: disconnect when all connection closed.
  1121 + if (vhost_is_edge) {
  1122 + // notice edge to start for the first client.
  1123 + if ((ret = s->on_edge_start_play()) != ERROR_SUCCESS) {
  1124 + srs_error("notice edge start play stream failed. ret=%d", ret);
  1125 + return ret;
  1126 + }
  1127 + }
  1128 +
  1129 + return ret;
  1130 +}
  1131 +
  1132 +int SrsHttpStreamServer::initialize_flv_streaming()
  1133 +{
  1134 + int ret = ERROR_SUCCESS;
  1135 +
  1136 + // http flv live stream mount for each vhost.
  1137 + SrsConfDirective* root = _srs_config->get_root();
  1138 + for (int i = 0; i < (int)root->directives.size(); i++) {
  1139 + SrsConfDirective* conf = root->at(i);
  1140 +
  1141 + if (!conf->is_vhost()) {
  1142 + continue;
  1143 + }
  1144 +
  1145 + std::string vhost = conf->arg0();
  1146 + if (!_srs_config->get_vhost_http_remux_enabled(vhost)) {
  1147 + continue;
  1148 + }
  1149 +
  1150 + SrsLiveEntry* entry = new SrsLiveEntry(
  1151 + _srs_config->get_vhost_http_remux_mount(vhost),
  1152 + _srs_config->get_vhost_http_remux_hstrs(vhost)
  1153 + );
  1154 + tflvs[vhost] = entry;
  1155 + srs_trace("http flv live stream, vhost=%s, mount=%s",
  1156 + vhost.c_str(), entry->mount.c_str());
  1157 + }
  1158 +
  1159 + return ret;
  1160 +}
  1161 +
  1162 +int SrsHttpStreamServer::initialize_hls_streaming()
  1163 +{
  1164 + int ret = ERROR_SUCCESS;
  1165 +
  1166 + // http hls live stream mount for each vhost.
  1167 + SrsConfDirective* root = _srs_config->get_root();
  1168 + for (int i = 0; i < (int)root->directives.size(); i++) {
  1169 + SrsConfDirective* conf = root->at(i);
  1170 +
  1171 + if (!conf->is_vhost()) {
  1172 + continue;
  1173 + }
  1174 +
  1175 + std::string vhost = conf->arg0();
  1176 + if (!_srs_config->get_hls_enabled(vhost)) {
  1177 + continue;
  1178 + }
  1179 +
  1180 + std::string storage = _srs_config->get_hls_storage(vhost);
  1181 + if (storage != "ram" && storage != "both") {
  1182 + continue;
  1183 + }
  1184 +
  1185 + SrsHlsEntry* entry = new SrsHlsEntry();
  1186 + entry->mount = _srs_config->get_hls_mount(vhost);
  1187 + thls[vhost] = entry;
  1188 + srs_trace("http hls live stream, vhost=%s, mount=%s",
  1189 + vhost.c_str(), entry->mount.c_str());
  1190 + }
  1191 +
  1192 + return ret;
  1193 +}
  1194 +
  1195 +string SrsHttpStreamServer::hls_mount_generate(SrsRequest* r, string uri, string tmpl)
  1196 +{
  1197 + std::string mount = tmpl;
  1198 +
  1199 + // the ts is relative from the m3u8, the same start dir.
  1200 + size_t pos = string::npos;
  1201 + if ((pos = mount.rfind("/")) != string::npos) {
  1202 + mount = mount.substr(0, pos);
  1203 + }
  1204 +
  1205 + // replace the vhost variable
  1206 + mount = srs_string_replace(mount, "[vhost]", r->vhost);
  1207 + mount = srs_string_replace(mount, "[app]", r->app);
  1208 +
  1209 + // remove the default vhost mount
  1210 + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");
  1211 +
  1212 + // mount with ts.
  1213 + mount += "/";
  1214 + mount += uri;
  1215 +
  1216 + return mount;
  1217 +}
  1218 +
  1219 +#endif
  1220 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 SRS(simple-rtmp-server)
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_APP_HTTP_STREAM_HPP
  25 +#define SRS_APP_HTTP_STREAM_HPP
  26 +
  27 +/*
  28 +#include <srs_app_http_stream.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <srs_app_http_conn.hpp>
  34 +
  35 +#ifdef SRS_AUTO_HTTP_SERVER
  36 +
  37 +/**
  38 +* for the srs http stream cache,
  39 +* for example, the audio stream cache to make android(weixin) happy.
  40 +* we start a thread to shrink the queue.
  41 +*/
  42 +class SrsStreamCache : public ISrsEndlessThreadHandler
  43 +{
  44 +private:
  45 + SrsMessageQueue* queue;
  46 + SrsSource* source;
  47 + SrsRequest* req;
  48 + SrsEndlessThread* pthread;
  49 +public:
  50 + SrsStreamCache(SrsSource* s, SrsRequest* r);
  51 + virtual ~SrsStreamCache();
  52 +public:
  53 + virtual int start();
  54 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);
  55 +// interface ISrsEndlessThreadHandler.
  56 +public:
  57 + virtual int cycle();
  58 +};
  59 +
  60 +/**
  61 +* the stream encoder in some codec, for example, flv or aac.
  62 +*/
  63 +class ISrsStreamEncoder
  64 +{
  65 +public:
  66 + ISrsStreamEncoder();
  67 + virtual ~ISrsStreamEncoder();
  68 +public:
  69 + /**
  70 + * initialize the encoder with file writer(to http response) and stream cache.
  71 + * @param w the writer to write to http response.
  72 + * @param c the stream cache for audio stream fast startup.
  73 + */
  74 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c) = 0;
  75 + /**
  76 + * write rtmp video/audio/metadata.
  77 + */
  78 + virtual int write_audio(int64_t timestamp, char* data, int size) = 0;
  79 + virtual int write_video(int64_t timestamp, char* data, int size) = 0;
  80 + virtual int write_metadata(int64_t timestamp, char* data, int size) = 0;
  81 +public:
  82 + /**
  83 + * for some stream, for example, mp3 and aac, the audio stream,
  84 + * we use large gop cache in encoder, for the gop cache of SrsSource is ignore audio.
  85 + * @return true to use gop cache of encoder; otherwise, use SrsSource.
  86 + */
  87 + virtual bool has_cache() = 0;
  88 + /**
  89 + * dumps the cache of encoder to consumer.
  90 + */
  91 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter) = 0;
  92 +};
  93 +
  94 +/**
  95 +* the flv stream encoder, remux rtmp stream to flv stream.
  96 +*/
  97 +class SrsFlvStreamEncoder : public ISrsStreamEncoder
  98 +{
  99 +protected:
  100 + SrsFlvEncoder* enc;
  101 +public:
  102 + SrsFlvStreamEncoder();
  103 + virtual ~SrsFlvStreamEncoder();
  104 +public:
  105 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
  106 + virtual int write_audio(int64_t timestamp, char* data, int size);
  107 + virtual int write_video(int64_t timestamp, char* data, int size);
  108 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  109 +public:
  110 + virtual bool has_cache();
  111 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);
  112 +};
  113 +
  114 +#ifdef SRS_PERF_FAST_FLV_ENCODER
  115 +/**
  116 + * the fast flv stream encoder.
  117 + * @see https://github.com/simple-rtmp-server/srs/issues/405
  118 + */
  119 +class SrsFastFlvStreamEncoder : public SrsFlvStreamEncoder
  120 +{
  121 +public:
  122 + SrsFastFlvStreamEncoder();
  123 + virtual ~SrsFastFlvStreamEncoder();
  124 +public:
  125 + /**
  126 + * write the tags in a time.
  127 + */
  128 + virtual int write_tags(SrsSharedPtrMessage** msgs, int count);
  129 +};
  130 +#endif
  131 +
  132 +/**
  133 +* the ts stream encoder, remux rtmp stream to ts stream.
  134 +*/
  135 +class SrsTsStreamEncoder : public ISrsStreamEncoder
  136 +{
  137 +private:
  138 + SrsTsEncoder* enc;
  139 +public:
  140 + SrsTsStreamEncoder();
  141 + virtual ~SrsTsStreamEncoder();
  142 +public:
  143 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
  144 + virtual int write_audio(int64_t timestamp, char* data, int size);
  145 + virtual int write_video(int64_t timestamp, char* data, int size);
  146 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  147 +public:
  148 + virtual bool has_cache();
  149 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);
  150 +};
  151 +
  152 +/**
  153 +* the aac stream encoder, remux rtmp stream to aac stream.
  154 +*/
  155 +class SrsAacStreamEncoder : public ISrsStreamEncoder
  156 +{
  157 +private:
  158 + SrsAacEncoder* enc;
  159 + SrsStreamCache* cache;
  160 +public:
  161 + SrsAacStreamEncoder();
  162 + virtual ~SrsAacStreamEncoder();
  163 +public:
  164 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
  165 + virtual int write_audio(int64_t timestamp, char* data, int size);
  166 + virtual int write_video(int64_t timestamp, char* data, int size);
  167 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  168 +public:
  169 + virtual bool has_cache();
  170 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);
  171 +};
  172 +
  173 +/**
  174 +* the mp3 stream encoder, remux rtmp stream to mp3 stream.
  175 +*/
  176 +class SrsMp3StreamEncoder : public ISrsStreamEncoder
  177 +{
  178 +private:
  179 + SrsMp3Encoder* enc;
  180 + SrsStreamCache* cache;
  181 +public:
  182 + SrsMp3StreamEncoder();
  183 + virtual ~SrsMp3StreamEncoder();
  184 +public:
  185 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
  186 + virtual int write_audio(int64_t timestamp, char* data, int size);
  187 + virtual int write_video(int64_t timestamp, char* data, int size);
  188 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  189 +public:
  190 + virtual bool has_cache();
  191 + virtual int dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter);
  192 +};
  193 +
  194 +/**
  195 +* write stream to http response direclty.
  196 +*/
  197 +class SrsStreamWriter : public SrsFileWriter
  198 +{
  199 +private:
  200 + ISrsHttpResponseWriter* writer;
  201 +public:
  202 + SrsStreamWriter(ISrsHttpResponseWriter* w);
  203 + virtual ~SrsStreamWriter();
  204 +public:
  205 + virtual int open(std::string file);
  206 + virtual void close();
  207 +public:
  208 + virtual bool is_open();
  209 + virtual int64_t tellg();
  210 +public:
  211 + virtual int write(void* buf, size_t count, ssize_t* pnwrite);
  212 + virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
  213 +};
  214 +
  215 +/**
  216 +* the flv live stream supports access rtmp in flv over http.
  217 +* srs will remux rtmp to flv streaming.
  218 +*/
  219 +class SrsLiveStream : public ISrsHttpHandler
  220 +{
  221 +private:
  222 + SrsRequest* req;
  223 + SrsSource* source;
  224 + SrsStreamCache* cache;
  225 +public:
  226 + SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c);
  227 + virtual ~SrsLiveStream();
  228 +public:
  229 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  230 +private:
  231 + virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs);
  232 +};
  233 +
  234 +/**
  235 +* the srs live entry
  236 +*/
  237 +struct SrsLiveEntry
  238 +{
  239 +private:
  240 + bool _is_flv;
  241 + bool _is_ts;
  242 + bool _is_aac;
  243 + bool _is_mp3;
  244 +public:
  245 + // for template, the mount contains variables.
  246 + // for concrete stream, the mount is url to access.
  247 + std::string mount;
  248 + // whether hstrs(http stream trigger rtmp source)
  249 + bool hstrs;
  250 +
  251 + SrsLiveStream* stream;
  252 + SrsStreamCache* cache;
  253 +
  254 + SrsLiveEntry(std::string m, bool h);
  255 +
  256 + bool is_flv();
  257 + bool is_ts();
  258 + bool is_mp3();
  259 + bool is_aac();
  260 +};
  261 +
  262 +/**
  263 +* the m3u8 stream handler.
  264 +*/
  265 +class SrsHlsM3u8Stream : public ISrsHttpHandler
  266 +{
  267 +private:
  268 + std::string m3u8;
  269 +public:
  270 + SrsHlsM3u8Stream();
  271 + virtual ~SrsHlsM3u8Stream();
  272 +public:
  273 + virtual void set_m3u8(std::string v);
  274 +public:
  275 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  276 +};
  277 +
  278 +/**
  279 +* the ts stream handler.
  280 +*/
  281 +class SrsHlsTsStream : public ISrsHttpHandler
  282 +{
  283 +private:
  284 + std::string ts;
  285 +public:
  286 + SrsHlsTsStream();
  287 + virtual ~SrsHlsTsStream();
  288 +public:
  289 + virtual void set_ts(std::string v);
  290 +public:
  291 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  292 +};
  293 +
  294 +/**
  295 +* the srs hls entry.
  296 +*/
  297 +// TODO: FIXME: use hte hls template and entry.
  298 +struct SrsHlsEntry
  299 +{
  300 + // for template, the mount contains variables.
  301 + // for concrete stream, the mount is url to access.
  302 + std::string mount;
  303 +
  304 + // the template to create the entry
  305 + SrsHlsEntry* tmpl;
  306 +
  307 + // key: the m3u8/ts file path.
  308 + // value: the http handler.
  309 + std::map<std::string, ISrsHttpHandler*> streams;
  310 +
  311 + SrsHlsEntry();
  312 +};
  313 +
  314 +/**
  315 +* the http stream server instance,
  316 +* serve http stream, for example, flv/ts/mp3/aac live stream.
  317 +*/
  318 +class SrsHttpStreamServer : virtual public ISrsReloadHandler
  319 + , virtual public ISrsHttpMatchHijacker
  320 +{
  321 +private:
  322 + SrsServer* server;
  323 +public:
  324 + SrsHttpServeMux mux;
  325 + // the http live streaming template, to create streams.
  326 + std::map<std::string, SrsLiveEntry*> tflvs;
  327 + // the http live streaming streams, crote by template.
  328 + std::map<std::string, SrsLiveEntry*> sflvs;
  329 + // the hls live streaming template, to create streams.
  330 + std::map<std::string, SrsHlsEntry*> thls;
  331 + // the hls live streaming streams, crote by template.
  332 + std::map<std::string, SrsHlsEntry*> shls;
  333 +public:
  334 + SrsHttpStreamServer(SrsServer* svr);
  335 + virtual ~SrsHttpStreamServer();
  336 +public:
  337 + virtual int initialize();
  338 +// http flv/ts/mp3/aac stream
  339 +public:
  340 + virtual int http_mount(SrsSource* s, SrsRequest* r);
  341 + virtual void http_unmount(SrsSource* s, SrsRequest* r);
  342 +// hls stream
  343 +public:
  344 + virtual int mount_hls(SrsRequest* r);
  345 + virtual int hls_update_m3u8(SrsRequest* r, std::string m3u8);
  346 + virtual int hls_update_ts(SrsRequest* r, std::string uri, std::string ts);
  347 + virtual int hls_remove_ts(SrsRequest* r, std::string uri);
  348 + virtual void unmount_hls(SrsRequest* r);
  349 +// interface ISrsReloadHandler.
  350 +public:
  351 + virtual int on_reload_vhost_http_remux_updated();
  352 + virtual int on_reload_vhost_hls(std::string vhost);
  353 +// interface ISrsHttpMatchHijacker
  354 +public:
  355 + virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph);
  356 +private:
  357 + virtual int initialize_flv_streaming();
  358 + virtual int initialize_hls_streaming();
  359 + virtual std::string hls_mount_generate(SrsRequest* r, std::string uri, std::string tmpl);
  360 +};
  361 +
  362 +#endif
  363 +
  364 +#endif
  365 +
@@ -496,7 +496,7 @@ SrsServer::SrsServer() @@ -496,7 +496,7 @@ SrsServer::SrsServer()
496 http_api_mux = new SrsHttpServeMux(); 496 http_api_mux = new SrsHttpServeMux();
497 #endif 497 #endif
498 #ifdef SRS_AUTO_HTTP_SERVER 498 #ifdef SRS_AUTO_HTTP_SERVER
499 - http_stream_mux = new SrsHttpServer(this); 499 + http_server = new SrsHttpServer(this);
500 #endif 500 #endif
501 #ifdef SRS_AUTO_HTTP_CORE 501 #ifdef SRS_AUTO_HTTP_CORE
502 http_heartbeat = NULL; 502 http_heartbeat = NULL;
@@ -522,7 +522,7 @@ void SrsServer::destroy() @@ -522,7 +522,7 @@ void SrsServer::destroy()
522 #endif 522 #endif
523 523
524 #ifdef SRS_AUTO_HTTP_SERVER 524 #ifdef SRS_AUTO_HTTP_SERVER
525 - srs_freep(http_stream_mux); 525 + srs_freep(http_server);
526 #endif 526 #endif
527 527
528 #ifdef SRS_AUTO_HTTP_CORE 528 #ifdef SRS_AUTO_HTTP_CORE
@@ -602,8 +602,8 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler) @@ -602,8 +602,8 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler)
602 #endif 602 #endif
603 603
604 #ifdef SRS_AUTO_HTTP_SERVER 604 #ifdef SRS_AUTO_HTTP_SERVER
605 - srs_assert(http_stream_mux);  
606 - if ((ret = http_stream_mux->initialize()) != ERROR_SUCCESS) { 605 + srs_assert(http_server);
  606 + if ((ret = http_server->initialize()) != ERROR_SUCCESS) {
607 return ret; 607 return ret;
608 } 608 }
609 #endif 609 #endif
@@ -810,13 +810,6 @@ int SrsServer::http_handle() @@ -810,13 +810,6 @@ int SrsServer::http_handle()
810 return ret; 810 return ret;
811 } 811 }
812 #endif 812 #endif
813 -  
814 -#if defined(SRS_AUTO_HTTP_SERVER) && defined(SRS_AUTO_HTTP_API)  
815 - // for SRS go-sharp to detect the status of HTTP server of SRS HTTP FLV Cluster.  
816 - if ((ret = http_stream_mux->mux.handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) {  
817 - return ret;  
818 - }  
819 -#endif  
820 813
821 return ret; 814 return ret;
822 } 815 }
@@ -1226,7 +1219,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) @@ -1226,7 +1219,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
1226 #endif 1219 #endif
1227 } else if (type == SrsListenerHttpStream) { 1220 } else if (type == SrsListenerHttpStream) {
1228 #ifdef SRS_AUTO_HTTP_SERVER 1221 #ifdef SRS_AUTO_HTTP_SERVER
1229 - conn = new SrsStaticHttpConn(this, client_stfd, &http_stream_mux->mux); 1222 + conn = new SrsStaticHttpConn(this, client_stfd, http_server);
1230 #else 1223 #else
1231 srs_warn("close http client for server not support http-server"); 1224 srs_warn("close http client for server not support http-server");
1232 srs_close_stfd(client_stfd); 1225 srs_close_stfd(client_stfd);
@@ -1364,7 +1357,7 @@ int SrsServer::on_publish(SrsSource* s, SrsRequest* r) @@ -1364,7 +1357,7 @@ int SrsServer::on_publish(SrsSource* s, SrsRequest* r)
1364 int ret = ERROR_SUCCESS; 1357 int ret = ERROR_SUCCESS;
1365 1358
1366 #ifdef SRS_AUTO_HTTP_SERVER 1359 #ifdef SRS_AUTO_HTTP_SERVER
1367 - if ((ret = http_stream_mux->http_mount(s, r)) != ERROR_SUCCESS) { 1360 + if ((ret = http_server->http_mount(s, r)) != ERROR_SUCCESS) {
1368 return ret; 1361 return ret;
1369 } 1362 }
1370 #endif 1363 #endif
@@ -1375,7 +1368,7 @@ int SrsServer::on_publish(SrsSource* s, SrsRequest* r) @@ -1375,7 +1368,7 @@ int SrsServer::on_publish(SrsSource* s, SrsRequest* r)
1375 void SrsServer::on_unpublish(SrsSource* s, SrsRequest* r) 1368 void SrsServer::on_unpublish(SrsSource* s, SrsRequest* r)
1376 { 1369 {
1377 #ifdef SRS_AUTO_HTTP_SERVER 1370 #ifdef SRS_AUTO_HTTP_SERVER
1378 - http_stream_mux->http_unmount(s, r); 1371 + http_server->http_unmount(s, r);
1379 #endif 1372 #endif
1380 } 1373 }
1381 1374
@@ -1384,7 +1377,7 @@ int SrsServer::on_hls_publish(SrsRequest* r) @@ -1384,7 +1377,7 @@ int SrsServer::on_hls_publish(SrsRequest* r)
1384 int ret = ERROR_SUCCESS; 1377 int ret = ERROR_SUCCESS;
1385 1378
1386 #ifdef SRS_AUTO_HTTP_SERVER 1379 #ifdef SRS_AUTO_HTTP_SERVER
1387 - if ((ret = http_stream_mux->mount_hls(r)) != ERROR_SUCCESS) { 1380 + if ((ret = http_server->mount_hls(r)) != ERROR_SUCCESS) {
1388 return ret; 1381 return ret;
1389 } 1382 }
1390 #endif 1383 #endif
@@ -1397,7 +1390,7 @@ int SrsServer::on_update_m3u8(SrsRequest* r, string m3u8) @@ -1397,7 +1390,7 @@ int SrsServer::on_update_m3u8(SrsRequest* r, string m3u8)
1397 int ret = ERROR_SUCCESS; 1390 int ret = ERROR_SUCCESS;
1398 1391
1399 #ifdef SRS_AUTO_HTTP_SERVER 1392 #ifdef SRS_AUTO_HTTP_SERVER
1400 - if ((ret = http_stream_mux->hls_update_m3u8(r, m3u8)) != ERROR_SUCCESS) { 1393 + if ((ret = http_server->hls_update_m3u8(r, m3u8)) != ERROR_SUCCESS) {
1401 return ret; 1394 return ret;
1402 } 1395 }
1403 #endif 1396 #endif
@@ -1410,7 +1403,7 @@ int SrsServer::on_update_ts(SrsRequest* r, string uri, string ts) @@ -1410,7 +1403,7 @@ int SrsServer::on_update_ts(SrsRequest* r, string uri, string ts)
1410 int ret = ERROR_SUCCESS; 1403 int ret = ERROR_SUCCESS;
1411 1404
1412 #ifdef SRS_AUTO_HTTP_SERVER 1405 #ifdef SRS_AUTO_HTTP_SERVER
1413 - if ((ret = http_stream_mux->hls_update_ts(r, uri, ts)) != ERROR_SUCCESS) { 1406 + if ((ret = http_server->hls_update_ts(r, uri, ts)) != ERROR_SUCCESS) {
1414 return ret; 1407 return ret;
1415 } 1408 }
1416 #endif 1409 #endif
@@ -1424,7 +1417,7 @@ int SrsServer::on_remove_ts(SrsRequest* r, string uri) @@ -1424,7 +1417,7 @@ int SrsServer::on_remove_ts(SrsRequest* r, string uri)
1424 int ret = ERROR_SUCCESS; 1417 int ret = ERROR_SUCCESS;
1425 1418
1426 #ifdef SRS_AUTO_HTTP_SERVER 1419 #ifdef SRS_AUTO_HTTP_SERVER
1427 - if ((ret = http_stream_mux->hls_remove_ts(r, uri)) != ERROR_SUCCESS) { 1420 + if ((ret = http_server->hls_remove_ts(r, uri)) != ERROR_SUCCESS) {
1428 return ret; 1421 return ret;
1429 } 1422 }
1430 #endif 1423 #endif
@@ -1437,7 +1430,7 @@ int SrsServer::on_hls_unpublish(SrsRequest* r) @@ -1437,7 +1430,7 @@ int SrsServer::on_hls_unpublish(SrsRequest* r)
1437 int ret = ERROR_SUCCESS; 1430 int ret = ERROR_SUCCESS;
1438 1431
1439 #ifdef SRS_AUTO_HTTP_SERVER 1432 #ifdef SRS_AUTO_HTTP_SERVER
1440 - http_stream_mux->unmount_hls(r); 1433 + http_server->unmount_hls(r);
1441 #endif 1434 #endif
1442 1435
1443 return ret; 1436 return ret;
@@ -235,10 +235,11 @@ class SrsServer : virtual public ISrsReloadHandler @@ -235,10 +235,11 @@ class SrsServer : virtual public ISrsReloadHandler
235 { 235 {
236 private: 236 private:
237 #ifdef SRS_AUTO_HTTP_API 237 #ifdef SRS_AUTO_HTTP_API
  238 + // TODO: FIXME: rename to http_api
238 SrsHttpServeMux* http_api_mux; 239 SrsHttpServeMux* http_api_mux;
239 #endif 240 #endif
240 #ifdef SRS_AUTO_HTTP_SERVER 241 #ifdef SRS_AUTO_HTTP_SERVER
241 - SrsHttpServer* http_stream_mux; 242 + SrsHttpServer* http_server;
242 #endif 243 #endif
243 #ifdef SRS_AUTO_HTTP_CORE 244 #ifdef SRS_AUTO_HTTP_CORE
244 SrsHttpHeartbeat* http_heartbeat; 245 SrsHttpHeartbeat* http_heartbeat;
@@ -228,6 +228,11 @@ ISrsHttpHandler::~ISrsHttpHandler() @@ -228,6 +228,11 @@ ISrsHttpHandler::~ISrsHttpHandler()
228 { 228 {
229 } 229 }
230 230
  231 +bool ISrsHttpHandler::is_not_found()
  232 +{
  233 + return false;
  234 +}
  235 +
231 SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c) 236 SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c)
232 { 237 {
233 url = u; 238 url = u;
@@ -253,6 +258,11 @@ SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler() @@ -253,6 +258,11 @@ SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler()
253 { 258 {
254 } 259 }
255 260
  261 +bool SrsHttpNotFoundHandler::is_not_found()
  262 +{
  263 + return true;
  264 +}
  265 +
256 int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) 266 int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
257 { 267 {
258 return srs_go_http_error(w, SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); 268 return srs_go_http_error(w, SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);
@@ -487,6 +497,14 @@ ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker() @@ -487,6 +497,14 @@ ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker()
487 { 497 {
488 } 498 }
489 499
  500 +ISrsHttpServeMux::ISrsHttpServeMux()
  501 +{
  502 +}
  503 +
  504 +ISrsHttpServeMux::~ISrsHttpServeMux()
  505 +{
  506 +}
  507 +
490 SrsHttpServeMux::SrsHttpServeMux() 508 SrsHttpServeMux::SrsHttpServeMux()
491 { 509 {
492 } 510 }
@@ -604,6 +622,19 @@ int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler) @@ -604,6 +622,19 @@ int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler)
604 return ret; 622 return ret;
605 } 623 }
606 624
  625 +bool SrsHttpServeMux::can_serve(ISrsHttpMessage* r)
  626 +{
  627 + int ret = ERROR_SUCCESS;
  628 +
  629 + ISrsHttpHandler* h = NULL;
  630 + if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) {
  631 + return false;
  632 + }
  633 +
  634 + srs_assert(h);
  635 + return !h->is_not_found();
  636 +}
  637 +
607 int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) 638 int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
608 { 639 {
609 int ret = ERROR_SUCCESS; 640 int ret = ERROR_SUCCESS;
@@ -654,9 +685,9 @@ int SrsHttpServeMux::find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph) @@ -654,9 +685,9 @@ int SrsHttpServeMux::find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph)
654 } 685 }
655 } 686 }
656 687
  688 + static ISrsHttpHandler* h404 = new SrsHttpNotFoundHandler();
657 if (*ph == NULL) { 689 if (*ph == NULL) {
658 - // TODO: FIXME: memory leak.  
659 - *ph = new SrsHttpNotFoundHandler(); 690 + *ph = h404;
660 } 691 }
661 692
662 return ret; 693 return ret;
@@ -247,6 +247,7 @@ public: @@ -247,6 +247,7 @@ public:
247 ISrsHttpHandler(); 247 ISrsHttpHandler();
248 virtual ~ISrsHttpHandler(); 248 virtual ~ISrsHttpHandler();
249 public: 249 public:
  250 + virtual bool is_not_found();
250 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) = 0; 251 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) = 0;
251 }; 252 };
252 253
@@ -270,6 +271,7 @@ public: @@ -270,6 +271,7 @@ public:
270 SrsHttpNotFoundHandler(); 271 SrsHttpNotFoundHandler();
271 virtual ~SrsHttpNotFoundHandler(); 272 virtual ~SrsHttpNotFoundHandler();
272 public: 273 public:
  274 + virtual bool is_not_found();
273 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); 275 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
274 }; 276 };
275 277
@@ -347,6 +349,18 @@ public: @@ -347,6 +349,18 @@ public:
347 virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) = 0; 349 virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) = 0;
348 }; 350 };
349 351
  352 +/**
  353 + * the server mux, all http server should implements it.
  354 + */
  355 +class ISrsHttpServeMux
  356 +{
  357 +public:
  358 + ISrsHttpServeMux();
  359 + virtual ~ISrsHttpServeMux();
  360 +public:
  361 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) = 0;
  362 +};
  363 +
350 // ServeMux is an HTTP request multiplexer. 364 // ServeMux is an HTTP request multiplexer.
351 // It matches the URL of each incoming request against a list of registered 365 // It matches the URL of each incoming request against a list of registered
352 // patterns and calls the handler for the pattern that 366 // patterns and calls the handler for the pattern that
@@ -374,7 +388,7 @@ public: @@ -374,7 +388,7 @@ public:
374 // ServeMux also takes care of sanitizing the URL request path, 388 // ServeMux also takes care of sanitizing the URL request path,
375 // redirecting any request containing . or .. elements to an 389 // redirecting any request containing . or .. elements to an
376 // equivalent .- and ..-free URL. 390 // equivalent .- and ..-free URL.
377 -class SrsHttpServeMux 391 +class SrsHttpServeMux : public ISrsHttpServeMux
378 { 392 {
379 private: 393 private:
380 // the pattern handler, to handle the http request. 394 // the pattern handler, to handle the http request.
@@ -406,7 +420,10 @@ public: @@ -406,7 +420,10 @@ public:
406 // Handle registers the handler for the given pattern. 420 // Handle registers the handler for the given pattern.
407 // If a handler already exists for pattern, Handle panics. 421 // If a handler already exists for pattern, Handle panics.
408 virtual int handle(std::string pattern, ISrsHttpHandler* handler); 422 virtual int handle(std::string pattern, ISrsHttpHandler* handler);
409 - // interface ISrsHttpHandler 423 + // whether the http muxer can serve the specified message,
  424 + // if not, user can try next muxer.
  425 + virtual bool can_serve(ISrsHttpMessage* r);
  426 +// interface ISrsHttpServeMux
410 public: 427 public:
411 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); 428 virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
412 private: 429 private: