mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #405, improve the HTT FLV to 3k. 2.0.169
This commit is contained in:
parent
b53e9814b3
commit
960341b9b2
8 changed files with 140 additions and 26 deletions
|
@ -716,7 +716,8 @@ The play HTTP FLV benchmark by [SB](https://github.com/simple-rtmp-server/srs-be
|
||||||
| Update | SRS | Clients | Type | CPU | Memory | Commit |
|
| Update | SRS | Clients | Type | CPU | Memory | Commit |
|
||||||
| ------------- | --------- | ------------- | ------------- | --------- | -------- | ------------ |
|
| ------------- | --------- | ------------- | ------------- | --------- | -------- | ------------ |
|
||||||
| 2014-05-24 | 2.0.167 | 1.0k(1000) | players | 82% | 86MB | - |
|
| 2014-05-24 | 2.0.167 | 1.0k(1000) | players | 82% | 86MB | - |
|
||||||
| 2014-05-24 | 2.0.168 | 2.3k(2300) | players | 92% | 276MB | - |
|
| 2014-05-24 | 2.0.168 | 2.3k(2300) | players | 92% | 276MB | [code][p17] |
|
||||||
|
| 2014-05-24 | 2.0.169 | 3.0k(3000) | players | 94% | 188MB | [code][p18] |
|
||||||
|
|
||||||
### Latency benchmark
|
### Latency benchmark
|
||||||
|
|
||||||
|
@ -832,6 +833,7 @@ Winlin
|
||||||
[p14]: https://github.com/simple-rtmp-server/srs/commit/10297fab519811845b549a8af40a6bcbd23411e8
|
[p14]: https://github.com/simple-rtmp-server/srs/commit/10297fab519811845b549a8af40a6bcbd23411e8
|
||||||
[p15]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
|
[p15]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
|
||||||
[p16]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
|
[p16]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
|
||||||
|
[p17]: https://github.com/simple-rtmp-server/srs/commit/fc995473eb02c7cf64b5b212b456e11f34aa7984
|
||||||
|
|
||||||
[authors]: https://github.com/simple-rtmp-server/srs/blob/develop/AUTHORS.txt
|
[authors]: https://github.com/simple-rtmp-server/srs/blob/develop/AUTHORS.txt
|
||||||
[bigthanks]: https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#bigthanks
|
[bigthanks]: https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#bigthanks
|
||||||
|
|
|
@ -98,8 +98,14 @@ int SrsHttpResponseWriter::write(char* data, int size)
|
||||||
|
|
||||||
if (!header_wrote) {
|
if (!header_wrote) {
|
||||||
write_header(SRS_CONSTS_HTTP_OK);
|
write_header(SRS_CONSTS_HTTP_OK);
|
||||||
|
|
||||||
|
if ((ret = send_header(data, size)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("http: send header failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the bytes send and content length.
|
||||||
written += size;
|
written += size;
|
||||||
if (content_length != -1 && written > content_length) {
|
if (content_length != -1 && written > content_length) {
|
||||||
ret = ERROR_HTTP_CONTENT_LENGTH;
|
ret = ERROR_HTTP_CONTENT_LENGTH;
|
||||||
|
@ -107,11 +113,6 @@ int SrsHttpResponseWriter::write(char* data, int size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = send_header(data, size)) != ERROR_SUCCESS) {
|
|
||||||
srs_error("http: send header failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore NULL content.
|
// ignore NULL content.
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -143,6 +144,71 @@ int SrsHttpResponseWriter::write(char* data, int size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsHttpResponseWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// when header not ready, or not chunked, send one by one.
|
||||||
|
if (!header_wrote || content_length != -1) {
|
||||||
|
ssize_t nwrite = 0;
|
||||||
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
iovec* piovc = iov + i;
|
||||||
|
nwrite += piovc->iov_len;
|
||||||
|
if ((ret = write((char*)piovc->iov_base, (int)piovc->iov_len)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pnwrite) {
|
||||||
|
*pnwrite = nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore NULL content.
|
||||||
|
if (iovcnt <= 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send in chunked encoding.
|
||||||
|
int nb_iovss = iovcnt * 4;
|
||||||
|
iovec* iovss = new iovec[nb_iovss];
|
||||||
|
SrsAutoFree(iovec, iovss);
|
||||||
|
|
||||||
|
char* pheader_cache = header_cache;
|
||||||
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
int left = SRS_HTTP_HEADER_CACHE_SIZE - (int)(pheader_cache - header_cache);
|
||||||
|
srs_assert(left > 0);
|
||||||
|
|
||||||
|
iovec* data_iov = iov + i;
|
||||||
|
int nb_size = snprintf(pheader_cache, left, "%x", (int)data_iov->iov_len);
|
||||||
|
|
||||||
|
iovec* iovs = iovss + (i * 4);
|
||||||
|
iovs[0].iov_base = (char*)pheader_cache;
|
||||||
|
iovs[0].iov_len = (int)nb_size;
|
||||||
|
iovs[1].iov_base = (char*)SRS_HTTP_CRLF;
|
||||||
|
iovs[1].iov_len = 2;
|
||||||
|
iovs[2].iov_base = (char*)data_iov->iov_base;
|
||||||
|
iovs[2].iov_len = (int)data_iov->iov_len;
|
||||||
|
iovs[3].iov_base = (char*)SRS_HTTP_CRLF;
|
||||||
|
iovs[3].iov_len = 2;
|
||||||
|
|
||||||
|
pheader_cache += nb_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t nwrite;
|
||||||
|
if ((ret = skt->writev(iovss, nb_iovss, &nwrite)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pnwrite) {
|
||||||
|
*pnwrite = nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void SrsHttpResponseWriter::write_header(int code)
|
void SrsHttpResponseWriter::write_header(int code)
|
||||||
{
|
{
|
||||||
if (header_wrote) {
|
if (header_wrote) {
|
||||||
|
@ -1513,6 +1579,11 @@ int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)
|
||||||
return writer->write((char*)buf, (int)count);
|
return writer->write((char*)buf, (int)count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
|
||||||
|
{
|
||||||
|
return writer->writev(iov, iovcnt, pnwrite);
|
||||||
|
}
|
||||||
|
|
||||||
SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
|
SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
|
||||||
{
|
{
|
||||||
source = s;
|
source = s;
|
||||||
|
|
|
@ -71,7 +71,11 @@ class SrsHttpMessage;
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_PARSER
|
#ifdef SRS_AUTO_HTTP_PARSER
|
||||||
|
|
||||||
#define SRS_HTTP_HEADER_CACHE_SIZE 16
|
// for HTTP FLV, each video/audio packet is send by 3 iovs,
|
||||||
|
// while each iov is send by 4 sub iovs, that is needs 3 chunk header,
|
||||||
|
// suppose each header is 16 length, 3*16=48 is ok.
|
||||||
|
// that is, 512 can used for 16 iovs to send.
|
||||||
|
#define SRS_HTTP_HEADER_CACHE_SIZE 512
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* response writer use st socket
|
* response writer use st socket
|
||||||
|
@ -105,6 +109,7 @@ public:
|
||||||
virtual int final_request();
|
virtual int final_request();
|
||||||
virtual SrsHttpHeader* header();
|
virtual SrsHttpHeader* header();
|
||||||
virtual int write(char* data, int size);
|
virtual int write(char* data, int size);
|
||||||
|
virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
|
||||||
virtual void write_header(int code);
|
virtual void write_header(int code);
|
||||||
virtual int send_header(char* data, int size);
|
virtual int send_header(char* data, int size);
|
||||||
};
|
};
|
||||||
|
@ -541,6 +546,7 @@ public:
|
||||||
virtual int64_t tellg();
|
virtual int64_t tellg();
|
||||||
public:
|
public:
|
||||||
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
||||||
|
virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR 2
|
#define VERSION_MAJOR 2
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 168
|
#define VERSION_REVISION 169
|
||||||
|
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "SRS"
|
#define RTMP_SIG_SRS_KEY "SRS"
|
||||||
|
|
|
@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <sys/uio.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_log.hpp>
|
#include <srs_kernel_log.hpp>
|
||||||
|
@ -145,6 +146,27 @@ int SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsFileWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
ssize_t nwrite = 0;
|
||||||
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
iovec* piov = iov + i;
|
||||||
|
ssize_t this_nwrite = 0;
|
||||||
|
if ((ret = write(piov->iov_base, piov->iov_len, &this_nwrite)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
nwrite += this_nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pnwrite) {
|
||||||
|
*pnwrite = nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SrsFileReader::SrsFileReader()
|
SrsFileReader::SrsFileReader()
|
||||||
{
|
{
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
|
@ -31,6 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
// for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* file writer, to write to file.
|
* file writer, to write to file.
|
||||||
*/
|
*/
|
||||||
|
@ -62,6 +67,11 @@ public:
|
||||||
* @param pnwrite the output nb_write, NULL to ignore.
|
* @param pnwrite the output nb_write, NULL to ignore.
|
||||||
*/
|
*/
|
||||||
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
||||||
|
/**
|
||||||
|
* for the HTTP FLV, to writev to improve performance.
|
||||||
|
* @see https://github.com/simple-rtmp-server/srs/issues/405
|
||||||
|
*/
|
||||||
|
virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -223,31 +223,24 @@ int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_s
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// write tag header.
|
|
||||||
if ((ret = _fs->write(header, header_size, NULL)) != ERROR_SUCCESS) {
|
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
|
||||||
srs_error("write flv tag header failed. ret=%d", ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write tag data.
|
|
||||||
if ((ret = _fs->write(tag, tag_size, NULL)) != ERROR_SUCCESS) {
|
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
|
||||||
srs_error("write flv tag failed. ret=%d", ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.
|
// PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.
|
||||||
char pre_size[SRS_FLV_PREVIOUS_TAG_SIZE];
|
char pre_size[SRS_FLV_PREVIOUS_TAG_SIZE];
|
||||||
if ((ret = tag_stream->initialize(pre_size, SRS_FLV_PREVIOUS_TAG_SIZE)) != ERROR_SUCCESS) {
|
if ((ret = tag_stream->initialize(pre_size, SRS_FLV_PREVIOUS_TAG_SIZE)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
tag_stream->write_4bytes(tag_size + header_size);
|
tag_stream->write_4bytes(tag_size + header_size);
|
||||||
if ((ret = _fs->write(pre_size, sizeof(pre_size), NULL)) != ERROR_SUCCESS) {
|
|
||||||
|
iovec iovs[3];
|
||||||
|
iovs[0].iov_base = header;
|
||||||
|
iovs[0].iov_len = header_size;
|
||||||
|
iovs[1].iov_base = tag;
|
||||||
|
iovs[1].iov_len = tag_size;
|
||||||
|
iovs[2].iov_base = pre_size;
|
||||||
|
iovs[2].iov_len = sizeof(SRS_FLV_PREVIOUS_TAG_SIZE);
|
||||||
|
|
||||||
|
if ((ret = _fs->writev(iovs, 3, NULL)) != ERROR_SUCCESS) {
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
if (!srs_is_client_gracefully_close(ret)) {
|
||||||
srs_error("write flv previous tag size failed. ret=%d", ret);
|
srs_error("write flv tag failed. ret=%d", ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class SrsFileReader;
|
class SrsFileReader;
|
||||||
class SrsHttpHeader;
|
class SrsHttpHeader;
|
||||||
class ISrsHttpMessage;
|
class ISrsHttpMessage;
|
||||||
|
@ -188,6 +193,11 @@ public:
|
||||||
// the initial 512 bytes of written data to DetectContentType.
|
// the initial 512 bytes of written data to DetectContentType.
|
||||||
// @param data, the data to send. NULL to flush header only.
|
// @param data, the data to send. NULL to flush header only.
|
||||||
virtual int write(char* data, int size) = 0;
|
virtual int write(char* data, int size) = 0;
|
||||||
|
/**
|
||||||
|
* for the HTTP FLV, to writev to improve performance.
|
||||||
|
* @see https://github.com/simple-rtmp-server/srs/issues/405
|
||||||
|
*/
|
||||||
|
virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite) = 0;
|
||||||
|
|
||||||
// WriteHeader sends an HTTP response header with status code.
|
// WriteHeader sends an HTTP response header with status code.
|
||||||
// If WriteHeader is not called explicitly, the first call to Write
|
// If WriteHeader is not called explicitly, the first call to Write
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue