mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 20:01:56 +00:00
merge
This commit is contained in:
commit
8687c50dc4
34 changed files with 1582 additions and 594 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
12
trunk/configure
vendored
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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.
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,14 @@ using namespace std;
|
|||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
ISrsEncoder::ISrsEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsEncoder::~ISrsEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsCodec::ISrsCodec()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue