It is no longer possible to send APP packets alone as RFC 3550 does
not permit this. Instead they are sent together with SR and RR as they
are supposed to.
RFC 3550 A.8 says that jitter should be saved as float and sampled to
32-bit unsigned integer. This commit fixes this and seems to improve
the accuracy of jitter estimation (previously it often showed just
15 or 10).
The allowed payload sizes were calculated slightly incorrectly and
this caused frames with sizes near the allowed frame size to be not
sent or sent incorrectly. Now all these errors should be fixed.
uvgRTP was using incorrect terms in few places which made the code more
difficult to understand. This commit fixes this by changing NAL header
(incorrect) to payload header (correct).
Integrated runner into holepuncher since it was the only remaining class
still using it and they both are small classes where separation does more
harm than good.
The dispatching is what technique the class uses, but it does not
describe its responsibilities at all making it very hard to figure out
what role it plays in the architecture just by looking at the name.
Also removed all references to obsolete System call dispatcher
(different concept) in all the comments.
With this separation, the user has the option of not including all
the classes with lib.hh, where as previously it was mandatory because
context is always needed.
The previous implementation had the pull_frame take around 20x longer
than what the user specifies (no matter how long the user specified.
Now the excess should only be max 30 ms, which is an improvement.
These tests are mostly just placeholders until something more
substantial is added. They are good tests, but it would be better to
also test the functions in different kinds of scenarios.
Note: the Crypto++ is causing problems in tests on Windows, because the
CMake is rerun often and this causes the Crypto++ linking to disappear.
I just switched all __linux to not _WIN32 in the hopes that Unix/Linux
API would be more likely to be found on Mac OS. This has not been
tested on Mac so it may or may not work.
Primary changes are:
- Versioning integrated in cmake build system with library for version usage in end user programs
- New minimum CMAke required version is 3.14
- Created install capabilities. Allows uvgRTP to be used in different scenarios for win and lin (mac-os still missing)
- Added testing environment with automatically fetched google test and some example test code.
- Added packaging capabilities (and some placeholders that have to be changed)
- Create Shared library with -DBUILD_SHARED_LIBS=TRUE
Send receiver reports instead of sender reports if we haven't sent any
RTP packets. Also don't include report blocks if we haven't received
any RTP packets.
The architecture is more easily modified with less dependencies. The
dependency concerned only getting the keys from zrtp and now that is
handled by media_stream.
Also added checks that we are not double freeing resources, since
previous version seemed very risky.
This commit removes little bit of duplicate code, making future bug
fixes easier. The length of the packet is not set correctly, but that
will bi fixed in future.
Since compiler was complaining about them and its little bit more
secure, I set all integers to 0 and pointers to nullptr. There is a
small risk of reduced performance if the initialization is done
frequently, but I think the risk is worth it since uvgRTP is already
one of the fastest RTP libraries in the world and there are issues with
reliability.
The member variable initialization was introduced in C++11 which is the
lowest we support at the moment.
I tried to make the headers be included in local to global order. This
way any potential missing includes are detected making it easier to
make changes to header location and includes.
The 2.0.0 release of uvgRTP fails to build on CentOS7, because :
- the gcc-c++ compiler doesn't support the c++17 standard, which is
required to compile the crypto.hh file
- the getrandom() function isn't available in the libc
This pull request adds CentOS7 build support.
The modified files are :
- CMakeLists.txt : the availability of the getrandom() function is checked.
If it exists, the HAVE_GETRANDOM preprocessor definition is added
- src/random.cc : if HAVE_GETRANDOM isn't defined, a syscall equivalent to
the getrandom() functions is called
- include/crypto.hh : the c++17 code is replaced by a code that compiles with
the CentOS7 compiler (c++11)
Fragmented generic frames whose sequence numbers crossed the overflow
boundary were incorrectly reconstructed as the last fragments of the
frame were in the beginning of the buffer.
Save the frame info to the media object and fetch it from there
when a packet is received, update the code to better handle out-of-order
packets and add support for RCE_H26X_PREPEND_SC
I have no idea why the name had an underscore but now it's gone.
The old namespace is kept as an alias for backwards-compatibility
but it may be removed in the future
1443 is the maximum payload size for H26X Fragmentation Units but
for generic frames there is no NAL + FU header meaning the 3 bytes
can be used for payload data
This change removes set_dynamic_payload() as ctx_configure() function
should be used for all context configuration instead of separate functions
for some configurations
Use __has_include to check if all needed headers are present in the
system and if so, build uvgRTP with crypto enabled.
Introduce new define, __RTP_NO_CRYPTO__ which disables SRTP/ZRTP
support even if Crypto++ is present in the system
This thread-based approach is no longer supported and optimistic
packet reception isn't possible to implement properly using the
new packet dispatcher architecture
If a media format needs to return multiple frames, it can install
a frame getter that is called by the packet dispatcher until all
frames have been queried and returned to user.
Because the receiver adds an offset to those sequence numbers which
cross the 0xfff boundary, the key must be extended to 32 bits so
the frames are reconstructible
blocked_recv() is a Windows-only function that is used to implement
a blocking socket that blocks only a certain amount of time.
This is quite an ugly hack and hopefully a better solution for
"semi-blocking" socket is implemented in the future
Previous implementation did not consider the fact that sequence number
could overflow and start fragment would thus appear later than the end
fragment.
This caused distortions in the video as the frames were constructed
incorrectly. By adjusting the overflown sequence number, the fragments
can be stored efficiently to std::map while maintaining their order.
Add all new source and header files to Visual Studio, CMake and
QtCreator project files.
Rename rtcp/runner.cc and zrtp/receiver.cc files because they
caused linking problems with QtCreator
H26x shall contain all code common to H26{4,5,6} and H26{4,5,6}
files shall contain format-specific code which is mainly just
NAL unit fragmentation.
This commit also changes the HEVC RTP format name from RTP_FORMAT_HEVC
to RTP_FORMAT_H265 to unify naming with upcoming AVC/VVC support
Add __RTP_CRYPTO__ around CryptoPP code and remove from all other
places. This should provide a cleaner way of compiling and linking
to the library.
Not sure if I'm totally happy with this solution either but it's
a step to a better direction at least.
Auxiliary handlers may need access to the original block of memory
(such as SRTP) so instead of relaying that parameter to every handler,
store pointer to the block inside the RTP frame. The pointer is valid
as long as the packet is being processed and the last handler should
set it to nullptr.
Some changes to the public frame should be made because a lot of
the fields in the frames used by uvgRTP are not important outside
the library.
By default uvgRTP assumes that the memory it gets from user is not
writable and if user doesn't explictly specify that the memory
is writable (RCE_SRTP_INPLACE_ENCRYPTION) or that encryption is
not necessary (RCE_SRTP_NULL_CIPHER), a copy of the memory block is
made before it is pushed into the frame queue.
Create separate classes for SRTP and SRTCP because even though
they are quite similar, they require some different actions when
en/decrypting the packets and create a whole bunch of if-elses
is ugly
Operate on a raw block of memory, extract interesting fields from the
packet and create user-friendly struct for the APP packet that
can be queried using SSRC
Caller must remember to free the memory occupied by the APP payload
Operate on a raw block of memory, extract interesting fields from the
packet and create user-friendly struct for the SDES packet that
can be queried using SSRC
Caller must remember to free the memory occupied by the SDES items
Operate on a raw block of memory, extract interesting fields from the
packet and create user-friendly struct for the Sender Report that
can be queried using SSRC
PACKED_STRUCT is quite an ugly hack if it must be cross-platform
so better to process the incoming (and soon outgoing) RTCP data
as raw memory and craft user-friendly RTCP packets from those
memory blocks which do not including strict padding or truncated fields.
The authentication tag for each packet is stored inside the active
transaction and they are destroyed when the transaction is deallocated.
This way neither Socket nor SRTP needs to worry about (de)allocation
of those tags.
The authentication tag occupies the last slot in the pkt_vec structure
of each packet so it's easily accessible for the security layer when
calculating the checksum and guaranteed to be there if
RCE_SRTP_AUTHENTICATE_RTP has been provided.
Move frame queue to Media object and implement the generic push API
using a frame queue
This change temporarily disable the fragmentation of generic frames
Introduce buf_vec and pkt_vec structures which enable cross-platform
scatter/gather I/O. This supersedes the previous Linux-only mmsghdr
hack. Buf_vec contains buffers of a single RTP frame
whereas pkt_vec contains multiple buf_vec structures that are sent
all at once when flush_queue() is called.
From now on all media formats should use frame queue to implement
RTP frame sending. This is because internally the frame queue
updates RTP header information and it can inject additional fields
to the RTP frame such as an authentication tag.
uvgRTP can install handler f.ex. for collecting RTCP sender statistics
information or to install SRTP encryption handler.
This way these unrelated objects don't have to be passed to src/socket.cc
and it will only contain code pertaining to actual socket operations
This kind of functionality is now provided by RTP packet dispatcher
for receive-functionality and similar kind of send functionality
is implemented very soon
Some packet handlers (such as RTCP) may need access to the parent
object or they may require some additional data from outside the
packet handler that is required when processing the packet.
Having a 1100 lines long file is not manageable so split RTCP
code into different files by packet type and leave all the
session-related code to src/rtcp.cc
Because most packet handlers do not require the raw UDP datagram
received through the socket, it makes little sense to relay those
parameters to them.
Additionally, there's a clear distinction between crafting
an RTP frame and operating on it so having one handler type
for both operations is not the best design choice.
Thus the packet handlers are divided into primary and auxiliary
handlers. Primary handlers are responsible for creating a packet
that the auxiliary handlers can operate on and auxiliary handlers
are responsible for doing all other operations on the packet such as
gathering sessions statistic information or decrypting the packet.
RTCP is used to gather session statistics and detect SSRC collisions
so all packets should be relayd to the RTCP layer for monitoring
even if RTCP packets are not being sent.
If RTCP Sender/Receiver reports are needed, RCE_RTCP should be given
when creating a media stream.
Indicate to the main thread through a mutex that the packet dispatcher
object can be destroyed. If this is not done, there's race condition
that can result into a segmentation fault as the dispatcher object
could be destroyed before it stops running.
Packet dispatcher does not need to store the socket because it
is passed to the actual runner when the packet dispatcher is started.
This also fixes a bug where the socket's destructor is called right
after the packet dispatcher's constructor
Remove the old generic interface and replace it with the push_frame()
implemented in some previous commit and with the new packet handler
implemented in this commit.
All media formats that do not require extra processing (such as Opus)
should use the generic interface.
Deprecate the old sender/receiver architecture from vanilla uvgRTP
and start using RTP packet dispatcher for incoming frames and Media
object for outgoing frames.
When a complete RTP frame has been received, the packet handler
must return the frame to RTP packet dispatcher which then returns
the frame to user either through frame queue or receive hook
Media is the base class from which all other media formats inherit
the common operations.
Media object contains two push_frame()s: one for normal pointers and
one for smart pointers. It also contains a packet handler which is
called by the RTP packet dispatcher when a UDP datagram is received.
All media formats must implement packet_handler() and __push_frame()
methods. If the media media format does not require any extra processing
(such as Opus), it can directly use the Media object and its implementation
of __push_frame() and packet_handler().
Media object implements the generic interface which supports sending
any kind of data and a uvgRTP-specific way of fragmenting/reconstructing
generic RTP frames which can be enabled with RCE_FRAGMENT_GENERIC.
Only RTP context and socketa are needed for the operations performed
by the frame queue so passing them to a constructor is much simpler
than passing sender to every function call and accessing the
context/socket through that.