diff --git a/include/media_stream.hh b/include/media_stream.hh index a2d6c08..a1163f3 100644 --- a/include/media_stream.hh +++ b/include/media_stream.hh @@ -84,8 +84,13 @@ namespace uvg_rtp { * NOTE: pull_frame() is a blocking operation and a separate thread should be * spawned for it! * + * You can specify for how long should pull_frame() block by giving "timeout" + * parameter that denotes how long pull_frame() will wait for an incoming frame + * in milliseconds + * * Return pointer to RTP frame on success */ uvg_rtp::frame::rtp_frame *pull_frame(); + uvg_rtp::frame::rtp_frame *pull_frame(size_t timeout); /* Alternative to pull_frame(). The provided hook is called when a frame is received. * diff --git a/include/receiver.hh b/include/receiver.hh index d24a9f8..2da7ad6 100644 --- a/include/receiver.hh +++ b/include/receiver.hh @@ -28,6 +28,9 @@ namespace uvg_rtp { /* NOTE: this operation is blocking */ uvg_rtp::frame::rtp_frame *pull_frame(); + /* Block at most "timeout" milliseconds and return nullptr if nothing was received */ + uvg_rtp::frame::rtp_frame *pull_frame(size_t timeout); + /* Open socket, start frame receiver and RTCP * * Return RTP_OK on success diff --git a/src/media_stream.cc b/src/media_stream.cc index 7557ca4..d74c1c3 100644 --- a/src/media_stream.cc +++ b/src/media_stream.cc @@ -223,6 +223,17 @@ uvg_rtp::frame::rtp_frame *uvg_rtp::media_stream::pull_frame() return receiver_->pull_frame(); } +uvg_rtp::frame::rtp_frame *uvg_rtp::media_stream::pull_frame(size_t timeout) +{ + if (!initialized_) { + LOG_ERROR("RTP context has not been initialized fully, cannot continue!"); + rtp_errno = RTP_NOT_INITIALIZED; + return nullptr; + } + + return receiver_->pull_frame(timeout); +} + rtp_error_t uvg_rtp::media_stream::install_receive_hook(void *arg, void (*hook)(void *, uvg_rtp::frame::rtp_frame *)) { if (!initialized_) { diff --git a/src/receiver.cc b/src/receiver.cc index 8031921..9c48da3 100644 --- a/src/receiver.cc +++ b/src/receiver.cc @@ -84,6 +84,27 @@ uvg_rtp::frame::rtp_frame *uvg_rtp::receiver::pull_frame() return frame; } +uvg_rtp::frame::rtp_frame *uvg_rtp::receiver::pull_frame(size_t timeout) +{ + while (frames_.empty() && this->active() && timeout) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + --timeout; + } + + if (!this->active()) + return nullptr; + + if (frames_.empty()) + return nullptr; + + frames_mtx_.lock(); + auto frame = frames_.front(); + frames_.erase(frames_.begin()); + frames_mtx_.unlock(); + + return frame; +} + uint8_t *uvg_rtp::receiver::get_recv_buffer() const { return recv_buf_;