1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-13 20:01:56 +00:00
This commit is contained in:
xiaozhihong 2020-04-13 14:29:19 +08:00
commit 8687c50dc4
34 changed files with 1582 additions and 594 deletions

View file

@ -149,7 +149,6 @@ For previous versions, please read:
- [ ] Support publishing stream by WebRTC, [#307][bug #307].
- [ ] Support change user to run SRS, [#1111][bug #1111].
- [ ] Support HLS variant, [#463][bug #463].
- [ ] Support playing stream by WebRTC.
> Remark: About the milestone and product plan, please read ([CN][v1_CN_Product], [EN][v1_EN_Product]) wiki.

View file

@ -639,10 +639,11 @@ if [[ $SRS_EXPORT_LIBRTMP_PROJECT == NO && $SRS_RTC == YES ]]; then
--disable-programs --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages \
--disable-avdevice --disable-avformat --disable-swscale --disable-postproc --disable-avfilter --disable-network \
--disable-dct --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils \
--disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-appkit --disable-coreimage \
--disable-avfoundation --disable-securetransport --disable-iconv --disable-lzma --disable-sdl2 --disable-everything \
--enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-decoder=libopus --enable-encoder=aac \
--enable-encoder=opus --enable-encoder=libopus --enable-libopus &&
--disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-cuda-llvm --disable-cuvid \
--disable-d3d11va --disable-dxva2 --disable-ffnvcodec --disable-nvdec --disable-nvenc --disable-v4l2-m2m --disable-vaapi \
--disable-vdpau --disable-appkit --disable-coreimage --disable-avfoundation --disable-securetransport --disable-iconv \
--disable-lzma --disable-sdl2 --disable-everything --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm \
--enable-decoder=libopus --enable-encoder=aac --enable-encoder=opus --enable-encoder=libopus --enable-libopus &&
make ${SRS_JOBS} && make install &&
cd .. && rm -rf ffmpeg && ln -sf ffmpeg-4.2-fit/${SRS_PLATFORM}/_release ffmpeg
)

View file

@ -430,6 +430,11 @@ rtc_server {
# @remark Should always turn it on, or Chrome will fail.
# default: on
encrypt on;
# We listen multiple times at the same port, by REUSEPORT, to increase the UDP queue.
# Note that you can set to 1 and increase the system UDP buffer size by net.core.rmem_max
# and net.core.rmem_default or just increase this to get larger UDP recv and send buffer.
# default: 4
reuseport 4;
}
vhost rtc.vhost.srs.com {

12
trunk/configure vendored
View file

@ -444,7 +444,7 @@ mv ${SRS_WORKDIR}/${SRS_MAKEFILE} ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk
# generate phony header
cat << END > ${SRS_WORKDIR}/${SRS_MAKEFILE}
.PHONY: default _default install install-api help clean destroy server srs_ingest_hls librtmp utest _prepare_dir $__mphonys
.PHONY: clean_srs clean_modules clean_openssl clean_nginx clean_cherrypy clean_srtp2 clean_opus
.PHONY: clean_srs clean_modules clean_openssl clean_nginx clean_cherrypy clean_srtp2 clean_opus clean_ffmpeg clean_st
.PHONY: st ffmpeg
# install prefix.
@ -481,6 +481,8 @@ help:
@echo " clean_openssl Remove the openssl cache."
@echo " clean_srtp2 Remove the libsrtp2 cache."
@echo " clean_opus Remove the opus cache."
@echo " clean_ffmpeg Remove the FFmpeg cache."
@echo " clean_st Remove the ST cache."
@echo "For example:"
@echo " make"
@echo " make help"
@ -519,6 +521,14 @@ clean_opus:
(cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf opus-1.3.1)
@echo "Please rebuild opus by: ./configure"
clean_ffmpeg:
(cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf ffmpeg-4.2-fit)
@echo "Please rebuild FFmpeg by: ./configure"
clean_st:
(cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf st-srs)
@echo "Please rebuild ST by: ./configure"
clean_nginx:
(cd ${SRS_OBJS_DIR} && rm -rf nginx)

View file

@ -388,16 +388,13 @@ srs_error_t SrsAudioRecode::initialize()
srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int &n)
{
srs_error_t err = srs_success;
static char decode_buffer[kPacketBufMax];
static char resample_buffer[kFrameBufMax];
static char encode_buffer[kPacketBufMax];
if (!dec_) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "dec_ nullptr");
}
int decode_len = kPacketBufMax;
static char decode_buffer[kPacketBufMax];
if ((err = dec_->decode(pkt, decode_buffer, decode_len)) != srs_success) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error");
}
@ -412,15 +409,18 @@ srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int
if (!resample_) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "SrsAudioResample failed");
}
resample_->initialize();
if ((err = resample_->initialize()) != srs_success) {
return srs_error_wrap(err, "init resample");
}
}
SrsSample pcm;
pcm.bytes = decode_buffer;
pcm.size = decode_len;
int resample_len = kFrameBufMax;
static char resample_buffer[kFrameBufMax];
if ((err = resample_->resample(&pcm, resample_buffer, resample_len)) != srs_success) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error");
return srs_error_new(ERROR_RTC_RTP_MUXER, "resample error");
}
n = 0;
@ -445,8 +445,9 @@ srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int
int encode_len;
pcm.bytes = (char *)data_;
pcm.size = size_;
static char encode_buffer[kPacketBufMax];
if ((err = enc_->encode(&pcm, encode_buffer, encode_len)) != srs_success) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error");
return srs_error_new(ERROR_RTC_RTP_MUXER, "encode error");
}
memcpy(buf[n], encode_buffer, encode_len);

View file

@ -1540,6 +1540,11 @@ srs_error_t SrsConfig::reload_conf(SrsConfig* conf)
if ((err = reload_http_stream(old_root)) != srs_success) {
return srs_error_wrap(err, "http steram");;
}
// Merge config: rtc_server
if ((err = reload_rtc_server(old_root)) != srs_success) {
return srs_error_wrap(err, "http steram");;
}
// TODO: FIXME: support reload stream_caster.
@ -1697,6 +1702,40 @@ srs_error_t SrsConfig::reload_http_stream(SrsConfDirective* old_root)
return err;
}
srs_error_t SrsConfig::reload_rtc_server(SrsConfDirective* old_root)
{
srs_error_t err = srs_success;
// merge config.
std::vector<ISrsReloadHandler*>::iterator it;
// state graph
// old_rtc_server new_rtc_server
// ENABLED => ENABLED (modified)
SrsConfDirective* new_rtc_server = root->get("rtc_server");
SrsConfDirective* old_rtc_server = old_root->get("rtc_server");
// TODO: FIXME: Support disable or enable reloading.
// ENABLED => ENABLED (modified)
if (get_rtc_server_enabled(old_rtc_server) && get_rtc_server_enabled(new_rtc_server)
&& !srs_directive_equals(old_rtc_server, new_rtc_server)
) {
for (it = subscribes.begin(); it != subscribes.end(); ++it) {
ISrsReloadHandler* subscribe = *it;
if ((err = subscribe->on_reload_rtc_server()) != srs_success) {
return srs_error_wrap(err, "rtc server enabled");
}
}
srs_trace("reload rtc server success.");
return err;
}
srs_trace("reload rtc server success, nothing changed.");
return err;
}
srs_error_t SrsConfig::reload_transcode(SrsConfDirective* new_vhost, SrsConfDirective* old_vhost)
{
srs_error_t err = srs_success;
@ -3575,7 +3614,7 @@ srs_error_t SrsConfig::check_normal_config()
for (int i = 0; conf && i < (int)conf->directives.size(); i++) {
string n = conf->at(i)->name;
if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa"
&& n != "sendmmsg" && n != "encrypt") {
&& n != "sendmmsg" && n != "encrypt" && n != "reuseport") {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str());
}
}
@ -4706,6 +4745,33 @@ int SrsConfig::get_rtc_server_sendmmsg()
#endif
}
int SrsConfig::get_rtc_server_reuseport()
{
#if defined(SO_REUSEPORT)
static int DEFAULT = 4;
#else
static int DEFAULT = 1;
#endif
SrsConfDirective* conf = root->get("rtc_server");
if (!conf) {
return DEFAULT;
}
conf = conf->get("reuseport");
if (!conf || conf->arg0().empty()) {
return DEFAULT;
}
int reuseport = ::atoi(conf->arg0().c_str());
#if !defined(SO_REUSEPORT)
srs_warn("REUSEPORT not supported, reset %d to %d", reuseport, DEFAULT);
reuseport = DEFAULT
#endif
return reuseport;
}
SrsConfDirective* SrsConfig::get_rtc(string vhost)
{
SrsConfDirective* conf = get_vhost(vhost);

View file

@ -333,6 +333,8 @@ private:
// Reload the http_stream section of config.
// TODO: FIXME: rename to http_server.
virtual srs_error_t reload_http_stream(SrsConfDirective* old_root);
// Reload the rtc_server section of config.
virtual srs_error_t reload_rtc_server(SrsConfDirective* old_root);
// Reload the transcode section of vhost of config.
virtual srs_error_t reload_transcode(SrsConfDirective* new_vhost, SrsConfDirective* old_vhost);
// Reload the ingest section of vhost of config.
@ -525,6 +527,7 @@ public:
virtual bool get_rtc_server_ecdsa();
virtual int get_rtc_server_sendmmsg();
virtual bool get_rtc_server_encrypt();
virtual int get_rtc_server_reuseport();
SrsConfDirective* get_rtc(std::string vhost);
bool get_rtc_enabled(std::string vhost);

View file

@ -40,6 +40,7 @@ using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_app_server.hpp>
#include <srs_app_utility.hpp>
#include <srs_kernel_utility.hpp>
// set the max packet size.
#define SRS_UDP_MAX_PACKET_SIZE 65535
@ -235,12 +236,21 @@ srs_error_t SrsTcpListener::cycle()
return err;
}
SrsUdpMuxSocket::SrsUdpMuxSocket(srs_netfd_t fd)
ISrsUdpSender::ISrsUdpSender()
{
}
ISrsUdpSender::~ISrsUdpSender()
{
}
SrsUdpMuxSocket::SrsUdpMuxSocket(ISrsUdpSender* h, srs_netfd_t fd)
{
nb_buf = SRS_UDP_MAX_PACKET_SIZE;
buf = new char[nb_buf];
nread = 0;
handler = h;
lfd = fd;
fromlen = 0;
@ -253,7 +263,7 @@ SrsUdpMuxSocket::~SrsUdpMuxSocket()
SrsUdpMuxSocket* SrsUdpMuxSocket::copy_sendonly()
{
SrsUdpMuxSocket* sendonly = new SrsUdpMuxSocket(lfd);
SrsUdpMuxSocket* sendonly = new SrsUdpMuxSocket(handler, lfd);
// Don't copy buffer
srs_freepa(sendonly->buf);
@ -339,16 +349,18 @@ std::string SrsUdpMuxSocket::get_peer_id()
return string(id_buf, len);
}
SrsUdpMuxListener::SrsUdpMuxListener(ISrsUdpMuxHandler* h, std::string i, int p)
SrsUdpMuxListener::SrsUdpMuxListener(ISrsUdpMuxHandler* h, ISrsUdpSender* s, std::string i, int p)
{
handler = h;
sender = s;
ip = i;
port = p;
lfd = NULL;
nb_buf = SRS_UDP_MAX_PACKET_SIZE;
buf = new char[nb_buf];
trd = new SrsDummyCoroutine();
}
@ -390,60 +402,108 @@ srs_error_t SrsUdpMuxListener::listen()
void SrsUdpMuxListener::set_socket_buffer()
{
int sndbuf_size = 0;
socklen_t opt_len = sizeof(sndbuf_size);
getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, &opt_len);
srs_trace("default udp remux socket sndbuf=%d", sndbuf_size);
int default_sndbuf = 0;
// TODO: FIXME: Config it.
int expect_sndbuf = 1024*1024*10; // 10M
int actual_sndbuf = expect_sndbuf;
int r0_sndbuf = 0;
if (true) {
socklen_t opt_len = sizeof(default_sndbuf);
getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&default_sndbuf, &opt_len);
sndbuf_size = 1024*1024*10; // 10M
if (setsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, sizeof(sndbuf_size)) < 0) {
srs_warn("set sock opt SO_SNDBUFFORCE failed");
if ((r0_sndbuf = setsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&actual_sndbuf, sizeof(actual_sndbuf))) < 0) {
srs_warn("set SO_SNDBUF failed, expect=%d, r0=%d", expect_sndbuf, r0_sndbuf);
}
opt_len = sizeof(actual_sndbuf);
getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&actual_sndbuf, &opt_len);
}
opt_len = sizeof(sndbuf_size);
getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, &opt_len);
srs_trace("udp remux socket sndbuf=%d", sndbuf_size);
int default_rcvbuf = 0;
// TODO: FIXME: Config it.
int expect_rcvbuf = 1024*1024*10; // 10M
int actual_rcvbuf = expect_rcvbuf;
int r0_rcvbuf = 0;
if (true) {
socklen_t opt_len = sizeof(default_rcvbuf);
getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&default_rcvbuf, &opt_len);
int rcvbuf_size = 0;
opt_len = sizeof(rcvbuf_size);
getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, &opt_len);
srs_trace("default udp remux socket rcvbuf=%d", rcvbuf_size);
if ((r0_rcvbuf = setsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&actual_rcvbuf, sizeof(actual_rcvbuf))) < 0) {
srs_warn("set SO_RCVBUF failed, expect=%d, r0=%d", expect_rcvbuf, r0_rcvbuf);
}
rcvbuf_size = 1024*1024*10; // 10M
if (setsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
srs_warn("set sock opt SO_RCVBUFFORCE failed");
opt_len = sizeof(actual_rcvbuf);
getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&actual_rcvbuf, &opt_len);
}
opt_len = sizeof(rcvbuf_size);
getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, &opt_len);
srs_trace("udp remux socket rcvbuf=%d", rcvbuf_size);
srs_trace("UDP #%d LISTEN at %s:%d, SO_SNDBUF(default=%d, expect=%d, actual=%d, r0=%d), SO_RCVBUF(default=%d, expect=%d, actual=%d, r0=%d)",
srs_netfd_fileno(lfd), ip.c_str(), port, default_sndbuf, expect_sndbuf, actual_sndbuf, r0_sndbuf, default_rcvbuf, expect_rcvbuf, actual_rcvbuf, r0_rcvbuf);
}
srs_error_t SrsUdpMuxListener::cycle()
{
srs_error_t err = srs_success;
SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_recv(srs_netfd_fileno(lfd));
SrsAutoFree(SrsPithyPrint, pprint);
uint64_t nn_msgs = 0;
uint64_t nn_msgs_stage = 0;
uint64_t nn_msgs_last = 0;
uint64_t nn_loop = 0;
srs_utime_t time_last = srs_get_system_time();
while (true) {
if ((err = trd->pull()) != srs_success) {
return srs_error_wrap(err, "udp listener");
}
}
SrsUdpMuxSocket udp_mux_skt(lfd);
nn_loop++;
int nread = udp_mux_skt.recvfrom(SRS_UTIME_NO_TIMEOUT);
SrsUdpMuxSocket skt(sender, lfd);
int nread = skt.recvfrom(SRS_UTIME_NO_TIMEOUT);
if (nread <= 0) {
if (nread < 0) {
srs_warn("udp recv error");
}
// remux udp never return
continue;
}
}
nn_msgs++;
nn_msgs_stage++;
if ((err = handler->on_udp_packet(&udp_mux_skt)) != srs_success) {
if ((err = handler->on_udp_packet(&skt)) != srs_success) {
// remux udp never return
srs_warn("udp packet handler error:%s", srs_error_desc(err).c_str());
continue;
}
srs_error_reset(err);
}
pprint->elapse();
if (pprint->can_print()) {
int pps_average = 0; int pps_last = 0;
if (true) {
if (srs_get_system_time() > srs_get_system_startup_time()) {
pps_average = (int)(nn_msgs * SRS_UTIME_SECONDS / (srs_get_system_time() - srs_get_system_startup_time()));
}
if (srs_get_system_time() > time_last) {
pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last));
}
}
string pps_unit = "";
if (pps_last > 10000 || pps_average > 10000) {
pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000;
} else if (pps_last > 1000 || pps_average > 1000) {
pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000;
}
srs_trace("<- RTC #%d RECV %" PRId64 ", pps %d/%d%s, schedule %" PRId64,
srs_netfd_fileno(lfd), nn_msgs_stage, pps_average, pps_last, pps_unit.c_str(), nn_loop);
nn_msgs_last = nn_msgs; time_last = srs_get_system_time();
nn_loop = 0; nn_msgs_stage = 0;
}
if (SrsUdpPacketRecvCycleInterval > 0) {
srs_usleep(SrsUdpPacketRecvCycleInterval);

View file

@ -69,7 +69,7 @@ public:
virtual ~ISrsUdpMuxHandler();
public:
virtual srs_error_t on_stfd_change(srs_netfd_t fd);
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* udp_mux_skt) = 0;
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* skt) = 0;
};
// The tcp connection handler.
@ -131,9 +131,22 @@ public:
virtual srs_error_t cycle();
};
class ISrsUdpSender
{
public:
ISrsUdpSender();
virtual ~ISrsUdpSender();
public:
// Fetch a mmsghdr from sender's cache.
virtual srs_error_t fetch(mmsghdr** pphdr) = 0;
// Notify the sender to send out the msg.
virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0;
};
class SrsUdpMuxSocket
{
private:
ISrsUdpSender* handler;
char* buf;
int nb_buf;
int nread;
@ -143,7 +156,7 @@ private:
std::string peer_ip;
int peer_port;
public:
SrsUdpMuxSocket(srs_netfd_t fd);
SrsUdpMuxSocket(ISrsUdpSender* h, srs_netfd_t fd);
virtual ~SrsUdpMuxSocket();
int recvfrom(srs_utime_t timeout);
@ -160,6 +173,7 @@ public:
std::string get_peer_id();
public:
SrsUdpMuxSocket* copy_sendonly();
ISrsUdpSender* sender() { return handler; };
private:
// Don't allow copy, user copy_sendonly instead
SrsUdpMuxSocket(const SrsUdpMuxSocket& rhs);
@ -170,6 +184,7 @@ class SrsUdpMuxListener : public ISrsCoroutineHandler
{
protected:
srs_netfd_t lfd;
ISrsUdpSender* sender;
SrsCoroutine* trd;
protected:
char* buf;
@ -179,7 +194,7 @@ protected:
std::string ip;
int port;
public:
SrsUdpMuxListener(ISrsUdpMuxHandler* h, std::string i, int p);
SrsUdpMuxListener(ISrsUdpMuxHandler* h, ISrsUdpSender* s, std::string i, int p);
virtual ~SrsUdpMuxListener();
public:
virtual int fd();

View file

@ -112,6 +112,10 @@ SrsPithyPrint::SrsPithyPrint(int _stage_id)
#define SRS_CONSTS_STAGE_EXEC 11
// for the rtc play
#define SRS_CONSTS_STAGE_RTC_PLAY 12
// for the rtc send
#define SRS_CONSTS_STAGE_RTC_SEND 13
// for the rtc recv
#define SRS_CONSTS_STAGE_RTC_RECV 14
SrsPithyPrint* SrsPithyPrint::create_rtmp_play()
{
@ -173,6 +177,16 @@ SrsPithyPrint* SrsPithyPrint::create_rtc_play()
return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_PLAY);
}
SrsPithyPrint* SrsPithyPrint::create_rtc_send(int fd)
{
return new SrsPithyPrint(fd<<16 | SRS_CONSTS_STAGE_RTC_SEND);
}
SrsPithyPrint* SrsPithyPrint::create_rtc_recv(int fd)
{
return new SrsPithyPrint(fd<<16 | SRS_CONSTS_STAGE_RTC_RECV);
}
SrsPithyPrint::~SrsPithyPrint()
{
leave_stage();

View file

@ -88,6 +88,9 @@ public:
static SrsPithyPrint* create_http_stream();
static SrsPithyPrint* create_http_stream_cache();
static SrsPithyPrint* create_rtc_play();
// For RTC sender and receiver, we create printer for each fd.
static SrsPithyPrint* create_rtc_send(int fd);
static SrsPithyPrint* create_rtc_recv(int fd);
virtual ~SrsPithyPrint();
private:
// Enter the specified stage, return the client id.

View file

@ -115,6 +115,11 @@ srs_error_t ISrsReloadHandler::on_reload_http_stream_crossdomain()
return srs_success;
}
srs_error_t ISrsReloadHandler::on_reload_rtc_server()
{
return srs_success;
}
srs_error_t ISrsReloadHandler::on_reload_vhost_http_updated()
{
return srs_success;

View file

@ -55,6 +55,7 @@ public:
virtual srs_error_t on_reload_http_stream_disabled();
virtual srs_error_t on_reload_http_stream_updated();
virtual srs_error_t on_reload_http_stream_crossdomain();
virtual srs_error_t on_reload_rtc_server();
public:
// TODO: FIXME: should rename to http_static
virtual srs_error_t on_reload_vhost_http_updated();

View file

@ -54,7 +54,7 @@ using namespace std;
#include <srs_app_audio_recode.hpp>
// TODO: Add this function into SrsRtpMux class.
srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer** stream_ptr)
srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char** pbuf, int* pnn_buf)
{
srs_error_t err = srs_success;
@ -62,37 +62,33 @@ srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFor
return err;
}
if (stream_ptr == NULL) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "adts");
}
if (format->audio->nb_samples != 1) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "adts");
}
int nb_buf = format->audio->samples[0].size + 7;
char* buf = new char[nb_buf];
SrsBuffer* stream = new SrsBuffer(buf, nb_buf);
SrsBuffer stream(buf, nb_buf);
// TODO: Add comment.
stream->write_1bytes(0xFF);
stream->write_1bytes(0xF9);
stream->write_1bytes(((format->acodec->aac_object - 1) << 6) | ((format->acodec->aac_sample_rate & 0x0F) << 2) | ((format->acodec->aac_channels & 0x04) >> 2));
stream->write_1bytes(((format->acodec->aac_channels & 0x03) << 6) | ((nb_buf >> 11) & 0x03));
stream->write_1bytes((nb_buf >> 3) & 0xFF);
stream->write_1bytes(((nb_buf & 0x07) << 5) | 0x1F);
stream->write_1bytes(0xFC);
stream.write_1bytes(0xFF);
stream.write_1bytes(0xF9);
stream.write_1bytes(((format->acodec->aac_object - 1) << 6) | ((format->acodec->aac_sample_rate & 0x0F) << 2) | ((format->acodec->aac_channels & 0x04) >> 2));
stream.write_1bytes(((format->acodec->aac_channels & 0x03) << 6) | ((nb_buf >> 11) & 0x03));
stream.write_1bytes((nb_buf >> 3) & 0xFF);
stream.write_1bytes(((nb_buf & 0x07) << 5) | 0x1F);
stream.write_1bytes(0xFC);
stream->write_bytes(format->audio->samples[0].bytes, format->audio->samples[0].size);
stream.write_bytes(format->audio->samples[0].bytes, format->audio->samples[0].size);
*stream_ptr = stream;
*pbuf = buf;
*pnn_buf = nb_buf;
return err;
}
SrsRtpH264Muxer::SrsRtpH264Muxer()
{
sequence = 0;
discard_bframe = false;
}
@ -100,269 +96,114 @@ SrsRtpH264Muxer::~SrsRtpH264Muxer()
{
}
srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsFormat* format)
srs_error_t SrsRtpH264Muxer::filter(SrsSharedPtrMessage* shared_frame, SrsFormat* format)
{
srs_error_t err = srs_success;
if (format->is_avc_sequence_header()) {
sps.assign(format->vcodec->sequenceParameterSetNALUnit.data(), format->vcodec->sequenceParameterSetNALUnit.size());
pps.assign(format->vcodec->pictureParameterSetNALUnit.data(), format->vcodec->pictureParameterSetNALUnit.size());
// only collect SPS/PPS.
// If IDR, we will insert SPS/PPS before IDR frame.
if (format->video && format->video->has_idr) {
shared_frame->set_has_idr(true);
}
// Update samples to shared frame.
for (int i = 0; i < format->video->nb_samples; ++i) {
SrsSample* sample = &format->video->samples[i];
// Because RTC does not support B-frame, so we will drop them.
// TODO: Drop B-frame in better way, which not cause picture corruption.
if (discard_bframe) {
if ((err = sample->parse_bframe()) != srs_success) {
return srs_error_wrap(err, "parse bframe");
}
if (sample->bframe) {
continue;
}
}
}
if (format->video->nb_samples <= 0) {
return err;
}
vector<SrsRtpSharedPacket*> rtp_packet_vec;
for (int i = 0; i < format->video->nb_samples; ++i) {
SrsSample sample = format->video->samples[i];
uint8_t header = sample.bytes[0];
uint8_t nal_type = header & kNalTypeMask;
// TODO: Use config to determine should check avc stream.
if (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR) {
SrsBuffer* stream = new SrsBuffer(sample.bytes, sample.size);
SrsAutoFree(SrsBuffer, stream);
// Skip nalu header.
stream->skip(1);
SrsBitBuffer bitstream(stream);
int32_t first_mb_in_slice = 0;
if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) {
return srs_error_wrap(err, "nalu read uev");
}
int32_t slice_type = 0;
if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type)) != srs_success) {
return srs_error_wrap(err, "nalu read uev");
}
srs_verbose("nal_type=%d, slice type=%d", nal_type, slice_type);
if (slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1) {
if (discard_bframe) {
continue;
}
}
}
if (sample.size <= kRtpMaxPayloadSize) {
if ((err = packet_single_nalu(shared_frame, format, &sample, rtp_packet_vec)) != srs_success) {
return srs_error_wrap(err, "packet single nalu");
}
} else {
if ((err = packet_fu_a(shared_frame, format, &sample, rtp_packet_vec)) != srs_success) {
return srs_error_wrap(err, "packet fu-a");
}
}
}
if (! rtp_packet_vec.empty()) {
// At the end of the frame, set marker bit.
// One frame may have multi nals. Set the marker bit in the last nal end, no the end of the nal.
if ((err = rtp_packet_vec.back()->modify_rtp_header_marker(true)) != srs_success) {
return srs_error_wrap(err, "set marker");
}
}
shared_frame->set_rtp_packets(rtp_packet_vec);
return err;
}
srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsRtpSharedPacket*>& rtp_packet_vec)
{
srs_error_t err = srs_success;
char* p = sample->bytes + 1;
int nb_left = sample->size - 1;
uint8_t header = sample->bytes[0];
uint8_t nal_type = header & kNalTypeMask;
if (nal_type == SrsAvcNaluTypeIDR) {
if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packet_vec)) != srs_success) {
return srs_error_wrap(err, "packet stap-a");
}
}
int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize;
for (int i = 0; i < num_of_packet; ++i) {
char buf[kRtpPacketSize];
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
SrsAutoFree(SrsBuffer, stream);
int packet_size = min(nb_left, kRtpMaxPayloadSize);
// fu-indicate
uint8_t fu_indicate = kFuA;
fu_indicate |= (header & (~kNalTypeMask));
stream->write_1bytes(fu_indicate);
uint8_t fu_header = nal_type;
if (i == 0)
fu_header |= kStart;
if (i == num_of_packet - 1)
fu_header |= kEnd;
stream->write_1bytes(fu_header);
stream->write_bytes(p, packet_size);
p += packet_size;
nb_left -= packet_size;
srs_verbose("rtp fu-a nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90));
SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket();
if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) {
return srs_error_wrap(err, "rtp packet encode");
}
rtp_packet_vec.push_back(rtp_shared_pkt);
}
return err;
}
srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsRtpSharedPacket*>& rtp_packet_vec)
{
srs_error_t err = srs_success;
uint8_t header = sample->bytes[0];
uint8_t nal_type = header & kNalTypeMask;
if (nal_type == SrsAvcNaluTypeIDR) {
if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packet_vec)) != srs_success) {
return srs_error_wrap(err, "packet stap-a");
}
}
srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90));
SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket();
if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) {
return srs_error_wrap(err, "rtp packet encode");
}
rtp_packet_vec.push_back(rtp_shared_pkt);
return err;
}
srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsSharedPtrMessage* shared_frame, vector<SrsRtpSharedPacket*>& rtp_packet_vec)
{
srs_error_t err = srs_success;
if (sps.empty() || pps.empty()) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty");
}
uint8_t header = sps[0];
uint8_t nal_type = header & kNalTypeMask;
char buf[kRtpPacketSize];
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
SrsAutoFree(SrsBuffer, stream);
// stap-a header
uint8_t stap_a_header = kStapA;
stap_a_header |= (nal_type & (~kNalTypeMask));
stream->write_1bytes(stap_a_header);
stream->write_2bytes(sps.size());
stream->write_bytes((char*)sps.data(), sps.size());
stream->write_2bytes(pps.size());
stream->write_bytes((char*)pps.data(), pps.size());
srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", (sps.size() + pps.size()), sequence, (shared_frame->timestamp * 90));
SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket();
if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) {
return srs_error_wrap(err, "rtp packet encode");
}
rtp_packet_vec.push_back(rtp_shared_pkt);
shared_frame->set_samples(format->video->samples, format->video->nb_samples);
return err;
}
SrsRtpOpusMuxer::SrsRtpOpusMuxer()
{
sequence = 0;
timestamp = 0;
transcode = NULL;
codec = NULL;
}
SrsRtpOpusMuxer::~SrsRtpOpusMuxer()
{
if (transcode) {
delete transcode;
transcode = NULL;
}
srs_freep(codec);
}
srs_error_t SrsRtpOpusMuxer::initialize()
{
srs_error_t err = srs_success;
transcode = new SrsAudioRecode(kChannel, kSamplerate);
if (!transcode) {
codec = new SrsAudioRecode(kChannel, kSamplerate);
if (!codec) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "SrsAacOpus init failed");
}
transcode->initialize();
if ((err = codec->initialize()) != srs_success) {
return srs_error_wrap(err, "init codec");
}
return err;
}
srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer* stream)
// An AAC packet may be transcoded to many OPUS packets.
const int kMaxOpusPackets = 8;
// The max size for each OPUS packet.
const int kMaxOpusPacketSize = 4096;
srs_error_t SrsRtpOpusMuxer::transcode(SrsSharedPtrMessage* shared_audio, char* adts_audio, int nn_adts_audio)
{
srs_error_t err = srs_success;
vector<SrsRtpSharedPacket*> rtp_packet_vec;
// Opus packet cache.
static char* opus_payloads[kMaxOpusPackets];
char* data_ptr[kArrayLength];
static char data_array[kArrayLength][kArrayBuffer];
int elen[kArrayLength], number = 0;
static bool initialized = false;
if (!initialized) {
initialized = true;
data_ptr[0] = &data_array[0][0];
for (int i = 1; i < kArrayLength; i++) {
data_ptr[i] = data_array[i];
static char opus_packets_cache[kMaxOpusPackets][kMaxOpusPacketSize];
opus_payloads[0] = &opus_packets_cache[0][0];
for (int i = 1; i < kMaxOpusPackets; i++) {
opus_payloads[i] = opus_packets_cache[i];
}
}
SrsSample pkt;
pkt.bytes = stream->data();
pkt.size = stream->pos();
// Transcode an aac packet to many opus packets.
SrsSample aac;
aac.bytes = adts_audio;
aac.size = nn_adts_audio;
if ((err = transcode->recode(&pkt, data_ptr, elen, number)) != srs_success) {
int nn_opus_packets = 0;
int opus_sizes[kMaxOpusPackets];
if ((err = codec->recode(&aac, opus_payloads, opus_sizes, nn_opus_packets)) != srs_success) {
return srs_error_wrap(err, "recode error");
}
for (int i = 0; i < number; i++) {
SrsSample sample;
sample.size = elen[i];
sample.bytes = data_ptr[i];
packet_opus(shared_audio, &sample, rtp_packet_vec);
// Save OPUS packets in shared message.
if (nn_opus_packets <= 0) {
return err;
}
shared_audio->set_rtp_packets(rtp_packet_vec);
return err;
}
srs_error_t SrsRtpOpusMuxer::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector<SrsRtpSharedPacket*>& rtp_packet_vec)
{
srs_error_t err = srs_success;
SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket();
rtp_shared_pkt->rtp_header.set_marker(true);
if ((err = rtp_shared_pkt->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) {
return srs_error_wrap(err, "rtp packet encode");
SrsSample samples[nn_opus_packets];
for (int i = 0; i < nn_opus_packets; i++) {
SrsSample* p = samples + i;
p->size = opus_sizes[i];
p->bytes = new char[p->size];
memcpy(p->bytes, opus_payloads[i], p->size);
}
// TODO: FIXME: Why 960? Need Refactoring?
timestamp += 960;
rtp_packet_vec.push_back(rtp_shared_pkt);
shared_audio->set_extra_payloads(samples, nn_opus_packets);
return err;
}
@ -485,17 +326,16 @@ srs_error_t SrsRtc::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma
// ignore sequence header
srs_assert(format->audio);
SrsBuffer* stream = NULL;
SrsAutoFree(SrsBuffer, stream);
if ((err = aac_raw_append_adts_header(shared_audio, format, &stream)) != srs_success) {
char* adts_audio = NULL;
int nn_adts_audio = 0;
// TODO: FIXME: Reserve 7 bytes header when create shared message.
if ((err = aac_raw_append_adts_header(shared_audio, format, &adts_audio, &nn_adts_audio)) != srs_success) {
return srs_error_wrap(err, "aac append header");
}
if (stream) {
char* stream_data = stream->data();
SrsAutoFreeA(char, stream_data);
return rtp_opus_muxer->frame_to_packet(shared_audio, format, stream);
if (adts_audio) {
err = rtp_opus_muxer->transcode(shared_audio, adts_audio, nn_adts_audio);
srs_freep(adts_audio);
}
return err;
@ -522,5 +362,5 @@ srs_error_t SrsRtc::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* forma
// ignore info frame,
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
srs_assert(format->video);
return rtp_h264_muxer->frame_to_packet(shared_video, format);
return rtp_h264_muxer->filter(shared_video, format);
}

View file

@ -39,30 +39,15 @@ class SrsOriginHub;
class SrsAudioRecode;
class SrsBuffer;
// Rtp packet max payload size, not include rtp header.
// Must left some bytes to payload header, rtp header, udp header, ip header.
const int kRtpMaxPayloadSize = 1200;
// The RTP packet max size, should never exceed this size.
const int kRtpPacketSize = 1500;
// Payload type will rewrite in srs_app_rtc_conn.cpp when send to client.
const uint8_t kOpusPayloadType = 111;
const uint8_t kH264PayloadType = 102;
// H.264 nalu header type mask.
const uint8_t kNalTypeMask = 0x1F;
// @see: https://tools.ietf.org/html/rfc6184#section-5.2
const uint8_t kStapA = 24;
const uint8_t kFuA = 28;
// @see: https://tools.ietf.org/html/rfc6184#section-5.8
const uint8_t kStart = 0x80; // Fu-header start bit
const uint8_t kEnd = 0x40; // Fu-header end bit
const int kChannel = 2;
const int kSamplerate = 48000;
const int kArrayLength = 8;
const int kArrayBuffer = 4096;
// SSRC will rewrite in srs_app_rtc_conn.cpp when send to client.
const uint32_t kAudioSSRC = 1;
@ -71,39 +56,26 @@ const uint32_t kVideoSSRC = 2;
// TODO: Define interface class like ISrsRtpMuxer
class SrsRtpH264Muxer
{
private:
uint16_t sequence;
std::string sps;
std::string pps;
public:
bool discard_bframe;
public:
SrsRtpH264Muxer();
virtual ~SrsRtpH264Muxer();
public:
srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_video, SrsFormat* format);
private:
srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector<SrsRtpSharedPacket*>& rtp_packet_vec);
srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector<SrsRtpSharedPacket*>& rtp_packet_vec);
srs_error_t packet_stap_a(const std::string &sps, const std::string& pps, SrsSharedPtrMessage* shared_frame, std::vector<SrsRtpSharedPacket*>& rtp_packet_vec);
srs_error_t filter(SrsSharedPtrMessage* shared_video, SrsFormat* format);
};
// TODO: FIXME: It's not a muxer, but a transcoder.
class SrsRtpOpusMuxer
{
private:
// TODO: FIXME: How to handle timestamp overflow?
uint32_t timestamp;
uint16_t sequence;
SrsAudioRecode* transcode;
SrsAudioRecode* codec;
public:
SrsRtpOpusMuxer();
virtual ~SrsRtpOpusMuxer();
virtual srs_error_t initialize();
public:
srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer* stream);
private:
srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector<SrsRtpSharedPacket*>& rtp_packet_vec);
srs_error_t transcode(SrsSharedPtrMessage* shared_audio, char* adts_audio, int nn_adts_audio);
};
class SrsRtc

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@
#include <srs_app_hybrid.hpp>
#include <srs_app_hourglass.hpp>
#include <srs_app_sdp.hpp>
#include <srs_app_reload.hpp>
#include <string>
#include <map>
@ -48,6 +49,7 @@ class SrsRtcServer;
class SrsRtcSession;
class SrsSharedPtrMessage;
class SrsSource;
class SrsRtpPacket2;
const uint8_t kSR = 200;
const uint8_t kRR = 201;
@ -98,16 +100,17 @@ public:
srs_error_t initialize(const SrsRequest& req);
srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_dtls_handshake_done(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_dtls(SrsUdpMuxSocket* skt);
srs_error_t on_dtls_handshake_done(SrsUdpMuxSocket* skt);
srs_error_t on_dtls_application_data(const char* data, const int len);
public:
srs_error_t protect_rtp(char* protected_buf, const char* ori_buf, int& nb_protected_buf);
srs_error_t protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* pkt);
srs_error_t unprotect_rtp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf);
srs_error_t protect_rtcp(char* protected_buf, const char* ori_buf, int& nb_protected_buf);
srs_error_t unprotect_rtcp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf);
private:
srs_error_t handshake(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t handshake(SrsUdpMuxSocket* skt);
private:
srs_error_t srtp_initialize();
srs_error_t srtp_send_init();
@ -125,6 +128,12 @@ private:
uint32_t audio_ssrc;
uint16_t video_payload_type;
uint16_t audio_payload_type;
private:
// TODO: FIXME: How to handle timestamp overflow?
uint32_t audio_timestamp;
uint16_t audio_sequence;
private:
uint16_t video_sequence;
public:
SrsUdpMuxSocket* sendonly_ukt;
public:
@ -139,11 +148,18 @@ public:
virtual void stop();
virtual void stop_loop();
public:
virtual srs_error_t cycle();
void update_sendonly_socket(SrsUdpMuxSocket* skt);
public:
void update_sendonly_socket(SrsUdpMuxSocket* ukt);
virtual srs_error_t cycle();
private:
void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* udp_mux_skt);
srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts);
srs_error_t send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt);
private:
srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket);
private:
srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, std::vector<SrsRtpPacket2*>& packets);
srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket);
srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket);
};
class SrsRtcSession
@ -194,40 +210,73 @@ public:
void switch_to_context();
public:
srs_error_t on_stun(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req);
srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_rtcp(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req);
srs_error_t on_dtls(SrsUdpMuxSocket* skt);
srs_error_t on_rtcp(SrsUdpMuxSocket* skt);
public:
srs_error_t send_client_hello(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_connection_established(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t start_play(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t send_client_hello(SrsUdpMuxSocket* skt);
srs_error_t on_connection_established(SrsUdpMuxSocket* skt);
srs_error_t start_play(SrsUdpMuxSocket* skt);
public:
bool is_stun_timeout();
private:
srs_error_t check_source();
private:
srs_error_t on_binding_request(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req);
srs_error_t on_binding_request(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req);
private:
<<<<<<< HEAD
srs_error_t on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt);
// Internal only.
public:
void send_and_free_messages(srs_netfd_t stfd, sockaddr_in* addr, socklen_t addrlen, char* buf, int length);
=======
srs_error_t on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt);
srs_error_t on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt);
srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* skt);
>>>>>>> upstream/feature/rtc
};
class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, virtual public ISrsCoroutineHandler
class SrsUdpMuxSender : virtual public ISrsUdpSender, virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler
{
private:
SrsUdpMuxListener* listener;
SrsHourGlass* timer;
private:
srs_netfd_t lfd;
SrsRtcServer* server;
SrsCoroutine* trd;
private:
srs_cond_t cond;
bool waiting_msgs;
// TODO: FIXME: Support multiple stfd.
srs_netfd_t mmstfd;
std::vector<mmsghdr> mmhdrs;
// Hotspot msgs, we are working on it.
// @remark We will wait util all messages are ready.
std::vector<mmsghdr> hotspot;
// Cache msgs, for other coroutines to fill it.
std::vector<mmsghdr> cache;
int cache_pos;
// The max number of messages for sendmmsg. If 1, we use sendmsg to send.
int max_sendmmsg;
public:
SrsUdpMuxSender(SrsRtcServer* s);
virtual ~SrsUdpMuxSender();
public:
virtual srs_error_t initialize(srs_netfd_t fd);
private:
void free_mhdrs(std::vector<mmsghdr>& mhdrs);
public:
virtual srs_error_t fetch(mmsghdr** pphdr);
virtual srs_error_t sendmmsg(mmsghdr* hdr);
virtual srs_error_t cycle();
// interface ISrsReloadHandler
public:
virtual srs_error_t on_reload_rtc_server();
};
class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass
{
private:
SrsHourGlass* timer;
std::vector<SrsUdpMuxListener*> listeners;
std::vector<SrsUdpMuxSender*> senders;
private:
std::map<std::string, SrsRtcSession*> map_username_session; // key: username(local_ufrag + ":" + remote_ufrag)
std::map<std::string, SrsRtcSession*> map_id_session; // key: peerip(ip + ":" + port)
@ -240,27 +289,31 @@ public:
// TODO: FIXME: Support gracefully quit.
// TODO: FIXME: Support reload.
virtual srs_error_t listen_udp();
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* udp_mux_skt);
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* skt);
public:
virtual srs_error_t listen_api();
SrsRtcSession* create_rtc_session(const SrsRequest& req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip);
bool insert_into_id_sessions(const std::string& peer_id, SrsRtcSession* rtc_session);
void check_and_clean_timeout_session();
int nn_sessions() { return (int)map_username_session.size(); }
private:
srs_error_t on_stun(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_rtp_or_rtcp(SrsUdpMuxSocket* udp_mux_skt);
srs_error_t on_stun(SrsUdpMuxSocket* skt);
srs_error_t on_dtls(SrsUdpMuxSocket* skt);
srs_error_t on_rtp_or_rtcp(SrsUdpMuxSocket* skt);
private:
SrsRtcSession* find_rtc_session_by_username(const std::string& ufrag);
SrsRtcSession* find_rtc_session_by_peer_id(const std::string& peer_id);
// interface ISrsHourGlass
public:
virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick);
<<<<<<< HEAD
// Internal only.
public:
void send_and_free_messages(srs_netfd_t stfd, sockaddr_in* addr, socklen_t addrlen, char* buf, int length);
void free_messages(std::vector<mmsghdr>& hdrs);
virtual srs_error_t cycle();
=======
>>>>>>> upstream/feature/rtc
};
// The RTC server adapter.

View file

@ -78,6 +78,14 @@ srs_error_t parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_par
if (kv[0] == "profile-level-id") {
h264_param.profile_level_id = kv[1];
} else if (kv[0] == "packetization-mode") {
// 6.3. Non-Interleaved Mode
// This mode is in use when the value of the OPTIONAL packetization-mode
// media type parameter is equal to 1. This mode SHOULD be supported.
// It is primarily intended for low-delay applications. Only single NAL
// unit packets, STAP-As, and FU-As MAY be used in this mode. STAP-Bs,
// MTAPs, and FU-Bs MUST NOT be used. The transmission order of NAL
// units MUST comply with the NAL unit decoding order.
// @see https://tools.ietf.org/html/rfc6184#section-6.3
h264_param.packetization_mode = kv[1];
} else if (kv[0] == "level-asymmetry-allowed") {
h264_param.level_asymmerty_allow = kv[1];

View file

@ -1143,7 +1143,8 @@ srs_error_t SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_se
// TODO: FIXME: Refactor to move to rtp?
// Save the RTP packets for find_rtp_packet() to rtx or restore it.
source->rtp_queue->push(msg->rtp_packets);
// TODO: FIXME: Remove dead code.
//source->rtp_queue->push(msg->rtp_packets);
#endif
if ((err = hls->on_video(msg, format)) != srs_success) {
@ -2718,4 +2719,9 @@ SrsRtpSharedPacket* SrsSource::find_rtp_packet(const uint16_t& seq)
{
return rtp_queue->find(seq);
}
SrsMetaCache* SrsSource::cached_meta()
{
return meta;
}
#endif

View file

@ -327,6 +327,7 @@ public:
#ifdef SRS_AUTO_RTC
// To find the RTP packet for RTX or restore.
// TODO: FIXME: Should queue RTP packets in connection level.
class SrsRtpPacketQueue
{
private:
@ -634,6 +635,8 @@ public:
#ifdef SRS_AUTO_RTC
// Find rtp packet by sequence
SrsRtpSharedPacket* find_rtp_packet(const uint16_t& seq);
// Get the cached meta, as such the sps/pps.
SrsMetaCache* cached_meta();
#endif
};

View file

@ -29,6 +29,14 @@ using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_kernel_utility.hpp>
ISrsEncoder::ISrsEncoder()
{
}
ISrsEncoder::~ISrsEncoder()
{
}
ISrsCodec::ISrsCodec()
{
}

View file

@ -31,6 +31,24 @@
class SrsBuffer;
// Encoder.
class ISrsEncoder
{
public:
ISrsEncoder();
virtual ~ISrsEncoder();
public:
/**
* get the number of bytes to code to.
*/
// TODO: FIXME: change to uint64_t.
virtual int nb_bytes() = 0;
/**
* encode object to bytes in SrsBuffer.
*/
virtual srs_error_t encode(SrsBuffer* buf) = 0;
};
/**
* the srs codec, to code and decode object with bytes:
* code: to encode/serialize object to bytes in buffer,
@ -56,21 +74,11 @@ class SrsBuffer;
* @remark protocol or amf0 or json should implements this interface.
*/
// TODO: FIXME: protocol, amf0, json should implements it.
class ISrsCodec
class ISrsCodec : public ISrsEncoder
{
public:
ISrsCodec();
virtual ~ISrsCodec();
public:
/**
* get the number of bytes to code to.
*/
// TODO: FIXME: change to uint64_t.
virtual int nb_bytes() = 0;
/**
* encode object to bytes in SrsBuffer.
*/
virtual srs_error_t encode(SrsBuffer* buf) = 0;
public:
/**
* decode object from bytes in SrsBuffer.

View file

@ -32,6 +32,7 @@ using namespace std;
#include <srs_kernel_buffer.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_rtp.hpp>
string srs_video_codec_id2str(SrsVideoCodecId codec)
{
@ -364,12 +365,50 @@ SrsSample::SrsSample()
{
size = 0;
bytes = NULL;
bframe = false;
}
SrsSample::~SrsSample()
{
}
srs_error_t SrsSample::parse_bframe()
{
srs_error_t err = srs_success;
uint8_t header = bytes[0];
SrsAvcNaluType nal_type = (SrsAvcNaluType)(header & kNalTypeMask);
if (nal_type != SrsAvcNaluTypeNonIDR && nal_type != SrsAvcNaluTypeDataPartitionA && nal_type != SrsAvcNaluTypeIDR) {
return err;
}
SrsBuffer* stream = new SrsBuffer(bytes, size);
SrsAutoFree(SrsBuffer, stream);
// Skip nalu header.
stream->skip(1);
SrsBitBuffer bitstream(stream);
int32_t first_mb_in_slice = 0;
if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) {
return srs_error_wrap(err, "nalu read uev");
}
int32_t slice_type_v = 0;
if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type_v)) != srs_success) {
return srs_error_wrap(err, "nalu read uev");
}
SrsAvcSliceType slice_type = (SrsAvcSliceType)slice_type_v;
if (slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1) {
bframe = true;
srs_verbose("nal_type=%d, slice type=%d", nal_type, slice_type);
}
return err;
}
SrsCodecConfig::SrsCodecConfig()
{
}
@ -458,6 +497,7 @@ srs_error_t SrsFrame::add_sample(char* bytes, int size)
SrsSample* sample = &samples[nb_samples++];
sample->bytes = bytes;
sample->size = size;
sample->bframe = false;
return err;
}
@ -488,6 +528,13 @@ SrsVideoFrame::~SrsVideoFrame()
{
}
srs_error_t SrsVideoFrame::initialize(SrsCodecConfig* c)
{
first_nalu_type = SrsAvcNaluTypeForbidden;
has_idr = has_sps_pps = has_aud = false;
return SrsFrame::initialize(c);
}
srs_error_t SrsVideoFrame::add_sample(char* bytes, int size)
{
srs_error_t err = srs_success;

View file

@ -532,11 +532,16 @@ class SrsSample
public:
// The size of unit.
int size;
// The ptr of unit, user must manage it.
// The ptr of unit, user must free it.
char* bytes;
// Whether is B frame.
bool bframe;
public:
SrsSample();
virtual ~SrsSample();
~SrsSample();
public:
// If we need to know whether sample is bframe, we have to parse the NALU payload.
srs_error_t parse_bframe();
};
/**
@ -703,6 +708,8 @@ public:
SrsVideoFrame();
virtual ~SrsVideoFrame();
public:
// Initialize the frame, to parse sampels.
virtual srs_error_t initialize(SrsCodecConfig* c);
// Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data.
virtual srs_error_t add_sample(char* bytes, int size);
public:

View file

@ -194,8 +194,11 @@ srs_error_t SrsCommonMessage::create(SrsMessageHeader* pheader, char* body, int
return srs_success;
}
SrsSharedMessageHeader::SrsSharedMessageHeader() : payload_length(0), message_type(0), perfer_cid(0)
SrsSharedMessageHeader::SrsSharedMessageHeader()
{
payload_length = 0;
message_type = 0;
perfer_cid = 0;
}
SrsSharedMessageHeader::~SrsSharedMessageHeader()
@ -207,6 +210,15 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload()
payload = NULL;
size = 0;
shared_count = 0;
#ifdef SRS_AUTO_RTC
samples = NULL;
nn_samples = 0;
has_idr = false;
extra_payloads = NULL;
nn_extra_payloads = 0;
#endif
}
SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload()
@ -215,6 +227,16 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload()
srs_memory_unwatch(payload);
#endif
srs_freepa(payload);
srs_freepa(samples);
#ifdef SRS_AUTO_RTC
for (int i = 0; i < nn_extra_payloads; i++) {
SrsSample* p = extra_payloads + i;
srs_freep(p->bytes);
}
srs_freepa(extra_payloads);
nn_extra_payloads = 0;
#endif
}
SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL)
@ -231,12 +253,6 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage()
ptr->shared_count--;
}
}
#ifdef SRS_AUTO_RTC
for (int i = 0; i < (int)rtp_packets.size(); ++i) {
srs_freep(rtp_packets[i]);
}
#endif
}
srs_error_t SrsSharedPtrMessage::create(SrsCommonMessage* msg)
@ -355,19 +371,30 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy()
copy->payload = ptr->payload;
copy->size = ptr->size;
#ifdef SRS_AUTO_RTC
for (int i = 0; i < (int)rtp_packets.size(); ++i) {
copy->rtp_packets.push_back(rtp_packets[i]->copy());
}
#endif
return copy;
}
#ifdef SRS_AUTO_RTC
void SrsSharedPtrMessage::set_rtp_packets(const std::vector<SrsRtpSharedPacket*>& pkts)
void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payloads)
{
rtp_packets = pkts;
srs_assert(nn_payloads);
srs_assert(!ptr->extra_payloads);
ptr->nn_extra_payloads = nn_payloads;
ptr->extra_payloads = new SrsSample[nn_payloads];
memcpy(ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample));
}
void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples)
{
srs_assert(nn_samples);
srs_assert(!ptr->samples);
ptr->nn_samples = nn_samples;
ptr->samples = new SrsSample[nn_samples];
memcpy(ptr->samples, samples, nn_samples * sizeof(SrsSample));
}
#endif

View file

@ -40,6 +40,7 @@ class ISrsReader;
class SrsFileReader;
class SrsPacket;
class SrsRtpSharedPacket;
class SrsSample;
#define SRS_FLV_TAG_HEADER_SIZE 11
#define SRS_FLV_PREVIOUS_TAG_SIZE 4
@ -288,10 +289,6 @@ public:
// video/audio packet use raw bytes, no video/audio packet.
char* payload;
#ifdef SRS_AUTO_RTC
std::vector<SrsRtpSharedPacket*> rtp_packets;
#endif
private:
class SrsSharedPtrPayload
{
@ -305,6 +302,19 @@ private:
int size;
// The reference count
int shared_count;
#ifdef SRS_AUTO_RTC
public:
// For RTC video, we need to know the NALU structures,
// because the RTP STAP-A or FU-A based on NALU.
SrsSample* samples;
int nn_samples;
// For RTC video, whether NALUs has IDR.
bool has_idr;
// For RTC audio, we may need to transcode AAC to opus,
// so there must be an extra payloads, which is transformed from payload.
SrsSample* extra_payloads;
int nn_extra_payloads;
#endif
public:
SrsSharedPtrPayload();
virtual ~SrsSharedPtrPayload();
@ -348,7 +358,18 @@ public:
virtual SrsSharedPtrMessage* copy();
public:
#ifdef SRS_AUTO_RTC
virtual void set_rtp_packets(const std::vector<SrsRtpSharedPacket*>& pkts);
// Set extra samples, for example, when we transcode an AAC audio packet to OPUS,
// we may get more than one OPUS packets, we set these OPUS packets in extra payloads.
void set_extra_payloads(SrsSample* payloads, int nn_payloads);
int nn_extra_payloads() { return ptr->nn_extra_payloads; }
SrsSample* extra_payloads() { return ptr->extra_payloads; }
// Whether samples has idr.
bool has_idr() { return ptr->has_idr; }
void set_has_idr(bool v) { ptr->has_idr = v; }
// Set samples, each sample points to the address of payload.
void set_samples(SrsSample* samples, int nn_samples);
int nn_samples() { return ptr->nn_samples; }
SrsSample* samples() { return ptr->samples; }
#endif
};

View file

@ -32,6 +32,15 @@ using namespace std;
#include <srs_kernel_buffer.hpp>
#include <srs_kernel_utility.hpp>
// @see: https://tools.ietf.org/html/rfc6184#section-5.2
const uint8_t kStapA = 24;
// @see: https://tools.ietf.org/html/rfc6184#section-5.2
const uint8_t kFuA = 28;
// @see: https://tools.ietf.org/html/rfc6184#section-5.8
const uint8_t kStart = 0x80; // Fu-header start bit
const uint8_t kEnd = 0x40; // Fu-header end bit
SrsRtpHeader::SrsRtpHeader()
{
@ -77,7 +86,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* stream)
{
srs_error_t err = srs_success;
// TODO:
// TODO: FIXME: Implements it.
return err;
}
@ -86,19 +95,21 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream)
{
srs_error_t err = srs_success;
uint8_t first = 0x80 | cc;
uint8_t v = 0x80 | cc;
if (padding) {
first |= 0x40;
v |= 0x40;
}
if (extension) {
first |= 0x10;
v |= 0x10;
}
stream->write_1bytes(first);
uint8_t second = payload_type;
stream->write_1bytes(v);
v = payload_type;
if (marker) {
payload_type |= kRtpMarker;
v |= kRtpMarker;
}
stream->write_1bytes(second);
stream->write_1bytes(v);
stream->write_2bytes(sequence);
stream->write_4bytes(timestamp);
stream->write_4bytes(ssrc);
@ -143,6 +154,200 @@ void SrsRtpHeader::set_ssrc(uint32_t ssrc)
this->ssrc = ssrc;
}
SrsRtpPacket2::SrsRtpPacket2()
{
payload = NULL;
padding = 0;
}
SrsRtpPacket2::~SrsRtpPacket2()
{
srs_freep(payload);
}
void SrsRtpPacket2::set_padding(int size)
{
rtp_header.set_padding(size > 0);
padding = size;
}
int SrsRtpPacket2::nb_bytes()
{
return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding;
}
srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf)
{
srs_error_t err = srs_success;
if ((err = rtp_header.encode(buf)) != srs_success) {
return srs_error_wrap(err, "rtp header");
}
if (payload && (err = payload->encode(buf)) != srs_success) {
return srs_error_wrap(err, "encode payload");
}
if (padding) {
if (!buf->require(padding)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", padding);
}
memset(buf->data(), padding, padding);
buf->skip(padding);
}
return err;
}
SrsRtpRawPayload::SrsRtpRawPayload()
{
payload = NULL;
nn_payload = 0;
}
SrsRtpRawPayload::~SrsRtpRawPayload()
{
}
int SrsRtpRawPayload::nb_bytes()
{
return nn_payload;
}
srs_error_t SrsRtpRawPayload::encode(SrsBuffer* buf)
{
if (nn_payload <= 0) {
return srs_success;
}
if (!buf->require(nn_payload)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", nn_payload);
}
buf->write_bytes(payload, nn_payload);
return srs_success;
}
SrsRtpSTAPPayload::SrsRtpSTAPPayload()
{
nri = (SrsAvcNaluType)0;
}
SrsRtpSTAPPayload::~SrsRtpSTAPPayload()
{
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
srs_freep(p);
}
nalus.clear();
}
int SrsRtpSTAPPayload::nb_bytes()
{
int size = 1;
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
size += 2 + p->size;
}
return size;
}
srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf)
{
if (!buf->require(1)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
// STAP header, RTP payload format for aggregation packets
// @see https://tools.ietf.org/html/rfc6184#section-5.7
uint8_t v = kStapA;
v |= (nri & (~kNalTypeMask));
buf->write_1bytes(v);
// NALUs.
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
if (!buf->require(2 + p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size);
}
buf->write_2bytes(p->size);
buf->write_bytes(p->bytes, p->size);
}
return srs_success;
}
SrsRtpFUAPayload::SrsRtpFUAPayload()
{
start = end = false;
nri = nalu_type = (SrsAvcNaluType)0;
}
SrsRtpFUAPayload::~SrsRtpFUAPayload()
{
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
srs_freep(p);
}
nalus.clear();
}
int SrsRtpFUAPayload::nb_bytes()
{
int size = 2;
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
size += p->size;
}
return size;
}
srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf)
{
if (!buf->require(2)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
uint8_t fu_indicate = kFuA;
fu_indicate |= (nri & (~kNalTypeMask));
buf->write_1bytes(fu_indicate);
// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
uint8_t fu_header = nalu_type;
if (start) {
fu_header |= kStart;
}
if (end) {
fu_header |= kEnd;
}
buf->write_1bytes(fu_header);
// FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8
vector<SrsSample*>::iterator it;
for (it = nalus.begin(); it != nalus.end(); ++it) {
SrsSample* p = *it;
if (!buf->require(p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size);
}
buf->write_bytes(p->bytes, p->size);
}
return srs_success;
}
SrsRtpSharedPacket::SrsRtpSharedPacketPayload::SrsRtpSharedPacketPayload()
{
payload = NULL;

View file

@ -26,11 +26,17 @@
#include <srs_core.hpp>
#include <srs_kernel_buffer.hpp>
#include <srs_kernel_codec.hpp>
#include <string>
const int kRtpHeaderFixedSize = 12;
const uint8_t kRtpMarker = 0x80;
// H.264 nalu header type mask.
const uint8_t kNalTypeMask = 0x1F;
class SrsBuffer;
class SrsRtpHeader
@ -68,6 +74,78 @@ public:
int64_t get_timestamp() const { return timestamp; }
void set_ssrc(uint32_t ssrc);
uint32_t get_ssrc() const { return ssrc; }
void set_padding(bool v) { padding = v; }
};
class SrsRtpPacket2
{
public:
SrsRtpHeader rtp_header;
ISrsEncoder* payload;
int padding;
public:
SrsRtpPacket2();
virtual ~SrsRtpPacket2();
public:
// Append size of bytes as padding.
virtual void set_padding(int size);
// interface ISrsEncoder
public:
virtual int nb_bytes();
virtual srs_error_t encode(SrsBuffer* buf);
};
class SrsRtpRawPayload : public ISrsEncoder
{
public:
// @remark We only refer to the memory, user must free it.
char* payload;
int nn_payload;
public:
SrsRtpRawPayload();
virtual ~SrsRtpRawPayload();
// interface ISrsEncoder
public:
virtual int nb_bytes();
virtual srs_error_t encode(SrsBuffer* buf);
};
class SrsRtpSTAPPayload : public ISrsEncoder
{
public:
// The NRI in NALU type.
SrsAvcNaluType nri;
// The NALU samples.
// @remark We only refer to the memory, user must free its bytes.
std::vector<SrsSample*> nalus;
public:
SrsRtpSTAPPayload();
virtual ~SrsRtpSTAPPayload();
// interface ISrsEncoder
public:
virtual int nb_bytes();
virtual srs_error_t encode(SrsBuffer* buf);
};
class SrsRtpFUAPayload : public ISrsEncoder
{
public:
// The NRI in NALU type.
SrsAvcNaluType nri;
// The FUA header.
bool start;
bool end;
SrsAvcNaluType nalu_type;
// The NALU samples.
// @remark We only refer to the memory, user must free its bytes.
std::vector<SrsSample*> nalus;
public:
SrsRtpFUAPayload();
virtual ~SrsRtpFUAPayload();
// interface ISrsEncoder
public:
virtual int nb_bytes();
virtual srs_error_t encode(SrsBuffer* buf);
};
class SrsRtpSharedPacket

View file

@ -209,7 +209,7 @@ srs_error_t do_main(int argc, char** argv)
int main(int argc, char** argv) {
srs_error_t err = do_main(argc, argv);
if (err != srs_success) {
srs_error("Failed, %s", srs_error_desc(err).c_str());
}

View file

@ -4539,6 +4539,11 @@ srs_error_t SrsOnMetaDataPacket::decode(SrsBuffer* stream)
return srs_error_wrap(err, "name");
}
}
// Allows empty body metadata.
if (stream->empty()) {
return err;
}
// the metadata maybe object or ecma array
SrsAmf0Any* any = NULL;

View file

@ -462,7 +462,7 @@ VOID TEST(SrsAVCTest, AACMuxSequenceHeader)
codec.sound_rate = SrsAudioSampleRate44100;
codec.sampling_frequency_index = 4;
HELPER_ASSERT_SUCCESS(h.mux_sequence_header(&codec, sh));
EXPECT_EQ(2, sh.length());
EXPECT_EQ(2, (int)sh.length());
EXPECT_EQ(0x0a, (uint8_t)sh.at(0));
EXPECT_EQ(0x08, (uint8_t)sh.at(1));
}
@ -475,7 +475,7 @@ VOID TEST(SrsAVCTest, AACMuxSequenceHeader)
codec.sound_rate = SrsAudioSampleRate22050;
codec.sampling_frequency_index = 4;
HELPER_ASSERT_SUCCESS(h.mux_sequence_header(&codec, sh));
EXPECT_EQ(2, sh.length());
EXPECT_EQ(2, (int)sh.length());
EXPECT_EQ(0x0a, (uint8_t)sh.at(0));
EXPECT_EQ(0x08, (uint8_t)sh.at(1));
}

View file

@ -2010,7 +2010,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost)
if (true) {
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF));
EXPECT_EQ(0, conf.get_hls_dispose(""));
EXPECT_EQ(0, (int)conf.get_hls_dispose(""));
EXPECT_EQ(10 * SRS_UTIME_SECONDS, conf.get_hls_fragment(""));
EXPECT_EQ(60 * SRS_UTIME_SECONDS, conf.get_hls_window(""));
@ -2033,7 +2033,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost)
if (true) {
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF));
EXPECT_EQ(30 * SRS_UTIME_SECONDS, conf.get_queue_length(""));
EXPECT_EQ(0, conf.get_send_min_interval(""));
EXPECT_EQ(0, (int)conf.get_send_min_interval(""));
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost v{play{queue_length 100;send_min_interval 10;}}"));
EXPECT_EQ(100 * SRS_UTIME_SECONDS, conf.get_queue_length("v"));
@ -2042,7 +2042,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost)
if (true) {
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF));
EXPECT_EQ(0, conf.get_vhost_http_remux_fast_cache(""));
EXPECT_EQ(0, (int)conf.get_vhost_http_remux_fast_cache(""));
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost v{http_remux{fast_cache 10;}}"));
EXPECT_EQ(10 * SRS_UTIME_SECONDS, conf.get_vhost_http_remux_fast_cache("v"));
@ -2768,19 +2768,19 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF));
EXPECT_EQ(0, conf.get_stream_casters().size());
EXPECT_EQ(0, (int)conf.get_stream_casters().size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
EXPECT_EQ(1, conf.get_stream_casters().size());
EXPECT_EQ(1, (int)conf.get_stream_casters().size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster; stream_caster;"));
EXPECT_EQ(2, conf.get_stream_casters().size());
EXPECT_EQ(2, (int)conf.get_stream_casters().size());
}
if (true) {
@ -2788,7 +2788,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_FALSE(conf.get_stream_caster_enabled(arr.at(0)));
}
@ -2798,7 +2798,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {enabled off;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_FALSE(conf.get_stream_caster_enabled(arr.at(0)));
}
@ -2808,7 +2808,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {enabled on;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_TRUE(conf.get_stream_caster_enabled(arr.at(0)));
}
@ -2818,7 +2818,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_TRUE(conf.get_stream_caster_output(arr.at(0)).empty());
}
@ -2828,7 +2828,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {output xxx;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("xxx", conf.get_stream_caster_output(arr.at(0)).c_str());
}
@ -2838,9 +2838,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(0, conf.get_stream_caster_listen(arr.at(0)));
EXPECT_EQ(0, (int)conf.get_stream_caster_listen(arr.at(0)));
}
if (true) {
@ -2848,7 +2848,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {listen 8080;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(8080, conf.get_stream_caster_listen(arr.at(0)));
}
@ -2858,9 +2858,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(0, conf.get_stream_caster_rtp_port_min(arr.at(0)));
EXPECT_EQ(0, (int)conf.get_stream_caster_rtp_port_min(arr.at(0)));
}
if (true) {
@ -2868,7 +2868,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {rtp_port_min 8080;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(8080, conf.get_stream_caster_rtp_port_min(arr.at(0)));
}
@ -2878,9 +2878,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(0, conf.get_stream_caster_rtp_port_max(arr.at(0)));
EXPECT_EQ(0, (int)conf.get_stream_caster_rtp_port_max(arr.at(0)));
}
if (true) {
@ -2888,7 +2888,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {rtp_port_max 8080;}"));
vector<SrsConfDirective*> arr = conf.get_stream_casters();
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(8080, conf.get_stream_caster_rtp_port_max(arr.at(0)));
}
@ -2912,14 +2912,14 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2)
EXPECT_TRUE(conf.get_debug_srs_upnode("ossrs.net"));
EXPECT_FALSE(conf.get_atc("ossrs.net"));
EXPECT_FALSE(conf.get_atc_auto("ossrs.net"));
EXPECT_EQ(1, conf.get_time_jitter("ossrs.net"));
EXPECT_EQ(1, (int)conf.get_time_jitter("ossrs.net"));
EXPECT_FALSE(conf.get_mix_correct("ossrs.net"));
EXPECT_EQ(30 * SRS_UTIME_SECONDS, conf.get_queue_length("ossrs.net"));
EXPECT_FALSE(conf.get_refer_enabled("ossrs.net"));
EXPECT_TRUE(conf.get_refer_all("ossrs.net") == NULL);
EXPECT_TRUE(conf.get_refer_play("ossrs.net") == NULL);
EXPECT_TRUE(conf.get_refer_publish("ossrs.net") == NULL);
EXPECT_EQ(0, conf.get_in_ack_size("ossrs.net"));
EXPECT_EQ(0, (int)conf.get_in_ack_size("ossrs.net"));
EXPECT_EQ(2500000, conf.get_out_ack_size("ossrs.net"));
EXPECT_EQ(60000, conf.get_chunk_size("ossrs.net"));
EXPECT_TRUE(conf.get_parse_sps("ossrs.net"));
@ -2928,7 +2928,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2)
EXPECT_EQ(350 * SRS_UTIME_MILLISECONDS, conf.get_mw_sleep("ossrs.net"));
EXPECT_FALSE(conf.get_realtime_enabled("ossrs.net"));
EXPECT_FALSE(conf.get_tcp_nodelay("ossrs.net"));
EXPECT_EQ(0, conf.get_send_min_interval("ossrs.net"));
EXPECT_EQ(0, (int)conf.get_send_min_interval("ossrs.net"));
EXPECT_FALSE(conf.get_reduce_sequence_header("ossrs.net"));
EXPECT_EQ(20000000, conf.get_publish_1stpkt_timeout("ossrs.net"));
EXPECT_EQ(5000000, conf.get_publish_normal_timeout("ossrs.net"));
@ -3065,7 +3065,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2)
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{play{time_jitter zero;}}"));
EXPECT_EQ(2, conf.get_time_jitter("ossrs.net"));
EXPECT_EQ(2, (int)conf.get_time_jitter("ossrs.net"));
}
if (true) {
@ -3132,7 +3132,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig3)
EXPECT_FALSE(conf.get_vhost_edge_token_traverse("ossrs.net"));
EXPECT_STREQ("[vhost]", conf.get_vhost_edge_transform_vhost("ossrs.net").c_str());
EXPECT_FALSE(conf.get_vhost_origin_cluster("ossrs.net"));
EXPECT_EQ(0, conf.get_vhost_coworkers("ossrs.net").size());
EXPECT_EQ(0, (int)conf.get_vhost_coworkers("ossrs.net").size());
EXPECT_FALSE(conf.get_security_enabled("ossrs.net"));
EXPECT_TRUE(conf.get_security_rules("ossrs.net") == NULL);
}
@ -3152,7 +3152,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig3)
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{cluster{coworkers xxx;}}"));
EXPECT_EQ(1, conf.get_vhost_coworkers("ossrs.net").size());
EXPECT_EQ(1, (int)conf.get_vhost_coworkers("ossrs.net").size());
}
if (true) {
@ -3286,14 +3286,14 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
EXPECT_TRUE(conf.get_transcode("ossrs.net", "") == NULL);
EXPECT_FALSE(conf.get_transcode_enabled(conf.get_transcode("ossrs.net", "")));
EXPECT_TRUE(conf.get_transcode_ffmpeg(conf.get_transcode("ossrs.net", "")).empty());
EXPECT_EQ(0, conf.get_transcode_engines(conf.get_transcode("ossrs.net", "")).size());
EXPECT_EQ(0, (int)conf.get_transcode_engines(conf.get_transcode("ossrs.net", "")).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{output xxx;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("xxx", conf.get_engine_output(arr.at(0)).c_str());
}
@ -3301,7 +3301,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{oformat flv;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("flv", conf.get_engine_oformat(arr.at(0)).c_str());
}
@ -3309,15 +3309,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{aparams {i;}}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
EXPECT_EQ(1, conf.get_engine_aparams(arr.at(0)).size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1, (int)conf.get_engine_aparams(arr.at(0)).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{achannels 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_achannels(arr.at(0)));
}
@ -3325,7 +3325,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{asample_rate 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_asample_rate(arr.at(0)));
}
@ -3333,7 +3333,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{abitrate 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_abitrate(arr.at(0)));
}
@ -3341,7 +3341,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{acodec aac;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("aac", conf.get_engine_acodec(arr.at(0)).c_str());
}
@ -3349,15 +3349,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vparams {t;}}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
EXPECT_EQ(1, conf.get_engine_vparams(arr.at(0)).size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1, (int)conf.get_engine_vparams(arr.at(0)).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vpreset main;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("main", conf.get_engine_vpreset(arr.at(0)).c_str());
}
@ -3365,7 +3365,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vprofile main;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("main", conf.get_engine_vprofile(arr.at(0)).c_str());
}
@ -3373,7 +3373,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vthreads 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_vthreads(arr.at(0)));
}
@ -3381,7 +3381,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vheight 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_vheight(arr.at(0)));
}
@ -3389,7 +3389,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vwidth 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_vwidth(arr.at(0)));
}
@ -3397,7 +3397,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfps 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_vfps(arr.at(0)));
}
@ -3405,7 +3405,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vbitrate 1000;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1000, conf.get_engine_vbitrate(arr.at(0)));
}
@ -3413,7 +3413,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vcodec x264;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("x264", conf.get_engine_vcodec(arr.at(0)).c_str());
}
@ -3421,23 +3421,23 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfilter {i;}}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
EXPECT_EQ(1, conf.get_engine_vfilter(arr.at(0)).size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1, (int)conf.get_engine_vfilter(arr.at(0)).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfilter {i logo.png;}}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
EXPECT_EQ(2, conf.get_engine_vfilter(arr.at(0)).size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(2, (int)conf.get_engine_vfilter(arr.at(0)).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{iformat mp4;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_STREQ("mp4", conf.get_engine_iformat(arr.at(0)).c_str());
}
@ -3445,15 +3445,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{perfile {re;}}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
EXPECT_EQ(1, conf.get_engine_perfile(arr.at(0)).size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_EQ(1, (int)conf.get_engine_perfile(arr.at(0)).size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{enabled on;}}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
EXPECT_TRUE(conf.get_engine_enabled(arr.at(0)));
}
@ -3461,7 +3461,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4)
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine;}}"));
vector<SrsConfDirective*> arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx"));
ASSERT_EQ(1, arr.size());
ASSERT_EQ(1, (int)arr.size());
}
if (true) {
@ -3492,13 +3492,13 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5)
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{exec{enabled on;publish xxx;}}"));
EXPECT_TRUE(conf.get_exec("ossrs.net") != NULL);
EXPECT_TRUE(conf.get_exec_enabled("ossrs.net"));
EXPECT_EQ(1, conf.get_exec_publishs("ossrs.net").size());
EXPECT_EQ(1, (int)conf.get_exec_publishs("ossrs.net").size());
}
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{ingest xxx{enabled on;ffmpeg xxx2;input{type xxx3;url xxx4;}}}"));
EXPECT_EQ(1, conf.get_ingesters("ossrs.net").size());
EXPECT_EQ(1, (int)conf.get_ingesters("ossrs.net").size());
ASSERT_TRUE(conf.get_ingest_by_id("ossrs.net", "xxx") != NULL);
EXPECT_TRUE(conf.get_ingest_enabled(conf.get_ingest_by_id("ossrs.net", "xxx")));
EXPECT_STREQ("xxx2", conf.get_ingest_ffmpeg(conf.get_ingest_by_id("ossrs.net", "xxx")).c_str());
@ -3584,7 +3584,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5)
EXPECT_STREQ("xxx2", conf.get_dvr_plan("ossrs.net").c_str());
EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dvr_duration("ossrs.net"));
EXPECT_TRUE(conf.get_dvr_wait_keyframe("ossrs.net"));
EXPECT_EQ(1, conf.get_dvr_time_jitter("ossrs.net"));
EXPECT_EQ(1, (int)conf.get_dvr_time_jitter("ossrs.net"));
}
if (true) {
@ -3637,7 +3637,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5)
if (true) {
MockSrsConfig conf;
HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stats{network 0;disk xxx;}"));
EXPECT_EQ(0, conf.get_stats_network());
EXPECT_EQ(0, (int)conf.get_stats_network());
EXPECT_TRUE(conf.get_stats_disk_device() != NULL);
}
}

View file

@ -4869,20 +4869,20 @@ VOID TEST(KernelMP4Test, CoverMP4CodecSingleFrame)
// Sequence header.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
// Frame group #0
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
}
@ -4984,20 +4984,20 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleVideos)
// Sequence header.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
// Frames order by dts asc.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(40, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(40, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
}
}
@ -5082,24 +5082,24 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleCTTs)
// Sequence header.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
// Frames order by dts asc.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(40, (int)dts); EXPECT_EQ(80, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(40, (int)dts); EXPECT_EQ(80, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(80, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(80, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
}
}
@ -5194,28 +5194,28 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleAVs)
// Sequence header.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
// Frames order by dts asc.
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(20, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(20, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
EXPECT_EQ(40, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
EXPECT_EQ(40, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct);
srs_freepa(sample);
}
}
@ -5338,3 +5338,16 @@ VOID TEST(KernelMP4Test, CoverMP4M2tsSegmentEncoder)
HELPER_EXPECT_SUCCESS(enc.flush(dts));
}
VOID TEST(KernelUtilityTest, CoverStringAssign)
{
string sps = "SRS";
ASSERT_STREQ("SRS", sps.c_str());
sps.assign("Hello", 5);
ASSERT_STREQ("Hello", sps.c_str());
sps.assign("World", 0);
ASSERT_EQ(0, (int)sps.length());
ASSERT_STREQ("", sps.c_str());
}

View file

@ -5855,7 +5855,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
HELPER_EXPECT_SUCCESS(parser.parse("HelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld"));
EXPECT_EQ(80, (int)parser.parsed);
EXPECT_EQ(0, (int)parser.parser->nread);
EXPECT_EQ(0, parser.parser->content_length);
EXPECT_EQ(0, (int)parser.parser->content_length);
}
if (true) {
@ -5864,7 +5864,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHel"));
EXPECT_EQ(73, (int)parser.parsed);
EXPECT_EQ(0, (int)parser.parser->nread);
EXPECT_EQ(2, parser.parser->content_length);
EXPECT_EQ(2, (int)parser.parser->content_length);
}
if (true) {
@ -5881,7 +5881,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 34, nparsed = 34, nread = 34
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHo"));
EXPECT_EQ(34, (int)parser.parsed);
EXPECT_EQ(34, parser.parser->nread);
EXPECT_EQ(34, (int)parser.parser->nread);
// size = 41, nparsed = 41, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("st: ossrs.net\r\nContent-Length: 5\r\n\r\nHello"));
@ -5894,7 +5894,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 41, nparsed = 41, nread = 41
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: oss"));
EXPECT_EQ(41, (int)parser.parsed);
EXPECT_EQ(41, parser.parser->nread);
EXPECT_EQ(41, (int)parser.parser->nread);
// size = 34, nparsed = 34, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("rs.net\r\nContent-Length: 5\r\n\r\nHello"));
@ -5907,7 +5907,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 48, nparsed = 48, nread = 48
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r"));
EXPECT_EQ(48, (int)parser.parsed);
EXPECT_EQ(48, parser.parser->nread);
EXPECT_EQ(48, (int)parser.parser->nread);
// size = 27, nparsed = 27, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello"));
@ -5920,7 +5920,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 68, nparsed = 68, nread = 68
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n"));
EXPECT_EQ(68, (int)parser.parsed);
EXPECT_EQ(68, parser.parser->nread);
EXPECT_EQ(68, (int)parser.parser->nread);
// size = 7, nparsed = 7, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello"));
@ -5933,7 +5933,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 69, nparsed = 69, nread = 69
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r"));
EXPECT_EQ(69, (int)parser.parsed);
EXPECT_EQ(69, parser.parser->nread);
EXPECT_EQ(69, (int)parser.parser->nread);
// size = 6, nparsed = 6, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\nHello"));
@ -5954,12 +5954,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// nparsed = 2, size = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, (int)parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
EXPECT_EQ(2, (int)parser.parser->nread);
// size = 0, nparsed = 1, nread=2
HELPER_EXPECT_FAILED(parser.parse(""));
EXPECT_EQ(1, (int)parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
EXPECT_EQ(2, (int)parser.parser->nread);
}
if (true) {
@ -5967,12 +5967,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 2, nparsed = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, (int)parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
EXPECT_EQ(2, (int)parser.parser->nread);
// size = 1, nparsed = 0, nread = 3
HELPER_EXPECT_FAILED(parser.parse("X"));
EXPECT_EQ(0, (int)parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
EXPECT_EQ(3, (int)parser.parser->nread);
}
if (true) {
@ -5980,12 +5980,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 2, nparsed = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, (int)parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
EXPECT_EQ(2, (int)parser.parser->nread);
// size = 1, nparsed = 1, nread = 3
HELPER_EXPECT_SUCCESS(parser.parse("T"));
EXPECT_EQ(1, (int)parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
EXPECT_EQ(3, (int)parser.parser->nread);
}
if (true) {
@ -5993,7 +5993,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
// size = 3, nparsed = 3, nread = 3
HELPER_EXPECT_SUCCESS(parser.parse("GET"));
EXPECT_EQ(3, (int)parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
EXPECT_EQ(3, (int)parser.parser->nread);
}
}