winlin

for bug #277, support flv stream.

@@ -38,6 +38,8 @@ using namespace std; @@ -38,6 +38,8 @@ 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 43
42 #define SRS_DEFAULT_HTTP_PORT 80 44 #define SRS_DEFAULT_HTTP_PORT 80
43 45
@@ -284,6 +286,29 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -284,6 +286,29 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
284 286
285 string fullpath = dir + "/" + upath; 287 string fullpath = dir + "/" + upath;
286 288
  289 + if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) {
  290 + std::string start = r->query_get("start");
  291 + if (start.empty()) {
  292 + return serve_file(fullpath, w, r);
  293 + }
  294 +
  295 + int offset = ::atoi(start.c_str());
  296 + if (offset <= 0) {
  297 + return serve_file(fullpath, w, r);
  298 + }
  299 +
  300 + return serve_flv_stream(fullpath, w, r, offset);
  301 + } else {
  302 + return serve_file(fullpath, w, r);
  303 + }
  304 +
  305 + return ret;
  306 +}
  307 +
  308 +int SrsGoHttpFileServer::serve_file(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
  309 +{
  310 + int ret = ERROR_SUCCESS;
  311 +
287 // open the target file. 312 // open the target file.
288 SrsFileReader fs; 313 SrsFileReader fs;
289 314
@@ -338,6 +363,98 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -338,6 +363,98 @@ int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
338 return ret; 363 return ret;
339 } 364 }
340 365
  366 +int SrsGoHttpFileServer::serve_flv_stream(string fullpath, ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, int offset)
  367 +{
  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;
  423 +
  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 + }
  435 +
  436 + // write body.
  437 + char* buf = r->http_ts_send_buffer();
  438 + if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {
  439 + return ret;
  440 + }
  441 +
  442 + // send data
  443 + while (left > 0) {
  444 + ssize_t nread = -1;
  445 + if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {
  446 + return ret;
  447 + }
  448 +
  449 + left -= nread;
  450 + if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) {
  451 + return ret;
  452 + }
  453 + }
  454 +
  455 + return ret;
  456 +}
  457 +
341 SrsGoHttpMuxEntry::SrsGoHttpMuxEntry() 458 SrsGoHttpMuxEntry::SrsGoHttpMuxEntry()
342 { 459 {
343 explicit_match = false; 460 explicit_match = false;
@@ -204,6 +204,9 @@ public: @@ -204,6 +204,9 @@ public:
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 }; 210 };
208 211
209 // the mux entry for server mux. 212 // the mux entry for server mux.
@@ -38,7 +38,6 @@ using namespace std; @@ -38,7 +38,6 @@ using namespace std;
38 #include <srs_app_st_socket.hpp> 38 #include <srs_app_st_socket.hpp>
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_flv.hpp>  
42 #include <srs_kernel_utility.hpp> 41 #include <srs_kernel_utility.hpp>
43 42
44 SrsHttpServer::SrsHttpServer() 43 SrsHttpServer::SrsHttpServer()