From bbe96a4b31736c8edd5e3314edb45d3b13c35351 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 17 Jan 2015 23:19:30 +0800 Subject: [PATCH] for bug #277, support flv stream. --- trunk/src/app/srs_app_http.cpp | 117 ++++++++++++++++++++++++++++ trunk/src/app/srs_app_http.hpp | 3 + trunk/src/app/srs_app_http_conn.cpp | 1 - 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index df559a3c0..8d0406c51 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -38,6 +38,8 @@ using namespace std; #include #include #include +#include +#include #define SRS_DEFAULT_HTTP_PORT 80 @@ -284,6 +286,29 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* string fullpath = dir + "/" + upath; + if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) { + std::string start = r->query_get("start"); + if (start.empty()) { + return serve_file(fullpath, w, r); + } + + int offset = ::atoi(start.c_str()); + if (offset <= 0) { + return serve_file(fullpath, w, r); + } + + return serve_flv_stream(fullpath, w, r, offset); + } else { + return serve_file(fullpath, w, r); + } + + return ret; +} + +int SrsGoHttpFileServer::serve_file(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +{ + int ret = ERROR_SUCCESS; + // open the target file. SrsFileReader fs; @@ -338,6 +363,98 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return ret; } +int SrsGoHttpFileServer::serve_flv_stream(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int offset) +{ + int ret = ERROR_SUCCESS; + + SrsFileReader fs; + + // open flv file + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) { + return ret; + } + + if (offset > fs.filesize()) { + ret = ERROR_HTTP_FLV_OFFSET_OVERFLOW; + srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", + fullpath.c_str(), fs.filesize(), offset, ret); + return ret; + } + + SrsFlvVodStreamDecoder ffd; + + // open fast decoder + if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) { + return ret; + } + + // save header, send later. + char flv_header[13]; + + // send flv header + if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) { + return ret; + } + + // save sequence header, send later + char* sh_data = NULL; + int sh_size = 0; + + if (true) { + // send sequence header + int64_t start = 0; + if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) { + return ret; + } + if (sh_size <= 0) { + ret = ERROR_HTTP_FLV_SEQUENCE_HEADER; + srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret); + return ret; + } + } + sh_data = new char[sh_size]; + SrsAutoFree(char, sh_data); + if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) { + return ret; + } + + // seek to data offset + int64_t left = fs.filesize() - offset; + + // write http header for ts. + w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left)); + w->header()->set_content_type("video/x-flv"); + + // write flv header and sequence header. + if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) { + return ret; + } + if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) { + return ret; + } + + // write body. + char* buf = r->http_ts_send_buffer(); + if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) { + return ret; + } + + // send data + while (left > 0) { + ssize_t nread = -1; + if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) { + return ret; + } + + left -= nread; + if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) { + return ret; + } + } + + return ret; +} + SrsGoHttpMuxEntry::SrsGoHttpMuxEntry() { explicit_match = false; diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index a004c6e61..9e14b2844 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -204,6 +204,9 @@ public: virtual ~SrsGoHttpFileServer(); public: virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); +private: + virtual int serve_file(std::string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); + virtual int serve_flv_stream(std::string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int offset); }; // the mux entry for server mux. diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 06ec9cef8..bbeccd5ed 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -38,7 +38,6 @@ using namespace std; #include #include #include -#include #include SrsHttpServer::SrsHttpServer()