mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
autoadapt: Add RTP Absolute Send Time extension
Change-Id: I81a9a4cfc3addaa4be00f45ddc79b5e9642ed4ae
This commit is contained in:

committed by
Adrien Béraud

parent
cc4f10cedf
commit
fa6f4a8771
71
contrib/src/ffmpeg/rtp_ext_abs_send_time.patch
Normal file
71
contrib/src/ffmpeg/rtp_ext_abs_send_time.patch
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
|
||||||
|
index 63047beccc..d59ec3dc8c 100644
|
||||||
|
--- a/libavformat/rtpenc.c
|
||||||
|
+++ b/libavformat/rtpenc.c
|
||||||
|
@@ -28,6 +28,8 @@
|
||||||
|
|
||||||
|
#include "rtpenc.h"
|
||||||
|
|
||||||
|
+#define EXT_ABS_SEND_TIME
|
||||||
|
+
|
||||||
|
static const AVOption options[] = {
|
||||||
|
FF_RTP_FLAG_OPTS(RTPMuxContext, flags),
|
||||||
|
{ "payload_type", "Specify RTP payload type", offsetof(RTPMuxContext, payload_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 127, AV_OPT_FLAG_ENCODING_PARAM },
|
||||||
|
@@ -146,7 +148,11 @@ static int rtp_write_header(AVFormatContext *s1)
|
||||||
|
s1->pb->max_packet_size);
|
||||||
|
} else
|
||||||
|
s1->packet_size = s1->pb->max_packet_size;
|
||||||
|
+#ifdef EXT_ABS_SEND_TIME
|
||||||
|
+ if (s1->packet_size <= 20) {
|
||||||
|
+#else
|
||||||
|
if (s1->packet_size <= 12) {
|
||||||
|
+#endif
|
||||||
|
av_log(s1, AV_LOG_ERROR, "Max packet size %u too low\n", s1->packet_size);
|
||||||
|
return AVERROR(EIO);
|
||||||
|
}
|
||||||
|
@@ -154,7 +160,11 @@ static int rtp_write_header(AVFormatContext *s1)
|
||||||
|
if (!s->buf) {
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
+#ifdef EXT_ABS_SEND_TIME
|
||||||
|
+ s->max_payload_size = s1->packet_size - 20;
|
||||||
|
+#else
|
||||||
|
s->max_payload_size = s1->packet_size - 12;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
|
avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);
|
||||||
|
@@ -332,16 +342,34 @@ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time, int bye)
|
||||||
|
void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m)
|
||||||
|
{
|
||||||
|
RTPMuxContext *s = s1->priv_data;
|
||||||
|
+ uint64_t ntp64_time;
|
||||||
|
+ uint32_t absoluteSendTime;
|
||||||
|
|
||||||
|
av_log(s1, AV_LOG_TRACE, "rtp_send_data size=%d\n", len);
|
||||||
|
|
||||||
|
/* build the RTP header */
|
||||||
|
+#ifdef EXT_ABS_SEND_TIME
|
||||||
|
+ avio_w8(s1->pb, RTP_VERSION << 6 | 0x10); // extention bit
|
||||||
|
+#else
|
||||||
|
avio_w8(s1->pb, RTP_VERSION << 6);
|
||||||
|
+#endif
|
||||||
|
avio_w8(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7));
|
||||||
|
avio_wb16(s1->pb, s->seq);
|
||||||
|
avio_wb32(s1->pb, s->timestamp);
|
||||||
|
avio_wb32(s1->pb, s->ssrc);
|
||||||
|
|
||||||
|
+#ifdef EXT_ABS_SEND_TIME
|
||||||
|
+ avio_wb16(s1->pb, 0xBEDE); // magic word
|
||||||
|
+ avio_wb16(s1->pb, 0x0001); // length=1
|
||||||
|
+ avio_w8(s1->pb, 0x32); // ID=3 and lenght=2
|
||||||
|
+ ntp64_time = ff_get_formatted_ntp_time(ff_ntp_time());
|
||||||
|
+ absoluteSendTime = (uint32_t)((ntp64_time>> 14) & 0x00ffffff);
|
||||||
|
+ av_log(s1, AV_LOG_TRACE, "ntp64:%lu, abs_time:%u\n", ntp64_time, absoluteSendTime);
|
||||||
|
+ avio_w8(s1->pb, (uint8_t)(absoluteSendTime >> 16));
|
||||||
|
+ avio_w8(s1->pb, (uint8_t)(absoluteSendTime >> 8 & 0xff));
|
||||||
|
+ avio_w8(s1->pb, (uint8_t)(absoluteSendTime & 0xff));
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
avio_write(s1->pb, buf1, len);
|
||||||
|
avio_flush(s1->pb);
|
@ -325,6 +325,7 @@ ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.gz
|
|||||||
(cd $@-$(FFMPEG_HASH) && tar x $(if ${BATCH_MODE},,-v) --strip-components=1 -f ../$<)
|
(cd $@-$(FFMPEG_HASH) && tar x $(if ${BATCH_MODE},,-v) --strip-components=1 -f ../$<)
|
||||||
$(APPLY) $(SRC)/ffmpeg/remove-mjpeg-log.patch
|
$(APPLY) $(SRC)/ffmpeg/remove-mjpeg-log.patch
|
||||||
$(APPLY) $(SRC)/ffmpeg/change-RTCP-ratio.patch
|
$(APPLY) $(SRC)/ffmpeg/change-RTCP-ratio.patch
|
||||||
|
$(APPLY) $(SRC)/ffmpeg/rtp_ext_abs_send_time.patch
|
||||||
$(UPDATE_AUTOCONFIG)
|
$(UPDATE_AUTOCONFIG)
|
||||||
$(MOVE)
|
$(MOVE)
|
||||||
|
|
||||||
|
@ -493,14 +493,21 @@ SocketPair::readCallback(uint8_t* buf, int buf_size)
|
|||||||
|
|
||||||
// SRTP decrypt
|
// SRTP decrypt
|
||||||
if (not fromRTCP and srtpContext_ and srtpContext_->srtp_in.aes) {
|
if (not fromRTCP and srtpContext_ and srtpContext_->srtp_in.aes) {
|
||||||
uint32_t curentSendTS = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7];
|
int32_t gradient = 0;
|
||||||
int32_t delay = 0;
|
int32_t deltaT = 0;
|
||||||
float abs = 0.0f;
|
float abs = 0.0f;
|
||||||
bool marker = (buf[1] & 0x80) >> 7;
|
bool res_parse = false;
|
||||||
bool res = getOneWayDelayGradient2(abs, marker, &delay);
|
bool res_delay = false;
|
||||||
|
|
||||||
if (res)
|
res_parse = parse_RTP_ext(buf, &abs);
|
||||||
rtpDelayCallback_(delay);
|
bool marker = (buf[1] & 0x80) >> 7;
|
||||||
|
|
||||||
|
if(res_parse)
|
||||||
|
res_delay = getOneWayDelayGradient2(abs, marker, &gradient, &deltaT);
|
||||||
|
|
||||||
|
// rtpDelayCallback_ is not set for audio
|
||||||
|
if (rtpDelayCallback_ && res_delay)
|
||||||
|
rtpDelayCallback_(gradient);
|
||||||
|
|
||||||
auto err = ff_srtp_decrypt(&srtpContext_->srtp_in, buf, &len);
|
auto err = ff_srtp_decrypt(&srtpContext_->srtp_in, buf, &len);
|
||||||
if(packetLossCallback_ and (buf[2] << 8 | buf[3]) != lastSeqNum_+1) {
|
if(packetLossCallback_ and (buf[2] << 8 | buf[3]) != lastSeqNum_+1) {
|
||||||
@ -667,7 +674,7 @@ SocketPair::getOneWayDelayGradient(uint32_t sendTS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SocketPair::getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient)
|
SocketPair::getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient, int32_t* deltaT)
|
||||||
{
|
{
|
||||||
// Keep only last packet of each frame
|
// Keep only last packet of each frame
|
||||||
if (not marker) {
|
if (not marker) {
|
||||||
@ -681,7 +688,7 @@ SocketPair::getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t deltaS = (sendTS - lastSendTS_) * 1000; // milliseconds
|
int32_t deltaS = (sendTS - lastSendTS_) * 1000; // milliseconds
|
||||||
if(deltaS < 0)
|
if(deltaS < 0)
|
||||||
deltaS += 64000;
|
deltaS += 64000;
|
||||||
lastSendTS_ = sendTS;
|
lastSendTS_ = sendTS;
|
||||||
@ -691,6 +698,7 @@ SocketPair::getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient
|
|||||||
lastReceiveTS_ = arrival_TS;
|
lastReceiveTS_ = arrival_TS;
|
||||||
|
|
||||||
*gradient = deltaR - deltaS;
|
*gradient = deltaR - deltaS;
|
||||||
|
*deltaT = deltaR;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -739,4 +747,22 @@ SocketPair::getOneWayDelayGradient3(uint32_t sendTS, int32_t* gradient)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SocketPair::parse_RTP_ext(uint8_t* buf, float* abs)
|
||||||
|
{
|
||||||
|
if(not(buf[0] & 0x10))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint16_t magic_word = (buf[12] << 8) + buf[13];
|
||||||
|
if(magic_word != 0xBEDE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t sec = buf[17] >> 2;
|
||||||
|
uint32_t fract = ((buf[17] & 0x3) << 16 | (buf[18] << 8) | buf[19]) << 14;
|
||||||
|
float milli = fract / pow(2,32);
|
||||||
|
|
||||||
|
*abs = sec + (milli);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace jami
|
} // namespace jami
|
||||||
|
@ -203,8 +203,9 @@ class SocketPair {
|
|||||||
std::function<void(void)> packetLossCallback_;
|
std::function<void(void)> packetLossCallback_;
|
||||||
std::function<void(int)> rtpDelayCallback_;
|
std::function<void(int)> rtpDelayCallback_;
|
||||||
int32_t getOneWayDelayGradient(uint32_t sendTS);
|
int32_t getOneWayDelayGradient(uint32_t sendTS);
|
||||||
bool getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient);
|
bool getOneWayDelayGradient2(float sendTS, bool marker, int32_t* gradient, int32_t* deltaR);
|
||||||
bool getOneWayDelayGradient3(uint32_t sendTS, int32_t* gradient);
|
bool getOneWayDelayGradient3(uint32_t sendTS, int32_t* gradient);
|
||||||
|
bool parse_RTP_ext(uint8_t* buf, float* abs);
|
||||||
|
|
||||||
std::list<rtcpRRHeader> listRtcpRRHeader_;
|
std::list<rtcpRRHeader> listRtcpRRHeader_;
|
||||||
std::list<rtcpREMBHeader> listRtcpREMBHeader_;
|
std::list<rtcpREMBHeader> listRtcpREMBHeader_;
|
||||||
@ -220,8 +221,7 @@ class SocketPair {
|
|||||||
|
|
||||||
std::chrono::steady_clock::time_point lastRR_time;
|
std::chrono::steady_clock::time_point lastRR_time;
|
||||||
uint16_t lastSeqNum_ {0};
|
uint16_t lastSeqNum_ {0};
|
||||||
uint32_t lastSendTS_ {0};
|
float lastSendTS_ {0.0f};
|
||||||
bool lastMarker_ {false};
|
|
||||||
std::chrono::steady_clock::time_point lastReceiveTS_ {};
|
std::chrono::steady_clock::time_point lastReceiveTS_ {};
|
||||||
std::chrono::steady_clock::time_point arrival_TS {};
|
std::chrono::steady_clock::time_point arrival_TS {};
|
||||||
|
|
||||||
|
@ -151,10 +151,6 @@ void VideoRtpSession::startSender()
|
|||||||
rtcpCheckerThread_.start();
|
rtcpCheckerThread_.start();
|
||||||
else if (not autoQuality and rtcpCheckerThread_.isRunning())
|
else if (not autoQuality and rtcpCheckerThread_.isRunning())
|
||||||
rtcpCheckerThread_.join();
|
rtcpCheckerThread_.join();
|
||||||
|
|
||||||
socketPair_->setRtpDelayCallback([&](int delay) {
|
|
||||||
this->delayMonitor(delay);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +203,8 @@ void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock,
|
|||||||
else
|
else
|
||||||
socketPair_.reset(new SocketPair(getRemoteRtpUri().c_str(), receive_.addr.getPort()));
|
socketPair_.reset(new SocketPair(getRemoteRtpUri().c_str(), receive_.addr.getPort()));
|
||||||
|
|
||||||
|
socketPair_->setRtpDelayCallback([&](int delay) {delayMonitor(delay);});
|
||||||
|
|
||||||
if (send_.crypto and receive_.crypto) {
|
if (send_.crypto and receive_.crypto) {
|
||||||
socketPair_->createSRTP(receive_.crypto.getCryptoSuite().c_str(),
|
socketPair_->createSRTP(receive_.crypto.getCryptoSuite().c_str(),
|
||||||
receive_.crypto.getSrtpKeyInfo().c_str(),
|
receive_.crypto.getSrtpKeyInfo().c_str(),
|
||||||
|
Reference in New Issue
Block a user