mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Merge branch 'develop' into min
This commit is contained in:
commit
fe09f3af87
15 changed files with 308 additions and 38 deletions
|
@ -54,3 +54,5 @@ CONTRIBUTORS ordered by first contribution.
|
|||
* Michael.Ma<wnpllr@gmail.com>
|
||||
* lam2003<linmin3@yy.com>
|
||||
* runner365<shi.weibd@hotmail.com>
|
||||
* XiaofengWang<wasphin@gmail.com>
|
||||
* XiaLixin<xialx@yuntongxun.com>
|
|
@ -153,6 +153,9 @@ For previous versions, please read:
|
|||
|
||||
## V4 changes
|
||||
|
||||
* v4.0, 2020-03-07, For [#1612][bug #1612], fix crash bug for RTSP. 4.0.12
|
||||
* v4.0, 2020-03-07, For [#1631][bug #1631], support sei_filter for SRT. 4.0.11
|
||||
* v4.0, 2020-03-01, For [#1621][bug #1621], support mix_correct for aggregate aac for SRT. 4.0.10
|
||||
* v4.0, 2020-02-25, For [#1615][bug #1615], support default app(live) for vmix SRT. 4.0.9
|
||||
* v4.0, 2020-02-21, For [#1598][bug #1598], support SLB health checking by TCP. 4.0.8
|
||||
* v4.0, 2020-02-19, For [#1579][bug #1579], support rolling update of k8s. 4.0.7
|
||||
|
@ -1687,6 +1690,11 @@ Winlin
|
|||
[bug #1579]: https://github.com/ossrs/srs/issues/1579
|
||||
[bug #1598]: https://github.com/ossrs/srs/issues/1598
|
||||
[bug #1615]: https://github.com/ossrs/srs/issues/1615
|
||||
[bug #1621]: https://github.com/ossrs/srs/issues/1621
|
||||
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
||||
|
||||
[bug #1631]: https://github.com/ossrs/srs/issues/1631
|
||||
[bug #1612]: https://github.com/ossrs/srs/issues/1612
|
||||
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
||||
|
||||
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
||||
|
|
1
trunk/configure
vendored
1
trunk/configure
vendored
|
@ -730,7 +730,6 @@ fi
|
|||
# next step
|
||||
#####################################################################################
|
||||
if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
|
||||
ip=`ifconfig|grep "inet addr"| grep -v "127.0.0.1"|awk '{print $2}'|awk -F ':' 'NR==1 {print $2}'`
|
||||
echo ""
|
||||
echo "You can run 3rdparty applications:"
|
||||
if [ $SRS_HTTP_CALLBACK = YES ]; then
|
||||
|
|
|
@ -3530,7 +3530,7 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
&& n != "mss" && n != "latency" && n != "recvlatency"
|
||||
&& n != "peerlatency" && n != "tlpkdrop" && n != "connect_timeout"
|
||||
&& n != "sendbuf" && n != "recvbuf" && n != "payloadsize"
|
||||
&& n != "default_app") {
|
||||
&& n != "default_app" && n != "mix_correct" && n != "sei_filter") {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal srt_stream.%s", n.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -6754,6 +6754,20 @@ unsigned short SrsConfig::get_srt_listen_port()
|
|||
return (unsigned short)atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
bool SrsConfig::get_srt_mix_correct() {
|
||||
static bool DEFAULT = true;
|
||||
SrsConfDirective* conf = root->get("srt_server");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("mix_correct");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||
}
|
||||
|
||||
int SrsConfig::get_srto_maxbw() {
|
||||
static int64_t DEFAULT = -1;
|
||||
SrsConfDirective* conf = root->get("srt_server");
|
||||
|
@ -6824,6 +6838,20 @@ int SrsConfig::get_srto_peer_latency() {
|
|||
return atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
bool SrsConfig::get_srt_sei_filter() {
|
||||
static bool DEFAULT = true;
|
||||
SrsConfDirective* conf = root->get("srt_server");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("sei_filter");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||
}
|
||||
|
||||
bool SrsConfig::get_srto_tlpkdrop() {
|
||||
static bool DEFAULT = true;
|
||||
SrsConfDirective* conf = root->get("srt_server");
|
||||
|
|
|
@ -613,6 +613,8 @@ public:
|
|||
virtual int get_srto_recv_latency();
|
||||
// Get the srt SRTO_PEERLATENCY, peer latency, default is 0..
|
||||
virtual int get_srto_peer_latency();
|
||||
// Get the srt h264 sei filter, default is on, it will drop h264 sei packet.
|
||||
virtual bool get_srt_sei_filter();
|
||||
// Get the srt SRTO_TLPKDROP, Too-late Packet Drop, default is true.
|
||||
virtual bool get_srto_tlpkdrop();
|
||||
// Get the srt SRTO_CONNTIMEO, connection timeout, default is 3000ms.
|
||||
|
@ -625,6 +627,8 @@ public:
|
|||
virtual int get_srto_payloadsize();
|
||||
// Get the default app.
|
||||
virtual std::string get_default_app_name();
|
||||
// Get the mix_correct
|
||||
virtual bool get_srt_mix_correct();
|
||||
|
||||
// http_hooks section
|
||||
private:
|
||||
|
|
|
@ -240,6 +240,12 @@ srs_error_t SrsRtspConn::serve()
|
|||
return err;
|
||||
}
|
||||
|
||||
std::string SrsRtspConn::remote_ip()
|
||||
{
|
||||
// TODO: FIXME: Implement it.
|
||||
return "";
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::do_cycle()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
@ -684,6 +690,7 @@ SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
|
|||
output = _srs_config->get_stream_caster_output(c);
|
||||
local_port_min = _srs_config->get_stream_caster_rtp_port_min(c);
|
||||
local_port_max = _srs_config->get_stream_caster_rtp_port_max(c);
|
||||
manager = new SrsCoroutineManager();
|
||||
}
|
||||
|
||||
SrsRtspCaster::~SrsRtspCaster()
|
||||
|
@ -691,10 +698,21 @@ SrsRtspCaster::~SrsRtspCaster()
|
|||
std::vector<SrsRtspConn*>::iterator it;
|
||||
for (it = clients.begin(); it != clients.end(); ++it) {
|
||||
SrsRtspConn* conn = *it;
|
||||
srs_freep(conn);
|
||||
manager->remove(conn);
|
||||
}
|
||||
clients.clear();
|
||||
used_ports.clear();
|
||||
|
||||
srs_freep(manager);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::initialize()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
if ((err = manager->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start manager");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::alloc_port(int* pport)
|
||||
|
@ -747,6 +765,6 @@ void SrsRtspCaster::remove(SrsRtspConn* conn)
|
|||
}
|
||||
srs_info("rtsp: remove connection from caster.");
|
||||
|
||||
srs_freep(conn);
|
||||
manager->remove(conn);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
};
|
||||
|
||||
// The rtsp connection serve the fd.
|
||||
class SrsRtspConn : public ISrsCoroutineHandler
|
||||
class SrsRtspConn : public ISrsCoroutineHandler, public ISrsConnection
|
||||
{
|
||||
private:
|
||||
std::string output_template;
|
||||
|
@ -143,6 +143,7 @@ public:
|
|||
virtual ~SrsRtspConn();
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
virtual std::string remote_ip();
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
// internal methods
|
||||
|
@ -179,6 +180,7 @@ private:
|
|||
std::map<int, bool> used_ports;
|
||||
private:
|
||||
std::vector<SrsRtspConn*> clients;
|
||||
SrsCoroutineManager* manager;
|
||||
public:
|
||||
SrsRtspCaster(SrsConfDirective* c);
|
||||
virtual ~SrsRtspCaster();
|
||||
|
@ -188,6 +190,7 @@ public:
|
|||
virtual srs_error_t alloc_port(int* pport);
|
||||
// Free the alloced rtp port.
|
||||
virtual void free_port(int lpmin, int lpmax);
|
||||
virtual srs_error_t initialize();
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
|
|
|
@ -179,6 +179,9 @@ SrsRtspListener::SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirec
|
|||
srs_assert(type == SrsListenerRtsp);
|
||||
if (type == SrsListenerRtsp) {
|
||||
caster = new SrsRtspCaster(c);
|
||||
|
||||
// TODO: FIXME: Must check error.
|
||||
caster->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class ISrsUdpHandler;
|
|||
class SrsUdpListener;
|
||||
class SrsTcpListener;
|
||||
class SrsAppCasterFlv;
|
||||
class SrsRtspCaster;
|
||||
class SrsCoroutineManager;
|
||||
|
||||
// The listener type for server to identify the connection,
|
||||
|
@ -107,7 +108,7 @@ class SrsRtspListener : virtual public SrsListener, virtual public ISrsTcpHandle
|
|||
{
|
||||
private:
|
||||
SrsTcpListener* listener;
|
||||
ISrsTcpHandler* caster;
|
||||
SrsRtspCaster* caster;
|
||||
public:
|
||||
SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
|
||||
virtual ~SrsRtspListener();
|
||||
|
|
|
@ -24,6 +24,6 @@
|
|||
#ifndef SRS_CORE_VERSION4_HPP
|
||||
#define SRS_CORE_VERSION4_HPP
|
||||
|
||||
#define SRS_VERSION4_REVISION 9
|
||||
#define SRS_VERSION4_REVISION 12
|
||||
|
||||
#endif
|
||||
|
|
|
@ -145,6 +145,8 @@ void srt_handle::add_newconn(SRT_CONN_PTR conn_ptr, int events) {
|
|||
srs_trace("srto SRTO_RCVBUF=%d", val_i);
|
||||
srt_getsockopt(conn_ptr->get_conn(), 0, SRTO_MAXBW, &val_i, &opt_len);
|
||||
srs_trace("srto SRTO_MAXBW=%d", val_i);
|
||||
srs_trace("srt mix_correct is %s.", _srs_config->get_srt_mix_correct() ? "enable" : "disable");
|
||||
srs_trace("srt h264 sei filter is %s.", _srs_config->get_srt_sei_filter() ? "enable" : "disable");
|
||||
|
||||
if (conn_ptr->get_mode() == PULL_SRT_MODE) {
|
||||
add_new_puller(conn_ptr, conn_ptr->get_subpath());
|
||||
|
|
|
@ -257,8 +257,9 @@ void srt_server::on_work()
|
|||
}
|
||||
}
|
||||
|
||||
// @see 2020-01-28 https://github.com/Haivision/srt/commit/b8c70ec801a56bea151ecce9c09c4ebb720c2f68#diff-fb66028e8746fea578788532533a296bR786
|
||||
#if SRT_VERSION_MAJOR > 1 || SRT_VERSION_MINOR > 4 || SRT_VERSION_PATCH > 1
|
||||
// New API at 2020-01-28, >1.4.1
|
||||
// @see https://github.com/Haivision/srt/commit/b8c70ec801a56bea151ecce9c09c4ebb720c2f68#diff-fb66028e8746fea578788532533a296bR786
|
||||
#if (SRT_VERSION_MAJOR<<24 | SRT_VERSION_MINOR<<16 | SRT_VERSION_PATCH<<8) > 0x01040100
|
||||
srt_epoll_clear_usocks(_pollid);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -322,10 +322,11 @@ srs_error_t rtmp_client::write_h264_sps_pps(uint32_t dts, uint32_t pts) {
|
|||
return srs_error_wrap(err, "avc to flv");
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
if ((err = rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "write packet");
|
||||
if (_srs_config->get_srt_mix_correct()) {
|
||||
_rtmp_queue.insert_rtmp_data((unsigned char*)flv, nb_flv, (int64_t)dts, SrsFrameTypeVideo);
|
||||
rtmp_write_work();
|
||||
} else {
|
||||
rtmp_write_packet(SrsFrameTypeVideo, dts, flv, nb_flv);
|
||||
}
|
||||
|
||||
// reset sps and pps.
|
||||
|
@ -367,10 +368,14 @@ srs_error_t rtmp_client::write_h264_ipb_frame(char* frame, int frame_size, uint3
|
|||
if ((err = _avc_ptr->mux_avc2flv(ibp, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux avc to flv");
|
||||
}
|
||||
if (_srs_config->get_srt_mix_correct()) {
|
||||
_rtmp_queue.insert_rtmp_data((unsigned char*)flv, nb_flv, (int64_t)dts, SrsFrameTypeVideo);
|
||||
rtmp_write_work();
|
||||
} else {
|
||||
rtmp_write_packet(SrsFrameTypeVideo, dts, flv, nb_flv);
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
return rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv);
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t rtmp_client::write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts) {
|
||||
|
@ -381,8 +386,14 @@ srs_error_t rtmp_client::write_audio_raw_frame(char* frame, int frame_size, SrsR
|
|||
if ((err = _aac_ptr->mux_aac2flv(frame, frame_size, codec, dts, &data, &size)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux aac to flv");
|
||||
}
|
||||
if (_srs_config->get_srt_mix_correct()) {
|
||||
_rtmp_queue.insert_rtmp_data((unsigned char*)data, size, (int64_t)dts, SrsFrameTypeAudio);
|
||||
rtmp_write_work();
|
||||
} else {
|
||||
rtmp_write_packet(SrsFrameTypeAudio, dts, data, size);
|
||||
}
|
||||
|
||||
return rtmp_write_packet(SrsFrameTypeAudio, dts, data, size);
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t rtmp_client::rtmp_write_packet(char type, uint32_t timestamp, char* data, int size) {
|
||||
|
@ -403,6 +414,19 @@ srs_error_t rtmp_client::rtmp_write_packet(char type, uint32_t timestamp, char*
|
|||
return err;
|
||||
}
|
||||
|
||||
void rtmp_client::rtmp_write_work() {
|
||||
rtmp_packet_info_s packet_info;
|
||||
bool ret = false;
|
||||
|
||||
do {
|
||||
ret = _rtmp_queue.get_rtmp_data(packet_info);
|
||||
if (ret) {
|
||||
rtmp_write_packet(packet_info._type, packet_info._dts, (char*)packet_info._data, packet_info._len);
|
||||
}
|
||||
} while(ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_error_t rtmp_client::on_ts_video(std::shared_ptr<SrsBuffer> avs_ptr, uint64_t dts, uint64_t pts) {
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
@ -410,6 +434,12 @@ srs_error_t rtmp_client::on_ts_video(std::shared_ptr<SrsBuffer> avs_ptr, uint64_
|
|||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
dts = dts / 90;
|
||||
pts = pts / 90;
|
||||
|
||||
if (dts == 0) {
|
||||
dts = pts;
|
||||
}
|
||||
|
||||
// send each frame.
|
||||
while (!avs_ptr->empty()) {
|
||||
|
@ -430,6 +460,13 @@ srs_error_t rtmp_client::on_ts_video(std::shared_ptr<SrsBuffer> avs_ptr, uint64_
|
|||
continue;
|
||||
}
|
||||
|
||||
// TODO: FIXME: Should cache this config, it's better not to get it for each video frame.
|
||||
if (_srs_config->get_srt_sei_filter()) {
|
||||
if (nal_unit_type == SrsAvcNaluTypeSEI) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// for sps
|
||||
if (_avc_ptr->is_sps(frame, frame_size)) {
|
||||
std::string sps;
|
||||
|
@ -480,14 +517,47 @@ srs_error_t rtmp_client::on_ts_video(std::shared_ptr<SrsBuffer> avs_ptr, uint64_
|
|||
return err;
|
||||
}
|
||||
|
||||
int rtmp_client::get_sample_rate(char sound_rate) {
|
||||
int sample_rate = 44100;
|
||||
|
||||
switch (sound_rate)
|
||||
{
|
||||
case SrsAudioSampleRate44100:
|
||||
sample_rate = 44100;
|
||||
break;
|
||||
case SrsAudioSampleRate22050:
|
||||
sample_rate = 22050;
|
||||
break;
|
||||
case SrsAudioSampleRate11025:
|
||||
sample_rate = 11025;
|
||||
break;
|
||||
case SrsAudioSampleRate5512:
|
||||
sample_rate = 5512;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
srs_error_t rtmp_client::on_ts_audio(std::shared_ptr<SrsBuffer> avs_ptr, uint64_t dts, uint64_t pts) {
|
||||
srs_error_t err = srs_success;
|
||||
uint64_t base_dts;
|
||||
uint64_t real_dts;
|
||||
uint64_t first_dts;
|
||||
int index = 0;
|
||||
int sample_size = 1024;
|
||||
|
||||
// ensure rtmp connected.
|
||||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
|
||||
base_dts = dts/90;
|
||||
if (base_dts == 0) {
|
||||
base_dts = pts/90;
|
||||
}
|
||||
|
||||
// send each frame.
|
||||
while (!avs_ptr->empty()) {
|
||||
char* frame = NULL;
|
||||
|
@ -496,15 +566,23 @@ srs_error_t rtmp_client::on_ts_audio(std::shared_ptr<SrsBuffer> avs_ptr, uint64_
|
|||
if ((err = _aac_ptr->adts_demux(avs_ptr.get(), &frame, &frame_size, codec)) != srs_success) {
|
||||
return srs_error_wrap(err, "demux adts");
|
||||
}
|
||||
//srs_trace("audio annexb demux sampling_frequency_index:%d, aac_packet_type:%d, sound_rate:%d, sound_size:%d",
|
||||
// codec.sampling_frequency_index, codec.aac_packet_type, codec.sound_rate,
|
||||
// codec.sound_size);
|
||||
//srs_trace_data(frame, frame_size, "audio annexb demux:");
|
||||
// ignore invalid frame,
|
||||
// * atleast 1bytes for aac to decode the data.
|
||||
|
||||
if (frame_size <= 0) {
|
||||
continue;
|
||||
}
|
||||
int sample_rate = get_sample_rate(codec.sound_rate);
|
||||
|
||||
if (codec.aac_packet_type > SrsAudioOpusFrameTraitRaw) {
|
||||
sample_size = 2048;
|
||||
} else {
|
||||
sample_size = 1024;
|
||||
}
|
||||
|
||||
real_dts = base_dts + index * 1000.0 * sample_size / sample_rate;
|
||||
if (index == 0) {
|
||||
first_dts = real_dts;
|
||||
}
|
||||
index++;
|
||||
|
||||
// generate sh.
|
||||
if (_aac_specific_config.empty()) {
|
||||
|
@ -516,19 +594,25 @@ srs_error_t rtmp_client::on_ts_audio(std::shared_ptr<SrsBuffer> avs_ptr, uint64_
|
|||
|
||||
codec.aac_packet_type = 0;
|
||||
|
||||
if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), &codec, dts)) != srs_success) {
|
||||
if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), &codec, real_dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write raw audio frame");
|
||||
}
|
||||
}
|
||||
|
||||
// audio raw data.
|
||||
codec.aac_packet_type = 1;
|
||||
if ((err = write_audio_raw_frame(frame, frame_size, &codec, dts)) != srs_success) {
|
||||
if ((err = write_audio_raw_frame(frame, frame_size, &codec, real_dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write audio raw frame");
|
||||
}
|
||||
_last_live_ts = now_ms();
|
||||
}
|
||||
|
||||
uint64_t diff_t = real_dts - first_dts;
|
||||
diff_t += 100;
|
||||
if ((diff_t > 200) && (diff_t < 600)) {
|
||||
srs_info("set_queue_timeout timeout:%lu", diff_t);
|
||||
_rtmp_queue.set_queue_timeout(diff_t);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -541,16 +625,85 @@ void rtmp_client::on_data_callback(SRT_DATA_MSG_PTR data_ptr, unsigned int media
|
|||
}
|
||||
|
||||
auto avs_ptr = std::make_shared<SrsBuffer>((char*)data_ptr->get_data(), data_ptr->data_len());
|
||||
dts = dts / 90;
|
||||
pts = pts / 90;
|
||||
|
||||
if (media_type == STREAM_TYPE_VIDEO_H264) {
|
||||
on_ts_video(avs_ptr, dts, pts);
|
||||
} else if (media_type == STREAM_TYPE_AUDIO_AAC) {
|
||||
on_ts_audio(avs_ptr, dts, pts);
|
||||
} else {
|
||||
srs_error("mpegts demux unkown stream type:0x%02x", media_type);
|
||||
assert(0);
|
||||
srs_error("mpegts demux unkown stream type:0x%02x, only support h264+aac", media_type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
rtmp_packet_queue::rtmp_packet_queue():_queue_timeout(QUEUE_DEF_TIMEOUT)
|
||||
,_queue_maxlen(QUEUE_LEN_MAX)
|
||||
,_first_packet_t(-1)
|
||||
,_first_local_t(-1) {
|
||||
|
||||
}
|
||||
|
||||
rtmp_packet_queue::~rtmp_packet_queue() {
|
||||
for (auto item : _send_map) {
|
||||
rtmp_packet_info_s info = item.second;
|
||||
if (info._data) {
|
||||
delete info._data;
|
||||
}
|
||||
}
|
||||
_send_map.clear();
|
||||
}
|
||||
|
||||
void rtmp_packet_queue::set_queue_timeout(int64_t queue_timeout) {
|
||||
_queue_timeout = queue_timeout;
|
||||
}
|
||||
|
||||
void rtmp_packet_queue::insert_rtmp_data(unsigned char* data, int len, int64_t dts, char media_type) {
|
||||
rtmp_packet_info_s packet_info;
|
||||
|
||||
packet_info._data = data;
|
||||
packet_info._len = len;
|
||||
packet_info._dts = dts;
|
||||
packet_info._type = media_type;
|
||||
|
||||
if (_first_packet_t == -1) {
|
||||
_first_packet_t = dts;
|
||||
_first_local_t = (int64_t)now_ms();
|
||||
}
|
||||
|
||||
_send_map.insert(std::make_pair(dts, packet_info));
|
||||
return;
|
||||
}
|
||||
|
||||
bool rtmp_packet_queue::is_ready() {
|
||||
if (!_srs_config->get_srt_mix_correct() && !_send_map.empty()) {
|
||||
return true;
|
||||
}
|
||||
if (_send_map.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_send_map.size() >= (size_t)_queue_maxlen) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto first_item = _send_map.begin();
|
||||
int64_t now_t = (int64_t)now_ms();
|
||||
|
||||
int64_t diff_t = (now_t - _first_local_t) - (first_item->first - _first_packet_t);
|
||||
|
||||
if (diff_t >= _queue_timeout) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rtmp_packet_queue::get_rtmp_data(rtmp_packet_info_s& packet_info) {
|
||||
if (!is_ready()) {
|
||||
return false;
|
||||
}
|
||||
auto iter = _send_map.begin();
|
||||
packet_info = iter->second;
|
||||
_send_map.erase(iter);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
|
@ -24,6 +25,37 @@ typedef std::shared_ptr<SrsRawAacStream> AAC_PTR;
|
|||
|
||||
#define DEFAULT_VHOST "__default_host__"
|
||||
|
||||
#define QUEUE_DEF_TIMEOUT 500
|
||||
#define QUEUE_LEN_MAX 100
|
||||
|
||||
typedef struct {
|
||||
unsigned char* _data;
|
||||
int _len;
|
||||
int64_t _dts;
|
||||
char _type;
|
||||
char reserve[3];
|
||||
} rtmp_packet_info_s;
|
||||
|
||||
class rtmp_packet_queue {
|
||||
public:
|
||||
rtmp_packet_queue();
|
||||
~rtmp_packet_queue();
|
||||
|
||||
void set_queue_timeout(int64_t queue_timeout);
|
||||
void insert_rtmp_data(unsigned char* data, int len, int64_t dts, char media_type);
|
||||
bool get_rtmp_data(rtmp_packet_info_s& packet_info);
|
||||
|
||||
private:
|
||||
bool is_ready();
|
||||
|
||||
private:
|
||||
int64_t _queue_timeout;
|
||||
int64_t _queue_maxlen;
|
||||
int64_t _first_packet_t;
|
||||
int64_t _first_local_t;
|
||||
std::multimap<int64_t, rtmp_packet_info_s> _send_map;//key:dts, value:rtmp_packet_info
|
||||
};
|
||||
|
||||
class rtmp_client : public ts_media_data_callback_I, public std::enable_shared_from_this<rtmp_client> {
|
||||
public:
|
||||
rtmp_client(std::string key_path);
|
||||
|
@ -46,6 +78,10 @@ private:
|
|||
virtual srs_error_t write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts);
|
||||
|
||||
int get_sample_rate(char sound_rate);
|
||||
|
||||
void rtmp_write_work();
|
||||
|
||||
private:
|
||||
virtual srs_error_t rtmp_write_packet(char type, uint32_t timestamp, char* data, int size);
|
||||
|
||||
|
@ -71,6 +107,9 @@ private:
|
|||
RTMP_CONN_PTR _rtmp_conn_ptr;
|
||||
bool _connect_flag;
|
||||
int64_t _last_live_ts;
|
||||
|
||||
private:
|
||||
rtmp_packet_queue _rtmp_queue;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<rtmp_client> RTMP_CLIENT_PTR;
|
||||
|
|
|
@ -259,11 +259,21 @@ int ts_demux::decode_unit(unsigned char* data_p, std::string key_path, TS_DATA_C
|
|||
if(ts_header_info._payload_unit_start_indicator){
|
||||
unsigned char* ret_data_p = nullptr;
|
||||
size_t ret_size = 0;
|
||||
uint64_t dts = 0;
|
||||
uint64_t pts = 0;
|
||||
|
||||
//callback last media data in data buffer
|
||||
on_callback(callback, _last_pid, key_path, _last_dts, _last_pts);
|
||||
|
||||
pes_parse(data_p+npos, npos, &ret_data_p, ret_size, _last_dts, _last_pts);
|
||||
int ret = pes_parse(data_p+npos, npos, &ret_data_p, ret_size, dts, pts);
|
||||
assert(ret <= 188);
|
||||
if (ret > 188) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_last_pts = pts;
|
||||
_last_dts = (dts == 0) ? pts : dts;
|
||||
|
||||
if ((ret_data_p != nullptr) && (ret_size > 0)) {
|
||||
insert_into_databuf(ret_data_p, ret_size, key_path, ts_header_info._PID);
|
||||
}
|
||||
|
@ -291,7 +301,6 @@ int ts_demux::decode(SRT_DATA_MSG_PTR data_ptr, TS_DATA_CALLBACK_PTR callback)
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int count = data_ptr->data_len()/188;
|
||||
path = data_ptr->get_path();
|
||||
for (unsigned int index = 0; index < count; index++)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue