From a2a6ca8258560ff19346533cba4c83a0bcb9c7cb Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Feb 2020 16:13:48 +0800 Subject: [PATCH 1/4] For #939, always enable fast FLV streaming. --- README.md | 2 ++ trunk/src/app/srs_app_http_stream.cpp | 17 ++--------------- trunk/src/app/srs_app_http_stream.hpp | 2 -- trunk/src/core/srs_core_performance.hpp | 7 ------- trunk/src/kernel/srs_kernel_flv.cpp | 16 +++++++--------- trunk/src/kernel/srs_kernel_flv.hpp | 4 +--- trunk/src/utest/srs_utest_kernel.cpp | 4 ---- 7 files changed, 12 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index aed7847b4..9d71e4071 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-02-04, For [#939][bug #939], always enable fast FLV streaming. * v3.0, 2020-02-02, [3.0 beta0(3.0.112)][r3.0b0] released. 121709 lines. * v3.0, 2020-01-29, Support isolate version file. 3.0.112 * v3.0, 2020-01-29, Fix [#1206][bug #1206], dispose ingester while server quiting. 3.0.111 @@ -1637,6 +1638,7 @@ Winlin [bug #1303]: https://github.com/ossrs/srs/issues/1303 [bug #1230]: https://github.com/ossrs/srs/issues/1230 [bug #1206]: https://github.com/ossrs/srs/issues/1206 +[bug #939]: https://github.com/ossrs/srs/issues/939 [bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 2a0d8e939..4bb38e5f9 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -300,7 +300,6 @@ srs_error_t SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJi return srs_success; } -#ifdef SRS_PERF_FAST_FLV_ENCODER SrsFastFlvStreamEncoder::SrsFastFlvStreamEncoder() { } @@ -313,7 +312,6 @@ srs_error_t SrsFastFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int { return enc->write_tags(msgs, count); } -#endif SrsAacStreamEncoder::SrsAacStreamEncoder() { @@ -511,7 +509,6 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess srs_assert(entry); if (srs_string_ends_with(entry->pattern, ".flv")) { w->header()->set_content_type("video/x-flv"); -#ifdef SRS_PERF_FAST_FLV_ENCODER bool realtime = _srs_config->get_realtime_enabled(req->vhost); if (realtime) { enc_desc = "FLV"; @@ -520,10 +517,6 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess enc_desc = "FastFLV"; enc = new SrsFastFlvStreamEncoder(); } -#else - enc_desc = "FLV"; - enc = new SrsFlvStreamEncoder(); -#endif } else if (srs_string_ends_with(entry->pattern, ".aac")) { w->header()->set_content_type("audio/x-aac"); enc_desc = "AAC"; @@ -576,10 +569,8 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess } } -#ifdef SRS_PERF_FAST_FLV_ENCODER SrsFastFlvStreamEncoder* ffe = dynamic_cast(enc); -#endif - + // Use receive thread to accept the close event to avoid FD leak. // @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427 SrsHttpMessage* hr = dynamic_cast(r); @@ -639,16 +630,12 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess } // sendout all messages. -#ifdef SRS_PERF_FAST_FLV_ENCODER if (ffe) { err = ffe->write_tags(msgs.msgs, count); } else { err = streaming_send_messages(enc, msgs.msgs, count); } -#else - err = streaming_send_messages(enc, msgs.msgs, count); -#endif - + // free the messages. for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp index cc1d23ed1..18f7a1b6c 100755 --- a/trunk/src/app/srs_app_http_stream.hpp +++ b/trunk/src/app/srs_app_http_stream.hpp @@ -97,7 +97,6 @@ public: virtual srs_error_t dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter); }; -#ifdef SRS_PERF_FAST_FLV_ENCODER // A Fast HTTP FLV Live Streaming, to write multiple tags by writev. // @see https://github.com/ossrs/srs/issues/405 class SrsFastFlvStreamEncoder : public SrsFlvStreamEncoder @@ -109,7 +108,6 @@ public: // Write the tags in a time. virtual srs_error_t write_tags(SrsSharedPtrMessage** msgs, int count); }; -#endif // Transmux RTMP to HTTP TS Streaming. class SrsTsStreamEncoder : public ISrsBufferEncoder diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 28eac85a9..bd962bbd4 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -177,13 +177,6 @@ #undef SRS_PERF_SO_SNDBUF_SIZE #endif -/** - * define the following macro to enable the fast flv encoder. - * @see https://github.com/ossrs/srs/issues/405 - */ -#undef SRS_PERF_FAST_FLV_ENCODER -#define SRS_PERF_FAST_FLV_ENCODER - /** * whether ensure glibc memory check. */ diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 63238b4c6..0259def06 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -353,23 +353,19 @@ SrsFlvTransmuxer::SrsFlvTransmuxer() { writer = NULL; -#ifdef SRS_PERF_FAST_FLV_ENCODER nb_tag_headers = 0; tag_headers = NULL; nb_iovss_cache = 0; iovss_cache = NULL; nb_ppts = 0; ppts = NULL; -#endif } SrsFlvTransmuxer::~SrsFlvTransmuxer() { -#ifdef SRS_PERF_FAST_FLV_ENCODER srs_freepa(tag_headers); srs_freepa(iovss_cache); srs_freepa(ppts); -#endif } srs_error_t SrsFlvTransmuxer::initialize(ISrsWriter* fw) @@ -379,15 +375,19 @@ srs_error_t SrsFlvTransmuxer::initialize(ISrsWriter* fw) return srs_success; } -srs_error_t SrsFlvTransmuxer::write_header() +srs_error_t SrsFlvTransmuxer::write_header(bool has_video, bool has_audio) { srs_error_t err = srs_success; - + + uint8_t av_flag = 0; + av_flag += (has_audio? 4:0); + av_flag += (has_video? 1:0); + // 9bytes header and 4bytes first previous-tag-size char flv_header[] = { 'F', 'L', 'V', // Signatures "FLV" (char)0x01, // File version (for example, 0x01 for FLV version 1) - (char)0x05, // 4, audio; 1, video; 5 audio+video. + (char)av_flag, // 4, audio; 1, video; 5 audio+video. (char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes }; @@ -472,7 +472,6 @@ int SrsFlvTransmuxer::size_tag(int data_size) return SRS_FLV_TAG_HEADER_SIZE + data_size + SRS_FLV_PREVIOUS_TAG_SIZE; } -#ifdef SRS_PERF_FAST_FLV_ENCODER srs_error_t SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage** msgs, int count) { srs_error_t err = srs_success; @@ -542,7 +541,6 @@ srs_error_t SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage** msgs, int count) return err; } -#endif void SrsFlvTransmuxer::cache_metadata(char type, char* data, int size, char* cache) { diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 0c77a6664..ebc587f39 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -362,7 +362,7 @@ public: // 1. E.2 The FLV header // 2. PreviousTagSize0 UI32 Always 0 // that is, 9+4=13bytes. - virtual srs_error_t write_header(); + virtual srs_error_t write_header(bool has_video = true, bool has_audio = true); virtual srs_error_t write_header(char flv_header[9]); // Write flv metadata. // @param type, the type of data, or other message type. @@ -381,7 +381,6 @@ public: // including the tag header, body, and 4bytes previous tag size. // @remark assert data_size is not negative. static int size_tag(int data_size); -#ifdef SRS_PERF_FAST_FLV_ENCODER private: // The cache tag header. int nb_tag_headers; @@ -395,7 +394,6 @@ private: public: // Write the tags in a time. virtual srs_error_t write_tags(SrsSharedPtrMessage** msgs, int count); -#endif private: virtual void cache_metadata(char type, char* data, int size, char* cache); virtual void cache_audio(int64_t timestamp, char* data, int size, char* cache); diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 5a113da84..f0270f9b6 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -912,7 +912,6 @@ VOID TEST(KernelFLVTest, CoverWriterErrorCase) HELPER_EXPECT_FAILED(m.write_video(0, NULL, 0)); } -#ifdef SRS_PERF_FAST_FLV_ENCODER if (true) { MockSrsFileWriter w; HELPER_EXPECT_SUCCESS(w.open("")); @@ -963,7 +962,6 @@ VOID TEST(KernelFLVTest, CoverWriterErrorCase) SrsSharedPtrMessage* msgs = &msg; HELPER_EXPECT_FAILED(m.write_tags(&msgs, 1)); } -#endif } VOID TEST(KernelFLVTest, CoverReaderErrorCase) @@ -4028,7 +4026,6 @@ VOID TEST(KernelFLVTest, CoverAll) EXPECT_TRUE(s.is_video()); } -#ifdef SRS_PERF_FAST_FLV_ENCODER if (true) { MockSrsFileWriter f; SrsFlvTransmuxer mux; @@ -4045,7 +4042,6 @@ VOID TEST(KernelFLVTest, CoverAll) EXPECT_EQ(16, f.tellg()); } -#endif } VOID TEST(KernelFLVTest, CoverSharedPtrMessage) From 68efca4fa995f677916c510013669444cb5c1778 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Feb 2020 16:39:01 +0800 Subject: [PATCH 2/4] For #939, always enable fast FLV streaming. --- trunk/src/app/srs_app_http_stream.cpp | 22 ++++------------------ trunk/src/app/srs_app_http_stream.hpp | 9 --------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 4bb38e5f9..e8253a94f 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -300,15 +300,7 @@ srs_error_t SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJi return srs_success; } -SrsFastFlvStreamEncoder::SrsFastFlvStreamEncoder() -{ -} - -SrsFastFlvStreamEncoder::~SrsFastFlvStreamEncoder() -{ -} - -srs_error_t SrsFastFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count) +srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count) { return enc->write_tags(msgs, count); } @@ -509,14 +501,8 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess srs_assert(entry); if (srs_string_ends_with(entry->pattern, ".flv")) { w->header()->set_content_type("video/x-flv"); - bool realtime = _srs_config->get_realtime_enabled(req->vhost); - if (realtime) { - enc_desc = "FLV"; - enc = new SrsFlvStreamEncoder(); - } else { - enc_desc = "FastFLV"; - enc = new SrsFastFlvStreamEncoder(); - } + enc_desc = "FLV"; + enc = new SrsFlvStreamEncoder(); } else if (srs_string_ends_with(entry->pattern, ".aac")) { w->header()->set_content_type("audio/x-aac"); enc_desc = "AAC"; @@ -569,7 +555,7 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess } } - SrsFastFlvStreamEncoder* ffe = dynamic_cast(enc); + SrsFlvStreamEncoder* ffe = dynamic_cast(enc); // Use receive thread to accept the close event to avoid FD leak. // @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427 diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp index 18f7a1b6c..c9a6f7904 100755 --- a/trunk/src/app/srs_app_http_stream.hpp +++ b/trunk/src/app/srs_app_http_stream.hpp @@ -95,15 +95,6 @@ public: public: virtual bool has_cache(); virtual srs_error_t dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter); -}; - -// A Fast HTTP FLV Live Streaming, to write multiple tags by writev. -// @see https://github.com/ossrs/srs/issues/405 -class SrsFastFlvStreamEncoder : public SrsFlvStreamEncoder -{ -public: - SrsFastFlvStreamEncoder(); - virtual ~SrsFastFlvStreamEncoder(); public: // Write the tags in a time. virtual srs_error_t write_tags(SrsSharedPtrMessage** msgs, int count); From 4f39303f3764cb09e51e562db0d909d7b293b942 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Feb 2020 17:02:02 +0800 Subject: [PATCH 3/4] Fix #939, response right A/V flag in FLV header. 3.0.113 --- README.md | 1 + trunk/src/app/srs_app_http_stream.cpp | 67 +++++++++++++++++++++++++-- trunk/src/app/srs_app_http_stream.hpp | 5 +- trunk/src/core/srs_core_version3.hpp | 2 +- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9d71e4071..ecdc0fad3 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-02-04, Fix [#939][bug #939], response right A/V flag in FLV header. 3.0.113 * v3.0, 2020-02-04, For [#939][bug #939], always enable fast FLV streaming. * v3.0, 2020-02-02, [3.0 beta0(3.0.112)][r3.0b0] released. 121709 lines. * v3.0, 2020-01-29, Support isolate version file. 3.0.112 diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index e8253a94f..c7720be19 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -249,6 +249,7 @@ srs_error_t SrsTsStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJit SrsFlvStreamEncoder::SrsFlvStreamEncoder() { + header_written = false; enc = new SrsFlvTransmuxer(); } @@ -265,26 +266,39 @@ srs_error_t SrsFlvStreamEncoder::initialize(SrsFileWriter* w, SrsBufferCache* /* return srs_error_wrap(err, "init encoder"); } - // write flv header. - if ((err = enc->write_header()) != srs_success) { - return srs_error_wrap(err, "write header"); - } - return err; } srs_error_t SrsFlvStreamEncoder::write_audio(int64_t timestamp, char* data, int size) { + srs_error_t err = srs_success; + + if ((err = write_header()) != srs_success) { + return srs_error_wrap(err, "write header"); + } + return enc->write_audio(timestamp, data, size); } srs_error_t SrsFlvStreamEncoder::write_video(int64_t timestamp, char* data, int size) { + srs_error_t err = srs_success; + + if ((err = write_header()) != srs_success) { + return srs_error_wrap(err, "write header"); + } + return enc->write_video(timestamp, data, size); } srs_error_t SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size) { + srs_error_t err = srs_success; + + if ((err = write_header()) != srs_success) { + return srs_error_wrap(err, "write header"); + } + return enc->write_metadata(SrsFrameTypeScript, data, size); } @@ -302,9 +316,52 @@ srs_error_t SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJi srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count) { + srs_error_t err = srs_success; + + // For https://github.com/ossrs/srs/issues/939 + if (!header_written) { + bool has_video = false; + bool has_audio = false; + + for (int i = 0; i < count && (!has_video || !has_audio); i++) { + SrsSharedPtrMessage* msg = msgs[i]; + if (msg->is_video()) { + has_video = true; + } else if (msg->is_audio()) { + has_audio = true; + } + } + + // Drop data if no A+V. + if (!has_video && !has_audio) { + return err; + } + + if ((err = write_header(has_video, has_audio)) != srs_success) { + return srs_error_wrap(err, "write header"); + } + } + return enc->write_tags(msgs, count); } +srs_error_t SrsFlvStreamEncoder::write_header(bool has_video, bool has_audio) +{ + srs_error_t err = srs_success; + + if (!header_written) { + header_written = true; + + if ((err = enc->write_header(has_video, has_audio)) != srs_success) { + return srs_error_wrap(err, "write header"); + } + + srs_trace("FLV: write header audio=%d, video=%d", has_audio, has_video); + } + + return err; +} + SrsAacStreamEncoder::SrsAacStreamEncoder() { enc = new SrsAacTransmuxer(); diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp index c9a6f7904..720e53e3a 100755 --- a/trunk/src/app/srs_app_http_stream.hpp +++ b/trunk/src/app/srs_app_http_stream.hpp @@ -82,8 +82,9 @@ public: // Transmux RTMP to HTTP Live Streaming. class SrsFlvStreamEncoder : public ISrsBufferEncoder { -protected: +private: SrsFlvTransmuxer* enc; + bool header_written; public: SrsFlvStreamEncoder(); virtual ~SrsFlvStreamEncoder(); @@ -98,6 +99,8 @@ public: public: // Write the tags in a time. virtual srs_error_t write_tags(SrsSharedPtrMessage** msgs, int count); +private: + virtual srs_error_t write_header(bool has_video = true, bool has_audio = true); }; // Transmux RTMP to HTTP TS Streaming. diff --git a/trunk/src/core/srs_core_version3.hpp b/trunk/src/core/srs_core_version3.hpp index 05251a733..0977c5458 100644 --- a/trunk/src/core/srs_core_version3.hpp +++ b/trunk/src/core/srs_core_version3.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION3_HPP #define SRS_CORE_VERSION3_HPP -#define SRS_VERSION3_REVISION 112 +#define SRS_VERSION3_REVISION 113 #endif From c01806d5c4a26fd2b3da0412effc93fe4d04e04c Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Feb 2020 17:04:03 +0800 Subject: [PATCH 4/4] Refine version3 --- trunk/configure | 2 +- trunk/src/core/srs_core_version3.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 trunk/src/core/srs_core_version3.cpp diff --git a/trunk/configure b/trunk/configure index 2441dbb07..a3558009a 100755 --- a/trunk/configure +++ b/trunk/configure @@ -180,7 +180,7 @@ fi MODULE_ID="CORE" MODULE_DEPENDS=() ModuleLibIncs=(${SRS_OBJS_DIR}) -MODULE_FILES=("srs_core" "srs_core_autofree" "srs_core_performance" +MODULE_FILES=("srs_core" "srs_core_version3" "srs_core_autofree" "srs_core_performance" "srs_core_mem_watch" "srs_core_time") CORE_INCS="src/core"; MODULE_DIR=${CORE_INCS} . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" diff --git a/trunk/src/core/srs_core_version3.cpp b/trunk/src/core/srs_core_version3.cpp new file mode 100644 index 000000000..97724f2b1 --- /dev/null +++ b/trunk/src/core/srs_core_version3.cpp @@ -0,0 +1,24 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2020 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include