2020-04-27 11:07:24 +00:00
|
|
|
#include <uvgrtp/lib.hh>
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2019-08-21 05:04:45 +00:00
|
|
|
#include <thread>
|
2022-08-24 13:05:38 +00:00
|
|
|
#include <iostream>
|
2019-08-21 05:04:45 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
/* There are two main ways of getting received RTP frames from uvgRTP.
|
|
|
|
* This example demonstrates the usage of hook function to receive RTP frames.
|
|
|
|
*
|
|
|
|
* The advantage of using a hook function is minimal CPU usage and delay between
|
|
|
|
* uvgRTP receiving the frame and application processing the frame. When using
|
|
|
|
* the hook method, the application must take care that it is not using the hook
|
|
|
|
* function for heavy processing since this may block RTP frame reception.
|
|
|
|
*
|
|
|
|
* Hook based frame reception is generally recommended for most serious applications,
|
|
|
|
* but there can be situations where polling method is better, especially if performance
|
|
|
|
* is not a huge concern or if there needs to be tight control when the frame is
|
|
|
|
* received by the application.
|
|
|
|
*
|
|
|
|
* This example only implements the receiving, but it can be used together with the
|
|
|
|
* sending example to test the functionality.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// parameters for this test. You can change these to suit your network environment
|
2021-07-16 13:22:58 +00:00
|
|
|
constexpr uint16_t LOCAL_PORT = 8890;
|
|
|
|
|
2022-09-06 07:46:50 +00:00
|
|
|
constexpr char LOCAL_ADDRESS[] = "127.0.0.1";
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
// This example runs for 5 seconds
|
2022-09-06 07:46:50 +00:00
|
|
|
constexpr auto RECEIVE_TIME_S = std::chrono::seconds(10);
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
void rtp_receive_hook(void *arg, uvgrtp::frame::rtp_frame *frame);
|
|
|
|
void cleanup(uvgrtp::context& ctx, uvgrtp::session *sess, uvgrtp::media_stream *receiver);
|
2019-08-21 05:04:45 +00:00
|
|
|
|
2020-02-14 06:12:50 +00:00
|
|
|
int main(void)
|
2019-08-21 05:04:45 +00:00
|
|
|
{
|
2021-07-16 13:22:58 +00:00
|
|
|
std::cout << "Starting uvgRTP RTP receive hook example" << std::endl;
|
|
|
|
|
2021-02-19 01:13:43 +00:00
|
|
|
uvgrtp::context ctx;
|
2022-09-06 07:46:50 +00:00
|
|
|
uvgrtp::session *sess = ctx.create_session(LOCAL_ADDRESS);
|
|
|
|
int flags = RCE_RECEIVE_ONLY;
|
|
|
|
uvgrtp::media_stream *receiver = sess->create_stream(LOCAL_PORT, RTP_FORMAT_H265, flags);
|
2019-08-21 05:04:45 +00:00
|
|
|
|
2021-04-23 05:55:15 +00:00
|
|
|
/* Receive hook can be installed and uvgRTP will call this hook when an RTP frame is received
|
2019-08-21 05:04:45 +00:00
|
|
|
*
|
|
|
|
* This is a non-blocking operation
|
|
|
|
*
|
|
|
|
* If necessary, receive hook can be given an argument and this argument is supplied to
|
2021-04-23 05:55:15 +00:00
|
|
|
* the receive hook every time the hook is called. This argument could a pointer to application-
|
2019-08-21 05:04:45 +00:00
|
|
|
* specfic object if the application needs to be called inside the hook
|
|
|
|
*
|
2020-02-14 06:12:50 +00:00
|
|
|
* If it's not needed, it should be set to nullptr */
|
2021-07-27 07:36:54 +00:00
|
|
|
if (!receiver || receiver->install_receive_hook(nullptr, rtp_receive_hook) != RTP_OK)
|
|
|
|
{
|
|
|
|
std::cerr << "Failed to install RTP reception hook";
|
|
|
|
cleanup(ctx, sess, receiver);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "Waiting incoming packets for " << RECEIVE_TIME_S.count() << " s" << std::endl;
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(RECEIVE_TIME_S); // lets this example run for some time
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
cleanup(ctx, sess, receiver);
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rtp_receive_hook(void *arg, uvgrtp::frame::rtp_frame *frame)
|
|
|
|
{
|
|
|
|
std::cout << "Received RTP frame" << std::endl;
|
|
|
|
|
|
|
|
/* Now we own the frame. Here you could give the frame to the application
|
|
|
|
* if f.ex "arg" was some application-specific pointer
|
|
|
|
*
|
|
|
|
* arg->copy_frame(frame) or whatever
|
|
|
|
*
|
|
|
|
* When we're done with the frame, it must be deallocated manually */
|
|
|
|
(void)uvgrtp::frame::dealloc_frame(frame);
|
|
|
|
}
|
2021-07-16 13:22:58 +00:00
|
|
|
|
2021-07-27 07:36:54 +00:00
|
|
|
void cleanup(uvgrtp::context& ctx, uvgrtp::session *sess, uvgrtp::media_stream *receiver)
|
|
|
|
{
|
|
|
|
if (receiver)
|
2021-07-16 13:22:58 +00:00
|
|
|
{
|
2021-07-27 07:36:54 +00:00
|
|
|
sess->destroy_stream(receiver);
|
2021-07-16 13:22:58 +00:00
|
|
|
}
|
2019-08-21 05:04:45 +00:00
|
|
|
|
2021-07-16 13:22:58 +00:00
|
|
|
if (sess)
|
|
|
|
{
|
|
|
|
/* Session must be destroyed manually */
|
|
|
|
ctx.destroy_session(sess);
|
|
|
|
}
|
2019-08-21 05:04:45 +00:00
|
|
|
}
|