diff --git a/README.md b/README.md index d8b879b..3f5e74e 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,4 @@ See [examples](examples/) directory for different uvgRTP examples Please cite the following paper for uvgRTP: -``` -A. Altonen, J. Räsänen, J. Laitinen, M. Viitanen, and J. Vanne, “Open-source RTP library for high-speed 4K HEVC video streaming,” in Proc. IEEE Int. Workshop on Multimedia Signal Processing, Tampere, Finland, Sept. 2020. -``` +```A. Altonen, J. Räsänen, J. Laitinen, M. Viitanen, and J. Vanne, “Open-source RTP library for high-speed 4K HEVC video streaming,” in Proc. IEEE Int. Workshop on Multimedia Signal Processing, Tampere, Finland, Sept. 2020.``` diff --git a/include/formats/h26x.hh b/include/formats/h26x.hh index 790e22a..921c543 100644 --- a/include/formats/h26x.hh +++ b/include/formats/h26x.hh @@ -33,7 +33,7 @@ namespace uvg_rtp { * * Return RTP_OK on success * Return RTP_INVALID_VALUE if one the parameters is invalid */ - rtp_error_t push_h26x_frame(uint8_t *data, size_t data_len); + rtp_error_t push_h26x_frame(uint8_t *data, size_t data_len, int flags); protected: /* Each H26x class overrides this function with their custom NAL pushing function */ diff --git a/include/rtp.hh b/include/rtp.hh index a0fcc05..84cb443 100644 --- a/include/rtp.hh +++ b/include/rtp.hh @@ -42,7 +42,7 @@ namespace uvg_rtp { uint8_t payload_; uint32_t clock_rate_; - uint32_t wc_start_; + uint64_t wc_start_; uvg_rtp::clock::hrc::hrc_t wc_start_2; size_t sent_pkts_; diff --git a/src/clock.cc b/src/clock.cc index acb0bc5..2e704a8 100644 --- a/src/clock.cc +++ b/src/clock.cc @@ -6,20 +6,23 @@ #endif #include "clock.hh" +#include + +static const uint64_t EPOCH = 2208988800ULL; +static const uint64_t NTP_SCALE_FRAC = 4294967296ULL; static inline uint32_t ntp_diff_ms(uint64_t t1, uint64_t t2) { - uint32_t s_diff = (t1 >> 32) - (t2 >> 32); - uint32_t us_diff = (t1 & 0xffffffff) - (t2 & 0xffffffff); + uint32_t s1 = (t1 >> 32) & 0xffffffff; + uint32_t s2 = (t2 >> 32) & 0xffffffff; + uint64_t us1 = ((t1 & 0xffffffff) * 1000000UL) / NTP_SCALE_FRAC; + uint64_t us2 = ((t2 & 0xffffffff) * 1000000UL) / NTP_SCALE_FRAC; - return s_diff * 1000 + (us_diff / 1000000UL); + return (((s1 - s2) * 1000000) + ((us1 - us2))) / 1000; } uint64_t uvg_rtp::clock::ntp::now() { - static const uint64_t EPOCH = 2208988800ULL; - static const uint64_t NTP_SCALE_FRAC = 4294967296ULL; - struct timeval tv; #ifdef _WIN32 uvg_rtp::clock::gettimeofday(&tv, NULL); @@ -30,7 +33,7 @@ uint64_t uvg_rtp::clock::ntp::now() uint64_t tv_ntp, tv_usecs; tv_ntp = tv.tv_sec + EPOCH; - tv_usecs = (NTP_SCALE_FRAC * tv.tv_usec) / 1000000UL; + tv_usecs = (float)(NTP_SCALE_FRAC * tv.tv_usec) / (float)1000000UL; return (tv_ntp << 32) | tv_usecs; } diff --git a/src/formats/h265.cc b/src/formats/h265.cc index c37cb65..9309537 100644 --- a/src/formats/h265.cc +++ b/src/formats/h265.cc @@ -99,6 +99,9 @@ rtp_error_t uvg_rtp::formats::h265::push_nal_unit(uint8_t *data, size_t data_len LOG_ERROR("Failed to enqueue Single NAL Unit packet!"); return ret; } + + if (more) + return RTP_NOT_READY; return fqueue_->flush_queue(); } else { (void)make_aggregation_pkt(); diff --git a/src/formats/h26x.cc b/src/formats/h26x.cc index d95a119..1ab4312 100644 --- a/src/formats/h26x.cc +++ b/src/formats/h26x.cc @@ -230,7 +230,7 @@ end: return -1; } -rtp_error_t uvg_rtp::formats::h26x::push_h26x_frame(uint8_t *data, size_t data_len) +rtp_error_t uvg_rtp::formats::h26x::push_h26x_frame(uint8_t *data, size_t data_len, int flags) { /* find first start code */ uint8_t start_len = 0; @@ -240,15 +240,19 @@ rtp_error_t uvg_rtp::formats::h26x::push_h26x_frame(uint8_t *data, size_t data_l rtp_error_t ret = RTP_GENERIC_ERROR; size_t payload_size = rtp_ctx_->get_payload_size(); - if (data_len < payload_size) { + if (data_len < payload_size || flags & RTP_SLICE) { r_off = (offset < 0) ? 0 : offset; - if ((ret = fqueue_->enqueue_message(data + r_off, data_len - r_off)) != RTP_OK) { - LOG_ERROR("Failed to enqueue Single NAL Unit packet!"); - return ret; - } + if (data_len > payload_size) { + return push_nal_unit(data + r_off, data_len, false); + } else { + if ((ret = fqueue_->enqueue_message(data + r_off, data_len - r_off)) != RTP_OK) { + LOG_ERROR("Failed to enqueue Single NAL Unit packet!"); + return ret; + } - return fqueue_->flush_queue(); + return fqueue_->flush_queue(); + } } while (offset != -1) { @@ -296,8 +300,6 @@ uvg_rtp::formats::h26x::~h26x() rtp_error_t uvg_rtp::formats::h26x::push_media_frame(uint8_t *data, size_t data_len, int flags) { - (void)flags; - rtp_error_t ret; if (!data || !data_len) @@ -308,5 +310,5 @@ rtp_error_t uvg_rtp::formats::h26x::push_media_frame(uint8_t *data, size_t data_ return ret; } - return push_h26x_frame(data, data_len); + return push_h26x_frame(data, data_len, flags); } diff --git a/src/queue.cc b/src/queue.cc index cb49ba7..ad6e672 100644 --- a/src/queue.cc +++ b/src/queue.cc @@ -353,7 +353,8 @@ rtp_error_t uvg_rtp::frame_queue::flush_queue() } /* set the marker bit of the last packet to 1 */ - ((uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr - 1])[1] |= (1 << 7); + if (active_->packets.size() > 1) + ((uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr - 1])[1] |= (1 << 7); transaction_mtx_.lock(); queued_.insert(std::make_pair(active_->key, active_)); diff --git a/src/rtp.cc b/src/rtp.cc index ad752a7..445a753 100644 --- a/src/rtp.cc +++ b/src/rtp.cc @@ -90,10 +90,9 @@ void uvg_rtp::rtp::fill_header(uint8_t *buffer) /* This is the first RTP message, get wall clock reading (t = 0) * and generate random RTP timestamp for this reading */ - if (wc_start_ == 0) { + if (!wc_start_) { ts_ = uvg_rtp::random::generate_32(); - wc_start_2 = uvg_rtp::clock::hrc::now(); - wc_start_ = 1; + wc_start_ = uvg_rtp::clock::ntp::now(); } buffer[0] = 2 << 6; // RTP version @@ -105,10 +104,11 @@ void uvg_rtp::rtp::fill_header(uint8_t *buffer) if (timestamp_ == INVALID_TS) { *(uint32_t *)&buffer[4] = htonl( ts_ - + uvg_rtp::clock::hrc::diff_now(wc_start_2) + + uvg_rtp::clock::ntp::diff_now(wc_start_) * clock_rate_ / 1000 ); + } else { *(uint32_t *)&buffer[4] = htonl(timestamp_); }