正在显示
4 个修改的文件
包含
147 行增加
和
103 行删除
| @@ -38,7 +38,6 @@ using namespace std; | @@ -38,7 +38,6 @@ using namespace std; | ||
| 38 | #include <srs_kernel_utility.hpp> | 38 | #include <srs_kernel_utility.hpp> |
| 39 | #include <srs_protocol_buffer.hpp> | 39 | #include <srs_protocol_buffer.hpp> |
| 40 | #include <srs_kernel_file.hpp> | 40 | #include <srs_kernel_file.hpp> |
| 41 | -#include <srs_kernel_flv.hpp> | ||
| 42 | #include <srs_core_autofree.hpp> | 41 | #include <srs_core_autofree.hpp> |
| 43 | 42 | ||
| 44 | #define SRS_DEFAULT_HTTP_PORT 80 | 43 | #define SRS_DEFAULT_HTTP_PORT 80 |
| @@ -289,23 +288,23 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* | @@ -289,23 +288,23 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* | ||
| 289 | if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) { | 288 | if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) { |
| 290 | std::string start = r->query_get("start"); | 289 | std::string start = r->query_get("start"); |
| 291 | if (start.empty()) { | 290 | if (start.empty()) { |
| 292 | - return serve_file(fullpath, w, r); | 291 | + return serve_file(w, r, fullpath); |
| 293 | } | 292 | } |
| 294 | 293 | ||
| 295 | int offset = ::atoi(start.c_str()); | 294 | int offset = ::atoi(start.c_str()); |
| 296 | if (offset <= 0) { | 295 | if (offset <= 0) { |
| 297 | - return serve_file(fullpath, w, r); | 296 | + return serve_file(w, r, fullpath); |
| 298 | } | 297 | } |
| 299 | 298 | ||
| 300 | - return serve_flv_stream(fullpath, w, r, offset); | 299 | + return serve_flv_stream(w, r, fullpath, offset); |
| 301 | } else { | 300 | } else { |
| 302 | - return serve_file(fullpath, w, r); | 301 | + return serve_file(w, r, fullpath); |
| 303 | } | 302 | } |
| 304 | 303 | ||
| 305 | return ret; | 304 | return ret; |
| 306 | } | 305 | } |
| 307 | 306 | ||
| 308 | -int SrsGoHttpFileServer::serve_file(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | 307 | +int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) |
| 309 | { | 308 | { |
| 310 | int ret = ERROR_SUCCESS; | 309 | int ret = ERROR_SUCCESS; |
| 311 | 310 | ||
| @@ -345,110 +344,35 @@ int SrsGoHttpFileServer::serve_file(string fullpath, ISrsGoHttpResponseWriter* w | @@ -345,110 +344,35 @@ int SrsGoHttpFileServer::serve_file(string fullpath, ISrsGoHttpResponseWriter* w | ||
| 345 | 344 | ||
| 346 | // write body. | 345 | // write body. |
| 347 | int64_t left = length; | 346 | int64_t left = length; |
| 348 | - char* buf = r->http_ts_send_buffer(); | ||
| 349 | - | ||
| 350 | - while (left > 0) { | ||
| 351 | - ssize_t nread = -1; | ||
| 352 | - if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) { | ||
| 353 | - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret); | ||
| 354 | - break; | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - left -= nread; | ||
| 358 | - if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) { | ||
| 359 | - break; | ||
| 360 | - } | 347 | + if ((ret = copy(&fs, w, r, left)) != ERROR_SUCCESS) { |
| 348 | + srs_warn("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret); | ||
| 349 | + return ret; | ||
| 361 | } | 350 | } |
| 362 | 351 | ||
| 363 | return ret; | 352 | return ret; |
| 364 | } | 353 | } |
| 365 | 354 | ||
| 366 | -int SrsGoHttpFileServer::serve_flv_stream(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int offset) | 355 | +int SrsGoHttpFileServer::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) |
| 367 | { | 356 | { |
| 368 | - int ret = ERROR_SUCCESS; | ||
| 369 | - | ||
| 370 | - SrsFileReader fs; | ||
| 371 | - | ||
| 372 | - // open flv file | ||
| 373 | - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) { | ||
| 374 | - return ret; | ||
| 375 | - } | ||
| 376 | - | ||
| 377 | - if (offset > fs.filesize()) { | ||
| 378 | - ret = ERROR_HTTP_FLV_OFFSET_OVERFLOW; | ||
| 379 | - srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", | ||
| 380 | - fullpath.c_str(), fs.filesize(), offset, ret); | ||
| 381 | - return ret; | ||
| 382 | - } | ||
| 383 | - | ||
| 384 | - SrsFlvVodStreamDecoder ffd; | ||
| 385 | - | ||
| 386 | - // open fast decoder | ||
| 387 | - if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) { | ||
| 388 | - return ret; | ||
| 389 | - } | ||
| 390 | - | ||
| 391 | - // save header, send later. | ||
| 392 | - char flv_header[13]; | ||
| 393 | - | ||
| 394 | - // send flv header | ||
| 395 | - if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) { | ||
| 396 | - return ret; | ||
| 397 | - } | ||
| 398 | - | ||
| 399 | - // save sequence header, send later | ||
| 400 | - char* sh_data = NULL; | ||
| 401 | - int sh_size = 0; | ||
| 402 | - | ||
| 403 | - if (true) { | ||
| 404 | - // send sequence header | ||
| 405 | - int64_t start = 0; | ||
| 406 | - if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) { | ||
| 407 | - return ret; | ||
| 408 | - } | ||
| 409 | - if (sh_size <= 0) { | ||
| 410 | - ret = ERROR_HTTP_FLV_SEQUENCE_HEADER; | ||
| 411 | - srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret); | ||
| 412 | - return ret; | ||
| 413 | - } | ||
| 414 | - } | ||
| 415 | - sh_data = new char[sh_size]; | ||
| 416 | - SrsAutoFree(char, sh_data); | ||
| 417 | - if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) { | ||
| 418 | - return ret; | ||
| 419 | - } | ||
| 420 | - | ||
| 421 | - // seek to data offset | ||
| 422 | - int64_t left = fs.filesize() - offset; | 357 | + return serve_file(w, r, fullpath); |
| 358 | +} | ||
| 423 | 359 | ||
| 424 | - // write http header for ts. | ||
| 425 | - w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left)); | ||
| 426 | - w->header()->set_content_type("video/x-flv"); | ||
| 427 | - | ||
| 428 | - // write flv header and sequence header. | ||
| 429 | - if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) { | ||
| 430 | - return ret; | ||
| 431 | - } | ||
| 432 | - if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) { | ||
| 433 | - return ret; | ||
| 434 | - } | 360 | +int SrsGoHttpFileServer::copy(SrsFileReader* fs, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int size) |
| 361 | +{ | ||
| 362 | + int ret = ERROR_SUCCESS; | ||
| 435 | 363 | ||
| 436 | - // write body. | 364 | + int left = size; |
| 437 | char* buf = r->http_ts_send_buffer(); | 365 | char* buf = r->http_ts_send_buffer(); |
| 438 | - if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) { | ||
| 439 | - return ret; | ||
| 440 | - } | ||
| 441 | 366 | ||
| 442 | - // send data | ||
| 443 | while (left > 0) { | 367 | while (left > 0) { |
| 444 | ssize_t nread = -1; | 368 | ssize_t nread = -1; |
| 445 | - if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) { | ||
| 446 | - return ret; | 369 | + if ((ret = fs->read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) { |
| 370 | + break; | ||
| 447 | } | 371 | } |
| 448 | 372 | ||
| 449 | left -= nread; | 373 | left -= nread; |
| 450 | if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) { | 374 | if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) { |
| 451 | - return ret; | 375 | + break; |
| 452 | } | 376 | } |
| 453 | } | 377 | } |
| 454 | 378 |
| @@ -40,12 +40,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -40,12 +40,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 40 | 40 | ||
| 41 | #include <srs_app_st.hpp> | 41 | #include <srs_app_st.hpp> |
| 42 | 42 | ||
| 43 | -class SrsSimpleBuffer; | ||
| 44 | class SrsRequest; | 43 | class SrsRequest; |
| 45 | class SrsStSocket; | 44 | class SrsStSocket; |
| 46 | class SrsHttpUri; | 45 | class SrsHttpUri; |
| 47 | class SrsHttpMessage; | 46 | class SrsHttpMessage; |
| 48 | -class SrsHttpHandler; | 47 | +class SrsFileReader; |
| 48 | +class SrsSimpleBuffer; | ||
| 49 | class ISrsGoHttpResponseWriter; | 49 | class ISrsGoHttpResponseWriter; |
| 50 | 50 | ||
| 51 | // http specification | 51 | // http specification |
| @@ -197,16 +197,27 @@ public: | @@ -197,16 +197,27 @@ public: | ||
| 197 | // http.Handle("/", SrsGoHttpFileServer("static-dir")) | 197 | // http.Handle("/", SrsGoHttpFileServer("static-dir")) |
| 198 | class SrsGoHttpFileServer : public ISrsGoHttpHandler | 198 | class SrsGoHttpFileServer : public ISrsGoHttpHandler |
| 199 | { | 199 | { |
| 200 | -private: | 200 | +protected: |
| 201 | std::string dir; | 201 | std::string dir; |
| 202 | public: | 202 | public: |
| 203 | SrsGoHttpFileServer(std::string root_dir); | 203 | SrsGoHttpFileServer(std::string root_dir); |
| 204 | virtual ~SrsGoHttpFileServer(); | 204 | virtual ~SrsGoHttpFileServer(); |
| 205 | public: | 205 | public: |
| 206 | virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); | 206 | virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 207 | -private: | ||
| 208 | - virtual int serve_file(std::string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 209 | - virtual int serve_flv_stream(std::string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int offset); | 207 | +protected: |
| 208 | + /** | ||
| 209 | + * serve the file by specified path. | ||
| 210 | + */ | ||
| 211 | + virtual int serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); | ||
| 212 | + /** | ||
| 213 | + * when access flv file with start=xxx. | ||
| 214 | + */ | ||
| 215 | + virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); | ||
| 216 | +protected: | ||
| 217 | + /** | ||
| 218 | + * copy the fs to response writer in size bytes. | ||
| 219 | + */ | ||
| 220 | + virtual int copy(SrsFileReader* fs, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int size); | ||
| 210 | }; | 221 | }; |
| 211 | 222 | ||
| 212 | // the mux entry for server mux. | 223 | // the mux entry for server mux. |
| @@ -39,6 +39,101 @@ using namespace std; | @@ -39,6 +39,101 @@ using namespace std; | ||
| 39 | #include <srs_core_autofree.hpp> | 39 | #include <srs_core_autofree.hpp> |
| 40 | #include <srs_app_config.hpp> | 40 | #include <srs_app_config.hpp> |
| 41 | #include <srs_kernel_utility.hpp> | 41 | #include <srs_kernel_utility.hpp> |
| 42 | +#include <srs_kernel_file.hpp> | ||
| 43 | +#include <srs_kernel_flv.hpp> | ||
| 44 | + | ||
| 45 | +SrsVodStream::SrsVodStream(string root_dir) | ||
| 46 | + : SrsGoHttpFileServer(root_dir) | ||
| 47 | +{ | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +SrsVodStream::~SrsVodStream() | ||
| 51 | +{ | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) | ||
| 55 | +{ | ||
| 56 | + int ret = ERROR_SUCCESS; | ||
| 57 | + | ||
| 58 | + SrsFileReader fs; | ||
| 59 | + | ||
| 60 | + // open flv file | ||
| 61 | + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) { | ||
| 62 | + return ret; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + if (offset > fs.filesize()) { | ||
| 66 | + ret = ERROR_HTTP_FLV_OFFSET_OVERFLOW; | ||
| 67 | + srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", | ||
| 68 | + fullpath.c_str(), fs.filesize(), offset, ret); | ||
| 69 | + return ret; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + SrsFlvVodStreamDecoder ffd; | ||
| 73 | + | ||
| 74 | + // open fast decoder | ||
| 75 | + if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) { | ||
| 76 | + return ret; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + // save header, send later. | ||
| 80 | + char flv_header[13]; | ||
| 81 | + | ||
| 82 | + // send flv header | ||
| 83 | + if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) { | ||
| 84 | + return ret; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // save sequence header, send later | ||
| 88 | + char* sh_data = NULL; | ||
| 89 | + int sh_size = 0; | ||
| 90 | + | ||
| 91 | + if (true) { | ||
| 92 | + // send sequence header | ||
| 93 | + int64_t start = 0; | ||
| 94 | + if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) { | ||
| 95 | + return ret; | ||
| 96 | + } | ||
| 97 | + if (sh_size <= 0) { | ||
| 98 | + ret = ERROR_HTTP_FLV_SEQUENCE_HEADER; | ||
| 99 | + srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret); | ||
| 100 | + return ret; | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + sh_data = new char[sh_size]; | ||
| 104 | + SrsAutoFree(char, sh_data); | ||
| 105 | + if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) { | ||
| 106 | + return ret; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + // seek to data offset | ||
| 110 | + int64_t left = fs.filesize() - offset; | ||
| 111 | + | ||
| 112 | + // write http header for ts. | ||
| 113 | + w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left)); | ||
| 114 | + w->header()->set_content_type("video/x-flv"); | ||
| 115 | + | ||
| 116 | + // write flv header and sequence header. | ||
| 117 | + if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) { | ||
| 118 | + return ret; | ||
| 119 | + } | ||
| 120 | + if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) { | ||
| 121 | + return ret; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + // write body. | ||
| 125 | + if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) { | ||
| 126 | + return ret; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + // send data | ||
| 130 | + if ((ret = copy(&fs, w, r, left)) != ERROR_SUCCESS) { | ||
| 131 | + srs_warn("read flv=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret); | ||
| 132 | + return ret; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + return ret; | ||
| 136 | +} | ||
| 42 | 137 | ||
| 43 | SrsHttpServer::SrsHttpServer() | 138 | SrsHttpServer::SrsHttpServer() |
| 44 | { | 139 | { |
| @@ -71,7 +166,7 @@ int SrsHttpServer::initialize() | @@ -71,7 +166,7 @@ int SrsHttpServer::initialize() | ||
| 71 | std::string mount = _srs_config->get_vhost_http_mount(vhost); | 166 | std::string mount = _srs_config->get_vhost_http_mount(vhost); |
| 72 | std::string dir = _srs_config->get_vhost_http_dir(vhost); | 167 | std::string dir = _srs_config->get_vhost_http_dir(vhost); |
| 73 | 168 | ||
| 74 | - if ((ret = mux.handle(mount, new SrsGoHttpFileServer(dir))) != ERROR_SUCCESS) { | 169 | + if ((ret = mux.handle(mount, new SrsVodStream(dir))) != ERROR_SUCCESS) { |
| 75 | srs_error("http: mount dir=%s for vhost=%s failed. ret=%d", dir.c_str(), vhost.c_str(), ret); | 170 | srs_error("http: mount dir=%s for vhost=%s failed. ret=%d", dir.c_str(), vhost.c_str(), ret); |
| 76 | return ret; | 171 | return ret; |
| 77 | } | 172 | } |
| @@ -84,7 +179,7 @@ int SrsHttpServer::initialize() | @@ -84,7 +179,7 @@ int SrsHttpServer::initialize() | ||
| 84 | if (!default_root_exists) { | 179 | if (!default_root_exists) { |
| 85 | // add root | 180 | // add root |
| 86 | std::string dir = _srs_config->get_http_stream_dir(); | 181 | std::string dir = _srs_config->get_http_stream_dir(); |
| 87 | - if ((ret = mux.handle("/", new SrsGoHttpFileServer(dir))) != ERROR_SUCCESS) { | 182 | + if ((ret = mux.handle("/", new SrsVodStream(dir))) != ERROR_SUCCESS) { |
| 88 | srs_error("http: mount root dir=%s failed. ret=%d", dir.c_str(), ret); | 183 | srs_error("http: mount root dir=%s failed. ret=%d", dir.c_str(), ret); |
| 89 | return ret; | 184 | return ret; |
| 90 | } | 185 | } |
| @@ -41,7 +41,21 @@ class SrsHttpParser; | @@ -41,7 +41,21 @@ class SrsHttpParser; | ||
| 41 | class SrsHttpMessage; | 41 | class SrsHttpMessage; |
| 42 | class SrsHttpHandler; | 42 | class SrsHttpHandler; |
| 43 | 43 | ||
| 44 | -// for http server. | 44 | +/** |
| 45 | +* the flv vod stream supports flv?start=offset-bytes. | ||
| 46 | +* for example, http://server/file.flv?start=10240 | ||
| 47 | +* server will write flv header and sequence header, | ||
| 48 | +* then seek(10240) and response flv tag data. | ||
| 49 | +*/ | ||
| 50 | +class SrsVodStream : public SrsGoHttpFileServer | ||
| 51 | +{ | ||
| 52 | +public: | ||
| 53 | + SrsVodStream(std::string root_dir); | ||
| 54 | + virtual ~SrsVodStream(); | ||
| 55 | +protected: | ||
| 56 | + virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); | ||
| 57 | +}; | ||
| 58 | + | ||
| 45 | class SrsHttpServer | 59 | class SrsHttpServer |
| 46 | { | 60 | { |
| 47 | public: | 61 | public: |
-
请 注册 或 登录 后发表评论