diff --git a/README.md b/README.md
index 3ce39ef6d..ec2e148e3 100755
--- a/README.md
+++ b/README.md
@@ -158,6 +158,8 @@ 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
* v3.0, 2020-01-29, Fix [#1206][bug #1206], dispose ingester while server quiting. 3.0.111
@@ -1658,6 +1660,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/configure b/trunk/configure
index 2f65cbbe2..d233f66db 100755
--- a/trunk/configure
+++ b/trunk/configure
@@ -191,7 +191,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_version4" "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/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp
index 2a0d8e939..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);
}
@@ -300,20 +314,53 @@ srs_error_t SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/, SrsRtmpJi
return srs_success;
}
-#ifdef SRS_PERF_FAST_FLV_ENCODER
-SrsFastFlvStreamEncoder::SrsFastFlvStreamEncoder()
+srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count)
{
-}
+ srs_error_t err = srs_success;
-SrsFastFlvStreamEncoder::~SrsFastFlvStreamEncoder()
-{
-}
+ // 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");
+ }
+ }
-srs_error_t SrsFastFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count)
-{
return enc->write_tags(msgs, count);
}
-#endif
+
+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()
{
@@ -511,19 +558,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");
-#ifdef SRS_PERF_FAST_FLV_ENCODER
- bool realtime = _srs_config->get_realtime_enabled(req->vhost);
- if (realtime) {
- enc_desc = "FLV";
- enc = new SrsFlvStreamEncoder();
- } else {
- 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 +612,8 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
}
}
-#ifdef SRS_PERF_FAST_FLV_ENCODER
- SrsFastFlvStreamEncoder* ffe = dynamic_cast(enc);
-#endif
-
+ 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
SrsHttpMessage* hr = dynamic_cast(r);
@@ -639,16 +673,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..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();
@@ -95,21 +96,12 @@ public:
public:
virtual bool has_cache();
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
-{
-public:
- SrsFastFlvStreamEncoder();
- virtual ~SrsFastFlvStreamEncoder();
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);
};
-#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/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
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
diff --git a/trunk/src/core/srs_core_version4.cpp b/trunk/src/core/srs_core_version4.cpp
new file mode 100644
index 000000000..e5071d6ef
--- /dev/null
+++ b/trunk/src/core/srs_core_version4.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
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)